Cleanly get rid of PyQt dependency.

* New: Hurricane::ErrorWidget, new widget exported to Python to replace
    helpers.io.ErrorWidget.
* New: Hurricane::AboutWindow, new window exported to Python to replace
    cumulus/plugins.aboutwindow.AboutWidget.
This commit is contained in:
Jean-Paul Chaput 2022-11-02 00:21:00 +01:00
parent 13795bec48
commit 8c182672dd
14 changed files with 710 additions and 287 deletions

View File

@ -19,157 +19,12 @@ import os
import os.path import os.path
import re import re
import traceback 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 Cfg
import helpers import helpers
from Hurricane import UpdateSession from Hurricane import UpdateSession
import Viewer 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". # Class : "ErrorMessage".
@ -247,10 +102,8 @@ class ErrorMessage ( Exception ):
e = ErrorMessage( code, *arguments ) e = ErrorMessage( code, *arguments )
if not Viewer.Graphics.get().isEnabled(): if not Viewer.Graphics.get().isEnabled():
raise e raise e
classErrorWidget = getErrorWidget() tryCont = Viewer.ErrorWidget.run( e.getLinesAsString()
if not classErrorWidget: , helpers.textStackTrace( e.trace, False, e.scriptPath ))
raise e
tryCont = ErrorWidget( e ).exec_()
if not tryCont: raise e if not tryCont: raise e
return return
@ -269,11 +122,10 @@ def catch ( errorObject ):
em.trace = traceback.extract_tb( sys.exc_info()[2] ) em.trace = traceback.extract_tb( sys.exc_info()[2] )
#em.scriptPath = __file__ #em.scriptPath = __file__
print( em ) print( em )
print( helpers.textStackTrace( em.trace, True, em.scriptPath ) ) print( helpers.textStackTrace( em.trace, True, em.scriptPath ))
if Viewer.Graphics.get().isEnabled(): if Viewer.Graphics.get().isEnabled():
classErrorWidget = getErrorWidget() Viewer.ErrorWidget.run( em.getLinesAsString()
if classErrorWidget: , helpers.textStackTrace( em.trace, False, em.scriptPath ))
tryCont = classErrorWidget( em ).exec_()
if UpdateSession.getStackSize() > 0: UpdateSession.close() if UpdateSession.getStackSize() > 0: UpdateSession.close()
return return

View File

@ -15,39 +15,6 @@
import sys import sys
import traceback 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 Viewer
import helpers import helpers
from helpers.io import ErrorMessage from helpers.io import ErrorMessage
@ -55,98 +22,6 @@ from helpers.io import WarningMessage
import plugins 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 # Plugin hook functions, unicornHook:menus, ScritMain:call
@ -162,14 +37,7 @@ def unicornHook ( **kw ):
def scriptMain ( **kw ): def scriptMain ( **kw ):
try: try:
#helpers.setTraceLevel( 550 ) Viewer.AboutWindow.show()
aboutWidget = getAboutWidget()()
if not pyQtIsEnabled:
print( aboutWidget.aboutText )
return True
answer = aboutWidget.exec_()
print( 'answer:', answer )
if not answer: return True
except Exception as e: except Exception as e:
helpers.io.catch( e ) helpers.io.catch( e )
sys.stdout.flush() sys.stdout.flush()

View File

@ -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 <unistd.h>
#include <csignal>
#include <memory>
#include <QAction>
#include <QCloseEvent>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
#include <QTextEdit>
#include <QScrollArea>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFrame>
#include <QFont>
#include <QFontMetrics>
#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( "<a href=\"http://coriolis.lip6.fr\">http://coriolis.lip6.fr</a>" );
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.

View File

