Ejemplo n.º 1
0
    def createRenderer(self) -> QgsSingleSymbolRenderer:  # pylint: disable=missing-function-docstring
        filtering = SettingsRegistry.label_filtering()

        topological = self.topological and self.layer.selectedFeatureCount(
        ) == 2

        if filtering == SettingsRegistry.LABEL_NONE:
            return QgsNullSymbolRenderer()
        if filtering == SettingsRegistry.LABEL_SELECTED:
            if self.feature_id is None or self.vertex_number is None:
                # labeling selected vertex only, and no selection => no renderer
                return QgsNullSymbolRenderer()
            selection = {self.feature_id}
            vertex_number = self.vertex_number
        else:
            selection = self.layer.selectedFeatureIds()
            vertex_number = None

        if topological:
            request = QgsFeatureRequest().setFilterFids(
                self.layer.selectedFeatureIds()).setNoAttributes()
            topological_geometries = {
                f.id(): f.geometry()
                for f in self.layer.getFeatures(request)
            }
        else:
            topological_geometries = None

        layer_source = QgsVectorLayerFeatureSource(self.layer)

        return VertexHighlighterRenderer(
            source=layer_source,
            layer_type=self.layer_type,
            selection=selection,
            vertex_number=vertex_number,
            topological_geometries=topological_geometries,
        )
Ejemplo n.º 2
0
    def setUp(self):
        self.iface = get_iface()
        myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp')
        self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr')
        QgsProject.instance().addMapLayer(self.layer)

        self.renderer = QgsNullSymbolRenderer()
        self.layer.setRenderer(self.renderer)

        rendered_layers = [self.layer]
        self.mapsettings = self.iface.mapCanvas().mapSettings()
        self.mapsettings.setOutputSize(QSize(400, 400))
        self.mapsettings.setOutputDpi(96)
        self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52))
        self.mapsettings.setLayers(rendered_layers)
Ejemplo n.º 3
0
 def getRenderer(self):
     """docstring for getRenderer"""
     if self.num_classes == 0:
         try:
             #qgis 2.16+
             if QGis.QGIS_VERSION_INT >= 21600:
                 return QgsNullSymbolRenderer()
         except Exception as e:
             return False
     elif (self.num_classes == 1 and not self.has_classitem
           and not self.has_expression and not self.has_scaledenom):
         return self.__getSingleSymbolRenderer()
     else:
         if not self.has_expression:
             #if self.has_scaledenom:
             return self.__getRuleBasedRenderer()
             # Mal formado el MAPFILE, se dibujara con estilo por defecto de QGIS
             #return False
         else:
             if self.has_classitem and self.are_all_exp_string and not self.has_scaledenom:
                 return self.__getCategorizedSymbolRenderer()
             elif self.are_all_exp_logical_between and not self.has_scaledenom:
                 return self.__getGraduatedSymbolRenderer()
             return self.__getRuleBasedRenderer()
