예제 #1
0
    def testExpressionInText(self):
        """Test expressions embedded in legend node text"""

        point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
        point_layer = QgsVectorLayer(point_path, 'points', 'ogr')

        layout = QgsPrintLayout(QgsProject.instance())
        layout.setName('LAYOUT')
        layout.initializeDefaults()

        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
        map.setFrameEnabled(True)
        map.setLayers([point_layer])
        layout.addLayoutItem(map)
        map.setExtent(point_layer.extent())

        legend = QgsLayoutItemLegend(layout)
        legend.setTitle("Legend")
        legend.attemptSetSceneRect(QRectF(120, 20, 100, 100))
        legend.setFrameEnabled(True)
        legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
        legend.setBackgroundColor(QColor(200, 200, 200))
        legend.setTitle('')
        legend.setLegendFilterByMapEnabled(False)
        legend.setStyleFont(QgsLegendStyle.Title, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Group, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.SymbolLabel, QgsFontUtils.getStandardTestFont('Bold', 16))

        legend.setAutoUpdateModel(False)

        QgsProject.instance().addMapLayers([point_layer])
        s = QgsMapSettings()
        s.setLayers([point_layer])

        group = legend.model().rootGroup().addGroup("Group [% 1 + 5 %] [% @layout_name %]")
        layer_tree_layer = group.addLayer(point_layer)
        layer_tree_layer.setCustomProperty("legend/title-label", 'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]')
        QgsMapLayerLegendUtils.setLegendNodeUserLabel(layer_tree_layer, 0, 'xxxx')
        legend.model().refreshLayerLegend(layer_tree_layer)
        legend.model().layerLegendNodes(layer_tree_layer)[0].setUserLabel('bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]')

        layout.addLayoutItem(legend)
        legend.setLinkedMap(map)

        map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))

        checker = QgsLayoutChecker(
            'composer_legend_expressions', layout)
        checker.setControlPathPrefix("composer_legend")
        result, message = checker.testLayout()
        self.assertTrue(result, message)

        QgsProject.instance().removeMapLayers([point_layer.id()])
예제 #2
0
    def testExpressionInText(self):
        """Test expressions embedded in legend node text"""

        point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
        point_layer = QgsVectorLayer(point_path, 'points', 'ogr')

        layout = QgsPrintLayout(QgsProject.instance())
        layout.setName('LAYOUT')
        layout.initializeDefaults()

        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
        map.setFrameEnabled(True)
        map.setLayers([point_layer])
        layout.addLayoutItem(map)
        map.setExtent(point_layer.extent())

        legend = QgsLayoutItemLegend(layout)
        legend.setTitle("Legend")
        legend.attemptSetSceneRect(QRectF(120, 20, 100, 100))
        legend.setFrameEnabled(True)
        legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
        legend.setBackgroundColor(QColor(200, 200, 200))
        legend.setTitle('')
        legend.setLegendFilterByMapEnabled(False)
        legend.setStyleFont(QgsLegendStyle.Title, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Group, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.SymbolLabel, QgsFontUtils.getStandardTestFont('Bold', 16))

        legend.setAutoUpdateModel(False)

        QgsProject.instance().addMapLayers([point_layer])
        s = QgsMapSettings()
        s.setLayers([point_layer])

        group = legend.model().rootGroup().addGroup("Group [% 1 + 5 %] [% @layout_name %]")
        layer_tree_layer = group.addLayer(point_layer)
        layer_tree_layer.setCustomProperty("legend/title-label", 'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]')
        QgsMapLayerLegendUtils.setLegendNodeUserLabel(layer_tree_layer, 0, 'xxxx')
        legend.model().refreshLayerLegend(layer_tree_layer)
        legend.model().layerLegendNodes(layer_tree_layer)[0].setUserLabel('bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]')

        layout.addLayoutItem(legend)
        legend.setLinkedMap(map)

        map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))

        checker = QgsLayoutChecker(
            'composer_legend_expressions', layout)
        checker.setControlPathPrefix("composer_legend")
        result, message = checker.testLayout()
        self.assertTrue(result, message)

        QgsProject.instance().removeMapLayers([point_layer.id()])