@ -20,6 +20,7 @@
hurricane/viewer/PaletteExtensionGoItem.h hurricane/viewer/PaletteExtensionGoItem.h
hurricane/viewer/PaletteWidget.h hurricane/viewer/PaletteWidget.h
hurricane/viewer/GraphicsWidget.h hurricane/viewer/GraphicsWidget.h
hurricane/viewer/ErrorWidget.h
hurricane/viewer/ExceptionWidget.h hurricane/viewer/ExceptionWidget.h
hurricane/viewer/BreakpointWidget.h hurricane/viewer/BreakpointWidget.h
hurricane/viewer/GotoWidget.h hurricane/viewer/GotoWidget.h
@ -44,6 +45,7 @@
hurricane/viewer/DisplayFilterWidget.h hurricane/viewer/DisplayFilterWidget.h
hurricane/viewer/ControllerWidget.h hurricane/viewer/ControllerWidget.h
hurricane/viewer/ScriptWidget.h hurricane/viewer/ScriptWidget.h
hurricane/viewer/AboutWindow.h
) )
set( includes hurricane/viewer/ScreenUtilities.h set( includes hurricane/viewer/ScreenUtilities.h
hurricane/viewer/DisplayStyle.h hurricane/viewer/DisplayStyle.h
@ -70,6 +72,8 @@
hurricane/viewer/PyHApplication.h hurricane/viewer/PyHApplication.h
hurricane/viewer/PyGraphics.h hurricane/viewer/PyGraphics.h
hurricane/viewer/PyCellViewer.h hurricane/viewer/PyCellViewer.h
hurricane/viewer/PyErrorWidget.h
hurricane/viewer/PyAboutWindow.h
hurricane/viewer/Script.h hurricane/viewer/Script.h
) )
set( cpps HApplication.cpp set( cpps HApplication.cpp
@ -78,6 +82,7 @@
ColorScale.cpp ColorScale.cpp
Graphics.cpp Graphics.cpp
GraphicsWidget.cpp GraphicsWidget.cpp
ErrorWidget.cpp
ExceptionWidget.cpp ExceptionWidget.cpp
BreakpointWidget.cpp BreakpointWidget.cpp
GotoWidget.cpp GotoWidget.cpp
@ -101,7 +106,7 @@
CellViewer.cpp CellViewer.cpp
CellPrinter.cpp CellPrinter.cpp
CellImage.cpp CellImage.cpp
OpenBlobDialog.cpp OpenBlobDialog.cpp
RecordModel.cpp RecordModel.cpp
InspectorWidget.cpp InspectorWidget.cpp
SelectionPopupModel.cpp SelectionPopupModel.cpp
@ -120,6 +125,7 @@
ScriptWidget.cpp ScriptWidget.cpp
DesignBlob.cpp DesignBlob.cpp
JsonConfiguration.cpp JsonConfiguration.cpp
AboutWindow.cpp
) )
set( pyCpps PyHSVr.cpp set( pyCpps PyHSVr.cpp
PyDrawingStyle.cpp PyDrawingStyle.cpp
@ -129,6 +135,8 @@
PyGraphics.cpp PyGraphics.cpp
PyViewer.cpp PyViewer.cpp
PyCellViewer.cpp PyCellViewer.cpp
PyErrorWidget.cpp
PyAboutWindow.cpp
Script.cpp Script.cpp
) )

View File

@ -17,5 +17,6 @@
<file>images/angry-birds-red.png</file> <file>images/angry-birds-red.png</file>
<file>images/angry-birds-chuck.png</file> <file>images/angry-birds-chuck.png</file>
<file>images/angry-birds-bomb.png</file> <file>images/angry-birds-bomb.png</file>
<file>images/Coriolis-logo-white-4.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -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 <unistd.h>
#include <csignal>
#include <memory>
#include <QCloseEvent>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
#include <QTextEdit>
#include <QScrollArea>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFrame>
#include <QFont>
#include <QFontMetrics>
#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("<A Python exception was raised>") );
setToolTip ( tr("Caramba! Encore rate!") );
//_header->setMinimumWidth( Graphics::isHighDpi() ? 1500 : 400 );
_header->setTextFormat ( Qt::RichText );
_header->setText ( "<b>[ERROR]</b>" );
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 ( "<b>No program trace sets yet.</b>" );
_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 ("<b>[ERROR]</b>");
_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.

