예제 #1
0
파일: default.py 프로젝트: inasafe/inasafe
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)
예제 #2
0
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
예제 #3
0
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)
예제 #4
0
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
예제 #5
0
파일: _fixes.py 프로젝트: qeryq/SFECOMLA
 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)
예제 #6
0
 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)
예제 #7
0
    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')
예제 #8
0
    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()
예제 #9
0
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
예제 #10
0
파일: mikro.py 프로젝트: moceap/scribus
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
예제 #11
0
    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()
예제 #12
0
    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()
예제 #13
0
    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()
예제 #14
0
    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
예제 #15
0
    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()
예제 #16
0
 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
예제 #17
0
 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
예제 #18
0
 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
예제 #19
0
    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()
예제 #20
0
 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)
예제 #21
0
    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)
예제 #22
0
    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')
예제 #23
0
 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
예제 #24
0
 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
예제 #25
0
    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
예제 #26
0
    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
예제 #27
0
 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
예제 #28
0
    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
예제 #29
0
 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)
예제 #30
0
    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)
예제 #31
0
    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}
예제 #32
0
    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
예제 #33
0
 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)
예제 #34
0
 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)
예제 #35
0
    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
예제 #36
0
    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
예제 #37
0
    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
예제 #38
0
    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
예제 #39
0
파일: gps.py 프로젝트: AnnijaViktorija/Roam
    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
예제 #40
0
    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
예제 #41
0
    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
예제 #43
0
    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
예제 #44
0
    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}
예제 #45
0
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")
예제 #46
0
    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')
예제 #47
0
    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')
예제 #48
0
  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)        
예제 #49
0
    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))
예제 #50
0
 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
예제 #51
0
    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())
예제 #52
0
 def unwrap(obj):
     return sip.unwrapinstance(sip.cast(obj, QObject))
예제 #53
0
 def toggle(self, state):
     doc = sip.cast(kate.activeDocument(), KateDocument)
     if state == True:
       self.enable(doc)
     else:
       self.disable(doc)
예제 #54
0
 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
예제 #55
0
    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())
예제 #56
0
    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))
예제 #57
0
    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())