Ejemplo n.º 4
0
    def testBlockingItems(self):
        """
        Test rendering map item with blocking items
        """
        format = QgsTextFormat()
        format.setFont(QgsFontUtils.getStandardTestFont("Bold"))
        format.setSize(20)
        format.setNamedStyle("Bold")
        format.setColor(QColor(0, 0, 0))
        settings = QgsPalLayerSettings()
        settings.setFormat(format)
        settings.fieldName = "'X'"
        settings.isExpression = True
        settings.placement = QgsPalLayerSettings.OverPoint

        vl = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer", "vl",
                            "memory")
        vl.setRenderer(QgsNullSymbolRenderer())
        f = QgsFeature(vl.fields(), 1)
        for x in range(15):
            for y in range(15):
                f.setGeometry(QgsPoint(x, y))
                vl.dataProvider().addFeature(f)

        vl.setLabeling(QgsVectorLayerSimpleLabeling(settings))
        vl.setLabelsEnabled(True)

        p = QgsProject()

        engine_settings = QgsLabelingEngineSettings()
        engine_settings.setFlag(QgsLabelingEngineSettings.DrawLabelRectOnly,
                                True)
        p.setLabelingEngineSettings(engine_settings)

        p.addMapLayer(vl)
        layout = QgsLayout(p)
        layout.initializeDefaults()
        p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(10, 10, 180, 180))
        map.setFrameEnabled(True)
        map.zoomToExtent(vl.extent())
        map.setLayers([vl])
        map.setId('map')
        layout.addLayoutItem(map)

        map2 = QgsLayoutItemMap(layout)
        map2.attemptSetSceneRect(QRectF(0, 5, 50, 80))
        map2.setFrameEnabled(True)
        map2.setBackgroundEnabled(False)
        map2.setId('map2')
        layout.addLayoutItem(map2)

        map3 = QgsLayoutItemMap(layout)
        map3.attemptSetSceneRect(QRectF(150, 160, 50, 50))
        map3.setFrameEnabled(True)
        map3.setBackgroundEnabled(False)
        map3.setId('map3')
        layout.addLayoutItem(map3)

        map.addLabelBlockingItem(map2)
        map.addLabelBlockingItem(map3)
        map.setMapFlags(QgsLayoutItemMap.MapItemFlags())
        checker = QgsLayoutChecker('composermap_label_blockers', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)

        doc = QDomDocument("testdoc")
        elem = layout.writeXml(doc, QgsReadWriteContext())

        l2 = QgsLayout(p)
        self.assertTrue(l2.readXml(elem, doc, QgsReadWriteContext()))
        map_restore = [
            i for i in l2.items()
            if isinstance(i, QgsLayoutItemMap) and i.id() == 'map'
        ][0]
        map2_restore = [
            i for i in l2.items()
            if isinstance(i, QgsLayoutItemMap) and i.id() == 'map2'
        ][0]
        map3_restore = [
            i for i in l2.items()
            if isinstance(i, QgsLayoutItemMap) and i.id() == 'map3'
        ][0]
        self.assertTrue(map_restore.isLabelBlockingItem(map2_restore))
        self.assertTrue(map_restore.isLabelBlockingItem(map3_restore))
Ejemplo n.º 5
0
    def testPartialLabels(self):
        """
        Test rendering map item with a show partial labels flag
        """
        format = QgsTextFormat()
        format.setFont(QgsFontUtils.getStandardTestFont("Bold"))
        format.setSize(20)
        format.setNamedStyle("Bold")
        format.setColor(QColor(0, 0, 0))
        settings = QgsPalLayerSettings()
        settings.setFormat(format)
        settings.fieldName = "'X'"
        settings.isExpression = True
        settings.placement = QgsPalLayerSettings.OverPoint

        vl = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer", "vl",
                            "memory")
        vl.setRenderer(QgsNullSymbolRenderer())
        f = QgsFeature(vl.fields(), 1)
        for x in range(15):
            for y in range(15):
                f.setGeometry(QgsPoint(x, y))
                vl.dataProvider().addFeature(f)

        vl.setLabeling(QgsVectorLayerSimpleLabeling(settings))
        vl.setLabelsEnabled(True)

        p = QgsProject()

        engine_settings = QgsLabelingEngineSettings()
        engine_settings.setFlag(QgsLabelingEngineSettings.UsePartialCandidates,
                                False)
        engine_settings.setFlag(QgsLabelingEngineSettings.DrawLabelRectOnly,
                                True)
        p.setLabelingEngineSettings(engine_settings)

        p.addMapLayer(vl)
        layout = QgsLayout(p)
        layout.initializeDefaults()
        p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(10, 10, 180, 180))
        map.setFrameEnabled(True)
        map.zoomToExtent(vl.extent())
        map.setLayers([vl])
        layout.addLayoutItem(map)

        # default should always be to hide partial labels
        self.assertFalse(map.mapFlags() & QgsLayoutItemMap.ShowPartialLabels)

        # hiding partial labels (the default)
        map.setMapFlags(QgsLayoutItemMap.MapItemFlags())
        checker = QgsLayoutChecker('composermap_label_nomargin', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)

        # showing partial labels
        map.setMapFlags(QgsLayoutItemMap.ShowPartialLabels)
        checker = QgsLayoutChecker('composermap_show_partial_labels', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)
