def _print(self): """Do the printing, hide the print preview dialog, set :attr:`_toBeCleared` flag to True to trigger clearing the next time the dialog is shown. If the printer is not setup, do it first.""" printer = self.printer painter = qt.QPainter() if not painter.begin(printer) or printer is None: _logger.error("Cannot initialize printer") return try: self.scene.render( painter, qt.QRectF(0, 0, printer.width(), printer.height()), qt.QRectF(self.page.rect().x(), self.page.rect().y(), self.page.rect().width(), self.page.rect().height()), qt.Qt.KeepAspectRatio) painter.end() self.hide() self.accept() self._toBeCleared = True except: # FIXME painter.end() qt.QMessageBox.critical( self, "ERROR", 'Printing problem:\n %s' % sys.exc_info()[1]) _logger.error('printing problem:\n %s' % sys.exc_info()[1]) return
def _updatePrinter(self): """Resize :attr:`page`, :attr:`scene` and :attr:`view` to :attr:`printer` width and height.""" printer = self.printer assert printer is not None, \ "_updatePrinter should not be called unless a printer is defined" if self.scene is None: self.scene = qt.QGraphicsScene() self.scene.setBackgroundBrush(qt.QColor(qt.Qt.lightGray)) self.scene.setSceneRect( qt.QRectF(0, 0, printer.width(), printer.height())) if self.page is None: self.page = qt.QGraphicsRectItem(0, 0, printer.width(), printer.height()) self.page.setBrush(qt.QColor(qt.Qt.white)) self.scene.addItem(self.page) self.scene.setSceneRect( qt.QRectF(0, 0, printer.width(), printer.height())) self.page.setPos(qt.QPointF(0.0, 0.0)) self.page.setRect(qt.QRectF(0, 0, printer.width(), printer.height())) if self.view is None: self.view = qt.QGraphicsView(self.scene) self.mainLayout.addWidget(self.view) self._buildStatusBar() # self.view.scale(1./self._viewScale, 1./self._viewScale) self.view.fitInView(self.page.rect(), qt.Qt.KeepAspectRatio) self._viewScale = 1.00 self._updateTargetLabel()
def _triggered(self, checked=False): plot3d = self.getPlot3DWidget() if plot3d is None: _logger.error('Cannot print widget, no associated Plot3DWidget') else: printer = self.getPrinter() dialog = qt.QPrintDialog(printer, plot3d) dialog.setWindowTitle('Print Plot3D snapshot') if not dialog.exec_(): return image = plot3d.grabGL() # Draw pixmap with painter painter = qt.QPainter() if not painter.begin(printer): return if (printer.pageRect().width() < image.width() or printer.pageRect().height() < image.height()): # Downscale to page xScale = printer.pageRect().width() / image.width() yScale = printer.pageRect().height() / image.height() scale = min(xScale, yScale) else: scale = 1. rect = qt.QRectF(0, 0, scale * image.width(), scale * image.height()) painter.drawImage(rect, image) painter.end()
def mousePressEvent(self, event): if self._newRect is not None: self._newRect = None self._point0 = self.pos() parent = self.parentItem() scene = self.scene() # following line prevents dragging along the previously selected # item when resizing another one scene.clearSelection() rect = parent.boundingRect() self._x = rect.x() self._y = rect.y() self._w = rect.width() self._h = rect.height() self._ratio = self._w / self._h if qt.qVersion() < "5.0": self._newRect = qt.QGraphicsRectItem(parent, scene) else: self._newRect = qt.QGraphicsRectItem(parent) self._newRect.setRect(qt.QRectF(self._x, self._y, self._w, self._h)) qt.QGraphicsRectItem.mousePressEvent(self, event)
def mouseMoveEvent(self, event): point1 = self.pos() deltax = point1.x() - self._point0.x() deltay = point1.y() - self._point0.y() if self.keepRatio: r1 = (self._w + deltax) / self._w r2 = (self._h + deltay) / self._h if r1 < r2: self._newRect.setRect( qt.QRectF(self._x, self._y, self._w + deltax, (self._w + deltax) / self._ratio)) else: self._newRect.setRect( qt.QRectF(self._x, self._y, (self._h + deltay) * self._ratio, self._h + deltay)) else: self._newRect.setRect( qt.QRectF(self._x, self._y, self._w + deltax, self._h + deltay)) qt.QGraphicsRectItem.mouseMoveEvent(self, event)
def __init__(self, parent=None, scene=None, keepratio=True): if qt.qVersion() < '5.0': qt.QGraphicsRectItem.__init__(self, parent, scene) else: qt.QGraphicsRectItem.__init__(self, parent) rect = parent.boundingRect() x = rect.x() y = rect.y() w = rect.width() h = rect.height() self._newRect = None self.keepRatio = keepratio self.setRect(qt.QRectF(x + w - 40, y + h - 40, 40, 40)) self.setAcceptHoverEvents(True) pen = qt.QPen() color = qt.QColor(qt.Qt.white) color.setAlpha(0) pen.setColor(color) pen.setStyle(qt.Qt.NoPen) self.setPen(pen) self.setBrush(color) self.setFlag(self.ItemIsMovable, True) self.show()
def paint(self, painter, option, index): """ Write multiline text without using any wrap or any alignment according to the cell size. :param qt.QPainter painter: Painter context used to displayed the cell :param qt.QStyleOptionViewItem option: Control how the editor is shown :param qt.QIndex index: Index of the data to display """ painter.save() # set colors painter.setPen(qt.QPen(qt.Qt.NoPen)) if option.state & qt.QStyle.State_Selected: brush = option.palette.highlight() painter.setBrush(brush) else: brush = index.data(qt.Qt.BackgroundRole) if brush is None: # default background color for a cell brush = qt.Qt.white painter.setBrush(brush) painter.drawRect(option.rect) if index.isValid(): if option.state & qt.QStyle.State_Selected: brush = option.palette.highlightedText() else: brush = index.data(qt.Qt.ForegroundRole) if brush is None: brush = option.palette.text() painter.setPen(qt.QPen(brush.color())) text = index.data(qt.Qt.DisplayRole) painter.drawText(qt.QRectF(option.rect), text, self.__textOptions) painter.restore()
' ': qt.Qt.NoPen, '-': qt.Qt.SolidLine, '--': qt.Qt.DashLine, '.': qt.Qt.DotLine, ':': qt.Qt.DotLine, '-.': qt.Qt.DashDotLine } lineStylesText = OrderedDict([('no line', ' '), ('solid', '-'), ('dashed', '--'), ('dash-dot', '-.'), ('dotted', ':'), ('', '')]) # Build all lineSymbols, from pyqtgraph lineSymbols = dict([(name, qt.QPainterPath()) for name in ['o', 's', 't', 'd', '+', 'x', '.', ',']]) lineSymbols['o'].addEllipse(qt.QRectF(.1, .1, .8, .8)) lineSymbols['.'].addEllipse(qt.QRectF(.3, .3, .4, .4)) lineSymbols[','].addEllipse(qt.QRectF(.4, .4, .2, .2)) lineSymbols['s'].addRect(qt.QRectF(.1, .1, .8, .8)) coords = { 't': [(0.5, 0.), (.1, .8), (.9, .8)], 'd': [(0.1, 0.5), (0.5, 0.), (0.9, 0.5), (0.5, 1.)], '+': [(0.0, 0.40), (0.40, 0.40), (0.40, 0.), (0.60, 0.), (0.60, 0.40), (1., 0.40), (1., 0.60), (0.60, 0.60), (0.60, 1.), (0.40, 1.), (0.40, 0.60), (0., 0.60)], 'x': [(0.0, 0.40), (0.40, 0.40), (0.40, 0.), (0.60, 0.), (0.60, 0.40), (1., 0.40), (1., 0.60), (0.60, 0.60), (0.60, 1.), (0.40, 1.), (0.40, 0.60), (0., 0.60)] } for s, c in coords.items():
def addSvgItem(self, item, title=None, comment=None, commentPosition=None, viewBox=None): """Add a SVG item to the scene. :param QSvgRenderer item: SVG item to be added to the scene. :param str title: Title shown above (centered) the SVG item. :param str comment: Comment displayed below the SVG item. :param str commentPosition: "CENTER" or "LEFT" :param QRectF viewBox: Bounding box for the item on the print page (xOffset, yOffset, width, height). If None, use original item size. """ if not qt.HAS_SVG: raise RuntimeError("Missing QtSvg library.") if not isinstance(item, qt.QSvgRenderer): raise TypeError("addSvgItem: QSvgRenderer expected") if self._toBeCleared: self._clearAll() self.ensurePrinterIsSet() if self.printer is None: _logger.error("printer is not set, cannot add SvgItem to page") return if title is None: title = 50 * ' ' if comment is None: comment = 80 * ' ' if commentPosition is None: commentPosition = "CENTER" if viewBox is None: if hasattr(item, "_viewBox"): # PyMca compatibility: viewbox attached to item viewBox = item._viewBox else: # try the original item viewbox viewBox = item.viewBoxF() svgItem = _GraphicsSvgRectItem(viewBox, self.page) svgItem.setSvgRenderer(item) svgItem.setCacheMode(qt.QGraphicsItem.NoCache) svgItem.setZValue(0) svgItem.setFlag(qt.QGraphicsItem.ItemIsSelectable, True) svgItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) svgItem.setFlag(qt.QGraphicsItem.ItemIsFocusable, False) rectItemResizeRect = _GraphicsResizeRectItem(svgItem, self.scene) rectItemResizeRect.setZValue(2) self._svgItems.append(item) if qt.qVersion() < '5.0': textItem = qt.QGraphicsTextItem(title, svgItem, self.scene) else: textItem = qt.QGraphicsTextItem(title, svgItem) textItem.setTextInteractionFlags(qt.Qt.TextEditorInteraction) title_offset = 0.5 * textItem.boundingRect().width() textItem.setZValue(1) textItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) dummyComment = 80 * "1" if qt.qVersion() < '5.0': commentItem = qt.QGraphicsTextItem(dummyComment, svgItem, self.scene) else: commentItem = qt.QGraphicsTextItem(dummyComment, svgItem) commentItem.setTextInteractionFlags(qt.Qt.TextEditorInteraction) scaleCalculationRect = qt.QRectF(commentItem.boundingRect()) scale = svgItem.boundingRect().width() / scaleCalculationRect.width() comment_offset = 0.5 * commentItem.boundingRect().width() if commentPosition.upper() == "LEFT": x = 1 else: x = 0.5 * svgItem.boundingRect().width( ) - comment_offset * scale # fixme: centering commentItem.moveBy( svgItem.boundingRect().x() + x, svgItem.boundingRect().y() + svgItem.boundingRect().height()) commentItem.setPlainText(comment) commentItem.setZValue(1) commentItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) if qt.qVersion() < "5.0": commentItem.scale(scale, scale) else: # the correct equivalent would be: # rectItem.setTransform(qt.QTransform.fromScale(scalex, scaley)) commentItem.setScale(scale) textItem.moveBy( svgItem.boundingRect().x() + 0.5 * svgItem.boundingRect().width() - title_offset * scale, svgItem.boundingRect().y()) if qt.qVersion() < "5.0": textItem.scale(scale, scale) else: # the correct equivalent would be: # rectItem.setTransform(qt.QTransform.fromScale(scalex, scaley)) textItem.setScale(scale)
def addPixmap(self, pixmap, title=None, comment=None, commentPosition=None): """Add a pixmap to the print preview scene :param QPixmap pixmap: Pixmap to be added to the scene :param str title: Title shown above (centered) the pixmap :param str comment: Comment displayed below the pixmap :param commentPosition: "CENTER" or "LEFT" """ if self._toBeCleared: self._clearAll() self.ensurePrinterIsSet() if self.printer is None: _logger.error("printer is not set, cannot add pixmap to page") return if title is None: title = ' ' * 88 if comment is None: comment = ' ' * 88 if commentPosition is None: commentPosition = "CENTER" if qt.qVersion() < "5.0": rectItem = qt.QGraphicsRectItem(self.page, self.scene) else: rectItem = qt.QGraphicsRectItem(self.page) rectItem.setRect(qt.QRectF(1, 1, pixmap.width(), pixmap.height())) pen = rectItem.pen() color = qt.QColor(qt.Qt.red) color.setAlpha(1) pen.setColor(color) rectItem.setPen(pen) rectItem.setZValue(1) rectItem.setFlag(qt.QGraphicsItem.ItemIsSelectable, True) rectItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) rectItem.setFlag(qt.QGraphicsItem.ItemIsFocusable, False) rectItemResizeRect = _GraphicsResizeRectItem(rectItem, self.scene) rectItemResizeRect.setZValue(2) if qt.qVersion() < "5.0": pixmapItem = qt.QGraphicsPixmapItem(rectItem, self.scene) else: pixmapItem = qt.QGraphicsPixmapItem(rectItem) pixmapItem.setPixmap(pixmap) pixmapItem.setZValue(0) # I add the title if qt.qVersion() < "5.0": textItem = qt.QGraphicsTextItem(title, rectItem, self.scene) else: textItem = qt.QGraphicsTextItem(title, rectItem) textItem.setTextInteractionFlags(qt.Qt.TextEditorInteraction) offset = 0.5 * textItem.boundingRect().width() textItem.moveBy(0.5 * pixmap.width() - offset, -20) textItem.setZValue(2) # I add the comment if qt.qVersion() < "5.0": commentItem = qt.QGraphicsTextItem(comment, rectItem, self.scene) else: commentItem = qt.QGraphicsTextItem(comment, rectItem) commentItem.setTextInteractionFlags(qt.Qt.TextEditorInteraction) offset = 0.5 * commentItem.boundingRect().width() if commentPosition.upper() == "LEFT": x = 1 else: x = 0.5 * pixmap.width() - offset commentItem.moveBy(x, pixmap.height() + 20) commentItem.setZValue(2) rectItem.moveBy(20, 40)
def addSvgItem(self, item, title=None, comment=None, commentPosition=None, viewBox=None, keepRatio=True): """Add a SVG item to the scene. :param QSvgRenderer item: SVG item to be added to the scene. :param str title: Title shown above (centered) the SVG item. :param str comment: Comment displayed below the SVG item. :param str commentPosition: "CENTER" or "LEFT" :param QRectF viewBox: Bounding box for the item on the print page (xOffset, yOffset, width, height). If None, use original item size. :param bool keepRatio: If True, resizing the item will preserve its original aspect ratio. """ if not qt.HAS_SVG: raise RuntimeError("Missing QtSvg library.") if not isinstance(item, qt.QSvgRenderer): raise TypeError("addSvgItem: QSvgRenderer expected") if self._toBeCleared: self._clearAll() self.ensurePrinterIsSet() if self.printer is None: _logger.error("printer is not set, cannot add SvgItem to page") return if title is None: title = 50 * ' ' if comment is None: comment = 80 * ' ' if commentPosition is None: commentPosition = "CENTER" if viewBox is None: if hasattr(item, "_viewBox"): # PyMca compatibility: viewbox attached to item viewBox = item._viewBox else: # try the original item viewbox viewBox = item.viewBoxF() svgItem = _GraphicsSvgRectItem(viewBox, self.page) svgItem.setSvgRenderer(item) svgItem.setCacheMode(qt.QGraphicsItem.NoCache) svgItem.setZValue(0) svgItem.setFlag(qt.QGraphicsItem.ItemIsSelectable, True) svgItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) svgItem.setFlag(qt.QGraphicsItem.ItemIsFocusable, False) rectItemResizeRect = _GraphicsResizeRectItem(svgItem, self.scene, keepratio=keepRatio) rectItemResizeRect.setZValue(2) self._svgItems.append(item) # Comment / legend dummyComment = 80 * "1" if qt.qVersion() < '5.0': commentItem = qt.QGraphicsTextItem(dummyComment, svgItem, self.scene) else: commentItem = qt.QGraphicsTextItem(dummyComment, svgItem) commentItem.setTextInteractionFlags(qt.Qt.TextEditorInteraction) # we scale the text to have the legend box have the same width as the graph scaleCalculationRect = qt.QRectF(commentItem.boundingRect()) scale = svgItem.boundingRect().width() / scaleCalculationRect.width() commentItem.setPlainText(comment) commentItem.setZValue(1) commentItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) if qt.qVersion() < "5.0": commentItem.scale(scale, scale) else: commentItem.setScale(scale) # align if commentPosition.upper() == "CENTER": alignment = qt.Qt.AlignCenter elif commentPosition.upper() == "RIGHT": alignment = qt.Qt.AlignRight else: alignment = qt.Qt.AlignLeft commentItem.setTextWidth(commentItem.boundingRect().width()) center_format = qt.QTextBlockFormat() center_format.setAlignment(alignment) cursor = commentItem.textCursor() cursor.select(qt.QTextCursor.Document) cursor.mergeBlockFormat(center_format) cursor.clearSelection() commentItem.setTextCursor(cursor) if alignment == qt.Qt.AlignLeft: deltax = 0 else: deltax = (svgItem.boundingRect().width() - commentItem.boundingRect().width()) / 2. commentItem.moveBy(svgItem.boundingRect().x() + deltax, svgItem.boundingRect().y() + svgItem.boundingRect().height()) # Title if qt.qVersion() < '5.0': textItem = qt.QGraphicsTextItem(title, svgItem, self.scene) else: textItem = qt.QGraphicsTextItem(title, svgItem) textItem.setTextInteractionFlags(qt.Qt.TextEditorInteraction) textItem.setZValue(1) textItem.setFlag(qt.QGraphicsItem.ItemIsMovable, True) title_offset = 0.5 * textItem.boundingRect().width() textItem.moveBy(svgItem.boundingRect().x() + 0.5 * svgItem.boundingRect().width() - title_offset * scale, svgItem.boundingRect().y()) if qt.qVersion() < "5.0": textItem.scale(scale, scale) else: textItem.setScale(scale)