diff -r 000000000000 -r de9c2efb9d02 Tools/UIPreviewer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Tools/UIPreviewer.py Mon Dec 28 16:03:33 2009 +0000 @@ -0,0 +1,559 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2004 - 2009 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the UI Previewer main window. +""" + +import sys + +from PyQt4.QtCore import * +from PyQt4.QtGui import * +from PyQt4 import uic + +import Preferences +import UI.PixmapCache +import UI.Config + + +class UIPreviewer(QMainWindow): + """ + Class implementing the UI Previewer main window. + """ + def __init__(self, filename = None, parent = None, name = None): + """ + Constructor + + @param filename name of a UI file to load + @param parent parent widget of this window (QWidget) + @param name name of this window (string) + """ + self.mainWidget = None + self.currentFile = QDir.currentPath() + + QMainWindow.__init__(self, parent) + if not name: + self.setObjectName("UIPreviewer") + else: + self.setObjectName(name) + self.resize(QSize(600, 480).expandedTo(self.minimumSizeHint())) + self.setAttribute(Qt.WA_DeleteOnClose) + self.statusBar() + + self.setWindowIcon(UI.PixmapCache.getIcon("eric.png")) + self.setWindowTitle(self.trUtf8("UI Previewer")) + + self.cw = QWidget(self) + self.cw.setObjectName("centralWidget") + + self.UIPreviewerLayout = QVBoxLayout(self.cw) + self.UIPreviewerLayout.setMargin(6) + self.UIPreviewerLayout.setSpacing(6) + self.UIPreviewerLayout.setObjectName("UIPreviewerLayout") + + self.styleLayout = QHBoxLayout() + self.styleLayout.setMargin(0) + self.styleLayout.setSpacing(6) + self.styleLayout.setObjectName("styleLayout") + + self.styleLabel = QLabel(self.trUtf8("Select GUI Theme"), self.cw) + self.styleLabel.setObjectName("styleLabel") + self.styleLayout.addWidget(self.styleLabel) + + self.styleCombo = QComboBox(self.cw) + self.styleCombo.setObjectName("styleCombo") + self.styleCombo.setEditable(False) + self.styleCombo.setToolTip(self.trUtf8("Select the GUI Theme")) + self.styleLayout.addWidget(self.styleCombo) + self.styleCombo.addItems(QStyleFactory().keys()) + self.styleCombo.setCurrentIndex(\ + Preferences.Prefs.settings.value('UIPreviewer/style').toInt()[0]) + + styleSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.styleLayout.addItem(styleSpacer) + self.UIPreviewerLayout.addLayout(self.styleLayout) + + self.previewSV = QScrollArea(self.cw) + self.previewSV.setObjectName("preview") + self.previewSV.setFrameShape(QFrame.NoFrame) + self.previewSV.setFrameShadow(QFrame.Plain) + self.previewSV.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.UIPreviewerLayout.addWidget(self.previewSV) + + self.setCentralWidget(self.cw) + + self.connect(self.styleCombo,SIGNAL("activated(const QString&)"), + self.__guiStyleSelected) + + self.__initActions() + self.__initMenus() + self.__initToolbars() + + self.__updateActions() + + # defere loading of a UI file until we are shown + self.fileToLoad = filename + + def show(self): + """ + Public slot to show this dialog. + + This overloaded slot loads a UI file to be previewed after + the main window has been shown. This way, previewing a dialog + doesn't interfere with showing the main window. + """ + QMainWindow.show(self) + if self.fileToLoad is not None: + fn, self.fileToLoad = (self.fileToLoad, None) + self.__loadFile(fn) + + def __initActions(self): + """ + Private method to define the user interface actions. + """ + self.openAct = QAction(UI.PixmapCache.getIcon("openUI.png"), + self.trUtf8('&Open File'), self) + self.openAct.setShortcut(QKeySequence(self.trUtf8("Ctrl+O", "File|Open"))) + self.openAct.setStatusTip(self.trUtf8('Open a UI file for display')) + self.openAct.setWhatsThis(self.trUtf8( + """<b>Open File</b>""" + """<p>This opens a new UI file for display.</p>""" + )) + self.connect(self.openAct, SIGNAL('triggered()'), self.__openFile) + + self.printAct = QAction(UI.PixmapCache.getIcon("print.png"), + self.trUtf8('&Print'), self) + self.printAct.setShortcut(QKeySequence(self.trUtf8("Ctrl+P", "File|Print"))) + self.printAct.setStatusTip(self.trUtf8('Print a screen capture')) + self.printAct.setWhatsThis(self.trUtf8( + """<b>Print</b>""" + """<p>Print a screen capture.</p>""" + )) + self.connect(self.printAct, SIGNAL('triggered()'), self.__printImage) + + self.printPreviewAct = QAction(UI.PixmapCache.getIcon("printPreview.png"), + self.trUtf8('Print Preview'), self) + self.printPreviewAct.setStatusTip(self.trUtf8( + 'Print preview a screen capture')) + self.printPreviewAct.setWhatsThis(self.trUtf8( + """<b>Print Preview</b>""" + """<p>Print preview a screen capture.</p>""" + )) + self.connect(self.printPreviewAct, SIGNAL('triggered()'), + self.__printPreviewImage) + + self.imageAct = QAction(UI.PixmapCache.getIcon("screenCapture.png"), + self.trUtf8('&Screen Capture'), self) + self.imageAct.setShortcut(\ + QKeySequence(self.trUtf8("Ctrl+S", "File|Screen Capture"))) + self.imageAct.setStatusTip(self.trUtf8('Save a screen capture to an image file')) + self.imageAct.setWhatsThis(self.trUtf8( + """<b>Screen Capture</b>""" + """<p>Save a screen capture to an image file.</p>""" + )) + self.connect(self.imageAct, SIGNAL('triggered()'), self.__saveImage) + + self.exitAct = QAction(UI.PixmapCache.getIcon("exit.png"), + self.trUtf8('&Quit'), self) + self.exitAct.setShortcut(QKeySequence(self.trUtf8("Ctrl+Q", "File|Quit"))) + self.exitAct.setStatusTip(self.trUtf8('Quit the application')) + self.exitAct.setWhatsThis(self.trUtf8( + """<b>Quit</b>""" + """<p>Quit the application.</p>""" + )) + self.connect(self.exitAct, SIGNAL('triggered()'), + qApp, SLOT('closeAllWindows()')) + + self.copyAct = QAction(UI.PixmapCache.getIcon("editCopy.png"), + self.trUtf8('&Copy'), self) + self.copyAct.setShortcut(QKeySequence(self.trUtf8("Ctrl+C", "Edit|Copy"))) + self.copyAct.setStatusTip(self.trUtf8('Copy screen capture to clipboard')) + self.copyAct.setWhatsThis(self.trUtf8( + """<b>Copy</b>""" + """<p>Copy screen capture to clipboard.</p>""" + )) + self.connect(self.copyAct,SIGNAL('triggered()'),self.__copyImageToClipboard) + + self.whatsThisAct = QAction(UI.PixmapCache.getIcon("whatsThis.png"), + self.trUtf8('&What\'s This?'), self) + self.whatsThisAct.setShortcut(QKeySequence(self.trUtf8("Shift+F1"))) + self.whatsThisAct.setStatusTip(self.trUtf8('Context sensitive help')) + self.whatsThisAct.setWhatsThis(self.trUtf8( + """<b>Display context sensitive help</b>""" + """<p>In What's This? mode, the mouse cursor shows an arrow with a""" + """ question mark, and you can click on the interface elements to get""" + """ a short description of what they do and how to use them. In""" + """ dialogs, this feature can be accessed using the context help""" + """ button in the titlebar.</p>""" + )) + self.connect(self.whatsThisAct,SIGNAL('triggered()'),self.__whatsThis) + + self.aboutAct = QAction(self.trUtf8('&About'), self) + self.aboutAct.setStatusTip(self.trUtf8('Display information about this software')) + self.aboutAct.setWhatsThis(self.trUtf8( + """<b>About</b>""" + """<p>Display some information about this software.</p>""" + )) + self.connect(self.aboutAct,SIGNAL('triggered()'),self.__about) + + self.aboutQtAct = QAction(self.trUtf8('About &Qt'), self) + self.aboutQtAct.setStatusTip(\ + self.trUtf8('Display information about the Qt toolkit')) + self.aboutQtAct.setWhatsThis(self.trUtf8( + """<b>About Qt</b>""" + """<p>Display some information about the Qt toolkit.</p>""" + )) + self.connect(self.aboutQtAct,SIGNAL('triggered()'),self.__aboutQt) + + def __initMenus(self): + """ + Private method to create the menus. + """ + mb = self.menuBar() + + menu = mb.addMenu(self.trUtf8('&File')) + menu.setTearOffEnabled(True) + menu.addAction(self.openAct) + menu.addAction(self.imageAct) + menu.addSeparator() + menu.addAction(self.printPreviewAct) + menu.addAction(self.printAct) + menu.addSeparator() + menu.addAction(self.exitAct) + + menu = mb.addMenu(self.trUtf8("&Edit")) + menu.setTearOffEnabled(True) + menu.addAction(self.copyAct) + + mb.addSeparator() + + menu = mb.addMenu(self.trUtf8('&Help')) + menu.setTearOffEnabled(True) + menu.addAction(self.aboutAct) + menu.addAction(self.aboutQtAct) + menu.addSeparator() + menu.addAction(self.whatsThisAct) + + def __initToolbars(self): + """ + Private method to create the toolbars. + """ + filetb = self.addToolBar(self.trUtf8("File")) + filetb.setIconSize(UI.Config.ToolBarIconSize) + filetb.addAction(self.openAct) + filetb.addAction(self.imageAct) + filetb.addSeparator() + filetb.addAction(self.printPreviewAct) + filetb.addAction(self.printAct) + filetb.addSeparator() + filetb.addAction(self.exitAct) + + edittb = self.addToolBar(self.trUtf8("Edit")) + edittb.setIconSize(UI.Config.ToolBarIconSize) + edittb.addAction(self.copyAct) + + helptb = self.addToolBar(self.trUtf8("Help")) + helptb.setIconSize(UI.Config.ToolBarIconSize) + helptb.addAction(self.whatsThisAct) + + def __whatsThis(self): + """ + Private slot called in to enter Whats This mode. + """ + QWhatsThis.enterWhatsThisMode() + + def __guiStyleSelected(self, selectedStyle): + """ + Private slot to handle the selection of a GUI style. + + @param selectedStyle name of the selected style (string) + """ + if self.mainWidget: + self.__updateChildren(selectedStyle) + + def __about(self): + """ + Private slot to show the about information. + """ + QMessageBox.about(self, self.trUtf8("UI Previewer"), self.trUtf8( + """<h3> About UI Previewer </h3>""" + """<p>The UI Previewer loads and displays Qt User-Interface files""" + """ with various styles, which are selectable via a selection list.</p>""" + )) + + def __aboutQt(self): + """ + Private slot to show info about Qt. + """ + QMessageBox.aboutQt(self, self.trUtf8("UI Previewer")) + + def __openFile(self): + """ + Private slot to load a new file. + """ + fn = QFileDialog.getOpenFileName( + self, + self.trUtf8("Select UI file"), + self.currentFile, + self.trUtf8("Qt User-Interface Files (*.ui)")) + if fn: + self.__loadFile(fn) + + def __loadFile(self, fn): + """ + Private slot to load a ui file. + + @param fn name of the ui file to be laoded (string) + """ + if self.mainWidget: + self.mainWidget.close() + self.previewSV.takeWidget() + del self.mainWidget + self.mainWidget = None + + # load the file + try: + self.mainWidget = uic.loadUi(fn) + except: + pass + + if self.mainWidget: + self.currentFile = fn + self.__updateChildren(self.styleCombo.currentText()) + if isinstance(self.mainWidget, QDialog) or \ + isinstance(self.mainWidget, QMainWindow): + self.mainWidget.show() + self.mainWidget.installEventFilter(self) + else: + self.previewSV.setWidget(self.mainWidget) + self.mainWidget.show() + else: + QMessageBox.warning(self, + self.trUtf8("Load UI File"), + self.trUtf8("""<p>The file <b>{0}</b> could not be loaded.</p>""")\ + .format(fn)) + self.__updateActions() + + def __updateChildren(self, sstyle): + """ + Private slot to change the style of the show UI. + + @param sstyle name of the selected style (string) + """ + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + qstyle = QStyleFactory.create(sstyle) + self.mainWidget.setStyle(qstyle) + + lst = self.mainWidget.findChildren(QWidget) + for obj in lst: + try: + obj.setStyle(qstyle) + except AttributeError: + pass + del lst + + self.mainWidget.hide() + self.mainWidget.show() + + self.lastQStyle = qstyle + self.lastStyle = sstyle + Preferences.Prefs.settings.setValue('UIPreviewer/style', + QVariant(self.styleCombo.currentIndex())) + QApplication.restoreOverrideCursor() + + def __updateActions(self): + """ + Private slot to update the actions state. + """ + if self.mainWidget: + self.imageAct.setEnabled(True) + self.printAct.setEnabled(True) + if self.printPreviewAct: + self.printPreviewAct.setEnabled(True) + self.copyAct.setEnabled(True) + self.styleCombo.setEnabled(True) + else: + self.imageAct.setEnabled(False) + self.printAct.setEnabled(False) + if self.printPreviewAct: + self.printPreviewAct.setEnabled(False) + self.copyAct.setEnabled(False) + self.styleCombo.setEnabled(False) + + def __handleCloseEvent(self): + """ + Private slot to handle the close event of a viewed QMainWidget. + """ + if self.mainWidget: + self.mainWidget.removeEventFilter(self) + del self.mainWidget + self.mainWidget = None + self.__updateActions() + + def eventFilter(self, obj, ev): + """ + Protected method called to filter an event. + + @param object object, that generated the event (QObject) + @param event the event, that was generated by object (QEvent) + @return flag indicating if event was filtered out + """ + if obj == self.mainWidget: + if ev.type() == QEvent.Close: + self.__handleCloseEvent() + return True + else: + if isinstance(self.mainWidget, QDialog): + return QDialog.eventFilter(self, obj, ev) + elif isinstance(self.mainWidget, QMainWindow): + return QMainWindow.eventFilter(self, obj, ev) + else: + return False + + def __saveImage(self): + """ + Private slot to handle the Save Image menu action. + """ + if self.mainWidget is None: + QMessageBox.critical(self, + self.trUtf8("Save Image"), + self.trUtf8("""There is no UI file loaded.""")) + return + + defaultExt = "PNG" + filters = "" + formats = QImageWriter.supportedImageFormats() + for format in formats: + filters = "%s*.%s " % (filters, unicode(format).lower()) + filter = self.trUtf8("Images ({0})").format(filters[:-1]) + + fname = QFileDialog.getSaveFileName(\ + self, + self.trUtf8("Save Image"), + "", + filter) + if not fname: + return + + ext = QFileInfo(fname).suffix().upper() + if not ext: + ext = defaultExt + fname.append(".%s" % defaultExt.lower()) + + pix = QPixmap.grabWidget(self.mainWidget) + self.__updateChildren(self.lastStyle) + if not pix.save(fname, str(ext)): + QMessageBox.critical(None, + self.trUtf8("Save Image"), + self.trUtf8("""<p>The file <b>{0}</b> could not be saved.</p>""") + .format(fname)) + + def __copyImageToClipboard(self): + """ + Private slot to handle the Copy Image menu action. + """ + if self.mainWidget is None: + QMessageBox.critical(None, + self.trUtf8("Save Image"), + self.trUtf8("""There is no UI file loaded.""")) + return + + cb = QApplication.clipboard() + cb.setPixmap(QPixmap.grabWidget(self.mainWidget)) + self.__updateChildren(self.lastStyle) + + def __printImage(self): + """ + Private slot to handle the Print Image menu action. + """ + if self.mainWidget is None: + QMessageBox.critical(None, + self.trUtf8("Print Image"), + self.trUtf8("""There is no UI file loaded.""")) + return + + settings = Preferences.Prefs.settings + printer = QPrinter(QPrinter.HighResolution) + printer.setFullPage(True) + + printer.setPrinterName(settings.value("UIPreviewer/printername").toString()) + printer.setPageSize( + QPrinter.PageSize(settings.value("UIPreviewer/pagesize").toInt()[0])) + printer.setPageOrder( + QPrinter.PageOrder(settings.value("UIPreviewer/pageorder").toInt()[0])) + printer.setOrientation( + QPrinter.Orientation(settings.value("UIPreviewer/orientation").toInt()[0])) + printer.setColorMode( + QPrinter.ColorMode(settings.value("UIPreviewer/colormode").toInt()[0])) + + printDialog = QPrintDialog(printer, self) + if printDialog.exec_() == QDialog.Accepted: + self.statusBar().showMessage(self.trUtf8("Printing the image...")) + self.__print(printer) + + settings.setValue("UIPreviewer/printername", + QVariant(printer.printerName())) + settings.setValue("UIPreviewer/pagesize", QVariant(printer.pageSize())) + settings.setValue("UIPreviewer/pageorder", QVariant(printer.pageOrder())) + settings.setValue("UIPreviewer/orientation", + QVariant(printer.orientation())) + settings.setValue("UIPreviewer/colormode", QVariant(printer.colorMode())) + + self.statusBar().showMessage(self.trUtf8("Image sent to printer..."), 2000) + + def __printPreviewImage(self): + """ + Private slot to handle the Print Preview menu action. + """ + from PyQt4.QtGui import QPrintPreviewDialog + + if self.mainWidget is None: + QMessageBox.critical(None, + self.trUtf8("Print Preview"), + self.trUtf8("""There is no UI file loaded.""")) + return + + settings = Preferences.Prefs.settings + printer = QPrinter(QPrinter.HighResolution) + printer.setFullPage(True) + + printer.setPrinterName(settings.value("UIPreviewer/printername").toString()) + printer.setPageSize( + QPrinter.PageSize(settings.value("UIPreviewer/pagesize").toInt()[0])) + printer.setPageOrder( + QPrinter.PageOrder(settings.value("UIPreviewer/pageorder").toInt()[0])) + printer.setOrientation( + QPrinter.Orientation(settings.value("UIPreviewer/orientation").toInt()[0])) + printer.setColorMode( + QPrinter.ColorMode(settings.value("UIPreviewer/colormode").toInt()[0])) + + preview = QPrintPreviewDialog(printer, self) + self.connect(preview, SIGNAL("paintRequested(QPrinter*)"), self.__print) + preview.exec_() + + def __print(self, printer): + """ + Private slot to the actual printing. + + @param printer reference to the printer object (QPrinter) + """ + p = QPainter(printer) + marginX = (printer.pageRect().x() - printer.paperRect().x()) / 2 + marginY = (printer.pageRect().y() - printer.paperRect().y()) / 2 + + # double the margin on bottom of page + if printer.orientation() == QPrinter.Portrait: + width = printer.width() - marginX * 2 + height = printer.height() - marginY * 3 + else: + marginX *= 2 + width = printer.width() - marginX * 2 + height = printer.height() - marginY * 2 + img = QPixmap.grabWidget(self.mainWidget).toImage() + self.__updateChildren(self.lastStyle) + p.drawImage(marginX, marginY, + img.scaled(width, height, + Qt.KeepAspectRatio, Qt.SmoothTransformation)) + p.end()