Ejemplo n.º 6
0
    def testLabelMargin(self):
        """
        Test rendering map item with a label margin set
        """
        format = QgsTextFormat()
        format.setFont(QgsFontUtils.getStandardTestFont("Bold"))
        format.setSize(20)
        format.setNamedStyle("Bold")
        format.setColor(QColor(0, 0, 0))
        settings = QgsPalLayerSettings()
        settings.setFormat(format)
        settings.fieldName = "'X'"
        settings.isExpression = True
        settings.placement = QgsPalLayerSettings.OverPoint

        vl = QgsVectorLayer("Point?crs=epsg:4326&field=id:integer", "vl",
                            "memory")
        vl.setRenderer(QgsNullSymbolRenderer())
        f = QgsFeature(vl.fields(), 1)
        for x in range(15):
            for y in range(15):
                f.setGeometry(QgsPoint(x, y))
                vl.dataProvider().addFeature(f)

        vl.setLabeling(QgsVectorLayerSimpleLabeling(settings))
        vl.setLabelsEnabled(True)

        p = QgsProject()

        engine_settings = QgsLabelingEngineSettings()
        engine_settings.setFlag(QgsLabelingEngineSettings.UsePartialCandidates,
                                False)
        engine_settings.setFlag(QgsLabelingEngineSettings.DrawLabelRectOnly,
                                True)
        p.setLabelingEngineSettings(engine_settings)

        p.addMapLayer(vl)
        layout = QgsLayout(p)
        layout.initializeDefaults()
        p.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(10, 10, 180, 180))
        map.setFrameEnabled(True)
        map.zoomToExtent(vl.extent())
        map.setLayers([vl])
        layout.addLayoutItem(map)

        checker = QgsLayoutChecker('composermap_label_nomargin', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)

        map.setLabelMargin(
            QgsLayoutMeasurement(15, QgsUnitTypes.LayoutMillimeters))
        checker = QgsLayoutChecker('composermap_label_margin', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)

        map.setLabelMargin(
            QgsLayoutMeasurement(3, QgsUnitTypes.LayoutCentimeters))
        checker = QgsLayoutChecker('composermap_label_cm_margin', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)

        map.setMapRotation(45)
        map.zoomToExtent(vl.extent())
        map.setScale(map.scale() * 1.2)
        checker = QgsLayoutChecker('composermap_rotated_label_margin', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)

        # data defined
        map.setMapRotation(0)
        map.zoomToExtent(vl.extent())
        map.dataDefinedProperties().setProperty(
            QgsLayoutObject.MapLabelMargin, QgsProperty.fromExpression('1+3'))
        map.refresh()
        checker = QgsLayoutChecker('composermap_dd_label_margin', layout)
        checker.setControlPathPrefix("composer_map")
        result, message = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(result, message)
Ejemplo n.º 7
0
    def add_joined_layer(
            source_layer: Union[FeatureLayer, StandaloneTable],  # pylint: disable=too-many-branches
            input_file,
            base_layer: QgsVectorLayer,
            context: Context):
        """
        Adds joined layers
        """
        if not source_layer.join:
            return None

        if isinstance(source_layer.join, MemoryRelationshipClassName):
            if isinstance(source_layer.join.origin_name, RelQueryTableName):
                if context.unsupported_object_callback:
                    context.unsupported_object_callback(
                        '{}: Nested joins are not supported in QGIS'.format(
                            context.layer_name),
                        level=Context.CRITICAL)

                return None

            join_info = QgsVectorLayerJoinInfo()

            join_info.setJoinFieldName(source_layer.join.origin_primary_key)
            join_info.setTargetFieldName(source_layer.join.origin_foreign_key)

            base, _ = os.path.split(input_file)

            source_layer_props = DatasetNameConverter.convert(
                name=source_layer.join.destination_name,
                base=base,
                crs=QgsCoordinateReferenceSystem(),
                context=context)
            context.layer_type_hint = source_layer_props.wkb_type

            name = 'join'
            if hasattr(source_layer.join.destination_name, 'name'):
                name = source_layer.join.destination_name.name
                join_info.setPrefix(name + '.')

            if Qgis.QGIS_VERSION_INT >= 30800:
                opts = QgsVectorLayer.LayerOptions()
                if source_layer_props.wkb_type is not None:
                    opts.fallbackWkbType = source_layer_props.wkb_type

                vl = QgsVectorLayer(source_layer_props.uri, name,
                                    source_layer_props.provider, opts)
            else:
                vl = QgsVectorLayer(source_layer_props.uri, name,
                                    source_layer_props.provider)
            if not vl.isValid() and Qgis.QGIS_VERSION_INT < 30600:
                if source_layer_props.provider == 'ogr' and not os.path.exists(
                        source_layer_props.file_name
                ) and context.invalid_layer_resolver:
                    res = context.invalid_layer_resolver(
                        source_layer.join.name, source_layer_props.uri,
                        source_layer_props.wkb_type)
                    source_layer_props.uri = res.uri
                    source_layer_props.provider = res.providerKey

                vl = QgsVectorLayer(source_layer_props.uri, 'join',
                                    source_layer_props.provider)

            # todo layer name
            vl.setRenderer(QgsNullSymbolRenderer())

            try:
                vl.setFlags(vl.flags() | QgsMapLayer.Private)
            except AttributeError:
                pass

            join_info.setJoinLayer(vl)
            base_layer.addJoin(join_info)

            return vl

        else:
            if context.unsupported_object_callback:
                context.unsupported_object_callback(
                    '{}: Join layers of type {} are not yet supported'.format(
                        context.layer_name,
                        source_layer.join.__class__.__name__),
                    level=Context.CRITICAL)

            return None
