def test_zip_filename(self): tmpDir = QTemporaryDir() tmpFile = "{}/project.qgz".format(tmpDir.path()) project = QgsProject() self.assertFalse(project.write()) project.setFileName(tmpFile) self.assertTrue(project.write()) self.assertTrue(os.path.isfile(tmpFile))
def testRelativePaths(self): """ Test whether paths to layer sources are stored as relative to the project path """ tmpDir = QTemporaryDir() tmpFile = "{}/project.qgs".format(tmpDir.path()) copyfile(os.path.join(TEST_DATA_DIR, "points.shp"), os.path.join(tmpDir.path(), "points.shp")) copyfile(os.path.join(TEST_DATA_DIR, "points.dbf"), os.path.join(tmpDir.path(), "points.dbf")) copyfile(os.path.join(TEST_DATA_DIR, "points.shx"), os.path.join(tmpDir.path(), "points.shx")) copyfile(os.path.join(TEST_DATA_DIR, "lines.shp"), os.path.join(tmpDir.path(), "lines.shp")) copyfile(os.path.join(TEST_DATA_DIR, "lines.dbf"), os.path.join(tmpDir.path(), "lines.dbf")) copyfile(os.path.join(TEST_DATA_DIR, "lines.shx"), os.path.join(tmpDir.path(), "lines.shx")) copyfile(os.path.join(TEST_DATA_DIR, "landsat_4326.tif"), os.path.join(tmpDir.path(), "landsat_4326.tif")) project = QgsProject() l0 = QgsVectorLayer(os.path.join(tmpDir.path(), "points.shp"), "points", "ogr") l1 = QgsVectorLayer(os.path.join(tmpDir.path(), "lines.shp"), "lines", "ogr") l2 = QgsRasterLayer(os.path.join(tmpDir.path(), "landsat_4326.tif"), "landsat", "gdal") self.assertTrue(l0.isValid()) self.assertTrue(l1.isValid()) self.assertTrue(l2.isValid()) self.assertTrue(project.addMapLayers([l0, l1, l2])) self.assertTrue(project.write(tmpFile)) del project with open(tmpFile, 'r') as f: content = ''.join(f.readlines()) self.assertTrue('source="./lines.shp"' in content) self.assertTrue('source="./points.shp"' in content) self.assertTrue('source="./landsat_4326.tif"' in content) # Re-read the project and store absolute project = QgsProject() self.assertTrue(project.read(tmpFile)) store = project.layerStore() self.assertEquals(set([l.name() for l in store.mapLayers().values()]), set(['lines', 'landsat', 'points'])) project.writeEntryBool('Paths', '/Absolute', True) tmpFile2 = "{}/project2.qgs".format(tmpDir.path()) self.assertTrue(project.write(tmpFile2)) with open(tmpFile2, 'r') as f: content = ''.join(f.readlines()) self.assertTrue('source="{}/lines.shp"'.format(tmpDir.path()) in content) self.assertTrue('source="{}/points.shp"'.format(tmpDir.path()) in content) self.assertTrue('source="{}/landsat_4326.tif"'.format(tmpDir.path()) in content) del project
def test_zip_new_project(self): tmpDir = QTemporaryDir() tmpFile = "{}/project.qgz".format(tmpDir.path()) # zip with existing file open(tmpFile, 'a').close() project = QgsProject() self.assertTrue(project.write(tmpFile)) # zip with non existing file os.remove(tmpFile) project = QgsProject() self.assertTrue(project.write(tmpFile)) self.assertTrue(os.path.isfile(tmpFile))
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())
def testSaveRestoreFromProject(self): p = QgsProject() provider = ProjectProvider(p) # add some algorithms alg = QgsProcessingModelAlgorithm('test name', 'test group') provider.add_model(alg) alg2 = QgsProcessingModelAlgorithm('test name2', 'test group2') provider.add_model(alg2) self.assertEqual(len(provider.algorithms()), 2) tmp_file = QTemporaryFile() tmp_file.open() # fileName is no available until open temp_path = tmp_file.fileName() tmp_file.close() self.assertTrue(p.write(temp_path)) # restore project p2 = QgsProject() provider2 = ProjectProvider(p2) self.assertTrue(p2.read(temp_path)) self.assertEqual(len(provider2.model_definitions), 2) self.assertEqual(len(provider2.algorithms()), 2) self.assertEqual(provider2.algorithms()[0].name(), 'test name') self.assertEqual(provider2.algorithms()[0].group(), 'test group') self.assertEqual(provider2.algorithms()[1].name(), 'test name2') self.assertEqual(provider2.algorithms()[1].group(), 'test group2') # clear project should remove algorithms p2.clear() self.assertFalse(provider2.algorithms())
def testSaveLoadProject(self): schema_uri = encode_uri(self.ds_uri, 'qgis_test') project_uri = encode_uri(self.ds_uri, 'qgis_test', 'abc') self.dropProjectsTable() # make sure we have a clean start prj = QgsProject() uri = self.vl.source() vl1 = QgsVectorLayer(uri, 'test', 'postgres') self.assertEqual(vl1.isValid(), True) prj.addMapLayer(vl1) prj_storage = QgsApplication.projectStorageRegistry().projectStorageFromType("postgresql") self.assertTrue(prj_storage) lst0 = prj_storage.listProjects(schema_uri) self.assertEqual(lst0, []) # try to save project in the database prj.setFileName(project_uri) res = prj.write() self.assertTrue(res) lst1 = prj_storage.listProjects(schema_uri) self.assertEqual(lst1, ["abc"]) # now try to load the project back prj2 = QgsProject() prj2.setFileName(project_uri) res = prj2.read() self.assertTrue(res) self.assertEqual(len(prj2.mapLayers()), 1) self.assertEqual(prj2.baseName(), "abc") self.assertEqual(prj2.absoluteFilePath(), "") # path not supported for project storages self.assertTrue(abs(prj2.lastModified().secsTo(QDateTime.currentDateTime())) < 10) # try to see project's metadata res, metadata = prj_storage.readProjectStorageMetadata(project_uri) self.assertTrue(res) self.assertEqual(metadata.name, "abc") time_project = metadata.lastModified time_now = QDateTime.currentDateTime() time_diff = time_now.secsTo(time_project) self.assertTrue(abs(time_diff) < 10) # try to remove the project res = prj_storage.removeProject(project_uri) self.assertTrue(res) lst2 = prj_storage.listProjects(schema_uri) self.assertEqual(lst2, []) self.dropProjectsTable() # make sure we have a clean finish... "leave no trace"
def testSymbolicLinkInProjectPath(self): """ Test whether paths to layer sources relative to the project are stored correctly when project'name contains a symbolic link. In other words, test if project's and layers' names are correctly resolved. """ tmpDir = QTemporaryDir() tmpFile = "{}/project.qgs".format(tmpDir.path()) copyfile(os.path.join(TEST_DATA_DIR, "points.shp"), os.path.join(tmpDir.path(), "points.shp")) copyfile(os.path.join(TEST_DATA_DIR, "points.dbf"), os.path.join(tmpDir.path(), "points.dbf")) copyfile(os.path.join(TEST_DATA_DIR, "points.shx"), os.path.join(tmpDir.path(), "points.shx")) copyfile(os.path.join(TEST_DATA_DIR, "lines.shp"), os.path.join(tmpDir.path(), "lines.shp")) copyfile(os.path.join(TEST_DATA_DIR, "lines.dbf"), os.path.join(tmpDir.path(), "lines.dbf")) copyfile(os.path.join(TEST_DATA_DIR, "lines.shx"), os.path.join(tmpDir.path(), "lines.shx")) copyfile(os.path.join(TEST_DATA_DIR, "landsat_4326.tif"), os.path.join(tmpDir.path(), "landsat_4326.tif")) project = QgsProject() l0 = QgsVectorLayer(os.path.join(tmpDir.path(), "points.shp"), "points", "ogr") l1 = QgsVectorLayer(os.path.join(tmpDir.path(), "lines.shp"), "lines", "ogr") l2 = QgsRasterLayer(os.path.join(tmpDir.path(), "landsat_4326.tif"), "landsat", "gdal") self.assertTrue(l0.isValid()) self.assertTrue(l1.isValid()) self.assertTrue(l2.isValid()) self.assertTrue(project.addMapLayers([l0, l1, l2])) self.assertTrue(project.write(tmpFile)) del project # Create symbolic link to previous project tmpDir2 = QTemporaryDir() symlinkDir = os.path.join(tmpDir2.path(), "dir") os.symlink(tmpDir.path(), symlinkDir) tmpFile = "{}/project.qgs".format(symlinkDir) # Open project from symmlink and force re-save. project = QgsProject() self.assertTrue(project.read(tmpFile)) self.assertTrue(project.write(tmpFile)) del project with open(tmpFile, 'r') as f: content = ''.join(f.readlines()) self.assertTrue('source="./lines.shp"' in content) self.assertTrue('source="./points.shp"' in content) self.assertTrue('source="./landsat_4326.tif"' in content)
def testCustomLayerOrder(self): """ test project layer order""" prj = QgsProject() 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]) layer_order_changed_spy = QSignalSpy(prj.layerTreeRoot().customLayerOrderChanged) prj.layerTreeRoot().setCustomLayerOrder([layer2, layer]) self.assertEqual(len(layer_order_changed_spy), 1) prj.layerTreeRoot().setCustomLayerOrder([layer2, layer]) self.assertEqual(len(layer_order_changed_spy), 1) # no signal, order not changed self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [layer2, layer]) prj.layerTreeRoot().setCustomLayerOrder([layer]) self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [layer]) self.assertEqual(len(layer_order_changed_spy), 2) # remove a layer prj.layerTreeRoot().setCustomLayerOrder([layer2, layer, layer3]) self.assertEqual(len(layer_order_changed_spy), 3) prj.removeMapLayer(layer) self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [layer2, layer3]) self.assertEqual(len(layer_order_changed_spy), 4) # save and restore file_name = os.path.join(QDir.tempPath(), 'proj.qgs') prj.setFileName(file_name) prj.write() prj2 = QgsProject() prj2.setFileName(file_name) prj2.read() self.assertEqual([l.id() for l in prj2.layerTreeRoot().customLayerOrder()], [layer2.id(), layer3.id()]) # clear project prj.clear() self.assertEqual(prj.layerTreeRoot().customLayerOrder(), [])
def testPalPropertiesReadWrite(self): tmpDir = QTemporaryDir() tmpFile = "{}/project.qgs".format(tmpDir.path()) s0 = QgsLabelingEngineSettings() s0.setNumCandidatePositions(3, 33, 333) p0 = QgsProject() p0.setFileName(tmpFile) p0.setLabelingEngineSettings(s0) p0.write() p1 = QgsProject() p1.read(tmpFile) s1 = p1.labelingEngineSettings() candidates = s1.numCandidatePositions() self.assertEqual(candidates[0], 3) self.assertEqual(candidates[1], 33) self.assertEqual(candidates[2], 333)
def testQgdCreation(self): # New project p = QgsProject() self.assertTrue(p.auxiliaryStorage().isValid()) # Save the project path = tmpPath() qgs = path + '.qgs' self.assertTrue(p.write(qgs)) self.assertTrue(os.path.exists(qgs)) # Auxiliary storage is empty so .qgd file should not be saved qgd = path + '.qgd' self.assertFalse(os.path.exists(qgd)) # Add a vector layer and an auxiliary layer in the project vl = createLayer() self.assertTrue(vl.isValid()) p.addMapLayers([vl]) pkf = vl.fields().field(vl.fields().indexOf('pk')) al = p.auxiliaryStorage().createAuxiliaryLayer(pkf, vl) self.assertTrue(al.isValid()) vl.setAuxiliaryLayer(al) # Add an auxiliary field to have a non empty auxiliary storage pdef = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut') self.assertTrue(al.addAuxiliaryField(pdef)) # Save the project newpath = tmpPath() qgs = newpath + '.qgs' self.assertTrue(p.write(qgs)) self.assertTrue(os.path.exists(qgs)) # Auxiliary storage is NOT empty so .qgd file should be saved now qgd = newpath + '.qgd' self.assertTrue(os.path.exists(qgd))
def testWriteEntry(self): tmpDir = QTemporaryDir() tmpFile = "{}/project.qgs".format(tmpDir.path()) # zip with existing file project = QgsProject() query = 'select * from "sample DH" where "sample DH"."Elev" > 130 and "sample DH"."Elev" < 140' self.assertTrue(project.writeEntry('myscope', 'myentry', query)) self.assertTrue(project.write(tmpFile)) self.assertTrue(project.read(tmpFile)) q, ok = project.readEntry('myscope', 'myentry') self.assertTrue(ok) self.assertEqual(q, query)
def processAlgorithm(self, parameters, context, feedback): project = QgsProject() project.setFileName( os.path.join(parameters[self.FOLDER], "all-outputs-qgis.qgs")) project.setCrs(QgsCoordinateReferenceSystem('EPSG:27700')) def getMaxValue(layer, fieldname): maxfound = float("-inf") for f in layer.getFeatures(): attr = f.attribute(fieldname) assert attr >= 0 if attr > maxfound: maxfound = attr return maxfound with open( os.path.join(parameters[self.FOLDER], "all-town-metadata.json")) as f: metadata = json.load(f) classmethods = { 'quantile': QgsClassificationQuantile, 'jenks': QgsClassificationJenks, 'equal': QgsClassificationEqualInterval } html = "" output = [] views_sorted_by_mode = sorted(metadata["views"], key=lambda v: v["mode"]) for view in views_sorted_by_mode: keysymbol = u'🔑' viewname = view["label"] keysign = "" if viewname.find(keysymbol) != -1: viewname = viewname.replace(keysymbol, '', 1) keysign = "*** " viewname = keysign + view["mode"] + " " + viewname html += f""" <h2>{viewname}</h2> {view["description"]} <ul> """ for layer in view["layers"]: layername = viewname + " - " + layer["scalar_field_units"] layerpath = os.path.join(parameters[self.FOLDER], layer["file"]) vlayer = QgsVectorLayer(layerpath, layername, "ogr") if not vlayer.isValid(): feedback.pushInfo("Layer failed to load: " + layerpath) else: context.temporaryLayerStore().addMapLayer(vlayer) html += f"""<li><b>file:</b> {layer["file"]}""" if "symbol_field" in layer: html += f"""<ul> <li><b>symbol field:</b> {layer["symbol_field"]} </ul> """ categories = [] scalar_fieldname = layer["scalar_field"] maxvalue = getMaxValue(vlayer, scalar_fieldname) feedback.pushInfo("Max value for %s is %f" % (scalar_fieldname, maxvalue)) for formality in ["I", "F"]: for severity, colour in [(3, 'red'), (2, 'yellow'), (1, 'green')]: colour = { ("I", "red"): "#FF0000", ("I", "yellow"): "#FFFF00", ("I", "green"): "#00FF00", ("F", "red"): "#FF9999", ("F", "yellow"): "#FFFF66", ("F", "green"): "#99FF99", }[(formality, colour)] symbol_code = "%s%d" % (formality, severity) if formality == "F": symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': '3', 'outline_color': '#888888' }) else: assert (formality == "I") symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': '3', 'outline_color': '#000000', 'name': 'star' }) objTransf = QgsSizeScaleTransformer( QgsSizeScaleTransformer.Flannery, 0, #minvalue maxvalue, #maxvalue 3, #minsize 10, #maxsize 0, #nullsize 1) #exponent objProp = QgsProperty() objProp.setField(scalar_fieldname) objProp.setTransformer(objTransf) symbol.setDataDefinedSize(objProp) label = { "F": "Formal", "I": "Informal" }[formality] + " " + { 3: "Major", 2: "Secondary", 1: "Tertiary" }[severity] cat = QgsRendererCategory( symbol_code, symbol, label, True) categories.append(cat) renderer = QgsCategorizedSymbolRenderer( "Crossings", categories) renderer.setClassAttribute(layer["symbol_field"]) vlayer.setRenderer(renderer) else: html += f"""<ul> <li><b>field:</b> {layer["scalar_field"]} <li><b>units:</b> {layer["scalar_field_units"]} <li><b>recommended classification:</b> {layer["classes"]} </ul> """ default_style = QgsStyle().defaultStyle() color_ramp = default_style.colorRamp('bt') renderer = QgsGraduatedSymbolRenderer() renderer.setClassAttribute(layer["scalar_field"]) classmethod = classmethods[layer["classes"]]() renderer.setClassificationMethod(classmethod) renderer.updateClasses(vlayer, 5) renderer.updateColorRamp(color_ramp) vlayer.setRenderer(renderer) project.addMapLayer(vlayer) feedback.pushInfo("Loaded " + layerpath) html += "</ul>" project.write() town = views_sorted_by_mode[0]["town"] with open(os.path.join(parameters[self.FOLDER], "metadata.html"), "w") as htmlfile: htmlfile.write( f"<html><head><title>{town} metadata</title></head><body><h1>{town}</h1>{html}</body></html>" ) return {self.OUTPUT: output}
def processAlgorithm(self, parameters, context, feedback): project = QgsProject() project.setFileName( os.path.join(parameters[self.FOLDER], "summary-cycle-qgis.qgs")) project.setCrs(QgsCoordinateReferenceSystem('EPSG:27700')) def getMaxValue(layer, fieldname): maxfound = float("-inf") for f in layer.getFeatures(): attr = f.attribute(fieldname) assert attr >= 0 if attr > maxfound: maxfound = attr return maxfound def addFlowLayerLineWidth(layerpath, fieldname, colour, transparent, layername, widthscale=1): vlayer = QgsVectorLayer(layerpath, layername, "ogr") if not vlayer.isValid(): feedback.pushInfo("Layer failed to load: " + layerpath) else: context.temporaryLayerStore().addMapLayer(vlayer) maxvalue = getMaxValue(vlayer, fieldname) symbol = QgsLineSymbol.createSimple({ 'color': colour, 'size': '1' }) objTransf = QgsSizeScaleTransformer( QgsSizeScaleTransformer.Flannery, 0, #minvalue maxvalue, #maxvalue 0.1, #minsize 5 * widthscale, #maxsize 0, #nullsize 1) #exponent objProp = QgsProperty() objProp.setField(fieldname) objProp.setTransformer(objTransf) symbol.setDataDefinedWidth(objProp) renderer = QgsSingleSymbolRenderer(symbol) vlayer.setRenderer(renderer) vlayer.setOpacity(1 - transparent) project.addMapLayer(vlayer) feedback.pushInfo("Loaded " + layerpath) addFlowLayerLineWidth(parameters[self.PCTSHAPE], parameters[self.PCTFIELD], "red", 0, "School cycling Go Dutch scenario (pupils)", widthscale=0.5) addFlowLayerLineWidth(parameters[self.ALLCYCLESHAPE], parameters[self.ALLFLOWSFIELD], "blue", 0.65, "All current cycling flows (relative)") project.write() return {}
def testProjectStorage(self): # New project without fileName p0 = QgsProject() self.assertTrue(p0.auxiliaryStorage().isValid()) # Create new layers with key otherwise auxiliary layers are not # automacially created when added in project vl0 = createLayer() vl0Shp = writeShape(vl0, 'vl0.shp') vl1 = createLayer() vl1Shp = writeShape(vl1, 'vl1.shp') vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr') self.assertTrue(vl0.isValid()) vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr') self.assertTrue(vl1.isValid()) # Add layers to project and check underlying auxiliary layers p0.addMapLayers([vl0, vl1]) self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk')) self.assertTrue(vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char')) al0 = vl0.auxiliaryLayer() al1 = vl1.auxiliaryLayer() self.assertEqual(al0.joinInfo().targetFieldName(), 'pk') self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char') # Add a field in auxiliary layers pdef0 = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut') self.assertTrue(al0.addAuxiliaryField(pdef0)) pdef1 = QgsPropertyDefinition('propname1', QgsPropertyDefinition.DataTypeString, '', '', 'ut') self.assertTrue(al1.addAuxiliaryField(pdef1)) # Check auxiliary fields names af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False) self.assertEqual(af0Name, 'ut_propname') af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False) self.assertEqual(af1Name, 'ut_propname1') # Set value for auxiliary fields req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl0.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True) index0 = vl0.fields().indexOf(af0Name) vl0.changeAttributeValue(f.id(), index0, 333) req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True) index1 = vl1.fields().indexOf(af1Name) vl1.changeAttributeValue(f.id(), index0, 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) vl1.changeAttributeValue(f.id(), index0, 'myvalue1') # Save the project in a zip file f = tmpPath() + '.qgz' p0.write(f) # Open the zip file with embedded auxiliary storage p1 = QgsProject() p1.read(f) # Check that auxiliary fields are well loaded in layers self.assertEqual(len(p1.mapLayers().values()), 2) for vl in p1.mapLayers().values(): al = vl.auxiliaryLayer() self.assertEqual(len(al.auxiliaryFields()), 1) af = al.auxiliaryFields()[0] afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af) self.assertEqual(afPropDef.origin(), 'ut') if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk': self.assertEqual(afPropDef.name(), 'propname') self.assertEqual(al.featureCount(), 1) req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index0], 333.0) else: # num_char self.assertEqual(al.featureCount(), 2) self.assertEqual(afPropDef.name(), 'propname1') req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue1')
def processAlgorithm(self, parameters, context, feedback): project = QgsProject() project.setFileName( os.path.join(parameters[self.FOLDER], "summary-walk-qgis.qgs")) project.setCrs(QgsCoordinateReferenceSystem('EPSG:27700')) def getMaxValue(layer, fieldname): maxfound = float("-inf") for f in layer.getFeatures(): attr = f.attribute(fieldname) assert attr >= 0 if attr > maxfound: maxfound = attr return maxfound def addFlowLayerLineWidth(layerpath, fieldname, colour, transparent, layername, widthscale=1): vlayer = QgsVectorLayer(layerpath, layername, "ogr") if not vlayer.isValid(): feedback.pushInfo("Layer failed to load: " + layerpath) else: context.temporaryLayerStore().addMapLayer(vlayer) maxvalue = getMaxValue(vlayer, fieldname) symbol = QgsLineSymbol.createSimple({ 'color': colour, 'size': '1' }) objTransf = QgsSizeScaleTransformer( QgsSizeScaleTransformer.Flannery, 0, #minvalue maxvalue, #maxvalue 0.1, #minsize 5 * widthscale, #maxsize 0, #nullsize 1) #exponent objProp = QgsProperty() objProp.setField(fieldname) objProp.setTransformer(objTransf) symbol.setDataDefinedWidth(objProp) renderer = QgsSingleSymbolRenderer(symbol) vlayer.setRenderer(renderer) vlayer.setOpacity(1 - transparent) project.addMapLayer(vlayer) feedback.pushInfo("Loaded " + layerpath) def addCrossingsLayerSeveritySize(layerpath, colour, transparent, layername): vlayer = QgsVectorLayer(layerpath, layername, "ogr") if not vlayer.isValid(): feedback.pushInfo("Layer failed to load: " + layerpath) else: context.temporaryLayerStore().addMapLayer(vlayer) categories = [] for formality in ["I", "F"]: for severity, size in [(3, 8), (2, 6), (1, 4)]: symbol_code = "%s%d" % (formality, severity) if formality == "F": symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': str(size), 'outline_color': '#888888' }) else: assert (formality == "I") symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': str(size), 'outline_color': '#000000', 'name': 'star' }) label = { "F": "Formal", "I": "Informal" }[formality] + " " + { 3: "Major", 2: "Secondary", 1: "Tertiary" }[severity] cat = QgsRendererCategory(symbol_code, symbol, label, True) categories.append(cat) renderer = QgsCategorizedSymbolRenderer( "Crossings", categories) renderer.setClassAttribute("symbol") vlayer.setRenderer(renderer) vlayer.setOpacity(1 - transparent) project.addMapLayer(vlayer) feedback.pushInfo("Loaded " + layerpath) addFlowLayerLineWidth(parameters[self.DESTFLOWSSHP], parameters[self.DESTFLOWSFIELD], "red", 0, "School walking flows (pupils)", widthscale=0.5) addFlowLayerLineWidth(parameters[self.ALLFLOWSSHP], parameters[self.ALLFLOWSFIELD], "blue", 0.65, "All walking flows (relative)") addCrossingsLayerSeveritySize(parameters[self.DESTCROSSINGSSHP], "red", 0, "School crossings") addCrossingsLayerSeveritySize(parameters[self.ALLCROSSINGSSHP], "blue", 0.65, "All crossings") project.write() return {}
def test_wmts_document_cache_time(client): """ Test getcapabilites response time """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Copy project shutil.copy( client.getprojectpath("france_parts.qgs"), client.getprojectpath("france_parts_copy.qgs") ) # Delete document project = QgsProject() project.setFileName(client.getprojectpath("france_parts_copy.qgs").strpath) # Get project document root path docroot = cachefilter._cache.get_documents_root(project.fileName()) cachefilter.deleteCachedDocuments(project) assert not os.path.exists(docroot.as_posix()) parameters = { 'MAP': project.fileName(), 'REQUEST': 'GetCapabilities', 'SERVICE': 'WMTS' } # Get the cached path from the request parameters docpath = cachefilter._cache.get_document_cache( project.fileName(), parameters, '.xml' ).as_posix() assert not os.path.exists(docpath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(docpath) # Get time of document cache creation docmtime = os.stat(docpath).st_mtime projmtime = project.lastModified().toMSecsSinceEpoch() / 1000.0 assert projmtime < docmtime project.write() projmtime = project.lastModified().toMSecsSinceEpoch() / 1000.0 assert projmtime > docmtime # Make a second request rv = client.get(qs, project.fileName()) assert rv.status_code == 200 ndocmtime = os.stat(docpath).st_mtime projmtime = project.lastModified().toMSecsSinceEpoch() / 1000.0 assert projmtime < ndocmtime assert docmtime < ndocmtime # Clean files after testing Path(client.getprojectpath("france_parts_copy.qgs")).unlink()
def test_read_write_project2(self): """ Test reading and writing to project, signals based """ p = QgsProject() original = PlotSettings('test', properties={ 'marker_width': 2, 'marker_size': 5 }, layout={ 'title': 'my plot', 'legend_orientation': 'v', 'font_xlabel_color': '#00FFFF' }) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_FILTER, QgsProperty.fromExpression('"ap">50')) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_MARKER_SIZE, QgsProperty.fromExpression('5+6')) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_COLOR, QgsProperty.fromExpression("'red'")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_STROKE_WIDTH, QgsProperty.fromExpression('12/2')) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_TITLE, QgsProperty.fromExpression("concat('my', '_title')")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_LEGEND_TITLE, QgsProperty.fromExpression("concat('my', '_legend')")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_X_TITLE, QgsProperty.fromExpression("concat('my', '_x_axis')")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_Y_TITLE, QgsProperty.fromExpression("concat('my', '_y_axis')")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_Z_TITLE, QgsProperty.fromExpression("concat('my', '_z_axis')")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_X_MIN, QgsProperty.fromExpression("-1*10")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_X_MAX, QgsProperty.fromExpression("+1*10")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_Y_MIN, QgsProperty.fromExpression("-1*10")) original.data_defined_properties.setProperty( PlotSettings.PROPERTY_Y_MAX, QgsProperty.fromExpression("+1*10")) self.test_read_write_project2_written = False def write(doc): self.test_read_write_project2_written = True original.write_to_project(doc) p.writeProject.connect(write) path = os.path.join(tempfile.gettempdir(), 'test_dataplotly_project.qgs') self.assertTrue(p.write(path)) for _ in range(100): QCoreApplication.processEvents() self.assertTrue(self.test_read_write_project2_written) p2 = QgsProject() res = PlotSettings('gg') self.test_read_write_project2_read = False def read(doc): res.read_from_project(doc) self.test_read_write_project2_read = True p2.readProject.connect(read) self.assertTrue(p2.read(path)) for _ in range(100): QCoreApplication.processEvents() self.assertTrue(self.test_read_write_project2_read) self.assertEqual(res.plot_type, original.plot_type) self.assertEqual(res.properties, original.properties) self.assertEqual(res.layout, original.layout) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_FILTER), original.data_defined_properties.property( PlotSettings.PROPERTY_FILTER)) self.assertEqual( res.data_defined_properties.property( PlotSettings.PROPERTY_MARKER_SIZE), original.data_defined_properties.property( PlotSettings.PROPERTY_MARKER_SIZE)) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_COLOR), original.data_defined_properties.property( PlotSettings.PROPERTY_COLOR)) self.assertEqual( res.data_defined_properties.property( PlotSettings.PROPERTY_STROKE_WIDTH), original.data_defined_properties.property( PlotSettings.PROPERTY_STROKE_WIDTH)) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_TITLE), original.data_defined_properties.property( PlotSettings.PROPERTY_TITLE)) self.assertEqual( res.data_defined_properties.property( PlotSettings.PROPERTY_LEGEND_TITLE), original.data_defined_properties.property( PlotSettings.PROPERTY_LEGEND_TITLE)) self.assertEqual( res.data_defined_properties.property( PlotSettings.PROPERTY_X_TITLE), original.data_defined_properties.property( PlotSettings.PROPERTY_X_TITLE)) self.assertEqual( res.data_defined_properties.property( PlotSettings.PROPERTY_Y_TITLE), original.data_defined_properties.property( PlotSettings.PROPERTY_Y_TITLE)) self.assertEqual( res.data_defined_properties.property( PlotSettings.PROPERTY_Z_TITLE), original.data_defined_properties.property( PlotSettings.PROPERTY_Z_TITLE)) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_X_MIN), original.data_defined_properties.property( PlotSettings.PROPERTY_X_MIN)) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_X_MAX), original.data_defined_properties.property( PlotSettings.PROPERTY_X_MAX)) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_Y_MIN), original.data_defined_properties.property( PlotSettings.PROPERTY_Y_MIN)) self.assertEqual( res.data_defined_properties.property(PlotSettings.PROPERTY_Y_MAX), original.data_defined_properties.property( PlotSettings.PROPERTY_Y_MAX))
def test_zip_invalid_path(self): project = QgsProject() self.assertFalse(project.write()) self.assertFalse(project.write("")) self.assertFalse(project.write("/fake/test.zip"))
def create_basic_qgis_project(project_path=None, project_name=None): """ Create a basic QGIS project with OSM background and a simple vector layer. :return: Project file path on successful creation of a new project, None otherwise """ if project_path is None: project_path = get_new_qgis_project_filepath(project_name=project_name) if project_path is None: return False new_project = QgsProject() crs = QgsCoordinateReferenceSystem() crs.createFromString("EPSG:3857") new_project.setCrs(crs) new_project.setFileName(project_path) osm_url = "crs=EPSG:3857&type=xyz&zmin=0&zmax=19&url=http://tile.openstreetmap.org/{z}/{x}/{y}.png" osm_layer = QgsRasterLayer(osm_url, "OpenStreetMap", "wms") new_project.addMapLayer(osm_layer) mem_uri = "Point?crs=epsg:3857" mem_layer = QgsVectorLayer(mem_uri, "Survey points", "memory") res = mem_layer.dataProvider().addAttributes([ QgsField("date", QVariant.DateTime), QgsField("notes", QVariant.String), QgsField("photo", QVariant.String), ]) mem_layer.updateFields() vector_fname, err = save_vector_layer_as_gpkg( mem_layer, os.path.dirname(project_path)) if err: QMessageBox.warning(None, "Error Creating New Project", f"Couldn't save vector layer to:\n{vector_fname}") vector_layer = QgsVectorLayer(vector_fname, "Survey", "ogr") symbol = QgsMarkerSymbol.createSimple({ 'name': 'circle', 'color': '#d73027', 'size': '3', "outline_color": '#e8e8e8', 'outline_style': 'solid', 'outline_width': '0.4' }) vector_layer.renderer().setSymbol(symbol) fid_ws = QgsEditorWidgetSetup("Hidden", {}) vector_layer.setEditorWidgetSetup(0, fid_ws) datetime_config = { 'allow_null': True, 'calendar_popup': True, 'display_format': 'yyyy-MM-dd HH:mm:ss', 'field_format': 'yyyy-MM-dd HH:mm:ss', 'field_iso_format': False } datetime_ws = QgsEditorWidgetSetup("DateTime", datetime_config) vector_layer.setEditorWidgetSetup(1, datetime_ws) photo_config = { 'DocumentViewer': 1, 'DocumentViewerHeight': 0, 'DocumentViewerWidth': 0, 'FileWidget': True, 'FileWidgetButton': True, 'FileWidgetFilter': '', 'RelativeStorage': 1, 'StorageMode': 0, 'PropertyCollection': { 'name': NULL, 'properties': {}, 'type': 'collection' }, } photo_ws = QgsEditorWidgetSetup("ExternalResource", photo_config) vector_layer.setEditorWidgetSetup(3, photo_ws) new_project.addMapLayer(vector_layer) write_success = new_project.write() if not write_success: QMessageBox.warning(None, "Error Creating New Project", f"Couldn't create new project:\n{project_path}") return None return project_path
def setUpTestData(cls): super().setUpTestData() cls.temp_dir = QTemporaryDir() cls.temp_project_path = os.path.join(cls.temp_dir.path(), 'pg_openrouteservice.qgs') # Create test layer conn_str = "dbname='{NAME}' host={HOST} port={PORT} user='******' password='******' sslmode=disable".format( **settings.DATABASES['default']) cls.conn_uri = conn_str md = QgsProviderRegistry.instance().providerMetadata('postgres') conn = md.createConnection(conn_str, {}) conn.executeSql( "DROP SCHEMA IF EXISTS \"openrouteservice test\" CASCADE") conn.executeSql("CREATE SCHEMA \"openrouteservice test\"") conn.executeSql( "CREATE TABLE \"openrouteservice test\".openrouteservice_poly_not_compatible ( pk SERIAL NOT NULL, name TEXT, geom GEOMETRY(POLYGON, 4326), PRIMARY KEY ( pk ) )" ) conn.executeSql( "CREATE TABLE \"openrouteservice test\".openrouteservice_point_not_compatible ( pk SERIAL NOT NULL, value NUMERIC, group_index INTEGER, area NUMERIC, reachfactor NUMERIC, total_pop INTEGER, geom GEOMETRY(POINT, 4326), PRIMARY KEY ( pk ) )" ) conn.executeSql( "CREATE TABLE \"openrouteservice test\".openrouteservice_compatible ( pk SERIAL NOT NULL, value NUMERIC, group_index INTEGER, area NUMERIC, reachfactor NUMERIC, total_pop INTEGER, geom GEOMETRY(POLYGON, 4326), PRIMARY KEY ( pk ) )" ) conn.executeSql( "CREATE TABLE \"openrouteservice test\".openrouteservice_compatible_3857 ( pk SERIAL NOT NULL, value NUMERIC, group_index INTEGER, area NUMERIC, reachfactor NUMERIC, total_pop INTEGER, geom GEOMETRY(POLYGON, 3857), PRIMARY KEY ( pk ) )" ) # Input layers for async tests conn.executeSql( "CREATE TABLE \"openrouteservice test\".openrouteservice_point_3857 ( pk SERIAL NOT NULL, geom GEOMETRY(POINT, 3857), PRIMARY KEY ( pk ) )" ) conn.executeSql( "CREATE TABLE \"openrouteservice test\".openrouteservice_multipoint_4326 ( pk SERIAL NOT NULL, geom GEOMETRY(MULTIPOINT, 4326), PRIMARY KEY ( pk ) )" ) # Add sample points for async tests conn.executeSql( """INSERT INTO "openrouteservice test".openrouteservice_multipoint_4326 (geom) VALUES ( 'SRID=4326;MULTIPOINT ((-77.55542807059459 37.56350130888833), (-77.5513628235481 37.547924590224554), (-77.53848954123421 37.58068563329007), (-77.59608054105951 37.59518182260462))'::geometry), ('SRID=4326;MULTIPOINT ((-77.4077240945721 37.538254644499624), (-77.41991983571157 37.54470141434406), (-77.4260177062813 37.55920460826607), (-77.39349572990939 37.562427156963516), (-77.40840163574651 37.58337032579007))'::geometry)""" ) conn.executeSql( """INSERT INTO "openrouteservice test".openrouteservice_point_3857 (geom) VALUES ('SRID=3857;POINT (-8636824.820306677 4510025.909782101)'::geometry), ('SRID=3857;POINT (-8633657.031688528 4512364.0394764505)'::geometry), ('SRID=3857;POINT (-8637126.514460787 4512741.157169087)'::geometry), ('SRID=3857;POINT (-8634109.572919691 4503916.603161385)'::geometry)""" ) cls.layer_specs = {} project = QgsProject() for table_name, table_spec in { 'openrouteservice_poly_not_compatible': ('Polygon', 4326), 'openrouteservice_point_not_compatible': ('Point', 4326), 'openrouteservice_compatible': ('Polygon', 4326), 'openrouteservice_compatible_3857': ('Polygon', 3857), 'openrouteservice_point_3857': ('Point', 3857), 'openrouteservice_multipoint_4326': ('MultiPoint', 4326), }.items(): layer_uri = conn_str + " sslmode=disable key='pk' estimatedmetadata=false srid={srid} type={geometry_type} checkPrimaryKeyUnicity='0' table=\"openrouteservice test\".\"{table_name}\" (geom)".format( table_name=table_name, geometry_type=table_spec[0], srid=table_spec[1]) layer = QgsVectorLayer(layer_uri, table_name, 'postgres') assert layer.isValid() cls.layer_specs[table_name] = layer_uri project.addMapLayers([layer]) assert project.write(cls.temp_project_path) Project.objects.filter(title='Test openrouteservice project').delete() toc = buildLayerTreeNodeObject(project.layerTreeRoot()) cls.qdjango_project = Project(qgis_file=File( open(cls.temp_project_path, 'r')), title='Test openrouteservice project', group=cls.project_group, layers_tree=toc) cls.qdjango_project.save() for layer_id, layer in project.mapLayers().items(): _, created = Layer.objects.get_or_create( name=layer.name(), title=layer.name(), origname=layer.name(), qgs_layer_id=layer_id, srid=layer.crs().postgisSrid(), project=cls.qdjango_project, layer_type='postgres', datasource=cls.layer_specs[layer.name()]) assert created OpenrouteserviceProject.objects.get_or_create( project=cls.qdjango_project, services={OpenrouteserviceService.ISOCHRONE.value})
def testSaveLoadProject(self): schema_uri = encode_uri(self.ds_uri, 'qgis_test') project_uri = encode_uri(self.ds_uri, 'qgis_test', 'abc') self.dropProjectsTable() # make sure we have a clean start prj = QgsProject() uri = self.vl.source() vl1 = QgsVectorLayer(uri, 'test', 'postgres') self.assertEqual(vl1.isValid(), True) prj.addMapLayer(vl1) prj_storage = QgsApplication.projectStorageRegistry( ).projectStorageFromType("postgresql") self.assertTrue(prj_storage) lst0 = prj_storage.listProjects(schema_uri) self.assertEqual(lst0, []) # try to save project in the database prj.setFileName(project_uri) res = prj.write() self.assertTrue(res) lst1 = prj_storage.listProjects(schema_uri) self.assertEqual(lst1, ["abc"]) # now try to load the project back prj2 = QgsProject() prj2.setFileName(project_uri) res = prj2.read() self.assertTrue(res) self.assertEqual(len(prj2.mapLayers()), 1) self.assertEqual(prj2.baseName(), "abc") self.assertEqual(prj2.absoluteFilePath(), "") # path not supported for project storages self.assertTrue( abs(prj2.lastModified().secsTo(QDateTime.currentDateTime())) < 10) # try to see project's metadata res, metadata = prj_storage.readProjectStorageMetadata(project_uri) self.assertTrue(res) self.assertEqual(metadata.name, "abc") time_project = metadata.lastModified time_now = QDateTime.currentDateTime() time_diff = time_now.secsTo(time_project) self.assertTrue(abs(time_diff) < 10) # try to remove the project res = prj_storage.removeProject(project_uri) self.assertTrue(res) lst2 = prj_storage.listProjects(schema_uri) self.assertEqual(lst2, []) self.dropProjectsTable( ) # make sure we have a clean finish... "leave no trace"
def create(self, path: str, qgis_project: QgsProject): qgis_project.setAutoTransaction(self.auto_transaction) qgis_project.setEvaluateDefaultValues(self.evaluate_default_values) qgis_layers = list() for layer in self.layers: qgis_layer = layer.create() self.layer_added.emit(qgis_layer.id()) if not self.crs and qgis_layer.isSpatial(): self.crs = qgis_layer.crs() qgis_layers.append(qgis_layer) qgis_project.addMapLayers(qgis_layers, not self.legend) if self.crs: if isinstance(self.crs, QgsCoordinateReferenceSystem): qgis_project.setCrs(self.crs) else: qgis_project.setCrs( QgsCoordinateReferenceSystem.fromEpsgId(self.crs)) qgis_relations = list( qgis_project.relationManager().relations().values()) dict_domains = { layer.layer.id(): layer.is_domain for layer in self.layers } for relation in self.relations: rel = relation.create(qgis_project, qgis_relations) assert rel.isValid() qgis_relations.append(rel) if rel.referencedLayerId() in dict_domains and dict_domains[ rel.referencedLayerId()]: editor_widget_setup = QgsEditorWidgetSetup( 'RelationReference', { 'Relation': rel.id(), 'ShowForm': False, 'OrderByValue': True, 'ShowOpenFormButton': False }) else: editor_widget_setup = QgsEditorWidgetSetup( 'RelationReference', { 'Relation': rel.id(), 'ShowForm': False, 'OrderByValue': True, 'ShowOpenFormButton': False, 'AllowAddFeatures': True }) referencing_layer = rel.referencingLayer() referencing_layer.setEditorWidgetSetup(rel.referencingFields()[0], editor_widget_setup) qgis_project.relationManager().setRelations(qgis_relations) # Set Bag of Enum widget for layer_name, bag_of_enum in self.bags_of_enum.items(): for attribute, bag_of_enum_info in bag_of_enum.items(): layer_obj = bag_of_enum_info[0] cardinality = bag_of_enum_info[1] domain_table = bag_of_enum_info[2] key_field = bag_of_enum_info[3] value_field = bag_of_enum_info[4] allow_null = cardinality.startswith('0') allow_multi = cardinality.endswith('*') current_layer = layer_obj.create() field_widget = 'ValueRelation' field_widget_config = { 'AllowMulti': allow_multi, 'UseCompleter': False, 'Value': value_field, 'OrderByValue': False, 'AllowNull': allow_null, 'Layer': domain_table.create().id(), 'FilterExpression': '', 'Key': key_field, 'NofColumns': 1 } field_idx = current_layer.fields().indexOf(attribute) setup = QgsEditorWidgetSetup(field_widget, field_widget_config) current_layer.setEditorWidgetSetup(field_idx, setup) for layer in self.layers: layer.create_form(self) if self.legend: self.legend.create(qgis_project) if path: qgis_project.write(path)
def testRelativePaths(self): """ Test whether paths to layer sources are stored as relative to the project path """ tmpDir = QTemporaryDir() tmpFile = "{}/project.qgs".format(tmpDir.path()) copyfile(os.path.join(TEST_DATA_DIR, "points.shp"), os.path.join(tmpDir.path(), "points.shp")) copyfile(os.path.join(TEST_DATA_DIR, "points.dbf"), os.path.join(tmpDir.path(), "points.dbf")) copyfile(os.path.join(TEST_DATA_DIR, "points.shx"), os.path.join(tmpDir.path(), "points.shx")) copyfile(os.path.join(TEST_DATA_DIR, "lines.shp"), os.path.join(tmpDir.path(), "lines.shp")) copyfile(os.path.join(TEST_DATA_DIR, "lines.dbf"), os.path.join(tmpDir.path(), "lines.dbf")) copyfile(os.path.join(TEST_DATA_DIR, "lines.shx"), os.path.join(tmpDir.path(), "lines.shx")) copyfile(os.path.join(TEST_DATA_DIR, "landsat_4326.tif"), os.path.join(tmpDir.path(), "landsat_4326.tif")) project = QgsProject() l0 = QgsVectorLayer(os.path.join(tmpDir.path(), "points.shp"), "points", "ogr") l1 = QgsVectorLayer(os.path.join(tmpDir.path(), "lines.shp"), "lines", "ogr") l2 = QgsRasterLayer(os.path.join(tmpDir.path(), "landsat_4326.tif"), "landsat", "gdal") self.assertTrue(l0.isValid()) self.assertTrue(l1.isValid()) self.assertTrue(l2.isValid()) self.assertTrue(project.addMapLayers([l0, l1, l2])) self.assertTrue(project.write(tmpFile)) del project with open(tmpFile, 'r') as f: content = ''.join(f.readlines()) self.assertTrue('source="./lines.shp"' in content) self.assertTrue('source="./points.shp"' in content) self.assertTrue('source="./landsat_4326.tif"' in content) # Re-read the project and store absolute project = QgsProject() self.assertTrue(project.read(tmpFile)) store = project.layerStore() self.assertEquals(set([l.name() for l in store.mapLayers().values()]), set(['lines', 'landsat', 'points'])) project.writeEntryBool('Paths', '/Absolute', True) tmpFile2 = "{}/project2.qgs".format(tmpDir.path()) self.assertTrue(project.write(tmpFile2)) with open(tmpFile2, 'r') as f: content = ''.join(f.readlines()) self.assertTrue( 'source="{}/lines.shp"'.format(tmpDir.path()) in content) self.assertTrue( 'source="{}/points.shp"'.format(tmpDir.path()) in content) self.assertTrue('source="{}/landsat_4326.tif"'.format( tmpDir.path()) in content) del project
def testProjectStorage(self): # New project without fileName p0 = QgsProject() self.assertTrue(p0.auxiliaryStorage().isValid()) # Create new layers with key otherwise auxiliary layers are not # automacially created when added in project vl0 = createLayer() vl0Shp = writeShape(vl0, 'vl0.shp') vl1 = createLayer() vl1Shp = writeShape(vl1, 'vl1.shp') vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr') self.assertTrue(vl0.isValid()) vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr') self.assertTrue(vl1.isValid()) # Add layers to project and check underlying auxiliary layers p0.addMapLayers([vl0, vl1]) self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk')) self.assertTrue( vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char')) al0 = vl0.auxiliaryLayer() al1 = vl1.auxiliaryLayer() self.assertEqual(al0.joinInfo().targetFieldName(), 'pk') self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char') # Add a field in auxiliary layers pdef0 = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut') self.assertTrue(al0.addAuxiliaryField(pdef0)) pdef1 = QgsPropertyDefinition('propname1', QgsPropertyDefinition.DataTypeString, '', '', 'ut') self.assertTrue(al1.addAuxiliaryField(pdef1)) # Check auxiliary fields names af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False) self.assertEqual(af0Name, 'ut_propname') af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False) self.assertEqual(af1Name, 'ut_propname1') # Set value for auxiliary fields req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl0.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True) index0 = vl0.fields().indexOf(af0Name) vl0.changeAttributeValue(f.id(), index0, 333) req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True) index1 = vl1.fields().indexOf(af1Name) vl1.changeAttributeValue(f.id(), index0, 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) vl1.changeAttributeValue(f.id(), index0, 'myvalue1') # Save the project in a zip file f = tmpPath() + '.qgz' p0.write(f) # Open the zip file with embedded auxiliary storage p1 = QgsProject() p1.read(f) # Check that auxiliary fields are well loaded in layers self.assertEqual(len(p1.mapLayers().values()), 2) for vl in p1.mapLayers().values(): al = vl.auxiliaryLayer() self.assertEqual(len(al.auxiliaryFields()), 1) af = al.auxiliaryFields()[0] afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af) self.assertEqual(afPropDef.origin(), 'ut') if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk': self.assertEqual(afPropDef.name(), 'propname') self.assertEqual(al.featureCount(), 1) req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index0], 333.0) else: # num_char self.assertEqual(al.featureCount(), 2) self.assertEqual(afPropDef.name(), 'propname1') req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue') req = QgsFeatureRequest().setFilterExpression( "name = 'Orange'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue1')