def pixmapSize(self, pixmap): """ Return the preferred pixmap size based on the current `zoom` value. """ scale = 2 * self.zoom / 100.0 size = QSizeF(pixmap.size()) * scale return size.expandedTo(QSizeF(16, 16))
def _updatePixmapSize(self): pixmap = self.pixmap() if not pixmap.isNull() and self._size.isValid(): pixsize = QSizeF(self.pixmap().size()) pixsize.scale(self._size, Qt.KeepAspectRatio) else: pixsize = QSizeF() self.pixmapWidget.setPixmapSize(pixsize)
def paintEvent(self, event): if self.__pixmap.isNull(): return sourcerect = QRect(QPoint(0, 0), self.__pixmap.size()) pixsize = QSizeF(self.__pixmap.size()) rect = self.contentsRect() pixsize.scale(QSizeF(rect.size()), Qt.KeepAspectRatio) targetrect = QRectF(QPointF(0, 0), pixsize) targetrect.moveCenter(QPointF(rect.center())) painter = QPainter(self) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(targetrect, self.__pixmap, QRectF(sourcerect)) painter.end()
def __init__(self, pixmap, title="", parent=None): QGraphicsWidget.__init__(self, parent) self._title = None self._size = QSizeF() layout = QGraphicsLinearLayout(Qt.Vertical, self) layout.setSpacing(2) layout.setContentsMargins(5, 5, 5, 5) self.setContentsMargins(0, 0, 0, 0) self.pixmapWidget = GraphicsPixmapWidget(pixmap, self) self.labelWidget = GraphicsTextWidget(title, self) layout.addItem(self.pixmapWidget) layout.addItem(self.labelWidget) layout.setAlignment(self.pixmapWidget, Qt.AlignCenter) layout.setAlignment(self.labelWidget, Qt.AlignHCenter | Qt.AlignBottom) self.setLayout(layout) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setTitle(title) self.setTitleWidth(100)
def _rescale(self): if self._root is None: return crect = self.contentsRect() leaf_count = len(list(leaves(self._root))) if self.orientation in [Left, Right]: drect = QSizeF(self._root.value.height, leaf_count - 1) else: drect = QSizeF(self._root.value.last - 1, self._root.value.height) transform = QTransform().scale(crect.width() / drect.width(), crect.height() / drect.height()) self._itemgroup.setPos(crect.topLeft()) self._itemgroup.setTransform(transform) self._selection_items = None self._update_selection_items()
def paint(self, painter, option, widget=0): if self._pixmap.isNull(): return rect = self.contentsRect() pixsize = QSizeF(self._pixmap.size()) aspectmode = (Qt.KeepAspectRatio if self._keepAspect else Qt.IgnoreAspectRatio) pixsize.scale(rect.size(), aspectmode) pixrect = QRectF(QPointF(0, 0), pixsize) pixrect.moveCenter(rect.center()) painter.save() painter.setPen(QPen(QColor(0, 0, 0, 50), 3)) painter.drawRoundedRect(pixrect, 2, 2) painter.setRenderHint(QPainter.SmoothPixmapTransform) source = QRectF(QPointF(0, 0), QSizeF(self._pixmap.size())) painter.drawPixmap(pixrect, self._pixmap, source) painter.restore()
class GraphicsPixmapWidget(QGraphicsWidget): def __init__(self, pixmap, parent=None): QGraphicsWidget.__init__(self, parent) self.setCacheMode(QGraphicsItem.ItemCoordinateCache) self._pixmap = pixmap self._pixmapSize = QSizeF() self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) def setPixmap(self, pixmap): if self._pixmap != pixmap: self._pixmap = QPixmap(pixmap) self.updateGeometry() def pixmap(self): return QPixmap(self._pixmap) def setPixmapSize(self, size): if self._pixmapSize != size: self._pixmapSize = QSizeF(size) self.updateGeometry() def pixmapSize(self): if self._pixmapSize.isValid(): return QSizeF(self._pixmapSize) else: return QSizeF(self._pixmap.size()) def sizeHint(self, which, constraint=QSizeF()): if which == Qt.PreferredSize: return self.pixmapSize() else: return QGraphicsWidget.sizeHint(self, which, constraint) def paint(self, painter, option, widget=0): if self._pixmap.isNull(): return rect = self.contentsRect() pixsize = self.pixmapSize() pixrect = QRectF(QPointF(0, 0), pixsize) pixrect.moveCenter(rect.center()) painter.save() painter.setPen(QPen(QColor(0, 0, 0, 50), 3)) painter.drawRoundedRect(pixrect, 2, 2) painter.setRenderHint(QPainter.SmoothPixmapTransform) source = QRectF(QPointF(0, 0), QSizeF(self._pixmap.size())) painter.drawPixmap(pixrect, self._pixmap, source) painter.restore()
def __init__(self, graph, scene): QGraphicsObject.__init__(self) if scene: scene.addItem(self) self.graph = graph self.curves = [] self.items = {} self.attributes = [] self.point_attrs = {} self.point_vals = {} self.default_values = { PointColor : Qt.black, PointSize : 8, PointSymbol : OWPoint.Ellipse } self.box_rect = QRectF() self.setFiltersChildEvents(True) self.setFlag(self.ItemHasNoContents, True) self.mouse_down = False self._orientation = Qt.Vertical self.max_size = QSizeF() self._floating = True self._floating_animation = None self._mouse_down_pos = QPointF()
def renderPdf(self, fileName): p = QPrinter() p.setOutputFormat(QPrinter.PdfFormat) p.setOutputFileName(fileName) p.setResolution(pdf_dpi) paperSize = self.m_paperSize if not len(paperSize): pageSize = QSize(self.m_webPage.mainFrame().contentsSize()) paperSize['width'] = str(pageSize.width()) + 'px' paperSize['height'] = str(pageSize.height()) + 'px' paperSize['border'] = '0px' if paperSize.get('width') and paperSize.get('height'): sizePt = QSizeF(ceil(self.stringToPointSize(paperSize['width'])), ceil(self.stringToPointSize(paperSize['height']))) p.setPaperSize(sizePt, QPrinter.Point) elif 'format' in paperSize: orientation = QPrinter.Landscape if paperSize.get( 'orientation') and paperSize['orientation'].lower( ) == 'landscape' else QPrinter.Portrait orientation = QPrinter.Orientation(orientation) p.setOrientation(orientation) formats = { 'A0': QPrinter.A0, 'A1': QPrinter.A1, 'A2': QPrinter.A2, 'A3': QPrinter.A3, 'A4': QPrinter.A4, 'A5': QPrinter.A5, 'A6': QPrinter.A6, 'A7': QPrinter.A7, 'A8': QPrinter.A8, 'A9': QPrinter.A9, 'B0': QPrinter.B0, 'B1': QPrinter.B1, 'B2': QPrinter.B2, 'B3': QPrinter.B3, 'B4': QPrinter.B4, 'B5': QPrinter.B5, 'B6': QPrinter.B6, 'B7': QPrinter.B7, 'B8': QPrinter.B8, 'B9': QPrinter.B9, 'B10': QPrinter.B10, 'C5E': QPrinter.C5E, 'Comm10E': QPrinter.Comm10E, 'DLE': QPrinter.DLE, 'Executive': QPrinter.Executive, 'Folio': QPrinter.Folio, 'Ledger': QPrinter.Ledger, 'Legal': QPrinter.Legal, 'Letter': QPrinter.Letter, 'Tabloid': QPrinter.Tabloid } p.setPaperSize(QPrinter.A4) # fallback for format, size in formats.items(): if format.lower() == paperSize['format'].lower(): p.setPaperSize(size) break else: return False border = floor(self.stringToPointSize( paperSize['border'])) if paperSize.get('border') else 0 p.setPageMargins(border, border, border, border, QPrinter.Point) self.m_webPage.mainFrame().print_(p) return True
def onSelectionRectPointChanged(self, point): self.sceneView.ensureVisible(QRectF(point, QSizeF(1, 1)), 5, 5)
def sizeHint(self, which, constraint=QSizeF()): if which == Qt.PreferredSize: return self.pixmapSize() else: return QGraphicsWidget.sizeHint(self, which, constraint)
def setPixmapSize(self, size): if self._pixmapSize != size: self._pixmapSize = QSizeF(size) self.updateGeometry()
def pixmapSize(self): if self._pixmapSize.isValid(): return QSizeF(self._pixmapSize) else: return QSizeF(self._pixmap.size())
def sizeHint(self, which, constraint=QRectF()): if not self.isVisible(): return QSizeF(0, 0) else: return QGraphicsWidget.sizeHint(self, which, constraint)
def change_geometry(self, newDim): """ This slot changes the unit dimensions of the item. """ self.unitDim = newDim self.size = QSizeF(self.unitDim.width() * self.width, self.unitDim.height() * self.height)
def updateSize(self): size = QSizeF(self.imageSize, self.imageSize) for item in self.thumbnailItems(): item.setThumbnailSize(size)
def canvasMoveEvent(self, e): sItem = self.selectedItem() if (sItem != None and (e.buttons() & Qt.LeftButton)): if (self.mCurrentMoveAction == QgsAnnotationItem.MoveMapPosition): sItem.setMapPosition(self.toMapCoordinates(e.pos())) sItem.update() elif (self.mCurrentMoveAction == QgsAnnotationItem.MoveFramePosition): if (sItem.mapPositionFixed()): sItem.setOffsetFromReferencePoint( sItem.offsetFromReferencePoint() + (e.posF() - self.mLastMousePosition)) else: newCanvasPos = sItem.pos() + (e.posF() - self.mLastMousePosition) sItem.setMapPosition( self.toMapCoordinates(newCanvasPos.toPoint())) sItem.update() elif (self.mCurrentMoveAction != QgsAnnotationItem.NoAction): size = sItem.frameSize() xmin = sItem.offsetFromReferencePoint().x() ymin = sItem.offsetFromReferencePoint().y() xmax = xmin + size.width() ymax = ymin + size.height() if (self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameRight or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameRightDown or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameRightUp): xmax += e.posF().x() - self.mLastMousePosition.x() if (self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameLeft or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameLeftDown or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameLeftUp): xmin += e.posF().x() - self.mLastMousePosition.x() if (self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameUp or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameLeftUp or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameRightUp): ymin += e.posF().y() - self.mLastMousePosition.y() if (self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameDown or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameLeftDown or self.mCurrentMoveAction == QgsAnnotationItem.ResizeFrameRightDown): ymax += e.posF().y() - self.mLastMousePosition.y() #//switch min / max if necessary tmp = 0.0 if (xmax < xmin): tmp = xmax xmax = xmin xmin = tmp if (ymax < ymin): tmp = ymax ymax = ymin ymin = tmp sItem.setOffsetFromReferencePoint(QPointF(xmin, ymin)) sItem.setFrameSize(QSizeF(xmax - xmin, ymax - ymin)) sItem.update() elif (sItem != None): moveAction = sItem.moveActionForPosition(e.posF()) self.mCanvas.setCursor( QCursor(sItem.cursorShapeForAction(moveAction))) self.mLastMousePosition = e.posF()
def __ensureVisible(self, point): self.ensureVisible(QRectF(point, QSizeF(1, 1)), 5, 5),
def _updatePixmapSize(self): pixsize = QSizeF(self._size) self.pixmapWidget.setMinimumSize(pixsize) self.pixmapWidget.setMaximumSize(pixsize)
# coding: utf-8 from PyQt4.QtCore import QSizeF from PyQt4.QtGui import QColor from qgis.core import QgsPoint from qgis.gui import QgsHtmlAnnotationItem from qgis.utils import iface layer = iface.activeLayer() canvas = iface.mapCanvas() html_annotation_item = QgsHtmlAnnotationItem(canvas, layer) X, Y = float(3), float(45) point = QgsPoint(X, Y) html_annotation_item.setMapPosition(point) html_annotation_item.setFrameSize(QSizeF(300, 200)) html_annotation_item.setFrameColor(QColor(0, 255, 0)) html_annotation_item.setFrameBackgroundColor(QColor(128, 128, 128)) html_content = """<!DOCTYPE html> <html> <head> <title></title> </head> <body> <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id
def sizeHint(self, which, constraint=QSizeF()): spacing = max(self.__spacing * (self.count() - 1), 0) return QSizeF(300, self.__barsize * self.count() + spacing)
def drawCorner(self, painter, position, cornerType, maxRadius=None): #logging.debug(self.__class__.__name__ +": drawCorner() "+ self.cornerTypeString(cornerType)) thickness = self.CONNECTION_THICKNESS * self.zoomFactor() halfthick = thickness / 2 cornerRoundness = halfthick**0.5 cornerOffset = halfthick * (cornerRoundness) innerCorner = halfthick * (cornerRoundness - 1) outerCorner = halfthick * (cornerRoundness + 1) innerWidth = halfthick * (cornerRoundness - 1) radius = halfthick * (cornerRoundness + 1) if maxRadius: maxRadius = max(maxRadius, thickness) radius = min(radius, maxRadius) if cornerType == self.CornerType.TOP_RIGHT: startAngle = 0 outerCorner = QPointF(position.x() + halfthick - 2 * radius, position.y() - halfthick) innerCorner = QPointF(outerCorner.x(), outerCorner.y() + (thickness)) center = QPointF(outerCorner.x() + radius, outerCorner.y() + radius) outerRect = QRectF(outerCorner, QSizeF(2 * radius, 2 * radius)) innerRect = QRectF( innerCorner, QSizeF((2 * radius - thickness), (2 * radius - thickness))) outerStart = QPointF(outerCorner.x() + 2 * radius, outerCorner.y() + (radius + halfthick)) innerStart = QPointF(outerCorner.x() + (radius - halfthick), outerCorner.y()) elif cornerType == self.CornerType.TOP_LEFT: startAngle = 90 outerCorner = QPointF(position.x() - halfthick, position.y() - halfthick) innerCorner = QPointF(outerCorner.x() + (thickness), outerCorner.y() + (thickness)) center = QPointF(outerCorner.x() + radius, outerCorner.y() + radius) outerRect = QRectF(outerCorner, QSizeF(2 * radius, 2 * radius)) innerRect = QRectF( innerCorner, QSizeF((2 * radius - thickness), (2 * radius - thickness))) outerStart = QPointF(outerCorner.x() + (radius + halfthick), outerCorner.y()) innerStart = QPointF(outerCorner.x(), outerCorner.y() + (radius + halfthick)) elif cornerType == self.CornerType.BOTTOM_LEFT: startAngle = 180 outerCorner = QPointF(position.x() - halfthick, position.y() + halfthick - 2 * radius) innerCorner = QPointF(outerCorner.x() + (thickness), outerCorner.y()) center = QPointF(outerCorner.x() + radius, outerCorner.y() + radius) outerRect = QRectF(outerCorner, QSizeF(2 * radius, 2 * radius)) innerRect = QRectF( innerCorner, QSizeF((2 * radius - thickness), (2 * radius - thickness))) outerStart = QPointF(outerCorner.x(), outerCorner.y() + (radius - halfthick)) innerStart = QPointF(outerCorner.x() + (radius + halfthick), outerCorner.y() + (2 * radius)) elif cornerType == self.CornerType.BOTTOM_RIGHT: startAngle = 270 outerCorner = QPointF(position.x() + halfthick - 2 * radius, position.y() + halfthick - 2 * radius) innerCorner = QPointF(outerCorner.x(), outerCorner.y()) center = QPointF(outerCorner.x() + radius, outerCorner.y() + radius) outerRect = QRectF(outerCorner, QSizeF(2 * radius, 2 * radius)) innerRect = QRectF( innerCorner, QSizeF((2 * radius - thickness), (2 * radius - thickness))) outerStart = QPointF(outerCorner.x() + (radius - halfthick), outerCorner.y() + 2 * radius) innerStart = QPointF(outerCorner.x() + 2 * radius, outerCorner.y() + (radius - halfthick)) else: # No defined corner, so nothing to draw. #print "PointToPointConnection.drawCorner() - No valid corner, aborting..." return if painter.redirected(painter.device()): # e.q. QPixmap.grabWidget() painter.setBrush(self.FILL_COLOR1) else: brush = QRadialGradient(center, radius) if radius >= thickness: brush.setColorAt((radius - thickness) / radius, self.FILL_COLOR1) # inner border brush.setColorAt((radius - halfthick + 1) / radius, self.FILL_COLOR2) # center of line else: # If zoom is too small use single color brush.setColorAt(0, self.FILL_COLOR1) brush.setColorAt(1, self.FILL_COLOR1) # outer border painter.setBrush(brush) path = QPainterPath() path.moveTo(outerStart) path.arcTo(outerRect, startAngle, 90) path.lineTo(innerStart) path.arcTo(innerRect, startAngle + 90, -90) path.closeSubpath() #painter.setPen(Qt.NoPen) painter.drawPath(path)
def _get_composer_pdf_image(self, width, height, dpi): pdfpath = getTempfilePath('pdf') temp_size = os.path.getsize(pdfpath) p = QPrinter() p.setOutputFormat(QPrinter.PdfFormat) p.setOutputFileName(pdfpath) p.setPaperSize(QSizeF(self._c.paperWidth(), self._c.paperHeight()), QPrinter.Millimeter) p.setFullPage(True) p.setColorMode(QPrinter.Color) p.setResolution(self._c.printResolution()) pdf_p = QPainter(p) # page_mm = p.pageRect(QPrinter.Millimeter) # page_px = p.pageRect(QPrinter.DevicePixel) # self._c.render(pdf_p, page_px, page_mm) self._c.renderPage(pdf_p, 0) pdf_p.end() if temp_size == os.path.getsize(pdfpath): return False, '' filepath = getTempfilePath('png') # Poppler (pdftocairo or pdftoppm): # PDFUTIL -png -singlefile -r 72 -x 0 -y 0 -W 420 -H 280 in.pdf pngbase # muPDF (mudraw): # PDFUTIL -c rgb[a] -r 72 -w 420 -h 280 -o out.png in.pdf if PDFUTIL.strip().endswith('pdftocairo'): filebase = os.path.join( os.path.dirname(filepath), os.path.splitext(os.path.basename(filepath))[0]) call = [ PDFUTIL, '-png', '-singlefile', '-r', str(dpi), '-x', '0', '-y', '0', '-W', str(width), '-H', str(height), pdfpath, filebase ] elif PDFUTIL.strip().endswith('mudraw'): call = [ PDFUTIL, '-c', 'rgba', '-r', str(dpi), '-w', str(width), '-h', str(height), # '-b', '8', '-o', filepath, pdfpath ] else: return False, '' qDebug("_get_composer_pdf_image call: {0}".format(' '.join(call))) res = False try: subprocess.check_call(call) res = True except subprocess.CalledProcessError as e: qDebug("_get_composer_pdf_image failed!\n" "cmd: {0}\n" "returncode: {1}\n" "message: {2}".format(e.cmd, e.returncode, e.message)) if not res: os.unlink(filepath) filepath = '' return res, filepath
class OWLegend(QGraphicsObject): """ A legend for :obj:`.OWPlot`. Its items are arranged into a hierarchy by `category`. This is useful when points differ in more than one attribute. In such a case, there can be one category for point color and one for point shape. Usually the category name will be the name of the attribute, while the item's title will be the value. Arbitrary categories can be created, for an example see :meth:`.OWPlot.update_axes`, which creates a special category for unused axes. decimals .. image:: files/legend-categories.png In the image above, `type` and `milk` are categories with 7 and 2 possible values, respectively. """ def __init__(self, graph, scene): QGraphicsObject.__init__(self) if scene: scene.addItem(self) self.graph = graph self.curves = [] self.items = {} self.attributes = [] self.point_attrs = {} self.point_vals = {} self.default_values = { PointColor : Qt.black, PointSize : 8, PointSymbol : OWPoint.Ellipse } self.box_rect = QRectF() self.setFiltersChildEvents(True) self.setFlag(self.ItemHasNoContents, True) self.mouse_down = False self._orientation = Qt.Vertical self.max_size = QSizeF() self._floating = True self._floating_animation = None self._mouse_down_pos = QPointF() def clear(self): """ Removes all items from the legend """ for lst in self.items.values(): for i in lst: i.setParentItem(None) if self.scene(): self.scene().removeItem(i) self.items = {} self.update_items() def add_curve(self, curve): """ Adds a legend item with the same point symbol and name as ``curve``. If the curve's name contains the equal sign (=), it is split at that sign. The first part of the curve is a used as the category, and the second part as the value. """ i = curve.name.find('=') if i == -1: cat = '' name = curve.name else: cat = curve.name[:i] name = curve.name[i+1:] self.add_item(cat, name, curve.point_item(0, 0, 0)) def add_item(self, category, value, point): """ Adds an item with title ``value`` and point symbol ``point`` to the specified ``category``. """ if category not in self.items: self.items[category] = [OWLegendTitle(category, self)] self.items[category].append(OWLegendItem(str(value), point, self)) self.update_items() def add_color_gradient(self, title, values): if len(values) < 2: # No point in showing a gradient with less that two values return if title in self.items: self.remove_category(title) item = OWLegendGradient(self.graph.contPalette, [str(v) for v in values], self) self.items[title] = [OWLegendTitle(title, self), item] self.update_items() def remove_category(self, category): """ Removes ``category`` and all items that belong to it. """ if category not in self.items: return if self.scene(): for item in self.items[category]: self.scene().removeItem(item) del self.items[category] def update_items(self): """ Updates the legend, repositioning the items according to the legend's orientation. """ self.box_rect = QRectF() x = y = 0 for lst in self.items.values(): for item in lst: if hasattr(item, 'text_item'): item.text_item.setDefaultTextColor(self.graph.color(OWPalette.Text)) if hasattr(item, 'rect_item'): item.rect_item.setBrush(self.graph.color(OWPalette.Canvas)) if hasattr(item, 'set_orientation'): item.set_orientation(self._orientation) if self._orientation == Qt.Vertical: for lst in self.items.values(): for item in lst: if self.max_size.height() and y and y + item.boundingRect().height() > self.max_size.height(): y = 0 x = x + item.boundingRect().width() self.box_rect = self.box_rect | item.boundingRect().translated(x, y) move_item_xy(item, x, y, self.graph.animate_plot) y = y + item.boundingRect().height() elif self._orientation == Qt.Horizontal: for lst in self.items.values(): max_h = max(item.boundingRect().height() for item in lst) for item in lst: if self.max_size.width() and x and x + item.boundingRect().width() > self.max_size.width(): x = 0 y = y + max_h self.box_rect = self.box_rect | item.boundingRect().translated(x, y) move_item_xy(item, x, y, self.graph.animate_plot) x = x + item.boundingRect().width() if lst: x = 0 y = y + max_h def mouseMoveEvent(self, event): self.graph.notify_legend_moved(event.scenePos()) if self._floating: p = event.scenePos() - self._mouse_down_pos if self._floating_animation and self._floating_animation.state() == QPropertyAnimation.Running: self.set_pos_animated(p) else: self.setPos(p) event.accept() def mousePressEvent(self, event): self.setCursor(Qt.ClosedHandCursor) self.mouse_down = True self._mouse_down_pos = event.scenePos() - self.pos() event.accept() def mouseReleaseEvent(self, event): self.unsetCursor() self.mouse_down = False self._mouse_down_pos = QPointF() event.accept() def boundingRect(self): return self.box_rect def paint(self, painter, option, widget=None): pass def set_orientation(self, orientation): """ Sets the legend's orientation to ``orientation``. """ self._orientation = orientation self.update_items() def orientation(self): return self._orientation def set_pos_animated(self, pos): if (self.pos() - pos).manhattanLength() < 6 or not self.graph.animate_plot: self.setPos(pos) else: t = 250 if self._floating_animation and self._floating_animation.state() == QPropertyAnimation.Running: t = t - self._floating_animation.currentTime() self._floating_animation.stop() self._floating_animation = QPropertyAnimation(self, 'pos') self._floating_animation.setEndValue(pos) self._floating_animation.setDuration(t) self._floating_animation.start(QPropertyAnimation.KeepWhenStopped) def set_floating(self, floating, pos=None): """ If floating is ``True``, the legend can be dragged with the mouse. Otherwise, it's fixed in its position. If ``pos`` is specified, the legend is moved there. """ if floating == self._floating: return self._floating = floating if pos: if floating: self.set_pos_animated(pos - self._mouse_down_pos) else: self.set_pos_animated(pos)
def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert (self.pos == pos) self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001)) # move a little # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage. # We seem to get better results if we do the following: # 1) Slightly offset the source window because apparently there is a small shift in the data # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x) # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image, # applying some threshold to determine if the final pixel is on or off. tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) # Offset the source window. At first I thought the right offset was 0.5, because # that would seem to make sure points are rounded to pixel CENTERS, but # experimentation indicates that 0.25 is slightly better for some reason... source_rect = QRectF(QPointF(self.bb.x() + 0.25, self.bb.y() + 0.25), QSizeF(self.bb.width(), self.bb.height())) target_rect = QRectF(QPointF(0, 0), QSizeF(4 * self.bb.width(), 4 * self.bb.height())) self.scene.render(painter, target=target_rect, source=source_rect) painter.end() # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int) ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) + (4, )) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) + (4, )) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr //= 4 * 4 downsample_threshold = (7. / 16) * 255 labels = numpy.where(ndarr >= downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0, 1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero( labels) == 0: labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)
def onPlotButton(self): """ Batch plots selected geometry items using the selected template and scale. """ # check if one layer is selected if self.ui.LayersComboBox.currentIndex() == -1: QMessageBox.warning(self, tr("Warning"), tr("Select a layer!")) self.ui.LayersComboBox.setFocus() return # check if one composition template is selected if self.ui.TemplateList.selectedItems() == []: QMessageBox.warning(self, tr("Warning"), tr("Select a composer template!")) self.ui.TemplateList.setFocus() return template_filename = QDir(self.templatepath).absoluteFilePath( self.ui.TemplateList.currentItem().text()) # get the scale if self.ui.ScaleCombo.currentText() == "<extent>": scale = -1 else: try: scale = int(self.ui.ScaleCombo.currentText()) except (ValueError): QMessageBox.warning( self, tr("Warning"), tr("Scale must be a positive integer value!")) self.ui.ScaleCombo.setFocus() return if scale <= 0: QMessageBox.warning( self, tr("Warning"), tr("Scale must be a positive integer value!")) self.ui.ScaleCombo.setFocus() return # get composer name composer_name = self.ui.ComposerEdit.text() #check if there are selected items on polygon layers if self.batch_plotting: selected_layer = self.ui.LayersComboBox.itemData( self.ui.LayersComboBox.currentIndex()) selected_polygons = get_features(selected_layer.name(), QGis.Polygon, True) if selected_polygons is None: QMessageBox.warning( self, tr("Warning"), tr("Select at least one polygon on layer '%s'!" % selected_layer.name())) return # check output setting if self.ui.OutputTab.currentIndex() == 0: # to PDF if not self.ui.SingleFileCheckbox.checkState(): if len(self.ui.OutputPDFEdit.text()) == 0: res = QMessageBox.warning( self, tr("Warning"), tr("The filename pattern is empty. A default one will be used." ), QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok) if res == QMessageBox.Cancel: return self.ui.OutputPDFEdit.setText( QgsAtlasComposition(None).filenamePattern()) elif self.ui.OutputTab.currentIndex() == 1: # to Printer # no need for checking pass elif self.ui.OutputTab.currentIndex() == 2: # to Composer View # no need for checking yet pass # get map renderer of map canvas renderer = self.iface.mapCanvas().mapRenderer() self.composition = QgsComposition(renderer) # if plot to Composer View the composition must be set # before loading the template # otherwise composer's item properties doesn't appear if self.ui.OutputTab.currentIndex() == 2: # to Composer View if len(composer_name) == 0: composer = self.iface.createNewComposer() else: composer = self.iface.createNewComposer(composer_name) composer.setComposition(self.composition) # read template file and add to composition template_file = QFile(template_filename) template_file.open(QIODevice.ReadOnly | QIODevice.Text) template_content = template_file.readAll() template_file.close() document = QDomDocument() document.setContent(template_content) self.composition.loadFromTemplate(document) # if batch_plotting is True create an atlas composition if self.batch_plotting: # get composer map item and set new scale and the grid cmap = self.composition.getComposerMapById(0) cmap.setNewScale(scale) cmap.setGridIntervalX(scale / 10) cmap.setGridIntervalY(scale / 10) cmap.setAtlasDriven(True) cmap.setAtlasScalingMode(QgsComposerMap.Fixed) # set atlas composition parameters atlas = self.composition.atlasComposition() atlas.setEnabled(True) atlas.setCoverageLayer(selected_layer) atlas.setHideCoverage(False) atlas.setFilenamePattern(self.ui.OutputPDFEdit.text()) atlas.setSingleFile(self.ui.SingleFileCheckbox.checkState()) atlas.setSortFeatures(False) atlas.setFilterFeatures(True) selected_ids = [f.id() for f in selected_layer.selectedFeatures()] filter_id_string = ','.join([str(sid) for sid in selected_ids]) atlas.setFeatureFilter("$id in (" + filter_id_string + ")") # print the complete atlas composition if self.ui.OutputTab.currentIndex() == 0: # to PDF self.composition.setAtlasMode(QgsComposition.ExportAtlas) if self.pdfpath == "": self.pdfpath = QgsProject.instance().homePath().encode( sys.getfilesystemencoding()) if self.ui.SingleFileCheckbox.checkState(): #print to single pdf (multi-page) outputFileName = QDir( self.pdfpath).absoluteFilePath("qgis.pdf") outputFileName = QFileDialog.getSaveFileName( self, tr("Choose a file name to save the map as"), outputFileName, tr("PDF Format") + " (*.pdf *.PDF)") if not outputFileName: return if not outputFileName.lower().endswith(".pdf"): outputFileName += ".pdf" self.pdfpath = QDir(outputFileName).absolutePath() else: #print to more pdf outputDir = QFileDialog.getExistingDirectory( self, tr("Directory where to save PDF files"), self.pdfpath, QFileDialog.ShowDirsOnly) if not outputDir: return # test directory (if it exists and is writable) if not QDir(outputDir).exists() or not QFileInfo( outputDir).isWritable(): QMessageBox.warning( self, tr("Unable to write into the directory"), tr("The given output directory is not writable. Cancelling." )) return self.pdfpath = outputDir printer = QPrinter() painter = QPainter() if not len(atlas.featureFilterErrorString()) == 0: QMessageBox.warning( self, tr("Atlas processing error"), tr("Feature filter parser error: %s" % atlas.featureFilterErrorString())) return atlas.beginRender() if self.ui.SingleFileCheckbox.checkState(): #prepare for first feature, so that we know paper size to begin with atlas.prepareForFeature(0) self.composition.beginPrintAsPDF(printer, outputFileName) # set the correct resolution self.composition.beginPrint(printer) printReady = painter.begin(printer) if not printReady: QMessageBox.warning( self, tr("Atlas processing error"), tr("Error creating %s." % outputFileName)) return progress = QProgressDialog(tr("Rendering maps..."), tr("Abort"), 0, atlas.numFeatures(), self) QApplication.setOverrideCursor(Qt.BusyCursor) for featureI in range(0, atlas.numFeatures()): progress.setValue(featureI + 1) # process input events in order to allow aborting QCoreApplication.processEvents() if progress.wasCanceled(): atlas.endRender() break if not atlas.prepareForFeature(featureI): QMessageBox.warning(self, tr("Atlas processing error"), tr("Atlas processing error")) progress.cancel() QApplication.restoreOverrideCursor() return if not self.ui.SingleFileCheckbox.checkState(): multiFilePrinter = QPrinter() outputFileName = QDir(outputDir).filePath( atlas.currentFilename()) + ".pdf" self.composition.beginPrintAsPDF( multiFilePrinter, outputFileName) # set the correct resolution self.composition.beginPrint(multiFilePrinter) printReady = painter.begin(multiFilePrinter) if not printReady: QMessageBox.warning( self, tr("Atlas processing error"), tr("Error creating %s." % outputFileName)) progress.cancel() QApplication.restoreOverrideCursor() return self.composition.doPrint(multiFilePrinter, painter) painter.end() else: # start print on a new page if we're not on the first feature if featureI > 0: printer.newPage() self.composition.doPrint(printer, painter) atlas.endRender() if self.ui.SingleFileCheckbox.checkState(): painter.end() QApplication.restoreOverrideCursor() elif self.ui.OutputTab.currentIndex() == 1: # to Printer # if To Printer is selected set the printer # setting up printer if self.printer is None: self.printer = QPrinter() self.printer.setFullPage(True) self.printer.setColorMode(QPrinter.Color) # open printer setting dialog pdlg = QPrintDialog(self.printer, self) pdlg.setModal(True) pdlg.setOptions(QAbstractPrintDialog.None) if not pdlg.exec_() == QDialog.Accepted: return QApplication.setOverrideCursor(Qt.BusyCursor) #prepare for first feature, so that we know paper size to begin with self.composition.setAtlasMode(QgsComposition.ExportAtlas) atlas.prepareForFeature(0) # set orientation if self.composition.paperWidth( ) > self.composition.paperHeight(): self.printer.setOrientation(QPrinter.Landscape) self.printer.setPaperSize( QSizeF(self.composition.paperHeight(), self.composition.paperWidth()), QPrinter.Millimeter) else: self.printer.setOrientation(QPrinter.Portrait) self.printer.setPaperSize( QSizeF(self.composition.paperWidth(), self.composition.paperHeight()), QPrinter.Millimeter) self.printer.setResolution(self.composition.printResolution()) self.composition.beginPrint(self.printer) painter = QPainter(self.printer) if not len(atlas.featureFilterErrorString()) == 0: QMessageBox.warning( self, tr("Atlas processing error"), tr("Feature filter parser error: %s" % atlas.featureFilterErrorString())) QApplication.restoreOverrideCursor() return atlas.beginRender() progress = QProgressDialog(tr("Rendering maps..."), tr("Abort"), 0, atlas.numFeatures(), self) for featureI in range(0, atlas.numFeatures()): progress.setValue(featureI + 1) # process input events in order to allow cancelling QCoreApplication.processEvents() if progress.wasCanceled(): atlas.endRender() break if not atlas.prepareForFeature(featureI): QMessageBox.warning(self, tr("Atlas processing error"), tr("Atlas processing error")) progress.cancel() QApplication.restoreOverrideCursor() return # start print on a new page if we're not on the first feature if featureI > 0: self.printer.newPage() self.composition.doPrint(self.printer, painter) atlas.endRender() painter.end() QApplication.restoreOverrideCursor() elif self.ui.OutputTab.currentIndex() == 2: # to Composer View # create new composer self.composition.setAtlasMode(QgsComposition.PreviewAtlas) composer.composerWindow().on_mActionAtlasPreview_triggered( True) atlas.parameterChanged.emit() # Increase the reference count of the composer object # for not being garbage collected. # If not doing this composer would lost reference and qgis would crash # when referring to this composer object or at quit. ctypes.c_long.from_address(id(composer)).value += 1 else: # if batch_plotting is False open a QgsComposerView with current map canvas cmap = self.composition.getComposerMapById(0) # set the new extent of composer map item newextent = self.iface.mapCanvas().mapRenderer().extent() currentextent = cmap.extent() canvas_ratio = newextent.width() / newextent.height() map_ratio = currentextent.width() / currentextent.height() if map_ratio < canvas_ratio: dh = newextent.width() / map_ratio - newextent.height() newextent.setYMinimum(newextent.yMinimum() - dh / 2) newextent.setYMaximum(newextent.yMaximum() + dh / 2) else: dw = map_ratio * newextent.height() - newextent.width() newextent.setXMinimum(newextent.xMinimum() - dw / 2) newextent.setXMaximum(newextent.xMaximum() + dw / 2) cmap.setNewExtent(newextent) # set the new scale of composer map item if scale > 0: cmap.setNewScale(scale) sc = cmap.scale() # set the grid interval according to the scale cmap.setGridIntervalX(sc / 10) cmap.setGridIntervalY(sc / 10) # Increase the reference count of the composer object # for not being garbage collected. # If not doing this composer would lost reference and qgis would crash # when referring to this composer object or at quit. ctypes.c_long.from_address(id(composer)).value += 1 self.accept()
class GraphicsThumbnailWidget(QGraphicsWidget): def __init__(self, pixmap, title="", parent=None): QGraphicsWidget.__init__(self, parent) self._title = None self._size = QSizeF() layout = QGraphicsLinearLayout(Qt.Vertical, self) layout.setSpacing(2) layout.setContentsMargins(5, 5, 5, 5) self.setContentsMargins(0, 0, 0, 0) self.pixmapWidget = GraphicsPixmapWidget(pixmap, self) self.labelWidget = GraphicsTextWidget(title, self) layout.addItem(self.pixmapWidget) layout.addItem(self.labelWidget) layout.setAlignment(self.pixmapWidget, Qt.AlignCenter) layout.setAlignment(self.labelWidget, Qt.AlignHCenter | Qt.AlignBottom) self.setLayout(layout) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setTitle(title) self.setTitleWidth(100) def setPixmap(self, pixmap): self.pixmapWidget.setPixmap(pixmap) self._updatePixmapSize() def pixmap(self): return self.pixmapWidget.pixmap() def setTitle(self, title): if self._title != title: self._title = title self.labelWidget.setHtml( '<center>' + escape(title) + '</center>' ) self.layout().invalidate() def title(self): return self._title def setThumbnailSize(self, size): if self._size != size: self._size = QSizeF(size) self._updatePixmapSize() self.labelWidget.setTextWidth(max(100, size.width())) def setTitleWidth(self, width): self.labelWidget.setTextWidth(width) self.layout().invalidate() def paint(self, painter, option, widget=0): contents = self.contentsRect() if self.isSelected(): painter.save() painter.setPen(QPen(QColor(125, 162, 206, 192))) painter.setBrush(QBrush(QColor(217, 232, 252, 192))) painter.drawRoundedRect(QRectF(contents.topLeft(), self.geometry().size()), 3, 3) painter.restore() def _updatePixmapSize(self): pixmap = self.pixmap() if not pixmap.isNull() and self._size.isValid(): pixsize = QSizeF(self.pixmap().size()) pixsize.scale(self._size, Qt.KeepAspectRatio) else: pixsize = QSizeF() self.pixmapWidget.setPixmapSize(pixsize)
def rect(self): return QRectF(self.pos(), QSizeF(*self.size()))
def setThumbnailSize(self, size): if self._size != size: self._size = QSizeF(size) self._updatePixmapSize() self.labelWidget.setTextWidth(max(100, size.width()))
def sizeHint(self, which, constraint=QSizeF()): if which == Qt.MinimumSize: return self.labelItem.boundingRect().size() else: return self.labelItem.boundingRect().size()
def __init__(self, pixmap, parent=None): QGraphicsWidget.__init__(self, parent) self.setCacheMode(QGraphicsItem.ItemCoordinateCache) self._pixmap = pixmap self._pixmapSize = QSizeF() self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
class GraphicsThumbnailWidget(QGraphicsWidget): def __init__(self, pixmap, title="", parent=None): QGraphicsWidget.__init__(self, parent) self._title = None self._size = QSizeF() layout = QGraphicsLinearLayout(Qt.Vertical, self) layout.setSpacing(2) layout.setContentsMargins(5, 5, 5, 5) self.setContentsMargins(0, 0, 0, 0) self.pixmapWidget = GraphicsPixmapWidget(pixmap, self) self.labelWidget = GraphicsTextWidget(title, self) layout.addItem(self.pixmapWidget) layout.addItem(self.labelWidget) layout.setAlignment(self.pixmapWidget, Qt.AlignCenter) layout.setAlignment(self.labelWidget, Qt.AlignHCenter | Qt.AlignBottom) self.setLayout(layout) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setTitle(title) self.setTitleWidth(100) def setPixmap(self, pixmap): self.pixmapWidget.setPixmap(pixmap) self._updatePixmapSize() def pixmap(self): return self.pixmapWidget.pixmap() def setTitle(self, title): if self._title != title: self._title = title self.labelWidget.setHtml('<center>' + escape(title) + '</center>') self.layout().invalidate() def title(self): return self._title def setThumbnailSize(self, size): if self._size != size: self._size = QSizeF(size) self._updatePixmapSize() self.labelWidget.setTextWidth(max(100, size.width())) def setTitleWidth(self, width): self.labelWidget.setTextWidth(width) self.layout().invalidate() def paint(self, painter, option, widget=0): contents = self.contentsRect() if self.isSelected(): painter.save() painter.setPen(QPen(QColor(125, 162, 206, 192))) painter.setBrush(QBrush(QColor(217, 232, 252, 192))) painter.drawRoundedRect( QRectF(contents.topLeft(), self.geometry().size()), 3, 3) painter.restore() def _updatePixmapSize(self): pixmap = self.pixmap() if not pixmap.isNull() and self._size.isValid(): pixsize = QSizeF(self.pixmap().size()) pixsize.scale(self._size, Qt.KeepAspectRatio) else: pixsize = QSizeF() self.pixmapWidget.setPixmapSize(pixsize)
c.setPlotStyle(QgsComposition.Print) compmap.setPreviewMode(QgsComposerMap.Render) #compmap.updateItem() #emit compmap.itemChanged(); #compmap.extentChanged(); #compmap.toggleAtlasPreview() #compmap.setNewScale(compmap.scale()+1) #c.setPrintResolution(150) #print c.printResolution() c.setPrintAsRaster(False) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOutputFileName(pdf_out) printer.setPaperSize(QSizeF(c.paperWidth(), c.paperHeight()), QPrinter.Millimeter) printer.setFullPage(True) printer.setColorMode(QPrinter.Color) printer.setResolution(c.printResolution()) pdfPainter = QPainter(printer) paperRectMM = printer.pageRect(QPrinter.Millimeter) paperRectPixel = printer.pageRect(QPrinter.DevicePixel) QgsPaintEngineHack.fixEngineFlags(printer.paintEngine()) #c.renderPage(pdfPainter, 0) c.doPrint(printer, pdfPainter) pdfPainter.end()