--- a/src/eric7/Tools/UIPreviewer.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Tools/UIPreviewer.py Wed Jul 13 14:55:47 2022 +0200 @@ -13,9 +13,20 @@ from PyQt6.QtCore import QDir, QEvent, QSize, Qt from PyQt6.QtGui import QAction, QKeySequence, QImageWriter, QPainter from PyQt6.QtWidgets import ( - QSizePolicy, QSpacerItem, QWidget, QHBoxLayout, QWhatsThis, QDialog, - QScrollArea, QApplication, QStyleFactory, QFrame, QMainWindow, - QComboBox, QVBoxLayout, QLabel + QSizePolicy, + QSpacerItem, + QWidget, + QHBoxLayout, + QWhatsThis, + QDialog, + QScrollArea, + QApplication, + QStyleFactory, + QFrame, + QMainWindow, + QComboBox, + QVBoxLayout, + QLabel, ) from PyQt6.QtPrintSupport import QPrinter, QPrintDialog from PyQt6 import uic @@ -35,35 +46,35 @@ """ 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() - + super().__init__(parent) if not name: self.setObjectName("UIPreviewer") else: self.setObjectName(name) - - self.setStyle(Preferences.getUI("Style"), - Preferences.getUI("StyleSheet")) - + + self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) + self.resize(QSize(600, 480).expandedTo(self.minimumSizeHint())) self.statusBar() - + self.setWindowIcon(UI.PixmapCache.getIcon("eric")) self.setWindowTitle(self.tr("UI Previewer")) self.cw = QWidget(self) self.cw.setObjectName("centralWidget") - + self.UIPreviewerLayout = QVBoxLayout(self.cw) self.UIPreviewerLayout.setContentsMargins(6, 6, 6, 6) self.UIPreviewerLayout.setSpacing(6) @@ -84,12 +95,13 @@ self.styleCombo.setToolTip(self.tr("Select the GUI Theme")) self.styleLayout.addWidget(self.styleCombo) self.styleCombo.addItems(sorted(QStyleFactory().keys())) - currentStyle = Preferences.getSettings().value('UIPreviewer/style') + currentStyle = Preferences.getSettings().value("UIPreviewer/style") if currentStyle is not None: self.styleCombo.setCurrentIndex(int(currentStyle)) - + styleSpacer = QSpacerItem( - 40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + 40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum + ) self.styleLayout.addItem(styleSpacer) self.UIPreviewerLayout.addLayout(self.styleLayout) @@ -98,26 +110,27 @@ self.previewSV.setFrameShape(QFrame.Shape.NoFrame) self.previewSV.setFrameShadow(QFrame.Shadow.Plain) self.previewSV.setSizePolicy( - QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding + ) self.UIPreviewerLayout.addWidget(self.previewSV) self.setCentralWidget(self.cw) - + self.styleCombo.activated[int].connect(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. @@ -126,113 +139,115 @@ 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"), - self.tr('&Open File'), self) - self.openAct.setShortcut( - QKeySequence(self.tr("Ctrl+O", "File|Open"))) - self.openAct.setStatusTip(self.tr('Open a UI file for display')) - self.openAct.setWhatsThis(self.tr( - """<b>Open File</b>""" - """<p>This opens a new UI file for display.</p>""" - )) + UI.PixmapCache.getIcon("openUI"), self.tr("&Open File"), self + ) + self.openAct.setShortcut(QKeySequence(self.tr("Ctrl+O", "File|Open"))) + self.openAct.setStatusTip(self.tr("Open a UI file for display")) + self.openAct.setWhatsThis( + self.tr( + """<b>Open File</b>""" + """<p>This opens a new UI file for display.</p>""" + ) + ) self.openAct.triggered.connect(self.__openFile) - + self.printAct = QAction( - UI.PixmapCache.getIcon("print"), - self.tr('&Print'), self) - self.printAct.setShortcut( - QKeySequence(self.tr("Ctrl+P", "File|Print"))) - self.printAct.setStatusTip(self.tr('Print a screen capture')) - self.printAct.setWhatsThis(self.tr( - """<b>Print</b>""" - """<p>Print a screen capture.</p>""" - )) + UI.PixmapCache.getIcon("print"), self.tr("&Print"), self + ) + self.printAct.setShortcut(QKeySequence(self.tr("Ctrl+P", "File|Print"))) + self.printAct.setStatusTip(self.tr("Print a screen capture")) + self.printAct.setWhatsThis( + self.tr("""<b>Print</b>""" """<p>Print a screen capture.</p>""") + ) self.printAct.triggered.connect(self.__printImage) - + self.printPreviewAct = QAction( - UI.PixmapCache.getIcon("printPreview"), - self.tr('Print Preview'), self) - self.printPreviewAct.setStatusTip(self.tr( - 'Print preview a screen capture')) - self.printPreviewAct.setWhatsThis(self.tr( - """<b>Print Preview</b>""" - """<p>Print preview a screen capture.</p>""" - )) + UI.PixmapCache.getIcon("printPreview"), self.tr("Print Preview"), self + ) + self.printPreviewAct.setStatusTip(self.tr("Print preview a screen capture")) + self.printPreviewAct.setWhatsThis( + self.tr( + """<b>Print Preview</b>""" """<p>Print preview a screen capture.</p>""" + ) + ) self.printPreviewAct.triggered.connect(self.__printPreviewImage) - + self.imageAct = QAction( - UI.PixmapCache.getIcon("screenCapture"), - self.tr('&Screen Capture'), self) + UI.PixmapCache.getIcon("screenCapture"), self.tr("&Screen Capture"), self + ) self.imageAct.setShortcut( - QKeySequence(self.tr("Ctrl+S", "File|Screen Capture"))) - self.imageAct.setStatusTip(self.tr( - 'Save a screen capture to an image file')) - self.imageAct.setWhatsThis(self.tr( - """<b>Screen Capture</b>""" - """<p>Save a screen capture to an image file.</p>""" - )) + QKeySequence(self.tr("Ctrl+S", "File|Screen Capture")) + ) + self.imageAct.setStatusTip(self.tr("Save a screen capture to an image file")) + self.imageAct.setWhatsThis( + self.tr( + """<b>Screen Capture</b>""" + """<p>Save a screen capture to an image file.</p>""" + ) + ) self.imageAct.triggered.connect(self.__saveImage) - - self.exitAct = QAction( - UI.PixmapCache.getIcon("exit"), self.tr('&Quit'), self) - self.exitAct.setShortcut( - QKeySequence(self.tr("Ctrl+Q", "File|Quit"))) - self.exitAct.setStatusTip(self.tr('Quit the application')) - self.exitAct.setWhatsThis(self.tr( - """<b>Quit</b>""" - """<p>Quit the application.</p>""" - )) + + self.exitAct = QAction(UI.PixmapCache.getIcon("exit"), self.tr("&Quit"), self) + self.exitAct.setShortcut(QKeySequence(self.tr("Ctrl+Q", "File|Quit"))) + self.exitAct.setStatusTip(self.tr("Quit the application")) + self.exitAct.setWhatsThis( + self.tr("""<b>Quit</b>""" """<p>Quit the application.</p>""") + ) self.exitAct.triggered.connect(ericApp().closeAllWindows) - + self.copyAct = QAction( - UI.PixmapCache.getIcon("editCopy"), self.tr('&Copy'), self) - self.copyAct.setShortcut( - QKeySequence(self.tr("Ctrl+C", "Edit|Copy"))) - self.copyAct.setStatusTip( - self.tr('Copy screen capture to clipboard')) - self.copyAct.setWhatsThis(self.tr( - """<b>Copy</b>""" - """<p>Copy screen capture to clipboard.</p>""" - )) + UI.PixmapCache.getIcon("editCopy"), self.tr("&Copy"), self + ) + self.copyAct.setShortcut(QKeySequence(self.tr("Ctrl+C", "Edit|Copy"))) + self.copyAct.setStatusTip(self.tr("Copy screen capture to clipboard")) + self.copyAct.setWhatsThis( + self.tr("""<b>Copy</b>""" """<p>Copy screen capture to clipboard.</p>""") + ) self.copyAct.triggered.connect(self.__copyImageToClipboard) - + self.whatsThisAct = QAction( - UI.PixmapCache.getIcon("whatsThis"), - self.tr('&What\'s This?'), self) + UI.PixmapCache.getIcon("whatsThis"), self.tr("&What's This?"), self + ) self.whatsThisAct.setShortcut(QKeySequence(self.tr("Shift+F1"))) - self.whatsThisAct.setStatusTip(self.tr('Context sensitive help')) - self.whatsThisAct.setWhatsThis(self.tr( - """<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.whatsThisAct.setStatusTip(self.tr("Context sensitive help")) + self.whatsThisAct.setWhatsThis( + self.tr( + """<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.whatsThisAct.triggered.connect(self.__whatsThis) - self.aboutAct = QAction(self.tr('&About'), self) - self.aboutAct.setStatusTip(self.tr( - 'Display information about this software')) - self.aboutAct.setWhatsThis(self.tr( - """<b>About</b>""" - """<p>Display some information about this software.</p>""" - )) + self.aboutAct = QAction(self.tr("&About"), self) + self.aboutAct.setStatusTip(self.tr("Display information about this software")) + self.aboutAct.setWhatsThis( + self.tr( + """<b>About</b>""" + """<p>Display some information about this software.</p>""" + ) + ) self.aboutAct.triggered.connect(self.__about) - - self.aboutQtAct = QAction(self.tr('About &Qt'), self) + + self.aboutQtAct = QAction(self.tr("About &Qt"), self) self.aboutQtAct.setStatusTip( - self.tr('Display information about the Qt toolkit')) - self.aboutQtAct.setWhatsThis(self.tr( - """<b>About Qt</b>""" - """<p>Display some information about the Qt toolkit.</p>""" - )) + self.tr("Display information about the Qt toolkit") + ) + self.aboutQtAct.setWhatsThis( + self.tr( + """<b>About Qt</b>""" + """<p>Display some information about the Qt toolkit.</p>""" + ) + ) self.aboutQtAct.triggered.connect(self.__aboutQt) def __initMenus(self): @@ -241,7 +256,7 @@ """ mb = self.menuBar() - menu = mb.addMenu(self.tr('&File')) + menu = mb.addMenu(self.tr("&File")) menu.setTearOffEnabled(True) menu.addAction(self.openAct) menu.addAction(self.imageAct) @@ -250,14 +265,14 @@ menu.addAction(self.printAct) menu.addSeparator() menu.addAction(self.exitAct) - + menu = mb.addMenu(self.tr("&Edit")) menu.setTearOffEnabled(True) menu.addAction(self.copyAct) - + mb.addSeparator() - - menu = mb.addMenu(self.tr('&Help')) + + menu = mb.addMenu(self.tr("&Help")) menu.setTearOffEnabled(True) menu.addAction(self.aboutAct) menu.addAction(self.aboutQtAct) @@ -277,11 +292,11 @@ filetb.addAction(self.printAct) filetb.addSeparator() filetb.addAction(self.exitAct) - + edittb = self.addToolBar(self.tr("Edit")) edittb.setIconSize(UI.Config.ToolBarIconSize) edittb.addAction(self.copyAct) - + helptb = self.addToolBar(self.tr("Help")) helptb.setIconSize(UI.Config.ToolBarIconSize) helptb.addAction(self.whatsThisAct) @@ -291,18 +306,18 @@ Private slot called in to enter Whats This mode. """ QWhatsThis.enterWhatsThisMode() - + def __guiStyleSelected(self, index): """ Private slot to handle the selection of a GUI style. - + @param index index of the selected entry @type int """ selectedStyle = self.styleCombo.itemText(index) if self.mainWidget: self.__updateChildren(selectedStyle) - + def __about(self): """ Private slot to show the about information. @@ -315,9 +330,9 @@ """<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. @@ -332,14 +347,15 @@ self, self.tr("Select UI file"), self.currentFile, - self.tr("Qt User-Interface Files (*.ui)")) + self.tr("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 @type str """ @@ -348,11 +364,11 @@ self.previewSV.takeWidget() del self.mainWidget self.mainWidget = None - + # load the file with contextlib.suppress(Exception): self.mainWidget = uic.loadUi(fn) - + if self.mainWidget: self.currentFile = fn self.__updateChildren(self.styleCombo.currentText()) @@ -366,35 +382,37 @@ EricMessageBox.warning( self, self.tr("Load UI File"), - self.tr( - """<p>The file <b>{0}</b> could not be loaded.</p>""") - .format(fn)) + self.tr("""<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) """ with EricOverrideCursor(): qstyle = QStyleFactory.create(sstyle) self.mainWidget.setStyle(qstyle) - + lst = self.mainWidget.findChildren(QWidget) for obj in lst: with contextlib.suppress(AttributeError): obj.setStyle(qstyle) del lst - + self.mainWidget.hide() self.mainWidget.show() - + self.lastQStyle = qstyle self.lastStyle = sstyle Preferences.getSettings().setValue( - 'UIPreviewer/style', self.styleCombo.currentIndex()) - + "UIPreviewer/style", self.styleCombo.currentIndex() + ) + def __updateActions(self): """ Private slot to update the actions state. @@ -423,11 +441,11 @@ del self.mainWidget self.mainWidget = None self.__updateActions() - + def eventFilter(self, obj, ev): """ Public method called to filter an event. - + @param obj object, that generated the event (QObject) @param ev the event, that was generated by object (QEvent) @return flag indicating if event was filtered out @@ -443,49 +461,46 @@ 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: EricMessageBox.critical( - self, - self.tr("Save Image"), - self.tr("""There is no UI file loaded.""")) + self, self.tr("Save Image"), self.tr("""There is no UI file loaded.""") + ) return - + defaultExt = "PNG" filters = "" formats = QImageWriter.supportedImageFormats() for imageFormat in formats: - filters = "{0}*.{1} ".format( - filters, bytes(imageFormat).decode().lower()) + filters = "{0}*.{1} ".format(filters, bytes(imageFormat).decode().lower()) fileFilter = self.tr("Images ({0})").format(filters[:-1]) - + fname = EricFileDialog.getSaveFileName( - self, - self.tr("Save Image"), - "", - fileFilter) + self, self.tr("Save Image"), "", fileFilter + ) if not fname: return - + fpath = pathlib.Path(fname) ext = fpath.suffix.upper().replace(".", "") if not ext: ext = defaultExt fpath = fpath.with_suffix(".{0}".format(defaultExt.lower())) - + pix = self.mainWidget.grab() self.__updateChildren(self.lastStyle) if not pix.save(str(fpath), str(ext)): EricMessageBox.critical( self, self.tr("Save Image"), - self.tr( - """<p>The file <b>{0}</b> could not be saved.</p>""") - .format(fpath)) + self.tr("""<p>The file <b>{0}</b> could not be saved.</p>""").format( + fpath + ), + ) def __copyImageToClipboard(self): """ @@ -493,103 +508,109 @@ """ if self.mainWidget is None: EricMessageBox.critical( - self, - self.tr("Save Image"), - self.tr("""There is no UI file loaded.""")) + self, self.tr("Save Image"), self.tr("""There is no UI file loaded.""") + ) return - + cb = QApplication.clipboard() cb.setPixmap(self.mainWidget.grab()) self.__updateChildren(self.lastStyle) - + def __printImage(self): """ Private slot to handle the Print Image menu action. """ if self.mainWidget is None: EricMessageBox.critical( - self, - self.tr("Print Image"), - self.tr("""There is no UI file loaded.""")) + self, self.tr("Print Image"), self.tr("""There is no UI file loaded.""") + ) return - + settings = Preferences.getSettings() printer = QPrinter(QPrinter.PrinterMode.HighResolution) printer.setFullPage(True) - + printerName = Preferences.getPrinter("UIPreviewer/printername") if printerName: printer.setPrinterName(printerName) printer.setPageSize( - QPrinter.PageSize(int(settings.value("UIPreviewer/pagesize")))) + QPrinter.PageSize(int(settings.value("UIPreviewer/pagesize"))) + ) printer.setPageOrder( - QPrinter.PageOrder(int(settings.value("UIPreviewer/pageorder")))) - printer.setOrientation(QPrinter.Orientation( - int(settings.value("UIPreviewer/orientation")))) + QPrinter.PageOrder(int(settings.value("UIPreviewer/pageorder"))) + ) + printer.setOrientation( + QPrinter.Orientation(int(settings.value("UIPreviewer/orientation"))) + ) printer.setColorMode( - QPrinter.ColorMode(int(settings.value("UIPreviewer/colormode")))) - + QPrinter.ColorMode(int(settings.value("UIPreviewer/colormode"))) + ) + printDialog = QPrintDialog(printer, self) if printDialog.exec() == QDialog.DialogCode.Accepted: self.statusBar().showMessage(self.tr("Printing the image...")) self.__print(printer) - + settings.setValue("UIPreviewer/printername", printer.printerName()) settings.setValue("UIPreviewer/pagesize", printer.pageSize()) settings.setValue("UIPreviewer/pageorder", printer.pageOrder()) settings.setValue("UIPreviewer/orientation", printer.orientation()) settings.setValue("UIPreviewer/colormode", printer.colorMode()) - - self.statusBar().showMessage( - self.tr("Image sent to printer..."), 2000) + + self.statusBar().showMessage(self.tr("Image sent to printer..."), 2000) def __printPreviewImage(self): """ Private slot to handle the Print Preview menu action. """ from PyQt6.QtPrintSupport import QPrintPreviewDialog - + if self.mainWidget is None: EricMessageBox.critical( self, self.tr("Print Preview"), - self.tr("""There is no UI file loaded.""")) + self.tr("""There is no UI file loaded."""), + ) return - + settings = Preferences.getSettings() printer = QPrinter(QPrinter.PrinterMode.HighResolution) printer.setFullPage(True) - + printerName = Preferences.getPrinter("UIPreviewer/printername") if printerName: printer.setPrinterName(printerName) printer.setPageSize( - QPrinter.PageSize(int(settings.value("UIPreviewer/pagesize")))) + QPrinter.PageSize(int(settings.value("UIPreviewer/pagesize"))) + ) printer.setPageOrder( - QPrinter.PageOrder(int(settings.value("UIPreviewer/pageorder")))) - printer.setOrientation(QPrinter.Orientation( - int(settings.value("UIPreviewer/orientation")))) + QPrinter.PageOrder(int(settings.value("UIPreviewer/pageorder"))) + ) + printer.setOrientation( + QPrinter.Orientation(int(settings.value("UIPreviewer/orientation"))) + ) printer.setColorMode( - QPrinter.ColorMode(int(settings.value("UIPreviewer/colormode")))) - + QPrinter.ColorMode(int(settings.value("UIPreviewer/colormode"))) + ) + preview = QPrintPreviewDialog(printer, self) preview.paintRequested.connect(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.pageLayout().paintRectPixels(printer.resolution()).x() - - printer.pageLayout().fullRectPixels(printer.resolution()).x() + printer.pageLayout().paintRectPixels(printer.resolution()).x() + - printer.pageLayout().fullRectPixels(printer.resolution()).x() ) // 2 marginY = ( - printer.pageLayout().paintRectPixels(printer.resolution()).y() - - printer.pageLayout().fullRectPixels(printer.resolution()).y() + printer.pageLayout().paintRectPixels(printer.resolution()).y() + - printer.pageLayout().fullRectPixels(printer.resolution()).y() ) // 2 # double the margin on bottom of page @@ -603,10 +624,13 @@ img = self.mainWidget.grab().toImage() self.__updateChildren(self.lastStyle) p.drawImage( - marginX, marginY, img.scaled( - width, height, + marginX, + marginY, + img.scaled( + width, + height, Qt.AspectRatioMode.KeepAspectRatio, - Qt.TransformationMode.SmoothTransformation - ) + Qt.TransformationMode.SmoothTransformation, + ), ) p.end()