def layout_item(layout, item_id, item_class): """Fetch a specific item according to its type in a layout. There's some sip casting conversion issues with QgsLayout::itemById. Don't use it, and use this function instead. See https://github.com/inasafe/inasafe/issues/4271 :param layout: The layout to look in. :type layout: QgsLayout :param item_id: The ID of the item to look for. :type item_id: basestring :param item_class: The expected class name. :type item_class: cls :return: The layout item, inherited class of QgsLayoutItem. """ item = layout.itemById(item_id) if item is None: # no match! return item if issubclass(item_class, QgsLayoutMultiFrame): # finding a multiframe by frame id frame = sip.cast(item, QgsLayoutFrame) multi_frame = frame.multiFrame() return sip.cast(multi_frame, item_class) else: # force sip to correctly cast item to required type return sip.cast(item, item_class)
def gradient_darker(grad, factor): """Return a copy of the QGradient darkened by factor. .. note:: Only QLinearGradeint and QRadialGradient are supported. """ if type(grad) is QGradient: if grad.type() == QGradient.LinearGradient: grad = sip.cast(grad, QLinearGradient) elif grad.type() == QGradient.RadialGradient: grad = sip.cast(grad, QRadialGradient) if isinstance(grad, QLinearGradient): new_grad = QLinearGradient(grad.start(), grad.finalStop()) elif isinstance(grad, QRadialGradient): new_grad = QRadialGradient(grad.center(), grad.radius(), grad.focalPoint()) else: raise TypeError new_grad.setCoordinateMode(grad.coordinateMode()) for pos, color in grad.stops(): new_grad.setColorAt(pos, color.darker(factor)) return new_grad
def gradient_darker(grad, factor): # type: (QGradient, float) -> QGradient """Return a copy of the QGradient darkened by factor. .. note:: Only QLinearGradeint and QRadialGradient are supported. """ if type(grad) is QGradient: if grad.type() == QGradient.LinearGradient: grad = sip.cast(grad, QLinearGradient) elif grad.type() == QGradient.RadialGradient: grad = sip.cast(grad, QRadialGradient) if isinstance(grad, QLinearGradient): new_grad = QLinearGradient(grad.start(), grad.finalStop()) elif isinstance(grad, QRadialGradient): new_grad = QRadialGradient(grad.center(), grad.radius(), grad.focalPoint()) else: raise TypeError new_grad.setCoordinateMode(grad.coordinateMode()) for pos, color in grad.stops(): new_grad.setColorAt(pos, color.darker(factor)) return new_grad
def QGraphicsItem_itemChange(self, change, value): if change in changeset: if isinstance(value, QGraphicsItem): value = sip.cast(value, QGraphicsItem) rval = QGraphicsItem_itemChange_old(self, change, value) if isinstance(rval, QGraphicsItem): rval = sip.cast(rval, QGraphicsItem) return rval else: return QGraphicsItem_itemChange_old(self, change, value)
def extension(self, extension, option, output): """ Public method to implement a specific extension. @param extension extension to be executed (QWebPage.Extension) @param option provides input to the extension (QWebPage.ExtensionOption) @param output stores the output results (QWebPage.ExtensionReturn) @return flag indicating a successful call of the extension (boolean) """ try: if extension == QWebPage.ErrorPageExtension: info = sip.cast(option, QWebPage.ErrorPageExtensionOption) if info.domain == QWebPage.QtNetwork and \ info.error == QNetworkReply.OperationCanceledError and \ info.errorString == "eric4:No Error": return False if info.domain == QWebPage.WebKit and info.error == 203: # "Loading is handled by the media engine" return False errorPage = sip.cast(output, QWebPage.ErrorPageExtensionReturn) html = QString(notFoundPage_html) urlString = QString.fromUtf8(info.url.toEncoded()) title = self.trUtf8("Error loading page: %1").arg(urlString) pixmap = qApp.style()\ .standardIcon(QStyle.SP_MessageBoxWarning, None, self.parent())\ .pixmap(32, 32) imageBuffer = QBuffer() imageBuffer.open(QIODevice.ReadWrite) if pixmap.save(imageBuffer, "PNG"): html = html.replace("IMAGE_BINARY_DATA_HERE", QString(imageBuffer.buffer().toBase64())) errorPage.content = html.arg( title, info.errorString, self.trUtf8("When connecting to: %1.").arg(urlString), self.trUtf8("Check the address for errors such as " "<b>ww</b>.example.org instead of " "<b>www</b>.example.org"), self.trUtf8("If the address is correct, try checking the network " "connection."), self.trUtf8("If your computer or network is protected by a firewall " "or proxy, make sure that the browser is permitted to " "access the network.") ).toUtf8() return True except AttributeError: pass return QWebPage.extension(self, extension, option, output)
def testCopyPaste(self): p = QgsProject() l = QgsLayout(p) # clear clipboard mime_data = QMimeData() mime_data.setData("text/xml", QByteArray()) clipboard = QApplication.clipboard() clipboard.setMimeData(mime_data) # add an item item1 = QgsLayoutItemLabel(l) item1.setText('label 1') l.addLayoutItem(item1) item1.setSelected(True) item2 = QgsLayoutItemLabel(l) item2.setText('label 2') l.addLayoutItem(item2) item2.setSelected(True) view = QgsLayoutView() view.setCurrentLayout(l) self.assertFalse(view.hasItemsInClipboard()) view.copySelectedItems(QgsLayoutView.ClipboardCopy) self.assertTrue(view.hasItemsInClipboard()) pasted = view.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 2) self.assertIn(pasted[0], l.items()) self.assertIn(pasted[1], l.items()) self.assertIn( sip.cast(pasted[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) self.assertIn( sip.cast(pasted[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) # copy specific item view.copyItems([item2], QgsLayoutView.ClipboardCopy) l2 = QgsLayout(p) view2 = QgsLayoutView() view2.setCurrentLayout(l2) pasted = view2.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 1) self.assertIn(pasted[0], l2.items()) self.assertEqual( sip.cast(pasted[0], QgsLayoutItemLabel).text(), 'label 2')
def __init__(self, _model, parent): """ Connect to all of the models signals, Whenever anything happens recheck everything. """ QtCore.QObject.__init__(self,parent) self._model = _model self.model = sip.cast(_model, QtCore.QAbstractItemModel) self.insert = [] self.remove = [] self.fetchingMore = False assert(self.model) self.connect( self.model, QtCore.SIGNAL("columnsAboutToBeInserted(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("columnsAboutToBeRemoved(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("columnsBeInserted(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("columnsRemoved(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("headerDataChanged(Qt::Orientation, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("layoutAboutToBeChanged()"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("layoutChanged()"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("modelReset()"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("rowsAboutToBeInserted(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("rowsAboutToBeRemoved(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("rowsBeInserted(const QModelIndex&, int, int)"), self.runAllTests) self.connect( self.model, QtCore.SIGNAL("rowsRemoved(const QModelIndex&, int, int)"), self.runAllTests) # Special checks for inserting/removing self.connect( self.model, QtCore.SIGNAL("rowsAboutToBeInserted(const QModelIndex&, int, int)"), self.rowsAboutToBeInserted) self.connect( self.model, QtCore.SIGNAL("rowsAboutToBeRemoved(const QModelIndex&, int, int)"), self.rowsAboutToBeRemoved) self.connect( self.model, QtCore.SIGNAL("rowsBeInserted(const QModelIndex&, int, int)"), self.rowsInserted) self.connect( self.model, QtCore.SIGNAL("rowsRemoved(const QModelIndex&, int, int)"), self.rowsRemoved) self.runAllTests()
def supercast(obj): """ cast a QObject subclass to the best known wrapped super class """ if not qtclasses: # To get really all Qt classes I would have to # import QtNetwork, QtXml, QtSvg and QtScript, too. import PyQt4 qtclasses.update( dict([(key, value) \ for key, value in PyQt4.QtCore.__dict__.items() + PyQt4.QtGui.__dict__.items() \ if hasattr(value, "__subclasses__") and issubclass(value, QObject)]) ) try: if not issubclass(value, QObject): return obj except TypeError: # no class - no cast... return obj mo = obj.metaObject() while mo: cls = qtclasses.get(str(mo.className())) if cls: return sip.cast(obj, cls) mo = mo.superClass() # This should never be reached return obj
def __init__(self, _model, verbose=True, parent=None): """ Connect to all of the models signals, Whenever anything happens recheck everything. """ QtCore.QObject.__init__(self,parent) self._model = _model self.model = sip.cast(_model, QtCore.QAbstractItemModel) self.insert = [] self.remove = [] self.fetchingMore = False self._verbose = verbose assert(self.model) self.model.columnsAboutToBeInserted.connect(self.runAllTests) self.model.columnsAboutToBeRemoved.connect(self.runAllTests) self.model.columnsInserted.connect(self.runAllTests) self.model.columnsRemoved.connect(self.runAllTests) self.model.dataChanged.connect(self.runAllTests) self.model.headerDataChanged.connect(self.runAllTests) self.model.layoutAboutToBeChanged.connect(self.runAllTests) self.model.layoutChanged.connect(self.runAllTests) self.model.modelReset.connect(self.runAllTests) self.model.rowsAboutToBeInserted.connect(self.runAllTests) self.model.rowsAboutToBeRemoved.connect(self.runAllTests) self.model.rowsInserted.connect(self.runAllTests) self.model.rowsRemoved.connect(self.runAllTests) # Special checks for inserting/removing self.model.rowsAboutToBeInserted.connect(self.rowsAboutToBeInserted) self.model.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved) self.model.rowsInserted.connect(self.rowsInserted) self.model.rowsRemoved.connect(self.rowsRemoved) self.runAllTests()
def __init__(self, _model, verbose=True, parent=None): """ Connect to all of the models signals, Whenever anything happens recheck everything. """ super().__init__(parent) self._model = _model self.model = sip.cast(_model, QtCore.QAbstractItemModel) self.insert = [] self.remove = [] self.fetchingMore = False self._verbose = verbose assert self.model self.model.columnsAboutToBeInserted.connect(self.run_all_tests) self.model.columnsAboutToBeRemoved.connect(self.run_all_tests) self.model.columnsInserted.connect(self.run_all_tests) self.model.columnsRemoved.connect(self.run_all_tests) self.model.dataChanged.connect(self.run_all_tests) self.model.headerDataChanged.connect(self.run_all_tests) self.model.layoutAboutToBeChanged.connect(self.run_all_tests) self.model.layoutChanged.connect(self.run_all_tests) self.model.modelReset.connect(self.run_all_tests) self.model.rowsAboutToBeInserted.connect(self.run_all_tests) self.model.rowsAboutToBeRemoved.connect(self.run_all_tests) self.model.rowsInserted.connect(self.run_all_tests) self.model.rowsRemoved.connect(self.run_all_tests) # Special checks for inserting/removing self.model.rowsAboutToBeInserted.connect(self.rowsAboutToBeInserted) self.model.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved) self.model.rowsInserted.connect(self.rowsInserted) self.model.rowsRemoved.connect(self.rowsRemoved) self.run_all_tests()
def __init__(self, _model, parent): """ Connect to all of the models signals, Whenever anything happens recheck everything. """ QObject.__init__(self, parent) self._model = _model self.model = sip.cast(_model, QAbstractItemModel) self.insert = [] self.remove = [] self.changing = [] self.fetchingMore = False assert(self.model) self.model.columnsAboutToBeInserted.connect(self.runAllTests) self.model.columnsAboutToBeRemoved.connect(self.runAllTests) self.model.columnsInserted.connect(self.runAllTests) self.model.columnsRemoved.connect(self.runAllTests) self.model.dataChanged.connect(self.runAllTests) self.model.headerDataChanged.connect(self.runAllTests) self.model.layoutAboutToBeChanged.connect(self.runAllTests) self.model.layoutChanged.connect(self.runAllTests) self.model.modelReset.connect(self.runAllTests) self.model.rowsAboutToBeInserted.connect(self.runAllTests) self.model.rowsAboutToBeRemoved.connect(self.runAllTests) self.model.rowsInserted.connect(self.runAllTests) self.model.rowsRemoved.connect(self.runAllTests) # Special checks for inserting/removing self.model.layoutAboutToBeChanged.connect(self.layoutAboutToBeChanged) self.model.layoutChanged.connect(self.layoutChanged) self.model.rowsAboutToBeInserted.connect(self.rowsAboutToBeInserted) self.model.rowsAboutToBeRemoved.connect(self.rowsAboutToBeRemoved) self.model.rowsInserted.connect(self.rowsInserted) self.model.rowsRemoved.connect(self.rowsRemoved) self.runAllTests()
def itemChange(self, change, value): if change == QtGui.QGraphicsItem.ItemPositionChange and self.scene(): # If Left mouse + alt is pressed then don't snap button = QtGui.QApplication.mouseButtons() == QtCore.Qt.LeftButton modifier = QtGui.QApplication.keyboardModifiers() == QtCore.Qt.AltModifier if button and modifier: self.position_changed.emit(value) return super(CoordinateSnapMixin, self).itemChange(change, value) # Get all items under the mouse # TODO: Use try instead of isinstance # TODO: Add priority # TODO: Use childItems items = [x for x in self.scene().items(value) if isinstance(x, SnapsCoordinates) and x.parentItem() is not self] for item in items: value = item.snap_coordinate(value) self.position_changed.emit(value) # itemChange and setParentItem causes error in PyQt4 # TODO: Test with PySide and PyQt5 # See http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html result = super(CoordinateSnapMixin, self).itemChange(change, value) if isinstance(result, QtGui.QGraphicsItem): result = sip.cast(result, QtGui.QGraphicsItem) return result
def registerObject(cls, obj): """ Workaround for PyQt bug in qgraphicsscene.items() All subclasses of QGraphicsObject must register themselves with this function. (otherwise, mouse interaction with those objects will likely fail) """ if HAVE_SIP and isinstance(obj, sip.wrapper): cls._addressCache[sip.unwrapinstance(sip.cast(obj, QtGui.QGraphicsItem))] = obj
def getLayoutItem(self, itemId, itemType): item = self.atlasLayout.itemById(itemId) if item is None: #print(u'Layout does not contain item: \'{0}\''.format(itemId)) return None if not type(item) == u'qgis._core.{0}'.format(itemType.__name__): item = sip.cast(item, itemType) return item
def __init__(self, _model, parent): """ Connect to all of the models signals, Whenever anything happens recheck everything. """ QtCore.QObject.__init__(self, parent) self._model = _model # QAbstractItemModel gives us a simple table of rows and columns. Each item in it (cell) # has a unique index via QtCore.QModelIndex with row, colum # for example: # 0 1 2 # 0 . , , # 1 . . X <-- this X is at row:1, column:2 # 2 . . . # # Any data associated with X can be retrieved via the data() function # passing it the 'role' that the data plays. The data is set via setData(). # self.model = sip.cast(_model, QtCore.QAbstractItemModel) self.insert = [] self.remove = [] self.fetchingMore = False assert (self.model) self.model.columnsAboutToBeInserted[QtCore.QModelIndex, int, int].connect(self.runAllTests) self.model.columnsAboutToBeRemoved[QtCore.QModelIndex, int, int].connect(self.runAllTests) self.model.columnsInserted[QtCore.QModelIndex, int, int].connect(self.runAllTests) self.model.columnsRemoved[QtCore.QModelIndex, int, int].connect(self.runAllTests) # self.model.dataChanged[QtCore.QModelIndex, QtCore.QModelIndex].connect(self.runAllTests) self.model.headerDataChanged[QtCore.Qt.Orientation, int, int].connect(self.runAllTests) self.model.layoutAboutToBeChanged.connect(self.runAllTests) self.model.layoutChanged.connect(self.runAllTests) self.model.modelReset.connect(self.runAllTests) self.model.rowsAboutToBeInserted[QtCore.QModelIndex, int, int].connect(self.runAllTests) self.model.rowsAboutToBeRemoved[QtCore.QModelIndex, int, int].connect(self.runAllTests) self.model.rowsInserted[QtCore.QModelIndex, int, int].connect(self.runAllTests) self.model.rowsRemoved[QtCore.QModelIndex, int, int].connect(self.runAllTests) # Special checks for inserting/removing self.model.rowsAboutToBeInserted[QtCore.QModelIndex, int, int].connect( self.rowsAboutToBeInserted) self.model.rowsAboutToBeRemoved[QtCore.QModelIndex, int, int].connect(self.rowsAboutToBeRemoved) self.model.rowsInserted[QtCore.QModelIndex, int, int].connect(self.rowsInserted) self.model.rowsRemoved[QtCore.QModelIndex, int, int].connect(self.rowsRemoved) self.runAllTests()
def styleSheetChanged(self): widget = self.sender() form = QDesignerFormWindowInterface.findFormWindow(widget) if form: sheet = form.core().extensionManager().extension( widget, Q_TYPEID['QDesignerPropertySheetExtension']) sheet = sip.cast(sheet, QPyDesignerPropertySheetExtension) index = sheet.indexOf('styleSheet') sheet.setChanged(index, True)
def __init__(self, brush, matrix, pdf, pixel_page_width, pixel_page_height): self.matrix = (matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), matrix.dx(), matrix.dy()) gradient = sip.cast(brush.gradient(), QLinearGradient) start, stop, stops = self.spread_gradient(gradient, pixel_page_width, pixel_page_height, matrix) # TODO: Handle colors with different opacities self.const_opacity = stops[0].color[-1] funcs = Array() bounds = Array() encode = Array() for i, current_stop in enumerate(stops): if i < len(stops) - 1: next_stop = stops[i+1] func = Dictionary({ 'FunctionType': 2, 'Domain': Array([0, 1]), 'C0': Array(current_stop.color[:3]), 'C1': Array(next_stop.color[:3]), 'N': 1, }) funcs.append(func) encode.extend((0, 1)) if i+1 < len(stops) - 1: bounds.append(next_stop.t) func = Dictionary({ 'FunctionType': 3, 'Domain': Array([stops[0].t, stops[-1].t]), 'Functions': funcs, 'Bounds': bounds, 'Encode': encode, }) shader = Dictionary({ 'ShadingType': 2, 'ColorSpace': Name('DeviceRGB'), 'AntiAlias': True, 'Coords': Array([start.x(), start.y(), stop.x(), stop.y()]), 'Function': func, 'Extend': Array([True, True]), }) Dictionary.__init__(self, { 'Type': Name('Pattern'), 'PatternType': 2, 'Shading': shader, 'Matrix': Array(self.matrix), }) self.cache_key = (self.__class__.__name__, self.matrix, tuple(shader['Coords']), stops)
def testCopyPaste(self): p = QgsProject() l = QgsLayout(p) # clear clipboard mime_data = QMimeData() mime_data.setData("text/xml", QByteArray()) clipboard = QApplication.clipboard() clipboard.setMimeData(mime_data) # add an item item1 = QgsLayoutItemLabel(l) item1.setText('label 1') l.addLayoutItem(item1) item1.setSelected(True) item2 = QgsLayoutItemLabel(l) item2.setText('label 2') l.addLayoutItem(item2) item2.setSelected(True) view = QgsLayoutView() view.setCurrentLayout(l) self.assertFalse(view.hasItemsInClipboard()) view.copySelectedItems(QgsLayoutView.ClipboardCopy) self.assertTrue(view.hasItemsInClipboard()) pasted = view.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 2) self.assertIn(pasted[0], l.items()) self.assertIn(pasted[1], l.items()) self.assertIn(sip.cast(pasted[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) self.assertIn(sip.cast(pasted[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) # copy specific item view.copyItems([item2], QgsLayoutView.ClipboardCopy) l2 = QgsLayout(p) view2 = QgsLayoutView() view2.setCurrentLayout(l2) pasted = view2.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 1) self.assertIn(pasted[0], l2.items()) self.assertEqual(sip.cast(pasted[0], QgsLayoutItemLabel).text(), 'label 2')
def _gpsfound(self, gpsConnection): if not isinstance(gpsConnection, QgsNmeaConnection): # This can be hit if the scan is used as the bindings in QGIS aren't # right and will not have the type set correctly import sip gpsConnection = sip.cast(gpsConnection, QgsGpsConnection) self.gpsConn = gpsConnection self.gpsConn.stateChanged.connect(self.gpsStateChanged) self.gpsConn.nmeaSentenceReceived.connect(self.parse_data) self.isConnected = True
def itemChange(self, change, value): ret = GraphicsObject.itemChange(self, change, value) ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html if change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) if change == self.ItemScenePositionHasChanged: self.setNewBounds() return ret
def itemChange(self, change, value): if change == QtGui.QGraphicsItem.ItemPositionHasChanged and self.scene(): self.parentItem().update() # itemChange and setParentItem causes error in PyQt4 # TODO: Test with PySide and PyQt5 # See http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html result = super(SegmentEndPointSceneItem, self).itemChange(change, value) if isinstance(result, QtGui.QGraphicsItem): result = sip.cast(result, QtGui.QGraphicsItem) return result
def createModel(self, nrows, ncols): dm = QicsDataModelDefault(nrows, ncols) # We need to access QicsDataModel.setItem(). d = sip.cast(dm, QicsDataModel) for i in range(nrows): for j in range(ncols): d.setItem(i, j, i + j) return dm
def itemChange(self, change, value): ret = GraphicsObject.itemChange(self, change, value) ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html if QT_LIB in ['PyQt4', 'PyQt5'] and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) if change == self.ItemScenePositionHasChanged: self.setNewBounds() return ret
def extension(self, extension, info=None, errorPage=None): if extension == QWebPage.ErrorPageExtension: if self.verbosity >= 2: log.msg("ErrorPageExtension in WebkitWebPage.extension") # catch the error, populate self.errorInfo and return an error page info = sip.cast(info, QWebPage.ErrorPageExtensionOption) domain = 'Unknown' if info.domain == QWebPage.QtNetwork: domain = 'Network' elif info.domain == QWebPage.Http: domain = 'HTTP' elif info.domain == QWebPage.WebKit: domain = 'WebKit' self.error_info = RenderErrorInfo(type=domain, code=int(info.error), text=str(info.errorString), url=str(info.url.toString())) # XXX: this page currently goes nowhere content = u""" <html><head><title>Failed loading page</title></head> <body> <h1>Failed loading page ({0.text})</h1> <h2>{0.url}</h2> <p>{0.type} error #{0.code}</p> </body></html>""".format(self.error_info) errorPage = sip.cast(errorPage, QWebPage.ErrorPageExtensionReturn) errorPage.content = QByteArray(content.encode('utf-8')) return True # XXX: this method always returns True, even if we haven't # handled the extension. Is it correct? When can this method be # called with extension which is not ErrorPageExtension if we # are returning False in ``supportsExtension`` for such extensions? if self.verbosity >= 1: log.msg("Unhandled condition in WebkitWebPage.extension") return True
def onViewChanged(self): try: doc = sip.cast(kate.activeDocument(), KateDocument) except kate.api.NoActiveView: return self.act.blockSignals(True) if doc.property('AutoReload'): self.act.setChecked(True) else: self.act.setChecked(False) self.act.blockSignals(False)
def processAlgorithm(self, parameters, context, feedback): layout_name = self.parameterAsString(parameters, self.LAYOUT, context) map_uuid = self.parameterAsString(parameters, self.MAP, context) layout = context.project().layoutManager().layoutByName(layout_name) if layout is None: raise QgsProcessingException( 'Cannot find layout with name "{}"'.format(layout_name)) item = layout.itemByUuid(map_uuid) if item is None: raise QgsProcessingException( 'Cannot find matching map item with uuid "{}"'.format( map_uuid)) map = sip.cast(item, QgsLayoutItemMap) target_crs = self.parameterAsCrs(parameters, self.CRS, context) if not target_crs.isValid(): target_crs = map.crs() fields = QgsFields() fields.append(QgsField('width', QVariant.Double)) fields.append(QgsField('height', QVariant.Double)) fields.append(QgsField('scale', QVariant.Double)) sink, dest = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, target_crs) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) width = map.rect().width() height = map.rect().height() scale = self.parameterAsDouble(parameters, self.SCALE, context) # blindly assume meters for now! feature_width = width / 1000.0 * scale feature_height = height / 1000.0 * scale origin = self.parameterAsPoint(parameters, self.ORIGIN, context) origin_x = origin.x() origin_y = origin.y() feat = QgsFeature(fields) feat.setAttributes([width, height, scale]) feat.setGeometry( QgsGeometry.fromRect( QgsRectangle(origin_x, origin_y - feature_height, origin_x + feature_width, origin_y))) sink.addFeature(feat, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest}
def itemChange(self, change, value): ret = QtGui.QGraphicsObject.itemChange(self, change, value) if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]: self.parentChanged() if self.__inform_view_on_changes and change in [self.ItemPositionHasChanged, self.ItemTransformHasChanged]: self.informViewBoundsChanged() ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html if change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) return ret
def pageTitleChanged(self, title): widget = self.sender() if widget and isinstance(widget, PyMultiPageWidget): page = widget.widget(widget.getCurrentIndex()) form = QDesignerFormWindowInterface.findFormWindow(widget) if form: editor = form.core() manager = editor.extensionManager() sheet = manager.extension(page, Q_TYPEID['QPyDesignerPropertySheetExtension']) # This explicit cast is necessary here sheet = sip.cast(sheet, QPyDesignerPropertySheetExtension) propertyIndex = sheet.indexOf('windowTitle') sheet.setChanged(propertyIndex, True)
def pageTitleChanged(self, title): widget = self.sender() if widget and isinstance(widget, PyMultiPageWidget): page = widget.widget(widget.getCurrentIndex()) form = QtDesigner.QDesignerFormWindowInterface.findFormWindow(widget) if form: editor = form.core() manager = editor.extensionManager() sheet = manager.extension(page, Q_TYPEID["QPyDesignerPropertySheetExtension"]) # This explicit cast is necessary here sheet = sip.cast(sheet, QtDesigner.QPyDesignerPropertySheetExtension) propertyIndex = sheet.indexOf("windowTitle") sheet.setChanged(propertyIndex, True)
def extension(self, extension, info=None, errorPage=None): if extension == QWebPage.ErrorPageExtension: # catch the error, populate self.errorInfo and return an error page info = sip.cast(info, QWebPage.ErrorPageExtensionOption) domain = 'Unknown' if info.domain == QWebPage.QtNetwork: domain = 'Network' elif info.domain == QWebPage.Http: domain = 'HTTP' elif info.domain == QWebPage.WebKit: domain = 'WebKit' self.error_info = RenderErrorInfo( domain, int(info.error), unicode(info.errorString), unicode(info.url.toString()) ) # XXX: this page currently goes nowhere content = u""" <html><head><title>Failed loading page</title></head> <body> <h1>Failed loading page ({0.text})</h1> <h2>{0.url}</h2> <p>{0.type} error #{0.code}</p> </body></html>""".format(self.error_info) errorPage = sip.cast(errorPage, QWebPage.ErrorPageExtensionReturn) errorPage.content = QByteArray(content.encode('utf-8')) return True # XXX: this method always returns True, even if we haven't # handled the extension. Is it correct? When can this method be # called with extension which is not ErrorPageExtension if we # are returning False in ``supportsExtension`` for such extensions? return True
def _handle_errorpage(self, opt, out): """Display an error page if needed. Loosly based on Helpviewer/HelpBrowserWV.py from eric5 (line 260 @ 5d937eb378dd) Args: opt: The QWebPage.ErrorPageExtensionOption instance. out: The QWebPage.ErrorPageExtensionReturn instance to write return values to. Return: False if no error page should be displayed, True otherwise. """ ignored_errors = [ (QWebPage.QtNetwork, QNetworkReply.OperationCanceledError), (QWebPage.WebKit, 203), # "Loading is handled by the media engine" ] info = sip.cast(opt, QWebPage.ErrorPageExtensionOption) errpage = sip.cast(out, QWebPage.ErrorPageExtensionReturn) errpage.baseUrl = info.url urlstr = info.url.toDisplayString() if (info.domain, info.error) in ignored_errors: log.webview.debug("Ignored error on {}: {} (error domain: {}, " "error code: {})".format( urlstr, info.errorString, info.domain, info.error)) return False log.webview.error("Error while loading {}: {}".format( urlstr, info.errorString)) log.webview.debug("Error domain: {}, error code: {}".format( info.domain, info.error)) title = "Error loading page: {}".format(urlstr) template = jinja.env.get_template('error.html') errpage.content = template.render( # pylint: disable=maybe-no-member title=title, url=urlstr, error=info.errorString, icon='') return True
def itemChange(self, change, value): # TODO(chrisbura): Find difference between ItemSelectedHasChanged and ItemSelectedChange if change == QtGui.QGraphicsItem.ItemSelectedHasChanged and value is not None: if value == True: self.on_selected() else: self.on_unselected() # itemChange and setParentItem causes error in PyQt4 # TODO: Test with PySide and PyQt5 # See http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html result = super(SelectableMixin, self).itemChange(change, value) if isinstance(result, QtGui.QGraphicsItem): result = sip.cast(result, QtGui.QGraphicsItem) return result
def _handle_multiple_files(self, opt, files): """Handle uploading of multiple files. Loosly based on Helpviewer/HelpBrowserWV.py from eric5. Args: opt: The ChooseMultipleFilesExtensionOption instance. files: The ChooseMultipleFilesExtensionReturn instance to write return values to. Return: True on success, the superclass return value on failure. """ info = sip.cast(opt, QWebPage.ChooseMultipleFilesExtensionOption) files = sip.cast(files, QWebPage.ChooseMultipleFilesExtensionReturn) if info is None or files is None: return super().extension(QWebPage.ChooseMultipleFilesExtension, opt, files) suggested_file = "" if opt.suggestedFileNames: suggested_file = opt.suggestedFileNames[0] files.fileNames, _ = QFileDialog.getOpenFileNames(None, None, suggested_file) return True
def gpsfound_handler(self, gpsConnection) -> None: """ Handler for when the GPS signal has been found :param gpsConnection: The connection for the GPS :return: None """ if not isinstance(gpsConnection, QgsNmeaConnection): # This can be hit if the scan is used as the bindings in QGIS aren't # right and will not have the type set correctly import sip gpsConnection = sip.cast(gpsConnection, QgsGpsConnection) self.gpsConn = gpsConnection self.gpsConn.stateChanged.connect(self.gpsStateChanged) self.gpsConn.nmeaSentenceReceived.connect(self.parse_data) self.connected = True
def itemChange(self, change, value): ret = QtGui.QGraphicsObject.itemChange(self, change, value) if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]: self.parentChanged() if self.__inform_view_on_changes and change in [ self.ItemPositionHasChanged, self.ItemTransformHasChanged ]: self.informViewBoundsChanged() ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html if change == self.ItemParentChange and isinstance( ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) return ret
def __init__(self, widget, parent=None): QtWidgets.QDialog.__init__(self, parent) self.widget = widget self.previewWidget = ActionButton() #self.previewWidget.notify_option = widget.notify_option buttonBox = QtWidgets.QDialogButtonBox() okButton = buttonBox.addButton(buttonBox.Ok) cancelButton = buttonBox.addButton(buttonBox.Cancel) okButton.clicked.connect(self.updateWidget) cancelButton.clicked.connect(self.reject) layout = QtWidgets.QGridLayout() self.c_estop = QtWidgets.QCheckBox("Estop Action") self.c_estop.setChecked(widget.estop) layout.addWidget(self.c_estop) layout.addWidget(buttonBox, 5, 0, 1, 2) self.setLayout(layout) self.setWindowTitle(self.tr("Set Options")) return # well this didn't give me what I wanted form = QDesignerFormWindowInterface.findFormWindow(widget) if form: editor = form.core() manager = editor.extensionManager() w = editor.topLevel() print w sheet = manager.extension( w, Q_TYPEID['QDesignerMemberSheetExtension']) # This explicit cast is necessary here sheet = sip.cast(sheet, QPyDesignerMemberSheetExtension) memberCount = sheet.count() print widget, 'count:', memberCount print sheet.indexOf('clicked()') print sheet.indexOf('sender') for i in range(0, memberCount): #sheet.setVisible(i,False) if sheet.isSignal(i) or sheet.isSlot(i): print i, sheet.signature(i)
def itemChange(self, change, value): ret = QtGui.QGraphicsObject.itemChange(self, change, value) if change in [self.ItemParentHasChanged, self.ItemSceneHasChanged]: self.parentChanged() try: inform_view_on_change = self.__inform_view_on_changes except AttributeError: # It's possible that the attribute was already collected when the itemChange happened # (if it was triggered during the gc of the object). pass else: if inform_view_on_change and change in [self.ItemPositionHasChanged, self.ItemTransformHasChanged]: self.informViewBoundsChanged() ## workaround for pyqt bug: ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html if not USE_PYSIDE and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem): ret = sip.cast(ret, QtGui.QGraphicsItem) return ret
def processAlgorithm(self, parameters, context, feedback): layout_name = self.parameterAsString(parameters, self.LAYOUT, context) map_uuid = self.parameterAsString(parameters, self.MAP, context) layout = context.project().layoutManager().layoutByName(layout_name) if layout is None: raise QgsProcessingException( 'Cannot find layout with name "{}"'.format(layout_name)) item = layout.itemByUuid(map_uuid) if item is None: raise QgsProcessingException( 'Cannot find matching map item with uuid "{}"'.format( map_uuid)) map = sip.cast(item, QgsLayoutItemMap) fields = QgsFields() fields.append(QgsField('width', QVariant.Double)) fields.append(QgsField('height', QVariant.Double)) fields.append(QgsField('scale', QVariant.Double)) fields.append(QgsField('rotation', QVariant.Double)) sink, dest = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Polygon, map.crs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) extent = QgsGeometry.fromQPolygonF(map.visibleExtentPolygon()) f = QgsFeature() f.setAttributes([ map.rect().width(), map.rect().height(), map.scale(), map.mapRotation() ]) f.setGeometry(extent) sink.addFeature(f, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest}
def main(*args, **kwargs): app = QtWidgets.QApplication(sys.argv) if False: lib = QtCore.QLibrary(LIB) if lib.load(): print("OK") fn = lib.resolve("get_widget") #qw = QtWidgets.QWidget(cast(fn, QtWidgets.QWidget)) print(fn.ascapsule()) else: print("FAIL") else: ploader = QtCore.QPluginLoader(LIB) plugin = ploader.instance() print(ploader) if plugin is not None: print("Plugin loaded OK") print(plugin) w = cast(plugin, QtWidgets.QWidget) w.show() else: print("Plugin failed")
def testCopyPaste(self): p = QgsProject() l = QgsLayout(p) # clear clipboard mime_data = QMimeData() mime_data.setData("text/xml", QByteArray()) clipboard = QApplication.clipboard() clipboard.setMimeData(mime_data) # add an item item1 = QgsLayoutItemLabel(l) item1.setText('label 1') l.addLayoutItem(item1) item1.setSelected(True) item2 = QgsLayoutItemLabel(l) item2.setText('label 2') l.addLayoutItem(item2) item2.setSelected(True) # multiframes multiframe1 = QgsLayoutItemHtml(l) multiframe1.setHtml('mf1') l.addMultiFrame(multiframe1) frame1 = QgsLayoutFrame(l, multiframe1) frame1.setId('frame1a') multiframe1.addFrame(frame1) frame1b = QgsLayoutFrame(l, multiframe1) frame1b.setId('frame1b') multiframe1.addFrame(frame1b) # not selected frame1c = QgsLayoutFrame(l, multiframe1) frame1c.setId('frame1b') multiframe1.addFrame(frame1c) # not selected multiframe2 = QgsLayoutItemHtml(l) multiframe2.setHtml('mf2') l.addMultiFrame(multiframe2) frame2 = QgsLayoutFrame(l, multiframe2) frame2.setId('frame2') multiframe2.addFrame(frame2) frame1.setSelected(True) frame2.setSelected(True) view = QgsLayoutView() view.setCurrentLayout(l) self.assertFalse(view.hasItemsInClipboard()) view.copySelectedItems(QgsLayoutView.ClipboardCopy) self.assertTrue(view.hasItemsInClipboard()) pasted = view.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 4) new_multiframes = [ m for m in l.multiFrames() if m not in [multiframe1, multiframe2] ] self.assertEqual(len(new_multiframes), 2) self.assertIn(pasted[0], l.items()) self.assertIn(pasted[1], l.items()) labels = [ p for p in pasted if p.type() == QgsLayoutItemRegistry.LayoutLabel ] self.assertIn( sip.cast(labels[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) self.assertIn( sip.cast(labels[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) frames = [ p for p in pasted if p.type() == QgsLayoutItemRegistry.LayoutFrame ] pasted_frame1 = sip.cast(frames[0], QgsLayoutFrame) pasted_frame2 = sip.cast(frames[1], QgsLayoutFrame) self.assertIn(pasted_frame1.multiFrame(), new_multiframes) self.assertIn(new_multiframes[0].frames()[0].uuid(), (pasted_frame1.uuid(), pasted_frame2.uuid())) self.assertIn(pasted_frame2.multiFrame(), new_multiframes) self.assertIn(new_multiframes[1].frames()[0].uuid(), (pasted_frame1.uuid(), pasted_frame2.uuid())) self.assertEqual(frame1.multiFrame(), multiframe1) self.assertCountEqual(multiframe1.frames(), [frame1, frame1b, frame1c]) self.assertEqual(frame1b.multiFrame(), multiframe1) self.assertEqual(frame1c.multiFrame(), multiframe1) self.assertEqual(frame2.multiFrame(), multiframe2) self.assertCountEqual(multiframe2.frames(), [frame2]) # copy specific item view.copyItems([item2], QgsLayoutView.ClipboardCopy) l2 = QgsLayout(p) view2 = QgsLayoutView() view2.setCurrentLayout(l2) pasted = view2.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 1) self.assertIn(pasted[0], l2.items()) self.assertEqual( sip.cast(pasted[0], QgsLayoutItemLabel).text(), 'label 2')
def testCopyPaste(self): p = QgsProject() l = QgsLayout(p) # clear clipboard mime_data = QMimeData() mime_data.setData("text/xml", QByteArray()) clipboard = QApplication.clipboard() clipboard.setMimeData(mime_data) # add an item item1 = QgsLayoutItemLabel(l) item1.setText('label 1') l.addLayoutItem(item1) item1.setSelected(True) item2 = QgsLayoutItemLabel(l) item2.setText('label 2') l.addLayoutItem(item2) item2.setSelected(True) # multiframes multiframe1 = QgsLayoutItemHtml(l) multiframe1.setHtml('mf1') l.addMultiFrame(multiframe1) frame1 = QgsLayoutFrame(l, multiframe1) frame1.setId('frame1a') multiframe1.addFrame(frame1) frame1b = QgsLayoutFrame(l, multiframe1) frame1b.setId('frame1b') multiframe1.addFrame(frame1b) # not selected frame1c = QgsLayoutFrame(l, multiframe1) frame1c.setId('frame1b') multiframe1.addFrame(frame1c) # not selected multiframe2 = QgsLayoutItemHtml(l) multiframe2.setHtml('mf2') l.addMultiFrame(multiframe2) frame2 = QgsLayoutFrame(l, multiframe2) frame2.setId('frame2') multiframe2.addFrame(frame2) frame1.setSelected(True) frame2.setSelected(True) view = QgsLayoutView() view.setCurrentLayout(l) self.assertFalse(view.hasItemsInClipboard()) view.copySelectedItems(QgsLayoutView.ClipboardCopy) self.assertTrue(view.hasItemsInClipboard()) pasted = view.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 4) new_multiframes = [m for m in l.multiFrames() if m not in [multiframe1, multiframe2]] self.assertEqual(len(new_multiframes), 2) self.assertIn(pasted[0], l.items()) self.assertIn(pasted[1], l.items()) labels = [p for p in pasted if p.type() == QgsLayoutItemRegistry.LayoutLabel] self.assertIn(sip.cast(labels[0], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) self.assertIn(sip.cast(labels[1], QgsLayoutItemLabel).text(), ('label 1', 'label 2')) frames = [p for p in pasted if p.type() == QgsLayoutItemRegistry.LayoutFrame] pasted_frame1 = sip.cast(frames[0], QgsLayoutFrame) pasted_frame2 = sip.cast(frames[1], QgsLayoutFrame) self.assertIn(pasted_frame1.multiFrame(), new_multiframes) self.assertIn(new_multiframes[0].frames()[0].uuid(), (pasted_frame1.uuid(), pasted_frame2.uuid())) self.assertIn(pasted_frame2.multiFrame(), new_multiframes) self.assertIn(new_multiframes[1].frames()[0].uuid(), (pasted_frame1.uuid(), pasted_frame2.uuid())) self.assertEqual(frame1.multiFrame(), multiframe1) self.assertCountEqual(multiframe1.frames(), [frame1, frame1b, frame1c]) self.assertEqual(frame1b.multiFrame(), multiframe1) self.assertEqual(frame1c.multiFrame(), multiframe1) self.assertEqual(frame2.multiFrame(), multiframe2) self.assertCountEqual(multiframe2.frames(), [frame2]) # copy specific item view.copyItems([item2], QgsLayoutView.ClipboardCopy) l2 = QgsLayout(p) view2 = QgsLayoutView() view2.setCurrentLayout(l2) pasted = view2.pasteItems(QgsLayoutView.PasteModeCursor) self.assertEqual(len(pasted), 1) self.assertIn(pasted[0], l2.items()) self.assertEqual(sip.cast(pasted[0], QgsLayoutItemLabel).text(), 'label 2')
def __init__(self): QObject.__init__(self) ## Create Kate window self.kate_window = kate.mainInterfaceWindow() self.tool_view = self.kate_window.createToolView("preview", self.kate_window.Right, SmallIcon("okular"), "Okular") self.win = QWidget(self.tool_view) ## Load okular part factory = KPluginLoader("okularpart").factory() self.part = factory.create(self, "OkularPart", ["ViewerWidgetout",]) self.part = sip.cast(self.part, Okular.Part) self.okular_actions = self.part.actionCollection() print("Okular actions: ", self.okular_actions) #print("Action: %s: %s, context: %s" % ( # action.objectName(), # action.iconText(), # action.shortcutContext())) kate.configuration.root.clear() #Actions ''' Adds a shortcut using its stored, or its default shortcut. Takes a name-string as icon. ''' def addAction(self, objectName, icon, text, shortcut = "", slot = None): act = KAction(KIcon(icon), text, self.win) act.setObjectName(objectName) if not act.objectName() in kate.configuration: kate.configuration[act.objectName()] = shortcut act.setShortcut(kate.configuration[act.objectName()]) act.changed.connect( self.onActionChange ) if slot != None: act.triggered.connect( slot ) self.kate_window.window().actionCollection().addAction(act.objectName(), act) act.setEnabled(False) return act self.act_preview_file = addAction(self, 'preview-file', 'document-open', 'preview file', 'Ctrl+Alt+Shift+O', self.open ) self.act_go_jump = addAction(self, 'goto-shortcut', 'go-jump', 'Goto page', 'Ctrl+Alt+G', self.okular_actions.action('go_goto_page').trigger ) self.act_preview_file.setEnabled(True) ## Build a toolbar self.toolBar = QToolBar(self.win) toolButtonAction = QWidgetAction(self.win) toolButton = QToolButton() self.toolMenu = QMenu(toolButton) toolButton.setMenu(self.toolMenu) toolButton.setPopupMode(QToolButton.InstantPopup) toolButtonAction.setDefaultWidget(toolButton) # Update the buttons icon / main action when an action gets selected self.toolMenu.triggered.connect(toolButton.setDefaultAction) # toolButton provides a menu with actions for item in ['mouse_drag', 'mouse_zoom', 'mouse_select', 'mouse_textselect', 'mouse_tableselect']: act = self.okular_actions.action(item) if act: act = addAction(self, item, act.icon(), act.text(), act.shortcut().toString(), act.trigger) act.setEnabled(True) self.toolMenu.addAction(act) if item == 'mouse_drag': act.trigger() ## Arrange toolbar # self.toolBar.addAction(self.act_show_panel) self.toolBar.addAction(self.act_preview_file) self.toolBar.addAction(toolButtonAction) self.toolBar.addAction(self.act_go_jump) ## Disable okular's actions shortcut's, after we have used their default's as our own for action in self.okular_actions.actions(): action.setShortcut(QKeySequence()) ## Fit okular and toolbar together layout = QVBoxLayout() layout.addWidget(self.part.widget()) layout.addWidget(self.toolBar) self.win.setLayout(layout) ## Don't let us take focus, TODO check if this actually works and subwidgets can't grab the focus. self.win.setFocusPolicy(Qt.NoFocus) ## Test #for (name, value) in inspect.getmembers(self.part): # print("Name: %s\nValue: %s\n" % (name,value)) #print(self.part.staticMetaObject.superClass().superClass().superClass().className()) # Connect to new document and document deleted. When opening a session etc. new documents # are created before the plugin, so the open preview function handles these. kate.documentManager.documentCreated.connect(self.new_document) kate.documentManager.documentDeleted.connect(self.close_document)
def testAddItemsFromXml(self): p = QgsProject() l = QgsLayout(p) # add some items item1 = QgsLayoutItemLabel(l) item1.setId('xxyyxx') item1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) item1.attemptResize( QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) l.addItem(item1) item2 = QgsLayoutItemLabel(l) item2.setId('zzyyzz') item2.attemptMove( QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) item2.attemptResize( QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) l.addItem(item2) doc = QDomDocument("testdoc") # store in xml elem = l.writeXml(doc, QgsReadWriteContext()) l2 = QgsLayout(p) new_items = l2.addItemsFromXml(elem, doc, QgsReadWriteContext()) self.assertEqual(len(new_items), 2) items = l2.items() self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue(new_items[0] in l2.items()) self.assertTrue(new_items[1] in l2.items()) new_item1 = [i for i in items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual( new_item2.positionWithUnits(), QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) self.assertEqual( new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) # test with a group group = QgsLayoutItemGroup(l) group.addItem(item1) group.addItem(item2) l.addLayoutItem(group) elem = l.writeXml(doc, QgsReadWriteContext()) l3 = QgsLayout(p) new_items = l3.addItemsFromXml(elem, doc, QgsReadWriteContext()) self.assertEqual(len(new_items), 3) items = l3.items() self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue(new_items[0] in l3.items()) self.assertTrue(new_items[1] in l3.items()) self.assertTrue(new_items[2] in l3.items()) # f*** you sip, I'll just manually cast new_group = sip.cast(l3.itemByUuid(group.uuid()), QgsLayoutItemGroup) self.assertIsNotNone(new_group) other_items = [i for i in new_items if i.type() != new_group.type()] self.assertCountEqual(new_group.items(), other_items) # test restoring at set position l3 = QgsLayout(p) new_items = l3.addItemsFromXml(elem, doc, QgsReadWriteContext(), QPointF(10, 30)) self.assertEqual(len(new_items), 3) items = l3.items() new_item1 = [i for i in items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in items if i.id() == 'zzyyzz'][0] self.assertEqual( new_item1.positionWithUnits(), QgsLayoutPoint(10, 30, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual( new_item2.positionWithUnits(), QgsLayoutPoint(2.0, 4.0, QgsUnitTypes.LayoutCentimeters)) self.assertEqual( new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) # paste in place l4 = QgsLayout(p) page = QgsLayoutItemPage(l) page.setPageSize('A3') l4.pageCollection().addPage(page) page = QgsLayoutItemPage(l) page.setPageSize('A6') l4.pageCollection().addPage(page) new_items = l4.addItemsFromXml(elem, doc, QgsReadWriteContext(), QPointF(10, 30), True) self.assertEqual(len(new_items), 3) new_item1 = [i for i in new_items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in new_items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.pagePositionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.page(), 0) self.assertEqual( new_item2.pagePositionWithUnits(), QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) self.assertEqual( new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.page(), 0) # paste in place, page 2 new_items = l4.addItemsFromXml(elem, doc, QgsReadWriteContext(), QPointF(10, 550), True) self.assertEqual(len(new_items), 3) new_item1 = [i for i in new_items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in new_items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.pagePositionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.page(), 1) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual( new_item2.pagePositionWithUnits(), QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.page(), 1) self.assertEqual( new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters))
def translateGraphicsItem(item): ## for fixing pyqt bugs where the wrong item is returned if HAVE_SIP and isinstance(item, sip.wrapper): addr = sip.unwrapinstance(sip.cast(item, QtGui.QGraphicsItem)) item = GraphicsScene._addressCache.get(addr, item) return item
def printAction(self): #export tmp imgs of qwebviews for imgFile,webview in {"tmpSV.png":self.view.SV,"tmpBE.png":self.view.BE}.items(): painter = QtGui.QPainter() img = QtGui.QImage(webview.size().width(), webview.size().height(), QtGui.QImage.Format_ARGB32) painter.begin(img) webview.page().mainFrame().render(painter) painter.end() img.save(os.path.join(self.dirPath,"tmp",imgFile)) # portion of code from: http://gis.stackexchange.com/questions/77848/programmatically-load-composer-from-template-and-generate-atlas-using-pyqgis # Load template myLayout = core.QgsLayout(core.QgsProject.instance()) myFile = os.path.join(os.path.dirname(__file__), 'res','go2SV_A4.qpt') myTemplateFile = open(myFile, 'rt') myTemplateContent = myTemplateFile.read() myTemplateFile.close() myDocument = QtXml.QDomDocument() myDocument.setContent(myTemplateContent) myLayout.loadFromTemplate(myDocument,core.QgsReadWriteContext()) #MAP mapFrame = sip.cast(myLayout.itemById('MAP'),core.QgsLayoutItemMap) mapFrameAspectRatio = mapFrame.extent().width()/mapFrame.extent().height() newMapFrameExtent = core.QgsRectangle() actualPosition = self.transformToCurrentSRS(core.QgsPointXY (float(self.actualPOV['lon']),float(self.actualPOV['lat']))) centerX = actualPosition.x() centerY = actualPosition.y() if float(self.actualPOV['heading']) > 360: head = float(self.actualPOV['heading'])-360 else: head = float(self.actualPOV['heading']) newMapFrameExtent.set(centerX - self.iface.mapCanvas().extent().height()*mapFrameAspectRatio/2,centerY - self.iface.mapCanvas().extent().height()/2,centerX + self.iface.mapCanvas().extent().height()*mapFrameAspectRatio/2,centerY + self.iface.mapCanvas().extent().height()/2) mapFrame.setExtent(newMapFrameExtent) mapFrame.setMapRotation(self.canvas.rotation()) mapFrame.redraw() #CURSOR mapFrameCursor = sip.cast(myLayout.itemById('CAMERA'),core.QgsLayoutItemPicture) mapFrameCursor.setPicturePath(os.path.join(os.path.dirname(__file__),'res', 'camera.svg')) mapFrameCursor.setItemRotation(head+self.canvas.rotation(), adjustPosition=True) #NORTH mapFrameNorth = sip.cast(myLayout.itemById('NORTH'),core.QgsLayoutItemPicture) mapFrameNorth.setPicturePath(os.path.join(os.path.dirname(__file__),'res', 'NorthArrow_01.svg')) mapFrameNorth.setPictureRotation(self.canvas.rotation()) #STREETVIEW AND GM PICS if self.view.SV.isHidden(): LargePic = os.path.join(os.path.dirname(__file__),'tmp', 'tmpBE.png') SmallPic = os.path.join(os.path.dirname(__file__),'tmp', 'tmpSV.png') else: LargePic = os.path.join(os.path.dirname(__file__),'tmp', 'tmpSV.png') SmallPic = os.path.join(os.path.dirname(__file__),'tmp', 'tmpBE.png') SVFrame = sip.cast(myLayout.itemById('LARGE'),core.QgsLayoutItemPicture) SVFrame.setPicturePath(LargePic) BEFrame = sip.cast(myLayout.itemById('SMALL'),core.QgsLayoutItemPicture) BEFrame.setPicturePath(SmallPic) #DESCRIPTION DescFrame = sip.cast(myLayout.itemById('DESC'),core.QgsLayoutItemLabel) info = self.snapshotOutput.getGeolocationInfo() DescFrame.setText("LAT: %s\nLON: %s\nHEAD: %s\nADDRESS:\n%s" % (info['lat'], info['lon'], head, info['address'])) workDir = core.QgsProject.instance().readPath("./") fileName, filter = QtWidgets.QFileDialog().getSaveFileName(None,"Save pdf", workDir, "*.pdf"); if fileName: if QtCore.QFileInfo(fileName).suffix() != "pdf": fileName += ".pdf" exporter = core.QgsLayoutExporter(myLayout) exporter.exportToPdf(fileName,core.QgsLayoutExporter.PdfExportSettings())
def unwrap(obj): return sip.unwrapinstance(sip.cast(obj, QObject))
def toggle(self, state): doc = sip.cast(kate.activeDocument(), KateDocument) if state == True: self.enable(doc) else: self.disable(doc)
def testSaveLoadTemplate(self): tmpfile = os.path.join(self.basetestpath, 'testTemplate.qpt') p = QgsProject() l = QgsLayout(p) l.initializeDefaults() # add some items item1 = QgsLayoutItemLabel(l) item1.setId('xxyyxx') item1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) item1.attemptResize(QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) l.addItem(item1) item2 = QgsLayoutItemLabel(l) item2.setId('zzyyzz') item2.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) item2.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) l.addItem(item2) # multiframe multiframe1 = QgsLayoutItemHtml(l) multiframe1.setHtml('mf1') l.addMultiFrame(multiframe1) frame1 = QgsLayoutFrame(l, multiframe1) frame1.setId('frame1') frame1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) frame1.attemptResize(QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) multiframe1.addFrame(frame1) multiframe2 = QgsLayoutItemHtml(l) multiframe2.setHtml('mf2') l.addMultiFrame(multiframe2) frame2 = QgsLayoutFrame(l, multiframe2) frame2.setId('frame2') frame2.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) frame2.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) multiframe2.addFrame(frame2) uuids = {item1.uuid(), item2.uuid(), frame1.uuid(), frame2.uuid(), multiframe1.uuid(), multiframe2.uuid()} original_uuids = {item1.uuid(), item2.uuid(), frame1.uuid(), frame2.uuid()} self.assertTrue(l.saveAsTemplate(tmpfile, QgsReadWriteContext())) l2 = QgsLayout(p) with open(tmpfile) as f: template_content = f.read() doc = QDomDocument() doc.setContent(template_content) # adding to existing items new_items, ok = l2.loadFromTemplate(doc, QgsReadWriteContext(), False) self.assertTrue(ok) self.assertEqual(len(new_items), 4) items = l2.items() multiframes = l2.multiFrames() self.assertEqual(len(multiframes), 2) self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue([i for i in items if i.id() == 'frame1']) self.assertTrue([i for i in items if i.id() == 'frame2']) self.assertTrue([i for i in multiframes if i.html() == 'mf1']) self.assertTrue([i for i in multiframes if i.html() == 'mf2']) self.assertTrue(new_items[0] in l2.items()) self.assertTrue(new_items[1] in l2.items()) self.assertTrue(new_items[2] in l2.items()) self.assertTrue(new_items[3] in l2.items()) # double check that new items have a unique uid self.assertNotIn(new_items[0].uuid(), uuids) uuids.add(new_items[0].uuid()) self.assertNotIn(new_items[1].uuid(), uuids) uuids.add(new_items[1].uuid()) self.assertNotIn(new_items[2].uuid(), uuids) uuids.add(new_items[2].uuid()) self.assertNotIn(new_items[3].uuid(), uuids) uuids.add(new_items[3].uuid()) self.assertNotIn(multiframes[0].uuid(), [multiframe1.uuid(), multiframe2.uuid()]) self.assertNotIn(multiframes[1].uuid(), [multiframe1.uuid(), multiframe2.uuid()]) new_multiframe1 = [i for i in multiframes if i.html() == 'mf1'][0] self.assertEqual(new_multiframe1.layout(), l2) new_multiframe2 = [i for i in multiframes if i.html() == 'mf2'][0] self.assertEqual(new_multiframe2.layout(), l2) new_frame1 = sip.cast([i for i in items if i.id() == 'frame1'][0], QgsLayoutFrame) new_frame2 = sip.cast([i for i in items if i.id() == 'frame2'][0], QgsLayoutFrame) self.assertEqual(new_frame1.multiFrame(), new_multiframe1) self.assertEqual(new_multiframe1.frames()[0].uuid(), new_frame1.uuid()) self.assertEqual(new_frame2.multiFrame(), new_multiframe2) self.assertEqual(new_multiframe2.frames()[0].uuid(), new_frame2.uuid()) # adding to existing items new_items2, ok = l2.loadFromTemplate(doc, QgsReadWriteContext(), False) self.assertTrue(ok) self.assertEqual(len(new_items2), 4) items = l2.items() self.assertEqual(len(items), 8) multiframes2 = l2.multiFrames() self.assertEqual(len(multiframes2), 4) multiframes2 = [m for m in l2.multiFrames() if not m.uuid() in [new_multiframe1.uuid(), new_multiframe2.uuid()]] self.assertEqual(len(multiframes2), 2) self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue([i for i in items if i.id() == 'frame1']) self.assertTrue([i for i in items if i.id() == 'frame2']) self.assertTrue([i for i in multiframes2 if i.html() == 'mf1']) self.assertTrue([i for i in multiframes2 if i.html() == 'mf2']) self.assertTrue(new_items[0] in l2.items()) self.assertTrue(new_items[1] in l2.items()) self.assertTrue(new_items[2] in l2.items()) self.assertTrue(new_items[3] in l2.items()) self.assertTrue(new_items2[0] in l2.items()) self.assertTrue(new_items2[1] in l2.items()) self.assertTrue(new_items2[2] in l2.items()) self.assertTrue(new_items2[3] in l2.items()) self.assertNotIn(new_items2[0].uuid(), uuids) uuids.add(new_items[0].uuid()) self.assertNotIn(new_items2[1].uuid(), uuids) uuids.add(new_items[1].uuid()) self.assertNotIn(new_items2[2].uuid(), uuids) uuids.add(new_items[2].uuid()) self.assertNotIn(new_items2[3].uuid(), uuids) uuids.add(new_items[3].uuid()) self.assertNotIn(multiframes2[0].uuid(), [multiframe1.uuid(), multiframe2.uuid(), new_multiframe1.uuid(), new_multiframe2.uuid()]) self.assertNotIn(multiframes2[1].uuid(), [multiframe1.uuid(), multiframe2.uuid(), new_multiframe1.uuid(), new_multiframe2.uuid()]) new_multiframe1b = [i for i in multiframes2 if i.html() == 'mf1'][0] self.assertEqual(new_multiframe1b.layout(), l2) new_multiframe2b = [i for i in multiframes2 if i.html() == 'mf2'][0] self.assertEqual(new_multiframe2b.layout(), l2) new_frame1b = sip.cast([i for i in items if i.id() == 'frame1' and i.uuid() != new_frame1.uuid()][0], QgsLayoutFrame) new_frame2b = sip.cast([i for i in items if i.id() == 'frame2' and i.uuid() != new_frame2.uuid()][0], QgsLayoutFrame) self.assertEqual(new_frame1b.multiFrame(), new_multiframe1b) self.assertEqual(new_multiframe1b.frames()[0].uuid(), new_frame1b.uuid()) self.assertEqual(new_frame2b.multiFrame(), new_multiframe2b) self.assertEqual(new_multiframe2b.frames()[0].uuid(), new_frame2b.uuid()) # clearing existing items new_items3, ok = l2.loadFromTemplate(doc, QgsReadWriteContext(), True) new_multiframes = l2.multiFrames() self.assertTrue(ok) self.assertEqual(len(new_items3), 5) # includes page self.assertEqual(len(new_multiframes), 2) items = l2.items() self.assertTrue([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'xxyyxx']) self.assertTrue([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'zzyyzz']) self.assertTrue([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame1']) self.assertTrue([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame2']) self.assertTrue(new_items3[0] in l2.items()) self.assertTrue(new_items3[1] in l2.items()) self.assertTrue(new_items3[2] in l2.items()) self.assertTrue(new_items3[3] in l2.items()) new_multiframe1 = [i for i in new_multiframes if i.html() == 'mf1'][0] new_multiframe2 = [i for i in new_multiframes if i.html() == 'mf2'][0] new_frame1 = sip.cast([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame1'][0], QgsLayoutFrame) new_frame2 = sip.cast([i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame2'][0], QgsLayoutFrame) self.assertEqual(new_frame1.multiFrame(), new_multiframe1) self.assertEqual(new_multiframe1.frames()[0].uuid(), new_frame1.uuid()) self.assertEqual(new_frame2.multiFrame(), new_multiframe2) self.assertEqual(new_multiframe2.frames()[0].uuid(), new_frame2.uuid())
def testAddItemsFromXml(self): p = QgsProject() l = QgsLayout(p) # add some items item1 = QgsLayoutItemLabel(l) item1.setId('xxyyxx') item1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) item1.attemptResize(QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) l.addItem(item1) item2 = QgsLayoutItemLabel(l) item2.setId('zzyyzz') item2.attemptMove(QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) item2.attemptResize(QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) l.addItem(item2) doc = QDomDocument("testdoc") # store in xml elem = l.writeXml(doc, QgsReadWriteContext()) l2 = QgsLayout(p) new_items = l2.addItemsFromXml(elem, doc, QgsReadWriteContext()) self.assertEqual(len(new_items), 2) items = l2.items() self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue(new_items[0] in l2.items()) self.assertTrue(new_items[1] in l2.items()) new_item1 = [i for i in items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item2.positionWithUnits(), QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) # test with a group group = QgsLayoutItemGroup(l) group.addItem(item1) group.addItem(item2) l.addLayoutItem(group) elem = l.writeXml(doc, QgsReadWriteContext()) l3 = QgsLayout(p) new_items = l3.addItemsFromXml(elem, doc, QgsReadWriteContext()) self.assertEqual(len(new_items), 3) items = l3.items() self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue(new_items[0] in l3.items()) self.assertTrue(new_items[1] in l3.items()) self.assertTrue(new_items[2] in l3.items()) # f*** you sip, I'll just manually cast new_group = sip.cast(l3.itemByUuid(group.uuid()), QgsLayoutItemGroup) self.assertIsNotNone(new_group) other_items = [i for i in new_items if i.type() != new_group.type()] self.assertCountEqual(new_group.items(), other_items) # test restoring at set position l3 = QgsLayout(p) new_items = l3.addItemsFromXml(elem, doc, QgsReadWriteContext(), QPointF(10, 30)) self.assertEqual(len(new_items), 3) items = l3.items() new_item1 = [i for i in items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.positionWithUnits(), QgsLayoutPoint(10, 30, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item2.positionWithUnits(), QgsLayoutPoint(2.0, 4.0, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) # paste in place l4 = QgsLayout(p) page = QgsLayoutItemPage(l) page.setPageSize('A3') l4.pageCollection().addPage(page) page = QgsLayoutItemPage(l) page.setPageSize('A6') l4.pageCollection().addPage(page) new_items = l4.addItemsFromXml(elem, doc, QgsReadWriteContext(), QPointF(10, 30), True) self.assertEqual(len(new_items), 3) new_item1 = [i for i in new_items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in new_items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.pagePositionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.page(), 0) self.assertEqual(new_item2.pagePositionWithUnits(), QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.page(), 0) # paste in place, page 2 new_items = l4.addItemsFromXml(elem, doc, QgsReadWriteContext(), QPointF(10, 550), True) self.assertEqual(len(new_items), 3) new_item1 = [i for i in new_items if i.id() == 'xxyyxx'][0] new_item2 = [i for i in new_items if i.id() == 'zzyyzz'][0] self.assertEqual(new_item1.pagePositionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item1.page(), 1) self.assertEqual(new_item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) self.assertEqual(new_item2.pagePositionWithUnits(), QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) self.assertEqual(new_item2.page(), 1) self.assertEqual(new_item2.sizeWithUnits(), QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters))
def testSaveLoadTemplate(self): tmpfile = os.path.join(self.basetestpath, 'testTemplate.qpt') p = QgsProject() l = QgsLayout(p) l.initializeDefaults() # add some items item1 = QgsLayoutItemLabel(l) item1.setId('xxyyxx') item1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) item1.attemptResize( QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) l.addItem(item1) item2 = QgsLayoutItemLabel(l) item2.setId('zzyyzz') item2.attemptMove( QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) item2.attemptResize( QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) l.addItem(item2) # multiframe multiframe1 = QgsLayoutItemHtml(l) multiframe1.setHtml('mf1') l.addMultiFrame(multiframe1) frame1 = QgsLayoutFrame(l, multiframe1) frame1.setId('frame1') frame1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters)) frame1.attemptResize( QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters)) multiframe1.addFrame(frame1) multiframe2 = QgsLayoutItemHtml(l) multiframe2.setHtml('mf2') l.addMultiFrame(multiframe2) frame2 = QgsLayoutFrame(l, multiframe2) frame2.setId('frame2') frame2.attemptMove( QgsLayoutPoint(1.4, 1.8, QgsUnitTypes.LayoutCentimeters)) frame2.attemptResize( QgsLayoutSize(2.8, 2.2, QgsUnitTypes.LayoutCentimeters)) multiframe2.addFrame(frame2) uuids = { item1.uuid(), item2.uuid(), frame1.uuid(), frame2.uuid(), multiframe1.uuid(), multiframe2.uuid() } original_uuids = { item1.uuid(), item2.uuid(), frame1.uuid(), frame2.uuid() } self.assertTrue(l.saveAsTemplate(tmpfile, QgsReadWriteContext())) l2 = QgsLayout(p) with open(tmpfile) as f: template_content = f.read() doc = QDomDocument() doc.setContent(template_content) # adding to existing items new_items, ok = l2.loadFromTemplate(doc, QgsReadWriteContext(), False) self.assertTrue(ok) self.assertEqual(len(new_items), 4) items = l2.items() multiframes = l2.multiFrames() self.assertEqual(len(multiframes), 2) self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue([i for i in items if i.id() == 'frame1']) self.assertTrue([i for i in items if i.id() == 'frame2']) self.assertTrue([i for i in multiframes if i.html() == 'mf1']) self.assertTrue([i for i in multiframes if i.html() == 'mf2']) self.assertTrue(new_items[0] in l2.items()) self.assertTrue(new_items[1] in l2.items()) self.assertTrue(new_items[2] in l2.items()) self.assertTrue(new_items[3] in l2.items()) # double check that new items have a unique uid self.assertNotIn(new_items[0].uuid(), uuids) uuids.add(new_items[0].uuid()) self.assertNotIn(new_items[1].uuid(), uuids) uuids.add(new_items[1].uuid()) self.assertNotIn(new_items[2].uuid(), uuids) uuids.add(new_items[2].uuid()) self.assertNotIn(new_items[3].uuid(), uuids) uuids.add(new_items[3].uuid()) self.assertNotIn( multiframes[0].uuid(), [multiframe1.uuid(), multiframe2.uuid()]) self.assertNotIn( multiframes[1].uuid(), [multiframe1.uuid(), multiframe2.uuid()]) new_multiframe1 = [i for i in multiframes if i.html() == 'mf1'][0] self.assertEqual(new_multiframe1.layout(), l2) new_multiframe2 = [i for i in multiframes if i.html() == 'mf2'][0] self.assertEqual(new_multiframe2.layout(), l2) new_frame1 = sip.cast([i for i in items if i.id() == 'frame1'][0], QgsLayoutFrame) new_frame2 = sip.cast([i for i in items if i.id() == 'frame2'][0], QgsLayoutFrame) self.assertEqual(new_frame1.multiFrame(), new_multiframe1) self.assertEqual(new_multiframe1.frames()[0].uuid(), new_frame1.uuid()) self.assertEqual(new_frame2.multiFrame(), new_multiframe2) self.assertEqual(new_multiframe2.frames()[0].uuid(), new_frame2.uuid()) # adding to existing items new_items2, ok = l2.loadFromTemplate(doc, QgsReadWriteContext(), False) self.assertTrue(ok) self.assertEqual(len(new_items2), 4) items = l2.items() self.assertEqual(len(items), 8) multiframes2 = l2.multiFrames() self.assertEqual(len(multiframes2), 4) multiframes2 = [ m for m in l2.multiFrames() if not m.uuid() in [new_multiframe1.uuid(), new_multiframe2.uuid()] ] self.assertEqual(len(multiframes2), 2) self.assertTrue([i for i in items if i.id() == 'xxyyxx']) self.assertTrue([i for i in items if i.id() == 'zzyyzz']) self.assertTrue([i for i in items if i.id() == 'frame1']) self.assertTrue([i for i in items if i.id() == 'frame2']) self.assertTrue([i for i in multiframes2 if i.html() == 'mf1']) self.assertTrue([i for i in multiframes2 if i.html() == 'mf2']) self.assertTrue(new_items[0] in l2.items()) self.assertTrue(new_items[1] in l2.items()) self.assertTrue(new_items[2] in l2.items()) self.assertTrue(new_items[3] in l2.items()) self.assertTrue(new_items2[0] in l2.items()) self.assertTrue(new_items2[1] in l2.items()) self.assertTrue(new_items2[2] in l2.items()) self.assertTrue(new_items2[3] in l2.items()) self.assertNotIn(new_items2[0].uuid(), uuids) uuids.add(new_items[0].uuid()) self.assertNotIn(new_items2[1].uuid(), uuids) uuids.add(new_items[1].uuid()) self.assertNotIn(new_items2[2].uuid(), uuids) uuids.add(new_items[2].uuid()) self.assertNotIn(new_items2[3].uuid(), uuids) uuids.add(new_items[3].uuid()) self.assertNotIn(multiframes2[0].uuid(), [ multiframe1.uuid(), multiframe2.uuid(), new_multiframe1.uuid(), new_multiframe2.uuid() ]) self.assertNotIn(multiframes2[1].uuid(), [ multiframe1.uuid(), multiframe2.uuid(), new_multiframe1.uuid(), new_multiframe2.uuid() ]) new_multiframe1b = [i for i in multiframes2 if i.html() == 'mf1'][0] self.assertEqual(new_multiframe1b.layout(), l2) new_multiframe2b = [i for i in multiframes2 if i.html() == 'mf2'][0] self.assertEqual(new_multiframe2b.layout(), l2) new_frame1b = sip.cast([ i for i in items if i.id() == 'frame1' and i.uuid() != new_frame1.uuid() ][0], QgsLayoutFrame) new_frame2b = sip.cast([ i for i in items if i.id() == 'frame2' and i.uuid() != new_frame2.uuid() ][0], QgsLayoutFrame) self.assertEqual(new_frame1b.multiFrame(), new_multiframe1b) self.assertEqual(new_multiframe1b.frames()[0].uuid(), new_frame1b.uuid()) self.assertEqual(new_frame2b.multiFrame(), new_multiframe2b) self.assertEqual(new_multiframe2b.frames()[0].uuid(), new_frame2b.uuid()) # clearing existing items new_items3, ok = l2.loadFromTemplate(doc, QgsReadWriteContext(), True) new_multiframes = l2.multiFrames() self.assertTrue(ok) self.assertEqual(len(new_items3), 5) # includes page self.assertEqual(len(new_multiframes), 2) items = l2.items() self.assertTrue([ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'xxyyxx' ]) self.assertTrue([ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'zzyyzz' ]) self.assertTrue([ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame1' ]) self.assertTrue([ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame2' ]) self.assertTrue(new_items3[0] in l2.items()) self.assertTrue(new_items3[1] in l2.items()) self.assertTrue(new_items3[2] in l2.items()) self.assertTrue(new_items3[3] in l2.items()) new_multiframe1 = [i for i in new_multiframes if i.html() == 'mf1'][0] new_multiframe2 = [i for i in new_multiframes if i.html() == 'mf2'][0] new_frame1 = sip.cast([ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame1' ][0], QgsLayoutFrame) new_frame2 = sip.cast([ i for i in items if isinstance(i, QgsLayoutItem) and i.id() == 'frame2' ][0], QgsLayoutFrame) self.assertEqual(new_frame1.multiFrame(), new_multiframe1) self.assertEqual(new_multiframe1.frames()[0].uuid(), new_frame1.uuid()) self.assertEqual(new_frame2.multiFrame(), new_multiframe2) self.assertEqual(new_multiframe2.frames()[0].uuid(), new_frame2.uuid())