Exemple #1
0
    def test_zip_unzip(self):
        tmpDir = QTemporaryDir()
        tmpFile = "{}/project.qgz".format(tmpDir.path())

        project = QgsProject()

        l0 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "points.shp"), "points", "ogr")
        l1 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "lines.shp"), "lines", "ogr")
        project.addMapLayers([l0, l1])

        self.assertTrue(project.write(tmpFile))

        project2 = QgsProject()
        self.assertFalse(project2.isZipped())
        self.assertTrue(project2.fileName() == "")
        self.assertTrue(project2.read(tmpFile))
        self.assertTrue(project2.isZipped())
        self.assertTrue(project2.fileName() == tmpFile)
        layers = project2.mapLayers()

        self.assertEqual(len(layers.keys()), 2)
        self.assertTrue(layers[l0.id()].isValid(), True)
        self.assertTrue(layers[l1.id()].isValid(), True)

        project2.clear()
        self.assertFalse(project2.isZipped())
Exemple #2
0
    def test_geometryTypes(self):

        geo = [(1, "POINT", "(0 0)"),
               (2, "LINESTRING", "(0 0,1 0)"),
               (3, "POLYGON", "((0 0,1 0,1 1,0 0))"),
               (4, "MULTIPOINT", "((1 1))"),
               (5, "MULTILINESTRING", "((0 0,1 0),(0 1,1 1))"),
               (6, "MULTIPOLYGON", "(((0 0,1 0,1 1,0 0)),((2 2,3 0,3 3,2 2)))")]
        for wkb_type, wkt_type, wkt in geo:
            l = QgsVectorLayer("%s?crs=epsg:4326" % wkt_type, "m1", "memory", False)
            self.assertEqual(l.isValid(), True)
            QgsProject.instance().addMapLayer(l)

            f1 = QgsFeature(1)
            g = QgsGeometry.fromWkt(wkt_type + wkt)
            self.assertEqual(g is None, False)
            f1.setGeometry(g)
            l.dataProvider().addFeatures([f1])

            l2 = QgsVectorLayer("?layer_ref=%s" % l.id(), "vtab", "virtual", False)
            self.assertEqual(l2.isValid(), True)
            self.assertEqual(l2.dataProvider().featureCount(), 1)
            self.assertEqual(l2.dataProvider().wkbType(), wkb_type)

            QgsProject.instance().removeMapLayer(l.id())
Exemple #3
0
    def checkRepaintNonLabeledLayerDoesNotInvalidateLabelCache(self, job_type):
        layer = QgsVectorLayer("Point?field=fldtxt:string",
                               "layer1", "memory")
        settings = QgsMapSettings()
        settings.setExtent(QgsRectangle(5, 25, 25, 45))
        settings.setOutputSize(QSize(600, 400))
        settings.setLayers([layer])

        # with cache - first run should populate cache
        cache = QgsMapRendererCache()
        job = job_type(settings)
        job.setCache(cache)
        job.start()
        job.waitForFinished()
        self.assertFalse(job.usedCachedLabels())
        self.assertTrue(cache.hasCacheImage('_labels_'))
        self.assertTrue(cache.hasCacheImage(layer.id()))
        self.assertEqual(cache.dependentLayers('_labels_'), [])

        # trigger repaint on layer - should not invalidate label cache because layer is not labeled
        layer.triggerRepaint()
        self.assertTrue(cache.hasCacheImage('_labels_'))
        self.assertFalse(cache.hasCacheImage(layer.id()))
        self.assertTrue(job.takeLabelingResults())

        # second job should still use label cache
        job = job_type(settings)
        job.setCache(cache)
        job.start()
        job.waitForFinished()
        self.assertTrue(job.usedCachedLabels())
        self.assertTrue(cache.hasCacheImage('_labels_'))
        self.assertTrue(job.takeLabelingResults())
Exemple #4
0
    def applySymbology(self):
        self.getConnection()
        vlayer = qgis.utils.iface.mapCanvas().currentLayer()
        if vlayer == None:
            return

        fields = vlayer.dataProvider().fields()
        classField = None
        for f in fields:
            if f.name() == "classtype":
                classField = 'classtype'
            elif f.name() == "result":
                classField = 'result'
        print classField

        class_loaded = False
        for layer in QgsMapLayerRegistry.instance().mapLayers().values():
            if  layer.name() == "class":
                vlayerClass = layer
                class_loaded = True
        if not class_loaded:
            uriSubClass = QgsDataSourceURI()
            uriSubClass.setConnection(self.serverName, "5432", self.database, self.usr , self.pw)
            uriSubClass.setDataSource("classification", "class", None, "", "id")
            vlayerClass = QgsVectorLayer(uriSubClass.uri(), "class", "postgres")
            QgsMapLayerRegistry.instance().addMapLayer(vlayerClass)

        for field in fields:
            index = vlayer.fieldNameIndex(field.name())
            if field.name() == classField:
                vlayer.editFormConfig().setWidgetType(index, 'ValueRelation')
                vlayer.editFormConfig().setWidgetConfig(index, {'Layer': vlayerClass.id(), 'Key': 'id', 'Value': 'classname'})

        useJoin = True
        if useJoin:
            joinObject = QgsVectorJoinInfo()
            joinObject.joinLayerId = vlayerClass.id()
            joinObject.joinFieldName = 'id'
            joinObject.targetFieldName = classField
            joinObject.memoryCache = True
            vlayer.addJoin(joinObject)
            self.join.append(joinObject)
            categories = []
            iter = vlayerClass.getFeatures()
            for feature in iter:
                classname = feature['classname']
                color = QColor(feature['red'], feature['green'], feature['blue'])
                sym = QgsSymbolV2.defaultSymbol(vlayer.geometryType())
                sym.setColor(QColor(color))
                category = QgsRendererCategoryV2(classname, sym, classname)
                categories.append(category)
            field = "class_classname"
            renderer = QgsCategorizedSymbolRendererV2(field, categories)
            vlayer.setRendererV2(renderer)

        qgis.utils.iface.messageBar().pushMessage("Information", "Editor widget set", level = qgis.gui.QgsMessageBar.INFO, duration = 5)
        qgis.utils.iface.setActiveLayer(vlayer)
Exemple #5
0
    def test_CsvNoGeometry(self):
        l1 = QgsVectorLayer(QUrl.fromLocalFile(os.path.join(self.testDataDir, "delimitedtext/test.csv")).toString() + "?type=csv&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        l2 = QgsVectorLayer("?layer_ref=" + l1.id(), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)

        QgsProject.instance().removeMapLayer(l1.id())
Exemple #6
0
def preview(request, layer_slug):
    """Home page for layers.

    :param request: The web request.
    :param layer_slug: The layer
    """
    layer = get_object_or_404(Layer, slug=layer_slug)

    layer_path = os.path.join(
        settings.MEDIA_ROOT, 'layers', layer.slug, 'raw')
    map_layer = QgsVectorLayer(layer_path, layer.name, 'ogr')
    QgsMapLayerRegistry.instance().addMapLayer(map_layer)
    layer_uri = tempfile.NamedTemporaryFile(
        suffix='.png', prefix='inasafe-web-', dir='/tmp/').name
    # create image
    image = QImage(QSize(100, 100), QImage.Format_ARGB32_Premultiplied)

    # set image's background color
    color = QColor(255, 255, 255)
    image.fill(color.rgb())

    # create painter
    p = QPainter()
    p.begin(image)
    p.setRenderHint(QPainter.Antialiasing)

    renderer = QgsMapRenderer()

    # set layer set
    layers = [map_layer.id()]  # add ID of every layer
    renderer.setLayerSet(layers)

    # set extent
    rect = QgsRectangle(renderer.fullExtent())
    rect.scale(1.1)
    renderer.setExtent(rect)

    # set output size
    renderer.setOutputSize(image.size(), image.logicalDpiX())

    # do the rendering
    renderer.render(p)

    p.end()

    # clean up
    registry_list = qgis_layers()
    QgsMapLayerRegistry.instance().removeMapLayer(map_layer.id())
    print registry_list

    # save image
    image.save(layer_uri, 'png')
    with open(layer_uri, 'rb') as f:
        response = HttpResponse(f.read(), content_type='png')
    os.remove(layer_uri)

    return response
    def legend_test(self):
        self.mAtlasMap.setAtlasDriven(True)
        self.mAtlasMap.setAtlasScalingMode(QgsComposerMap.Auto)
        self.mAtlasMap.setAtlasMargin(0.10)

        # add a point layer
        ptLayer = QgsVectorLayer("Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)", "points", "memory")

        pr = ptLayer.dataProvider()
        f1 = QgsFeature(1)
        f1.initAttributes(2)
        f1.setAttribute(0, 1)
        f1.setAttribute(1, "Test label 1")
        f1.setGeometry(QgsGeometry.fromPoint(QgsPoint(-0.638, 48.954)))
        f2 = QgsFeature(2)
        f2.initAttributes(2)
        f2.setAttribute(0, 2)
        f2.setAttribute(1, "Test label 2")
        f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(-1.682, 48.550)))
        pr.addFeatures([f1, f2])

        # categorized symbology
        r = QgsCategorizedSymbolRendererV2("attr", [QgsRendererCategoryV2(1, QgsMarkerSymbolV2.createSimple({"color": "255,0,0"}), "red"),
                                                    QgsRendererCategoryV2(2, QgsMarkerSymbolV2.createSimple({"color": "0,0,255"}), "blue")])
        ptLayer.setRendererV2(r)

        QgsMapLayerRegistry.instance().addMapLayer(ptLayer)

        # add the point layer to the map settings
        layers = self.mapSettings.layers()
        layers = [ptLayer.id()] + layers
        self.mapSettings.setLayers(layers)

        # add a legend
        legend = QgsComposerLegend(self.mComposition)
        legend.moveBy(200, 100)
        # sets the legend filter parameter
        legend.setComposerMap(self.mAtlasMap)
        legend.setLegendFilterOutAtlas(True)
        self.mComposition.addComposerLegend(legend)

        self.mAtlas.beginRender()

        self.mAtlas.prepareForFeature(0)
        self.mLabel1.adjustSizeToText()

        checker = QgsCompositionChecker('atlas_legend', self.mComposition)
        myTestResult, myMessage = checker.testComposition()
        assert myTestResult

        self.mAtlas.endRender()

        # restore state
        self.mapSettings.setLayers([layers[1]])
        self.mComposition.removeComposerItem(legend)
        QgsMapLayerRegistry.instance().removeMapLayer(ptLayer.id())
class TestQgsArrowSymbolLayer(unittest.TestCase):

    def setUp(self):
        self.iface = get_iface()

        lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp')
        self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer)

        # Create style
        sym2 = QgsLineSymbolV2.createSimple({'color': '#fdbf6f'})
        self.lines_layer.setRendererV2(QgsSingleSymbolRendererV2(sym2))

        self.mapsettings = self.iface.mapCanvas().mapSettings()
        self.mapsettings.setOutputSize(QSize(400, 400))
        self.mapsettings.setOutputDpi(96)
        self.mapsettings.setExtent(QgsRectangle(-113, 28, -91, 40))
        self.mapsettings.setBackgroundColor(QColor("white"))

    def tearDown(self):
        QgsMapLayerRegistry.instance().removeAllMapLayers()

    def test_1(self):
        sym = self.lines_layer.rendererV2().symbol()
        sym_layer = QgsArrowSymbolLayer.create({'head_size': '6.5'})
        dd = QgsDataDefined("(@geometry_point_num % 4) * 2")
        sym_layer.setDataDefinedProperty("arrow_width", dd)
        dd2 = QgsDataDefined("(@geometry_point_num % 4) * 2")
        sym_layer.setDataDefinedProperty("head_size", dd2)
        fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'})
        sym_layer.setSubSymbol(fill_sym)
        sym.changeSymbolLayer(0, sym_layer)

        rendered_layers = [self.lines_layer.id()]
        self.mapsettings.setLayers(rendered_layers)

        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_arrowsymbollayer_1')
        self.assertTrue(renderchecker.runTest('arrowsymbollayer_1'))

    def test_2(self):
        sym = self.lines_layer.rendererV2().symbol()
        # double headed
        sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '5', 'head_size': '6.5', 'head_type': '2'})
        fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'})
        sym_layer.setSubSymbol(fill_sym)
        sym.changeSymbolLayer(0, sym_layer)

        rendered_layers = [self.lines_layer.id()]
        self.mapsettings.setLayers(rendered_layers)

        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_arrowsymbollayer_2')
        self.assertTrue(renderchecker.runTest('arrowsymbollayer_2'))
Exemple #9
0
    def test_QueryUrlEncoding(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        query = toPercent("SELECT * FROM vtab1")
        l2 = QgsVectorLayer("?layer_ref=%s&query=%s&uid=ObjectId&nogeometry" % (l1.id(), query), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)

        QgsProject.instance().removeMapLayer(l1.id())
    def test_CsvNoGeometry(self):
        l1 = QgsVectorLayer( os.path.join(self.testDataDir_, "test.csv") + "?type=csv&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", False)
        self.assertEqual( l1.isValid(), True )
        QgsMapLayerRegistry.instance().addMapLayer(l1)

        l2 = QgsVectorLayer( "?layer_ref=" + l1.id(), "vtab", "virtual", False )
        self.assertEqual(l2.isValid(), True)
        print sum([f.id() for f in l2.getFeatures()])

        QgsMapLayerRegistry.instance().removeMapLayer(l1.id())        
Exemple #11
0
    def test_recursiveLayer(self):
        source = toPercent(os.path.join(self.testDataDir, "france_parts.shp"))
        l = QgsVectorLayer("?layer=ogr:%s" % source, "vtab", "virtual", False)
        self.assertEqual(l.isValid(), True)
        QgsProject.instance().addMapLayer(l)

        l2 = QgsVectorLayer("?layer_ref=" + l.id(), "vtab2", "virtual", False)
        self.assertEqual(l2.isValid(), True)

        QgsProject.instance().removeMapLayer(l.id())
Exemple #12
0
    def test_QueryTableName(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        query = toPercent("SELECT * FROM vt")
        l2 = QgsVectorLayer("?layer_ref=%s:vt&query=%s&uid=ObJeCtId&nogeometry" % (l1.id(), query), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)
        self.assertEqual(l2.dataProvider().wkbType(), 100)  # NoGeometry

        QgsProject.instance().removeMapLayer(l1.id())
    def test_QueryUrlEncoding( self ):
        l1 = QgsVectorLayer( os.path.join(self.testDataDir_, "france_parts.shp"), "france_parts", "ogr", False )
        self.assertEqual( l1.isValid(), True )
        QgsMapLayerRegistry.instance().addMapLayer(l1)

        query = str(QUrl.toPercentEncoding("SELECT * FROM vtab1"))
        l2 = QgsVectorLayer("?layer_ref=%s&query=%s&uid=ObjectId&nogeometry" % (l1.id(), query), "vtab", "virtual", False)
        self.assertEqual( l2.isValid(), True )
        print sum([f.id() for f in l2.getFeatures()])

        QgsMapLayerRegistry.instance().removeMapLayer(l1.id())
    def test_DynamicGeometry(self):
        l1 = QgsVectorLayer( os.path.join(self.testDataDir_, "testextpt.txt") + "?type=csv&delimiter=%7C&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", False)
        self.assertEqual( l1.isValid(), True )
        QgsMapLayerRegistry.instance().addMapLayer(l1)

        query = QUrl.toPercentEncoding("select *,makepoint(x,y) as geom from vtab1")
        l2 = QgsVectorLayer( "?layer_ref=%s&query=%s&geometry=geom&uid=id" % (l1.id(),query), "vtab", "virtual", False )
        self.assertEqual( l2.isValid(), True )
        print sum([f.id() for f in l2.getFeatures()])

        QgsMapLayerRegistry.instance().removeMapLayer(l1.id())        
    def test_recursiveLayer( self ):
        source = QUrl.toPercentEncoding(os.path.join(self.testDataDir_, "france_parts.shp"))
        l = QgsVectorLayer("?layer=ogr:%s" % source, "vtab", "virtual", False)
        self.assertEqual(l.isValid(), True)
        QgsMapLayerRegistry.instance().addMapLayer(l)

        l2 = QgsVectorLayer("?layer_ref=" + l.id(), "vtab2", "virtual", False)
        self.assertEqual( l2.isValid(), True )
        print sum([f.id() for f in l2.getFeatures()])

        QgsMapLayerRegistry.instance().removeMapLayer(l.id())
Exemple #16
0
    def test_refLayer(self):
        l1 = QgsVectorLayer(QUrl.fromLocalFile(os.path.join(self.testDataDir, "delimitedtext/test.csv")).toString() + "?type=csv&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        l2 = QgsVectorLayer("?layer_ref=" + l1.id(), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)

        # now delete the layer
        QgsProject.instance().removeMapLayer(l1.id())
        # check that it does not crash
        print((sum([f.id() for f in l2.getFeatures()])))
Exemple #17
0
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer("Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string", "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer("Point?field=id:integer&field=bname:string&field=bfield:integer", "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C", "memory")
        self.assertEqual(v3.isValid(), True)
        QgsMapLayerRegistry.instance().addMapLayers([v1, v2, v3])
        joinInfo = QgsVectorJoinInfo()
        joinInfo.targetFieldName = "b_id"
        joinInfo.joinLayerId = v2.id()
        joinInfo.joinFieldName = "id"
        #joinInfo.prefix = "B_";
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.prefix = "BB_"
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS BB_bname, j1.bfield AS BB_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.prefix = ""
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorJoinInfo()
        joinInfo2.targetFieldName = "c_id"
        joinInfo2.joinLayerId = v3.id()
        joinInfo2.joinFieldName = "id"
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), ('SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield, j2.cname AS C_cname FROM {} AS t ' +
                                      'LEFT JOIN {} AS j1 ON t."b_id"=j1."id" ' +
                                      'LEFT JOIN {} AS j2 ON t."c_id"=j2."id"').format(v1.id(), v2.id(), v3.id()))

        QgsMapLayerRegistry.instance().removeMapLayers([v1, v2, v3])
Exemple #18
0
    def test_ShapefileWithGeometry(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        # use a temporary file
        l2 = QgsVectorLayer("?layer_ref=" + l1.id(), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)

        l2 = QgsVectorLayer("?layer_ref=%s:nn" % l1.id(), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)

        QgsProject.instance().removeMapLayer(l1.id())
Exemple #19
0
    def test_refLayers(self):
        l1 = QgsVectorLayer(QUrl.fromLocalFile(os.path.join(self.testDataDir, "delimitedtext/test.csv")).toString() + "?type=csv&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)

        # cf qgis bug #12266
        for i in range(10):
            q = toPercent("select * from t" + str(i))
            l2 = QgsVectorLayer("?layer_ref=%s:t%d&query=%s&uid=id" % (l1.id(), i, q), "vtab", "virtual", False)
            QgsProject.instance().addMapLayer(l2)
            self.assertEqual(l2.isValid(), True)
            s = sum([f.id() for f in l2.dataProvider().getFeatures()])  # NOQA
            self.assertEqual(sum([f.id() for f in l2.getFeatures()]), 21)
            QgsProject.instance().removeMapLayer(l2.id())
Exemple #20
0
    def testFilterByLayer(self):
        """ test filtering by layer"""
        QgsProject.instance().clear()
        m = QgsMapLayerProxyModel()
        l1 = QgsVectorLayer("Point?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
                            'layer 1', "memory")
        QgsProject.instance().addMapLayer(l1)
        l2 = QgsVectorLayer("Polygon?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
                            'lAyEr 2', "memory")
        QgsProject.instance().addMapLayer(l2)
        l3 = QgsVectorLayer("None?field=fldtxt:string&field=fldint:integer",
                            'another', "memory")
        QgsProject.instance().addMapLayer(l3)
        l4 = QgsVectorLayer("LineString?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer",
                            'final layer', "memory")
        QgsProject.instance().addMapLayer(l4)

        self.assertEqual(m.rowCount(), 4)
        self.assertEqual(m.data(m.index(0, 0)), 'another')
        self.assertEqual(m.data(m.index(1, 0)), 'final layer')
        self.assertEqual(m.data(m.index(2, 0)), 'layer 1')
        self.assertEqual(m.data(m.index(3, 0)), 'lAyEr 2')

        m.setExceptedLayerList([l1, l3])
        self.assertEqual(m.rowCount(), 2)
        self.assertEqual(m.data(m.index(0, 0)), 'final layer')
        self.assertEqual(m.data(m.index(1, 0)), 'lAyEr 2')

        m.setExceptedLayerIds([l2.id(), l4.id()])
        self.assertEqual(m.rowCount(), 2)
        self.assertEqual(m.data(m.index(0, 0)), 'another')
        self.assertEqual(m.data(m.index(1, 0)), 'layer 1')

        m.setLayerWhitelist([l1])
        self.assertEqual(m.rowCount(), 1)
        self.assertEqual(m.data(m.index(0, 0)), 'layer 1')

        m.setExceptedLayerIds([])
        self.assertEqual(m.rowCount(), 1)
        self.assertEqual(m.data(m.index(0, 0)), 'layer 1')

        m.setLayerWhitelist([l2, l3])
        self.assertEqual(m.rowCount(), 2)
        self.assertEqual(m.data(m.index(0, 0)), 'another')
        self.assertEqual(m.data(m.index(1, 0)), 'lAyEr 2')

        m.setLayerWhitelist([])
        self.assertEqual(m.rowCount(), 4)
    def test_expressionRequiresFormScope(self):

        res = list(QgsValueRelationFieldFormatter.expressionFormAttributes("current_value('ONE') AND current_value('TWO')"))
        res = sorted(res)
        self.assertEqual(res, ['ONE', 'TWO'])

        res = list(QgsValueRelationFieldFormatter.expressionFormVariables("@current_geometry"))
        self.assertEqual(res, ['current_geometry'])

        self.assertFalse(QgsValueRelationFieldFormatter.expressionRequiresFormScope(""))
        self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value('TWO')"))
        self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value ( 'TWO' )"))
        self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("@current_geometry"))

        self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("", QgsFeature()))
        self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry", QgsFeature()))
        self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", QgsFeature()))

        layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string",
                               "layer", "memory")
        self.assertTrue(layer.isValid())
        QgsProject.instance().addMapLayer(layer)
        f = QgsFeature(layer.fields())
        f.setAttributes([1, 'value'])
        point = QgsGeometry.fromPointXY(QgsPointXY(123, 456))
        f.setGeometry(point)
        self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_geometry", f))
        self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", f))
        self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'pkid' )", f))
        self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry current_value ( 'pkid' )", f))

        QgsProject.instance().removeMapLayer(layer.id())
    def setUp(self):
        self.iface = get_iface()
        myShpFile = os.path.join(TEST_DATA_DIR, 'rectangles.shp')
        layer = QgsVectorLayer(myShpFile, 'Points', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(layer)

        # Create rulebased style
        sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'})
        sym2 = QgsFillSymbolV2.createSimple({'color': '#71bd6c'})
        sym3 = QgsFillSymbolV2.createSimple({'color': '#1f78b4'})

        self.r1 = QgsRuleBasedRendererV2.Rule(sym1, 0, 0, '"id" = 1')
        self.r2 = QgsRuleBasedRendererV2.Rule(sym2, 0, 0, '"id" = 2')
        self.r3 = QgsRuleBasedRendererV2.Rule(sym3, 0, 0, 'ELSE')

        self.rootrule = QgsRuleBasedRendererV2.Rule(None)
        self.rootrule.appendChild(self.r1)
        self.rootrule.appendChild(self.r2)
        self.rootrule.appendChild(self.r3)

        self.renderer = QgsRuleBasedRendererV2(self.rootrule)
        layer.setRendererV2(self.renderer)
        self.mapsettings = self.iface.mapCanvas().mapSettings()
        self.mapsettings.setOutputSize(QSize(400, 400))
        self.mapsettings.setOutputDpi(96)
        self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52))

        rendered_layers = [layer.id()]
        self.mapsettings.setLayers(rendered_layers)
    def testRenderMarkerLayerDataDefined(self):
        """ test that rendering a marker symbol with data defined enabled layer works"""

        points_shp = os.path.join(TEST_DATA_DIR, 'points.shp')
        points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(points_layer)

        layer = QgsSimpleMarkerSymbolLayer()
        layer.setDataDefinedProperty("enabled", QgsDataDefined("Class='Biplane'"))
        layer.setColor(QColor(100, 150, 150))
        layer.setSize(5)
        layer.setOutlineStyle(Qt.NoPen)

        symbol = QgsMarkerSymbol()
        symbol.changeSymbolLayer(0, layer)
        points_layer.setRenderer(QgsSingleSymbolRenderer(symbol))

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(400, 400))
        ms.setOutputDpi(96)
        ms.setExtent(QgsRectangle(-133, 22, -70, 52))
        ms.setLayers([points_layer.id()])

        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(ms)
        renderchecker.setControlPathPrefix('symbol_layer')
        renderchecker.setControlName('expected_markerlayer_ddenabled')
        self.assertTrue(renderchecker.runTest('markerlayer_ddenabled'))
        QgsMapLayerRegistry.instance().removeMapLayer(points_layer)