Ejemplo n.º 8
0
    def layer_to_QgsVectorLayer(
            source_layer,  # pylint: disable=too-many-locals,too-many-branches,too-many-statements
            input_file,
            context: Context,
            fallback_crs=QgsCoordinateReferenceSystem(),
            defer_layer_uri_set: bool = False):
        """
        Converts a vector layer
        """
        if source_layer.__class__.__name__ == 'CadFeatureLayer':
            layer = source_layer.layer
        else:
            layer = source_layer

        crs = CrsConverter.convert_crs(
            layer.layer_extent.crs,
            context) if layer.layer_extent else QgsCoordinateReferenceSystem()
        if not crs.isValid():
            crs = fallback_crs

        subset_string = ''
        if layer.selection_set:
            subset_string = 'fid in ({})'.format(','.join(
                [str(s) for s in layer.selection_set]))
        elif layer.definition_query:
            subset_string = ExpressionConverter.convert_esri_sql(
                layer.definition_query)

        base, _ = os.path.split(input_file)

        uri, wkb_type, provider, encoding, file_name = VectorLayerConverter.get_uri(
            source_layer=source_layer,
            obj=layer,
            base=base,
            crs=crs,
            subset=subset_string,
            context=context)

        if wkb_type is None or wkb_type == QgsWkbTypes.Unknown:
            wkb_type = VectorLayerConverter.layer_to_wkb_type(layer)
        context.layer_type_hint = wkb_type

        if Qgis.QGIS_VERSION_INT >= 31600:
            # try to get the layer name so that we can remove it from field references.
            # e.g. if layer name is polys then qgis won't support to arcgis style "polys.field" format
            parts = QgsProviderRegistry.instance().decodeUri(provider, uri)
            context.main_layer_name = parts.get('layerName')
            if not context.main_layer_name and provider == 'ogr':
                context.main_layer_name = Path(parts['path']).stem

            if context.main_layer_name:
                subset_string = subset_string.replace(
                    context.main_layer_name + '.', '')
        else:
            context.main_layer_name = None

        if provider == 'ogr' and (not file_name
                                  or not os.path.exists(file_name)
                                  ) and context.invalid_layer_resolver:
            res = context.invalid_layer_resolver(layer.name, uri, wkb_type)
            uri = res.uri
            provider = res.providerKey

        if Qgis.QGIS_VERSION_INT >= 31000:
            opts = QgsVectorLayer.LayerOptions()
            if wkb_type is not None:
                opts.fallbackWkbType = wkb_type

            if provider == 'ogr' and subset_string:
                uri += '|subset={}'.format(subset_string)

            original_uri = uri
            if defer_layer_uri_set:
                uri = 'xxxxxxxxx' + uri

            vl = QgsVectorLayer(uri, layer.name, provider, opts)
            if defer_layer_uri_set:
                vl.setCustomProperty('original_uri', original_uri)
        else:
            vl = QgsMemoryProviderUtils.createMemoryLayer(
                layer.name, QgsFields(), wkb_type, crs)

        # context.style_folder, _ = os.path.split(output_file)
        if layer.renderer:
            renderer = VectorRendererConverter.convert_renderer(
                layer.renderer, context)
            try:
                if not renderer.usingSymbolLevels():
                    renderer.setUsingSymbolLevels(
                        layer.use_advanced_symbol_levels)
            except AttributeError:
                pass

            if layer.use_page_definition_query:
                filter_expression = '"{}" {} @atlas_pagename'.format(
                    layer.page_name_field, layer.page_name_match_operator)
                root_rule = QgsRuleBasedRenderer.Rule(None)

                # special case -- convert a simple renderer
                if isinstance(renderer, QgsSingleSymbolRenderer):
                    filter_rule = QgsRuleBasedRenderer.Rule(
                        renderer.symbol().clone())
                    filter_rule.setFilterExpression(filter_expression)
                    filter_rule.setLabel(layer.name)
                    filter_rule.setDescription(layer.name)
                    root_rule.appendChild(filter_rule)
                else:
                    source_rule_renderer = QgsRuleBasedRenderer.convertFromRenderer(
                        renderer)
                    filter_rule = QgsRuleBasedRenderer.Rule(None)
                    filter_rule.setFilterExpression(filter_expression)
                    filter_rule.setLabel('Current Atlas Page')
                    filter_rule.setDescription('Current Atlas Page')
                    root_rule.appendChild(filter_rule)
                    for child in source_rule_renderer.rootRule().children():
                        filter_rule.appendChild(child.clone())

                renderer = QgsRuleBasedRenderer(root_rule)

            if renderer:
                vl.setRenderer(renderer)
                vl.triggerRepaint()
        else:
            vl.setRenderer(QgsNullSymbolRenderer())
            vl.triggerRepaint()

        metadata = vl.metadata()
        metadata.setAbstract(layer.description)
        vl.setMetadata(metadata)  #

        # layer.zoom_max = "don't show when zoomed out beyond"
        zoom_max = layer.zoom_max
        # layer.zoom_min = "don't show when zoomed in beyond"
        zoom_min = layer.zoom_min

        enabled_scale_range = bool(zoom_max or zoom_min)
        if zoom_max and zoom_min and zoom_min > zoom_max:
            # inconsistent scale range -- zoom_max should be bigger number than zoom_min
            zoom_min, zoom_max = zoom_max, zoom_min

        # qgis minimum scale = don't show when zoomed out beyond, i.e. ArcGIS zoom_max
        vl.setMinimumScale(
            zoom_max if enabled_scale_range else layer.stored_zoom_max)
        # qgis maximum scale = don't show when zoomed in beyond, i.e. ArcGIS zoom_min
        vl.setMaximumScale(
            zoom_min if enabled_scale_range else layer.stored_zoom_min)
        vl.setScaleBasedVisibility(enabled_scale_range)

        vl.setOpacity(1.0 - (layer.transparency or 0) / 100)

        if layer.display_expression_properties and layer.display_expression_properties.expression and layer.display_expression_properties.expression_parser is not None:
            vl.setDisplayExpression(
                ExpressionConverter.convert(
                    layer.display_expression_properties.expression,
                    layer.display_expression_properties.expression_parser,
                    layer.display_expression_properties.advanced, context))

        if Qgis.QGIS_VERSION_INT < 31000:
            vl.setDataSource(uri, layer.name, provider)

        if encoding:
            vl.dataProvider().setEncoding(encoding)

        if subset_string:
            vl.setSubsetString(subset_string)

        vl.setCrs(crs)

        for e in layer.extensions:
            if e.__class__.__name__ == 'ServerLayerExtension':
                if 'CopyrightText' in e.properties.properties:
                    layer_credits = e.properties.properties['CopyrightText']
                    metadata = vl.metadata()
                    rights = metadata.rights()
                    rights.append(layer_credits)
                    metadata.setRights(rights)
                    vl.setMetadata(metadata)

        LabelConverter.convert_annotation_collection(
            layer.annotation_collection, dest_layer=vl, context=context)
        vl.setLabelsEnabled(layer.labels_enabled)

        DiagramConverter.convert_diagrams(layer.renderer,
                                          dest_layer=vl,
                                          context=context)

        # setup joins
        join_layer = VectorLayerConverter.add_joined_layer(
            source_layer=layer,
            input_file=input_file,
            base_layer=vl,
            context=context)

        context.dataset_name = ''

        vl.setLegend(QgsMapLayerLegend.defaultVectorLegend(vl))

        if layer.hyperlinks:
            VectorLayerConverter.convert_hyperlinks(layer.hyperlinks, vl)

        vl.setDisplayExpression(
            QgsExpression.quotedColumnRef(layer.display_field))

        res = [vl]
        if join_layer:
            res.append(join_layer)

        context.main_layer_name = None
        return res