# -*- mode:Python; explicit-buffer-name: "io.py" -*- # # This file is part of the Coriolis Software. # Copyright (c) UPMC 2012-2018, All Rights Reserved # # +-----------------------------------------------------------------+ # | C O R I O L I S | # | C o r i o l i s / C h a m s B u i l d e r | # | | # | Author : Jean-Paul Chaput | # | E-mail : Jean-Paul.Chaput@lip6.fr | # | =============================================================== | # | Python : "./crlcore/helpers/io.py" | # +-----------------------------------------------------------------+ import sys import os import os.path import re import traceback 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 import helpers from Hurricane import UpdateSession import Viewer # ------------------------------------------------------------------- # Class : "ErrorWidget". 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 ) pixmap = QPixmap( ':/images/angry-birds-red.png' ) pixmap = pixmap.scaledToWidth( 150 ) 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 # ------------------------------------------------------------------- # Class : "ErrorMessage". class ErrorMessage ( Exception ): def __init__ ( self, code, *arguments ): self.scriptPath = None self.trace = traceback.extract_stack() self._code = code self._errors = [ 'Malformed call to ErrorMessage()' , '%s' % str(arguments) ] text = None if len(arguments) == 1: if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n') else: self._errors = arguments[0] elif len(arguments) > 1: sys.stdout.flush() text = list(arguments) if text: self._errors = [] while len(text[0]) == 0: del text[0] lstrip = 0 if text[0].startswith('[ERROR]'): lstrip = 8 for line in text: if line[0:lstrip] == ' '*lstrip or \ line[0:lstrip-1] == '[ERROR]': self._errors += [ line[lstrip:] ] else: self._errors += [ line.lstrip() ] sys.stdout.flush() return def __str__ ( self ): if not isinstance(self._errors,list): return "[ERROR] %s" % self._errors formatted = "\n" for i in range(len(self._errors)): if i == 0: formatted += "[ERROR] %s" % self._errors[i] else: formatted += " %s" % self._errors[i] if i+1 < len(self._errors): formatted += "\n" return formatted def getLinesAsString ( self ): if not isinstance(self._errors,list): return self._errors lines = '' for line in self._errors: lines += line + '\n' return lines def addMessage ( self, message ): if not isinstance(self._errors,list): self._errors = [ self._errors ] if isinstance(message,list): for line in message: self._errors += [ line ] else: self._errors += [ message ] return def terminate ( self ): print self sys.exit( self._code ) def _getCode ( self ): return self._code code = property(_getCode) @staticmethod def show ( code, *arguments ): e = ErrorMessage( code, *arguments ) if Viewer.Graphics.get().isEnabled(): tryCont = ErrorWidget( e ).exec_() if not tryCont: raise e else: raise e return def catch ( errorObject ): if isinstance(errorObject,ErrorMessage): em = errorObject else: em = ErrorMessage( 2, errorObject ) em.trace = traceback.extract_tb( sys.exc_info()[2] ) em.scriptPath = __file__ if Viewer.Graphics.get().isEnabled(): tryCont = ErrorWidget( em ).exec_() print em print helpers.textStackTrace( em.trace, True, em.scriptPath ) if UpdateSession.getStackSize() > 0: UpdateSession.close() return # ------------------------------------------------------------------- # Class : "WarningMessage". class WarningMessage ( Exception ): def __init__ ( self, message ): self._warnings = message return def __str__ ( self ): if not isinstance(self._warnings,list): return "[WARNING] %s" % self._warnings formatted = "\n" for i in range(len(self._warnings)): if i == 0: formatted += "[WARNING] %s" % self._warnings[i] else: formatted += " %s" % self._warnings[i] if i+1 < len(self._warnings): formatted += "\n" return formatted