View File

@ -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.

View File

@ -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.

View File

@ -21,7 +21,9 @@
#include "hurricane/viewer/PyDrawingGroup.h" #include "hurricane/viewer/PyDrawingGroup.h"
#include "hurricane/viewer/PyDisplayStyle.h" #include "hurricane/viewer/PyDisplayStyle.h"
#include "hurricane/viewer/PyHSVr.h" #include "hurricane/viewer/PyHSVr.h"
#include "hurricane/viewer/PyErrorWidget.h"
#include "hurricane/viewer/PyCellViewer.h" #include "hurricane/viewer/PyCellViewer.h"
#include "hurricane/viewer/PyAboutWindow.h"
namespace Hurricane { namespace Hurricane {
@ -89,7 +91,9 @@ extern "C" {
PyDisplayStyleVector_LinkPyType (); PyDisplayStyleVector_LinkPyType ();
PyHApplication_LinkPyType (); PyHApplication_LinkPyType ();
PyGraphics_LinkPyType (); PyGraphics_LinkPyType ();
PyErrorWidget_LinkPyType ();
PyCellViewer_LinkPyType (); PyCellViewer_LinkPyType ();
PyAboutWindow_LinkPyType ();
PYTYPE_READY ( HSVr ); PYTYPE_READY ( HSVr );
PYTYPE_READY ( RawDrawingStyle ); PYTYPE_READY ( RawDrawingStyle );
@ -103,7 +107,9 @@ extern "C" {
PYTYPE_READY ( DisplayStyleVectorIterator ); PYTYPE_READY ( DisplayStyleVectorIterator );
PYTYPE_READY ( HApplication ); PYTYPE_READY ( HApplication );
PYTYPE_READY ( Graphics ); PYTYPE_READY ( Graphics );
PYTYPE_READY ( ErrorWidget );
PYTYPE_READY ( CellViewer ); PYTYPE_READY ( CellViewer );
PYTYPE_READY ( AboutWindow );
// Identifier string can take up to 10 characters. // Identifier string can take up to 10 characters.
__cs.addType ( "hsvr" , &PyTypeHSVr , "<HSVr>" , false ); __cs.addType ( "hsvr" , &PyTypeHSVr , "<HSVr>" , false );
@ -125,7 +131,11 @@ extern "C" {
Py_INCREF ( &PyTypeGraphics ); Py_INCREF ( &PyTypeGraphics );
PyModule_AddObject ( module, "Graphics" , (PyObject*)&PyTypeGraphics ); PyModule_AddObject ( module, "Graphics" , (PyObject*)&PyTypeGraphics );
Py_INCREF ( &PyTypeCellViewer ); Py_INCREF ( &PyTypeCellViewer );
PyModule_AddObject ( module, "ErrorWidget" , (PyObject*)&PyTypeErrorWidget );
Py_INCREF ( &PyTypeErrorWidget );
PyModule_AddObject ( module, "CellViewer" , (PyObject*)&PyTypeCellViewer ); PyModule_AddObject ( module, "CellViewer" , (PyObject*)&PyTypeCellViewer );
Py_INCREF ( &PyTypeAboutWindow );
PyModule_AddObject ( module, "AboutWindow" , (PyObject*)&PyTypeAboutWindow );
PyDisplayStyle_postModuleInit(); PyDisplayStyle_postModuleInit();
PyCellViewer_postModuleInit(); PyCellViewer_postModuleInit();

View File

@ -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 <exception>
#include <QDialog>
class QLabel;
class QTextEdit;
namespace Hurricane {
class AboutWindow : public QDialog {
Q_OBJECT;
public:
static bool show ();
public:
AboutWindow ( QWidget* parent=NULL);
};
} // Hurricane namespace.

View File

@ -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 <exception>
#include <functional>
#include <QDialog>
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.

View File

@ -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.

View File

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B