Exemple #24
0
 def return_batch_route(self, features):
     """Save and/or display the routes retrieved"""
     osrm_batch_route_layer = QgsVectorLayer(
         "Linestring?crs=epsg:4326&field=id:integer"
         "&field=total_time:integer(20)&field=distance:integer(20)",
         "routes_osrm{}".format(self.nb_done), "memory")
     provider = osrm_batch_route_layer.dataProvider()
     provider.addFeatures(features)
     QgsMapLayerRegistry.instance().addMapLayer(osrm_batch_route_layer)
     if self.filename:
         error = QgsVectorFileWriter.writeAsVectorFormat(
             osrm_batch_route_layer, self.filename,
             self.encoding, None, "ESRI Shapefile")
         if error != QgsVectorFileWriter.NoError:
             self.iface.messageBar().pushMessage(
                 "Error",
                 "Can't save the result into {} - Output have been "
                 "added to the canvas (see QGis log for error trace"
                 "back)".format(self.filename), duration=10)
             QgsMessageLog.logMessage(
                 'OSRM-plugin error report :\n {}'.format(error),
                 level=QgsMessageLog.WARNING)
             self.iface.setActiveLayer(osrm_batch_route_layer)
             return -1
         else:
             QtGui.QMessageBox.information(
                 self.iface.mainWindow(), 'Info',
                 "Result saved in {}".format(self.filename))
     if self.check_add_layer.isChecked():
         self.iface.setActiveLayer(osrm_batch_route_layer)
     else:
         QgsMapLayerRegistry.instance().removeMapLayer(
             osrm_batch_route_layer.id())
     self.iface.messageBar().clearWidgets()
    def testRequestRepaintSimple(self):
        """ test requesting repaint with a single dependent layer """
        layer = QgsVectorLayer("Point?field=fldtxt:string",
                               "layer", "memory")
        QgsProject.instance().addMapLayers([layer])
        self.assertTrue(layer.isValid())

        # add image to cache
        cache = QgsMapRendererCache()
        im = QImage(200, 200, QImage.Format_RGB32)
        cache.setCacheImage('xxx', im, [layer])
        self.assertFalse(cache.cacheImage('xxx').isNull())
        self.assertTrue(cache.hasCacheImage('xxx'))

        # trigger repaint on layer
        layer.triggerRepaint()
        # cache image should be cleared
        self.assertTrue(cache.cacheImage('xxx').isNull())
        self.assertFalse(cache.hasCacheImage('xxx'))
        QgsProject.instance().removeMapLayer(layer.id())

        # test that cache is also cleared on deferred update
        layer = QgsVectorLayer("Point?field=fldtxt:string",
                               "layer", "memory")
        cache.setCacheImage('xxx', im, [layer])
        layer.triggerRepaint(True)
        self.assertFalse(cache.hasCacheImage('xxx'))
    def testRenderLineLayerDataDefined(self):
        """ test that rendering a line symbol with data defined enabled layer works"""

        lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp')
        lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(lines_layer)

        layer = QgsSimpleLineSymbolLayer()
        layer.setDataDefinedProperty("enabled", QgsDataDefined("Name='Highway'"))
        layer.setColor(QColor(100, 150, 150))
        layer.setWidth(5)

        symbol = QgsLineSymbol()
        symbol.changeSymbolLayer(0, layer)
        lines_layer.setRenderer(QgsSingleSymbolRenderer(symbol))

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(400, 400))
        ms.setOutputDpi(96)
        ms.setExtent(QgsRectangle(-133, 22, -70, 52))
        ms.setLayers([lines_layer.id()])

        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(ms)
        renderchecker.setControlPathPrefix('symbol_layer')
        renderchecker.setControlName('expected_linelayer_ddenabled')
        self.assertTrue(renderchecker.runTest('linelayer_ddenabled'))
        QgsMapLayerRegistry.instance().removeMapLayer(lines_layer)
 def _loadBufferLayer(self, sourceLayer, layerPath, layerName):
     layer = None
     layerId = ''
     layerList = QgsMapLayerRegistry.instance().mapLayersByName(layerName)
     if (len(layerList) > 0):
         layer = layerList[0]
         self._iface.legendInterface().moveLayer(layer, self._bufferGroupIndex)
     else:
         fullLayerPath = self.projectPath + '/' + layerPath
         if (layerName and layerPath and sourceLayer and sourceLayer.isValid()):
             if not QFile.exists(fullLayerPath):
                 # If the layer doesn't exist, clone from the source layer
                 layer = layers.cloneAsShapefile(sourceLayer, fullLayerPath, layerName)
             else:
                 # If the layer does exist, then load it and copy the style
                 layer = QgsVectorLayer(fullLayerPath, layerName, 'ogr')
             layer = layers.addLayerToLegend(self._iface, layer, self._bufferGroupIndex)
     if layer and layer.isValid():
         layerId = layer.id()
         layers.loadStyle(layer, fromLayer=sourceLayer)
         self._setDefaultSnapping(layer)
         layer.startEditing()
         layer.setFeatureFormSuppress(QgsVectorLayer.SuppressOn)
         self._iface.legendInterface().setLayerExpanded(layer, False)
     else:
         layer = None
     return layer, layerId
Exemple #28
0
    def testNoSliverPolygons(self):

        # create a layer with some polygons that will be used as a source for "avoid intersections"
        l = QgsVectorLayer('MultiPolygon', 'test_layer', 'memory')
        assert l.isValid()
        QgsProject.instance().addMapLayer(l)
        QgsProject.instance().writeEntry("Digitizing", "/AvoidIntersectionsList", [l.id()])

        features = []
        for i, wkt in enumerate(feat_wkt):
            f = QgsFeature(i + 1)
            f.setGeometry(QgsGeometry.fromWkt(wkt))
            features.append(f)

        l.dataProvider().addFeatures(features)
        assert l.pendingFeatureCount() == 7

        # create a geometry and remove its intersections with other geometries

        g = QgsGeometry.fromWkt(newg_wkt)
        assert g.avoidIntersections() == 0

        # the resulting multi-polygon must have exactly three parts
        # (in QGIS 2.0 it has one more tiny part that appears at the border between two of the original polygons)
        mpg = g.asMultiPolygon()
        assert len(mpg) == 3
 def _loadLogLayer(self, sourceLayer, layerPath, layerName):
     layer = None
     layerId = ''
     layerList = QgsMapLayerRegistry.instance().mapLayersByName(layerName)
     if (len(layerList) > 0):
         layer = layerList[0]
         self._iface.legendInterface().moveLayer(layer, self._bufferGroupIndex)
     else:
         fullLayerPath = self.projectPath + '/' + layerPath
         if (layerName and layerPath and sourceLayer and sourceLayer.isValid()):
             if not QFile.exists(fullLayerPath):
                 # If the layer doesn't exist, clone from the source layer
                 layer = layers.cloneAsShapefile(sourceLayer, fullLayerPath, layerName)
                 if layer and layer.isValid():
                     layer.dataProvider().addAttributes([QgsField('timestamp', QVariant.String, '', 10, 0, 'timestamp')])
                     layer.dataProvider().addAttributes([QgsField('event', QVariant.String, '', 6, 0, 'event')])
             else:
                 # If the layer does exist, then load it and copy the style
                 layer = QgsVectorLayer(fullLayerPath, layerName, 'ogr')
                 if layer and layer.isValid():
                     layers.loadStyle(layer, fromLayer=sourceLayer)
     if layer and layer.isValid():
         layerId = layer.id()
         layer.setFeatureFormSuppress(QgsVectorLayer.SuppressOn)
         self._iface.legendInterface().setLayerExpanded(layer, False)
     else:
         layer = None
     return layer, layerId
    def testLayerDataSourceReset(self):
        """When adding a layer with the same id to the store make sure
        the data source is also updated in case the layer validity has
        changed from False to True"""

        p = QgsProject()
        store = p.layerStore()
        vl1 = createLayer('valid')
        vl2 = QgsVectorLayer('/not_a_valid_path.shp', 'invalid', 'ogr')
        self.assertTrue(vl1.isValid())
        self.assertFalse(vl2.isValid())
        store.addMapLayers([vl1, vl2])
        self.assertEqual(store.validCount(), 1)
        self.assertEqual(len(store.mapLayers()), 2)

        # Re-add the bad layer
        store.addMapLayers([vl2])
        self.assertEqual(store.validCount(), 1)
        self.assertEqual(len(store.mapLayers()), 2)

        doc = QDomDocument()
        doc.setContent('<maplayer><provider encoding="UTF-8">ogr</provider><layername>fixed</layername><id>%s</id></maplayer>' % vl2.id())
        layer_node = QDomNode(doc.firstChild())
        self.assertTrue(vl2.writeXml(layer_node, doc, QgsReadWriteContext()))
        datasource_node = doc.createElement("datasource")
        datasource_node.appendChild(doc.createTextNode(os.path.join(TEST_DATA_DIR, 'points.shp')))
        layer_node.appendChild(datasource_node)
        p.readLayer(layer_node)
        self.assertEqual(store.validCount(), 2)
        self.assertEqual(len(store.mapLayers()), 2)
        self.assertEqual(store.mapLayers()[vl2.id()].name(), 'fixed')
Exemple #31
0
    def test_Query(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"),
                            "france_parts", "ogr", False)
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)
        ref_sum = sum(f.attributes()[0] for f in l1.getFeatures())

        query = toPercent("SELECT * FROM vtab1")
        l2 = QgsVectorLayer(
            "?layer_ref=%s&geometry=geometry:3:4326&query=%s&uid=OBJECTID" %
            (l1.id(), query), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)
        self.assertEqual(l2.dataProvider().wkbType(), 3)

        ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures())
        ref_sum3 = sum(f.id() for f in l2.getFeatures())
        # check we have the same rows
        self.assertEqual(ref_sum, ref_sum2)
        # check the id is ok
        self.assertEqual(ref_sum, ref_sum3)

        # the same, without specifying the geometry column name
        l2 = QgsVectorLayer(
            "?layer_ref=%s&query=%s&uid=OBJECTID" % (l1.id(), query), "vtab",
            "virtual", False)
        self.assertEqual(l2.isValid(), True)
        self.assertEqual(l2.dataProvider().wkbType(), 3)
        ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures())
        ref_sum3 = sum(f.id() for f in l2.getFeatures())
        # check we have the same rows
        self.assertEqual(ref_sum, ref_sum2)
        # check the id is ok
        self.assertEqual(ref_sum, ref_sum3)

        # with two geometry columns
        query = toPercent("SELECT *,geometry as geom FROM vtab1")
        l2 = QgsVectorLayer(
            "?layer_ref=%s&query=%s&uid=OBJECTID&geometry=geom:3:4326" %
            (l1.id(), query), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)
        self.assertEqual(l2.dataProvider().wkbType(), 3)
        ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures())
        ref_sum3 = sum(f.id() for f in l2.getFeatures())
        # check we have the same rows
        self.assertEqual(ref_sum, ref_sum2)
        # check the id is ok
        self.assertEqual(ref_sum, ref_sum3)

        # with two geometry columns, but no geometry column specified (will take the first)
        l2 = QgsVectorLayer(
            "?layer_ref=%s&query=%s&uid=OBJECTID" % (l1.id(), query), "vtab",
            "virtual", False)
        self.assertEqual(l2.isValid(), True)
        self.assertEqual(l2.dataProvider().wkbType(), 3)
        ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures())
        ref_sum3 = sum(f.id() for f in l2.getFeatures())
        # check we have the same rows
        self.assertEqual(ref_sum, ref_sum2)
        # check the id is ok
        self.assertEqual(ref_sum, ref_sum3)

        # the same, without geometry
        query = toPercent("SELECT * FROM ww")
        l2 = QgsVectorLayer(
            "?layer_ref=%s:ww&query=%s&uid=ObJeCtId&nogeometry" %
            (l1.id(), query), "vtab", "virtual", False)
        self.assertEqual(l2.isValid(), True)
        self.assertEqual(l2.dataProvider().wkbType(), 100)  # NoGeometry
        ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures())
        ref_sum3 = sum(f.id() for f in l2.getFeatures())
        self.assertEqual(ref_sum, ref_sum2)
        self.assertEqual(ref_sum, ref_sum3)

        # check that it fails when a query has a wrong geometry column
        l2 = QgsVectorLayer(
            "?layer_ref=%s&query=%s&geometry=geo" % (l1.id(), query), "vtab",
            "virtual", False)
        self.assertEqual(l2.isValid(), False)

        QgsProject.instance().removeMapLayer(l1.id())
Exemple #32
0
class AddField:
    def __init__(self, parent_widget):
        """This class handle the creation of Fields. This class is also imported
        in the MeanAnalyse class.

        Parameters
        ----------
        parent_widget: GeoDataFarm
        """
        self.iface = parent_widget.iface
        self.tsk_mngr = parent_widget.tsk_mngr
        self.db = parent_widget.db
        translate = TR('AddField')
        self.tr = translate.tr
        self.dock_widget = parent_widget.dock_widget
        self.parent = parent_widget
        self.AFD = AddFieldFileDialog()
        self.field = None
        self.defined_field = ''

    def run(self):
        """Presents the sub widget AddField and connects the different
        buttons to their function"""
        self.AFD.show()
        self.AFD.PBSelectExtent.clicked.connect(self.clicked_define_field)
        self.AFD.PBSave.clicked.connect(self.save)
        self.AFD.PBHelp.clicked.connect(self.help)
        self.AFD.PBQuit.clicked.connect(self.quit)
        self.AFD.exec()
        self.parent.populate.reload_fields()

    def set_widget_connections(self):
        """Function that sets the main widget connections."""
        self.parent.dock_widget.PBAddField.clicked.connect(self.run)
        self.parent.dock_widget.PBRemoveField.clicked.connect(
            self.remove_field)
        self.parent.dock_widget.PBViewFields.clicked.connect(self.view_fields)

    def clicked_define_field(self, ignore_name=True):
        """Creates an empty polygon that's define a field"""
        if ignore_name:
            self.field = QgsVectorLayer("Polygon?crs=epsg:4326", 'Search area',
                                        "memory")
        else:
            name = self.AFD.LEFieldName.text()
            if len(name) == 0:
                QMessageBox.information(
                    None, self.tr('Error:'),
                    self.tr('Field name must be filled in.'))
                return
            self.field = QgsVectorLayer("Polygon?crs=epsg:4326", name,
                                        "memory")

        add_background()
        set_zoom(self.parent.iface, 2)
        self.field.startEditing()
        self.iface.actionAddFeature().trigger()
        QgsProject.instance().addMapLayer(self.field)

    def remove_field(self):
        """Removes a field that the user wants, a check that there are no
        data that is depended on is made."""
        j = -1
        for i in range(self.parent.dock_widget.LWFields.count()):
            j += 1
            item = self.parent.dock_widget.LWFields.item(j)
            if item.checkState() == 2:
                field_name = item.text()
                qm = QMessageBox()
                res = qm.question(
                    None, self.tr('Question'),
                    self.tr("Do you want to delete ") + str(field_name),
                    qm.Yes, qm.No)
                if res == qm.No:
                    continue
                field_names = []
                for tble_type in [
                        'plant', 'ferti', 'spray', 'harvest', 'soil'
                ]:
                    field_names.extend(
                        self.db.execute_and_return(
                            "select field from {type}.manual".format(
                                type=tble_type)))
                sql = """SELECT table_name
               FROM   information_schema.tables 
               WHERE  table_schema = 'other'"""
                for tble_type in self.db.execute_and_return(sql):
                    tbl = tble_type[0]
                    field_names.extend(
                        self.db.execute_and_return(
                            "select field from other.{tbl}".format(tbl=tbl)))
                stop_removing = False
                for row in field_names:
                    if row[0] == field_name:
                        QMessageBox.information(
                            None, self.tr('Error'),
                            self.
                            tr('There are data sets that are dependent on this field, '
                               'it cant be removed.'))
                        stop_removing = True
                if stop_removing:
                    continue
                sql = "delete from fields where field_name='{f}'".format(
                    f=field_name)
                self.db.execute_sql(sql)
                self.parent.dock_widget.LWFields.takeItem(j)
                j -= 1

    def view_fields(self):
        """Add all fields that aren't displayed on the canvas,
        if no background map is loaded Google maps are loaded."""
        defined_field = self.defined_field
        if defined_field == '':
            add_background()
        sources = [
            layer.name().split('_')[0]
            for layer in QgsProject.instance().mapLayers().values()
        ]
        fields_db = self.db.execute_and_return("select field_name from fields")
        task = QgsTask.fromFunction('Adding fields to the canvas',
                                    add_fields_2_canvas,
                                    self.db,
                                    fields_db,
                                    defined_field,
                                    sources,
                                    on_finished=self.finish)
        self.tsk_mngr.addTask(task)

    def finish(self, result, values):
        """Produces either an error message telling what went wrong or adds the fields to canvas and zoom to the layers.

        Parameters
        ----------
        result: object
        values: list
            If all went ok:
                [True, list of layers]
            Else:
                [False, exception, traceback]
        """
        if values[0] is False:
            QMessageBox.information(
                None, self.tr('Error'),
                self.tr(
                    'Following error occurred: {m}\n\n Traceback: {t}'.format(
                        m=values[1], t=values[2])))
            return
        for layer in values[-1]:
            QgsProject.instance().addMapLayer(layer)
        if self.defined_field == '':
            set_zoom(self.parent.iface, 1.1)
        self.defined_field = ''

    def quit(self):
        """Closes the widget."""
        self.AFD.PBSelectExtent.clicked.disconnect()
        self.AFD.PBSave.clicked.disconnect()
        self.AFD.PBHelp.clicked.disconnect()
        self.AFD.PBQuit.clicked.disconnect()
        self.AFD.done(0)

    def save(self):
        """Saves the field in the database"""
        try:
            self.iface.actionSaveActiveLayerEdits().trigger()
            self.iface.actionToggleEditing().trigger()
            feature = self.field.getFeature(1)
            QgsProject.instance().removeMapLayers([self.field.id()])
        except:
            QMessageBox.information(
                None, self.tr("Error:"),
                self.
                tr('No coordinates were found, did you mark the field on the canvas?'
                   ))
            return
        polygon = feature.geometry().asWkt()
        name = self.AFD.LEFieldName.text()
        if len(name) == 0:
            QMessageBox.information(None, self.tr('Error:'),
                                    self.tr('Field name must be filled in.'))
            return
        sql = """Insert into fields (field_name, polygon) 
        VALUES ('{name}', st_geomfromtext('{poly}', 4326))""".format(
            name=name, poly=polygon)
        try:
            self.db.execute_sql(sql)
        except IntegrityError:
            QMessageBox.information(
                None, self.tr('Error:'),
                self.tr('Field name already exist, please select a new name'))
            return
        except InternalError as e:
            QMessageBox.information(None, self.tr('Error:'), str(e))
            return
        _name = QApplication.translate("qadashboard", name, None)
        item = QListWidgetItem(_name, self.dock_widget.LWFields)
        item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
        item.setCheckState(QtCore.Qt.Unchecked)
        self.defined_field = name
        self.view_fields()

    def help(self):
        """A function that gives some advice on how the function works for the user.
        """
        QMessageBox.information(
            None, self.tr("Help:"),
            self.
            tr('Here is where you add a field.\n'
               '1. Start with giving the field a name.\n'
               '2. Press "select extent" and switch to the QGIS window and zoom to your field.\n'
               '3. To mark your field, left click with the mouse in one corner of the field.\n'
               'then left click in all corners of the field then right click anywhere on the map.\n'
               '(There might be some errors while clicking the corners if the lines are crossing each other but in the end this does not matter if they does not do it in the end)\n'
               '4. Press "Save field" to store the field.\n'
               '5. When all fields are added press "Finished"'))
        return
    def testCreateExpression(self):
        """ Test creating an expression using the widget"""
        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer", "test", "memory")
        # setup value relation
        parent_layer = QgsVectorLayer(
            "Point?field=stringkey:string&field=intkey:integer&field=display:string",
            "parent", "memory")
        f1 = QgsFeature(parent_layer.fields(), 1)
        f1.setAttributes(['a', 1, 'value a'])
        f2 = QgsFeature(parent_layer.fields(), 2)
        f2.setAttributes(['b', 2, 'value b'])
        f3 = QgsFeature(parent_layer.fields(), 3)
        f3.setAttributes(['c', 3, 'value c'])
        parent_layer.dataProvider().addFeatures([f1, f2, f3])
        QgsProject.instance().addMapLayers([layer, parent_layer])

        relationManager = QgsProject.instance().relationManager()
        relation = QgsRelation()
        relation.setId('relation')
        relation.setReferencingLayer(layer.id())
        relation.setReferencedLayer(parent_layer.id())
        relation.addFieldPair('fldtxt', 'stringkey')
        self.assertTrue(relation.isValid())

        relationManager.addRelation(relation)

        # Everything valid
        config = {'Relation': relation.id(), 'AllowNULL': True}

        w = QgsRelationReferenceSearchWidgetWrapper(layer, 0, None)
        w.setConfig(config)

        w.widget().setForeignKey('a')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldtxt"=\'a\'')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldtxt"<>\'a\'')

        w.widget().setForeignKey('b')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldtxt"=\'b\'')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldtxt"<>\'b\'')

        w.widget().setForeignKey('c')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldtxt"=\'c\'')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldtxt"<>\'c\'')

        w.widget().setForeignKey(None)
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldtxt" IS NOT NULL')
class oivImportFileWidget(QDockWidget, FORM_CLASS):
    """the actions class for the import"""

    parentWidget = None
    canvas = None
    selectTool = None
    importLayer = None
    layerImportType = None
    mappingDict = {}
    layerTypes = ['Point', 'LineString', 'Polygon']

    def __init__(self, parent=None):
        """Constructor."""
        super(oivImportFileWidget, self).__init__(parent)
        self.iface = iface
        self.setupUi(self)
        self.select_file.clicked.connect(self.selectfile)
        self.terug.clicked.connect(self.close_import)
        self.mapping.clicked.connect(self.run_mapping)
        self.import_file.clicked.connect(self.inlezen)
        self.hide_all()

    def selectfile(self):
        """select the import shape or dxf file"""
        dxfInfo = None
        importFile = QFileDialog.getOpenFileName(
            None, "Selecteer bestand:", None,
            "AutoCad (*.dxf);;Shape (*.shp);;GeoPackage (*.gpkg)")[0]
        self.bestandsnaam.setText(importFile)
        if importFile:
            if importFile.endswith('.dxf'):
                self.layerImportType, ok = DxfDialogObject.getGeometryType()
                dxfInfo = "|layername=entities|geometrytype=" + self.layerImportType
                importFileFeat = importFile + dxfInfo
                if not self.layerImportType or not ok:
                    return
                self.importLayer = QgsVectorLayer(importFileFeat, "import",
                                                  "ogr")
            elif importFile.endswith('.gpkg'):
                layerNames = [l.GetName() for l in ogr.Open(importFile)]
                GpkgDialog.layerNames = layerNames
                layerName, dummy = GpkgDialog.getLayerName()
                gpkgInfo = "|layername={}".format(layerName)
                importFileFeat = importFile + gpkgInfo
                self.importLayer = QgsVectorLayer(importFileFeat, "import",
                                                  "ogr")
            else:
                importFileFeat = importFile
                self.importLayer = QgsVectorLayer(importFileFeat, "import",
                                                  "ogr")
                if self.importLayer.geometryType() < 3:
                    self.layerImportType = self.layerTypes[
                        self.importLayer.geometryType()]
                else:
                    return
        else:
            return
        crs = self.importLayer.crs()
        crs.createFromId(28992)
        self.importLayer.setCrs(crs)
        QgsProject.instance().addMapLayer(self.importLayer, True)
        fields = self.importLayer.fields()
        for field in fields:
            self.type.addItem(field.name())
        self.label3.setVisible(True)
        self.type.setVisible(True)
        self.label6.setVisible(True)
        self.mapping.setVisible(True)

    def read_types(self):
        types = {}
        actionList, dummy, dummy = get_actions('config_object')
        for lst in actionList:
            tempList = []
            for action in lst:
                layerName = action[0]
                layer = getlayer_byname(layerName)
                layerType = check_layer_type(layer)
                tempList.append(action[1])
            tempList.append("niet importeren")
            if layerType in types:
                types[layerType].update({layerName: tempList})
            else:
                types.update({layerType: {layerName: tempList}})
        return types

    def inlezen(self):
        """import the file after all settings wehere made"""
        importAttr = self.type.currentText()
        invalidCount = 0
        for importType in self.mappingDict:
            if self.mappingDict[importType]["targetType"] != 'niet importeren':
                checkConv = False
                expr = QgsExpression('"{}"= \'{}\''.format(
                    importAttr, importType))
                featureIt = self.importLayer.getFeatures(
                    QgsFeatureRequest(expr))
                targetFeature = QgsFeature()
                targetLayerName = self.mappingDict[importType]["layerName"]
                if 'Labels' in targetLayerName:
                    LabelDialog.attributes = [
                        self.type.itemText(i) for i in range(self.type.count())
                    ]
                    LabelDialog.importType = importType
                    labelField, dummy = LabelDialog.getLabelAtrribute()
                targetLayer = getlayer_byname(targetLayerName)
                targetFields = targetLayer.fields()
                targetFeature.initAttributes(targetFields.count())
                targetFeature.setFields(targetFields)
                if self.mappingDict[importType][
                        "convType"] != self.layerImportType:
                    checkConv = True
                query = "SELECT foreign_key, identifier, input_label FROM config_object WHERE child_layer = '{}'".format(
                    targetLayerName)
                attrs = read_settings(query, False)[0]
                targetFeature[
                    attrs[1]] = self.mappingDict[importType]["targetType"]
                targetFeature[attrs[0]] = self.object_id.text()
                targetLayer.startEditing()

                for feat in featureIt:
                    geom = None
                    if not checkConv:
                        geom = getfeature_geometry(feat.geometry(),
                                                   self.layerImportType)
                        if 'Labels' in targetLayerName:
                            if feat[labelField]:
                                targetFeature[attrs[2]] = feat[labelField]
                            else:
                                targetFeature[attrs[2]] = 'geen label'
                    if geom:
                        targetFeature.setGeometry(geom)
                        invalidCheck = write_layer(targetLayer, targetFeature,
                                                   True)
                        if invalidCheck == 'invalid':
                            invalidCount += 1
                targetLayer.commitChanges()
        if invalidCount > 0:
            message = (
                'Features zijn geimporteerd.\n'
                '{} features zijn niet geimporteerd vanwege ongeldige geometrie!'
                .format(invalidCount))
        else:
            message = 'Alle feature zijn succesvol geimporteerd!'
        QMessageBox.information(None, "INFO:", message)
        QgsProject.instance().removeMapLayers([self.importLayer.id()])

    def run_mapping(self):
        """get attribute mapping from the user"""
        targetTypes = self.read_types()
        importTypes = []
        importAttribute = self.type.currentText()
        for feat in self.importLayer.getFeatures():
            if feat[importAttribute] not in importTypes:
                importTypes.append(feat[importAttribute])
        if self.layerImportType == 'Point':
            MappingDialog.layerType = ['Point']
        else:
            MappingDialog.layerType = ['LineString', 'Polygon']
        MappingDialog.targetTypes = targetTypes
        MappingDialog.importTypes = importTypes
        self.mappingDict, ok = MappingDialog.getMapping()
        if ok:
            self.label7.setVisible(True)
            self.import_file.setVisible(True)

    def hide_all(self):
        """when the import start hide all on the UI"""
        self.bouwlaag_id.setVisible(False)
        self.label1.setVisible(True)
        self.label3.setVisible(False)
        self.label6.setVisible(False)
        self.label7.setVisible(False)
        self.mapping.setVisible(False)
        self.type.setVisible(False)
        self.select_file.setVisible(True)
        self.bestandsnaam.setVisible(True)
        self.import_file.setVisible(False)

    def close_import(self):
        """close feature form and save changes"""
        try:
            QgsProject.instance().removeMapLayers([self.importLayer.id()])
        except:  # pylint: disable=bare-except
            pass
        self.hide_all()
        self.close()
        try:
            self.parentWidget.show()
            del self.parentWidget
        except:  # pylint: disable=bare-except
            pass
        del self
