def testTransparency(self): myPath = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() myRasterLayer = QgsRasterLayer(myPath, myBaseName) myMessage = 'Raster not loaded: %s' % myPath assert myRasterLayer.isValid(), myMessage renderer = QgsSingleBandGrayRenderer(myRasterLayer.dataProvider(), 1) myRasterLayer.setRenderer(renderer) myRasterLayer.setContrastEnhancement( QgsContrastEnhancement.StretchToMinimumMaximum, QgsRasterMinMaxOrigin.MinMax) myContrastEnhancement = myRasterLayer.renderer().contrastEnhancement() # print ("myContrastEnhancement.minimumValue = %.17g" % # myContrastEnhancement.minimumValue()) # print ("myContrastEnhancement.maximumValue = %.17g" % # myContrastEnhancement.maximumValue()) # Unfortunately the minimum/maximum values calculated in C++ and Python # are slightly different (e.g. 3.3999999521443642e+38 x # 3.3999999521444001e+38) # It is not clear where the precision is lost. # We set the same values as C++. myContrastEnhancement.setMinimumValue(-3.3319999287625854e+38) myContrastEnhancement.setMaximumValue(3.3999999521443642e+38) #myType = myRasterLayer.dataProvider().dataType(1); #myEnhancement = QgsContrastEnhancement(myType); myTransparentSingleValuePixelList = [] rasterTransparency = QgsRasterTransparency() myTransparentPixel1 = \ QgsRasterTransparency.TransparentSingleValuePixel() myTransparentPixel1.min = -2.5840000772112106e+38 myTransparentPixel1.max = -1.0879999684602689e+38 myTransparentPixel1.percentTransparent = 50 myTransparentSingleValuePixelList.append(myTransparentPixel1) myTransparentPixel2 = \ QgsRasterTransparency.TransparentSingleValuePixel() myTransparentPixel2.min = 1.359999960575336e+37 myTransparentPixel2.max = 9.520000231087593e+37 myTransparentPixel2.percentTransparent = 70 myTransparentSingleValuePixelList.append(myTransparentPixel2) rasterTransparency.setTransparentSingleValuePixelList( myTransparentSingleValuePixelList) rasterRenderer = myRasterLayer.renderer() assert rasterRenderer rasterRenderer.setRasterTransparency(rasterTransparency) QgsProject.instance().addMapLayers([myRasterLayer, ]) myMapSettings = QgsMapSettings() myMapSettings.setLayers([myRasterLayer]) myMapSettings.setExtent(myRasterLayer.extent()) myChecker = QgsRenderChecker() myChecker.setControlName("expected_raster_transparency") myChecker.setMapSettings(myMapSettings) myResultFlag = myChecker.runTest("raster_transparency_python") assert myResultFlag, "Raster transparency rendering test failed"
def testIteration(self): p = QgsProject() vectorFileInfo = QFileInfo(unitTestDataPath() + "/france_parts.shp") vector_layer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") self.assertTrue(vector_layer.isValid()) p.addMapLayer(vector_layer) l = QgsPrintLayout(p) atlas = l.atlas() atlas.setEnabled(True) atlas.setCoverageLayer(vector_layer) atlas_feature_changed_spy = QSignalSpy(atlas.featureChanged) context_changed_spy = QSignalSpy(l.reportContext().changed) self.assertTrue(atlas.beginRender()) self.assertTrue(atlas.first()) self.assertEqual(len(atlas_feature_changed_spy), 1) self.assertEqual(len(context_changed_spy), 1) self.assertEqual(atlas.currentFeatureNumber(), 0) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertEqual(l.reportContext().layer(), vector_layer) f1 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 2) self.assertEqual(len(context_changed_spy), 2) self.assertEqual(atlas.currentFeatureNumber(), 1) self.assertEqual(l.reportContext().feature()[4], 'Bretagne') f2 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 3) self.assertEqual(len(context_changed_spy), 3) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') f3 = l.reportContext().feature() self.assertTrue(atlas.next()) self.assertEqual(len(atlas_feature_changed_spy), 4) self.assertEqual(len(context_changed_spy), 4) self.assertEqual(atlas.currentFeatureNumber(), 3) self.assertEqual(l.reportContext().feature()[4], 'Centre') f4 = l.reportContext().feature() self.assertFalse(atlas.next()) self.assertTrue(atlas.seekTo(2)) self.assertEqual(len(atlas_feature_changed_spy), 5) self.assertEqual(len(context_changed_spy), 5) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.last()) self.assertEqual(len(atlas_feature_changed_spy), 6) self.assertEqual(len(context_changed_spy), 6) self.assertEqual(atlas.currentFeatureNumber(), 3) self.assertEqual(l.reportContext().feature()[4], 'Centre') self.assertTrue(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 7) self.assertEqual(len(context_changed_spy), 7) self.assertEqual(atlas.currentFeatureNumber(), 2) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.previous()) self.assertTrue(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 9) self.assertFalse(atlas.previous()) self.assertEqual(len(atlas_feature_changed_spy), 9) self.assertTrue(atlas.endRender()) self.assertEqual(len(atlas_feature_changed_spy), 10) self.assertTrue(atlas.seekTo(f1)) self.assertEqual(l.reportContext().feature()[4], 'Basse-Normandie') self.assertTrue(atlas.seekTo(f4)) self.assertEqual(l.reportContext().feature()[4], 'Centre') self.assertTrue(atlas.seekTo(f3)) self.assertEqual(l.reportContext().feature()[4], 'Pays de la Loire') self.assertTrue(atlas.seekTo(f2)) self.assertEqual(l.reportContext().feature()[4], 'Bretagne') self.assertFalse(atlas.seekTo(QgsFeature(5)))
def testPaletted(self): """ test paletted raster renderer with raster with color table""" path = os.path.join(unitTestDataPath('raster'), 'with_color_table.tif') info = QFileInfo(path) base_name = info.baseName() layer = QgsRasterLayer(path, base_name) self.assertTrue(layer.isValid(), 'Raster not loaded: {}'.format(path)) renderer = QgsPalettedRasterRenderer(layer.dataProvider(), 1, [QgsPalettedRasterRenderer.Class(1, QColor(0, 255, 0), 'class 2'), QgsPalettedRasterRenderer.Class(3, QColor(255, 0, 0), 'class 1')]) self.assertEqual(renderer.nColors(), 2) self.assertEqual(renderer.usesBands(), [1]) # test labels self.assertEqual(renderer.label(1), 'class 2') self.assertEqual(renderer.label(3), 'class 1') self.assertFalse(renderer.label(101)) # test legend symbology - should be sorted by value legend = renderer.legendSymbologyItems() self.assertEqual(legend[0][0], 'class 2') self.assertEqual(legend[1][0], 'class 1') self.assertEqual(legend[0][1].name(), '#00ff00') self.assertEqual(legend[1][1].name(), '#ff0000') # test retrieving classes classes = renderer.classes() self.assertEqual(classes[0].value, 1) self.assertEqual(classes[1].value, 3) self.assertEqual(classes[0].label, 'class 2') self.assertEqual(classes[1].label, 'class 1') self.assertEqual(classes[0].color.name(), '#00ff00') self.assertEqual(classes[1].color.name(), '#ff0000') # test set label # bad index renderer.setLabel(1212, 'bad') renderer.setLabel(3, 'new class') self.assertEqual(renderer.label(3), 'new class') # color ramp r = QgsLimitedRandomColorRamp(5) renderer.setSourceColorRamp(r) self.assertEqual(renderer.sourceColorRamp().type(), 'random') self.assertEqual(renderer.sourceColorRamp().count(), 5) # clone new_renderer = renderer.clone() classes = new_renderer.classes() self.assertEqual(classes[0].value, 1) self.assertEqual(classes[1].value, 3) self.assertEqual(classes[0].label, 'class 2') self.assertEqual(classes[1].label, 'new class') self.assertEqual(classes[0].color.name(), '#00ff00') self.assertEqual(classes[1].color.name(), '#ff0000') self.assertEqual(new_renderer.sourceColorRamp().type(), 'random') self.assertEqual(new_renderer.sourceColorRamp().count(), 5) # write to xml and read doc = QDomDocument('testdoc') elem = doc.createElement('qgis') renderer.writeXml(doc, elem) restored = QgsPalettedRasterRenderer.create(elem.firstChild().toElement(), layer.dataProvider()) self.assertTrue(restored) self.assertEqual(restored.usesBands(), [1]) classes = restored.classes() self.assertTrue(classes) self.assertEqual(classes[0].value, 1) self.assertEqual(classes[1].value, 3) self.assertEqual(classes[0].label, 'class 2') self.assertEqual(classes[1].label, 'new class') self.assertEqual(classes[0].color.name(), '#00ff00') self.assertEqual(classes[1].color.name(), '#ff0000') self.assertEqual(restored.sourceColorRamp().type(), 'random') self.assertEqual(restored.sourceColorRamp().count(), 5) # render test layer.setRenderer(renderer) ms = QgsMapSettings() ms.setLayers([layer]) ms.setExtent(layer.extent()) checker = QgsRenderChecker() checker.setControlName("expected_paletted_renderer") checker.setMapSettings(ms) self.assertTrue(checker.runTest("expected_paletted_renderer"), "Paletted rendering test failed")
def testPalettedClassDataFromLayer(self): # no layer classes = QgsPalettedRasterRenderer.classDataFromRaster(None, 1) self.assertFalse(classes) # 10 class layer path = os.path.join(unitTestDataPath('raster'), 'with_color_table.tif') info = QFileInfo(path) base_name = info.baseName() layer10 = QgsRasterLayer(path, base_name) classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1) self.assertEqual(len(classes), 10) self.assertEqual(classes[0].value, 1) self.assertEqual(classes[0].label, '1') self.assertEqual(classes[1].value, 2) self.assertEqual(classes[1].label, '2') self.assertEqual(classes[2].value, 3) self.assertEqual(classes[2].label, '3') self.assertEqual(classes[3].value, 4) self.assertEqual(classes[3].label, '4') self.assertEqual(classes[4].value, 5) self.assertEqual(classes[4].label, '5') self.assertEqual(classes[5].value, 6) self.assertEqual(classes[5].label, '6') self.assertEqual(classes[6].value, 7) self.assertEqual(classes[6].label, '7') self.assertEqual(classes[7].value, 8) self.assertEqual(classes[7].label, '8') self.assertEqual(classes[8].value, 9) self.assertEqual(classes[8].label, '9') self.assertEqual(classes[9].value, 10) self.assertEqual(classes[9].label, '10') # bad band self.assertFalse(QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 10101010)) # with ramp r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200)) classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1, r) self.assertEqual(len(classes), 10) self.assertEqual(classes[0].color.name(), '#c80000') self.assertEqual(classes[1].color.name(), '#b21600') self.assertEqual(classes[2].color.name(), '#9c2c00') self.assertEqual(classes[3].color.name(), '#854200') self.assertEqual(classes[4].color.name(), '#6f5900') self.assertEqual(classes[5].color.name(), '#596f00') self.assertEqual(classes[6].color.name(), '#428500') self.assertEqual(classes[7].color.name(), '#2c9c00') self.assertEqual(classes[8].color.name(), '#16b200') self.assertEqual(classes[9].color.name(), '#00c800') # 30 class layer path = os.path.join(unitTestDataPath('raster'), 'unique_1.tif') info = QFileInfo(path) base_name = info.baseName() layer10 = QgsRasterLayer(path, base_name) classes = QgsPalettedRasterRenderer.classDataFromRaster(layer10.dataProvider(), 1) self.assertEqual(len(classes), 30) expected = [11, 21, 22, 24, 31, 82, 2002, 2004, 2014, 2019, 2027, 2029, 2030, 2080, 2081, 2082, 2088, 2092, 2097, 2098, 2099, 2105, 2108, 2110, 2114, 2118, 2126, 2152, 2184, 2220] self.assertEqual([c.value for c in classes], expected) # bad layer path = os.path.join(unitTestDataPath('raster'), 'hub13263.vrt') info = QFileInfo(path) base_name = info.baseName() layer = QgsRasterLayer(path, base_name) classes = QgsPalettedRasterRenderer.classDataFromRaster(layer.dataProvider(), 1) self.assertFalse(classes)
def save(self): toSave = [] context = dataobjects.createContext() for row in range(self.tblParameters.rowCount()): algParams = {} algOutputs = {} col = 0 alg = self.alg for param in alg.parameterDefinitions(): if param.flags() & QgsProcessingParameterDefinition.FlagHidden: continue if param.isDestination(): continue wrapper = self.wrappers[row][col] # For compatibility with 3.x API, we need to check whether the wrapper is # the deprecated WidgetWrapper class. If not, it's the newer # QgsAbstractProcessingParameterWidgetWrapper class # TODO QGIS 4.0 - remove if issubclass(wrapper.__class__, WidgetWrapper): widget = wrapper.widget else: widget = wrapper.wrappedWidget() value = wrapper.parameterValue() if not param.checkValueIsAcceptable(value, context): self.parent.messageBar().pushMessage( "", self.tr( 'Wrong or missing parameter value: {0} (row {1})'). format(param.description(), row + 1), level=Qgis.Warning, duration=5) return algParams[param.name()] = param.valueAsPythonString( value, context) col += 1 for out in alg.destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.FlagHidden: continue widget = self.tblParameters.cellWidget(row, col) text = widget.getValue() if text.strip() != '': algOutputs[out.name()] = text.strip() col += 1 else: self.parent.messageBar().pushMessage( "", self.tr('Wrong or missing output value: {0} (row {1})' ).format(out.description(), row + 1), level=Qgis.Warning, duration=5) return toSave.append({ self.PARAMETERS: algParams, self.OUTPUTS: algOutputs }) settings = QgsSettings() last_path = settings.value("/Processing/LastBatchPath", QDir.homePath()) filename, __ = QFileDialog.getSaveFileName( self, self.tr('Save Batch'), last_path, self.tr('JSON files (*.json)')) if filename: if not filename.endswith('.json'): filename += '.json' last_path = QFileInfo(filename).path() settings.setValue('/Processing/LastBatchPath', last_path) with open(filename, 'w') as f: json.dump(toSave, f)
def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob( os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) self.layers = [mVectorLayer] # create layout with layout map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.layout = QgsPrintLayout(QgsProject.instance()) self.layout.initializeDefaults() # fix the renderer, fill with green props = {"color": "0,127,0", 'outline_color': 'black'} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.atlas_map = QgsLayoutItemMap(self.layout) self.atlas_map.attemptSetSceneRect(QRectF(20, 20, 130, 130)) self.atlas_map.setFrameEnabled(True) self.atlas_map.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.atlas_map) # the atlas self.atlas = self.layout.atlas() self.atlas.setCoverageLayer(mVectorLayer) self.atlas.setEnabled(True) # an overview self.overview = QgsLayoutItemMap(self.layout) self.overview.attemptSetSceneRect(QRectF(180, 20, 50, 50)) self.overview.setFrameEnabled(True) self.overview.overview().setLinkedMap(self.atlas_map) self.overview.setLayers([mVectorLayer]) self.layout.addLayoutItem(self.overview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.overview.setExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127", 'outline_color': 'black'} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.overview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.attemptSetSceneRect(QRectF(150, 5, 60, 15)) self.mLabel1.setMarginX(1) self.mLabel1.setMarginY(1) # feature number label self.mLabel2 = QgsLayoutItemLabel(self.layout) self.layout.addLayoutItem(self.mLabel2) self.mLabel2.setText( "# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.attemptSetSceneRect(QRectF(150, 200, 60, 15)) self.mLabel2.setMarginX(1) self.mLabel2.setMarginY(1) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() self.rotation_test() shutil.rmtree(tmppath, True)
def testWriteSld(self): """Test SLD generation for the XMLS fields geneerated at RasterLayer level and not to the deeper renderer level.""" myPath = os.path.join(unitTestDataPath(), 'landsat.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() myRasterLayer = QgsRasterLayer(myPath, myBaseName) myMessage = 'Raster not loaded: %s' % myPath assert myRasterLayer.isValid(), myMessage # do generic export with default layer values dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = root.elementsByTagName('sld:LayerFeatureConstraints') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() elements = element.elementsByTagName('sld:FeatureTypeConstraint') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() elements = root.elementsByTagName('sld:UserStyle') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() name = element.firstChildElement('sld:Name') self.assertFalse(name.isNull()) self.assertEqual(name.text(), 'landsat') abstract = element.firstChildElement('sld:Abstract') self.assertTrue(abstract.isNull()) title = element.firstChildElement('sld:Title') self.assertTrue(title.isNull()) featureTypeStyle = element.firstChildElement('sld:FeatureTypeStyle') self.assertFalse(featureTypeStyle.isNull()) rule = featureTypeStyle.firstChildElement('sld:Rule') self.assertFalse(rule.isNull()) temp = rule.firstChildElement('sld:MinScaleDenominator') self.assertTrue(temp.isNull()) temp = rule.firstChildElement('sld:MaxScaleDenominator') self.assertTrue(temp.isNull()) rasterSymbolizer = rule.firstChildElement('sld:RasterSymbolizer') self.assertFalse(rule.isNull()) vendorOptions = rasterSymbolizer.elementsByTagName('sld:VendorOption') self.assertTrue(vendorOptions.size() == 0) # set no default values and check exported sld myRasterLayer.setName('') myRasterLayer.setAbstract('fake') myRasterLayer.setTitle('fake') dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = root.elementsByTagName('sld:LayerFeatureConstraints') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() elements = element.elementsByTagName('sld:FeatureTypeConstraint') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() elements = root.elementsByTagName('sld:UserStyle') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() # no generated if empty name = element.firstChildElement('sld:Name') self.assertTrue(name.isNull()) # generated if not empty abstract = element.firstChildElement('sld:Abstract') self.assertFalse(abstract.isNull()) self.assertEqual(abstract.text(), 'fake') title = element.firstChildElement('sld:Title') self.assertFalse(title.isNull()) self.assertEqual(title.text(), 'fake') # if setScaleBasedVisibility is true print scales myRasterLayer.setScaleBasedVisibility(True) myRasterLayer.setMaximumScale(0.0001) myRasterLayer.setMinimumScale(0.01) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:Rule') self.assertEqual(len(elements), 1) rule = elements.at(0).toElement() self.assertFalse(rule.isNull()) temp = rule.firstChildElement('sld:MinScaleDenominator') self.assertFalse(temp.isNull()) self.assertEqual(temp.text(), '0.0001') temp = rule.firstChildElement('sld:MaxScaleDenominator') self.assertFalse(temp.isNull()) self.assertEqual(temp.text(), '0.01') # check non default hueSaturationFilter values hue = myRasterLayer.hueSaturationFilter() hue.setGrayscaleMode(QgsHueSaturationFilter.GrayscaleLightness) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'grayScale', 'lightness') hue = myRasterLayer.hueSaturationFilter() hue.setGrayscaleMode(QgsHueSaturationFilter.GrayscaleLuminosity) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'grayScale', 'luminosity') hue = myRasterLayer.hueSaturationFilter() hue.setGrayscaleMode(QgsHueSaturationFilter.GrayscaleAverage) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'grayScale', 'average') hue = myRasterLayer.hueSaturationFilter() hue.setGrayscaleMode(QgsHueSaturationFilter.GrayscaleOff) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'grayScale', None) # manage colorize vendorOption tags hue = myRasterLayer.hueSaturationFilter() hue.setColorizeOn(True) hue.setColorizeStrength(50) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'colorizeOn', '1') self.assertVendorOption(element, 'colorizeRed', '255') self.assertVendorOption(element, 'colorizeGreen', '128') self.assertVendorOption(element, 'colorizeBlue', '128') self.assertVendorOption(element, 'colorizeStrength', '0.5') self.assertVendorOption(element, 'saturation', '0.498039') # other hue non default values, no colorize and saturation = 0 hue = myRasterLayer.hueSaturationFilter() hue.setColorizeOn(False) hue.setSaturation(0) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'colorizeOn', None) self.assertVendorOption(element, 'colorizeRed', None) self.assertVendorOption(element, 'colorizeGreen', None) self.assertVendorOption(element, 'colorizeBlue', None) self.assertVendorOption(element, 'colorizeStrength', None) self.assertVendorOption(element, 'saturation', None) self.assertVendorOption(element, 'brightness', None) self.assertVendorOption(element, 'contrast', None) # other hue non default values, no colorize and saturation = 100 hue = myRasterLayer.hueSaturationFilter() hue.setColorizeOn(False) hue.setSaturation(100) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'colorizeOn', None) self.assertVendorOption(element, 'colorizeRed', None) self.assertVendorOption(element, 'colorizeGreen', None) self.assertVendorOption(element, 'colorizeBlue', None) self.assertVendorOption(element, 'colorizeStrength', None) self.assertVendorOption(element, 'saturation', '1') hue.setSaturation(-100) dom, root, errorMessage = self.layerToSld(myRasterLayer) self.assertVendorOption(root, 'saturation', '0') # brightness filter default values dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertTrue(myRasterLayer.brightnessFilter().brightness() == 0) self.assertTrue(myRasterLayer.brightnessFilter().contrast() == 0) self.assertVendorOption(element, 'brightness', None) self.assertVendorOption(element, 'contrast', None) # brightness filter no default values bf = myRasterLayer.brightnessFilter() bf.setBrightness(-255) bf.setContrast(-100) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'brightness', '0') self.assertVendorOption(element, 'contrast', '0') bf.setBrightness(255) bf.setContrast(100) dom, root, errorMessage = self.layerToSld(myRasterLayer) elements = dom.elementsByTagName('sld:RasterSymbolizer') self.assertEqual(len(elements), 1) element = elements.at(0).toElement() self.assertFalse(element.isNull()) self.assertVendorOption(element, 'brightness', '1') self.assertVendorOption(element, 'contrast', '1')
def addLayer(self, uri, fileName, layerId, group=None, visible=False, expanded=False): theLayer = None # read QGIS project doc, _ = self.getQgsDoc(fileName) # is project in relative path ? absolute = is_absolute(doc) trusted = project_trusted(doc) node = getFirstChildByTagNameValue(doc.documentElement(), "maplayer", "id", layerId) node = node.cloneNode() if node: idNode = node.namedItem("id") layerType = node.toElement().attribute("type", "vector") # give it a new id (for multiple import) newLayerId = "L%s" % re.sub("[{}-]", "", QUuid.createUuid().toString()) try: idNode.firstChild().toText().setData(newLayerId) except Exception: pass # if relative path, adapt datasource if not absolute: try: datasourceNode = node.namedItem("datasource") ds = datasourceNode.firstChild().toText().data() providerNode = node.namedItem("provider") provider = providerNode.firstChild().toText().data() if provider in ["ogr", "gdal"] and (ds.find(".") == 0): projectpath = QFileInfo(uri).path() newlayerpath = projectpath + "/" + ds datasourceNode.firstChild().toText().setData( newlayerpath) except Exception: pass # read modified layer node if self.optionCreateGroup and group is not None: if layerType == "raster": theLayer = QgsRasterLayer() else: theLayer = QgsVectorLayer() theLayer.setReadExtentFromXml(trusted) theLayer.readLayerXml(node.toElement(), QgsReadWriteContext()) # Special process if the plugin "DB Style Manager" is installed flag = "use_db_style_manager_in_custom_menu" in os.environ if flag and "db-style-manager" in plugins: try: plugins["db-style-manager"].load_style_from_database( theLayer) except Exception: self.log("DB-Style-Manager failed to load the style.") # needed QgsProject.instance().addMapLayer(theLayer, False) # add to group treeNode = group.insertLayer(0, theLayer) treeNode.setExpanded(expanded) treeNode.setItemVisibilityChecked(visible) else: # create layer theLayer = QgsProject.instance().readLayer(node) return QgsProject.instance().mapLayer(newLayerId) else: self.log("{} not found".format(layerId)) return None
def addMenuItem(self, uri, filename, node, menu, absolute, mapLayersDict): """Add menu to an item.""" yaLayer = False if node is None or node.nodeName() == "": return yaLayer element = node.toElement() # if legendlayer tag if node.nodeName() == "layer-tree-layer": try: name = element.attribute("name") layerId = element.attribute("id") visible = element.attribute("checked", "") == "Qt::Checked" expanded = element.attribute("expanded", "0") == "1" action = QAction(name, self.iface.mainWindow()) embedNd = getFirstChildByAttrValue(element, "property", "key", "embedded") # is layer embedded ? if embedNd and embedNd.toElement().attribute("value") == "1": # layer is embeded efilename = None eFileNd = getFirstChildByAttrValue(element, "property", "key", "embedded_project") if eFileNd: # get project file name embeddedFile = eFileNd.toElement().attribute("value") if not absolute and (embeddedFile.find(".") == 0): efilename = QFileInfo( filename).path() + "/" + embeddedFile # if ok if efilename: # add menu item action.triggered.connect( lambda checked, uri=uri, f=efilename, lid= layerId, m=menu, v=visible, x=expanded: self. loadLayer(uri, f, lid, m, v, x)) menu.addAction(action) yaLayer = True if self.optionTooltip: # search embeded maplayer (for title, abstract) mapLayer = self.getMapLayerDomFromQgs( efilename, layerId) if mapLayer is not None: self.addToolTip(mapLayer, action) else: self.log("Menu from layer: {} not found in project {}". format(layerId, efilename)) # layer is not embedded else: efilename = filename if self.optionTooltip: self.addToolTip(mapLayersDict[layerId], action) action.triggered.connect( lambda checked, uri=uri, f=filename, lid=layerId, m= menu, v=visible, x=expanded: self.loadLayer( uri, f, lid, m, v, x)) menu.addAction(action) yaLayer = True # Add geometry type icon try: map_layer = self.getMapLayerDomFromQgs( efilename, layerId).toElement() geometry_type = map_layer.attribute("geometry") if geometry_type == "": # A TMS has not a geometry attribute. # Let's read the "type" geometry_type = map_layer.attribute("type") action.setIcon(icon_per_geometry_type(geometry_type)) except Exception: pass except Exception as e: for m in e.args: self.log(m) # / if element.tagName() == "layer-tree-layer": # if legendgroup tag if node.nodeName() == "layer-tree-group": name = element.attribute("name") propertiesNode = node.firstChild() embedNd = getFirstChildByAttrValue(propertiesNode.toElement(), "property", "key", "embedded") # is group embedded ? if embedNd and embedNd.toElement().attribute("value") == "1": # group is embeded efilename = None eFileNd = getFirstChildByAttrValue(element, "property", "key", "embedded_project") if eFileNd: # get project file name embeddedFile = eFileNd.toElement().attribute("value") if not absolute and (embeddedFile.find(".") == 0): efilename = QFileInfo( filename).path() + "/" + embeddedFile # if ok if efilename: # add menu group doc, _ = self.getQgsDoc(efilename) groupNode = getFirstChildByAttrValue( doc.documentElement(), "layer-tree-group", "name", name) # and do recursion r = self.addMenuItem( efilename, efilename, groupNode, menu, absolute, getMapLayersDict(doc), ) yaLayer = yaLayer or r else: self.log( "Menu from layer: {} not found in project {}".format( layerId, efilename)) # group is not embedded else: if name == "-": menu.addSeparator() elif name.startswith("-"): action = QAction(name[1:], self.iface.mainWindow()) font = QFont() font.setBold(True) action.setFont(font) menu.addAction(action) else: # sub-menu sousmenu = menu.addMenu("&" + element.attribute("name")) sousmenu.menuAction().setToolTip("") sousmenu.setToolTipsVisible(self.optionTooltip) childNode = node.firstChild() # ! recursion r = self.addMenuItem(uri, filename, childNode, sousmenu, absolute, mapLayersDict) if r and self.optionLoadAll and (len(sousmenu.actions()) > 1): action = QAction(self.tr("Load all"), self.iface.mainWindow()) font = QFont() font.setBold(True) action.setFont(font) sousmenu.addAction(action) action.triggered.connect( lambda checked, f=None, w=None, m=sousmenu: self. loadLayer(uri, f, w, m)) # / if element.tagName() == "legendgroup": nextNode = node.nextSibling() if nextNode is not None: # ! recursion r = self.addMenuItem(uri, filename, nextNode, menu, absolute, mapLayersDict) yaLayer = yaLayer or r return yaLayer
def getInstalledPlugin(self, key, path, readOnly): """ get the metadata of an installed plugin """ def metadataParser(fct): """ plugin metadata parser reimplemented from qgis.utils for better control on wchich module is examined in case there is an installed plugin masking a core one """ global errorDetails cp = configparser.ConfigParser() try: with codecs.open(metadataFile, "r", "utf8") as f: cp.read_file(f) return cp.get('general', fct) except Exception as e: if not errorDetails: errorDetails = e.args[0] # set to the first problem return "" def pluginMetadata(fct): """ calls metadataParser for current l10n. If failed, fallbacks to the standard metadata """ locale = QLocale.system().name() if locale and fct in translatableAttributes: value = metadataParser("{}[{}]".format(fct, locale)) if value: return value value = metadataParser("{}[{}]".format(fct, locale.split("_")[0])) if value: return value return metadataParser(fct) if not QDir(path).exists(): return global errorDetails # to communicate with the metadataParser fn plugin = dict() error = "" errorDetails = "" version = None metadataFile = os.path.join(path, 'metadata.txt') if os.path.exists(metadataFile): version = normalizeVersion(pluginMetadata("version")) if version: qgisMinimumVersion = pluginMetadata("qgisMinimumVersion").strip() if not qgisMinimumVersion: qgisMinimumVersion = "0" qgisMaximumVersion = pluginMetadata("qgisMaximumVersion").strip() if not qgisMaximumVersion: qgisMaximumVersion = qgisMinimumVersion[0] + ".99" # if compatible, add the plugin to the list if not isCompatible(pyQgisVersion(), qgisMinimumVersion, qgisMaximumVersion): error = "incompatible" errorDetails = "{} - {}".format(qgisMinimumVersion, qgisMaximumVersion) elif not os.path.exists(metadataFile): error = "broken" errorDetails = QCoreApplication.translate("QgsPluginInstaller", "Missing metadata file") else: error = "broken" e = errorDetails errorDetails = QCoreApplication.translate( "QgsPluginInstaller", u"Error reading metadata") if e: errorDetails += ": " + e if not version: version = "?" if error[:16] == "No module named ": mona = error.replace("No module named ", "") if mona != key: error = "dependent" errorDetails = mona icon = pluginMetadata("icon") if QFileInfo(icon).isRelative(): icon = path + "/" + icon changelog = pluginMetadata("changelog") changelogFile = os.path.join(path, "CHANGELOG") if not changelog and QFile(changelogFile).exists(): with open(changelogFile) as f: changelog = f.read() plugin = { "id": key, "plugin_id": None, "name": pluginMetadata("name") or key, "description": pluginMetadata("description"), "about": pluginMetadata("about"), "icon": icon, "category": pluginMetadata("category"), "tags": pluginMetadata("tags"), "changelog": changelog, "author_name": pluginMetadata("author_name") or pluginMetadata("author"), "author_email": pluginMetadata("email"), "homepage": pluginMetadata("homepage"), "tracker": pluginMetadata("tracker"), "code_repository": pluginMetadata("repository"), "version_installed": version, "library": path, "pythonic": True, "experimental": pluginMetadata("experimental").strip().upper() in ["TRUE", "YES"], "deprecated": pluginMetadata("deprecated").strip().upper() in ["TRUE", "YES"], "trusted": False, "version_available": "", "zip_repository": "", "download_url": path, # warning: local path as url! "filename": "", "downloads": "", "average_vote": "", "rating_votes": "", "available": False, # Will be overwritten, if any available version found. "installed": True, "status": "orphan", # Will be overwritten, if any available version found. "error": error, "error_details": errorDetails, "readonly": readOnly } return plugin
def xmlDownloaded(self): """ populate the plugins object with the fetched data """ reply = self.sender() reposName = reply.property('reposName') if reply.error() != QNetworkReply.NoError: # fetching failed self.mRepositories[reposName]["state"] = 3 self.mRepositories[reposName]["error"] = reply.errorString() if reply.error() == QNetworkReply.OperationCanceledError: self.mRepositories[reposName][ "error"] += "\n\n" + QCoreApplication.translate( "QgsPluginInstaller", "If you haven't canceled the download manually, it was most likely caused by a timeout. In this case consider increasing the connection timeout value in QGIS options window." ) elif reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 301: redirectionUrl = reply.attribute( QNetworkRequest.RedirectionTargetAttribute) if redirectionUrl.isRelative(): redirectionUrl = reply.url().resolved(redirectionUrl) redirectionCounter = reply.property('redirectionCounter') + 1 if redirectionCounter > 4: self.mRepositories[reposName]["state"] = 3 self.mRepositories[reposName][ "error"] = QCoreApplication.translate( "QgsPluginInstaller", "Too many redirections") else: # Fire a new request and exit immediately in order to quietly destroy the old one self.requestFetching(reposName, redirectionUrl, redirectionCounter) reply.deleteLater() return else: reposXML = QDomDocument() content = reply.readAll() # Fix lonely ampersands in metadata a = QByteArray() a.append("& ") b = QByteArray() b.append("& ") content = content.replace(a, b) reposXML.setContent(content) pluginNodes = reposXML.elementsByTagName("pyqgis_plugin") if pluginNodes.size(): for i in range(pluginNodes.size()): fileName = pluginNodes.item(i).firstChildElement( "file_name").text().strip() if not fileName: fileName = QFileInfo( pluginNodes.item(i).firstChildElement( "download_url").text().strip().split("?") [0]).fileName() name = fileName.partition(".")[0] experimental = False if pluginNodes.item(i).firstChildElement( "experimental").text().strip().upper() in [ "TRUE", "YES" ]: experimental = True deprecated = False if pluginNodes.item(i).firstChildElement( "deprecated").text().strip().upper() in [ "TRUE", "YES" ]: deprecated = True trusted = False if pluginNodes.item(i).firstChildElement( "trusted").text().strip().upper() in [ "TRUE", "YES" ]: trusted = True icon = pluginNodes.item(i).firstChildElement( "icon").text().strip() if icon and not icon.startswith("http"): icon = "http://{}/{}".format( QUrl(self.mRepositories[reposName]["url"]).host(), icon) if pluginNodes.item(i).toElement().hasAttribute( "plugin_id"): plugin_id = pluginNodes.item(i).toElement().attribute( "plugin_id") else: plugin_id = None plugin = { "id": name, "plugin_id": plugin_id, "name": pluginNodes.item(i).toElement().attribute("name"), "version_available": pluginNodes.item(i).toElement().attribute("version"), "description": pluginNodes.item(i).firstChildElement( "description").text().strip(), "about": pluginNodes.item(i).firstChildElement( "about").text().strip(), "author_name": pluginNodes.item(i).firstChildElement( "author_name").text().strip(), "homepage": pluginNodes.item(i).firstChildElement( "homepage").text().strip(), "download_url": pluginNodes.item(i).firstChildElement( "download_url").text().strip(), "category": pluginNodes.item(i).firstChildElement( "category").text().strip(), "tags": pluginNodes.item(i).firstChildElement( "tags").text().strip(), "changelog": pluginNodes.item(i).firstChildElement( "changelog").text().strip(), "author_email": pluginNodes.item(i).firstChildElement( "author_email").text().strip(), "tracker": pluginNodes.item(i).firstChildElement( "tracker").text().strip(), "code_repository": pluginNodes.item(i).firstChildElement( "repository").text().strip(), "downloads": pluginNodes.item(i).firstChildElement( "downloads").text().strip(), "average_vote": pluginNodes.item(i).firstChildElement( "average_vote").text().strip(), "rating_votes": pluginNodes.item(i).firstChildElement( "rating_votes").text().strip(), "icon": icon, "experimental": experimental, "deprecated": deprecated, "trusted": trusted, "filename": fileName, "installed": False, "available": True, "status": "not installed", "error": "", "error_details": "", "version_installed": "", "zip_repository": reposName, "library": "", "readonly": False } qgisMinimumVersion = pluginNodes.item(i).firstChildElement( "qgis_minimum_version").text().strip() if not qgisMinimumVersion: qgisMinimumVersion = "2" qgisMaximumVersion = pluginNodes.item(i).firstChildElement( "qgis_maximum_version").text().strip() if not qgisMaximumVersion: qgisMaximumVersion = qgisMinimumVersion[0] + ".99" # if compatible, add the plugin to the list if not pluginNodes.item(i).firstChildElement( "disabled").text().strip().upper() in [ "TRUE", "YES" ]: if isCompatible(pyQgisVersion(), qgisMinimumVersion, qgisMaximumVersion): # add the plugin to the cache plugins.addFromRepository(plugin) self.mRepositories[reposName]["state"] = 2 else: # no plugin metadata found self.mRepositories[reposName]["state"] = 3 if reply.attribute( QNetworkRequest.HttpStatusCodeAttribute) == 200: self.mRepositories[reposName][ "error"] = QCoreApplication.translate( "QgsPluginInstaller", "Server response is 200 OK, but doesn't contain plugin metatada. This is most likely caused by a proxy or a wrong repository URL. You can configure proxy settings in QGIS options." ) else: self.mRepositories[reposName][ "error"] = QCoreApplication.translate( "QgsPluginInstaller", "Status code:") + " {} {}".format( reply.attribute( QNetworkRequest.HttpStatusCodeAttribute), reply.attribute( QNetworkRequest.HttpReasonPhraseAttribute)) self.repositoryFetched.emit(reposName) # is the checking done? if not self.fetchingInProgress(): self.checkingDone.emit() reply.deleteLater()