From 118b28b5a777242770396770f638c65caddc675d Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Wed, 26 Oct 2022 16:37:16 +0200 Subject: [PATCH] Prevent the absence of PyQt5 to stop lauching cgt. * Change: In CRL/helpers.io, the ErrorWidget requires PyQt5 to execute but is not mandatory to run Coriolis/cgt. In order to be more portable, if it is not availble just evert to text display on the console. This widget will be directly supplied by Coriolis in the future completely removing the need for PyQt. *Change: In cumulus/plugins/aboutwindow, same as above. --- crlcore/python/helpers/io.py | 201 +++++++++++++----------- cumulus/src/plugins/aboutwindow.py | 238 +++++++++++++++-------------- 2 files changed, 235 insertions(+), 204 deletions(-) diff --git a/crlcore/python/helpers/io.py b/crlcore/python/helpers/io.py index f9a7d8ef..15987ec6 100644 --- a/crlcore/python/helpers/io.py +++ b/crlcore/python/helpers/io.py @@ -19,6 +19,7 @@ import os import os.path import re import traceback +pyQtIsEnabled = True try: from PyQt4.QtCore import Qt from PyQt4.QtGui import QSizePolicy @@ -57,8 +58,8 @@ except Exception as e: from PyQt5.QtWidgets import QAction from PyQt5.QtGui import QKeySequence except Exception: - print( '[ERROR] helpers.io, neither PyQt4 nor PyQt5 is available.' ) - sys.exit( 1 ) + print( '[WARNING] helpers.io, neither PyQt4 nor PyQt5 is available, disabling ErrorWidget.' ) + pyQtIsEnabled = False import Cfg import helpers from Hurricane import UpdateSession @@ -68,93 +69,105 @@ import Viewer # ------------------------------------------------------------------- # Class : "ErrorWidget". -class ErrorWidget ( QDialog ): +def getErrorWidget (): - def __init__ ( self, e ): - QWidget.__init__ ( self, None ) + if pyQtIsEnabled: + + class ErrorWidget ( QDialog ): - self.setWindowTitle( 'Error' ) - - message = QLabel( e.getLinesAsString() ) - message.setAlignment( Qt.AlignLeft ) - message.setFont( QFont('Courier',10,QFont.Bold) ) - - error = QLabel( '[ERROR]' ) - error.setAlignment( Qt.AlignLeft ) - font = error.font() - font.setWeight( QFont.Bold ) - error.setFont( font ) - - self._tryCont = QPushButton() - self._tryCont.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) - self._tryCont.setText ( 'Try to continue' ) - self._abort = QPushButton() - self._abort.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) - self._abort.setText ( 'Abort' ) - self._abort.setDefault ( True ) - - traceFont = QFont('Courier',10,QFont.Normal) - lineHeight = QFontMetrics( traceFont ).height() - traceText = helpers.textStackTrace( e.trace, False, e.scriptPath ) - lineCount = traceText.count( '\n' ) + 2 - minimumWidth = 400 - if Viewer.Graphics.isHighDpi(): minimumWidth = 2100 - self._trace = QTextEdit() - self._trace.setReadOnly ( True ); - self._trace.setLineWrapMode( QTextEdit.NoWrap ); - self._trace.setMinimumSize ( minimumWidth, lineCount*lineHeight ); - self._trace.setFont ( traceFont ) - self._trace.setText ( traceText ) - - buttonLayout = QHBoxLayout() - buttonLayout.addStretch( 1 ) - buttonLayout.addWidget ( self._tryCont ) - buttonLayout.addStretch( 1 ) - buttonLayout.addWidget ( self._abort ) - buttonLayout.addStretch( 1 ) - - vLayout = QVBoxLayout() - vLayout.addWidget ( error ) - vLayout.addStretch( 1 ) - vLayout.addWidget ( message ) - vLayout.addStretch( 1 ) - vLayout.addWidget ( self._trace ) - vLayout.addStretch( 1 ) - vLayout.addLayout ( buttonLayout ) - - pixmapWidth = 150 - if not Viewer.Graphics.isHighDpi(): pixmapWidth = 70 - pixmap = QPixmap( ':/images/angry-birds-red.png' ) - pixmap = pixmap.scaledToWidth( pixmapWidth ) - icon = QLabel() - icon.setPixmap( pixmap ) - - hLayout = QHBoxLayout() - hLayout.addWidget( icon ) - hLayout.addLayout( vLayout ) - self.setLayout( hLayout ) - - self._tryCont.clicked.connect( self.accept ) - self._abort .clicked.connect( self.reject ) - - self._exitAction = QAction( '&Exit', self ) - self._exitAction.setStatusTip( 'Exit Coriolis' ) - self._exitAction.setShortcut ( QKeySequence('CTRL+Q') ) - self._exitAction.triggered.connect( self.reject ) - self.addAction( self._exitAction ) - - self._closeAction = QAction( '&Close', self ) - self._closeAction.setStatusTip( 'Try to continue' ) - self._closeAction.setShortcut ( QKeySequence('CTRL+W') ) - self._closeAction.triggered.connect( self.reject ) - self.addAction( self._closeAction ) - - return - - def closeEvent ( self, event ): - self.setResult( QDialog.Rejected ) - event.accept() - return + def __init__ ( self, e ): + + QWidget.__init__ ( self, None ) + + self.setWindowTitle( 'Error' ) + + message = QLabel( e.getLinesAsString() ) + message.setAlignment( Qt.AlignLeft ) + message.setFont( QFont('Courier',10,QFont.Bold) ) + + error = QLabel( '[ERROR]' ) + error.setAlignment( Qt.AlignLeft ) + font = error.font() + font.setWeight( QFont.Bold ) + error.setFont( font ) + + self._tryCont = QPushButton() + self._tryCont.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) + self._tryCont.setText ( 'Try to continue' ) + self._abort = QPushButton() + self._abort.setSizePolicy( QSizePolicy.Fixed, QSizePolicy.Fixed ) + self._abort.setText ( 'Abort' ) + self._abort.setDefault ( True ) + + traceFont = QFont('Courier',10,QFont.Normal) + lineHeight = QFontMetrics( traceFont ).height() + traceText = helpers.textStackTrace( e.trace, False, e.scriptPath ) + lineCount = traceText.count( '\n' ) + 2 + minimumWidth = 400 + if Viewer.Graphics.isHighDpi(): minimumWidth = 2100 + self._trace = QTextEdit() + self._trace.setReadOnly ( True ); + self._trace.setLineWrapMode( QTextEdit.NoWrap ); + self._trace.setMinimumSize ( minimumWidth, lineCount*lineHeight ); + self._trace.setFont ( traceFont ) + self._trace.setText ( traceText ) + + buttonLayout = QHBoxLayout() + buttonLayout.addStretch( 1 ) + buttonLayout.addWidget ( self._tryCont ) + buttonLayout.addStretch( 1 ) + buttonLayout.addWidget ( self._abort ) + buttonLayout.addStretch( 1 ) + + vLayout = QVBoxLayout() + vLayout.addWidget ( error ) + vLayout.addStretch( 1 ) + vLayout.addWidget ( message ) + vLayout.addStretch( 1 ) + vLayout.addWidget ( self._trace ) + vLayout.addStretch( 1 ) + vLayout.addLayout ( buttonLayout ) + + pixmapWidth = 150 + if not Viewer.Graphics.isHighDpi(): pixmapWidth = 70 + pixmap = QPixmap( ':/images/angry-birds-red.png' ) + pixmap = pixmap.scaledToWidth( pixmapWidth ) + icon = QLabel() + icon.setPixmap( pixmap ) + + hLayout = QHBoxLayout() + hLayout.addWidget( icon ) + hLayout.addLayout( vLayout ) + self.setLayout( hLayout ) + + self._tryCont.clicked.connect( self.accept ) + self._abort .clicked.connect( self.reject ) + + self._exitAction = QAction( '&Exit', self ) + self._exitAction.setStatusTip( 'Exit Coriolis' ) + self._exitAction.setShortcut ( QKeySequence('CTRL+Q') ) + self._exitAction.triggered.connect( self.reject ) + self.addAction( self._exitAction ) + + self._closeAction = QAction( '&Close', self ) + self._closeAction.setStatusTip( 'Try to continue' ) + self._closeAction.setShortcut ( QKeySequence('CTRL+W') ) + self._closeAction.triggered.connect( self.reject ) + self.addAction( self._closeAction ) + + return + + def closeEvent ( self, event ): + if not pyQtIsEnabled: return + self.setResult( QDialog.Rejected ) + event.accept() + return + + else: + + ErrorWidget = None + + return ErrorWidget # ------------------------------------------------------------------- @@ -232,11 +245,13 @@ class ErrorMessage ( Exception ): @staticmethod def show ( code, *arguments ): e = ErrorMessage( code, *arguments ) - if Viewer.Graphics.get().isEnabled(): - tryCont = ErrorWidget( e ).exec_() - if not tryCont: raise e - else: + if not Viewer.Graphics.get().isEnabled(): raise e + classErrorWidget = getErrorWidget() + if not classErrorWidget: + raise e + tryCont = ErrorWidget( e ).exec_() + if not tryCont: raise e return @@ -256,7 +271,9 @@ def catch ( errorObject ): print( em ) print( helpers.textStackTrace( em.trace, True, em.scriptPath ) ) if Viewer.Graphics.get().isEnabled(): - tryCont = ErrorWidget( em ).exec_() + classErrorWidget = getErrorWidget() + if classErrorWidget: + tryCont = classErrorWidget( em ).exec_() if UpdateSession.getStackSize() > 0: UpdateSession.close() return diff --git a/cumulus/src/plugins/aboutwindow.py b/cumulus/src/plugins/aboutwindow.py index cf44f450..0bb03981 100644 --- a/cumulus/src/plugins/aboutwindow.py +++ b/cumulus/src/plugins/aboutwindow.py @@ -13,126 +13,138 @@ # +-----------------------------------------------------------------+ +import sys +import traceback +pyQtIsEnabled = True try: - import sys - import traceback + from PyQt4.QtCore import Qt + from PyQt4.QtCore import QEventLoop + from PyQt4.QtGui import QDialog + from PyQt4.QtGui import QPalette + from PyQt4.QtGui import QColor + from PyQt4.QtGui import QFont + from PyQt4.QtGui import QWidget + from PyQt4.QtGui import QFrame + from PyQt4.QtGui import QLabel + from PyQt4.QtGui import QVBoxLayout + from PyQt4.QtGui import QAction + from PyQt4.QtGui import QKeySequence + from PyQt4.QtGui import QApplication +except: try: - from PyQt4.QtCore import Qt - from PyQt4.QtCore import QEventLoop - from PyQt4.QtGui import QDialog - from PyQt4.QtGui import QPalette - from PyQt4.QtGui import QColor - from PyQt4.QtGui import QFont - from PyQt4.QtGui import QWidget - from PyQt4.QtGui import QFrame - from PyQt4.QtGui import QLabel - from PyQt4.QtGui import QVBoxLayout - from PyQt4.QtGui import QAction - from PyQt4.QtGui import QKeySequence - from PyQt4.QtGui import QApplication + from PyQt5.QtCore import Qt + from PyQt5.QtCore import QEventLoop + from PyQt5.QtWidgets import QDialog + from PyQt5.QtGui import QPalette + from PyQt5.QtGui import QColor + from PyQt5.QtGui import QFont + from PyQt5.QtWidgets import QWidget + from PyQt5.QtWidgets import QFrame + from PyQt5.QtWidgets import QLabel + from PyQt5.QtWidgets import QVBoxLayout + from PyQt5.QtWidgets import QAction + from PyQt5.QtGui import QKeySequence + from PyQt5.QtWidgets import QApplication except: - try: - from PyQt5.QtCore import Qt - from PyQt5.QtCore import QEventLoop - from PyQt5.QtWidgets import QDialog - from PyQt5.QtGui import QPalette - from PyQt5.QtGui import QColor - from PyQt5.QtGui import QFont - from PyQt5.QtWidgets import QWidget - from PyQt5.QtWidgets import QFrame - from PyQt5.QtWidgets import QLabel - from PyQt5.QtWidgets import QVBoxLayout - from PyQt5.QtWidgets import QAction - from PyQt5.QtGui import QKeySequence - from PyQt5.QtWidgets import QApplication - except: - print( '[ERROR] AboutWindow: Neither PyQt4 nor PyQt5 is available.' ) - sys.exit( 1 ) - import Viewer - import helpers - from helpers.io import ErrorMessage - from helpers.io import WarningMessage - import plugins -except Exception as e: - helpers.io.catch( e ) - sys.exit(2) + print( '[WARNING] AboutWindow: Neither PyQt4 nor PyQt5 is available, disabling AboutWidget.' ) + pyQtIsEnabled = False +import Viewer +import helpers +from helpers.io import ErrorMessage +from helpers.io import WarningMessage +import plugins # -------------------------------------------------------------------- # Class : "AboutWidget". -class AboutWidget ( QDialog ): +def getAboutWidget (): + aboutText = 'Coriolis CAD System 1.0 . . . . . . . . . . . . . . ccb 1.0\n' \ + 'Copyright (c) 2008-2022 . . . . . . . . Sorbonne Université\n' \ + 'Authors . . . . . . . . . . . . . . . . Christophe Alexandre\n' \ + ' . . . . . . . . . . . . . . . . . . Sophie Belloeil\n' \ + ' . . . . . . . . . . . . . . . . . . Jean-Paul Chaput\n' \ + ' . . . . . . . . . . . . . . . . . . . Damien Dupuis\n' \ + ' . . . . . . . . . . . . . . . . . . . Remy Escassut\n' \ + ' . . . . . . . . . . . . . . . . . . Christian Masson\n' \ + 'E-Mail . . . . . . . . . . . . . . Jean-Paul.Chaput@lip6.fr' - def __init__ ( self, parent=None ): - QWidget.__init__ ( self, parent ) - #self.setFixedSize( 500, 400 ) - #self.setStyleSheet( 'background-color: #ffffdd;' ) - - topLine = QFrame() - topLine.setFrameShape( QFrame.HLine ) - topLine.setLineWidth ( 2 ) - botLine = QFrame() - botLine.setFrameShape( QFrame.HLine ) - botLine.setLineWidth ( 2 ) - - title = QLabel( 'CCB' ) - title.setAlignment( Qt.AlignCenter ) - font = title.font() - font.setPointSize( 72 ) - font.setWeight ( QFont.Bold ) - title.setFont( font ) - - subTitle = QLabel( 'Coriolis & Chams Builder for the Dummies' ) - subTitle.setAlignment( Qt.AlignCenter ) - subTitle.setFont( QFont('Courier',10,QFont.Bold) ) - - authors = QLabel( 'Coriolis CAD System 1.0 . . . . . . . . ccb 1.0\n' - 'Copyright (c) 2008-2016 . . . . . . . . . . UPMC\n' - 'Authors . . . . . . . . . . . . . Damien Dupuis\n' - ' . . . . . . . . . . . . Jean-Paul Chaput\n' - 'E-Mail . . . . . . . . Jean-Paul.Chaput@lip6.fr' - ) - authors.setAlignment( Qt.AlignCenter ) - authors.setFont( QFont('Courier',10,QFont.Bold) ) - - vLayout = QVBoxLayout() - vLayout.addStretch(10) - vLayout.addWidget( topLine ) - vLayout.addWidget( title ) - vLayout.addStretch(1) - vLayout.addWidget( subTitle ) - vLayout.addWidget( authors ) - vLayout.addStretch(1) - vLayout.addWidget( botLine ) - vLayout.addStretch(10) - - frame = QFrame() - frame.setFrameShape ( QFrame.Box ) - frame.setFrameShadow( QFrame.Sunken ) - frame.setLayout ( vLayout ) - frame.setLineWidth ( 1 ) - - vLayout = QVBoxLayout() - vLayout.addWidget( frame ) + if pyQtIsEnabled: + + class AboutWidget ( QDialog ): - self.setLayout( vLayout ) - - self._exitAction = QAction( '&Exit', self ) - self._exitAction.setStatusTip( 'Exit CCB (settings are saved)' ) - self._exitAction.setShortcut ( QKeySequence('CTRL+Q') ) - #self._exitAction.triggered.connect( QApplication.closeAllWindows ) - self._exitAction.triggered.connect( self.reject ) - self.addAction( self._exitAction ) - - self._closeAction = QAction( '&Close', self ) - self._closeAction.setStatusTip( 'Close the About Window' ) - self._closeAction.setShortcut ( QKeySequence('CTRL+A') ) - #self._closeAction.triggered.connect( self.close ) - self._closeAction.triggered.connect( self.accept ) - self.addAction( self._closeAction ) - - return + def __init__ ( self, parent=None ): + QWidget.__init__ ( self, parent ) + #self.setFixedSize( 500, 400 ) + #self.setStyleSheet( 'background-color: #ffffdd;' ) + + topLine = QFrame() + topLine.setFrameShape( QFrame.HLine ) + topLine.setLineWidth ( 2 ) + botLine = QFrame() + botLine.setFrameShape( QFrame.HLine ) + botLine.setLineWidth ( 2 ) + + title = QLabel( 'CGT' ) + title.setAlignment( Qt.AlignCenter ) + font = title.font() + font.setPointSize( 72 ) + font.setWeight ( QFont.Bold ) + title.setFont( font ) + + subTitle = QLabel( 'Coriolis Graphical Interface' ) + subTitle.setAlignment( Qt.AlignCenter ) + subTitle.setFont( QFont('Courier',10,QFont.Bold) ) + + authors = QLabel( aboutText ) + authors.setAlignment( Qt.AlignCenter ) + authors.setFont( QFont('Courier',10,QFont.Bold) ) + + vLayout = QVBoxLayout() + vLayout.addStretch(10) + vLayout.addWidget( topLine ) + vLayout.addWidget( title ) + vLayout.addStretch(1) + vLayout.addWidget( subTitle ) + vLayout.addWidget( authors ) + vLayout.addStretch(1) + vLayout.addWidget( botLine ) + vLayout.addStretch(10) + + frame = QFrame() + frame.setFrameShape ( QFrame.Box ) + frame.setFrameShadow( QFrame.Sunken ) + frame.setLayout ( vLayout ) + frame.setLineWidth ( 1 ) + + vLayout = QVBoxLayout() + vLayout.addWidget( frame ) + + self.setLayout( vLayout ) + + self._exitAction = QAction( '&Exit', self ) + self._exitAction.setStatusTip( 'Exit CCB (settings are saved)' ) + self._exitAction.setShortcut ( QKeySequence('CTRL+Q') ) + #self._exitAction.triggered.connect( QApplication.closeAllWindows ) + self._exitAction.triggered.connect( self.reject ) + self.addAction( self._exitAction ) + + self._closeAction = QAction( '&Close', self ) + self._closeAction.setStatusTip( 'Close the About Window' ) + self._closeAction.setShortcut ( QKeySequence('CTRL+A') ) + #self._closeAction.triggered.connect( self.close ) + self._closeAction.triggered.connect( self.accept ) + self.addAction( self._closeAction ) + + else: + + class AboutWidget ( object ): + + def __init__ ( self ): + self.aboutText = aboutText + + return AboutWidget # -------------------------------------------------------------------- @@ -149,10 +161,12 @@ def unicornHook ( **kw ): def scriptMain ( **kw ): - rvalue = True try: #helpers.setTraceLevel( 550 ) - aboutWidget = AboutWidget() + aboutWidget = getAboutWidget()() + if not pyQtIsEnabled: + print( aboutWidget.aboutText ) + return True answer = aboutWidget.exec_() print( 'answer:', answer ) if not answer: return True @@ -160,4 +174,4 @@ def scriptMain ( **kw ): helpers.io.catch( e ) sys.stdout.flush() sys.stderr.flush() - return rvalue + return True