Exemple #35
0
    def legend_test(self):
        self.atlas_map.setAtlasDriven(True)
        self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto)
        self.atlas_map.setAtlasMargin(0.10)

        # add a point layer
        ptLayer = QgsVectorLayer(
            "Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)",
            "points", "memory")

        pr = ptLayer.dataProvider()
        f1 = QgsFeature(1)
        f1.initAttributes(2)
        f1.setAttribute(0, 1)
        f1.setAttribute(1, "Test label 1")
        f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-0.638, 48.954)))
        f2 = QgsFeature(2)
        f2.initAttributes(2)
        f2.setAttribute(0, 2)
        f2.setAttribute(1, "Test label 2")
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-1.682, 48.550)))
        pr.addFeatures([f1, f2])

        # categorized symbology
        r = QgsCategorizedSymbolRenderer("attr", [
            QgsRendererCategory(
                1,
                QgsMarkerSymbol.createSimple({
                    "color": "255,0,0",
                    'outline_color': 'black'
                }), "red"),
            QgsRendererCategory(
                2,
                QgsMarkerSymbol.createSimple({
                    "color": "0,0,255",
                    'outline_color': 'black'
                }), "blue")
        ])
        ptLayer.setRenderer(r)

        QgsProject.instance().addMapLayer(ptLayer)

        # add the point layer to the map settings
        layers = self.layers
        layers = [ptLayer] + layers
        self.atlas_map.setLayers(layers)
        self.overview.setLayers(layers)

        # add a legend
        legend = QgsLayoutItemLegend(self.layout)
        legend.attemptMove(QgsLayoutPoint(200, 100))
        # sets the legend filter parameter
        legend.setLinkedMap(self.atlas_map)
        legend.setLegendFilterOutAtlas(True)
        self.layout.addLayoutItem(legend)

        self.atlas.beginRender()

        self.atlas.seekTo(0)
        self.mLabel1.adjustSizeToText()

        checker = QgsLayoutChecker('atlas_legend', self.layout)
        myTestResult, myMessage = checker.testLayout()
        self.report += checker.report()
        self.assertTrue(myTestResult, myMessage)

        self.atlas.endRender()

        # restore state
        self.atlas_map.setLayers([layers[1]])
        self.layout.removeLayoutItem(legend)
        QgsProject.instance().removeMapLayer(ptLayer.id())
Exemple #36
0
class TestQgsBlendModes(unittest.TestCase):
    def __init__(self, methodName):
        """Run once on class initialization."""
        unittest.TestCase.__init__(self, methodName)

        self.iface = get_iface()

        # initialize class MapRegistry, Canvas, MapRenderer, Map and PAL
        self.mMapRegistry = QgsMapLayerRegistry.instance()

        # create point layer
        myShpFile = os.path.join(TEST_DATA_DIR, 'points.shp')
        self.mPointLayer = QgsVectorLayer(myShpFile, 'Points', 'ogr')
        self.mMapRegistry.addMapLayer(self.mPointLayer)

        self.mSimplifyMethod = QgsVectorSimplifyMethod()
        self.mSimplifyMethod.setSimplifyHints(
            QgsVectorSimplifyMethod.NoSimplification)

        # create polygon layer
        myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp')
        self.mPolygonLayer = QgsVectorLayer(myShpFile, 'Polygons', 'ogr')
        self.mPolygonLayer.setSimplifyMethod(self.mSimplifyMethod)
        self.mMapRegistry.addMapLayer(self.mPolygonLayer)

        # create line layer
        myShpFile = os.path.join(TEST_DATA_DIR, 'lines.shp')
        self.mLineLayer = QgsVectorLayer(myShpFile, 'Lines', 'ogr')
        self.mLineLayer.setSimplifyMethod(self.mSimplifyMethod)
        self.mMapRegistry.addMapLayer(self.mLineLayer)

        # create two raster layers
        myRasterFile = os.path.join(TEST_DATA_DIR, 'rgb256x256.png')
        self.mRasterLayer1 = QgsRasterLayer(myRasterFile, "raster1")
        self.mRasterLayer2 = QgsRasterLayer(myRasterFile, "raster2")
        myMultiBandRenderer1 = QgsMultiBandColorRenderer(
            self.mRasterLayer1.dataProvider(), 1, 2, 3)
        self.mRasterLayer1.setRenderer(myMultiBandRenderer1)
        self.mMapRegistry.addMapLayer(self.mRasterLayer1)
        myMultiBandRenderer2 = QgsMultiBandColorRenderer(
            self.mRasterLayer2.dataProvider(), 1, 2, 3)
        self.mRasterLayer2.setRenderer(myMultiBandRenderer2)
        self.mMapRegistry.addMapLayer(self.mRasterLayer2)

        # to match blend modes test comparisons background
        self.mapSettings = QgsMapSettings()
        self.mapSettings.setLayers(
            [self.mRasterLayer1.id(),
             self.mRasterLayer2.id()])
        self.mapSettings.setBackgroundColor(QColor(152, 219, 249))
        self.mapSettings.setOutputSize(QSize(400, 400))
        self.mapSettings.setOutputDpi(96)

        self.extent = QgsRectangle(-118.8888888888887720, 22.8002070393376783,
                                   -83.3333333333331581, 46.8719806763287536)

    def testVectorBlending(self):
        """Test that blend modes work for vector layers."""

        # Add vector layers to map
        myLayers = []
        myLayers.append(self.mLineLayer.id())
        myLayers.append(self.mPolygonLayer.id())
        self.mapSettings.setLayers(myLayers)
        self.mapSettings.setExtent(self.extent)

        # Set blending modes for both layers
        self.mLineLayer.setBlendMode(QPainter.CompositionMode_Difference)
        self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_Difference)

        checker = QgsMultiRenderChecker()
        checker.setControlName("expected_vector_blendmodes")
        checker.setMapSettings(self.mapSettings)
        checker.setColorTolerance(1)

        myResult = checker.runTest("vector_blendmodes", 20)
        myMessage = ('vector blending failed')
        assert myResult, myMessage

        # Reset layers
        self.mLineLayer.setBlendMode(QPainter.CompositionMode_SourceOver)
        self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_SourceOver)

    def testVectorFeatureBlending(self):
        """Test that feature blend modes work for vector layers."""

        # Add vector layers to map
        myLayers = []
        myLayers.append(self.mLineLayer.id())
        myLayers.append(self.mPolygonLayer.id())
        self.mapSettings.setLayers(myLayers)
        self.mapSettings.setExtent(self.extent)

        # Set feature blending for line layer
        self.mLineLayer.setFeatureBlendMode(QPainter.CompositionMode_Plus)

        checker = QgsMultiRenderChecker()
        checker.setControlName("expected_vector_featureblendmodes")
        checker.setMapSettings(self.mapSettings)
        checker.setColorTolerance(1)

        myResult = checker.runTest("vector_featureblendmodes", 20)
        myMessage = ('vector feature blending failed')
        assert myResult, myMessage

        # Reset layers
        self.mLineLayer.setFeatureBlendMode(
            QPainter.CompositionMode_SourceOver)

    def testVectorLayerTransparency(self):
        """Test that layer transparency works for vector layers."""

        # Add vector layers to map
        myLayers = []
        myLayers.append(self.mLineLayer.id())
        myLayers.append(self.mPolygonLayer.id())
        self.mapSettings.setLayers(myLayers)
        self.mapSettings.setExtent(self.extent)

        # Set feature blending for line layer
        self.mLineLayer.setLayerTransparency(50)

        checker = QgsMultiRenderChecker()
        checker.setControlName("expected_vector_layertransparency")
        checker.setMapSettings(self.mapSettings)
        checker.setColorTolerance(1)

        myResult = checker.runTest("vector_layertransparency", 20)
        myMessage = ('vector layer transparency failed')
        assert myResult, myMessage

    def testRasterBlending(self):
        """Test that blend modes work for raster layers."""
        # Add raster layers to map
        myLayers = []
        myLayers.append(self.mRasterLayer1.id())
        myLayers.append(self.mRasterLayer2.id())
        self.mapSettings.setLayers(myLayers)
        self.mapSettings.setExtent(self.mRasterLayer1.extent())

        # Set blending mode for top layer
        self.mRasterLayer1.setBlendMode(QPainter.CompositionMode_Difference)
        checker = QgsMultiRenderChecker()
        checker.setControlName("expected_raster_blendmodes")
        checker.setMapSettings(self.mapSettings)
        checker.setColorTolerance(1)
        checker.setColorTolerance(1)

        myResult = checker.runTest("raster_blendmodes", 20)
        myMessage = ('raster blending failed')
        assert myResult, myMessage
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer("Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string", "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer("Point?field=id:integer&field=bname:string&field=bfield:integer", "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C", "memory")
        self.assertEqual(v3.isValid(), True)
        tl1 = QgsVectorLayer("NoGeometry?field=id:integer&field=e_id:integer&field=0name:string", "D", "memory")
        self.assertEqual(tl1.isValid(), True)
        tl2 = QgsVectorLayer("NoGeometry?field=id:integer&field=ena me:string", "E", "memory")
        self.assertEqual(tl2.isValid(), True)
        QgsProject.instance().addMapLayers([v1, v2, v3, tl1, tl2])
        joinInfo = QgsVectorLayerJoinInfo()
        joinInfo.setTargetFieldName("b_id")
        joinInfo.setJoinLayer(v2)
        joinInfo.setJoinFieldName("id")
        #joinInfo.setPrefix("B_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.setPrefix("BB_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), 'SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "BB_bname", j1."bfield" AS "BB_bfield" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id"'.format(v1.id(), v2.id()))
        joinInfo.setPrefix("")
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorLayerJoinInfo()
        joinInfo2.setTargetFieldName("c_id")
        joinInfo2.setJoinLayer(v3)
        joinInfo2.setJoinFieldName("id")
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), ('SELECT t.geometry, t.rowid AS uid, t."id", t."b_id", t."c_id", t."name", j1."bname" AS "B_bname", j1."bfield" AS "B_bfield", j2."cname" AS "C_cname" FROM "{}" AS t '
                                      + 'LEFT JOIN "{}" AS j1 ON t."b_id"=j1."id" '
                                      + 'LEFT JOIN "{}" AS j2 ON t."c_id"=j2."id"').format(v1.id(), v2.id(), v3.id()))

        # test NoGeometry joined layers with field names starting with a digit or containing white spaces
        joinInfo3 = QgsVectorLayerJoinInfo()
        joinInfo3.setTargetFieldName("e_id")
        joinInfo3.setJoinLayer(tl2)
        joinInfo3.setJoinFieldName("id")
        tl1.addJoin(joinInfo3)
        self.assertEqual(len(tl1.fields()), 4)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(tl1)
        self.assertEqual(df.query(), 'SELECT t.rowid AS uid, t."id", t."e_id", t."0name", j1."ena me" AS "E_ena me" FROM "{}" AS t LEFT JOIN "{}" AS j1 ON t."e_id"=j1."id"'.format(tl1.id(), tl2.id()))

        QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id(), tl1.id(), tl2.id()])