예제 #3
0
    def testSymbolExpressionRender(self):
        """Test expressions embedded in legend node text"""
        point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
        point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
        layout = QgsPrintLayout(QgsProject.instance())
        layout.setName('LAYOUT')
        layout.initializeDefaults()

        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(20, 20, 80, 80))
        map.setFrameEnabled(True)
        map.setLayers([point_layer])
        layout.addLayoutItem(map)
        map.setExtent(point_layer.extent())

        legend = QgsLayoutItemLegend(layout)
        legend.setTitle("Legend")
        legend.attemptSetSceneRect(QRectF(120, 20, 100, 100))
        legend.setFrameEnabled(True)
        legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
        legend.setBackgroundColor(QColor(200, 200, 200))
        legend.setTitle('')
        legend.setLegendFilterByMapEnabled(False)
        legend.setStyleFont(QgsLegendStyle.Title,
                            QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Group,
                            QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Subgroup,
                            QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.Symbol,
                            QgsFontUtils.getStandardTestFont('Bold', 16))
        legend.setStyleFont(QgsLegendStyle.SymbolLabel,
                            QgsFontUtils.getStandardTestFont('Bold', 16))

        legend.setAutoUpdateModel(False)

        QgsProject.instance().addMapLayers([point_layer])
        s = QgsMapSettings()
        s.setLayers([point_layer])

        group = legend.model().rootGroup().addGroup(
            "Group [% 1 + 5 %] [% @layout_name %]")
        layer_tree_layer = group.addLayer(point_layer)
        counterTask = point_layer.countSymbolFeatures()
        counterTask.waitForFinished()  # does this even work?
        layer_tree_layer.setCustomProperty(
            "legend/title-label",
            'bbbb [% 1+2 %] xx [% @layout_name %] [% @layer_name %]')
        QgsMapLayerLegendUtils.setLegendNodeUserLabel(layer_tree_layer, 0,
                                                      'xxxx')
        legend.model().refreshLayerLegend(layer_tree_layer)
        layer_tree_layer.setLabelExpression(
            'Concat(@symbol_id, @symbol_label, count("Class"))')
        legend.model().layerLegendNodes(layer_tree_layer)[0].setUserLabel(
            ' sym 1')
        legend.model().layerLegendNodes(layer_tree_layer)[1].setUserLabel(
            '[%@symbol_count %]')
        legend.model().layerLegendNodes(layer_tree_layer)[2].setUserLabel(
            '[% count("Class") %]')
        layout.addLayoutItem(legend)
        legend.setLinkedMap(map)
        legend.updateLegend()
        print(layer_tree_layer.labelExpression())
        TM = QgsApplication.taskManager()
        actask = TM.activeTasks()
        print(TM.tasks(), actask)
        count = actask[0]
        count.waitForFinished()
        map.setExtent(QgsRectangle(-102.51, 41.16, -102.36, 41.30))
        checker = QgsLayoutChecker('composer_legend_symbol_expression', layout)
        checker.setControlPathPrefix("composer_legend")
        sleep(4)
        result, message = checker.testLayout()
        self.assertTrue(result, message)

        QgsProject.instance().removeMapLayers([point_layer.id()])
예제 #4
0
def deduplicate_legend_entries(iface, raster_layer, criteria, unique_class_row_indexes=None, expand=None):
    """Remove duplicate entries from layer legend.

    :param iface: QGIS interface
    :type iface: QgisInterface
    :param raster_layer: raster layer
    :type raster_layer: QgsRasterLayer
    :param criteria: classification criteria: label for the legend band
    :type criteria: str
    :param unique_class_row_indexes: list of 1-indexed unique entries, defaults to None
    :type unique_class_row_indexes: list, optional
    :param expand: whether to expand the legend, defaults to None
    :type expand: any, optional
    """

    assert iface is not None
    model = iface.layerTreeView().layerTreeModel()
    root = QgsProject.instance().layerTreeRoot()
    node = root.findLayer(raster_layer.id())

    if unique_class_row_indexes is None:
        # QGIS >= 3.18 for first element label
        if Qgis.QGIS_VERSION_INT >= 31800:
            unique_class_row_indexes = [0]
            idx = 1
        else:
            unique_class_row_indexes = []
            idx = 0

        renderer = raster_layer.renderer()
        unique_labels = []

        # Get classes from renderer
        if isinstance(raster_layer.renderer(), QgsPalettedRasterRenderer):
            classes = renderer.classes()
        elif isinstance(raster_layer.renderer(), QgsSingleBandPseudoColorRenderer):
            shader = raster_layer.renderer().shader()
            if shader:
                colorRampShaderFcn = shader.rasterShaderFunction()
                if colorRampShaderFcn:
                    classes = colorRampShaderFcn.colorRampItemList()
        else:
            rat_log('Unsupported renderer for layer %s' %
                    raster_layer, Qgis.Critical)
            return

        for klass in classes:
            if klass.label not in unique_labels:
                unique_labels.append(klass.label)
                unique_class_row_indexes.append(idx)
            idx += 1

    rat_log(
        f'Deduplicating legend entries for layer {raster_layer.name()}: {unique_class_row_indexes}')
    QgsMapLayerLegendUtils.setLegendNodeOrder(
        node, unique_class_row_indexes)

    # QGIS >= 3.18 for first element label
    if Qgis.QGIS_VERSION_INT >= 31800:
        QgsMapLayerLegendUtils.setLegendNodeUserLabel(
            node, 0, criteria)

    model.refreshLayerLegend(node)
    if expand is not None:
        node.setExpanded(True)