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 tempFolder(): tempDir = os.path.join(str(QDir.tempPath()), 'processing' + _tempFolderSuffix) if not QDir(tempDir).exists(): QDir().mkpath(tempDir) return str(os.path.abspath(tempDir))
def requestFinished(self): reply = self.sender() self.buttonBox.setEnabled(False) if reply.error() != QNetworkReply.NoError: self.mResult = reply.errorString() if reply.error() == QNetworkReply.OperationCanceledError: self.mResult += "<br/><br/>" + QCoreApplication.translate( "QgsPluginInstaller", "If you haven't canceled the download manually, it might be caused by a timeout. In this case consider increasing the connection timeout value in QGIS options." ) self.reject() reply.deleteLater() return elif reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 301: redirectionUrl = reply.attribute( QNetworkRequest.RedirectionTargetAttribute) self.redirectionCounter += 1 if self.redirectionCounter > 4: self.mResult = QCoreApplication.translate( "QgsPluginInstaller", "Too many redirections") self.reject() reply.deleteLater() return else: if redirectionUrl.isRelative(): redirectionUrl = reply.url().resolved(redirectionUrl) # Fire a new request and exit immediately in order to quietly destroy the old one self.url = redirectionUrl self.requestDownloading() reply.deleteLater() return self.file.open(QFile.WriteOnly) self.file.write(reply.readAll()) self.file.close() self.stateChanged(0) reply.deleteLater() pluginDir = qgis.utils.home_plugin_path tmpPath = self.file.fileName() # make sure that the parent directory exists if not QDir(pluginDir).exists(): QDir().mkpath(pluginDir) # if the target directory already exists as a link, remove the link without resolving: QFile(pluginDir + str(QDir.separator()) + self.plugin["id"]).remove() try: unzip( str(tmpPath), str(pluginDir) ) # test extract. If fails, then exception will be raised and no removing occurs # removing old plugin files if exist removeDir(QDir.cleanPath( pluginDir + "/" + self.plugin["id"])) # remove old plugin if exists unzip(str(tmpPath), str(pluginDir)) # final extract. except: self.mResult = self.tr( "Failed to unzip the plugin package. Probably it's broken or missing from the repository. You may also want to make sure that you have write permission to the plugin directory:" ) + "\n" + pluginDir self.reject() return try: # cleaning: removing the temporary zip file QFile(tmpPath).remove() except: pass self.close()
def _create_plugin_directory(self): """Create the plugin directory using the module name.""" self.plugin_path = os.path.join( str(self.plugin_path), str(self.dialog.module_name.text().lower())) QDir().mkdir(self.plugin_path)
def installPlugin(self, key, quiet=False): """ Install given plugin """ error = False infoString = ('', '') plugin = plugins.all()[key] previousStatus = plugin["status"] if not plugin: return if plugin["status"] == "newer" and not plugin[ "error"]: # ask for confirmation if user downgrades an usable plugin if QMessageBox.warning( iface.mainWindow(), self.tr("QGIS Python Plugin Installer"), self. tr("Are you sure you want to downgrade the plugin to the latest available version? The installed one is newer!" ), QMessageBox.Yes, QMessageBox.No) == QMessageBox.No: return dlg = QgsPluginInstallerInstallingDialog(iface.mainWindow(), plugin) dlg.exec_() if dlg.result(): error = True infoString = (self.tr("Plugin installation failed"), dlg.result()) elif not QDir(qgis.utils.home_plugin_path + "/" + key).exists(): error = True infoString = ( self.tr("Plugin has disappeared"), self. tr("The plugin seems to have been installed but I don't know where. Probably the plugin package contained a wrong named directory.\nPlease search the list of installed plugins. I'm nearly sure you'll find the plugin there, but I just can't determine which of them it is. It also means that I won't be able to determine if this plugin is installed and inform you about available updates. However the plugin may work. Please contact the plugin author and submit this issue." )) QApplication.setOverrideCursor(Qt.WaitCursor) plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() QApplication.restoreOverrideCursor() else: QApplication.setOverrideCursor(Qt.WaitCursor) # update the list of plugins in plugin handling routines updateAvailablePlugins() # try to load the plugin loadPlugin(plugin["id"]) plugins.getAllInstalled() plugins.rebuild() plugin = plugins.all()[key] if not plugin["error"]: if previousStatus in ["not installed", "new"]: infoString = (self.tr("Plugin installed successfully"), "") if startPlugin(plugin["id"]): settings = QgsSettings() settings.setValue("/PythonPlugins/" + plugin["id"], True) else: settings = QgsSettings() if settings.value( "/PythonPlugins/" + key, False, type=bool ): # plugin will be reloaded on the fly only if currently loaded reloadPlugin( key) # unloadPlugin + loadPlugin + startPlugin infoString = ( self.tr("Plugin reinstalled successfully"), "") else: unloadPlugin( key ) # Just for a case. Will exit quietly if really not loaded loadPlugin(key) infoString = ( self.tr("Plugin reinstalled successfully"), self. tr("Python plugin reinstalled.\nYou need to restart QGIS in order to reload it." )) if quiet: infoString = (None, None) QApplication.restoreOverrideCursor() else: QApplication.restoreOverrideCursor() if plugin["error"] == "incompatible": message = self.tr( "The plugin is not compatible with this version of QGIS. It's designed for QGIS versions:" ) message += " <b>" + plugin["error_details"] + "</b>" elif plugin["error"] == "dependent": message = self.tr( "The plugin depends on some components missing on your system. You need to install the following Python module in order to enable it:" ) message += "<b> " + plugin["error_details"] + "</b>" else: message = self.tr("The plugin is broken. Python said:") message += "<br><b>" + plugin["error_details"] + "</b>" dlg = QgsPluginInstallerPluginErrorDialog( iface.mainWindow(), message) dlg.exec_() if dlg.result(): # revert installation pluginDir = qgis.utils.home_plugin_path + "/" + plugin["id"] result = removeDir(pluginDir) if QDir(pluginDir).exists(): error = True infoString = (self.tr("Plugin uninstall failed"), result) try: exec("sys.path_importer_cache.clear()") exec("import %s" % plugin["id"]) exec("reload (%s)" % plugin["id"]) except: pass else: try: exec("del sys.modules[%s]" % plugin["id"]) except: pass plugins.getAllInstalled() plugins.rebuild() self.exportPluginsToManager() if infoString[0]: level = error and Qgis.Critical or Qgis.Info msg = "<b>%s</b>" % infoString[0] if infoString[1]: msg += "<b>:</b> %s" % infoString[1] iface.pluginManagerInterface().pushMessage(msg, level)
def tempFolder(): temp_dir = os.path.join(QDir.tempPath(), meta.PLUGIN_NAMESPACE) if not QDir(temp_dir).exists(): QDir().mkpath(temp_dir) return os.path.abspath(temp_dir)
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 userFolder(): userDir = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing') if not QDir(userDir).exists(): QDir().mkpath(userDir) return str(QDir.toNativeSeparators(userDir))
def accept(self): self.btnOk.setEnabled(False) self.btnCancel.setEnabled(False) project_name = self.project_name_le.text() if project_name.endswith('.qgs'): project_name = project_name[:-4] if not project_name: msg = tr("Please specify the project name") log_msg(msg, level='C', message_bar=iface.messageBar()) self.restoreGui() return outputDir = self.leOutputDir.text() if not outputDir: msg = tr("Please specify the output directory.") log_msg(msg, level='C', message_bar=iface.messageBar()) self.restoreGui() return outputDir = os.path.join(outputDir, get_valid_filename(project_name)) # create main directory if not exists d = QDir(outputDir) if not d.exists(): if not d.mkpath("."): msg = tr("Can't create directory to store the project.") log_msg(msg, level='C', message_bar=iface.messageBar()) self.restoreGui() return # create directory for layers if not exists if d.exists("layers"): res = QMessageBox.question( self, self.tr("Directory exists"), self.tr("Output directory already contains 'layers'" " subdirectory. Maybe this directory was used to" " consolidate another project. Continue?"), QMessageBox.Yes | QMessageBox.No) if res == QMessageBox.No: self.restoreGui() return else: if not d.mkdir("layers"): msg = tr("Can't create directory for layers.") log_msg(msg, level='C', message_bar=iface.messageBar()) self.restoreGui() return # copy project file projectFile = QgsProject.instance().fileName() try: if projectFile: f = QFile(projectFile) newProjectFile = os.path.join(outputDir, '%s.qgs' % project_name) f.copy(newProjectFile) else: newProjectFile = os.path.join(outputDir, '%s.qgs' % project_name) p = QgsProject.instance() p.write(newProjectFile) except Exception as exc: self.restoreGui() log_msg(str(exc), level='C', message_bar=iface.messageBar(), exception=exc) return # start consolidate task that does all real work self.consolidateTask = ConsolidateTask('Consolidation', QgsTask.CanCancel, outputDir, newProjectFile, self.checkBoxZip.isChecked(), self.cb.currentText()) self.consolidateTask.begun.connect(self.on_consolidation_begun) QgsApplication.taskManager().addTask(self.consolidateTask) super().accept()
def uploadDocument(self, entity_source, doc_type, fileinfo): """ Upload document in central repository """ self._entity_source = entity_source self._doc_type = doc_type self.fileID = self.generateFileID() self.sourcePath = str(fileinfo.filePath()) profile_name = self.curr_profile.name root_dir = QDir(self.networkPath) doc_dir = QDir('{}/{}/{}/{}'.format( self.networkPath, profile_name.lower(), self._entity_source, self._doc_type.lower().replace(' ', '_') ) ) doc_path_str = '{}/{}/{}/{}'.format( self.networkPath, profile_name.lower(), self._entity_source, self._doc_type.lower().replace(' ', '_') ).lower() if not doc_dir.exists(): res = root_dir.mkpath(doc_path_str) if res: root_doc_type_path = doc_path_str else: root_doc_type_path = self.networkPath else: root_doc_type_path = doc_path_str self.destinationPath = '{}/{}.{}'.format( root_doc_type_path, self.fileID, fileinfo.completeSuffix() ) srcFile = open(self.sourcePath, 'rb') destinationFile = open(self.destinationPath, 'wb') # srcLen = self.sourceFile.bytesAvailable() totalRead = 0 while True: inbytes = srcFile.read(4096) if not inbytes: break destinationFile.write(inbytes) totalRead += len(inbytes) # Raise signal on each block written self.blockWritten.emit(totalRead) self.completed.emit(self.fileID) srcFile.close() destinationFile.close() return self.fileID
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 tempFolder(): tempDir = os.path.join(unicode(QDir.tempPath()), "geocatbridge") if not QDir(tempDir).exists(): QDir().mkpath(tempDir) return unicode(os.path.abspath(tempDir))
def tempFolder(): tempDir = os.path.join(str(QDir.tempPath()), "profilesplugin") if not QDir(tempDir).exists(): QDir().mkpath(tempDir) return str(os.path.abspath(tempDir))
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 tempFolder(namespace=None): namespace = namespace or _callerName().split(".")[0] tempDir = os.path.join(unicode(QDir.tempPath()), "qgiscommons2", namespace) if not QDir(tempDir).exists(): QDir().mkpath(tempDir) return unicode(os.path.abspath(tempDir))
def tempHelpFolder(): tmp = os.path.join(str(QDir.tempPath()), 'processing_help') if not QDir(tmp).exists(): QDir().mkpath(tmp) return str(os.path.abspath(tmp))
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 defaultOutputFolder(): folder = os.path.join(userFolder(), 'outputs') if not QDir(folder).exists(): QDir().mkpath(folder) return str(QDir.toNativeSeparators(folder))
def tempFolder(): tempDir = os.path.join(QDir.tempPath(), 'qgis2web') if not QDir(tempDir).exists(): QDir().mkpath(tempDir) return os.path.abspath(tempDir)
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() 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 run(self, *args, **kwargs): """ :param templatePath: The file path to the user-defined template. :param entityFieldName: The name of the column for the specified entity which must exist in the data source view or table. :param entityFieldValue: The value for filtering the records in the data source view or table. :param outputMode: Whether the output composition should be an image or PDF. :param filePath: The output file where the composition will be written to. Applies to single mode output generation. :param dataFields: List containing the field names whose values will be used to name the files. This is used in multiple mode configuration. :param fileExtension: The output file format. Used in multiple mode configuration. :param data_source: Name of the data source table or view whose row values will be used to name output files if the options has been specified by the user. """ templatePath = args[0] entityFieldName = args[1] entityFieldValue = args[2] outputMode = args[3] filePath = kwargs.get("filePath", None) dataFields = kwargs.get("dataFields", []) fileExtension = kwargs.get("fileExtension", "") data_source = kwargs.get("data_source", "") templateFile = QFile(templatePath) if not templateFile.open(QIODevice.ReadOnly): return False, QApplication.translate("DocumentGenerator", "Cannot read template file.") templateDoc = QDomDocument() if templateDoc.setContent(templateFile): composerDS = ComposerDataSource.create(templateDoc) spatialFieldsConfig = SpatialFieldsConfiguration.create(templateDoc) composerDS.setSpatialFieldsConfig(spatialFieldsConfig) #Check if data source exists and return if it doesn't if not self.data_source_exists(composerDS): msg = QApplication.translate("DocumentGenerator", "'{0}' data source does not exist in the database." "\nPlease contact your database " "administrator.".format(composerDS.name())) return False, msg #Set file name value formatter self._file_name_value_formatter = EntityValueFormatter( name=data_source ) #Register field names to be used for file naming self._file_name_value_formatter.register_columns(dataFields) #TODO: Need to automatically register custom configuration collections #Photo config collection ph_config_collection = PhotoConfigurationCollection.create(templateDoc) #Table configuration collection table_config_collection = TableConfigurationCollection.create(templateDoc) #Create chart configuration collection object chart_config_collection = ChartConfigurationCollection.create(templateDoc) # Create QR code configuration collection object qrc_config_collection = QRCodeConfigurationCollection.create(templateDoc) #Load the layers required by the table composer items self._table_mem_layers = load_table_layers(table_config_collection) entityFieldName = self.format_entity_field_name(composerDS.name(), data_source) #Execute query dsTable,records = self._exec_query(composerDS.name(), entityFieldName, entityFieldValue) if records is None or len(records) == 0: return False, QApplication.translate("DocumentGenerator", "No matching records in the database") """ Iterate through records where a single file output will be generated for each matching record. """ for rec in records: composition = QgsPrintLayout(self._map_settings) composition.loadFromTemplate(templateDoc) ref_layer = None #Set value of composer items based on the corresponding db values for composerId in composerDS.dataFieldMappings().reverse: #Use composer item id since the uuid is stripped off composerItem = composition.getComposerItemById(composerId) if not composerItem is None: fieldName = composerDS.dataFieldName(composerId) fieldValue = getattr(rec,fieldName) self._composeritem_value_handler(composerItem, fieldValue) # Extract photo information self._extract_photo_info(composition, ph_config_collection, rec) # Set table item values based on configuration information self._set_table_data(composition, table_config_collection, rec) # Refresh non-custom map composer items self._refresh_composer_maps(composition, list(spatialFieldsConfig.spatialFieldsMapping().keys())) # Set use fixed scale to false i.e. relative zoom use_fixed_scale = False # Create memory layers for spatial features and add them to the map for mapId,spfmList in spatialFieldsConfig.spatialFieldsMapping().items(): map_item = composition.getComposerItemById(mapId) if not map_item is None: # Clear any previous map memory layer # self.clear_temporary_map_layers() for spfm in spfmList: #Use the value of the label field to name the layer lbl_field = spfm.labelField() spatial_field = spfm.spatialField() if not spatial_field: continue if lbl_field: if hasattr(rec, spfm.labelField()): layerName = getattr(rec, spfm.labelField()) else: layerName = self._random_feature_layer_name(spatial_field) else: layerName = self._random_feature_layer_name(spatial_field) #Extract the geometry using geoalchemy spatial capabilities geom_value = getattr(rec, spatial_field) if geom_value is None: continue geom_func = geom_value.ST_AsText() geomWKT = self._dbSession.scalar(geom_func) #Get geometry type geom_type, srid = geometryType(composerDS.name(), spatial_field) #Create reference layer with feature ref_layer = self._build_vector_layer(layerName, geom_type, srid) if ref_layer is None or not ref_layer.isValid(): continue # Add feature bbox = self._add_feature_to_layer(ref_layer, geomWKT) zoom_type = spfm.zoom_type # Only scale the extents if zoom type is relative if zoom_type == 'RELATIVE': bbox.scale(spfm.zoomLevel()) #Workaround for zooming to single point extent if ref_layer.wkbType() == QgsWkbTypes.Point: canvas_extent = self._iface.mapCanvas().fullExtent() cnt_pnt = bbox.center() canvas_extent.scale(1.0/32, cnt_pnt) bbox = canvas_extent #Style layer based on the spatial field mapping symbol layer symbol_layer = spfm.symbolLayer() if not symbol_layer is None: ref_layer.rendererV2().symbols()[0].changeSymbolLayer(0,spfm.symbolLayer()) ''' Add layer to map and ensure its always added at the top ''' self.map_registry.addMapLayer(ref_layer) self._iface.mapCanvas().setExtent(bbox) # Set scale if type is FIXED if zoom_type == 'FIXED': self._iface.mapCanvas().zoomScale(spfm.zoomLevel()) use_fixed_scale = True self._iface.mapCanvas().refresh() # Add layer to map memory layer list self._map_memory_layers.append(ref_layer.id()) self._hide_layer(ref_layer) ''' Use root layer tree to get the correct ordering of layers in the legend ''' self._refresh_map_item(map_item, use_fixed_scale) # Extract chart information and generate chart self._generate_charts(composition, chart_config_collection, rec) # Extract QR code information in order to generate QR codes self._generate_qr_codes(composition, qrc_config_collection,rec) #Build output path and generate composition if not filePath is None and len(dataFields) == 0: self._write_output(composition, outputMode, filePath) elif filePath is None and len(dataFields) > 0: entityFieldName = 'id' docFileName = self._build_file_name(data_source, entityFieldName, entityFieldValue, dataFields, fileExtension) # Replace unsupported characters in Windows file naming docFileName = docFileName.replace('/', '_').replace \ ('\\', '_').replace(':', '_').strip('*?"<>|') if not docFileName: return (False, QApplication.translate("DocumentGenerator", "File name could not be generated from the data fields.")) outputDir = self._composer_output_path() if outputDir is None: return (False, QApplication.translate("DocumentGenerator", "System could not read the location of the output directory in the registry.")) qDir = QDir() if not qDir.exists(outputDir): return (False, QApplication.translate("DocumentGenerator", "Output directory does not exist")) absDocPath = "{0}/{1}".format(outputDir, docFileName) self._write_output(composition, outputMode, absDocPath) return True, "Success" return False, "Document composition could not be generated"
def tempFolderInTempFolder(): path = tempFolder() folder = os.path.join(path, uuid.uuid4().hex) if not QDir(folder).exists(): QDir().mkpath(folder) return folder
def exportStyles(layers, folder, clustered, feedback): stylesFolder = os.path.join(folder, "styles") QDir().mkpath(stylesFolder) legendFolder = os.path.join(stylesFolder, "legend") QDir().mkpath(legendFolder) vtStyles = {} mapUnitLayers = [] for count, (layer, cluster) in enumerate(zip(layers, clustered)): sln = safeName(layer.name()) + "_" + str(count) if layer.type() != layer.VectorLayer: continue pattern = "" setPattern = "" vts = layer.customProperty("VectorTilesReader/vector_tile_url") labelText = getLabels(layer, folder, sln) defs = "var size = 0;\nvar placement = 'point';" renderer = layer.renderer() layer_alpha = layer.opacity() try: if isinstance(renderer, QgsSingleSymbolRenderer): (style, pattern, setPattern, value, useMapUnits) = singleSymbol(renderer, stylesFolder, layer_alpha, sln, legendFolder, layer, feedback) elif isinstance(renderer, QgsCategorizedSymbolRenderer): (style, pattern, setPattern, value, defs, useMapUnits) = categorized(defs, sln, layer, renderer, legendFolder, stylesFolder, layer_alpha, feedback) elif isinstance(renderer, QgsGraduatedSymbolRenderer): (style, pattern, setPattern, value, useMapUnits) = graduated(layer, renderer, legendFolder, sln, stylesFolder, layer_alpha, feedback) elif isinstance(renderer, QgsRuleBasedRenderer): (style, pattern, setPattern, value, useMapUnits) = ruleBased(renderer, folder, stylesFolder, layer_alpha, sln, layer, feedback) else: value = "''" style = """ var style = [ new ol.style.Style({ text: createTextStyle(feature, resolution, labelText, labelFont, labelFill, placement, bufferColor, bufferWidth) })];""" useMapUnits = False if useMapUnits: if vts is None: mapUnitLayers.append(sln) else: mapUnitLayers.append(safeName(vts)) (labelRes, size, face, color, bufferColor, bufferWidth) = getLabelFormat(layer) if style != "": geom = TYPE_MAP[layer.wkbType()].replace("Multi", "") style = getStyle(style, cluster, labelRes, labelText, sln, size, face, color, bufferColor, bufferWidth, value, geom) else: style = "''" except Exception: style = "''" feedback.showFeedback("""Exception in layer {} with renderer {}: <span style=\"color: red\">{}</span>""".format( layer.id(), renderer.dump(), traceback.format_exc())) if vts is None: path = os.path.join(stylesFolder, sln + "_style.js") with codecs.open(path, "w", "utf-8") as f: f.write( '''%(defs)s %(pattern)s var style_%(name)s = %(style)s; %(setPattern)s''' % { "defs": defs, "pattern": pattern, "name": sln, "style": style, "setPattern": setPattern }) elif style != "" and style != "''": new_vtStyle = defs new_vtStyle += "if (feature.get('layer') == " new_vtStyle += """'%s' && feature.getGeometry().getType() == '%s'){ return %s(feature, resolution); }""" % (layer.name(), TYPE_MAP[layer.wkbType()].replace("Multi", ""), style) try: old_vtStyles = vtStyles[vts] new_vtStyles = """%s %s""" % (old_vtStyles, new_vtStyle) except Exception: new_vtStyles = new_vtStyle vtStyles[vts] = new_vtStyles for k, v in vtStyles.items(): styleName = safeName(k) styleString = v path = os.path.join(stylesFolder, styleName + "_style.js") with codecs.open(path, "w", "utf-8") as f: f.write( ''' var style_%(name)s = function(feature, resolution) { %(style)s; }''' % { "defs": defs, "pattern": pattern, "name": styleName, "style": styleString, "setPattern": setPattern }) return mapUnitLayers
def testStatistics(self): """Test zonal stats""" TEST_DATA_DIR = unitTestDataPath() + "/zonalstatistics/" myTempPath = QDir.tempPath() + "/" testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRaster = QgsRasterLayer(myTempPath + "edge_problem.asc", "raster", "gdal") zs = QgsZonalStatistics(myVector, myRaster, "", 1, QgsZonalStatistics.All) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.47140452079103201, feat[5])) assert abs(feat[5] - 0.47140452079103201) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(1) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.49690399499995302, feat[5])) assert abs(feat[5] - 0.49690399499995302) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(2) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.372677996249965, feat[5])) assert abs(feat[5] - 0.372677996249965) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage
def insertDocumentFromFile(self, path, doc_type_id, entity, record_count=1): """ Insert a new document into one of the registered containers with the document type id. This document is registered :param path: The local user path of the document :type path: String :param doc_type_id: The entity document type id :type doc_type_id: Integer :param entity: The entity in which the document is inserted into. :type entity: Entity class :param record_count: The number of records for which a document is uploaded. Default is 1. For instance, more records could be used in STR wizard in multi-party. :type record_count: Integer :return: None :rtype: NoneType """ if len(self.containers) > 0: if doc_type_id in self.containers: container = self.containers[doc_type_id] # Check if the file exists if QFile.exists(path): network_location = network_document_path() if not network_location: self._doc_repository_error() return # Check if the directory exists doc_dir = QDir(network_location) if not doc_dir.exists(): msg = QApplication.translate( "sourceDocumentManager", "The root document " "repository '{0}' does " "not exist.\nPlease " "check the path settings." ) parent = self.parent() if not isinstance(parent, QWidget): parent = None QMessageBox.critical( parent, QApplication.translate( "sourceDocumentManager", "Document Manager" ), msg.format(network_location) ) return for i in range(record_count): # Use the default network file manager networkManager = NetworkFileManager( network_location, self.parent() ) # Add document widget docWidg = DocumentWidget( self.document_model, networkManager, parent=self.parent(), view_manager=self._doc_view_manager ) # Connect slot once the document # has been successfully uploaded. docWidg.fileUploadComplete.connect( lambda: self.onFileUploadComplete(doc_type_id) ) self._linkWidgetRemovedSignal(docWidg) doc_type_entity = entity.supporting_doc.document_type_entity doc_type_value = entity_id_to_attr( doc_type_entity, 'value', doc_type_id ) docWidg.setFile( path, entity.name, doc_type_value, doc_type_id ) container.addWidget(docWidg)