--- a/src/eric7/EricGraphics/EricGraphicsView.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/EricGraphics/EricGraphicsView.py Wed Jul 13 14:55:47 2022 +0200 @@ -21,63 +21,87 @@ class EricGraphicsView(QGraphicsView): """ Class implementing a graphics view. - + @signal zoomValueChanged(int) emitted to signal a change of the zoom value """ + zoomValueChanged = pyqtSignal(int) - + ZoomLevels = [ - 1, 3, 5, 7, 9, - 10, 20, 30, 50, 67, 80, 90, + 1, + 3, + 5, + 7, + 9, + 10, + 20, + 30, + 50, + 67, + 80, + 90, 100, - 110, 120, 133, 150, 170, 200, 240, 300, 400, - 500, 600, 700, 800, 900, 1000, + 110, + 120, + 133, + 150, + 170, + 200, + 240, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, ] ZoomLevelDefault = 100 - + def __init__(self, scene, parent=None): """ Constructor - + @param scene reference to the scene object (QGraphicsScene) @param parent parent widget (QWidget) """ super().__init__(scene, parent) self.setObjectName("EricGraphicsView") - + self.__initialSceneSize = self.scene().sceneRect().size() self.setBackgroundBrush(QBrush(self.getBackgroundColor())) self.setRenderHint(QPainter.RenderHint.Antialiasing, True) self.setDragMode(QGraphicsView.DragMode.RubberBandDrag) - self.setAlignment( - Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) + self.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop) self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) - self.setViewportUpdateMode( - QGraphicsView.ViewportUpdateMode.SmartViewportUpdate) - - self.setWhatsThis(self.tr( - "<b>Graphics View</b>\n" - "<p>This graphics view is used to show a diagram. \n" - "There are various actions available to manipulate the \n" - "shown items.</p>\n" - "<ul>\n" - "<li>Clicking on an item selects it.</li>\n" - "<li>Ctrl-clicking adds an item to the selection.</li>\n" - "<li>Ctrl-clicking a selected item deselects it.</li>\n" - "<li>Clicking on an empty spot of the canvas resets the selection." - "</li>\n" - "<li>Dragging the mouse over the canvas spans a rubberband to \n" - "select multiple items.</li>\n" - "<li>Dragging the mouse over a selected item moves the \n" - "whole selection.</li>\n" - "</ul>\n" - )) - + self.setViewportUpdateMode(QGraphicsView.ViewportUpdateMode.SmartViewportUpdate) + + self.setWhatsThis( + self.tr( + "<b>Graphics View</b>\n" + "<p>This graphics view is used to show a diagram. \n" + "There are various actions available to manipulate the \n" + "shown items.</p>\n" + "<ul>\n" + "<li>Clicking on an item selects it.</li>\n" + "<li>Ctrl-clicking adds an item to the selection.</li>\n" + "<li>Ctrl-clicking a selected item deselects it.</li>\n" + "<li>Clicking on an empty spot of the canvas resets the selection." + "</li>\n" + "<li>Dragging the mouse over the canvas spans a rubberband to \n" + "select multiple items.</li>\n" + "<li>Dragging the mouse over a selected item moves the \n" + "whole selection.</li>\n" + "</ul>\n" + ) + ) + def getDrawingColors(self): """ Public method to get the configured drawing colors. - + @return tuple containing the foreground and background colors @rtype tuple of (QColor, QColor) """ @@ -87,34 +111,34 @@ drawingMode = "white_black" else: drawingMode = "black_white" - + if drawingMode == "white_black": return (QColor("#ffffff"), QColor("#262626")) else: return (QColor("#000000"), QColor("#ffffff")) - + def getForegroundColor(self): """ Public method to get the configured foreground color. - + @return foreground color @rtype QColor """ return self.getDrawingColors()[0] - + def getBackgroundColor(self): """ Public method to get the configured background color. - + @return background color @rtype QColor """ return self.getDrawingColors()[1] - + def __levelForZoom(self, zoom): """ Private method determining the zoom level index given a zoom factor. - + @param zoom zoom factor (integer) @return index of zoom factor (integer) """ @@ -125,7 +149,7 @@ if zoom <= EricGraphicsView.ZoomLevels[index]: break return index - + def zoomIn(self): """ Public method to zoom in. @@ -133,7 +157,7 @@ index = self.__levelForZoom(self.zoom()) if index < len(EricGraphicsView.ZoomLevels) - 1: self.setZoom(EricGraphicsView.ZoomLevels[index + 1]) - + def zoomOut(self): """ Public method to zoom out. @@ -141,18 +165,17 @@ index = self.__levelForZoom(self.zoom()) if index > 0: self.setZoom(EricGraphicsView.ZoomLevels[index - 1]) - + def zoomReset(self): """ Public method to handle the reset the zoom value. """ - self.setZoom( - EricGraphicsView.ZoomLevels[EricGraphicsView.ZoomLevelDefault]) - + self.setZoom(EricGraphicsView.ZoomLevels[EricGraphicsView.ZoomLevelDefault]) + def setZoom(self, value): """ Public method to set the zoom value in percent. - + @param value zoom value in percent (integer) """ if value != self.zoom(): @@ -160,19 +183,19 @@ factor = value / 100.0 self.scale(factor, factor) self.zoomValueChanged.emit(value) - + def zoom(self): """ Public method to get the current zoom factor in percent. - + @return current zoom factor in percent (integer) """ return int(self.transform().m11() * 100.0) - + def resizeScene(self, amount, isWidth=True): """ Public method to resize the scene. - + @param amount size increment (integer) @param isWidth flag indicating width is to be resized (boolean) """ @@ -188,13 +211,13 @@ width = rect.width() if height < rect.height(): height = rect.height() - + self.setSceneSize(width, height) - + def setSceneSize(self, width, height): """ Public method to set the scene size. - + @param width width for the scene (real) @param height height for the scene (real) """ @@ -202,11 +225,11 @@ rect.setHeight(height) rect.setWidth(width) self.scene().setSceneRect(rect) - + def autoAdjustSceneSize(self, limit=False): """ Public method to adjust the scene size to the diagram size. - + @param limit flag indicating to limit the scene to the initial size (boolean) """ @@ -218,12 +241,12 @@ newWidth = size.width() newHeight = size.height() self.setSceneSize(newWidth, newHeight) - + def _getDiagramRect(self, border=0): """ Protected method to calculate the minimum rectangle fitting the diagram. - + @param border border width to include in the calculation (integer) @return the minimum rectangle (QRectF) """ @@ -251,13 +274,13 @@ starty -= border endx += border endy += border - + return QRectF(startx, starty, endx - startx + 1, endy - starty + 1) - + def _getDiagramSize(self, border=0): """ Protected method to calculate the minimum size fitting the diagram. - + @param border border width to include in the calculation (integer) @return the minimum size (QSizeF) """ @@ -275,14 +298,14 @@ if border: endx += border endy += border - + return QSizeF(endx + 1, endy + 1) - + def __getDiagram(self, rect, imageFormat="PNG", filename=None): """ Private method to retrieve the diagram from the scene fitting it in the minimum rectangle. - + @param rect minimum rectangle fitting the diagram @type QRectF @param imageFormat format for the image file @@ -293,18 +316,19 @@ @rtype QPixmap or QSvgGenerator """ selectedItems = self.scene().selectedItems() - + # step 1: deselect all widgets if selectedItems: for item in selectedItems: item.setSelected(False) - + # step 2: grab the diagram if imageFormat == "PNG": paintDevice = QPixmap(int(rect.width()), int(rect.height())) paintDevice.fill(self.backgroundBrush().color()) else: from PyQt6.QtSvg import QSvgGenerator + paintDevice = QSvgGenerator() paintDevice.setResolution(100) # 100 dpi paintDevice.setSize(QSize(int(rect.width()), int(rect.height()))) @@ -313,18 +337,18 @@ painter = QPainter(paintDevice) painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) self.scene().render(painter, QRectF(), rect) - + # step 3: reselect the widgets if selectedItems: for item in selectedItems: item.setSelected(True) - + return paintDevice - + def saveImage(self, filename, imageFormat="PNG"): """ Public method to save the scene to a file. - + @param filename name of the file to write the image to (string) @param imageFormat format for the image file (string) @return flag indicating success (boolean) @@ -336,73 +360,81 @@ else: pixmap = self.__getDiagram(rect) return pixmap.save(filename, imageFormat) - + def printDiagram(self, printer, diagramName=""): """ Public method to print the diagram. - + @param printer reference to a ready configured printer object (QPrinter) @param diagramName name of the diagram (string) """ painter = QPainter(printer) - + font = QFont(["times"], 10) painter.setFont(font) fm = painter.fontMetrics() fontHeight = fm.lineSpacing() 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() ) marginX = ( - Preferences.getPrinter("LeftMargin") * - int(printer.resolution() / 2.54) - marginX + Preferences.getPrinter("LeftMargin") * int(printer.resolution() / 2.54) + - marginX ) 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() ) marginY = ( - Preferences.getPrinter("TopMargin") * - int(printer.resolution() / 2.54) - marginY + Preferences.getPrinter("TopMargin") * int(printer.resolution() / 2.54) + - marginY ) - + width = ( - printer.width() - marginX - - Preferences.getPrinter("RightMargin") * - int(printer.resolution() / 2.54) + printer.width() + - marginX + - Preferences.getPrinter("RightMargin") * int(printer.resolution() / 2.54) ) height = ( - printer.height() - fontHeight - 4 - marginY - - Preferences.getPrinter("BottomMargin") * - int(printer.resolution() / 2.54) + printer.height() + - fontHeight + - 4 + - marginY + - Preferences.getPrinter("BottomMargin") * int(printer.resolution() / 2.54) ) - - self.scene().render(painter, - target=QRectF(marginX, marginY, width, height)) - + + self.scene().render(painter, target=QRectF(marginX, marginY, width, height)) + # write a foot note tc = QColor(50, 50, 50) painter.setPen(tc) painter.drawRect(marginX, marginY, width, height) - painter.drawLine(marginX, marginY + height + 2, - marginX + width, marginY + height + 2) + painter.drawLine( + marginX, marginY + height + 2, marginX + width, marginY + height + 2 + ) painter.setFont(font) - painter.drawText(marginX, marginY + height + 4, width, - fontHeight, Qt.AlignmentFlag.AlignRight, diagramName) - + painter.drawText( + marginX, + marginY + height + 4, + width, + fontHeight, + Qt.AlignmentFlag.AlignRight, + diagramName, + ) + painter.end() - + ########################################################################### ## The methods below should be overridden by subclasses to get special ## behavior. ########################################################################### - + def filteredItems(self, items): """ Public method to filter a list of items. - + @param items list of items as returned by the scene object (QGraphicsItem) @return list of interesting collision items (QGraphicsItem)