def batchFinished(self): self.base.stop() if len(self.errors) > 0: msg = u"Processing of the following files ended with error: <br><br>" + "<br><br>".join(self.errors) QErrorMessage(self).showMessage(msg) inDir = self.getInputFileName() outDir = self.getOutputFileName() if outDir is None or inDir == outDir: self.outFiles = self.inFiles # load layers managing the render flag to avoid waste of time canvas = self.iface.mapCanvas() previousRenderFlag = canvas.renderFlag() canvas.setRenderFlag(False) notCreatedList = [] for item in self.outFiles: fileInfo = QFileInfo(item) if fileInfo.exists(): if self.base.loadCheckBox.isChecked(): self.addLayerIntoCanvas(fileInfo) else: notCreatedList.append(item) canvas.setRenderFlag(previousRenderFlag) if len(notCreatedList) == 0: QMessageBox.information(self, self.tr("Finished"), self.tr("Operation completed.")) else: QMessageBox.warning(self, self.tr("Warning"), self.tr("The following files were not created: \n{0}").format(', '.join(notCreatedList)))
def testOneBandRaster(self): path = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') info = QFileInfo(path) base_name = info.baseName() layer = QgsRasterLayer(path, base_name) self.assertTrue(layer) combo = QgsRasterBandComboBox() combo.setLayer(layer) self.assertEqual(combo.layer(), layer) self.assertEqual(combo.currentBand(), 1) self.assertEqual(combo.count(), 1) combo.setShowNotSetOption(True) self.assertEqual(combo.currentBand(), 1) self.assertEqual(combo.count(), 2) combo.setBand(-1) self.assertEqual(combo.currentBand(), -1) combo.setBand(1) self.assertEqual(combo.currentBand(), 1) combo.setShowNotSetOption(False) self.assertEqual(combo.currentBand(), 1) self.assertEqual(combo.count(), 1)
def addToLayout(self): mgr = QgsProject.instance().layoutManager() layout = None layouts = mgr.layouts() if len(layouts) == 0: QMessageBox.warning(self, QApplication.translate("code", "Keine Layouts"), QApplication.translate("code", "Zuerst ein Layout erstellen")) return elif len(layouts) == 1: layout = layouts[0] else: d = VoGISProfilToolLayoutsDialog(self, layouts) result = d.exec_() if result == QDialog.Accepted: layout = mgr.layoutByName(d.ui.cmbLayouts.currentText()) else: return u = Util(self.iface) caption = QApplication.translate("code", "PNG Datei") file_format = [] file_format.append(["PNG files", "png"]) fileName, fileExt = u.getFileName(caption, file_format, QgsProject.instance().homePath()) if fileName == "": return fInfo = QFileInfo(fileName) self.filePath = fInfo.path() figure = self.subplot.figure figure.savefig(fileName, format="png") image = QgsLayoutItemPicture(layout) image.setPicturePath(fileName) image.attemptResize(QgsLayoutSize(200, 200)) layout.addLayoutItem(image)
def selFile(self): sf = QFileInfo(QFileDialog.getOpenFileName(self, 'Open logo file', QDir.homePath(), 'Image files (*.png)')) f = sf.fileName() if f!='': self.logopath = sf.absoluteFilePath() self.label.setPixmap(QPixmap(self.logopath)) return f
def run_clicked(self): self.setEnabled(False) input = self.inputbox.currentLayer().source() if str(self.output.text()) == '': try: output = os.environ['temp']+'out'+str(int(clock()*10000))+'.tif' except: if os.access('/tmp/kuw_filter', os.F_OK)==False: os.mkdir('/tmp/kuw_filter') output = '/tmp/kuw_filter/out'+str(int(clock()*10000))+'.tif' else: output = str(self.output.text()) self.setCursor(QCursor(Qt.WaitCursor)) start = dt.datetime.now() if doFilter(self, input, output): elapsed = dt.datetime.now() - start elapsed = str(dt.timedelta(seconds=round(elapsed.total_seconds()))) self.msgbox(QApplication.translate('kuw_filterdialog','Time elapsed:\n ')+elapsed) if self.addout.isChecked(): fileName = str(output) fileInfo = QFileInfo(fileName) baseName = fileInfo.baseName() iface.addRasterLayer(fileName, baseName) self.setCursor(QCursor(Qt.ArrowCursor)) self.setEnabled(True) self.close()
def testPalettedColorTableToClassData(self): entries = [QgsColorRampShader.ColorRampItem(5, QColor(255, 0, 0), 'item1'), QgsColorRampShader.ColorRampItem(3, QColor(0, 255, 0), 'item2'), QgsColorRampShader.ColorRampItem(6, QColor(0, 0, 255), 'item3'), ] classes = QgsPalettedRasterRenderer.colorTableToClassData(entries) self.assertEqual(classes[0].value, 5) self.assertEqual(classes[1].value, 3) self.assertEqual(classes[2].value, 6) self.assertEqual(classes[0].label, 'item1') self.assertEqual(classes[1].label, 'item2') self.assertEqual(classes[2].label, 'item3') self.assertEqual(classes[0].color.name(), '#ff0000') self.assertEqual(classes[1].color.name(), '#00ff00') self.assertEqual(classes[2].color.name(), '#0000ff') # test #13263 path = os.path.join(unitTestDataPath('raster'), 'hub13263.vrt') info = QFileInfo(path) base_name = info.baseName() layer = QgsRasterLayer(path, base_name) self.assertTrue(layer.isValid(), 'Raster not loaded: {}'.format(path)) classes = QgsPalettedRasterRenderer.colorTableToClassData(layer.dataProvider().colorTable(1)) self.assertEqual(len(classes), 4) classes = QgsPalettedRasterRenderer.colorTableToClassData(layer.dataProvider().colorTable(15)) self.assertEqual(len(classes), 256)
def testSetDataSource(self): """Test change data source""" temp_dir = QTemporaryDir() options = QgsDataProvider.ProviderOptions() myPath = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() layer = QgsRasterLayer(myPath, myBaseName) renderer = QgsSingleBandGrayRenderer(layer.dataProvider(), 2) image = layer.previewAsImage(QSize(400, 400)) self.assertFalse(image.isNull()) self.assertTrue(image.save(os.path.join(temp_dir.path(), 'expected.png'), "PNG")) layer.setDataSource(myPath.replace('4326.tif', '4326-BAD_SOURCE.tif'), 'bad_layer', 'gdal', options) self.assertFalse(layer.isValid()) image = layer.previewAsImage(QSize(400, 400)) self.assertTrue(image.isNull()) layer.setDataSource(myPath.replace('4326-BAD_SOURCE.tif', '4326.tif'), 'bad_layer', 'gdal', options) self.assertTrue(layer.isValid()) image = layer.previewAsImage(QSize(400, 400)) self.assertFalse(image.isNull()) self.assertTrue(image.save(os.path.join(temp_dir.path(), 'actual.png'), "PNG")) self.assertTrue(filecmp.cmp(os.path.join(temp_dir.path(), 'actual.png'), os.path.join(temp_dir.path(), 'expected.png')), False)
def testIdentify(self): 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 myPoint = QgsPointXY(786690, 3345803) # print 'Extents: %s' % myRasterLayer.extent().toString() #myResult, myRasterValues = myRasterLayer.identify(myPoint) #assert myResult myRasterValues = myRasterLayer.dataProvider().identify(myPoint, QgsRaster.IdentifyFormatValue).results() assert len(myRasterValues) > 0 # Get the name of the first band myBand = list(myRasterValues.keys())[0] # myExpectedName = 'Band 1 myExpectedBand = 1 myMessage = 'Expected "%s" got "%s" for first raster band name' % ( myExpectedBand, myBand) assert myExpectedBand == myBand, myMessage # Convert each band value to a list of ints then to a string myValues = list(myRasterValues.values()) myIntValues = [] for myValue in myValues: myIntValues.append(int(myValue)) myValues = str(myIntValues) myExpectedValues = '[127, 141, 112, 72, 86, 126, 156, 211, 170]' myMessage = 'Expected: %s\nGot: %s' % (myValues, myExpectedValues) self.assertEqual(myValues, myExpectedValues, myMessage)
def exportTxt(self): delimiter = self.__getDelimiter() decimalDelimiter = self.__getDecimalDelimiter() if delimiter == decimalDelimiter: msg = QApplication.translate("code", "Gleiches Dezimal- und Spaltentrennzeichen gewählt!") QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", msg) return u = Util(self.iface) caption = QApplication.translate("code", "Textdatei exportieren") fileName, file_ext = u.getFileName(caption, [["txt", "txt"]], self.filePath) if fileName == "": return fInfo = QFileInfo(fileName) self.filePath = fInfo.path() QgsSettings().setValue("vogisprofiltoolmain/savepath", self.filePath) hekto = (self.ui.IDC_chkHekto.checkState() == Qt.Checked) attribs = (self.ui.IDC_chkLineAttributes.checkState() == Qt.Checked) txt = open(fileName, "w") txt.write(self.profiles[0].writeHeader(self.settings.mapData.rasters.selectedRasters(), hekto, attribs, delimiter)) for p in self.profiles: #txt.write("=====Profil {0}======{1}".format(p.id, os.linesep)) #txt.write("Segments:{0}{1}".format(len(p.segments), os.linesep)) #for s in p.segments: # txt.write("Vertices:{0}{1}".format(len(s.vertices), os.linesep)) txt.write(p.toString(hekto, attribs, delimiter, decimalDelimiter )) txt.close()
def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) myPath = os.path.join(TEST_DATA_DIR, 'rgb256x256.png') rasterFileInfo = QFileInfo(myPath) mRasterLayer = QgsRasterLayer(rasterFileInfo.filePath(), rasterFileInfo.completeBaseName()) rasterRenderer = QgsMultiBandColorRenderer( mRasterLayer.dataProvider(), 1, 2, 3) mRasterLayer.setRenderer(rasterRenderer) #pipe = mRasterLayer.pipe() #assert pipe.set(rasterRenderer), 'Cannot set pipe renderer' QgsMapLayerRegistry.instance().addMapLayers([mRasterLayer]) # create composition with composer map self.mMapRenderer = QgsMapRenderer() layerStringList = [] layerStringList.append(mRasterLayer.id()) self.mMapRenderer.setLayerSet(layerStringList) self.mMapRenderer.setProjectionsEnabled(False) self.mComposition = QgsComposition(self.mMapRenderer) self.mComposition.setPaperSize(297, 210) self.mComposerMap = QgsComposerMap(self.mComposition, 20, 20, 200, 100) self.mComposerMap.setFrameEnabled(True) self.mComposition.addComposerMap(self.mComposerMap)
def __exportShp(self, asPnt): u = Util(self.iface) if asPnt is True: caption = QApplication.translate("code", "Punkt Shapefile exportieren") else: caption = QApplication.translate("code", "Linien Shapefile exportieren") fileName, file_ext = u.getFileName(caption, [["shp", "shp"]], self.filePath) if fileName == "": return fInfo = QFileInfo(fileName) self.filePath = fInfo.path() QgsSettings().setValue("vogisprofiltoolmain/savepath", self.filePath) expShp = ExportShape(self.iface, (self.ui.IDC_chkHekto.checkState() == Qt.Checked), (self.ui.IDC_chkLineAttributes.checkState() == Qt.Checked), self.__getDelimiter(), self.__getDecimalDelimiter(), fileName, self.settings, self.profiles ) if asPnt is False: expShp.exportLine() else: expShp.exportPoint()
def selFile(self): sf = QFileInfo(QFileDialog.getOpenFileName(self, 'Select SLD file', '', 'SLD files (*.sld)')) f = sf.fileName() if f!='': df = os.path.join(os.path.join(self.plugin_dir, 'sld'), f) shutil.copy(sf.absoluteFilePath(), df) return f
def __init__(self, methodName): """Run once on class initialization.""" unittest.TestCase.__init__(self, methodName) myPath = os.path.join(TEST_DATA_DIR, 'landsat.tif') rasterFileInfo = QFileInfo(myPath) self.raster_layer = QgsRasterLayer(rasterFileInfo.filePath(), rasterFileInfo.completeBaseName())
def setLastUsedDir(filePath): settings = QSettings() fileInfo = QFileInfo(filePath) if fileInfo.isDir(): dirPath = fileInfo.filePath() else: dirPath = fileInfo.path() settings.setValue("/GdalTools/lastUsedDir", dirPath)
def createDataItem(self, path, parentItem): file_info = QFileInfo(path) if file_info.suffix().lower() == 'model3': alg = QgsProcessingModelAlgorithm() if alg.fromFile(path): return ProcessingModelItem(parentItem, alg.name(), path) return None
def testIssue7023(self): """Check if converting a raster from 1.8 to 2 works.""" myPath = os.path.join(unitTestDataPath("raster"), "raster-pallette-crash2.tif") myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() myRasterLayer = QgsRasterLayer(myPath, myBaseName) myMessage = "Raster not loaded: %s" % myPath assert myRasterLayer.isValid(), myMessage # crash on next line QgsProject.instance().addMapLayers([myRasterLayer])
def testPrintMapFromTemplate(self): """Test that we can get a map to render in the template.""" myPath = os.path.join(TEST_DATA_DIR, 'landsat.tif') myFileInfo = QFileInfo(myPath) myRasterLayer = QgsRasterLayer(myFileInfo.filePath(), myFileInfo.completeBaseName()) myRenderer = QgsMultiBandColorRenderer( myRasterLayer.dataProvider(), 2, 3, 4 ) #mRasterLayer.setRenderer( rasterRenderer ) myPipe = myRasterLayer.pipe() assert myPipe.set(myRenderer), "Cannot set pipe renderer" QgsMapLayerRegistry.instance().addMapLayers([myRasterLayer]) myMapRenderer = QgsMapRenderer() myLayerStringList = [] myLayerStringList.append(myRasterLayer.id()) myMapRenderer.setLayerSet(myLayerStringList) myMapRenderer.setProjectionsEnabled(False) myComposition = QgsComposition(myMapRenderer) myFile = os.path.join(TEST_DATA_DIR, 'template-for-substitution.qpt') with open(myFile) as f: myTemplateContent = f.read() myDocument = QDomDocument() myDocument.setContent(myTemplateContent) myComposition.loadFromTemplate(myDocument) # now render the map, first zooming to the raster extents myMap = myComposition.getComposerMapById(0) myMessage = ('Map 0 could not be found in template %s', myFile) assert myMap is not None, myMessage myExtent = myRasterLayer.extent() myMap.setNewExtent(myExtent) myImagePath = os.path.join(str(QDir.tempPath()), 'template_map_render_python.png') myPageNumber = 0 myImage = myComposition.printPageAsRaster(myPageNumber) myImage.save(myImagePath) assert os.path.exists(myImagePath), 'Map render was not created.' # Not sure if this is a predictable way to test but its quicker than # rendering. myFileSize = QFileInfo(myImagePath).size() myExpectedFileSize = 100000 myMessage = ('Expected file size to be greater than %s, got %s' ' for %s' % (myExpectedFileSize, myFileSize, myImagePath)) assert myFileSize > myExpectedFileSize, myMessage
def exportAutoCadTxt(self): u = Util(self.iface) caption = QApplication.translate("code", "AutoCad Textdatei exportieren") fileName, file_ext = u.getFileName(caption, [["txt", "txt"]], self.filePath) if fileName == "": return fInfo = QFileInfo(fileName) self.filePath = fInfo.path() QgsSettings().setValue("vogisprofiltoolmain/savepath", self.filePath) txt = open(fileName, "w") for p in self.profiles: txt.write(p.toACadTxt(" ", ".")) txt.close()
def testShaderCrash(self): """Check if we assign a shader and then reassign it no crash occurs.""" 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 myRasterShader = QgsRasterShader() myColorRampShader = QgsColorRampShader() myColorRampShader.setColorRampType(QgsColorRampShader.Interpolated) myItems = [] myItem = QgsColorRampShader.ColorRampItem( 10, QColor('#ffff00'), 'foo') myItems.append(myItem) myItem = QgsColorRampShader.ColorRampItem( 100, QColor('#ff00ff'), 'bar') myItems.append(myItem) myItem = QgsColorRampShader.ColorRampItem( 1000, QColor('#00ff00'), 'kazam') myItems.append(myItem) myColorRampShader.setColorRampItemList(myItems) myRasterShader.setRasterShaderFunction(myColorRampShader) myPseudoRenderer = QgsSingleBandPseudoColorRenderer( myRasterLayer.dataProvider(), 1, myRasterShader) myRasterLayer.setRenderer(myPseudoRenderer) return # ####### works first time ############# myRasterShader = QgsRasterShader() myColorRampShader = QgsColorRampShader() myColorRampShader.setColorRampType(QgsColorRampShader.Interpolated) myItems = [] myItem = QgsColorRampShader.ColorRampItem(10, QColor('#ffff00'), 'foo') myItems.append(myItem) myItem = QgsColorRampShader.ColorRampItem(100, QColor('#ff00ff'), 'bar') myItems.append(myItem) myItem = QgsColorRampShader.ColorRampItem(1000, QColor('#00ff00'), 'kazam') myItems.append(myItem) myColorRampShader.setColorRampItemList(myItems) myRasterShader.setRasterShaderFunction(myColorRampShader) # ####### crash on next line (fixed now)################## myPseudoRenderer = QgsSingleBandPseudoColorRenderer( myRasterLayer.dataProvider(), 1, myRasterShader) myRasterLayer.setRenderer(myPseudoRenderer)
def __exportDxf(self, asPnt): u = Util(self.iface) caption = QApplication.translate("code", "DXF exportieren") fileName, file_ext = u.getFileName(caption, [["dxf", "dxf"]], self.filePath) if fileName == "": return fInfo = QFileInfo(fileName) self.filePath = fInfo.path() QgsSettings().setValue("vogisprofiltoolmain/savepath", self.filePath) exDxf = ExportDxf(self.iface, fileName, self.settings, self.profiles) if asPnt is True: exDxf.exportPoint() else: exDxf.exportLine()
def test_setRenderer(self): myPath = os.path.join(unitTestDataPath("raster"), "band1_float32_noct_epsg4326.tif") myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() layer = QgsRasterLayer(myPath, myBaseName) self.rendererChanged = False layer.rendererChanged.connect(self.onRendererChanged) rShader = QgsRasterShader() r = QgsSingleBandPseudoColorRenderer(layer.dataProvider(), 1, rShader) layer.setRenderer(r) assert self.rendererChanged assert layer.renderer() == r
def finished(self): outFn = self.getOutputFileName() if self.needOverwrite: oldFile = QFile(outFn) newFile = QFile(self.tempFile) if oldFile.remove(): newFile.rename(outFn) fileInfo = QFileInfo(outFn) if fileInfo.exists(): if self.base.loadCheckBox.isChecked(): self.addLayerIntoCanvas(fileInfo) QMessageBox.information(self, self.tr("Finished"), self.tr("Processing completed.")) else: QMessageBox.warning(self, self.tr("Warning"), self.tr("{0} not created.").format(outFn))
def testPalettedRendererWithNegativeColorValue(self): """ test paletted raster renderer with negative values in color table""" path = os.path.join(unitTestDataPath('raster'), 'hub13263.vrt') 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])
def __init__(self, uri): """ Constructor for the GeoPackage DataStore. :param uri: A filepath which doesn't exist :type uri: QFileInfo, str .. versionadded:: 4.0 """ super(GeoPackage, self).__init__(uri) self.vector_driver = ogr.GetDriverByName('GPKG') self.raster_driver = gdal.GetDriverByName('GPKG') if isinstance(uri, QFileInfo): self._uri = uri elif isinstance(uri, str): self._uri = QFileInfo(uri) else: raise ErrorDataStore('Unknown type') if self.uri.exists(): raster_datasource = gdal.Open(self.uri.absoluteFilePath()) if raster_datasource is None: # Let's try if it's a vector one. vector_datasource = self.vector_driver.Open( self.uri.absoluteFilePath()) if vector_datasource is None: msg = 'The file is not a geopackage or it doesn\'t ' \ 'contain any layers.' raise ErrorDataStore(msg) else: path = self.uri.absoluteFilePath() # We need this variable to be created. The delete will create it. datasource = self.vector_driver.CreateDataSource(path) # NOQA del datasource
def testCase(self): TEST_DATA_DIR = unitTestDataPath() vectorFileInfo = QFileInfo(TEST_DATA_DIR + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) layout = QgsPrintLayout(QgsProject.instance()) layout.initializeDefaults() label = QgsLayoutItemLabel(layout) layout.addLayoutItem(label) self.evaluation_test(layout, label) self.feature_evaluation_test(layout, label, mVectorLayer) self.page_evaluation_test(layout, label, mVectorLayer)
def finished(self, load): outFn = self.getOutputFileName() if outFn is None: return if outFn == '': QMessageBox.warning(self, self.tr("Warning"), self.tr("No output file created.")) return fileInfo = QFileInfo(outFn) if fileInfo.exists(): if load: self.addLayerIntoCanvas(fileInfo) QMessageBox.information(self, self.tr("Finished"), self.tr("Processing completed.")) else: #QMessageBox.warning(self, self.tr( "Warning" ), self.tr( "%1 not created." ).arg( outFn ) ) QMessageBox.warning(self, self.tr("Warning"), self.tr("%s not created.") % outFn)
def loadList(self): self.fileName, _ = QFileDialog.getOpenFileName( None, "Load data separated by ';'", self.fPath, "" ) if not os.path.exists(self.fileName): return 0 # update selected file's folder fInfo = QFileInfo(self.fileName) self.fPath = fInfo.absolutePath() self.saveConf() self.render_temp_band() # get saved data try: f = open(self.fileName) lines = f.readlines() f.close() self.clearList() for line in lines: # remove trailing 'new lines', etc and break into parts parts = ((line.strip()).lower()).split("=") if len(parts) > 1: # self.say("line="+line+'\nparts[0]='+parts[0]+'\nparts[1]='+parts[1]) if parts[0].lower() == "angle": self.setAngle(parts[1].lower()) elif parts[0].lower() == "heading": self.setHeading(parts[1].lower()) elif parts[0].lower() == "declination": self.setDeclination(parts[1].lower()) elif parts[0].lower() == "dist_units": self.setDistanceUnits(parts[1].lower()) elif parts[0].lower() == "angle_unit": self.setAngleUnit(parts[1].lower()) elif parts[0].lower() == "startat": self.setStartAt(parts[1].lower()) elif parts[0].lower() == "survey": self.setSurvey(parts[1].lower()) else: coords = tuple((line.strip()).split(";")) if coords[0].lower() == "[data]": pass else: self.addrow(*coords) except: self.say("Invalid input")
def testNameForPage(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.setPageNameExpression("\"NAME_1\"") self.assertTrue(atlas.beginRender()) self.assertEqual(atlas.nameForPage(0), 'Basse-Normandie') self.assertEqual(atlas.nameForPage(1), 'Bretagne') self.assertEqual(atlas.nameForPage(2), 'Pays de la Loire') self.assertEqual(atlas.nameForPage(3), 'Centre')
def testSignals(self): path = os.path.join(unitTestDataPath('raster'), 'band3_float32_noct_epsg4326.tif') info = QFileInfo(path) base_name = info.baseName() layer = QgsRasterLayer(path, base_name) self.assertTrue(layer) combo = QgsRasterBandComboBox() combo.setLayer(layer) signal_spy = QSignalSpy(combo.bandChanged) combo.setBand(2) self.assertEqual(len(signal_spy), 1) self.assertEqual(signal_spy[0][0], 2) combo.setBand(3) self.assertEqual(len(signal_spy), 2) self.assertEqual(signal_spy[1][0], 3)
def testCase(self): TEST_DATA_DIR = unitTestDataPath() vectorFileInfo = QFileInfo(TEST_DATA_DIR + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsProject.instance().addMapLayers([mVectorLayer]) # create composition with composer map mapSettings = QgsMapSettings() mapSettings.setLayers([mVectorLayer]) mComposition = QgsComposition(QgsProject.instance()) mComposition.setPaperSize(297, 210) mLabel = QgsComposerLabel(mComposition) mComposition.addComposerLabel(mLabel) self.evaluation_test(mComposition, mLabel) self.feature_evaluation_test(mComposition, mLabel, mVectorLayer) self.page_evaluation_test(mComposition, mLabel, mVectorLayer)
def installFromZipFile(self, filePath): if not os.path.isfile(filePath): return settings = QgsSettings() settings.setValue(settingsGroup + '/lastZipDirectory', QFileInfo(filePath).absoluteDir().absolutePath()) error = False infoString = None with zipfile.ZipFile(filePath, 'r') as zf: pluginName = os.path.split(zf.namelist()[0])[0] pluginFileName = os.path.splitext(os.path.basename(filePath))[0] pluginsDirectory = qgis.utils.home_plugin_path if not QDir(pluginsDirectory).exists(): QDir().mkpath(pluginsDirectory) # If the target directory already exists as a link, # remove the link without resolving QFile(os.path.join(pluginsDirectory, pluginFileName)).remove() try: # Test extraction. If fails, then exception will be raised # and no removing occurs unzip(str(filePath), str(pluginsDirectory)) # Removing old plugin files if exist removeDir( QDir.cleanPath(os.path.join(pluginsDirectory, pluginFileName))) # Extract new files unzip(str(filePath), str(pluginsDirectory)) except: error = True infoString = ( self.tr("Plugin installation failed"), self. tr("Failed to unzip the plugin package\n{}.\nProbably it is broken" .format(filePath))) if infoString is None: updateAvailablePlugins() loadPlugin(pluginName) plugins.getAllInstalled() plugins.rebuild() if settings.contains('/PythonPlugins/' + pluginName): if settings.value('/PythonPlugins/' + pluginName, False, bool): startPlugin(pluginName) reloadPlugin(pluginName) else: unloadPlugin(pluginName) loadPlugin(pluginName) else: if startPlugin(pluginName): settings.setValue('/PythonPlugins/' + pluginName, True) infoString = (self.tr("Plugin installed successfully"), "") if infoString[0]: level = error and QgsMessageBar.CRITICAL or QgsMessageBar.INFO msg = "<b>%s:</b>%s" % (infoString[0], infoString[1]) iface.pluginManagerInterface().pushMessage(msg, level)
def accept(self): self.startTime = time.time() self.tileCount = 0 self.blankCount = 0 if self.rbOutputZip.isChecked(): output = self.leZipFileName.text() elif self.rbOutputDir.isChecked(): output = self.leDirectoryName.text() if not QFileInfo(output).exists(): os.mkdir(QFileInfo(output).absoluteFilePath()) elif self.rbOutputNGM.isChecked(): output = self.leTilesFroNGM.text() if not output: QMessageBox.warning( self, self.tr('No output'), self. tr('Output path is not set. Please enter correct path and try again.' )) return fileInfo = QFileInfo(output) if fileInfo.isDir() and not len( QDir(output).entryList(QDir.Dirs | QDir.Files | QDir.NoDotAndDotDot)) == 0: res = QMessageBox.warning( self, self.tr('Directory not empty'), self.tr('Selected directory is not empty. Continue?'), QMessageBox.Yes | QMessageBox.No) if res == QMessageBox.No: return if self.spnZoomMin.value() > self.spnZoomMax.value(): QMessageBox.warning( self, self.tr('Wrong zoom'), self. tr('Maximum zoom value is lower than minimum. Please correct this and try again.' )) return self.settings.setValue('rootDir', self.leRootDir.text()) self.settings.setValue('outputToZip', self.rbOutputZip.isChecked()) self.settings.setValue('outputToDir', self.rbOutputDir.isChecked()) self.settings.setValue('outputToNGM', self.rbOutputNGM.isChecked()) self.settings.setValue('extentCanvas', self.rbExtentCanvas.isChecked()) self.settings.setValue('extentFull', self.rbExtentFull.isChecked()) self.settings.setValue('extentLayer', self.rbExtentLayer.isChecked()) self.settings.setValue('minZoom', self.spnZoomMin.value()) self.settings.setValue('maxZoom', self.spnZoomMax.value()) self.settings.setValue('keepRatio', self.chkLockRatio.isChecked()) self.settings.setValue('tileWidth', self.spnTileWidth.value()) self.settings.setValue('tileHeight', self.spnTileHeight.value()) self.settings.setValue('format', self.cmbFormat.currentIndex()) self.settings.setValue('transparency', self.spnTransparency.value()) self.settings.setValue('quality', self.spnQuality.value()) self.settings.setValue('macroTile', self.spnMacroTile.value()) self.settings.setValue('enable_antialiasing', self.chkAntialiasing.isChecked()) self.settings.setValue('use_tms_filenames', self.chkTMSConvention.isChecked()) self.settings.setValue('skipBlankTiles', self.chkSkipBlankTiles.isChecked()) self.settings.setValue('use_mbtiles_compression', self.chkMBTilesCompression.isChecked()) self.settings.setValue('write_json', self.chkWriteJson.isChecked()) self.settings.setValue('write_overview', self.chkWriteOverview.isChecked()) self.settings.setValue('write_mapurl', self.chkWriteMapurl.isChecked()) self.settings.setValue('write_viewer', self.chkWriteViewer.isChecked()) self.settings.setValue('chkMsgDialogs', self.chkMsgDialogs.isChecked()) canvas = self.iface.mapCanvas() if self.rbExtentCanvas.isChecked(): extent = canvas.extent() elif self.rbExtentFull.isChecked(): extent = canvas.fullExtent() else: layer = utils.getLayerById( self.cmbLayers.itemData(self.cmbLayers.currentIndex())) extent = canvas.mapSettings().layerExtentToOutputExtent( layer, layer.extent()) extent = QgsCoordinateTransform( canvas.mapSettings().destinationCrs(), QgsCoordinateReferenceSystem('EPSG:4326'), QgsProject.instance()).transform(extent) arctanSinhPi = math.degrees(math.atan(math.sinh(math.pi))) extent = extent.intersect( QgsRectangle(-180, -arctanSinhPi, 180, arctanSinhPi)) layers = canvas.layers() writeMapurl = self.chkWriteMapurl.isEnabled( ) and self.chkWriteMapurl.isChecked() writeViewer = self.chkWriteViewer.isEnabled( ) and self.chkWriteViewer.isChecked() self.workThread = TilingThread( layers, extent, self.spnZoomMin.value(), self.spnZoomMax.value(), self.spnTileWidth.value(), self.spnTileHeight.value(), self.spnMacroTile.value(), self.spnTransparency.value(), self.spnQuality.value(), self.cmbFormat.currentText(), fileInfo, self.leRootDir.text(), self.chkAntialiasing.isChecked(), self.chkTMSConvention.isChecked(), self.chkMBTilesCompression.isChecked(), self.chkWriteJson.isChecked(), self.chkWriteOverview.isChecked(), # self.chkRenderOutsideTiles.isChecked(), self.chkSkipBlankTiles.isChecked(), writeMapurl, writeViewer) self.workThread.rangeChanged.connect(self.setProgressRange) self.workThread.updateProgress.connect(self.updateProgress) self.workThread.processFinished.connect(self.processFinished) self.workThread.processInterrupted.connect(self.processInterrupted) self.workThread.threshold.connect(self.confirmContinueThreshold) self.btnOk.setEnabled(False) self.btnClose.setText(self.tr('Cancel')) self.buttonBox.rejected.disconnect(self.reject) self.btnClose.clicked.connect(self.stopProcessing) self.workThread.start()
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 __init__(self, conn, cursor, raster, max_size, progress_label): QObject.__init__(self) self.cursor = cursor self.conn = conn self.progress_label = progress_label self.messages = "" opts = {} opts['version'] = g_rt_version opts['endian'] = NDR opts['column'] = 'rast' opts['create_table'] = 1 opts['drop_table'] = 1 opts['overview_level'] = 1 opts['block_size'] = 'auto' opts['band'] = None opts['register'] = None # Create PostGIS Raster Tool Functions raster_tools_file = "%s/raster_tools.sql" % os.path.dirname(__file__) sql = open(raster_tools_file).read().encode('ascii', errors='ignore') self.cursor.execute(sql) self.conn.commit() i = 0 # Burn all specified input raster files into single WKTRaster table gt = None layer_info = raster opts['srid'] = layer_info['layer'].dataProvider().crs().postgisSrid() infile = layer_info['data_source'] file_info = QFileInfo(infile) file_size = file_info.size() size = DbConnections().db_size() file_size /= 1024 * 1024 size = size + file_size if size > float(max_size): QMessageBox.warning( None, self.tr("Database full"), self. tr("Upload would exceeded the maximum database size for your current QGIS Cloud plan. Please free up some space or upgrade your QGIS Cloud plan." )) return False opts['table'] = layer_info['table_name'] self.progress_label.setText( self.tr("Creating table '{table}'...").format(table=opts['table'])) QApplication.processEvents() self.cursor.execute(self.make_sql_drop_raster_table(opts['table'])) self.conn.commit() self.cursor.execute(self.make_sql_create_table(opts, opts['table'])) self.conn.commit() gt = self.wkblify_raster(opts, infile.replace('\\', '/'), i, gt) i += 1 self.cursor.execute( self.make_sql_create_gist(opts['table'], opts['column'])) self.conn.commit() # create raster overviews for level in [4, 8, 16, 32]: sql = 'drop table if exists o_%d_%s' % (level, opts['table']) self.cursor.execute(sql) self.conn.commit() sql = "select st_createoverview_qgiscloud('%s'::regclass, '%s'::name, %d)" % ( opts['table'], opts['column'], level) self.progress_label.setText( self.tr( "Creating overview-level {level} for table '{table}'..."). format(level=level, table=opts['table'])) QApplication.processEvents() self.cursor.execute(sql) self.conn.commit() index_table = 'o_' + str(level) + '_' + opts['table'] self.cursor.execute( self.make_sql_create_gist(index_table, opts['column'])) self.conn.commit() self.progress_label.setText( self.tr("Registering raster columns of table '%s'..." % (opts['table']))) QApplication.processEvents() self.cursor.execute(self.make_sql_addrastercolumn(opts)) self.conn.commit()
def reloadData(self): self.beginResetModel() self._document_list = [] if self._relation.isValid() is False or self._feature.isValid( ) is False: self.endResetModel() return feature_list = [] layer = self._relation.referencingLayer() request = self._relation.getRelatedFeaturesRequest(self._feature) for feature in layer.getFeatures(request): feature_list.append(feature) if self._nmRelation.isValid(): filters = [] for joinTableFeature in feature_list: referencedFeatureRequest = self._nmRelation.getReferencedFeatureRequest( joinTableFeature) filterExpression = referencedFeatureRequest.filterExpression() filters.append("(" + filterExpression.expression() + ")") nmRequest = QgsFeatureRequest() nmRequest.setFilterExpression(" OR ".join(filters)) feature_list = [] layer = self._nmRelation.referencedLayer() for documentFeature in layer.getFeatures(nmRequest): feature_list.append(documentFeature) for documentFeature in feature_list: documents_path = str() if self._documents_path: exp = QgsExpression(self._documents_path) context = QgsExpressionContext() context.appendScopes( QgsExpressionContextUtils.globalProjectLayerScopes(layer)) context.setFeature(documentFeature) documents_path = exp.evaluate(context) document_filename = str() if self._document_filename: exp = QgsExpression(self._document_filename) context = QgsExpressionContext() context.appendScopes( QgsExpressionContextUtils.globalProjectLayerScopes(layer)) context.setFeature(documentFeature) document_filename = exp.evaluate(context) file_info = QFileInfo(QDir(str(documents_path)), str(document_filename)) # ToolTip toolTipList = [] toolTipList.append("<ul>") for field in documentFeature.fields(): index = documentFeature.fields().indexFromName(field.name()) toolTipList.append("<li><strong>{0}</strong>: {1}</li>".format( field.displayName(), documentFeature[index])) toolTipList.append("</ul>") self._document_list.append({ self.DocumentIdRole: documentFeature.id(), self.DocumentPathRole: file_info.filePath(), self.DocumentNameRole: file_info.fileName(), self.DocumentExistsRole: file_info.exists(), self.DocumentToolTipRole: "".join(toolTipList), self.DocumentIsImageRole: PreviewImageProvider.isMimeTypeSupported(file_info.filePath()) }) self.endResetModel()
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 installFromZipFile(self, filePath): if not os.path.isfile(filePath): return settings = QgsSettings() settings.setValue(settingsGroup + '/lastZipDirectory', QFileInfo(filePath).absoluteDir().absolutePath()) with zipfile.ZipFile(filePath, 'r') as zf: pluginName = os.path.split(zf.namelist()[0])[0] pluginFileName = os.path.splitext(os.path.basename(filePath))[0] pluginsDirectory = qgis.utils.home_plugin_path if not QDir(pluginsDirectory).exists(): QDir().mkpath(pluginsDirectory) pluginDirectory = QDir.cleanPath(os.path.join(pluginsDirectory, pluginName)) # If the target directory already exists as a link, # remove the link without resolving QFile(pluginDirectory).remove() password = None infoString = None success = False keepTrying = True while keepTrying: try: # Test extraction. If fails, then exception will be raised and no removing occurs unzip(filePath, pluginsDirectory, password) # Removing old plugin files if exist removeDir(pluginDirectory) # Extract new files unzip(filePath, pluginsDirectory, password) keepTrying = False success = True except Exception as e: success = False if 'password' in str(e): infoString = self.tr('Aborted by user') if 'Bad password' in str(e): msg = self.tr('Wrong password. Please enter a correct password to the zip file.') else: msg = self.tr('The zip file is encrypted. Please enter password.') # Display a password dialog with QgsPasswordLineEdit dlg = QDialog() dlg.setWindowTitle(self.tr('Enter password')) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal) buttonBox.rejected.connect(dlg.reject) buttonBox.accepted.connect(dlg.accept) lePass = QgsPasswordLineEdit() layout = QVBoxLayout() layout.addWidget(QLabel(msg)) layout.addWidget(lePass) layout.addWidget(buttonBox) dlg.setLayout(layout) keepTrying = dlg.exec_() password = lePass.text() else: infoString = self.tr("Failed to unzip the plugin package\n{}.\nProbably it is broken".format(filePath)) keepTrying = False if success: updateAvailablePlugins() self.processDependencies(pluginName) loadPlugin(pluginName) plugins.getAllInstalled() plugins.rebuild() if settings.contains('/PythonPlugins/' + pluginName): if settings.value('/PythonPlugins/' + pluginName, False, bool): startPlugin(pluginName) reloadPlugin(pluginName) else: unloadPlugin(pluginName) loadPlugin(pluginName) else: if startPlugin(pluginName): settings.setValue('/PythonPlugins/' + pluginName, True) self.exportPluginsToManager() msg = "<b>%s</b>" % self.tr("Plugin installed successfully") else: msg = "<b>%s:</b> %s" % (self.tr("Plugin installation failed"), infoString) level = Qgis.Info if success else Qgis.Critical iface.pluginManagerInterface().pushMessage(msg, level)
def installFromZipFile(self, filePath): if not os.path.isfile(filePath): return settings = QgsSettings() settings.setValue(settingsGroup + '/lastZipDirectory', QFileInfo(filePath).absoluteDir().absolutePath()) pluginName = None with zipfile.ZipFile(filePath, 'r') as zf: # search for metadata.txt. In case of multiple files, we can assume that # the shortest path relates <pluginname>/metadata.txt metadatafiles = sorted(f for f in zf.namelist() if f.endswith('metadata.txt')) if len(metadatafiles) > 0: pluginName = os.path.split(metadatafiles[0])[0] pluginFileName = os.path.splitext(os.path.basename(filePath))[0] if not pluginName: msg_box = QMessageBox() msg_box.setIcon(QMessageBox.Warning) msg_box.setWindowTitle( self.tr("QGIS Python Install from ZIP Plugin Installer")) msg_box.setText( self. tr("The Zip file is not a valid QGIS python plugin. No root folder was found inside." )) msg_box.setStandardButtons(QMessageBox.Ok) more_info_btn = msg_box.addButton(self.tr("More Information"), QMessageBox.HelpRole) msg_box.exec() if msg_box.clickedButton() == more_info_btn: QgsHelp.openHelp( "plugins/plugins.html#the-install-from-zip-tab") return pluginsDirectory = qgis.utils.home_plugin_path if not QDir(pluginsDirectory).exists(): QDir().mkpath(pluginsDirectory) pluginDirectory = QDir.cleanPath( os.path.join(pluginsDirectory, pluginName)) # If the target directory already exists as a link, # remove the link without resolving QFile(pluginDirectory).remove() password = None infoString = None success = False keepTrying = True while keepTrying: try: # Test extraction. If fails, then exception will be raised and no removing occurs unzip(filePath, pluginsDirectory, password) # Removing old plugin files if exist removeDir(pluginDirectory) # Extract new files unzip(filePath, pluginsDirectory, password) keepTrying = False success = True except Exception as e: success = False if 'password' in str(e): infoString = self.tr('Aborted by user') if 'Bad password' in str(e): msg = self.tr( 'Wrong password. Please enter a correct password to the zip file.' ) else: msg = self.tr( 'The zip file is encrypted. Please enter password.' ) # Display a password dialog with QgsPasswordLineEdit dlg = QDialog() dlg.setWindowTitle(self.tr('Enter password')) buttonBox = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal) buttonBox.rejected.connect(dlg.reject) buttonBox.accepted.connect(dlg.accept) lePass = QgsPasswordLineEdit() layout = QVBoxLayout() layout.addWidget(QLabel(msg)) layout.addWidget(lePass) layout.addWidget(buttonBox) dlg.setLayout(layout) keepTrying = dlg.exec_() password = lePass.text() else: infoString = self.tr( "Failed to unzip the plugin package\n{}.\nProbably it is broken" .format(filePath)) keepTrying = False if success: with OverrideCursor(Qt.WaitCursor): updateAvailablePlugins() self.processDependencies(pluginName) loadPlugin(pluginName) plugins.getAllInstalled() plugins.rebuild() if settings.contains('/PythonPlugins/' + pluginName): # Plugin was available? if settings.value('/PythonPlugins/' + pluginName, False, bool): # Plugin was also active? reloadPlugin( pluginName ) # unloadPlugin + loadPlugin + startPlugin else: unloadPlugin(pluginName) loadPlugin(pluginName) else: if startPlugin(pluginName): settings.setValue('/PythonPlugins/' + pluginName, True) self.exportPluginsToManager() msg = "<b>%s</b>" % self.tr("Plugin installed successfully") else: msg = "<b>%s:</b> %s" % (self.tr("Plugin installation failed"), infoString) level = Qgis.Info if success else Qgis.Critical iface.pluginManagerInterface().pushMessage(msg, level)
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 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 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 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 onGenerate(self): """ Slot raised to initiate the certificate generation process. """ self._notif_bar.clear() success_status = True config = self.current_config() self.last_data_source = config.data_source() if config is None: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "The entity configuration could not be extracted.")) return # Get selected records and validate records = self.tabWidget.currentWidget().entities() if self.chk_template_datasource.isChecked(): records = self._dummy_template_records() if len(records) == 0: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "Please load at least one entity record")) return if not self._docTemplatePath: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "Please select a document template to use")) return documentNamingAttrs = self.lstDocNaming.selectedMappings() if self.chkUseOutputFolder.checkState() == Qt.Checked and len( documentNamingAttrs) == 0: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "Please select at least one field for naming the output document")) return # Set output file properties if self.rbExpImage.isChecked(): outputMode = DocumentGenerator.Image fileExtension = self.cboImageType.currentText() saveAsText = "Image File" else: outputMode = DocumentGenerator.PDF fileExtension = "pdf" saveAsText = "PDF File" # Show save file dialog if not using output folder if self.chkUseOutputFolder.checkState() == Qt.Unchecked: docDir = source_document_location() if self._outputFilePath: fileInfo = QFileInfo(self._outputFilePath) docDir = fileInfo.dir().path() self._outputFilePath, _ = QFileDialog.getSaveFileName( self, QApplication.translate("DocumentGeneratorDialog", "Save Document"), docDir, "{0} (*.{1})".format( QApplication.translate("DocumentGeneratorDialog", saveAsText), fileExtension)) if not self._outputFilePath: self._notif_bar.insertErrorNotification( QApplication.translate( "DocumentGeneratorDialog", "Process aborted. No output file was specified.")) return # Include extension in file name self._outputFilePath = self._outputFilePath # + "." + fileExtension # else: # Multiple files to be generated. # pass self._doc_generator.set_link_field(config.link_field()) self._doc_generator.clear_attr_value_formatters() if not self.chk_template_datasource.isChecked(): # Apply cell formatters for naming output files self._doc_generator.set_attr_value_formatters(config.formatters()) entity_field_name = "id" # Iterate through the selected records progressDlg = QProgressDialog(self) progressDlg.setMaximum(len(records)) try: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) for i, record in enumerate(records): progressDlg.setValue(i) if progressDlg.wasCanceled(): success_status = False break # User-defined location if self.chkUseOutputFolder.checkState() == Qt.Unchecked: status, msg = self._doc_generator.run( self._docTemplatePath, entity_field_name, record.id, outputMode, data_source=self.ds_entity.name, filePath=self._outputFilePath) self._doc_generator.clear_temporary_layers() # Output folder location using custom naming else: status, msg = self._doc_generator.run( self._docTemplatePath, entity_field_name, record.id, outputMode, dataFields=documentNamingAttrs, fileExtension=fileExtension, data_source=self.ds_entity.name) self._doc_generator.clear_temporary_layers() if not status: result = QMessageBox.warning( self, QApplication.translate("DocumentGeneratorDialog", "Document Generate Error"), msg, QMessageBox.Ignore | QMessageBox.Abort) if result == QMessageBox.Abort: progressDlg.close() success_status = False # Restore cursor QApplication.restoreOverrideCursor() return # If its the last record and user has selected to ignore if i + 1 == len(records): progressDlg.close() success_status = False # Restore cursor QApplication.restoreOverrideCursor() return else: progressDlg.setValue(len(records)) QApplication.restoreOverrideCursor() QMessageBox.information( self, QApplication.translate("DocumentGeneratorDialog", "Document Generation Complete"), QApplication.translate( "DocumentGeneratorDialog", "Document generation has successfully completed.")) except DummyException as ex: LOGGER.debug(str(ex)) err_msg = sys.exc_info()[1] QApplication.restoreOverrideCursor() QMessageBox.critical( self, "STDM", QApplication.translate( "DocumentGeneratorDialog", "Error Generating documents - %s" % (err_msg))) success_status = False # Reset UI self.reset(success_status)
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 composition with composer map # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) QgsProject.instance().setCrs(crs) self.mComposition = QgsComposition(QgsProject.instance()) self.mComposition.setPaperSize(297, 210) # fix the renderer, fill with green props = {"color": "0,127,0"} fillSymbol = QgsFillSymbol.createSimple(props) renderer = QgsSingleSymbolRenderer(fillSymbol) mVectorLayer.setRenderer(renderer) # the atlas map self.mAtlasMap = QgsComposerMap(self.mComposition, 20, 20, 130, 130) self.mAtlasMap.setFrameEnabled(True) self.mAtlasMap.setLayers([mVectorLayer]) self.mComposition.addComposerMap(self.mAtlasMap) # the atlas self.mAtlas = self.mComposition.atlasComposition() self.mAtlas.setCoverageLayer(mVectorLayer) self.mAtlas.setEnabled(True) self.mComposition.setAtlasMode(QgsComposition.ExportAtlas) # an overview self.mOverview = QgsComposerMap(self.mComposition, 180, 20, 50, 50) self.mOverview.setFrameEnabled(True) self.mOverview.overview().setFrameMap(self.mAtlasMap.id()) self.mOverview.setLayers([mVectorLayer]) self.mComposition.addComposerMap(self.mOverview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) self.mOverview.setNewExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127"} fillSymbol2 = QgsFillSymbol.createSimple(props2) self.mOverview.overview().setFrameSymbol(fillSymbol2) # header label self.mLabel1 = QgsComposerLabel(self.mComposition) self.mComposition.addComposerLabel(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.setSceneRect(QRectF(150, 5, 60, 15)) qWarning( "header label font: %s exactMatch:%s" % (self.mLabel1.font().toString(), self.mLabel1.font().exactMatch())) # feature number label self.mLabel2 = QgsComposerLabel(self.mComposition) self.mComposition.addComposerLabel(self.mLabel2) self.mLabel2.setText( "# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.setSceneRect(QRectF(150, 200, 60, 15)) qWarning( "feature number label font: %s exactMatch:%s" % (self.mLabel2.font().toString(), self.mLabel2.font().exactMatch())) self.filename_test() self.autoscale_render_test() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() shutil.rmtree(tmppath, True)
def open_style(input_file): # pylint: disable=too-many-locals,too-many-branches,too-many-statements """ Opens a .style file """ if not Extractor.is_mdb_tools_binary_available(): message_bar = iface.messageBar() widget = message_bar.createMessage('SLYR', "MDB Tools utility not found") settings_button = QPushButton("Configure…", pressed=partial( open_settings, widget)) widget.layout().addWidget(settings_button) message_bar.pushWidget(widget, Qgis.Critical) return True style = QgsStyle() style.createMemoryDatabase() symbol_names = set() def make_name_unique(name): """ Ensures that the symbol name is unique (in a case insensitive way) """ counter = 0 candidate = name while candidate.lower() in symbol_names: # make name unique if counter == 0: candidate += '_1' else: candidate = candidate[:candidate.rfind('_') + 1] + str(counter) counter += 1 symbol_names.add(candidate.lower()) return candidate feedback = QgsFeedback() progress_dialog = QProgressDialog("Loading style database…", "Abort", 0, 100, None) progress_dialog.setWindowTitle("Loading Style") def progress_changed(progress): """ Handles feedback to progress dialog bridge """ progress_dialog.setValue(progress) iters = 0 while QCoreApplication.hasPendingEvents() and iters < 100: QCoreApplication.processEvents() iters += 1 feedback.progressChanged.connect(progress_changed) def cancel(): """ Slot to cancel the import """ feedback.cancel() progress_dialog.canceled.connect(cancel) unreadable = [] warnings = set() errors = set() types_to_extract = [ Extractor.FILL_SYMBOLS, Extractor.LINE_SYMBOLS, Extractor.MARKER_SYMBOLS, Extractor.COLOR_RAMPS, Extractor.TEXT_SYMBOLS, Extractor.LABELS, Extractor.MAPLEX_LABELS, Extractor.AREA_PATCHES, Extractor.LINE_PATCHES ] type_percent = 100 / len(types_to_extract) for type_index, symbol_type in enumerate(types_to_extract): try: raw_symbols = Extractor.extract_styles(input_file, symbol_type) except MissingBinaryException: show_warning( 'MDB Tools utility not found', 'Convert style', 'The MDB tools "mdb-export" utility is required to convert .style databases. Please setup a path to the MDB tools utility in the SLYR options panel.', level=Qgis.Critical) progress_dialog.deleteLater() return True if feedback.isCanceled(): break for index, raw_symbol in enumerate(raw_symbols): feedback.setProgress(index / len(raw_symbols) * type_percent + type_percent * type_index) if feedback.isCanceled(): break name = raw_symbol[Extractor.NAME] tags = raw_symbol[Extractor.TAGS].split(';') if symbol_type in (Extractor.AREA_PATCHES, Extractor.LINE_PATCHES, Extractor.TEXT_SYMBOLS, Extractor.MAPLEX_LABELS, Extractor.LABELS): if symbol_type == Extractor.AREA_PATCHES: type_string = 'area patches' elif symbol_type == Extractor.LINE_PATCHES: type_string = 'line patches' elif symbol_type == Extractor.TEXT_SYMBOLS: type_string = 'text symbols' elif symbol_type == Extractor.MAPLEX_LABELS: type_string = 'maplex labels' elif symbol_type == Extractor.LABELS: type_string = 'labels' else: type_string = '' unreadable.append( '<b>{}</b>: {} conversion requires a licensed version of the SLYR plugin' .format(html.escape(name), type_string)) continue unique_name = make_name_unique(name) handle = BytesIO(raw_symbol[Extractor.BLOB]) stream = Stream(handle) stream.allow_shortcuts = False try: symbol = stream.read_object() except UnreadableSymbolException as e: e = 'Unreadable object: {}'.format(e) unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue except NotImplementedException as e: unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue except UnsupportedVersionException as e: e = 'Unsupported version: {}'.format(e) unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue except UnknownClsidException as e: unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue except UnreadablePictureException as e: unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue context = Context() context.symbol_name = unique_name def unsupported_object_callback(msg, level=Context.WARNING): if level == Context.WARNING: warnings.add('<b>{}</b>: {}'.format( html.escape(unique_name), # pylint: disable=cell-var-from-loop html.escape(msg))) elif level == Context.CRITICAL: errors.add('<b>{}</b>: {}'.format( html.escape(unique_name), # pylint: disable=cell-var-from-loop html.escape(msg))) context.unsupported_object_callback = unsupported_object_callback # context.style_folder, _ = os.path.split(output_file) try: qgis_symbol = SymbolConverter.Symbol_to_QgsSymbol( symbol, context) except NotImplementedException as e: unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue except UnreadablePictureException as e: unreadable.append('<b>{}</b>: {}'.format( html.escape(name), html.escape(str(e)))) continue if isinstance(qgis_symbol, QgsSymbol): # self.check_for_missing_fonts(qgis_symbol, feedback) style.addSymbol(unique_name, qgis_symbol, True) elif isinstance(qgis_symbol, QgsColorRamp): style.addColorRamp(unique_name, qgis_symbol, True) if tags: if isinstance(qgis_symbol, QgsSymbol): assert style.tagSymbol(QgsStyle.SymbolEntity, unique_name, tags) elif isinstance(qgis_symbol, QgsColorRamp): assert style.tagSymbol(QgsStyle.ColorrampEntity, unique_name, tags) progress_dialog.deleteLater() if feedback.isCanceled(): return True if errors or unreadable or warnings: message = '' if unreadable: message = '<p>The following symbols could not be converted:</p>' message += '<ul>' for w in unreadable: message += '<li>{}</li>'.format(w.replace('\n', '<br>')) message += '</ul>' if errors: message += '<p>The following errors were generated while converting symbols:</p>' message += '<ul>' for w in errors: message += '<li>{}</li>'.format(w.replace('\n', '<br>')) message += '</ul>' if warnings: message += '<p>The following warnings were generated while converting symbols:</p>' message += '<ul>' for w in warnings: message += '<li>{}</li>'.format(w.replace('\n', '<br>')) message += '</ul>' show_warning('style could not be completely converted', 'Convert style', message, level=Qgis.Critical if (unreadable or errors) else Qgis.Warning) if Qgis.QGIS_VERSION_INT >= 30800: dlg = QgsStyleManagerDialog(style, readOnly=True) dlg.setFavoritesGroupVisible(False) dlg.setSmartGroupsVisible(False) fi = QFileInfo(input_file) dlg.setBaseStyleName(fi.baseName()) else: dlg = QgsStyleManagerDialog(style) dlg.exec_() return True
def btnBrowseInputFile_clicked(self): file_path = QFileDialog.getOpenFileName( self, tr("Choose interlis transfer file"), self.input_itf_path, "ITF (*.itf *.ITF)")[0] file_info = QFileInfo(file_path) self.lineEditInputFile.setText(file_info.absoluteFilePath())
def testInvalidLayer(self): layer = QgsRasterLayer('blah', 'blah') self.assertTrue(layer) self.assertFalse(layer.isValid()) combo = QgsRasterBandComboBox() combo.setLayer(layer) self.assertEqual(combo.count(), 0) self.assertTrue(combo.isEditable()) signal_spy = QSignalSpy(combo.bandChanged) combo.setBand(11111) self.assertEqual(len(signal_spy), 1) self.assertEqual(signal_spy[-1][0], 11111) self.assertEqual(combo.currentBand(), 11111) combo.setBand(-11111) self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 2) self.assertEqual(signal_spy[-1][0], -1) # replace with valid layer path = os.path.join(unitTestDataPath('raster'), 'band3_float32_noct_epsg4326.tif') info = QFileInfo(path) base_name = info.baseName() layer2 = QgsRasterLayer(path, base_name) self.assertTrue(layer2.isValid()) combo.setBand(2) self.assertEqual(combo.currentBand(), 2) self.assertEqual(len(signal_spy), 3) self.assertEqual(signal_spy[-1][0], 2) combo.setLayer(layer2) self.assertEqual(combo.count(), 3) self.assertFalse(combo.isEditable()) self.assertEqual(combo.currentBand(), 2) self.assertEqual(len(signal_spy), 3) # back to invalid combo.setLayer(layer) self.assertEqual(combo.count(), 0) self.assertTrue(combo.isEditable()) self.assertEqual(combo.currentBand(), 2) self.assertEqual(len(signal_spy), 3) # with not set option combo.setShowNotSetOption(True) combo.setBand(-1) self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 4) self.assertEqual(signal_spy[-1][0], -1) combo.setBand(3) self.assertEqual(combo.currentBand(), 3) self.assertEqual(len(signal_spy), 5) self.assertEqual(signal_spy[-1][0], 3) combo.setBand(-1) self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 6) self.assertEqual(signal_spy[-1][0], -1) combo.setLayer(layer2) self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 6) combo.setLayer(layer) combo.setCurrentText('bad') self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 6) self.assertEqual(signal_spy[-1][0], -1) combo.setCurrentText('5') self.assertEqual(combo.currentBand(), 5) self.assertEqual(len(signal_spy), 7) self.assertEqual(signal_spy[-1][0], 5) combo.setCurrentText('6.5') self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 8) self.assertEqual(signal_spy[-1][0], -1) combo.setCurrentText('5') self.assertEqual(combo.currentBand(), 5) self.assertEqual(len(signal_spy), 9) self.assertEqual(signal_spy[-1][0], 5) combo.setCurrentText('Not set') self.assertEqual(combo.currentBand(), -1) self.assertEqual(len(signal_spy), 10) self.assertEqual(signal_spy[-1][0], -1)
def do_aeag_menu(self, fileName, who, menu=None, visible=None, expanded=None): self.canvas.freeze(True) self.canvas.setRenderFlag(False) group = None theLayer = None groupName = None QgsApplication.setOverrideCursor(Qt.WaitCursor) try: if (type(menu.parentWidget()) == QMenu or type(menu.parentWidget()) == QWidget) and self.optionCreateGroup: groupName = menu.title().replace("&", "") group = QgsProject.instance().layerTreeRoot().findGroup( groupName) if group is None: group = QgsProject.instance().layerTreeRoot().addGroup( groupName) # load all layers if fileName is None and who is None and self.optionLoadAll: for action in menu.actions(): if ((action.text() != self.tr("&Load all")) and (action.text() != "Load all")): action.trigger() else: # read QGis project doc = QtXml.QDomDocument() xml = QFile(fileName) if xml.open(QIODevice.ReadOnly | QIODevice.Text): doc.setContent(xml) # is project in relative path ? absolute = self.isAbsolute(doc) node = getFirstChildByTagNameValue(doc.documentElement(), "maplayer", "id", who) if node: idNode = node.namedItem("id") layerType = node.toElement().attribute("type", "vector") # give it a new id (for multiple import) import re newLayerId = "L%s" % re.sub("[{}-]", "", QUuid.createUuid().toString()) try: idNode.firstChild().toText().setData(newLayerId) except: 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 == "ogr" and (ds.find(".") == 0): projectpath = QFileInfo( os.path.realpath(fileName)).path() newlayerpath = projectpath + "/" + ds datasourceNode.firstChild().toText().setData( newlayerpath) except: pass # read modified layer node if self.optionCreateGroup and group is not None: """# sol 1 bug : layer incomplete # because of API strange behaviour, we clone the layer... theLayer = QgsProject.instance().mapLayer(newLayerId) cloneLayer = theLayer.clone() # removing the first QgsProject.instance().removeMapLayer(newLayerId) # adding the clone... treeNode = group.addLayer(cloneLayer) treeNode.setExpanded(expanded) treeNode.setItemVisibilityChecked(visible)""" # solution 2, ok ! if layerType == "raster": theLayer = QgsRasterLayer() else: theLayer = QgsVectorLayer() theLayer.readLayerXml(node.toElement(), QgsReadWriteContext()) # needed QgsProject.instance().addMapLayer(theLayer, False) # add to group treeNode = group.addLayer(theLayer) treeNode.setExpanded(expanded) treeNode.setItemVisibilityChecked(visible) else: # create layer QgsProject.instance().readLayer(node) except Exception as e: QgsMessageLog.logMessage( 'Menu from layer: Invalid ' + (fileName if fileName is not None else ""), 'Extensions') for m in e.args: QgsMessageLog.logMessage(m, 'Extensions') self.canvas.freeze(False) self.canvas.setRenderFlag(True) self.canvas.refresh() QgsApplication.restoreOverrideCursor()
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("%s[%s]" % (fct, locale)) if value: return value value = metadataParser("%s[%s]" % (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 = "%s - %s" % (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 saveProject(name): project = QgsProject.instance() project.write(QFileInfo(root + name + '.qgs')) return
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://%s/%s" % (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:") + " %d %s" % ( 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()
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 on_btnBrowseProjectsRootDir_clicked(self): dir_path = QFileDialog.getExistingDirectory(self, tr( "Choose projects root directory"), self.projects_root_directory) dir_info = QFileInfo(dir_path) self.lineEditProjectsRootDir.setText(dir_info.absoluteFilePath())
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"
class DocumentWidget(WIDGET, BASE): """ Widget for displaying source document details """ # Reference removed signal is raised prior # to destroying the widget. referencesRemoved = pyqtSignal(int) fileUploadComplete = pyqtSignal() def __init__( self, document_model=None, fileManager=None, mode=UPLOAD_MODE, parent=None, canRemove=True, view_manager=None ): QWidget.__init__(self, parent) self.setupUi(self) self.lblClose.setPixmap(GuiUtils.get_icon_pixmap('close.png')) self.initGui() self.fileInfo = None self.fileUUID = None self.document_model = document_model self.fileManager = fileManager self._mode = mode self._displayName = "" self._docSize = 0 self._srcDoc = None self._fileName = "" self._canRemove = canRemove self._view_manager = view_manager self.curr_profile = current_profile() self.removed_doc = [] self.lblClose.installEventFilter(self) self.lblName.installEventFilter(self) self._source_entity = "" self._doc_type = "" self._doc_type_id = None # Set defaults self.fileNameColor = "#5555ff" self.fileMetaColor = "#8f8f8f" def eventFilter(self, watched, e): """ Capture label mouse release events for deleting and opening a source document respectively. """ if QEvent is None: return False if watched == self.lblClose and e.type() == QEvent.MouseButtonRelease: self.removeDocument() return True elif watched == self.lblName and e.type() == QEvent.MouseButtonRelease: self.openDocument() return True else: return QWidget.eventFilter(self, watched, e) def initGui(self): """ Initialize GUI """ self.lblName.clear() self.pgBar.setVisible(False) self.pgBar.setValue(0) def mode(self): """ Returns the mode that the widget is configured to run. Returns either UPLOAD_MODE or DOWNLOAD_MODE. """ return self._mode def view_manager(self): """ Manager for viewing the document contents. """ return self._view_manager def removeDocument(self): """ Destroy the document widget and removes file references in the network drive and corresponding database record. """ msgConfirm = QApplication.translate("DocumentWidget", """Are you sure you want to delete this document? This action cannot be undone. \nClick Yes to proceed or No to cancel.""") response = QMessageBox.warning(self.parent(), QApplication.translate("DocumentWidget", "Delete Source Document"), msgConfirm, QMessageBox.Yes | QMessageBox.No) if response == QMessageBox.No: return self._remove_doc() def clean_up(self): """ Remove the referenced uploaded file which has not yet been saved. :return: True to indicate that the document was successfully removed or False if an error was encountered. :rtype: bool """ if self._mode == UPLOAD_MODE: return self._remove_doc(True) return True def _remove_doc(self, suppress_messages=False): """ :param suppress_messages: Set whether user messages should be displayed or the system should continue with execution. :type suppress_messages: bool :return: True to indicate that the document was successfully removed or False if an error was encountered. :rtype: bool """ status = True if self._mode == UPLOAD_MODE: status = self.fileManager.deleteDocument() else: doc_type = self.doc_type_value() self.removed_doc.append(self._srcDoc) # Before anything, we check if file exist! if self.fileManager.file_exist(self._srcDoc, doc_type): status = self.fileManager.deleteDocument(self._srcDoc, doc_type) if not status: if not suppress_messages: msg = QApplication.translate("DocumentWidget", "The system could not delete the document. Please " "check your document repository settings.") QMessageBox.critical(self.parent(), QApplication.translate("DocumentWidget", "Delete Source Document"), msg) return False if self._mode == DOWNLOAD_MODE: # Try to delete document and suppress error if it does not exist try: self._srcDoc.delete() # Remove the same document from supporting # doc table linked to other str record as the file doesn't exist. doc_obj = self.document_model() other_party_doc = doc_obj.queryObject().filter( self.document_model.document_identifier == self._srcDoc.document_identifier ).all() for docs in other_party_doc: self.removed_doc.append(docs) docs.delete() except sqlalchemy.exc.SQLAlchemyError as exc: LOGGER.debug(str(exc)) # Emit signal to indicate the widget is ready to be removed self.referencesRemoved.emit(self._doc_type_id) self.deleteLater() return True def openDocument(self): """ Open the document referenced by this widget. """ if not self._view_manager is None: self._view_manager.load_viewer(self) def setCanRemoveDocument(self, state): """ Disable the close button so that users are not able to remove the document from the list. """ self.lblClose.setVisible(state) def setFile(self, dfile, source_entity, doc_type, doc_type_id): """ Set the absolute file path including the name, that is to be associated with the document widget. """ if self._mode == UPLOAD_MODE: self.fileInfo = QFileInfo(dfile) self._displayName = str(self.fileInfo.fileName()) self._docSize = self.fileInfo.size() self._source_entity = source_entity self._doc_type = doc_type self._doc_type_id = doc_type_id self.uploadDoc() self.buildDisplay() def setModel(self, sourcedoc): """ Set the SourceDocument model that is to be associated with the widget. Only valid if the widget mode is in DOWNLOAD_MODE. """ self.pgBar.setVisible(False) if self._mode == DOWNLOAD_MODE: self._displayName = sourcedoc.filename self._docSize = sourcedoc.document_size self.fileUUID = sourcedoc.document_identifier self._srcDoc = sourcedoc self._source_entity = sourcedoc.source_entity self._doc_type_id = sourcedoc.document_type self.buildDisplay() def doc_type_value(self): """ Returns the document type value. :return: the document type value in which a document is uploaded. :type: String :rtype: String """ entity = self.curr_profile.entity_by_name(self._source_entity) doc_type_entity = entity.supporting_doc.document_type_entity self._doc_type = entity_id_to_attr( doc_type_entity, 'value', self._doc_type_id ) return self._doc_type def doc_source_entity(self): """ Returns the document type (enumeration) that the widget currently references. """ return self._source_entity def set_source_entity(self, source_entity): """ Set the document type using its code. See enumeration options. """ self._source_entity = source_entity def displayName(self): """ Returns the original file name of the supporting document. """ return self._displayName def file_identifier(self): """ Returns the unique identifier of the file generated by the system upon uploading. """ return self.fileUUID def sourceDocument(self, doc_type_id): """ Builds the database model for the source document file reference. """ if self._mode == UPLOAD_MODE: entity_doc_obj = self.document_model() entity_doc_obj.document_identifier = self.fileUUID entity_doc_obj.filename = self.fileInfo.fileName() entity_doc_obj.document_size = self._docSize entity_doc_obj.creation_date = datetime.now() entity_doc_obj.source_entity = self._source_entity entity_doc_obj.document_type = doc_type_id self._srcDoc = entity_doc_obj return self._srcDoc def set_thumbnail(self): """ Sets thumbnail to the document widget by cropping if necessary. :return: None :rtype: NoneType """ extension = self._displayName[self._displayName.rfind('.'):] QApplication.processEvents() doc_path = '{}/{}/{}/{}/{}{}'.format( source_document_location(), str(self.curr_profile.name), str(self._source_entity), str(self.doc_type_value()).replace(' ', '_'), str(self.fileUUID), str(extension) ).lower() ph_image = QImage(doc_path) ph_pixmap = QPixmap.fromImage(ph_image) # If width is larger than height, use height as width and height if ph_pixmap.width() > ph_pixmap.height(): rectangle = QRect(0, 0, ph_pixmap.height(), ph_pixmap.height()) ph_pixmap = ph_pixmap.copy(rectangle) # If height is larger than width, use width as width and height elif ph_pixmap.height() > ph_pixmap.width(): rectangle = QRect(0, 0, ph_pixmap.width(), ph_pixmap.width()) ph_pixmap = ph_pixmap.copy(rectangle) self.lblThumbnail.setPixmap(ph_pixmap) self.lblThumbnail.setScaledContents(True) def buildDisplay(self): """ Build html text for displaying file information. """ if not self._docSize is None: display_doc_size = str(size(self._docSize)) else: display_doc_size = '0' html = '<html>' \ '<head/>' \ '<body>' \ '<p>' \ '<span ' \ 'style="font-weight:600;' \ 'text-decoration: underline;' \ 'color:#5555ff;"' \ '>' \ '{}</span>' \ '<span ' \ 'style="font-weight:600;' \ 'color:#8f8f8f;"' \ '> ({})' \ '</span>' \ '</p>' \ '</body>' \ '</html>'.format( str(self._displayName), display_doc_size ) self.lblName.setText(html) # Enable/disable close self.setCanRemoveDocument(self._canRemove) # Disable link if no view manager has been configured if self._view_manager is None: self.lblName.setEnabled(False) self.set_thumbnail() def uploadDoc(self): """ Upload the file to the central repository in a separate thread using the specified file manager """ if isinstance(self.fileManager, NetworkFileManager): self.pgBar.setVisible(True) self._docSize = self.fileInfo.size() ''' Create document transfer helper for multi-threading capabilities. Use of queued connections will guarantee that signals and slots are captured in any thread. ''' workerThread = QThread(self) docWorker = DocumentTransferWorker( self.fileManager, self.fileInfo, "%s" % (self._source_entity), "%s" % (self._doc_type), self ) docWorker.moveToThread(workerThread) workerThread.started.connect(docWorker.transfer) docWorker.blockWrite.connect(self.onBlockWritten) docWorker.complete.connect(self.onCompleteTransfer) workerThread.finished.connect(docWorker.deleteLater) workerThread.finished.connect(workerThread.deleteLater) workerThread.start() # Call transfer() to get fileUUID early # docWorker.transfer() self.fileUUID = docWorker.file_uuid def onBlockWritten(self, size): """ Raised when a block of data is written to the central repository. Updates the progress bar with the bytes transferred as a percentage. """ progress = (size * 100) / self._docSize self.pgBar.setValue(progress) QApplication.processEvents() def onCompleteTransfer(self, fileid): """ Slot raised when file has been successfully transferred. """ self.pgBar.setVisible(False) self.fileUUID = str(fileid) self.fileUploadComplete.emit()