diff --git a/crlcore/python/helpers/io.py b/crlcore/python/helpers/io.py index 15987ec6..2f66c5d4 100644 --- a/crlcore/python/helpers/io.py +++ b/crlcore/python/helpers/io.py @@ -19,157 +19,12 @@ import os import os.path import re import traceback -pyQtIsEnabled = True -try: - from PyQt4.QtCore import Qt - from PyQt4.QtGui import QSizePolicy - from PyQt4.QtGui import QDialog - from PyQt4.QtGui import QPalette - from PyQt4.QtGui import QColor - from PyQt4.QtGui import QFont - from PyQt4.QtGui import QFontMetrics - from PyQt4.QtGui import QWidget - from PyQt4.QtGui import QFrame - from PyQt4.QtGui import QLabel - from PyQt4.QtGui import QPixmap - from PyQt4.QtGui import QPushButton - from PyQt4.QtGui import QTextEdit - from PyQt4.QtGui import QVBoxLayout - from PyQt4.QtGui import QHBoxLayout - from PyQt4.QtGui import QAction - from PyQt4.QtGui import QKeySequence -except Exception as e: - try: - from PyQt5.QtCore import Qt - from PyQt5.QtWidgets import QSizePolicy - from PyQt5.QtWidgets import QDialog - from PyQt5.QtGui import QPalette - from PyQt5.QtGui import QColor - from PyQt5.QtGui import QFont - from PyQt5.QtGui import QFontMetrics - from PyQt5.QtWidgets import QWidget - from PyQt5.QtWidgets import QFrame - from PyQt5.QtWidgets import QLabel - from PyQt5.QtGui import QPixmap - from PyQt5.QtWidgets import QPushButton - from PyQt5.QtWidgets import QTextEdit - from PyQt5.QtWidgets import QVBoxLayout - from PyQt5.QtWidgets import QHBoxLayout - from PyQt5.QtWidgets import QAction - from PyQt5.QtGui import QKeySequence - except Exception: - print( '[WARNING] helpers.io, neither PyQt4 nor PyQt5 is available, disabling ErrorWidget.' ) - pyQtIsEnabled = False import Cfg import helpers from Hurricane import UpdateSession import Viewer -# ------------------------------------------------------------------- -# Class : "ErrorWidget". - -def getErrorWidget (): - - if pyQtIsEnabled: - - class ErrorWidget ( QDialog ): - - 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 - - # ------------------------------------------------------------------- # Class : "ErrorMessage". @@ -247,10 +102,8 @@ class ErrorMessage ( Exception ): e = ErrorMessage( code, *arguments ) if not Viewer.Graphics.get().isEnabled(): raise e - classErrorWidget = getErrorWidget() - if not classErrorWidget: - raise e - tryCont = ErrorWidget( e ).exec_() + tryCont = Viewer.ErrorWidget.run( e.getLinesAsString() + , helpers.textStackTrace( e.trace, False, e.scriptPath )) if not tryCont: raise e return @@ -269,11 +122,10 @@ def catch ( errorObject ): em.trace = traceback.extract_tb( sys.exc_info()[2] ) #em.scriptPath = __file__ print( em ) - print( helpers.textStackTrace( em.trace, True, em.scriptPath ) ) + print( helpers.textStackTrace( em.trace, True, em.scriptPath )) if Viewer.Graphics.get().isEnabled(): - classErrorWidget = getErrorWidget() - if classErrorWidget: - tryCont = classErrorWidget( em ).exec_() + Viewer.ErrorWidget.run( em.getLinesAsString() + , helpers.textStackTrace( em.trace, False, em.scriptPath )) if UpdateSession.getStackSize() > 0: UpdateSession.close() return diff --git a/cumulus/src/plugins/aboutwindow.py b/cumulus/src/plugins/aboutwindow.py index 0bb03981..d3a431ab 100644 --- a/cumulus/src/plugins/aboutwindow.py +++ b/cumulus/src/plugins/aboutwindow.py @@ -15,39 +15,6 @@ import sys import traceback -pyQtIsEnabled = True -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 -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( '[WARNING] AboutWindow: Neither PyQt4 nor PyQt5 is available, disabling AboutWidget.' ) - pyQtIsEnabled = False import Viewer import helpers from helpers.io import ErrorMessage @@ -55,98 +22,6 @@ from helpers.io import WarningMessage import plugins -# -------------------------------------------------------------------- -# Class : "AboutWidget". - - -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' - - if pyQtIsEnabled: - - class AboutWidget ( QDialog ): - - 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 - - # -------------------------------------------------------------------- # Plugin hook functions, unicornHook:menus, ScritMain:call @@ -162,14 +37,7 @@ def unicornHook ( **kw ): def scriptMain ( **kw ): try: - #helpers.setTraceLevel( 550 ) - aboutWidget = getAboutWidget()() - if not pyQtIsEnabled: - print( aboutWidget.aboutText ) - return True - answer = aboutWidget.exec_() - print( 'answer:', answer ) - if not answer: return True + Viewer.AboutWindow.show() except Exception as e: helpers.io.catch( e ) sys.stdout.flush() diff --git a/hurricane/src/viewer/AboutWindow.cpp b/hurricane/src/viewer/AboutWindow.cpp new file mode 100644 index 00000000..ec53a13a --- /dev/null +++ b/hurricane/src/viewer/AboutWindow.cpp @@ -0,0 +1,141 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./AboutWindow.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hurricane/TextTranslator.h" +#include "hurricane/viewer/Graphics.h" +#include "hurricane/viewer/AboutWindow.h" + + +namespace Hurricane { + + + bool AboutWindow::show () + { + AboutWindow* abw = new AboutWindow(); + return (abw->exec() != QDialog::Rejected); + } + + + AboutWindow::AboutWindow ( QWidget* parent ) + : QDialog( parent ) + { + setAttribute ( Qt::WA_DeleteOnClose ); + setModal ( true ); + setWindowTitle( tr("Coriolis About Window") ); + setToolTip ( tr("Sorbonne Université Proudly Present") ); + + QString about = "Coriolis EDA System 0.x . . . . . . . . . . . . . . cgt 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" + " . . . . . . . . . . . . . . . . . . Gabriel Gouvine\n" + " . . . . . . . . . . . . . . . . . . Christian Masson\n" + "E-Mail . . . . . . . . . . . . . . Jean-Paul.Chaput@lip6.fr"; + + QFrame* topLine = new QFrame (); + topLine->setFrameShape( QFrame::HLine ); + topLine->setLineWidth ( 2 ); + QFrame* botLine = new QFrame (); + botLine->setFrameShape( QFrame::HLine ); + botLine->setLineWidth ( 2 ); + + QLabel* logo = new QLabel (); + logo->setAlignment ( Qt::AlignCenter ); + logo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); + logo->setPixmap ( QPixmap(":/images/Coriolis-logo-white-4.png").scaledToWidth( Graphics::isHighDpi() ? 200 : 80 ) ); + + QLabel* title = new QLabel( "CGT" ); + title->setAlignment( Qt::AlignCenter ); + QFont font = title->font(); + font.setPointSize( 72 ); + font.setWeight ( QFont::Bold ); + title->setFont( font ); + + QLabel* subTitle = new QLabel ( "Coriolis Graphical Interface" ); + subTitle->setAlignment( Qt::AlignCenter ); + subTitle->setFont( QFont( "Courier", 10, QFont::Bold )); + + QLabel* authors = new QLabel( about ); + authors->setAlignment( Qt::AlignCenter ); + authors->setFont( QFont( "Courier", 10, QFont::Bold )); + + QLabel* documentation = new QLabel( "http://coriolis.lip6.fr" ); + documentation->setAlignment( Qt::AlignCenter ); + documentation->setFont( QFont( "Courier", 10, QFont::Bold )); + + QPushButton* thanksButton = new QPushButton (); + //thanksButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + thanksButton->setText ( tr("Thanks for flying Coriolis") ); + + QAction* closeAction = new QAction( tr("Close AboutWindow"), this ); + closeAction->setStatusTip( tr("CloseWindow") ); + closeAction->setShortcut ( QKeySequence(tr("CTRL+W")) ); + + QVBoxLayout* vLayout = new QVBoxLayout (); + vLayout->addStretch( 10 ); + vLayout->addWidget( topLine ); + vLayout->addWidget( logo ); + vLayout->addWidget( title ); + vLayout->addStretch( 1 ); + vLayout->addWidget( subTitle ); + vLayout->addWidget( authors ); + vLayout->addStretch( 10 ); + vLayout->addWidget( documentation ); + vLayout->addStretch( 1 ); + vLayout->addWidget( botLine ); + vLayout->addStretch( 10 ); + + QFrame* frame = new QFrame (); + frame->setFrameShape ( QFrame::Box ); + frame->setFrameShadow( QFrame::Sunken ); + frame->setLayout ( vLayout ); + frame->setLineWidth ( 1 ); + + QHBoxLayout* hLayout = new QHBoxLayout (); + //hLayout->addStretch( 1 ); + hLayout->addWidget ( thanksButton, Qt::AlignCenter ); + //hLayout->addStretch( 1 ); + + vLayout = new QVBoxLayout (); + vLayout->addWidget( frame ); + vLayout->addLayout( hLayout ); + + setLayout( vLayout ); + + connect( thanksButton, SIGNAL(clicked ()), this, SLOT(accept()) ); + connect( closeAction , SIGNAL(triggered()), this, SLOT(accept()) ); + } + + +} // End of Hurricane Namespace. diff --git a/hurricane/src/viewer/CMakeLists.txt b/hurricane/src/viewer/CMakeLists.txt index 23fd50c8..c7093a4e 100644 --- a/hurricane/src/viewer/CMakeLists.txt +++ b/hurricane/src/viewer/CMakeLists.txt @@ -20,6 +20,7 @@ hurricane/viewer/PaletteExtensionGoItem.h hurricane/viewer/PaletteWidget.h hurricane/viewer/GraphicsWidget.h + hurricane/viewer/ErrorWidget.h hurricane/viewer/ExceptionWidget.h hurricane/viewer/BreakpointWidget.h hurricane/viewer/GotoWidget.h @@ -44,6 +45,7 @@ hurricane/viewer/DisplayFilterWidget.h hurricane/viewer/ControllerWidget.h hurricane/viewer/ScriptWidget.h + hurricane/viewer/AboutWindow.h ) set( includes hurricane/viewer/ScreenUtilities.h hurricane/viewer/DisplayStyle.h @@ -70,6 +72,8 @@ hurricane/viewer/PyHApplication.h hurricane/viewer/PyGraphics.h hurricane/viewer/PyCellViewer.h + hurricane/viewer/PyErrorWidget.h + hurricane/viewer/PyAboutWindow.h hurricane/viewer/Script.h ) set( cpps HApplication.cpp @@ -78,6 +82,7 @@ ColorScale.cpp Graphics.cpp GraphicsWidget.cpp + ErrorWidget.cpp ExceptionWidget.cpp BreakpointWidget.cpp GotoWidget.cpp @@ -101,7 +106,7 @@ CellViewer.cpp CellPrinter.cpp CellImage.cpp - OpenBlobDialog.cpp + OpenBlobDialog.cpp RecordModel.cpp InspectorWidget.cpp SelectionPopupModel.cpp @@ -120,6 +125,7 @@ ScriptWidget.cpp DesignBlob.cpp JsonConfiguration.cpp + AboutWindow.cpp ) set( pyCpps PyHSVr.cpp PyDrawingStyle.cpp @@ -129,6 +135,8 @@ PyGraphics.cpp PyViewer.cpp PyCellViewer.cpp + PyErrorWidget.cpp + PyAboutWindow.cpp Script.cpp ) diff --git a/hurricane/src/viewer/CellViewer.qrc b/hurricane/src/viewer/CellViewer.qrc index 6e7c6388..a01fe4d6 100644 --- a/hurricane/src/viewer/CellViewer.qrc +++ b/hurricane/src/viewer/CellViewer.qrc @@ -17,5 +17,6 @@ images/angry-birds-red.png images/angry-birds-chuck.png images/angry-birds-bomb.png + images/Coriolis-logo-white-4.png diff --git a/hurricane/src/viewer/ErrorWidget.cpp b/hurricane/src/viewer/ErrorWidget.cpp new file mode 100644 index 00000000..38c33558 --- /dev/null +++ b/hurricane/src/viewer/ErrorWidget.cpp @@ -0,0 +1,186 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./ErrorWidget.cpp" | +// +-----------------------------------------------------------------+ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hurricane/Bug.h" +#include "hurricane/Error.h" +#include "hurricane/Error.h" +#include "hurricane/TextTranslator.h" +#include "hurricane/viewer/Graphics.h" +#include "hurricane/viewer/ErrorWidget.h" + + +namespace Hurricane { + + + bool ErrorWidget::run ( const QString& message, const QString& trace ) + { + ErrorWidget* ew = new ErrorWidget(); + + ew->setMessage( message ); + if (not trace.isEmpty()) + ew->setTrace( trace ); + + if (ew->exec() == QDialog::Rejected) { + cerr << "\n[BUG] A Python exception was catched:\n" << endl; + cerr << TextTranslator::toTextTranslator().translate( message.toStdString() ) << endl; + cerr << "\n[Backtrace]" << endl; + cerr << TextTranslator::toTextTranslator().translate( trace.toStdString() ) << endl; + return false; + } + return true; + } + + + ErrorWidget::ErrorWidget ( QWidget* parent ) + : QDialog (parent) + , _header (new QLabel()) + , _message (new QTextEdit()) + , _trace (new QTextEdit()) + { + setAttribute ( Qt::WA_DeleteOnClose ); + setModal ( true ); + setWindowTitle( tr("") ); + setToolTip ( tr("Caramba! Encore rate!") ); + + //_header->setMinimumWidth( Graphics::isHighDpi() ? 1500 : 400 ); + _header->setTextFormat ( Qt::RichText ); + _header->setText ( "[ERROR]" ); + + QString labelBackground = _header->palette().color( _header->backgroundRole() ).name(); + _message->setFrameStyle ( QFrame::NoFrame|QFrame::Plain ); + _message->setStyleSheet ( QString("p, li { white-space: wrap; } * { background-color: %1 }").arg(labelBackground) ); + _message->setTextInteractionFlags( Qt::TextSelectableByMouse ); + _message->setAcceptRichText ( false ); + _message->setLineWrapMode ( QTextEdit::NoWrap ); + _message->setWordWrapMode ( QTextOption::NoWrap ); + _message->setMinimumSize ( Graphics::isHighDpi() ? QSize(2500,200) : QSize(1000,100) ); + //_message->setTextFormat ( Qt::RichText ); + _message->setFont ( Graphics::getFixedFont(QFont::Normal,false,false) ); + _message->setPlainText ( "Oups! I did it again!" ); + + _trace->setTextInteractionFlags ( Qt::TextBrowserInteraction ); + _trace->setAcceptRichText ( true ); + _trace->setStyleSheet ( "* { white-space: pre; }" ); + _trace->setPlainText ( "No program trace sets yet." ); + _trace->setMinimumSize ( Graphics::isHighDpi() ? QSize(2500,1000) : QSize(1000,500) ); + _trace->setFont ( Graphics::getFixedFont(QFont::Normal,false,false,-2) ); + _trace->setLineWrapMode ( QTextEdit::FixedColumnWidth ); + _trace->setLineWrapColumnOrWidth( 140 ); + _trace->setSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding ); + _trace->setSizeAdjustPolicy ( QAbstractScrollArea::AdjustToContents ); + _trace->hide (); + + QCheckBox* showTrace = new QCheckBox (); + showTrace->setText ( "Show Program Trace" ); + showTrace->setChecked( false ); + + QLabel* leftMargin = new QLabel (); + leftMargin->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding ); + leftMargin->setPixmap ( QPixmap(":/images/angry-birds-red.png").scaledToWidth( Graphics::isHighDpi() ? 200 : 80 ) ); + leftMargin->setStyleSheet( "QLabel { background-color: #FF9999;" + " padding: 5px }" ); + + QPushButton* abortButton = new QPushButton (); + abortButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + abortButton->setText ( tr("Abort") ); + + QPushButton* contButton = new QPushButton (); + contButton->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + contButton->setText ( tr("Try to Continue") ); + + QFrame* separator = new QFrame (); + separator->setFrameShape ( QFrame::HLine ); + separator->setFrameShadow( QFrame::Sunken ); + + QHBoxLayout* hLayout2 = new QHBoxLayout (); + hLayout2->addStretch( 1 ); + hLayout2->addWidget ( contButton, Qt::AlignCenter ); + hLayout2->addStretch( 4 ); + hLayout2->addWidget ( abortButton, Qt::AlignCenter ); + hLayout2->addStretch( 1 ); + + QVBoxLayout* vLayout1 = new QVBoxLayout (); + vLayout1->setContentsMargins ( 10, 10, 10, 10 ); + vLayout1->setSpacing( 0 ); + vLayout1->addWidget ( _header , 0, Qt::AlignLeft ); + vLayout1->addWidget ( _message , 0, Qt::AlignLeft ); + vLayout1->addWidget ( separator ); + vLayout1->addWidget ( showTrace , 0, Qt::AlignLeft ); + vLayout1->addWidget ( _trace , 0, Qt::AlignLeft ); + vLayout1->addSpacing( 10 ); + vLayout1->addLayout ( hLayout2 , Qt::AlignCenter ); + + QHBoxLayout* hLayout1 = new QHBoxLayout (); + //hLayout1->setSizeConstraint ( QLayout::SetFixedSize ); + hLayout1->setContentsMargins( 0, 0, 0, 0 ); + hLayout1->addWidget ( leftMargin ); + hLayout1->addLayout ( vLayout1 ); + + setLayout ( hLayout1 ); + //setMinimumSize ( QSize(400,150) ); + //setSizePolicy ( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding) ); + setSizeGripEnabled( true ); + + connect( contButton , SIGNAL(clicked()) , this, SLOT(accept()) ); + connect( abortButton, SIGNAL(clicked()) , this, SLOT(reject()) ); + connect( showTrace , SIGNAL(stateChanged(int)), this, SLOT(_showTrace(int)) ); + } + + + void ErrorWidget::closeEvent ( QCloseEvent* event ) + { event->ignore(); } + + + void ErrorWidget::setMessage ( const QString& message ) + { + QString contents = message; + _header->setText ("[ERROR]"); + _message->setPlainText( contents ); + } + + + void ErrorWidget::setTrace ( const QString& where ) + { + _trace->setPlainText( where ); + _trace->setStyleSheet( "* { white-space: pre; }" ); + //cerr << _trace->toHtml().toStdString() << endl; + } + + + void ErrorWidget::_showTrace ( int state ) + { + if (state == Qt::Checked) _trace->show(); + else _trace->hide(); + + adjustPosition( NULL ); + } + + +} // End of Hurricane Namespace. diff --git a/hurricane/src/viewer/PyAboutWindow.cpp b/hurricane/src/viewer/PyAboutWindow.cpp new file mode 100644 index 00000000..0d231ac6 --- /dev/null +++ b/hurricane/src/viewer/PyAboutWindow.cpp @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyAboutWindow.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/viewer/PyAboutWindow.h" + + +namespace Hurricane { + + using Isobar::HurricaneError; + using Isobar::HurricaneWarning; + + +extern "C" { + + +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(AboutWindow,abw,function) + + +// +=================================================================+ +// | "PyAboutWindow" Python Module Code Part | +// +=================================================================+ + +#if defined(__PYTHON_MODULE__) + + + // Standart Destroy (Attribute). + DirectDestroyAttribute(PyAboutWindow_destroy, PyAboutWindow) + + + static PyObject* PyAboutWindow_show ( PyObject*, PyObject* args ) + { + cdebug_log(20,0) << "PyAboutWindow_show()" << endl; + HTRY + if (AboutWindow::show()) + Py_RETURN_TRUE; + HCATCH + Py_RETURN_FALSE; + } + + + // --------------------------------------------------------------- + // PyAboutWindow Attribute Method table. + + PyMethodDef PyAboutWindow_Methods[] = + { { "show" , (PyCFunction)PyAboutWindow_show, METH_STATIC|METH_VARARGS + , "Display the About window." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + PythonOnlyDeleteMethod(AboutWindow) + PyTypeObjectLinkPyTypeWithoutObject(AboutWindow,AboutWindow) + +#else // End of Python Module Code Part. + + +// +=================================================================+ +// | "PyAboutWindow" Shared Library Code Part | +// +=================================================================+ + + + PyTypeRootObjectDefinitions(AboutWindow) + +#endif // Shared Library Code Part. + +} // extern "C". + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/PyErrorWidget.cpp b/hurricane/src/viewer/PyErrorWidget.cpp new file mode 100644 index 00000000..7ae235c6 --- /dev/null +++ b/hurricane/src/viewer/PyErrorWidget.cpp @@ -0,0 +1,85 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyErrorWidget.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/viewer/PyErrorWidget.h" + + +namespace Isobar { + +using namespace Hurricane; + +extern "C" { + + +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(ErrorWidget,ew,function) + + +// +=================================================================+ +// | "PyErrorWidget" Python Module Code Part | +// +=================================================================+ + +#if defined(__PYTHON_MODULE__) + + + // Standart Destroy (Attribute). + DirectDestroyAttribute(PyErrorWidget_destroy, PyErrorWidget) + + + static PyObject* PyErrorWidget_run ( PyObject*, PyObject* args ) + { + cdebug_log(20,0) << "PyErrorWidget_run()" << endl; + HTRY + char* message = NULL; + char* trace = NULL; + if (not PyArg_ParseTuple(args,"s|s:ErrorWidget.run()", &message,&trace)) { + PyErr_SetString( ConstructorError, "ErrorWidget.run(): Takes one or two *string* arguments." ); + return NULL; + } + if (ErrorWidget::run( QString(message), QString(trace) )) + Py_RETURN_TRUE; + HCATCH + Py_RETURN_FALSE; + } + + + // --------------------------------------------------------------- + // PyErrorWidget Attribute Method table. + + PyMethodDef PyErrorWidget_Methods[] = + { { "run" , (PyCFunction)PyErrorWidget_run, METH_STATIC|METH_VARARGS + , "Launch the error widget. Return True if continue." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + + PythonOnlyDeleteMethod(ErrorWidget) + PyTypeObjectLinkPyTypeWithoutObject(ErrorWidget,ErrorWidget) + +#else // End of Python Module Code Part. + + +// +=================================================================+ +// | "PyErrorWidget" Shared Library Code Part | +// +=================================================================+ + + + PyTypeRootObjectDefinitions(ErrorWidget) + +#endif // Shared Library Code Part. + +} // extern "C". + +} // Isobar namespace. diff --git a/hurricane/src/viewer/PyViewer.cpp b/hurricane/src/viewer/PyViewer.cpp index 53b09889..ebee0029 100644 --- a/hurricane/src/viewer/PyViewer.cpp +++ b/hurricane/src/viewer/PyViewer.cpp @@ -21,7 +21,9 @@ #include "hurricane/viewer/PyDrawingGroup.h" #include "hurricane/viewer/PyDisplayStyle.h" #include "hurricane/viewer/PyHSVr.h" +#include "hurricane/viewer/PyErrorWidget.h" #include "hurricane/viewer/PyCellViewer.h" +#include "hurricane/viewer/PyAboutWindow.h" namespace Hurricane { @@ -89,7 +91,9 @@ extern "C" { PyDisplayStyleVector_LinkPyType (); PyHApplication_LinkPyType (); PyGraphics_LinkPyType (); + PyErrorWidget_LinkPyType (); PyCellViewer_LinkPyType (); + PyAboutWindow_LinkPyType (); PYTYPE_READY ( HSVr ); PYTYPE_READY ( RawDrawingStyle ); @@ -103,7 +107,9 @@ extern "C" { PYTYPE_READY ( DisplayStyleVectorIterator ); PYTYPE_READY ( HApplication ); PYTYPE_READY ( Graphics ); + PYTYPE_READY ( ErrorWidget ); PYTYPE_READY ( CellViewer ); + PYTYPE_READY ( AboutWindow ); // Identifier string can take up to 10 characters. __cs.addType ( "hsvr" , &PyTypeHSVr , "" , false ); @@ -125,7 +131,11 @@ extern "C" { Py_INCREF ( &PyTypeGraphics ); PyModule_AddObject ( module, "Graphics" , (PyObject*)&PyTypeGraphics ); Py_INCREF ( &PyTypeCellViewer ); + PyModule_AddObject ( module, "ErrorWidget" , (PyObject*)&PyTypeErrorWidget ); + Py_INCREF ( &PyTypeErrorWidget ); PyModule_AddObject ( module, "CellViewer" , (PyObject*)&PyTypeCellViewer ); + Py_INCREF ( &PyTypeAboutWindow ); + PyModule_AddObject ( module, "AboutWindow" , (PyObject*)&PyTypeAboutWindow ); PyDisplayStyle_postModuleInit(); PyCellViewer_postModuleInit(); diff --git a/hurricane/src/viewer/hurricane/viewer/AboutWindow.h b/hurricane/src/viewer/hurricane/viewer/AboutWindow.h new file mode 100644 index 00000000..f333d64f --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/AboutWindow.h @@ -0,0 +1,36 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/AboutWindow.h" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include +#include +class QLabel; +class QTextEdit; + + +namespace Hurricane { + + + class AboutWindow : public QDialog { + Q_OBJECT; + public: + static bool show (); + public: + AboutWindow ( QWidget* parent=NULL); + }; + + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/ErrorWidget.h b/hurricane/src/viewer/hurricane/viewer/ErrorWidget.h new file mode 100644 index 00000000..043bbea7 --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/ErrorWidget.h @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | V L S I B a c k e n d D a t a - B a s e | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/ErrorWidget.h" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include +#include +#include +class QLabel; +class QTextEdit; + + +namespace Hurricane { + + + class ErrorWidget : public QDialog { + Q_OBJECT; + public: + static bool run ( const QString& message, const QString& trace="" ); + public: + ErrorWidget ( QWidget* parent=NULL); + void setMessage ( const QString& ); + void setTrace ( const QString& ); + protected: + virtual void closeEvent ( QCloseEvent* ); + private slots: + void _showTrace ( int state ); + private: + QLabel* _header; + QTextEdit* _message; + QTextEdit* _trace; + }; + + +} // Hurricane namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/PyAboutWindow.h b/hurricane/src/viewer/hurricane/viewer/PyAboutWindow.h new file mode 100644 index 00000000..be98db66 --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/PyAboutWindow.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/PyAboutWindow.cpp" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include "hurricane/isobar/PyHurricane.h" +#include "hurricane/viewer/AboutWindow.h" + + +namespace Hurricane { + + +extern "C" { + +// ------------------------------------------------------------------- +// Python Object : "PyAboutWindow". + + typedef struct { + PyObject_HEAD + Hurricane::AboutWindow* _object; + } PyAboutWindow; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyHurricane.cpp". + + extern PyTypeObject PyTypeAboutWindow; + extern PyMethodDef PyAboutWindow_Methods[]; + + extern PyObject* PyAboutWindow_create ( PyObject* self, PyObject* args ); + extern void PyAboutWindow_LinkPyType (); + + +#define IsPyAboutWindow(v) ( (v)->ob_type == &PyTypeAboutWindow ) +#define PYABOUTWINDOW(v) ( (PyAboutWindow*)(v) ) +#define PYABOUTWINDOW_O(v) ( PYABOUTWINDOW(v)->_object ) + + +} // extern "C". + + +} // Isobar namespace. diff --git a/hurricane/src/viewer/hurricane/viewer/PyErrorWidget.h b/hurricane/src/viewer/hurricane/viewer/PyErrorWidget.h new file mode 100644 index 00000000..79d99924 --- /dev/null +++ b/hurricane/src/viewer/hurricane/viewer/PyErrorWidget.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/viewer/PyErrorWidget.cpp" | +// +-----------------------------------------------------------------+ + + +#pragma once +#include "hurricane/isobar/PyHurricane.h" +#include "hurricane/viewer/ErrorWidget.h" + + +namespace Hurricane { + + +extern "C" { + +// ------------------------------------------------------------------- +// Python Object : "PyErrorWidget". + + typedef struct { + PyObject_HEAD + Hurricane::ErrorWidget* _object; + } PyErrorWidget; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyHurricane.cpp". + + extern PyTypeObject PyTypeErrorWidget; + extern PyMethodDef PyErrorWidget_Methods[]; + + extern PyObject* PyErrorWidget_create ( PyObject* self, PyObject* args ); + extern void PyErrorWidget_LinkPyType (); + + +#define IsPyErrorWidget(v) ( (v)->ob_type == &PyTypeErrorWidget ) +#define PYERRORWIDGET(v) ( (PyErrorWidget*)(v) ) +#define PYERRORWIDGET_O(v) ( PYERRORWIDGET(v)->_object ) + + +} // extern "C". + + +} // Isobar namespace. diff --git a/hurricane/src/viewer/images/Coriolis-logo-white-4.png b/hurricane/src/viewer/images/Coriolis-logo-white-4.png new file mode 100644 index 00000000..bcdbc596 Binary files /dev/null and b/hurricane/src/viewer/images/Coriolis-logo-white-4.png differ