Exemple #38
0
    def testExportFeatureRelations(self):
        """ Test exporting a feature with relations """

        #parent layer
        parent = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer&field=foreignkey:integer",
            "parent", "memory")
        pr = parent.dataProvider()
        pf1 = QgsFeature()
        pf1.setFields(parent.fields())
        pf1.setAttributes(["test1", 67, 123])
        pf2 = QgsFeature()
        pf2.setFields(parent.fields())
        pf2.setAttributes(["test2", 68, 124])
        assert pr.addFeatures([pf1, pf2])

        #child layer
        child = QgsVectorLayer(
            "Point?field=x:string&field=y:integer&field=z:integer",
            "referencedlayer", "memory")
        pr = child.dataProvider()
        f1 = QgsFeature()
        f1.setFields(child.fields())
        f1.setAttributes(["foo", 123, 321])
        f2 = QgsFeature()
        f2.setFields(child.fields())
        f2.setAttributes(["bar", 123, 654])
        f3 = QgsFeature()
        f3.setFields(child.fields())
        f3.setAttributes(["foobar", 124, 554])
        assert pr.addFeatures([f1, f2, f3])

        QgsProject.instance().addMapLayers([child, parent])

        rel = QgsRelation()
        rel.setId('rel1')
        rel.setName('relation one')
        rel.setReferencingLayer(child.id())
        rel.setReferencedLayer(parent.id())
        rel.addFieldPair('y', 'foreignkey')

        QgsProject.instance().relationManager().addRelation(rel)

        exporter = QgsJsonExporter()

        exporter.setVectorLayer(parent)
        self.assertEqual(exporter.vectorLayer(), parent)
        exporter.setIncludeRelated(True)
        self.assertEqual(exporter.includeRelated(), True)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test1",
      "fldint":67,
      "foreignkey":123,
      "relation one":[{"x":"foo",
"y":123,
"z":321},
{"x":"bar",
"y":123,
"z":654}]
   }
}"""
        self.assertEqual(exporter.exportFeature(pf1), expected)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test2",
      "fldint":68,
      "foreignkey":124,
      "relation one":[{"x":"foobar",
"y":124,
"z":554}]
   }
}"""
        self.assertEqual(exporter.exportFeature(pf2), expected)

        # with field formatter
        setup = QgsEditorWidgetSetup('ValueMap',
                                     {"map": {
                                         "apples": 123,
                                         "bananas": 124
                                     }})
        child.setEditorWidgetSetup(1, setup)
        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test1",
      "fldint":67,
      "foreignkey":123,
      "relation one":[{"x":"foo",
"y":"apples",
"z":321},
{"x":"bar",
"y":"apples",
"z":654}]
   }
}"""
        self.assertEqual(exporter.exportFeature(pf1), expected)

        # test excluding related attributes
        exporter.setIncludeRelated(False)
        self.assertEqual(exporter.includeRelated(), False)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test2",
      "fldint":68,
      "foreignkey":124
   }
}"""
        self.assertEqual(exporter.exportFeature(pf2), expected)

        # test without vector layer set
        exporter.setIncludeRelated(True)
        exporter.setVectorLayer(None)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test2",
      "fldint":68,
      "foreignkey":124
   }
}"""
        self.assertEqual(exporter.exportFeature(pf2), expected)
class Print_utility(QObject):
    progressBarUpdated = pyqtSignal(int, int)

    HOME = os.environ['PYARCHINIT_HOME']
    FILEPATH = os.path.dirname(__file__)
    LAYER_STYLE_PATH = '{}{}{}{}'.format(FILEPATH, os.sep, 'styles', os.sep)
    LAYER_STYLE_PATH_SPATIALITE = '{}{}{}{}'.format(FILEPATH, os.sep,
                                                    'styles_spatialite',
                                                    os.sep)
    SRS = 3004

    layerUS = ""
    layerQuote = ""
    ##	layerCL = ""
    ##	layerGriglia = "" #sperimentale da riattivare

    USLayerId = ""
    CLayerId = ""
    QuoteLayerId = ""
    GrigliaLayerId = ""

    mapHeight = ""
    mapWidth = ""

    tav_num = ""
    us = ""
    uri = ""

    def __init__(self, iface, data):
        super().__init__()
        self.iface = iface
        self.data = data
        # self.area = area
        # self.us = us
        self.canvas = self.iface.mapCanvas()

    # set host name, port, database name, username and password
    """
    def on_pushButton_runTest_pressed(self):
        self.first_batch_try()
    """

    def first_batch_try(self, server):

        if server == 'postgres':
            for i in range(len(self.data)):
                test = self.charge_layer_postgis(self.data[i].sito,
                                                 self.data[i].area,
                                                 self.data[i].us)
                self.us = self.data[i].us
                if test != 0:
                    if self.layerUS.featureCount() > 0:
                        self.test_bbox()
                        tav_num = i
                        self.print_map(tav_num)
                        self.progressBarUpdated.emit(i, len(self.data) - 1)
                        QApplication.processEvents()
                    else:
                        self.remove_layer()
                if test == 0:
                    Report_path = '{}{}{}'.format(
                        self.HOME, os.sep,
                        "pyarchinit_Report_folder/report_errori.txt")
                    f = open(Report_path, "w")
                    f.write(str("Presenza di errori nel layer"))
                    f.close()

        elif server == 'sqlite':
            for i in range(len(self.data)):
                test = self.charge_layer_sqlite(self.data[i].sito,
                                                self.data[i].area,
                                                self.data[i].us)
                self.us = self.data[i].us
                if test != 0:
                    if self.layerUS.featureCount() > 0:
                        self.test_bbox()
                        tav_num = i
                        self.print_map(tav_num)
                        self.progressBarUpdated.emit(i, len(self.data) - 1)
                        QApplication.processEvents()
                    else:
                        self.remove_layer()
                else:
                    pass

    def converter_1_20(self, n):
        n *= 100
        res = n / 20
        return res

    def test_bbox(self):
        # f = open("/test_type.txt", "w")
        # ff.write(str(type(self.layerUS)))
        # ff.close()

        self.layerUS.select([])  # recuperi tutte le geometrie senza attributi
        #  featPoly = QgsFeature()  # crei una feature vuota per il poligono

        dizionario_id_contains = {}
        lista_quote = []

        it = self.layerUS.getFeatures()
        featPoly = next(
            it
        )  # cicli sulle feature recuperate, featPoly conterra la feature poligonale attuale
        bbox = featPoly.geometry().boundingBox(
        )  # recupera i punti nel bbox del poligono
        self.height = self.converter_1_20(float(
            bbox.height())) * 10  # la misura da cm e' portata in mm
        self.width = self.converter_1_20(float(
            bbox.width())) * 10  # la misura da cm e' portata in mm

        # f = open("/test_paper_size_5.txt", "w")
        # f.write(str(self.width))
        # f.close()

    def getMapExtentFromMapCanvas(self, mapWidth, mapHeight, scale):
        # code from easyPrint plugin
        # print "in methode: " + str(scale)

        xmin = self.canvas.extent().xMinimum()
        xmax = self.canvas.extent().xMaximum()
        ymin = self.canvas.extent().yMinimum()
        ymax = self.canvas.extent().yMaximum()
        xcenter = xmin + (xmax - xmin) / 2
        ycenter = ymin + (ymax - ymin) / 2

        mapWidth = mapWidth * scale / 1000  # misura in punti
        mapHeight = mapHeight * scale / 1000  # misura in punti

        # f = open("/test_paper_size_3.txt", "w")
        # f.write(str(mapWidth))
        # f.close()

        minx = xcenter - mapWidth / 2
        miny = ycenter - mapHeight / 2
        maxx = xcenter + mapWidth / 2
        maxy = ycenter + mapHeight / 2

        return QgsRectangle(minx, miny, maxx, maxy)

    def print_map(self, tav_num):
        self.tav_num = tav_num

        p = QgsProject.instance()
        crs = QgsCoordinateReferenceSystem()
        crs.createFromSrid(self.SRS)
        p.setCrs(crs)

        l = QgsLayout(p)
        l.initializeDefaults()
        page = l.pageCollection().page(0)

        # map - this item tells the libraries where to put the map itself. Here we create a map and stretch it over the whole paper size:
        x, y = 0, 0  # angolo 0, o in alto a sx

        if (0 <= self.width <= 297) and (0 <= self.height <= 210):
            width, height = 297, 210  # Formato A4 Landscape
        elif (0 <= self.height <= 297) and (0 <= self.width <= 210):
            width, height = 210, 297  # Formato A4

        elif (0 <= self.width <= 420) and (0 <= self.height <= 297):
            width, height = 297, 420  # Formato A3 Landscape
        elif (0 <= self.height <= 420) and (0 <= self.width <= 297):
            width, height = 240, 297  # Formato A4

        elif (0 <= self.width <= 1189) and (0 <= self.height <= 841):
            width, height = 1189, 841  # Formato A0 Landscape
        elif (0 <= self.height <= 1189) and (0 <= self.width <= 841):
            width, height = 841, 1189  # Formato A0
        else:
            width, height = self.width * 1.2, self.height * 1.2  # self.width*10, self.height*10 da un valore alla larghezza e altezza del foglio aumentato di 5 per dare un margine

        size = QgsLayoutSize(width, height)
        page.setPageSize(size)

        map = QgsLayoutItemMap(l)

        rect = self.getMapExtentFromMapCanvas(page.pageSize().width(),
                                              page.pageSize().height(), 20.0)

        map.attemptSetSceneRect(
            QRectF(0, 0,
                   page.pageSize().width(),
                   page.pageSize().height()))
        map.setExtent(rect)
        map.setLayers([self.layerUS])
        l.setReferenceMap(map)
        l.addLayoutItem(map)

        intestazioneLabel = QgsLayoutItemLabel(l)
        txt = "Tavola %s - US:%d" % (self.tav_num + 1, self.us)
        intestazioneLabel.setText(txt)
        intestazioneLabel.adjustSizeToText()
        intestazioneLabel.attemptMove(QgsLayoutPoint(1, 0), page=0)
        intestazioneLabel.setFrameEnabled(False)
        l.addLayoutItem(intestazioneLabel)

        scaleLabel = QgsLayoutItemLabel(l)
        txt = "Scala: "
        scaleLabel.setText(txt)
        scaleLabel.adjustSizeToText()
        scaleLabel.attemptMove(QgsLayoutPoint(1, 5), page=0)
        scaleLabel.setFrameEnabled(False)
        l.addLayoutItem(scaleLabel)

        # aggiunge la scale bar
        scaleBarItem = QgsLayoutItemScaleBar(l)
        scaleBarItem.setStyle('Numeric')  # optionally modify the style
        scaleBarItem.setLinkedMap(map)
        scaleBarItem.applyDefaultSize()
        scaleBarItem.attemptMove(QgsLayoutPoint(10, 5), page=0)
        scaleBarItem.setFrameEnabled(False)
        l.addLayoutItem(scaleBarItem)

        le = QgsLayoutExporter(l)
        settings = QgsLayoutExporter.ImageExportSettings()
        settings.dpi = 100

        MAPS_path = '{}{}{}'.format(self.HOME, os.sep,
                                    "pyarchinit_MAPS_folder")
        tav_name = "Tavola_{}_us_{}.png".format(self.tav_num + 1, self.us)
        filename_png = '{}{}{}'.format(MAPS_path, os.sep, tav_name)

        le.exportToImage(filename_png, settings)

        self.remove_layer()

    def open_connection_postgis(self):
        cfg_rel_path = os.path.join(os.sep, 'pyarchinit_DB_folder',
                                    'config.cfg')
        file_path = '{}{}'.format(self.HOME, cfg_rel_path)
        conf = open(file_path, "r")
        con_sett = conf.read()
        conf.close()
        settings = Settings(con_sett)
        settings.set_configuration()
        self.uri = QgsDataSourceUri()
        self.uri.setConnection(settings.HOST, settings.PORT, settings.DATABASE,
                               settings.USER, settings.PASSWORD)

    def remove_layer(self):
        if self.USLayerId != "":
            QgsProject.instance().removeMapLayer(self.USLayerId)
            self.USLayerId = ""

        if self.QuoteLayerId != "":
            QgsProject.instance().removeMapLayer(self.QuoteLayerId)
            self.QuoteLayerId = ""

    def charge_layer_sqlite(self, sito, area, us):
        sqliteDB_path = os.path.join(os.sep, 'pyarchinit_DB_folder',
                                     'pyarchinit_db.sqlite')

        db_file_path = '{}{}'.format(self.HOME, sqliteDB_path)

        srs = QgsCoordinateReferenceSystem(
            3004, QgsCoordinateReferenceSystem.PostgisCrsId)

        gidstr = "scavo_s = '%s' and area_s = '%s' and us_s = '%d'" % (
            sito, area, us)

        uri = QgsDataSourceUri()
        uri.setDatabase(db_file_path)

        uri.setDataSource('', 'pyarchinit_us_view', 'the_geom', gidstr,
                          "ROWID")
        self.layerUS = QgsVectorLayer(uri.uri(), 'pyarchinit_us_view',
                                      'spatialite')

        if self.layerUS.isValid():
            self.layerUS.setCrs(srs)
            self.USLayerId = self.layerUS.id()
            # self.mapLayerRegistry.append(USLayerId)
            style_path = '{}{}'.format(self.LAYER_STYLE_PATH_SPATIALITE,
                                       'us_view.qml')
            self.layerUS.loadNamedStyle(style_path)
            self.iface.mapCanvas().setExtent(self.layerUS.extent())
            QgsProject.instance().addMapLayer(self.layerUS, True)
        else:
            QMessageBox.warning(None, "Errore", "Non Valido", QMessageBox.Ok)
            return 0
            # QMessageBox.warning(self, "Messaggio", "Geometria inesistente", QMessageBox.Ok)

        gidstr = "sito_q = '%s' and area_q = '%s' and us_q = '%d'" % (sito,
                                                                      area, us)

        uri.setDataSource('', 'pyarchinit_quote_view', 'the_geom', gidstr,
                          "ROWID")
        self.layerQuote = QgsVectorLayer(uri.uri(), 'pyarchinit_quote_view',
                                         'spatialite')

        if self.layerQuote.isValid():
            self.layerQuote.setCrs(srs)
            self.QuoteLayerId = self.layerQuote.id()
            # self.mapLayerRegistry.append(QuoteLayerId)
            style_path = '{}{}'.format(self.LAYER_STYLE_PATH_SPATIALITE,
                                       'stile_quote.qml')
            self.layerQuote.loadNamedStyle(style_path)
            QgsProject.instance().addMapLayer(self.layerQuote, True)

    def charge_layer_postgis(self, sito, area, us):
        self.open_connection_postgis()

        srs = QgsCoordinateReferenceSystem(
            3004, QgsCoordinateReferenceSystem.PostgisCrsId)

        gidstr = "scavo_s = '%s' and area_s = '%s' and us_s = '%d'" % (
            sito, area, us)

        self.uri.setDataSource("public", "pyarchinit_us_view", "the_geom",
                               gidstr, 'gid')

        self.layerUS = QgsVectorLayer(self.uri.uri(), "US", "postgres")

        if self.layerUS.isValid():
            self.layerUS.setCrs(srs)
            self.USLayerId = self.layerUS.id()
            # self.mapLayerRegistry.append(USLayerId)
            style_path = '{}{}'.format(self.LAYER_STYLE_PATH,
                                       'us_caratterizzazioni.qml')
            self.layerUS.loadNamedStyle(style_path)
            self.iface.mapCanvas().setExtent(self.layerUS.extent())
            QgsProject.instance().addMapLayer(self.layerUS, True)
        else:
            return 0

        gidstr = "sito_q = '%s' and area_q = '%s' and us_q = '%d'" % (sito,
                                                                      area, us)

        self.uri.setDataSource("public", "pyarchinit_quote", "the_geom",
                               gidstr, 'gid')
        self.layerQuote = QgsVectorLayer(self.uri.uri(), "Quote", "postgres")

        if self.layerQuote.isValid():
            self.layerQuote.setCrs(srs)
            self.QuoteLayerId = self.layerQuote.id()
            # self.mapLayerRegistry.append(QuoteLayerId)
            style_path = '{}{}'.format(self.LAYER_STYLE_PATH,
                                       'stile_quote.qml')
            self.layerQuote.loadNamedStyle(style_path)
            QgsProject.instance().addMapLayer(self.layerQuote, True)
Exemple #40
0
class TestQgsEditFormConfig(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        QgsGui.editorWidgetRegistry().initEditors()

        # Bring up a simple HTTP server
        os.chdir(unitTestDataPath() + '')
        handler = http.server.SimpleHTTPRequestHandler

        cls.httpd = socketserver.TCPServer(('localhost', 0), handler)
        cls.port = cls.httpd.server_address[1]

        cls.httpd_thread = threading.Thread(target=cls.httpd.serve_forever)
        cls.httpd_thread.setDaemon(True)
        cls.httpd_thread.start()

    def createLayer(self):
        self.layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                                    "addfeat", "memory")
        return self.layer

    def testReadWriteXml(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        config.setReadOnly(0, True)
        config.setReadOnly(1, False)
        config.setLabelOnTop(0, False)
        config.setLabelOnTop(1, True)

        doc = QDomDocument("testdoc")
        elem = doc.createElement('edit')
        config.writeXml(elem, QgsReadWriteContext())

        layer2 = self.createLayer()
        config2 = layer2.editFormConfig()
        config2.readXml(elem, QgsReadWriteContext())

        self.assertTrue(config2.readOnly(0))
        self.assertFalse(config2.readOnly(1))
        self.assertFalse(config2.labelOnTop(0))
        self.assertTrue(config2.labelOnTop(1))

    def testFormUi(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        config.setLayout(QgsEditFormConfig.GeneratedLayout)
        self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout)

        uiLocal = os.path.join(
            unitTestDataPath(), '/qgis_local_server/layer_attribute_form.ui')
        config.setUiForm(uiLocal)
        self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout)

        config.setLayout(QgsEditFormConfig.GeneratedLayout)
        self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout)

        uiUrl = 'http://localhost:' + \
            str(self.port) + '/qgis_local_server/layer_attribute_form.ui'
        config.setUiForm(uiUrl)
        self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout)
        content = QgsApplication.networkContentFetcherRegistry().fetch(uiUrl)
        self.assertTrue(content is not None)
        while True:
            if content.status() in (QgsFetchedContent.Finished, QgsFetchedContent.Failed):
                break
            app.processEvents()
        self.assertEqual(content.status(), QgsFetchedContent.Finished)

    def testReadOnly(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        # safety checks
        config.setReadOnly(-1, True)
        config.setReadOnly(100, True)

        # real checks
        config.setReadOnly(0, True)
        config.setReadOnly(1, True)
        self.assertTrue(config.readOnly(0))
        self.assertTrue(config.readOnly(1))

        config.setReadOnly(0, False)
        config.setReadOnly(1, False)
        self.assertFalse(config.readOnly(0))
        self.assertFalse(config.readOnly(1))

    def testLabelOnTop(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        # safety checks
        config.setLabelOnTop(-1, True)
        config.setLabelOnTop(100, True)

        # real checks
        config.setLabelOnTop(0, True)
        config.setLabelOnTop(1, True)
        self.assertTrue(config.labelOnTop(0))
        self.assertTrue(config.labelOnTop(1))

        config.setLabelOnTop(0, False)
        config.setLabelOnTop(1, False)
        self.assertFalse(config.labelOnTop(0))
        self.assertFalse(config.labelOnTop(1))

    def test_backgroundColorSerialize(self):
        """Test backgroundColor serialization"""

        layer = self.createLayer()
        config = layer.editFormConfig()
        color_name = '#ff00ff'
        container = QgsAttributeEditorContainer('container name', None, QColor('#ff00ff'))
        doc = QDomDocument()
        element = container.toDomElement(doc)
        config = QgsEditFormConfig()
        container2 = config.attributeEditorElementFromDomElement(element, None, self.layer.id())
        self.assertEqual(container2.backgroundColor().name(), color_name)
    def test_representValue(self):

        first_layer = QgsVectorLayer("none?field=foreign_key:integer",
                                     "first_layer", "memory")
        self.assertTrue(first_layer.isValid())
        second_layer = QgsVectorLayer(
            "none?field=pkid:integer&field=decoded:string", "second_layer",
            "memory")
        self.assertTrue(second_layer.isValid())
        QgsProject.instance().addMapLayers([first_layer, second_layer])
        f = QgsFeature()
        f.setAttributes([123])
        first_layer.dataProvider().addFeatures([f])
        f = QgsFeature()
        f.setAttributes([123, 'decoded_val'])
        second_layer.dataProvider().addFeatures([f])

        relMgr = QgsProject.instance().relationManager()

        fieldFormatter = QgsRelationReferenceFieldFormatter()

        rel = QgsRelation()
        rel.setId('rel1')
        rel.setName('Relation Number One')
        rel.setReferencingLayer(first_layer.id())
        rel.setReferencedLayer(second_layer.id())
        rel.addFieldPair('foreign_key', 'pkid')
        self.assertTrue(rel.isValid())

        relMgr.addRelation(rel)

        # Everything valid
        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            'decoded_val')

        # Code not find match in foreign layer
        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '456'),
            '456')

        # Invalid relation id
        config = {'Relation': 'invalid'}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            '123')

        # No display expression
        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression(None)
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            '123')

        # Invalid display expression
        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression('invalid +')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            '123')

        # Missing relation
        config = {}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            '123')

        # Inconsistent layer provided to representValue()
        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(second_layer, 0, config, None,
                                          '123'), '123')

        # Inconsistent idx provided to representValue()
        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 1, config, None, '123'),
            '123')

        # Invalid relation
        rel = QgsRelation()
        rel.setId('rel2')
        rel.setName('Relation Number Two')
        rel.setReferencingLayer(first_layer.id())
        rel.addFieldPair('foreign_key', 'pkid')
        self.assertFalse(rel.isValid())

        relMgr.addRelation(rel)

        config = {'Relation': rel.id()}
        second_layer.setDisplayExpression('decoded')
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            '123')

        QgsProject.instance().removeAllMapLayers()
    def test_representValue(self):

        first_layer = QgsVectorLayer("none?field=foreign_key:integer",
                                     "first_layer", "memory")
        self.assertTrue(first_layer.isValid())
        second_layer = QgsVectorLayer(
            "none?field=pkid:integer&field=decoded:string", "second_layer",
            "memory")
        self.assertTrue(second_layer.isValid())
        QgsProject.instance().addMapLayer(second_layer)
        f = QgsFeature()
        f.setAttributes([123])
        first_layer.dataProvider().addFeatures([f])
        f = QgsFeature()
        f.setAttributes([123, 'decoded_val'])
        second_layer.dataProvider().addFeatures([f])

        fieldFormatter = QgsValueRelationFieldFormatter()

        # Everything valid
        config = {
            'Layer': second_layer.id(),
            'Key': 'pkid',
            'Value': 'decoded'
        }
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '123'),
            'decoded_val')

        # Code not find match in foreign layer
        config = {
            'Layer': second_layer.id(),
            'Key': 'pkid',
            'Value': 'decoded'
        }
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '456'),
            '(456)')

        # Missing Layer
        config = {'Key': 'pkid', 'Value': 'decoded'}
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '456'),
            '(456)')

        # Invalid Layer
        config = {'Layer': 'invalid', 'Key': 'pkid', 'Value': 'decoded'}
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '456'),
            '(456)')

        # Invalid Key
        config = {
            'Layer': second_layer.id(),
            'Key': 'invalid',
            'Value': 'decoded'
        }
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '456'),
            '(456)')

        # Invalid Value
        config = {
            'Layer': second_layer.id(),
            'Key': 'pkid',
            'Value': 'invalid'
        }
        self.assertEqual(
            fieldFormatter.representValue(first_layer, 0, config, None, '456'),
            '(456)')

        QgsProject.instance().removeMapLayer(second_layer.id())
    def testMasterLayerOrder(self):
        """ test master layer order"""
        prj = QgsProject.instance()
        prj.clear()
        layer = QgsVectorLayer("Point?field=fldtxt:string",
                               "layer1", "memory")
        layer2 = QgsVectorLayer("Point?field=fldtxt:string",
                                "layer2", "memory")
        layer3 = QgsVectorLayer("Point?field=fldtxt:string",
                                "layer3", "memory")
        prj.addMapLayers([layer, layer2, layer3])

        prj.layerTreeRoot().setHasCustomLayerOrder(True)
        prj.layerTreeRoot().setCustomLayerOrder([layer2, layer])
        self.assertEqual(prj.mapThemeCollection().masterLayerOrder(), [layer2, layer])

        prj.layerTreeRoot().setCustomLayerOrder([layer, layer2, layer3])
        # make some themes...
        theme1 = QgsMapThemeCollection.MapThemeRecord()
        theme1.setLayerRecords([QgsMapThemeCollection.MapThemeLayerRecord(layer3),
                                QgsMapThemeCollection.MapThemeLayerRecord(layer)])

        theme2 = QgsMapThemeCollection.MapThemeRecord()
        theme2.setLayerRecords([QgsMapThemeCollection.MapThemeLayerRecord(layer3),
                                QgsMapThemeCollection.MapThemeLayerRecord(layer2),
                                QgsMapThemeCollection.MapThemeLayerRecord(layer)])

        theme3 = QgsMapThemeCollection.MapThemeRecord()
        theme3.setLayerRecords([QgsMapThemeCollection.MapThemeLayerRecord(layer2),
                                QgsMapThemeCollection.MapThemeLayerRecord(layer)])

        prj.mapThemeCollection().insert('theme1', theme1)
        prj.mapThemeCollection().insert('theme2', theme2)
        prj.mapThemeCollection().insert('theme3', theme3)

        #order of layers in theme should respect master order
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme1'), [layer, layer3])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme2'), [layer, layer2, layer3])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme3'), [layer, layer2])

        # also check ids!
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme1'), [layer.id(), layer3.id()])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme2'), [layer.id(), layer2.id(), layer3.id()])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme3'), [layer.id(), layer2.id()])

        # reset master order
        prj.layerTreeRoot().setCustomLayerOrder([layer2, layer3, layer])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme1'), [layer3, layer])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme2'), [layer2, layer3, layer])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme3'), [layer2, layer])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme1'), [layer3.id(), layer.id()])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme2'), [layer2.id(), layer3.id(), layer.id()])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme3'), [layer2.id(), layer.id()])

        # check that layers include those hidden in the layer tree
        canvas = QgsMapCanvas()
        bridge = QgsLayerTreeMapCanvasBridge(prj.layerTreeRoot(), canvas)
        root = prj.layerTreeRoot()
        layer_node = root.findLayer(layer2.id())
        layer_node.setItemVisibilityChecked(False)
        app.processEvents()
        prj.layerTreeRoot().setHasCustomLayerOrder(False)
        self.assertEqual(prj.mapThemeCollection().masterLayerOrder(), [layer, layer2, layer3])

        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme1'), [layer, layer3])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme2'), [layer, layer2, layer3])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayers('theme3'), [layer, layer2])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme1'), [layer.id(), layer3.id()])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme2'),
                         [layer.id(), layer2.id(), layer3.id()])
        self.assertEqual(prj.mapThemeCollection().mapThemeVisibleLayerIds('theme3'), [layer.id(), layer2.id()])
Exemple #44
0
class TestQgsEditFormConfig(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        QgsGui.editorWidgetRegistry().initEditors()
        QgsSettings().clear()

        # Bring up a simple HTTP server
        os.chdir(unitTestDataPath() + '')
        handler = http.server.SimpleHTTPRequestHandler

        cls.httpd = socketserver.TCPServer(('localhost', 0), handler)
        cls.port = cls.httpd.server_address[1]

        cls.httpd_thread = threading.Thread(target=cls.httpd.serve_forever)
        cls.httpd_thread.setDaemon(True)
        cls.httpd_thread.start()

    def createLayer(self):
        self.layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer", "addfeat",
            "memory")
        f = QgsFeature()
        pr = self.layer.dataProvider()
        assert pr.addFeatures([f])
        return self.layer

    def testReadWriteXml(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        config.setReadOnly(0, True)
        config.setReadOnly(1, False)
        config.setLabelOnTop(0, False)
        config.setLabelOnTop(1, True)

        doc = QDomDocument("testdoc")
        elem = doc.createElement('edit')
        config.writeXml(elem, QgsReadWriteContext())

        layer2 = self.createLayer()
        config2 = layer2.editFormConfig()
        config2.readXml(elem, QgsReadWriteContext())

        self.assertTrue(config2.readOnly(0))
        self.assertFalse(config2.readOnly(1))
        self.assertFalse(config2.labelOnTop(0))
        self.assertTrue(config2.labelOnTop(1))

    def testFormUi(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        config.setLayout(QgsEditFormConfig.GeneratedLayout)
        self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout)

        uiLocal = os.path.join(unitTestDataPath(),
                               '/qgis_local_server/layer_attribute_form.ui')
        config.setUiForm(uiLocal)
        self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout)

        config.setLayout(QgsEditFormConfig.GeneratedLayout)
        self.assertEqual(config.layout(), QgsEditFormConfig.GeneratedLayout)

        uiUrl = 'http://localhost:' + \
            str(self.port) + '/qgis_local_server/layer_attribute_form.ui'
        config.setUiForm(uiUrl)
        self.assertEqual(config.layout(), QgsEditFormConfig.UiFileLayout)
        content = QgsApplication.networkContentFetcherRegistry().fetch(
            uiUrl, QgsNetworkContentFetcherRegistry.DownloadImmediately)
        self.assertTrue(content is not None)
        while True:
            if content.status() in (QgsFetchedContent.Finished,
                                    QgsFetchedContent.Failed):
                break
            app.processEvents()
        self.assertEqual(content.status(), QgsFetchedContent.Finished)

    # Failing on Travis, seg fault in event loop, no idea why
    """
    @unittest.expectedFailure
    def testFormPy(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        config.setInitCodeSource(QgsEditFormConfig.CodeSourceFile)

        uiLocal = os.path.join(
            unitTestDataPath(), 'qgis_local_server/layer_attribute_form.ui')
        config.setUiForm(uiLocal)

        pyUrl = 'http://localhost:' + \
            str(self.port) + '/qgis_local_server/layer_attribute_form.py'

        QgsSettings().setEnumValue('qgis/enableMacros', Qgis.Always)

        config.setInitFilePath(pyUrl)
        config.setInitFunction('formOpen')

        content = QgsApplication.networkContentFetcherRegistry().fetch(pyUrl, QgsNetworkContentFetcherRegistry.DownloadImmediately)
        self.assertTrue(content is not None)
        while True:
            if content.status() in (QgsFetchedContent.Finished, QgsFetchedContent.Failed):
                break
            app.processEvents()
        self.assertEqual(content.status(), QgsFetchedContent.Finished)

        layer.setEditFormConfig(config)
        form = QgsAttributeForm(layer, next(layer.getFeatures()))
        label = form.findChild(QLabel, 'label')
        self.assertIsNotNone(label)
        self.assertEqual(label.text(), 'Flying Monkey')
    """

    def testReadOnly(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        # safety checks
        config.setReadOnly(-1, True)
        config.setReadOnly(100, True)

        # real checks
        config.setReadOnly(0, True)
        config.setReadOnly(1, True)
        self.assertTrue(config.readOnly(0))
        self.assertTrue(config.readOnly(1))

        config.setReadOnly(0, False)
        config.setReadOnly(1, False)
        self.assertFalse(config.readOnly(0))
        self.assertFalse(config.readOnly(1))

    def testLabelOnTop(self):
        layer = self.createLayer()
        config = layer.editFormConfig()

        # safety checks
        config.setLabelOnTop(-1, True)
        config.setLabelOnTop(100, True)

        # real checks
        config.setLabelOnTop(0, True)
        config.setLabelOnTop(1, True)
        self.assertTrue(config.labelOnTop(0))
        self.assertTrue(config.labelOnTop(1))

        config.setLabelOnTop(0, False)
        config.setLabelOnTop(1, False)
        self.assertFalse(config.labelOnTop(0))
        self.assertFalse(config.labelOnTop(1))

    def test_backgroundColorSerialize(self):
        """Test backgroundColor serialization"""

        layer = self.createLayer()
        config = layer.editFormConfig()
        color_name = '#ff00ff'
        container = QgsAttributeEditorContainer('container name', None,
                                                QColor('#ff00ff'))
        doc = QDomDocument()
        element = container.toDomElement(doc)
        config = QgsEditFormConfig()
        container2 = config.attributeEditorElementFromDomElement(
            element, None, self.layer.id())
        self.assertEqual(container2.backgroundColor().name(), color_name)
    def test_Join(self):
        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "points.shp"), "points", "ogr", QgsVectorLayer.LayerOptions(False))
        self.assertEqual(l1.isValid(), True)
        QgsProject.instance().addMapLayer(l1)
        l2 = QgsVectorLayer(os.path.join(self.testDataDir, "points_relations.shp"), "points_relations", "ogr", QgsVectorLayer.LayerOptions(False))
        self.assertEqual(l2.isValid(), True)
        QgsProject.instance().addMapLayer(l2)
        ref_sum = sum(f.attributes()[1] for f in l2.getFeatures())

        # use a temporary file
        query = toPercent("select id,Pilots,vtab1.geometry from vtab1,vtab2 where intersects(vtab1.geometry,vtab2.geometry)")
        l3 = QgsVectorLayer("?layer_ref=%s&layer_ref=%s&uid=id&query=%s&geometry=geometry:1:4326" % (l1.id(), l2.id(), query), "vtab", "virtual", QgsVectorLayer.LayerOptions(False))
        self.assertEqual(l3.isValid(), True)
        self.assertEqual(l3.dataProvider().wkbType(), 1)
        self.assertEqual(l3.dataProvider().fields().count(), 2)
        ref_sum2 = sum(f.id() for f in l3.getFeatures())
        self.assertEqual(ref_sum, ref_sum2)

        QgsProject.instance().removeMapLayer(l1)
        QgsProject.instance().removeMapLayer(l2)
Exemple #46
0
    def test_joined_layers_conversion(self):
        v1 = QgsVectorLayer(
            "Point?field=id:integer&field=b_id:integer&field=c_id:integer&field=name:string",
            "A", "memory")
        self.assertEqual(v1.isValid(), True)
        v2 = QgsVectorLayer(
            "Point?field=id:integer&field=bname:string&field=bfield:integer",
            "B", "memory")
        self.assertEqual(v2.isValid(), True)
        v3 = QgsVectorLayer("Point?field=id:integer&field=cname:string", "C",
                            "memory")
        self.assertEqual(v3.isValid(), True)
        QgsProject.instance().addMapLayers([v1, v2, v3])
        joinInfo = QgsVectorLayerJoinInfo()
        joinInfo.setTargetFieldName("b_id")
        joinInfo.setJoinLayer(v2)
        joinInfo.setJoinFieldName("id")
        #joinInfo.setPrefix("B_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)

        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))

        # with a field subset
        v1.removeJoin(v2.id())
        joinInfo.setJoinFieldNamesSubset(["bname"])
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 5)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))
        joinInfo.setJoinFieldNamesSubset(None)

        # add a table prefix to the join
        v1.removeJoin(v2.id())
        joinInfo.setPrefix("BB_")
        v1.addJoin(joinInfo)
        self.assertEqual(len(v1.fields()), 6)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(
            df.query(),
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS BB_bname, j1.bfield AS BB_bfield FROM {} AS t LEFT JOIN {} AS j1 ON t."b_id"=j1."id"'
            .format(v1.id(), v2.id()))
        joinInfo.setPrefix("")
        v1.removeJoin(v2.id())
        v1.addJoin(joinInfo)

        # add another join
        joinInfo2 = QgsVectorLayerJoinInfo()
        joinInfo2.setTargetFieldName("c_id")
        joinInfo2.setJoinLayer(v3)
        joinInfo2.setJoinFieldName("id")
        v1.addJoin(joinInfo2)
        self.assertEqual(len(v1.fields()), 7)
        df = QgsVirtualLayerDefinitionUtils.fromJoinedLayer(v1)
        self.assertEqual(df.query(), (
            'SELECT t.rowid AS uid, t.id, t.b_id, t.c_id, t.name, j1.bname AS B_bname, j1.bfield AS B_bfield, j2.cname AS C_cname FROM {} AS t '
            + 'LEFT JOIN {} AS j1 ON t."b_id"=j1."id" ' +
            'LEFT JOIN {} AS j2 ON t."c_id"=j2."id"').format(
                v1.id(), v2.id(), v3.id()))

        QgsProject.instance().removeMapLayers([v1.id(), v2.id(), v3.id()])
Exemple #47
0
class TestQgsSymbolExpressionVariables(unittest.TestCase):
    def setUp(self):
        myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp')
        self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(self.layer)

        self.iface = get_iface()
        rendered_layers = [self.layer.id()]
        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)

    def tearDown(self):
        QgsMapLayerRegistry.instance().removeAllMapLayers()

    def testPartNum(self):
        # Create rulebased style
        sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f'})

        renderer = QgsSingleSymbolRenderer(sym1)
        renderer.symbols(
            QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty(
                'color',
                QgsDataDefined(
                    'color_rgb( (@geometry_part_num - 1) * 200, 0, 0 )'))
        self.layer.setRenderer(renderer)

        # Setup rendering check
        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_geometry_part_num')
        result = renderchecker.runTest('part_geometry_part_num')

        self.assertTrue(result)

    def testPartCount(self):
        # Create rulebased style
        sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f'})

        renderer = QgsSingleSymbolRenderer(sym1)
        renderer.symbols(
            QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty(
                'color',
                QgsDataDefined(
                    'color_rgb( (@geometry_part_count - 1) * 200, 0, 0 )'))
        self.layer.setRenderer(renderer)

        # Setup rendering check
        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_geometry_part_count')
        result = renderchecker.runTest('part_geometry_part_count')

        self.assertTrue(result)

    def testSymbolColor(self):
        # Create rulebased style
        sym1 = QgsFillSymbol.createSimple({'color': '#ff0000'})

        renderer = QgsSingleSymbolRenderer(sym1)
        renderer.symbols(
            QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty(
                'color',
                QgsDataDefined(
                    'set_color_part( @symbol_color, \'value\', "Value" * 4)'))
        self.layer.setRenderer(renderer)

        # Setup rendering check
        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_symbol_color_variable')
        result = renderchecker.runTest('symbol_color_variable', 50)

        self.assertTrue(result)
Exemple #48
0
    def testMapTheme(self):
        canvas = QgsMapCanvas()
        canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326))
        canvas.setFrameStyle(0)
        canvas.resize(600, 400)
        self.assertEqual(canvas.width(), 600)
        self.assertEqual(canvas.height(), 400)

        layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string",
                               "layer", "memory")
        # add a polygon to layer
        f = QgsFeature()
        f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45)))
        self.assertTrue(layer.dataProvider().addFeatures([f]))

        # create a style
        sym1 = QgsFillSymbol.createSimple({'color': '#ffb200'})
        renderer = QgsSingleSymbolRenderer(sym1)
        layer.setRenderer(renderer)

        canvas.setLayers([layer])
        canvas.setExtent(QgsRectangle(10, 30, 20, 35))
        canvas.show()

        # need to wait until first redraw can occur (note that we first need to wait till drawing starts!)
        while not canvas.isDrawing():
            app.processEvents()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas))

        # add some styles
        layer.styleManager().addStyleFromLayer('style1')
        sym2 = QgsFillSymbol.createSimple({'color': '#00b2ff'})
        renderer2 = QgsSingleSymbolRenderer(sym2)
        layer.setRenderer(renderer2)
        layer.styleManager().addStyleFromLayer('style2')

        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas))

        layer.styleManager().setCurrentStyle('style1')
        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas))

        # ok, so all good with setting/rendering map styles
        # try setting canvas to a particular theme

        # make some themes...
        theme1 = QgsMapThemeCollection.MapThemeRecord()
        record1 = QgsMapThemeCollection.MapThemeLayerRecord(layer)
        record1.currentStyle = 'style1'
        record1.usingCurrentStyle = True
        theme1.setLayerRecords([record1])

        theme2 = QgsMapThemeCollection.MapThemeRecord()
        record2 = QgsMapThemeCollection.MapThemeLayerRecord(layer)
        record2.currentStyle = 'style2'
        record2.usingCurrentStyle = True
        theme2.setLayerRecords([record2])

        QgsProject.instance().mapThemeCollection().insert('theme1', theme1)
        QgsProject.instance().mapThemeCollection().insert('theme2', theme2)

        canvas.setTheme('theme2')
        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme2', 'theme2', canvas))

        canvas.setTheme('theme1')
        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas))

        # add another layer
        layer2 = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string",
                                "layer2", "memory")
        f = QgsFeature()
        f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45)))
        self.assertTrue(layer2.dataProvider().addFeatures([f]))

        # create a style
        sym1 = QgsFillSymbol.createSimple({'color': '#b2ff00'})
        renderer = QgsSingleSymbolRenderer(sym1)
        layer2.setRenderer(renderer)

        # rerender canvas - should NOT show new layer
        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas))
        # test again - this time refresh all layers
        canvas.refreshAllLayers()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme1', 'theme1', canvas))

        # add layer 2 to theme1
        record3 = QgsMapThemeCollection.MapThemeLayerRecord(layer2)
        theme1.setLayerRecords([record3])
        QgsProject.instance().mapThemeCollection().update('theme1', theme1)

        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas))

        # change the appearance of an active style
        layer2.styleManager().addStyleFromLayer('original')
        layer2.styleManager().addStyleFromLayer('style4')
        record3.currentStyle = 'style4'
        record3.usingCurrentStyle = True
        theme1.setLayerRecords([record3])
        QgsProject.instance().mapThemeCollection().update('theme1', theme1)

        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme3', 'theme3', canvas))

        layer2.styleManager().setCurrentStyle('style4')
        sym3 = QgsFillSymbol.createSimple({'color': '#b200b2'})
        layer2.renderer().setSymbol(sym3)
        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas))

        # try setting layers while a theme is in place
        canvas.setLayers([layer])
        canvas.refresh()

        # should be no change... setLayers should be ignored if canvas is following a theme!
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas))

        # setLayerStyleOverrides while theme is in place
        canvas.setLayerStyleOverrides({layer2.id(): 'original'})
        # should be no change... setLayerStyleOverrides should be ignored if canvas is following a theme!
        canvas.refresh()
        canvas.waitWhileRendering()
        self.assertTrue(self.canvasImageCheck('theme4', 'theme4', canvas))

        # clear theme
        canvas.setTheme('')
        canvas.refresh()
        canvas.waitWhileRendering()
        # should be different - we should now render project layers
        self.assertFalse(self.canvasImageCheck('theme4', 'theme4', canvas))
class TestQgsPointDisplacementRenderer(unittest.TestCase):

    def setUp(self):
        myShpFile = os.path.join(TEST_DATA_DIR, 'points.shp')
        self.layer = QgsVectorLayer(myShpFile, 'Points', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(self.layer)

        self.renderer = QgsPointDisplacementRenderer()
        sym1 = QgsMarkerSymbol.createSimple({'color': '#ff00ff', 'size': '3', 'outline_style': 'no'})
        renderer = QgsSingleSymbolRenderer(sym1)
        self.renderer.setEmbeddedRenderer(renderer)
        self.renderer.setCircleRadiusAddition(2)
        self.renderer.setCircleWidth(1)
        self.renderer.setCircleColor(QColor(0, 0, 0))
        self.renderer.setCenterSymbol(QgsMarkerSymbol.createSimple({'color': '#ffff00', 'size': '3', 'outline_style': 'no'}))
        self.layer.setRenderer(self.renderer)

        rendered_layers = [self.layer.id()]
        self.mapsettings = QgsMapSettings()
        self.mapsettings.setOutputSize(QSize(400, 400))
        self.mapsettings.setOutputDpi(96)
        self.mapsettings.setExtent(QgsRectangle(-123, 18, -70, 52))
        self.mapsettings.setLayers(rendered_layers)

    def tearDown(self):
        QgsMapLayerRegistry.instance().removeAllMapLayers()

    def _setProperties(self, r):
        """ set properties for a renderer for testing with _checkProperties"""
        r.setLabelAttributeName('name')
        f = QgsFontUtils.getStandardTestFont('Bold Oblique', 14)
        r.setLabelFont(f)
        r.setMaxLabelScaleDenominator(50000)
        r.setLabelColor(QColor(255, 0, 0))
        r.setTolerance(5)
        r.setToleranceUnit(QgsUnitTypes.RenderMapUnits)
        r.setToleranceMapUnitScale(QgsMapUnitScale(5, 15))
        r.setCircleWidth(15)
        r.setCircleColor(QColor(0, 255, 0))
        r.setCircleRadiusAddition(2.5)
        r.setPlacement(QgsPointDisplacementRenderer.ConcentricRings)
        m = QgsMarkerSymbol()
        m.setColor(QColor(0, 255, 0))
        r.setCenterSymbol(m)
        sym1 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f'})
        renderer = QgsSingleSymbolRenderer(sym1)
        r.setEmbeddedRenderer(renderer)

    def _checkProperties(self, r):
        """ test properties of renderer against expected"""
        self.assertEqual(r.labelAttributeName(), 'name')
        f = QgsFontUtils.getStandardTestFont('Bold Oblique', 14)
        self.assertEqual(r.labelFont().styleName(), f.styleName())
        self.assertEqual(r.maxLabelScaleDenominator(), 50000)
        self.assertEqual(r.labelColor(), QColor(255, 0, 0))
        self.assertEqual(r.tolerance(), 5)
        self.assertEqual(r.toleranceUnit(), QgsUnitTypes.RenderMapUnits)
        self.assertEqual(r.toleranceMapUnitScale(), QgsMapUnitScale(5, 15))
        self.assertEqual(r.circleWidth(), 15)
        self.assertEqual(r.circleColor(), QColor(0, 255, 0))
        self.assertEqual(r.circleRadiusAddition(), 2.5)
        self.assertEqual(r.placement(), QgsPointDisplacementRenderer.ConcentricRings)
        self.assertEqual(r.centerSymbol().color(), QColor(0, 255, 0))
        self.assertEqual(r.embeddedRenderer().symbol().color().name(), '#fdbf6f')

    def testGettersSetters(self):
        """ test getters and setters """
        r = QgsPointDisplacementRenderer()
        self._setProperties(r)
        self._checkProperties(r)

    def testClone(self):
        """ test cloning renderer """
        r = QgsPointDisplacementRenderer()
        self._setProperties(r)
        c = r.clone()
        self._checkProperties(c)

    def testSaveCreate(self):
        """ test saving and recreating from XML """
        r = QgsPointDisplacementRenderer()
        self._setProperties(r)
        doc = QDomDocument("testdoc")
        elem = r.save(doc)
        c = QgsPointDisplacementRenderer.create(elem)
        self._checkProperties(c)

    def testConvert(self):
        """ test renderer conversion """

        # same type, should clone
        r = QgsPointDisplacementRenderer()
        self._setProperties(r)
        c = QgsPointDisplacementRenderer.convertFromRenderer(r)
        self._checkProperties(c)

        # test conversion from cluster renderer
        r = QgsPointClusterRenderer()
        r.setTolerance(5)
        r.setToleranceUnit(QgsUnitTypes.RenderMapUnits)
        r.setToleranceMapUnitScale(QgsMapUnitScale(5, 15))
        m = QgsMarkerSymbol()
        m.setColor(QColor(0, 255, 0))
        r.setClusterSymbol(m)
        sym1 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f'})
        renderer = QgsSingleSymbolRenderer(sym1)
        r.setEmbeddedRenderer(renderer)

        # want to keep as many settings as possible when converting between cluster and displacement renderer
        d = QgsPointDisplacementRenderer.convertFromRenderer(r)
        self.assertEqual(d.tolerance(), 5)
        self.assertEqual(d.toleranceUnit(), QgsUnitTypes.RenderMapUnits)
        self.assertEqual(d.toleranceMapUnitScale(), QgsMapUnitScale(5, 15))
        self.assertEqual(d.centerSymbol().color(), QColor(0, 255, 0))
        self.assertEqual(d.embeddedRenderer().symbol().color().name(), '#fdbf6f')

    def testRenderNoCluster(self):
        self.layer.renderer().setTolerance(1)
        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlPathPrefix('displacement_renderer')
        renderchecker.setControlName('expected_displacement_no_cluster')
        self.assertTrue(renderchecker.runTest('displacement_no_cluster'))

    def testRenderWithin(self):
        self.layer.renderer().setTolerance(10)
        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlPathPrefix('displacement_renderer')
        renderchecker.setControlName('expected_displacement_cluster')
        self.assertTrue(renderchecker.runTest('expected_displacement_cluster'))

    def testRenderVariables(self):
        """ test rendering with expression variables in marker """
        self.layer.renderer().setTolerance(10)

        old_marker = self.layer.renderer().centerSymbol().clone()

        new_marker = QgsMarkerSymbol.createSimple({'color': '#ffff00', 'size': '3', 'outline_style': 'no'})
        new_marker.symbolLayer(0).setDataDefinedProperty('color', QgsDataDefined('@cluster_color'))
        new_marker.symbolLayer(0).setDataDefinedProperty('size', QgsDataDefined('@cluster_size*2'))
        self.layer.renderer().setCenterSymbol(new_marker)
        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlPathPrefix('displacement_renderer')
        renderchecker.setControlName('expected_displacement_variables')
        result = renderchecker.runTest('expected_displacement_variables')
        self.layer.renderer().setCenterSymbol(old_marker)
        self.assertTrue(result)
Exemple #50
0
    def testDuplicateFeature(self):
        """ test duplicating a feature """

        project = QgsProject().instance()

        # LAYERS
        # - add first layer (parent)
        layer1 = QgsVectorLayer("Point?field=fldtxt:string&field=pkid:integer",
                                "parentlayer", "memory")
        # > check first layer (parent)
        self.assertTrue(layer1.isValid())
        # -  set the value for the copy
        layer1.setDefaultValueDefinition(1, QgsDefaultValue("rand(1000,2000)"))
        # > check first layer (parent)
        self.assertTrue(layer1.isValid())
        # - add second layer (child)
        layer2 = QgsVectorLayer(
            "Point?field=fldtxt:string&field=id:integer&field=foreign_key:integer",
            "childlayer", "memory")
        # > check second layer (child)
        self.assertTrue(layer2.isValid())
        # - add layers
        project.addMapLayers([layer1, layer2])

        # FEATURES
        # - add 2 features on layer1 (parent)
        l1f1orig = QgsFeature()
        l1f1orig.setFields(layer1.fields())
        l1f1orig.setAttributes(["F_l1f1", 100])
        l1f2orig = QgsFeature()
        l1f2orig.setFields(layer1.fields())
        l1f2orig.setAttributes(["F_l1f2", 101])
        # > check by adding features
        self.assertTrue(layer1.dataProvider().addFeatures([l1f1orig,
                                                           l1f2orig]))
        # add 4 features on layer2 (child)
        l2f1orig = QgsFeature()
        l2f1orig.setFields(layer2.fields())
        l2f1orig.setAttributes(["F_l2f1", 201, 100])
        l2f2orig = QgsFeature()
        l2f2orig.setFields(layer2.fields())
        l2f2orig.setAttributes(["F_l2f2", 202, 100])
        l2f3orig = QgsFeature()
        l2f3orig.setFields(layer2.fields())
        l2f3orig.setAttributes(["F_l2f3", 203, 100])
        l2f4orig = QgsFeature()
        l2f4orig.setFields(layer2.fields())
        l2f4orig.setAttributes(["F_l2f4", 204, 101])
        # > check by adding features
        self.assertTrue(layer2.dataProvider().addFeatures(
            [l2f1orig, l2f2orig, l2f3orig, l2f4orig]))

        # RELATION
        # - create the relationmanager
        relMgr = project.relationManager()
        # - create the relation
        rel = QgsRelation()
        rel.setId('rel1')
        rel.setName('childrel')
        rel.setReferencingLayer(layer2.id())
        rel.setReferencedLayer(layer1.id())
        rel.addFieldPair('foreign_key', 'pkid')
        rel.setStrength(QgsRelation.Composition)
        # > check relation
        self.assertTrue(rel.isValid())
        # - add relation
        relMgr.addRelation(rel)
        # > check if referencedLayer is layer1
        self.assertEqual(rel.referencedLayer(), layer1)
        # > check if referencingLayer is layer2
        self.assertEqual(rel.referencingLayer(), layer2)
        # > check if the layers are correct in relation when loading from relationManager
        relations = project.relationManager().relations()
        relation = relations[list(relations.keys())[0]]
        # > check if referencedLayer is layer1
        self.assertEqual(relation.referencedLayer(), layer1)
        # > check if referencingLayer is layer2
        self.assertEqual(relation.referencingLayer(), layer2)
        # > check the relatedfeatures
        '''
        # testoutput 1
        print( "\nAll Features and relations")
        featit=layer1.getFeatures()
        f=QgsFeature()
        while featit.nextFeature(f):
            print( f.attributes())
            childFeature = QgsFeature()
            relfeatit=rel.getRelatedFeatures(f)
            while relfeatit.nextFeature(childFeature):
                 print( childFeature.attributes() )
        print( "\n--------------------------")

        print( "\nFeatures on layer1")
        for f in layer1.getFeatures():
            print( f.attributes() )

        print( "\nFeatures on layer2")
        for f in layer2.getFeatures():
            print( f.attributes() )
        '''

        # DUPLICATION
        # - duplicate feature l1f1orig with children
        layer1.startEditing()
        results = QgsVectorLayerUtils.duplicateFeature(layer1, l1f1orig,
                                                       project, 0)

        # > check if name is name of duplicated (pk is different)
        result_feature = results[0]
        self.assertEqual(result_feature.attribute('fldtxt'),
                         l1f1orig.attribute('fldtxt'))
        # > check duplicated child layer
        result_layer = results[1].layers()[0]
        self.assertEqual(result_layer, layer2)
        #  > check duplicated child features
        self.assertTrue(results[1].duplicatedFeatures(result_layer))
        '''
        # testoutput 2
        print( "\nFeatures on layer1 (after duplication)")
        for f in layer1.getFeatures():
            print( f.attributes() )

        print( "\nFeatures on layer2 (after duplication)")
        for f in layer2.getFeatures():
            print( f.attributes() )
            
        print( "\nAll Features and relations")
        featit=layer1.getFeatures()
        f=QgsFeature()
        while featit.nextFeature(f):
            print( f.attributes())
            childFeature = QgsFeature()
            relfeatit=rel.getRelatedFeatures(f)
            while relfeatit.nextFeature(childFeature):
                 print( childFeature.attributes() )
        '''

        # > compare text of parent feature
        self.assertEqual(result_feature.attribute('fldtxt'),
                         l1f1orig.attribute('fldtxt'))

        # - create copyValueList
        childFeature = QgsFeature()
        relfeatit = rel.getRelatedFeatures(result_feature)
        copyValueList = []
        while relfeatit.nextFeature(childFeature):
            copyValueList.append(childFeature.attribute('fldtxt'))
        # - create origValueList
        childFeature = QgsFeature()
        relfeatit = rel.getRelatedFeatures(l1f1orig)
        origValueList = []
        while relfeatit.nextFeature(childFeature):
            origValueList.append(childFeature.attribute('fldtxt'))

        # - check if the ids are still the same
        self.assertEqual(copyValueList, origValueList)
Exemple #51
0
class TestQgsBlendModes(TestCase):
    def __init__(self, methodName):
        """Run once on class initialisation."""
        unittest.TestCase.__init__(self, methodName)

        # initialize class MapRegistry, Canvas, MapRenderer, Map and PAL
        self.mMapRegistry = QgsMapLayerRegistry.instance()

        # create point layer
        myShpFile = os.path.join(TEST_DATA_DIR, 'points.shp')
        self.mPointLayer = QgsVectorLayer(myShpFile, 'Points', 'ogr')
        self.mMapRegistry.addMapLayer(self.mPointLayer)

        self.mSimplifyMethod = QgsVectorSimplifyMethod()
        self.mSimplifyMethod.setSimplifyHints(
            QgsVectorSimplifyMethod.NoSimplification)

        # create polygon layer
        myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp')
        self.mPolygonLayer = QgsVectorLayer(myShpFile, 'Polygons', 'ogr')
        self.mPolygonLayer.setSimplifyMethod(self.mSimplifyMethod)
        self.mMapRegistry.addMapLayer(self.mPolygonLayer)

        # create line layer
        myShpFile = os.path.join(TEST_DATA_DIR, 'lines.shp')
        self.mLineLayer = QgsVectorLayer(myShpFile, 'Lines', 'ogr')
        self.mLineLayer.setSimplifyMethod(self.mSimplifyMethod)
        self.mMapRegistry.addMapLayer(self.mLineLayer)

        # create two raster layers
        myRasterFile = os.path.join(TEST_DATA_DIR, 'landsat.tif')
        self.mRasterLayer1 = QgsRasterLayer(myRasterFile, "raster1")
        self.mRasterLayer2 = QgsRasterLayer(myRasterFile, "raster2")
        myMultiBandRenderer1 = QgsMultiBandColorRenderer(
            self.mRasterLayer1.dataProvider(), 2, 3, 4)
        self.mRasterLayer1.setRenderer(myMultiBandRenderer1)
        self.mMapRegistry.addMapLayer(self.mRasterLayer1)
        myMultiBandRenderer2 = QgsMultiBandColorRenderer(
            self.mRasterLayer2.dataProvider(), 2, 3, 4)
        self.mRasterLayer2.setRenderer(myMultiBandRenderer2)
        self.mMapRegistry.addMapLayer(self.mRasterLayer2)

        # to match blend modes test comparisons background
        self.mCanvas = CANVAS
        self.mCanvas.setCanvasColor(QColor(152, 219, 249))
        self.mMap = self.mCanvas.map()
        self.mMap.resize(QSize(400, 400))
        self.mMapRenderer = self.mCanvas.mapRenderer()
        self.mMapRenderer.setOutputSize(QSize(400, 400), 72)

    def testVectorBlending(self):
        """Test that blend modes work for vector layers."""

        #Add vector layers to map
        myLayers = []
        myLayers.append(self.mLineLayer.id())
        myLayers.append(self.mPolygonLayer.id())
        self.mMapRenderer.setLayerSet(myLayers)
        self.mMapRenderer.setExtent(self.mPointLayer.extent())

        #Set blending modes for both layers
        self.mLineLayer.setBlendMode(QPainter.CompositionMode_Difference)
        self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_Difference)

        checker = QgsRenderChecker()
        checker.setControlName("expected_vector_blendmodes")
        checker.setMapRenderer(self.mMapRenderer)

        myResult = checker.runTest("vector_blendmodes")
        myMessage = ('vector blending failed')
        assert myResult, myMessage

        #Reset layers
        self.mLineLayer.setBlendMode(QPainter.CompositionMode_SourceOver)
        self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_SourceOver)

    def testVectorFeatureBlending(self):
        """Test that feature blend modes work for vector layers."""

        #Add vector layers to map
        myLayers = []
        myLayers.append(self.mLineLayer.id())
        myLayers.append(self.mPolygonLayer.id())
        self.mMapRenderer.setLayerSet(myLayers)
        self.mMapRenderer.setExtent(self.mPointLayer.extent())

        #Set feature blending for line layer
        self.mLineLayer.setFeatureBlendMode(QPainter.CompositionMode_Plus)

        checker = QgsRenderChecker()
        checker.setControlName("expected_vector_featureblendmodes")
        checker.setMapRenderer(self.mMapRenderer)

        myResult = checker.runTest("vector_featureblendmodes")
        myMessage = ('vector feature blending failed')
        assert myResult, myMessage

        #Reset layers
        self.mLineLayer.setFeatureBlendMode(
            QPainter.CompositionMode_SourceOver)

    def testVectorLayerTransparency(self):
        """Test that layer transparency works for vector layers."""

        #Add vector layers to map
        myLayers = []
        myLayers.append(self.mLineLayer.id())
        myLayers.append(self.mPolygonLayer.id())
        self.mMapRenderer.setLayerSet(myLayers)
        self.mMapRenderer.setExtent(self.mPointLayer.extent())

        #Set feature blending for line layer
        self.mLineLayer.setLayerTransparency(50)

        checker = QgsRenderChecker()
        checker.setControlName("expected_vector_layertransparency")
        checker.setMapRenderer(self.mMapRenderer)

        myResult = checker.runTest("vector_layertransparency")
        myMessage = ('vector layer transparency failed')
        assert myResult, myMessage

    def testRasterBlending(self):
        """Test that blend modes work for raster layers."""
        #Add raster layers to map
        myLayers = []
        myLayers.append(self.mRasterLayer1.id())
        myLayers.append(self.mRasterLayer2.id())
        self.mMapRenderer.setLayerSet(myLayers)
        self.mMapRenderer.setExtent(self.mRasterLayer1.extent())

        #Set blending mode for top layer
        self.mRasterLayer1.setBlendMode(QPainter.CompositionMode_Plus)
        checker = QgsRenderChecker()
        checker.setControlName("expected_raster_blendmodes")
        checker.setMapRenderer(self.mMapRenderer)

        myResult = checker.runTest("raster_blendmodes")
        myMessage = ('raster blending failed')
        assert myResult, myMessage
    def download_tiles(self, force=None):
        #calculate zoom_level con current canvas extents
        ex = self.iface.mapCanvas().extent()
        wgs84_minimum = self.transformToWGS84(
            QgsPointXY(ex.xMinimum(), ex.yMinimum()))
        wgs84_maximum = self.transformToWGS84(
            QgsPointXY(ex.xMaximum(), ex.yMaximum()))
        bounds = (wgs84_minimum.x(), wgs84_minimum.y(), wgs84_maximum.x(),
                  wgs84_maximum.y())
        map_units_per_pixel = (wgs84_maximum.x() - wgs84_minimum.x()
                               ) / self.iface.mapCanvas().width()
        zoom_level = ZoomForPixelSize(map_units_per_pixel)
        if zoom_level > 14:
            zoom_level = 14

        try:
            ranges = getTileRange(bounds, zoom_level)
        except ValueError:
            return

        if not self.actual_ranges or not (
                ranges[0][0] == self.actual_ranges[0][0]
                and ranges[0][1] == self.actual_ranges[0][1]
                and ranges[1][0] == self.actual_ranges[1][0]
                and ranges[1][1] == self.actual_ranges[1][1]):
            #print ("ZOOM_LEVEL", zoom_level, "NEW RANGES", ranges, "LAST RANGES", self.actual_ranges)
            self.actual_ranges = ranges
            x_range = ranges[0]
            y_range = ranges[1]

            overview_features = []
            sequences_features = []
            images_features = []

            progress = progressBar(self, 'go2mapillary')

            start_time = datetime.datetime.now()

            for y in range(y_range[0], y_range[1] + 1):
                for x in range(x_range[0], x_range[1] + 1):
                    folderPath = os.path.join(self.cache_dir, str(zoom_level),
                                              str(x))
                    filePathMvt = os.path.join(folderPath, str(y) + '.mvt')
                    #filePathJson = os.path.join(folderPath, str(y) + '.json')
                    if not os.path.exists(folderPath):
                        os.makedirs(folderPath)
                    res = None

                    if not os.path.exists(filePathMvt) or (
                            datetime.datetime.fromtimestamp(
                                os.path.getmtime(filePathMvt)) <
                        (datetime.datetime.now() - self.expire_time)):
                        # make the URL
                        url = getURL(x, y, zoom_level, SERVER_URL)
                        with open(filePathMvt, 'wb') as f:
                            response = requests.get(url,
                                                    proxies=getProxiesConf(),
                                                    stream=True)
                            total_length = response.headers.get(
                                'content-length')

                            if total_length is None:  # no content length header
                                f.write(response.content)
                            else:
                                dl = 0
                                total_length = int(total_length)
                                progress.start(
                                    total_length,
                                    'caching vector tile [%d,%d,%d]' %
                                    (x, y, zoom_level))
                                QgsMessageLog.logMessage("MISS [%d,%d,%d]" %
                                                         (x, y, zoom_level),
                                                         tag="go2mapillary",
                                                         level=Qgis.Info)
                                for data in response.iter_content(
                                        chunk_size=4096):
                                    dl += len(data)
                                    f.write(data)
                                    progress.setProgress(dl)

                    if os.path.exists(filePathMvt):
                        progress.start(
                            0, 'loading vector tile [%d,%d,%d]' %
                            (x, y, zoom_level))
                        if not res:
                            with open(filePathMvt, "rb") as f:
                                mvt = f.read()
                                QgsMessageLog.logMessage("CACHE [%d,%d,%d]" %
                                                         (x, y, zoom_level),
                                                         tag="go2mapillary",
                                                         level=Qgis.Info)
                        else:
                            mvt = res.content

                        bounds = mercantile.bounds(x, y, zoom_level)
                        tile_box = (bounds.west, bounds.south, bounds.east,
                                    bounds.north)
                        json_data = mapbox_vector_tile.decode(
                            mvt, quantize_bounds=tile_box)
                        if "mapillary-sequence-overview" in json_data:
                            overview_features = overview_features + json_data[
                                "mapillary-sequence-overview"]["features"]
                        elif "mapillary-sequences" in json_data:
                            sequences_features = sequences_features + json_data[
                                "mapillary-sequences"]["features"]
                        if "mapillary-images" in json_data and zoom_level == 14:
                            images_features = images_features + json_data[
                                "mapillary-images"]["features"]

            print("loading time", datetime.datetime.now() - start_time)
            progress.stop('loading complete')

            for level in LAYER_LEVELS:
                geojson_file = os.path.join(self.cache_dir,
                                            "mapillary_%s.geojson" % level)
                try:
                    QgsProject.instance().removeMapLayer(
                        getattr(self, level + 'Layer').id())
                except:
                    pass
                if locals()[level + '_features']:
                    setattr(self, level, True)
                    geojson = {
                        "type": "FeatureCollection",
                        "features": locals()[level + '_features']
                    }

                    with open(geojson_file, 'w') as outfile:
                        json.dump(geojson, outfile)
                    defLyr = QgsVectorLayer(
                        os.path.join(self.cache_dir,
                                     'mapillary_%s.geojson' % level),
                        "Mapillary " + level, "ogr")
                    defLyr.loadNamedStyle(
                        os.path.join(os.path.dirname(__file__), "res",
                                     "mapillary_%s.qml" % level))
                    QgsExpressionContextUtils.setLayerVariable(
                        defLyr, "mapillaryCurrentKey",
                        self.module.viewer.locationKey)
                    defLyr.setCrs(QgsCoordinateReferenceSystem(4326))
                    QgsProject.instance().addMapLayer(defLyr)
                    self.iface.addCustomActionForLayerType(
                        getattr(self.module, 'filterAction_' + level),
                        None,
                        QgsMapLayer.VectorLayer,
                        allLayers=False)
                    self.module.filterDialog.applySqlFilter(layer=defLyr)
                    self.iface.addCustomActionForLayer(
                        getattr(self.module, 'filterAction_' + level), defLyr)
                    legendLayerNode = QgsProject.instance().layerTreeRoot(
                    ).findLayer(defLyr.id())
                    legendLayerNode.setExpanded(False)
                    setattr(self, level + 'Layer', defLyr)
                else:
                    setattr(self, level, False)

        else:
            pass
Exemple #53
0
class TestQgsArrowSymbolLayer(unittest.TestCase):
    def setUp(self):
        self.iface = get_iface()

        lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp')
        self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr')
        QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer)

        # Create style
        sym2 = QgsLineSymbol.createSimple({'color': '#fdbf6f'})
        self.lines_layer.setRenderer(QgsSingleSymbolRenderer(sym2))

        self.mapsettings = self.iface.mapCanvas().mapSettings()
        self.mapsettings.setOutputSize(QSize(400, 400))
        self.mapsettings.setOutputDpi(96)
        self.mapsettings.setExtent(QgsRectangle(-113, 28, -91, 40))
        self.mapsettings.setBackgroundColor(QColor("white"))

    def tearDown(self):
        QgsMapLayerRegistry.instance().removeAllMapLayers()

    def test_1(self):
        sym = self.lines_layer.renderer().symbol()
        sym_layer = QgsArrowSymbolLayer.create({
            'head_length': '6.5',
            'head_thickness': '6.5'
        })
        dd = QgsDataDefined("(@geometry_point_num % 4) * 2")
        sym_layer.setDataDefinedProperty("arrow_width", dd)
        dd2 = QgsDataDefined("(@geometry_point_num % 4) * 2")
        sym_layer.setDataDefinedProperty("head_length", dd2)
        dd3 = QgsDataDefined("(@geometry_point_num % 4) * 2")
        sym_layer.setDataDefinedProperty("head_thickness", dd3)
        fill_sym = QgsFillSymbol.createSimple({
            'color': '#8bcfff',
            'outline_color': '#000000',
            'outline_style': 'solid',
            'outline_width': '1'
        })
        sym_layer.setSubSymbol(fill_sym)
        sym.changeSymbolLayer(0, sym_layer)

        rendered_layers = [self.lines_layer.id()]
        self.mapsettings.setLayers(rendered_layers)

        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_arrowsymbollayer_1')
        self.assertTrue(renderchecker.runTest('arrowsymbollayer_1'))

    def test_2(self):
        sym = self.lines_layer.renderer().symbol()
        # double headed
        sym_layer = QgsArrowSymbolLayer.create({
            'arrow_width': '5',
            'head_length': '4',
            'head_thickness': '6',
            'head_type': '2'
        })
        fill_sym = QgsFillSymbol.createSimple({
            'color': '#8bcfff',
            'outline_color': '#000000',
            'outline_style': 'solid',
            'outline_width': '1'
        })
        sym_layer.setSubSymbol(fill_sym)
        sym.changeSymbolLayer(0, sym_layer)

        rendered_layers = [self.lines_layer.id()]
        self.mapsettings.setLayers(rendered_layers)

        renderchecker = QgsMultiRenderChecker()
        renderchecker.setMapSettings(self.mapsettings)
        renderchecker.setControlName('expected_arrowsymbollayer_2')
        self.assertTrue(renderchecker.runTest('arrowsymbollayer_2'))

    def test_3(self):
        sym = self.lines_layer.renderer().symbol()
        # double headed
        sym_layer = QgsArrowSymbolLayer.create({
            'arrow_width': '7',
            'head_length': '6',
            'head_thickness': '8',
            'head_type': '0',
            'arrow_type': '1',
            'is_curved': '0'
        })
        fill_sym = QgsFillSymbol.createSimple({
            'color': '#8bcfff',
            'outline_color': '#000000',
            'outline_style': 'solid',
            'outline_width': '1'
        })
        sym_layer.setSubSymbol(fill_sym)
        sym.changeSymbolLayer(0, sym_layer)

        rendered_layers = [self.lines_layer.id()]
        self.mapsettings.setLayers(rendered_layers)

        renderchecker = QgsMultiRenderChecker()
        ms = self.mapsettings
        ms.setExtent(QgsRectangle(-101, 35, -99, 37))
        renderchecker.setMapSettings(ms)
        renderchecker.setControlName('expected_arrowsymbollayer_3')
        self.assertTrue(renderchecker.runTest('arrowsymbollayer_3'))

    def test_unrepeated(self):
        sym = self.lines_layer.renderer().symbol()
        # double headed
        sym_layer = QgsArrowSymbolLayer.create({
            'arrow_width': '7',
            'head_length': '6',
            'head_thickness': '8',
            'head_type': '0',
            'arrow_type': '0'
        })
        # no repetition
        sym_layer.setIsRepeated(False)
        fill_sym = QgsFillSymbol.createSimple({
            'color': '#8bcfff',
            'outline_color': '#000000',
            'outline_style': 'solid',
            'outline_width': '1'
        })
        sym_layer.setSubSymbol(fill_sym)
        sym.changeSymbolLayer(0, sym_layer)

        rendered_layers = [self.lines_layer.id()]
        self.mapsettings.setLayers(rendered_layers)

        renderchecker = QgsMultiRenderChecker()
        ms = self.mapsettings
        ms.setExtent(QgsRectangle(-119, 17, -82, 50))
        renderchecker.setMapSettings(ms)
        renderchecker.setControlName('expected_arrowsymbollayer_4')
        self.assertTrue(renderchecker.runTest('arrowsymbollayer_4'))

    def testColors(self):
        """
        Test colors, need to make sure colors are passed/retrieved from subsymbol
        """
        sym_layer = QgsArrowSymbolLayer.create()
        sym_layer.setColor(QColor(150, 50, 100))
        self.assertEqual(sym_layer.color(), QColor(150, 50, 100))
        self.assertEqual(sym_layer.subSymbol().color(), QColor(150, 50, 100))
        sym_layer.subSymbol().setColor(QColor(250, 150, 200))
        self.assertEqual(sym_layer.subSymbol().color(), QColor(250, 150, 200))
        self.assertEqual(sym_layer.color(), QColor(250, 150, 200))
Exemple #54
0
    def testInitialSizeSymbolMapUnits(self):
        """Test initial size of legend with a symbol size in map units"""

        point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
        point_layer = QgsVectorLayer(point_path, 'points', 'ogr')
        QgsProject.instance().addMapLayers([point_layer])

        marker_symbol = QgsMarkerSymbol.createSimple({
            'color': '#ff0000',
            'outline_style': 'no',
            'size': '5',
            'size_unit': 'MapUnit'
        })

        point_layer.setRenderer(QgsSingleSymbolRenderer(marker_symbol))

        s = QgsMapSettings()
        s.setLayers([point_layer])
        layout = QgsLayout(QgsProject.instance())
        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.attemptSetSceneRect(QRectF(120, 20, 80, 80))
        legend.setFrameEnabled(True)
        legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
        legend.setBackgroundColor(QColor(200, 200, 200))
        legend.setTitle('')
        layout.addLayoutItem(legend)
        legend.setLinkedMap(map)

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

        # resize with non-top-left reference point
        legend.setResizeToContents(False)
        legend.setReferencePoint(QgsLayoutItem.LowerRight)
        legend.attemptMove(QgsLayoutPoint(120, 90))
        legend.attemptResize(QgsLayoutSize(50, 60))

        self.assertEqual(legend.positionWithUnits().x(), 120.0)
        self.assertEqual(legend.positionWithUnits().y(), 90.0)
        self.assertAlmostEqual(legend.pos().x(), 70, -1)
        self.assertAlmostEqual(legend.pos().y(), 30, -1)

        legend.setResizeToContents(True)
        legend.updateLegend()
        self.assertEqual(legend.positionWithUnits().x(), 120.0)
        self.assertEqual(legend.positionWithUnits().y(), 90.0)
        self.assertAlmostEqual(legend.pos().x(), 91, -1)
        self.assertAlmostEqual(legend.pos().y(), 71, -1)

        QgsProject.instance().removeMapLayers([point_layer.id()])
Exemple #55
0
class OutputTabManager(QtCore.QObject):
    ''' Class to hide managing of relative tab
    '''
    projectModified = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        '''constructor'''
        super(OutputTabManager, self).__init__(parent)

        # parent is the dock widget with all graphical elements
        self.gui = parent
        self.plugin = parent.parent

        # init some globals
        self.applicationPath = os.path.dirname(os.path.realpath(__file__))
        self.project = None
        self.projectPath = None
        self.outLayer = None
        self.outLayerId = None
        self.outLayerRemoved = False

        # retrieve the current tab index
        self.initTabTabIndex()

        # disable tab at the beginning
        self.gui.tabWidget.setTabEnabled(self.tabIndex, False)

        # add some gui events
        self.gui.createNewLayer_RButton.toggled.connect(self.setInputLayer)
        self.gui.selectOutfile_TButton.clicked.connect(self.selectNewOutFile)
        self.gui.calculate_PButton.clicked.connect(self.calculate)

    def initTabTabIndex(self):
        ''' Retrieve what tab index refer the current tab manager
        '''
        for tabIndex in range(self.gui.tabWidget.count()):
            if self.gui.tabWidget.tabText(tabIndex) == "Output":
                self.tabIndex = tabIndex

    def setProject(self, project=None):
        ''' setting the new project on which the tab is based
        '''
        self.project = project
        if self.project:
            # write everything on disk
            self.project.sync()

            # set some globals
            confFileName = self.project.fileName()
            self.projectPath = os.path.dirname(confFileName)

            # emit configurationLoaded with the status of loading
            self.setTabGUIBasingOnProject()

            # enable current tab because project has been loaded
            self.gui.tabWidget.setTabEnabled(self.tabIndex, True)

        else:
            # disable current tab because no project has been loaded yet
            self.gui.tabWidget.setTabEnabled(self.tabIndex, False)

    def selectNewOutFile(self):
        ''' Select the the file
        '''
        oldOutputLayer = self.gui.outFile_LEdit.text()

        # get last conf to start from its path
        startPath = self.projectPath
        newOutputLayer = self.project.value(
            'Processing.OutputFileDefinition/newOutputLayer', '')
        if newOutputLayer:
            startPath = os.path.dirname(newOutputLayer)

        # ask for the new out file
        newOutputLayer = QtGui.QFileDialog.getSaveFileName(
            self.gui, "Select an autput file", startPath,
            self.plugin.tr("All (*)"))
        if not newOutputLayer:
            return

        if oldOutputLayer == newOutputLayer:
            return

        # add shp extension
        components = os.path.splitext(newOutputLayer)
        if len(components) == 1:
            newOutputLayer = newOutputLayer + '.shp'
        else:
            if components[1] != '.shp':
                newOutputLayer = components[0] + '.shp'

        # update gui
        self.gui.outFile_LEdit.setText(newOutputLayer)

        self.saveTabOnProject()

    def setInputLayer(self):
        ''' Set GUI basing on toggled ComboBox to set if the layer is the input one 
        or have to select a new one 
        '''
        self.gui.outFile_LEdit.setEnabled(
            self.gui.createNewLayer_RButton.isChecked())
        self.gui.selectOutfile_TButton.setEnabled(
            self.gui.createNewLayer_RButton.isChecked())

    def setTabGUIBasingOnProject(self):
        '''Set tab basing on project conf
        '''
        if not self.project:
            return

        # get conf parameters
        addToInputLayer = self.project.value(
            'Processing.OutputFileDefinition/addToInputLayer', False, bool)
        newOutputLayer = self.project.value(
            'Processing.OutputFileDefinition/newOutputLayer', '')

        Gasoline_Consumption = self.project.value(
            'Processing.Parameters/Gasoline_Consumption', False, bool)
        Diesel_Consumption = self.project.value(
            'Processing.Parameters/Diesel_Consumption', False, bool)
        LPG_Consumption = self.project.value(
            'Processing.Parameters/LPG_Consumption', False, bool)
        NewFuel_Consumption = self.project.value(
            'Processing.Parameters/NewFuel_Consumption', False, bool)
        Fuel_Consumption_Total = self.project.value(
            'Processing.Parameters/Fuel_Consumption_Total', False, bool)
        Energy_Consumption = self.project.value(
            'Processing.Parameters/Energy_Consumption', False, bool)

        CO = self.project.value('Processing.Parameters/CO', False, bool)
        NOx = self.project.value('Processing.Parameters/NOx', False, bool)
        NMVOC = self.project.value('Processing.Parameters/NMVOC', False, bool)
        CO2 = self.project.value('Processing.Parameters/CO2', False, bool)
        CH4 = self.project.value('Processing.Parameters/CH4', False, bool)
        N2O = self.project.value('Processing.Parameters/N2O', False, bool)
        NH3 = self.project.value('Processing.Parameters/NH3', False, bool)
        SO2 = self.project.value('Processing.Parameters/SO2', False, bool)
        PM25 = self.project.value('Processing.Parameters/PM', False, bool)
        C6H6 = self.project.value('Processing.Parameters/C6H6', False, bool)

        # avoid emitting signal in case of reset of indexes
        try:
            # to avoid add multiple listener, remove previous listener
            self.gui.addToOriginaLayer_RButton.toggled.disconnect(
                self.saveTabOnProject)
            self.gui.createNewLayer_RButton.toggled.disconnect(
                self.saveTabOnProject)
            self.gui.outFile_LEdit.returnPressed.disconnect(
                self.saveTabOnProject)

            self.gui.fuelEnergyConsumptionGasoline_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.fuelEnergyConsumptionDiesel_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.fuelEnergyConsumptionLPG_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.fuelEnergyConsumptionNewFuels_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.totalFuelConsumption_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.energyConsumption_CBox.clicked.disconnect(
                self.saveTabOnProject)

            self.gui.pollutantsCO_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsNOx_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsNMVOCs_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsCO2_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsCH4_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsN2O_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsNH3_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsSO2_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsPM25_CBox.clicked.disconnect(
                self.saveTabOnProject)
            self.gui.pollutantsC6H6_CBox.clicked.disconnect(
                self.saveTabOnProject)
        except (Exception) as ex:
            pass

        # now populate interface
        self.gui.addToOriginaLayer_RButton.setChecked(addToInputLayer)
        self.gui.createNewLayer_RButton.setChecked(not addToInputLayer)
        self.gui.outFile_LEdit.setText(newOutputLayer)

        self.gui.fuelEnergyConsumptionGasoline_CBox.setChecked(
            Gasoline_Consumption)
        self.gui.fuelEnergyConsumptionDiesel_CBox.setChecked(
            Diesel_Consumption)
        self.gui.fuelEnergyConsumptionLPG_CBox.setChecked(LPG_Consumption)
        self.gui.fuelEnergyConsumptionNewFuels_CBox.setChecked(
            NewFuel_Consumption)
        self.gui.totalFuelConsumption_CBox.setChecked(Fuel_Consumption_Total)
        self.gui.energyConsumption_CBox.setChecked(Energy_Consumption)

        self.gui.pollutantsCO_CBox.setChecked(CO)
        self.gui.pollutantsNOx_CBox.setChecked(NOx)
        self.gui.pollutantsNMVOCs_CBox.setChecked(NMVOC)
        self.gui.pollutantsCO2_CBox.setChecked(CO2)
        self.gui.pollutantsCH4_CBox.setChecked(CH4)
        self.gui.pollutantsN2O_CBox.setChecked(N2O)
        self.gui.pollutantsNH3_CBox.setChecked(NH3)
        self.gui.pollutantsSO2_CBox.setChecked(SO2)
        self.gui.pollutantsPM25_CBox.setChecked(PM25)
        self.gui.pollutantsC6H6_CBox.setChecked(C6H6)

        # add all modification events to notify project modification
        self.gui.addToOriginaLayer_RButton.toggled.connect(
            self.saveTabOnProject)
        self.gui.createNewLayer_RButton.toggled.connect(self.saveTabOnProject)
        self.gui.outFile_LEdit.returnPressed.connect(self.saveTabOnProject)

        self.gui.fuelEnergyConsumptionGasoline_CBox.clicked.connect(
            self.saveTabOnProject)
        self.gui.fuelEnergyConsumptionDiesel_CBox.clicked.connect(
            self.saveTabOnProject)
        self.gui.fuelEnergyConsumptionLPG_CBox.clicked.connect(
            self.saveTabOnProject)
        self.gui.fuelEnergyConsumptionNewFuels_CBox.clicked.connect(
            self.saveTabOnProject)
        self.gui.totalFuelConsumption_CBox.clicked.connect(
            self.saveTabOnProject)
        self.gui.energyConsumption_CBox.clicked.connect(self.saveTabOnProject)

        self.gui.pollutantsCO_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsNOx_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsNMVOCs_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsCO2_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsCH4_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsN2O_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsNH3_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsSO2_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsPM25_CBox.clicked.connect(self.saveTabOnProject)
        self.gui.pollutantsC6H6_CBox.clicked.connect(self.saveTabOnProject)

        # if and output file is specified and it's available => load it
        if newOutputLayer and os.path.exists(newOutputLayer):

            # check if layer is already loaded in layer list checking it's source
            found = False
            for layerName, layer in QgsMapLayerRegistry.instance().mapLayers(
            ).items():
                if newOutputLayer == layer.publicSource():
                    # set the found layer as roadLayer
                    self.outLayer = layer
                    self.outLayerId = self.outLayer.id()
                    found = True
                    break

            if not found:
                # get layer name to set as public name in the legend
                layerName = os.path.splitext(
                    os.path.basename(newOutputLayer))[0]

                # load layer
                self.outLayer = QgsVectorLayer(newOutputLayer, layerName,
                                               'ogr')
                if not self.outLayer.isValid():
                    message = self.tr(
                        "Error loading layer: %s" %
                        self.outLayer.error().message(QgsErrorMessage.Text))
                    iface.messageBar().pushMessage(message,
                                                   QgsMessageBar.CRITICAL)
                    return

                self.outLayerId = self.outLayer.id()

                # show layer in the canvas
                QgsMapLayerRegistry.instance().addMapLayer(self.outLayer)

    def saveTabOnProject(self):
        ''' Save tab configuration in the project basing on GUI values
        '''
        # get values from the GUI
        addToInputLayer = self.gui.addToOriginaLayer_RButton.isChecked()
        newOutputLayer = self.gui.outFile_LEdit.text()

        Gasoline_Consumption = self.gui.fuelEnergyConsumptionGasoline_CBox.isChecked(
        )
        Diesel_Consumption = self.gui.fuelEnergyConsumptionDiesel_CBox.isChecked(
        )
        LPG_Consumption = self.gui.fuelEnergyConsumptionLPG_CBox.isChecked()
        NewFuel_Consumption = self.gui.fuelEnergyConsumptionNewFuels_CBox.isChecked(
        )
        Fuel_Consumption_Total = self.gui.totalFuelConsumption_CBox.isChecked()
        Energy_Consumption = self.gui.energyConsumption_CBox.isChecked()

        CO = self.gui.pollutantsCO_CBox.isChecked()
        NOx = self.gui.pollutantsNOx_CBox.isChecked()
        NMVOC = self.gui.pollutantsNMVOCs_CBox.isChecked()
        CO2 = self.gui.pollutantsCO2_CBox.isChecked()
        CH4 = self.gui.pollutantsCH4_CBox.isChecked()
        N2O = self.gui.pollutantsN2O_CBox.isChecked()
        NH3 = self.gui.pollutantsNH3_CBox.isChecked()
        SO2 = self.gui.pollutantsSO2_CBox.isChecked()
        PM25 = self.gui.pollutantsPM25_CBox.isChecked()
        C6H6 = self.gui.pollutantsC6H6_CBox.isChecked()

        # set conf parameters
        self.project.setValue(
            'Processing.OutputFileDefinition/addToInputLayer',
            int(addToInputLayer))
        self.project.setValue('Processing.OutputFileDefinition/newOutputLayer',
                              newOutputLayer)

        self.project.setValue('Processing.Parameters/Gasoline_Consumption',
                              int(Gasoline_Consumption))
        self.project.setValue('Processing.Parameters/Diesel_Consumption',
                              int(Diesel_Consumption))
        self.project.setValue('Processing.Parameters/LPG_Consumption',
                              int(LPG_Consumption))
        self.project.setValue('Processing.Parameters/NewFuel_Consumption',
                              int(NewFuel_Consumption))
        self.project.setValue('Processing.Parameters/Fuel_Consumption_Total',
                              int(Fuel_Consumption_Total))
        self.project.setValue('Processing.Parameters/Energy_Consumption',
                              int(Energy_Consumption))

        self.project.setValue('Processing.Parameters/CO', int(CO))
        self.project.setValue('Processing.Parameters/NOx', int(NOx))
        self.project.setValue('Processing.Parameters/NMVOC', int(NMVOC))
        self.project.setValue('Processing.Parameters/CO2', int(CO2))
        self.project.setValue('Processing.Parameters/CH4', int(CH4))
        self.project.setValue('Processing.Parameters/N2O', int(N2O))
        self.project.setValue('Processing.Parameters/NH3', int(NH3))
        self.project.setValue('Processing.Parameters/SO2', int(SO2))
        self.project.setValue('Processing.Parameters/PM', int(PM25))
        self.project.setValue('Processing.Parameters/C6H6', int(C6H6))

        # notify project modification
        self.projectModified.emit()

    def calculate(self):
        ''' Prepare environment to run the alg and run it. After run, merge produced 
        data basing on plugin configuration.
        Before calculation a parametere validation will be executed
        '''
        # perform validation
        if not self.gui.validate():
            return
        else:
            # notify successful validation
            message = self.tr(
                "QTraffic: Parameters validation passed successfully")
            iface.messageBar().pushMessage(message, QgsMessageBar.SUCCESS)

        # set number of classes in the project config (that is the temporary one... but equal to the official one)
        fleetDistributionRoadTypes = self.gui.getRoadTypes()
        self.project.setValue('Processing.Parameters/maximum_type',
                              len(fleetDistributionRoadTypes))
        self.project.sync()

        # create the algorithm
        self.alg = Algorithm()
        roadLayer = self.gui.getRoadLayer()

        # prepare layer where to add result
        addToInputLayer = self.gui.addToOriginaLayer_RButton.isChecked()
        newOutputLayer = self.gui.outFile_LEdit.text()

        if addToInputLayer:
            self.outLayer = roadLayer
            self.outLayerId = self.outLayer.id()
        else:
            # if layer is present... remove it
            # out layer would not be the same of input road layer... in thi scase don't remove it
            if self.outLayer and self.outLayer.isValid():
                # to be sure, remove only if roadLayer and outLayer are different
                if self.outLayer.publicSource() != roadLayer.publicSource():
                    self.outLayerRemoved = False
                    QgsMapLayerRegistry.instance().layerRemoved.connect(
                        self.checkOutLayerRemoved)
                    QgsMapLayerRegistry.instance().removeMapLayer(
                        self.outLayer.id())

                    # remove file when it has been removed from qgis
                    while not self.outLayerRemoved:
                        sleep(0.1)
                    QgsMapLayerRegistry.instance().layerRemoved.disconnect(
                        self.checkOutLayerRemoved)

                    # reinit outLayer variables
                    # If not, under windws remain a locking of the related file creating
                    # an error during QgsVectorFileWriter.deleteShapeFile
                    self.outLayer = None
                    self.outLayerId = None

                    if os.path.exists(newOutputLayer):
                        if not QgsVectorFileWriter.deleteShapeFile(
                                newOutputLayer):
                            message = self.tr(
                                "Error removing shape: {}".format(
                                    newOutputLayer))
                            iface.messageBar().pushMessage(
                                message, QgsMessageBar.CRITICAL)
                            return

            # copy input layer to the new one
            writeError = QgsVectorFileWriter.writeAsVectorFormat(
                roadLayer, newOutputLayer, 'utf-8', roadLayer.crs())
            if writeError != QgsVectorFileWriter.NoError:
                message = self.tr(
                    'Error writing vector file {}'.format(newOutputLayer))
                QgsMessageLog.logMessage(message, 'QTraffic',
                                         QgsMessageLog.CRITICAL)
                iface.messageBar().pushCritical('QTraffic', message)
                return

            # load the layer
            newLayerName = os.path.splitext(
                os.path.basename(newOutputLayer))[0]
            self.outLayer = QgsVectorLayer(newOutputLayer, newLayerName, 'ogr')
            if not self.outLayer.isValid():
                message = self.tr(
                    'Error loading vector file {}'.format(newOutputLayer))
                QgsMessageLog.logMessage(message, 'QTraffic',
                                         QgsMessageLog.CRITICAL)
                iface.messageBar().pushCritical('QTraffic', message)
                return

            self.outLayerId = self.outLayer.id()

        # prepare environment
        try:
            self.alg.setProject(self.project)
            self.alg.setLayer(roadLayer)
            self.alg.initConfig()
            self.alg.prepareRun()
        except Exception as ex:
            traceback.print_exc()
            message = self.tr(
                'Error preparing running contex for the algoritm: %s' %
                str(ex))
            QgsMessageLog.logMessage(message, 'QTraffic',
                                     QgsMessageLog.CRITICAL)
            iface.messageBar().pushCritical('QTraffic', message)
            return

        # run the self.alg
        self.thread = QtCore.QThread(self)
        self.thread.started.connect(self.alg.run)
        self.thread.finished.connect(self.threadCleanup)
        self.thread.terminated.connect(self.threadCleanup)

        self.alg.moveToThread(self.thread)
        self.alg.started.connect(self.manageStarted)
        self.alg.progress.connect(self.manageProgress)
        self.alg.message.connect(self.manageMessage)
        self.alg.error.connect(self.manageError)
        self.alg.finished.connect(self.manageFinished)

        # set wait cursor and start
        QgsApplication.instance().setOverrideCursor(QtCore.Qt.WaitCursor)
        self.thread.start()

    def checkOutLayerRemoved(self, layerId):
        ''' check when outLayer has been removed settign semaphore to True
        '''
        if self.outLayerId == layerId:
            QgsMessageLog.logMessage('Completly removed outLayer', 'QTraffic',
                                     QgsMessageLog.INFO)
            self.outLayerRemoved = True

    def threadCleanup(self):
        ''' cleanup after thread run
        '''
        # restore cursor
        QgsApplication.instance().restoreOverrideCursor()

        if self.alg:
            self.alg.deleteLater()
            self.alg = None
        self.thread.wait()
        self.thread.deleteLater()

        # remove progress bar
        if self.progressMessageBarItem:
            iface.messageBar().popWidget(self.progressMessageBarItem)
            self.progressMessageBarItem = None

    def manageStarted(self):
        ''' Setup GUI env to notify processing progress
        '''
        message = self.tr('Processing started')
        QgsMessageLog.logMessage(message, 'QTraffic', QgsMessageLog.INFO)

        # create message bar to show progress
        self.progressMessageBarItem = iface.messageBar().createMessage(
            self.tr('Executing alg'))
        self.progress = QtGui.QProgressBar()
        self.progress.setMaximum(0)
        self.progress.setMinimum(0)
        self.progress.setAlignment(QtCore.Qt.AlignLeft
                                   | QtCore.Qt.AlignVCenter)
        self.progressMessageBarItem.layout().addWidget(self.progress)
        iface.messageBar().pushWidget(self.progressMessageBarItem,
                                      QgsMessageBar.INFO)

    def manageProgress(self, percentage):
        ''' Update progress bar basing on alg nofify
        '''
        self.progress.setValue(percentage)

    def manageMessage(self, message, msgType):
        ''' expose alg thread messages to gui and log
        '''
        QgsMessageLog.logMessage(message, 'QTraffic', msgType)

        duration = 0
        if msgType == QgsMessageLog.INFO:
            return

        if msgType == QgsMessageLog.CRITICAL:
            msgType = QgsMessageBar.CRITICAL

        if msgType == QgsMessageLog.WARNING:
            duration = 3
            msgType = QgsMessageBar.WARNING

        iface.messageBar().pushMessage(message, msgType, duration)

    def manageError(self, ex, exceptionMessage):
        ''' Do actions in case of alg thread error. Now only notify exception 
        '''
        QgsMessageLog.logMessage(exceptionMessage, 'QTraffic',
                                 QgsMessageLog.CRITICAL)
        iface.messageBar().pushMessage(exceptionMessage,
                                       QgsMessageBar.CRITICAL)

    def manageFinished(self, success, reason):
        ''' Do action after notify that alg is finished. These are the postprocessing steps
        1) merge result to the output layer
        2) add the layer to canvas in case it is new
        3) notify edn of processing
        4) terminate the thread
        '''
        # finish the thread
        self.thread.quit()

        # check result
        if not success:
            QgsMessageLog.logMessage('Failed execution: {}'.format(reason),
                                     'QTraffic', QgsMessageLog.CRITICAL)
            iface.messageBar().pushCritical(
                'QTraffic',
                self.tr("Error executing the algorithm: {}".format(reason)))
            return

        # prepare result
        try:
            self.alg.addResultToLayer(self.outLayer)
        except Exception as ex:
            traceback.print_exc()
            QgsMessageLog.logMessage(
                'Cannot add result to layer: {}'.format(str(ex)), 'QTraffic',
                QgsMessageLog.CRITICAL)
            iface.messageBar().pushCritical(
                'QTraffic', self.tr("Cannot add result to layer"))
            return

        # add or refresh rsult vector layer
        addToInputLayer = self.gui.addToOriginaLayer_RButton.isChecked()
        if not addToInputLayer:
            QgsMapLayerRegistry.instance().addMapLayer(self.outLayer)
        iface.mapCanvas().refresh()

        # notify the user the end of process
        iface.messageBar().pushSuccess('QTraffic',
                                       self.tr('Alg terminated successfully'))

    def validate(self):
        ''' pre calcluation validation related only to this tab
        Mandatory:
            At least an output parameters have to be set
            if "create new layer" a new layer name have to be set
        '''
        addToInputLayer = self.gui.addToOriginaLayer_RButton.isChecked()
        newOutputLayer = self.gui.outFile_LEdit.text()
        if (not addToInputLayer and not newOutputLayer):
            message = self.tr('No output vector specified')
            iface.messageBar().pushMessage(message, QgsMessageBar.CRITICAL)
            return False

        Gasoline_Consumption = self.gui.fuelEnergyConsumptionGasoline_CBox.isChecked(
        )
        Diesel_Consumption = self.gui.fuelEnergyConsumptionDiesel_CBox.isChecked(
        )
        LPG_Consumption = self.gui.fuelEnergyConsumptionLPG_CBox.isChecked()
        NewFuel_Consumption = self.gui.fuelEnergyConsumptionNewFuels_CBox.isChecked(
        )
        Fuel_Consumption_Total = self.gui.totalFuelConsumption_CBox.isChecked()
        Energy_Consumption = self.gui.energyConsumption_CBox.isChecked()

        CO = self.gui.pollutantsCO_CBox.isChecked()
        NOx = self.gui.pollutantsNOx_CBox.isChecked()
        NMVOC = self.gui.pollutantsNMVOCs_CBox.isChecked()
        CO2 = self.gui.pollutantsCO2_CBox.isChecked()
        CH4 = self.gui.pollutantsCH4_CBox.isChecked()
        N2O = self.gui.pollutantsN2O_CBox.isChecked()
        NH3 = self.gui.pollutantsNH3_CBox.isChecked()
        SO2 = self.gui.pollutantsSO2_CBox.isChecked()
        PM25 = self.gui.pollutantsPM25_CBox.isChecked()
        C6H6 = self.gui.pollutantsC6H6_CBox.isChecked()

        if (not Gasoline_Consumption and not Diesel_Consumption
                and not LPG_Consumption and not NewFuel_Consumption
                and not Fuel_Consumption_Total and not Energy_Consumption
                and not CO and not NOx and not NMVOC and not CO2 and not CH4
                and not N2O and not NH3 and not SO2 and not PM25 and not C6H6):
            message = self.tr(
                "Validation error: At least an output parameter have to be selected"
            )
            iface.messageBar().pushMessage(message, QgsMessageBar.CRITICAL)
            return False

        return True

    def tr(self, string, context=''):
        if not context:
            context = 'QTraffic'
        return QtCore.QCoreApplication.translate(context, string)
Exemple #56
0
    def testCreateExpression(self):
        """ Test creating an expression using the widget"""
        layer = QgsVectorLayer(
            "Point?field=fldtxt:string&field=fldint:integer", "test", "memory")
        # setup value relation
        parent_layer = QgsVectorLayer(
            "Point?field=stringkey:string&field=intkey:integer&field=display:string",
            "parent", "memory")
        f1 = QgsFeature(parent_layer.fields(), 1)
        f1.setAttributes(['a', 1, 'value a'])
        f2 = QgsFeature(parent_layer.fields(), 2)
        f2.setAttributes(['b', 2, 'value b'])
        f3 = QgsFeature(parent_layer.fields(), 3)
        f3.setAttributes(['c', 3, 'value c'])
        parent_layer.dataProvider().addFeatures([f1, f2, f3])
        QgsProject.instance().addMapLayers([layer, parent_layer])

        config = {
            "Layer": parent_layer.id(),
            "Key": 'stringkey',
            "Value": 'display'
        }

        w = QgsValueRelationSearchWidgetWrapper(layer, 0)
        w.setConfig(config)
        c = w.widget()

        # first, set it to the "select value" item
        c.setCurrentIndex(0)

        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '')

        c.setCurrentIndex(1)
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldtxt"=\'a\'')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldtxt"<>\'a\'')
        c.setCurrentIndex(2)
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldtxt" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldtxt" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldtxt"=\'b\'')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldtxt"<>\'b\'')

        # try with numeric field
        w = QgsValueRelationSearchWidgetWrapper(layer, 1)
        config['Key'] = 'intkey'
        w.setConfig(config)
        c = w.widget()
        c.setCurrentIndex(c.findText('value c'))
        self.assertEqual(c.currentIndex(), 3)
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldint" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldint" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldint"=3')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldint"<>3')

        # try with allow null set
        w = QgsValueRelationSearchWidgetWrapper(layer, 1)
        config['AllowNull'] = True
        w.setConfig(config)
        c = w.widget()
        c.setCurrentIndex(c.findText('value c'))
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldint" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldint" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldint"=3')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldint"<>3')

        # try with line edit
        w = QgsValueRelationSearchWidgetWrapper(layer, 1)
        config['UseCompleter'] = True
        w.setConfig(config)
        l = w.widget()
        l.setText('value b')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull),
                         '"fldint" IS NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull),
                         '"fldint" IS NOT NULL')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo),
                         '"fldint"=2')
        self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo),
                         '"fldint"<>2')
class TestLayerDependencies(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        """Run before all tests"""

        # create a temp spatialite db with a trigger
        fo = tempfile.NamedTemporaryFile()
        fn = fo.name
        fo.close()
        cls.fn = fn
        con = spatialite_connect(fn)
        cur = con.cursor()
        cur.execute("SELECT InitSpatialMetadata(1)")
        cur.execute("create table node(id integer primary key autoincrement);")
        cur.execute("select AddGeometryColumn('node', 'geom', 4326, 'POINT');")
        cur.execute(
            "create table section(id integer primary key autoincrement, node1 integer, node2 integer);"
        )
        cur.execute(
            "select AddGeometryColumn('section', 'geom', 4326, 'LINESTRING');")
        cur.execute(
            "create trigger add_nodes after insert on section begin insert into node (geom) values (st_startpoint(NEW.geom)); insert into node (geom) values (st_endpoint(NEW.geom)); end;"
        )
        cur.execute(
            "insert into node (geom) values (geomfromtext('point(0 0)', 4326));"
        )
        cur.execute(
            "insert into node (geom) values (geomfromtext('point(1 0)', 4326));"
        )
        cur.execute(
            "create table node2(id integer primary key autoincrement);")
        cur.execute(
            "select AddGeometryColumn('node2', 'geom', 4326, 'POINT');")
        cur.execute(
            "create trigger add_nodes2 after insert on node begin insert into node2 (geom) values (st_translate(NEW.geom, 0.2, 0, 0)); end;"
        )
        con.commit()
        con.close()

        cls.pointsLayer = QgsVectorLayer(
            "dbname='%s' table=\"node\" (geom) sql=" % fn, "points",
            "spatialite")
        assert (cls.pointsLayer.isValid())
        cls.linesLayer = QgsVectorLayer(
            "dbname='%s' table=\"section\" (geom) sql=" % fn, "lines",
            "spatialite")
        assert (cls.linesLayer.isValid())
        cls.pointsLayer2 = QgsVectorLayer(
            "dbname='%s' table=\"node2\" (geom) sql=" % fn, "_points2",
            "spatialite")
        assert (cls.pointsLayer2.isValid())
        QgsProject.instance().addMapLayers(
            [cls.pointsLayer, cls.linesLayer, cls.pointsLayer2])

        # save the project file
        fo = tempfile.NamedTemporaryFile()
        fn = fo.name
        fo.close()
        cls.projectFile = fn
        QgsProject.instance().setFileName(cls.projectFile)
        QgsProject.instance().write()

    @classmethod
    def tearDownClass(cls):
        """Run after all tests"""
        pass

    def setUp(self):
        """Run before each test."""
        pass

    def tearDown(self):
        """Run after each test."""
        pass

    def test_resetSnappingIndex(self):
        self.pointsLayer.setDependencies([])
        self.linesLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(
            self.pointsLayer,
            QgsSnappingConfig.IndividualLayerSettings(True,
                                                      QgsSnappingConfig.Vertex,
                                                      20, QgsTolerance.Pixels))
        u.setConfig(cfg)

        m = u.snapToMap(QPoint(95, 100))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(1, 0))

        f = QgsFeature(self.linesLayer.fields())
        f.setId(1)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()

        l1 = len([f for f in self.pointsLayer.getFeatures()])
        self.assertEqual(l1, 4)
        m = u.snapToMap(QPoint(95, 0))
        # snapping not updated
        self.pointsLayer.setDependencies([])
        self.assertEqual(m.isValid(), False)

        # set layer dependencies
        self.pointsLayer.setDependencies(
            [QgsMapLayerDependency(self.linesLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(2)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the snapped point is ok
        m = u.snapToMap(QPoint(45, 50))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(0.5, 0.5))
        self.pointsLayer.setDependencies([])

        # test chained layer dependencies A -> B -> C
        cfg.setIndividualLayerSettings(
            self.pointsLayer2,
            QgsSnappingConfig.IndividualLayerSettings(True,
                                                      QgsSnappingConfig.Vertex,
                                                      20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        self.pointsLayer.setDependencies(
            [QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies(
            [QgsMapLayerDependency(self.pointsLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(3)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is ok
        m = u.snapToMap(QPoint(75, 100 - 80))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(0.7, 0.8))
        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])

    def test_cycleDetection(self):
        self.assertTrue(
            self.pointsLayer.setDependencies(
                [QgsMapLayerDependency(self.linesLayer.id())]))
        self.assertFalse(
            self.linesLayer.setDependencies(
                [QgsMapLayerDependency(self.pointsLayer.id())]))
        self.pointsLayer.setDependencies([])
        self.linesLayer.setDependencies([])

    def test_layerDefinitionRewriteId(self):
        tmpfile = os.path.join(tempfile.tempdir, "test.qlr")

        ltr = QgsProject.instance().layerTreeRoot()

        self.pointsLayer.setDependencies(
            [QgsMapLayerDependency(self.linesLayer.id())])

        QgsLayerDefinition.exportLayerDefinition(tmpfile, [ltr])

        grp = ltr.addGroup("imported")
        QgsLayerDefinition.loadLayerDefinition(tmpfile, QgsProject.instance(),
                                               grp)

        newPointsLayer = None
        newLinesLayer = None
        for l in grp.findLayers():
            if l.layerId().startswith('points'):
                newPointsLayer = l.layer()
            elif l.layerId().startswith('lines'):
                newLinesLayer = l.layer()
        self.assertIsNotNone(newPointsLayer)
        self.assertIsNotNone(newLinesLayer)
        self.assertTrue(newLinesLayer.id(
        ) in [dep.layerId() for dep in newPointsLayer.dependencies()])

        self.pointsLayer.setDependencies([])

    def test_signalConnection(self):
        # remove all layers
        QgsProject.instance().removeAllMapLayers()
        # set dependencies and add back layers
        self.pointsLayer = QgsVectorLayer(
            "dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points",
            "spatialite")
        assert (self.pointsLayer.isValid())
        self.linesLayer = QgsVectorLayer(
            "dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines",
            "spatialite")
        assert (self.linesLayer.isValid())
        self.pointsLayer2 = QgsVectorLayer(
            "dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2",
            "spatialite")
        assert (self.pointsLayer2.isValid())
        self.pointsLayer.setDependencies(
            [QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies(
            [QgsMapLayerDependency(self.pointsLayer.id())])
        # this should update connections between layers
        QgsProject.instance().addMapLayers([self.pointsLayer])
        QgsProject.instance().addMapLayers([self.linesLayer])
        QgsProject.instance().addMapLayers([self.pointsLayer2])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(
            self.pointsLayer,
            QgsSnappingConfig.IndividualLayerSettings(True,
                                                      QgsSnappingConfig.Vertex,
                                                      20, QgsTolerance.Pixels))
        cfg.setIndividualLayerSettings(
            self.pointsLayer2,
            QgsSnappingConfig.IndividualLayerSettings(True,
                                                      QgsSnappingConfig.Vertex,
                                                      20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(4)
        geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is ok
        m = u.snapToMap(QPoint(75, 100 - 0))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(0.8, 0.0))

        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
Exemple #58
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()])
Exemple #59
0
    def testDistance(self):
        self.checkConstructWrapper(QgsProcessingParameterDistance('test'),
                                   DistanceWidgetWrapper)

        alg = QgsApplication.processingRegistry().algorithmById(
            'native:centroids')
        dlg = AlgorithmDialog(alg)
        param = QgsProcessingParameterDistance('test')
        wrapper = DistanceWidgetWrapper(param, dlg)
        widget = wrapper.createWidget()

        # test units
        widget.show()

        # crs values
        widget.setUnitParameterValue('EPSG:3111')
        self.assertEqual(widget.label.text(), 'meters')
        self.assertFalse(widget.warning_label.isVisible())
        self.assertTrue(widget.units_combo.isVisible())
        self.assertFalse(widget.label.isVisible())
        self.assertEqual(widget.units_combo.currentData(),
                         QgsUnitTypes.DistanceMeters)

        widget.setUnitParameterValue('EPSG:4326')
        self.assertEqual(widget.label.text(), 'degrees')
        self.assertTrue(widget.warning_label.isVisible())
        self.assertFalse(widget.units_combo.isVisible())
        self.assertTrue(widget.label.isVisible())

        widget.setUnitParameterValue(QgsCoordinateReferenceSystem('EPSG:3111'))
        self.assertEqual(widget.label.text(), 'meters')
        self.assertFalse(widget.warning_label.isVisible())
        self.assertTrue(widget.units_combo.isVisible())
        self.assertFalse(widget.label.isVisible())
        self.assertEqual(widget.units_combo.currentData(),
                         QgsUnitTypes.DistanceMeters)

        widget.setUnitParameterValue(QgsCoordinateReferenceSystem('EPSG:4326'))
        self.assertEqual(widget.label.text(), 'degrees')
        self.assertTrue(widget.warning_label.isVisible())
        self.assertFalse(widget.units_combo.isVisible())
        self.assertTrue(widget.label.isVisible())

        # layer values
        vl = QgsVectorLayer("Polygon?crs=epsg:3111&field=pk:int", "vl",
                            "memory")
        widget.setUnitParameterValue(vl)
        self.assertEqual(widget.label.text(), 'meters')
        self.assertFalse(widget.warning_label.isVisible())
        self.assertTrue(widget.units_combo.isVisible())
        self.assertFalse(widget.label.isVisible())
        self.assertEqual(widget.units_combo.currentData(),
                         QgsUnitTypes.DistanceMeters)

        vl2 = QgsVectorLayer("Polygon?crs=epsg:4326&field=pk:int", "vl",
                             "memory")
        widget.setUnitParameterValue(vl2)
        self.assertEqual(widget.label.text(), 'degrees')
        self.assertTrue(widget.warning_label.isVisible())
        self.assertFalse(widget.units_combo.isVisible())
        self.assertTrue(widget.label.isVisible())

        # unresolvable values
        widget.setUnitParameterValue(vl.id())
        self.assertEqual(widget.label.text(), '<unknown>')
        self.assertFalse(widget.warning_label.isVisible())
        self.assertFalse(widget.units_combo.isVisible())
        self.assertTrue(widget.label.isVisible())

        # resolvable text value
        QgsProject.instance().addMapLayer(vl)
        widget.setUnitParameterValue(vl.id())
        self.assertEqual(widget.label.text(), 'meters')
        self.assertFalse(widget.warning_label.isVisible())
        self.assertTrue(widget.units_combo.isVisible())
        self.assertFalse(widget.label.isVisible())
        self.assertEqual(widget.units_combo.currentData(),
                         QgsUnitTypes.DistanceMeters)

        widget.setValue(5)
        self.assertEqual(widget.getValue(), 5)
        widget.units_combo.setCurrentIndex(
            widget.units_combo.findData(QgsUnitTypes.DistanceKilometers))
        self.assertEqual(widget.getValue(), 5000)
        widget.setValue(2)
        self.assertEqual(widget.getValue(), 2000)

        widget.setUnitParameterValue(vl.id())
        self.assertEqual(widget.getValue(), 2)
        widget.setValue(5)
        self.assertEqual(widget.getValue(), 5)

        widget.deleteLater()
    def test_settings_round_trip(self):  # pylint: disable=too-many-statements
        """
        Test setting and retrieving settings results in identical results
        """
        layer_path = os.path.join(
            os.path.dirname(__file__), 'test_layer.geojson')

        vl1 = QgsVectorLayer(layer_path, 'test_layer', 'ogr')
        vl2 = QgsVectorLayer(layer_path, 'test_layer1', 'ogr')
        vl3 = QgsVectorLayer(layer_path, 'test_layer2', 'ogr')
        QgsProject.instance().addMapLayers([vl1, vl2, vl3])

        dialog = DataPlotlyPanelWidget(None, override_iface=IFACE)
        settings = dialog.get_settings()
        # default should be scatter plot
        self.assertEqual(settings.plot_type, 'scatter')
        # print('dialog loaded')

        # customise settings
        settings.plot_type = 'bar'
        settings.properties['name'] = 'my legend title'
        settings.properties['hover_text'] = 'y'
        settings.properties['box_orientation'] = 'h'
        settings.properties['normalization'] = 'probability'
        settings.properties['box_stat'] = 'sd'
        settings.properties['box_outliers'] = 'suspectedoutliers'
        settings.properties['violin_side'] = 'negative'
        settings.properties['show_mean_line'] = True
        settings.properties['cumulative'] = True
        settings.properties['invert_hist'] = 'decreasing'
        settings.source_layer_id = vl3.id()
        settings.properties['x_name'] = 'so4'
        settings.properties['y_name'] = 'ca'
        settings.properties['z_name'] = 'mg'
        settings.properties['color_scale'] = 'Earth'
        settings.properties['violin_box'] = True
        settings.properties['layout_filter_by_map'] = True
        settings.properties['layout_filter_by_atlas'] = True

        # TODO: likely need to test other settings.properties values here!

        settings.layout['legend'] = False
        settings.layout['legend_orientation'] = 'h'
        settings.layout['title'] = 'my title'
        settings.layout['x_title'] = 'my x title'
        settings.layout['y_title'] = 'my y title'
        settings.layout['z_title'] = 'my z title'
        settings.layout['range_slider']['visible'] = True
        settings.layout['bar_mode'] = 'overlay'
        settings.layout['x_type'] = 'log'
        settings.layout['y_type'] = 'category'
        settings.layout['x_inv'] = 'reversed'
        settings.layout['y_inv'] = 'reversed'
        settings.layout['bargaps'] = 0.8
        settings.layout['additional_info_expression'] = '1+2'
        settings.layout['bins_check'] = True
        settings.layout['gridcolor'] = '#bdbfc0'

        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_FILTER,
                                                     QgsProperty.fromExpression('"ap">50'))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_MARKER_SIZE,
                                                     QgsProperty.fromExpression('5+64'))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_COLOR, QgsProperty.fromExpression("'red'"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_STROKE_WIDTH,
                                                     QgsProperty.fromExpression("12/2"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_TITLE,
                                                     QgsProperty.fromExpression("concat('my', '_title_', @some_var)"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_LEGEND_TITLE,
                                                     QgsProperty.fromExpression("concat('my', '_legend_', @some_var)"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_X_TITLE,
                                                     QgsProperty.fromExpression("concat('my', '_x_axis_', @some_var)"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_Y_TITLE,
                                                     QgsProperty.fromExpression("concat('my', '_y_axis_', @some_var)"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_Z_TITLE,
                                                     QgsProperty.fromExpression("concat('my', '_z_axis_', @some_var)"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_X_MIN, QgsProperty.fromExpression("-1*10"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_X_MAX, QgsProperty.fromExpression("+1*10"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_Y_MIN, QgsProperty.fromExpression("-1*10"))
        settings.data_defined_properties.setProperty(PlotSettings.PROPERTY_Y_MAX, QgsProperty.fromExpression("+1*10"))

        dialog2 = DataPlotlyPanelWidget(None, override_iface=IFACE)
        dialog2.set_settings(settings)

        # print('set settings')

        self.assertEqual(dialog2.get_settings().plot_type, settings.plot_type)
        for k in settings.properties.keys():
            # print(k)
            if k in ['x', 'y', 'z', 'additional_hover_text', 'featureIds', 'featureBox', 'custom']:
                continue
            self.assertEqual(dialog2.get_settings().properties[k], settings.properties[k])
        for k in settings.layout.keys():
            self.assertEqual(dialog2.get_settings().layout[k], settings.layout[k])
        self.assertEqual(dialog2.get_settings().source_layer_id, vl3.id())
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_FILTER),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_FILTER))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_MARKER_SIZE),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_MARKER_SIZE))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_COLOR),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_COLOR))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_STROKE_WIDTH),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_STROKE_WIDTH))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_X_MIN),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_X_MIN))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_X_MAX),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_X_MAX))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_Y_MIN),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_Y_MIN))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_Y_MAX),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_Y_MAX))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_TITLE),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_TITLE))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_LEGEND_TITLE),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_LEGEND_TITLE))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_X_TITLE),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_X_TITLE))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_Y_TITLE),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_Y_TITLE))
        self.assertEqual(dialog2.get_settings().data_defined_properties.property(PlotSettings.PROPERTY_Z_TITLE),
                         settings.data_defined_properties.property(PlotSettings.PROPERTY_Z_TITLE))

        dialog2.deleteLater()
        del dialog2

        settings = dialog.get_settings()
        dialog.deleteLater()
        del dialog

        dialog3 = DataPlotlyPanelWidget(None, override_iface=IFACE)
        # print('dialog 2')
        dialog3.set_settings(settings)
        # print('set settings')

        self.assertEqual(dialog3.get_settings().plot_type, settings.plot_type)
        for k in settings.properties.keys():
            # print(k)
            self.assertEqual(dialog3.get_settings().properties[k], settings.properties[k])
        self.assertEqual(dialog3.get_settings().properties, settings.properties)
        for k in settings.layout.keys():
            # print(k)
            self.assertEqual(dialog3.get_settings().layout[k], settings.layout[k])

        dialog3.deleteLater()
        del dialog3

        # print('done')
        QgsProject.instance().clear()