def removeDir(path): result = "" if not QFile(path).exists(): result = QCoreApplication.translate( "QgsPluginInstaller", "Nothing to remove! Plugin directory doesn't exist:") + "\n" + path elif QFile(path).remove( ): # if it is only link, just remove it without resolving. pass else: fltr = QDir.Dirs | QDir.Files | QDir.Hidden iterator = QDirIterator(path, fltr, QDirIterator.Subdirectories) while iterator.hasNext(): item = iterator.next() if QFile(item).remove(): pass fltr = QDir.Dirs | QDir.Hidden iterator = QDirIterator(path, fltr, QDirIterator.Subdirectories) while iterator.hasNext(): item = iterator.next() if QDir().rmpath(item): pass if QFile(path).exists(): result = QCoreApplication.translate( "QgsPluginInstaller", "Failed to remove the directory:" ) + "\n" + path + "\n" + QCoreApplication.translate( "QgsPluginInstaller", "Check permissions or remove it manually") # restore plugin directory if removed by QDir().rmpath() pluginDir = qgis.utils.home_plugin_path if not QDir(pluginDir).exists(): QDir().mkpath(pluginDir) return result
def getRasterFiles(path, recursive=False): rasters = [] if not QFileInfo(path).exists(): return rasters # TODO remove *.aux.xml _filter = getRasterExtensions() workDir = QDir(path) workDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.NoDotAndDotDot) workDir.setNameFilters(_filter) files = workDir.entryList() for f in files: rasters.append(path + "/" + f) if recursive: for myRoot, myDirs, myFiles in os.walk(unicode(path)): for dir in myDirs: workDir = QDir(myRoot + "/" + dir) workDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.NoDotAndDotDot) workDir.setNameFilters(_filter) workFiles = workDir.entryList() for f in workFiles: rasters.append(myRoot + "/" + dir + "/" + f) return rasters
def tempFolder(): tempDir = os.path.join(unicode(QDir.tempPath()), 'processing' + _tempFolderSuffix) if not QDir(tempDir).exists(): QDir().mkpath(tempDir) return unicode(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 cancelled 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 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 + unicode(QDir.separator()) + self.plugin["id"]).remove() try: unzip( unicode(tmpPath), unicode(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(unicode(tmpPath), unicode(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 fillInputDir(self): inputDir = Utils.FileDialog.getExistingDirectory( self, self.tr("Select the input directory with files to Warp")) if not inputDir: return self.inSelector.setFilename(inputDir) filter = Utils.getRasterExtensions() workDir = QDir(inputDir) workDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.NoDotAndDotDot) workDir.setNameFilters(filter) if len(workDir.entryList()) > 0: fl = inputDir + "/" + workDir.entryList()[0] self.sourceSRSEdit.setText(Utils.getRasterSRS(self, fl))
def unload(self): self.toolbox.setVisible(False) self.menu.deleteLater() # delete temporary output files folder = tempFolder() if QDir(folder).exists(): shutil.rmtree(folder, True) self.iface.unregisterMainWindowAction(self.toolboxAction) self.iface.unregisterMainWindowAction(self.modelerAction) self.iface.unregisterMainWindowAction(self.historyAction) self.iface.unregisterMainWindowAction(self.configAction) self.iface.unregisterMainWindowAction(self.resultsAction) self.iface.unregisterMainWindowAction(self.commanderAction) removeMenus()
def setMacOSXDefaultEnvironment(): # fix bug #3170: many GDAL Tools don't work in OS X standalone if platform.system() != "Darwin": return # QgsApplication.prefixPath() contains the path to qgis executable (i.e. .../Qgis.app/MacOS) # get the path to Qgis application folder qgis_app = u"%s/.." % QgsApplication.prefixPath() qgis_app = QDir(qgis_app).absolutePath() qgis_bin = u"%s/bin" % QgsApplication.prefixPath( ) # path to QGis bin folder qgis_python = u"%s/Resources/python" % qgis_app # path to QGis python folder # path to the GDAL framework within the Qgis application folder (QGis standalone only) qgis_standalone_gdal_path = u"%s/Frameworks/GDAL.framework" % qgis_app # path to the GDAL framework when installed as external framework gdal_versionsplit = unicode(GdalConfig.version()).split('.') gdal_base_path = u"/Library/Frameworks/GDAL.framework/Versions/%s.%s" % ( gdal_versionsplit[0], gdal_versionsplit[1]) if os.path.exists(qgis_standalone_gdal_path): # qgis standalone # GDAL executables are in the QGis bin folder if getGdalBinPath() == '': setGdalBinPath(qgis_bin) # GDAL pymods are in the QGis python folder if getGdalPymodPath() == '': setGdalPymodPath(qgis_python) # GDAL help is in the framework folder if getHelpPath() == '': setHelpPath(u"%s/Resources/doc" % qgis_standalone_gdal_path) elif os.path.exists(gdal_base_path): # all GDAL parts are in the GDAL framework folder if getGdalBinPath() == '': setGdalBinPath(u"%s/Programs" % gdal_base_path) if getGdalPymodPath() == '': setGdalPymodPath( u"%s/Python/%s.%s/site-packages" % (gdal_base_path, sys.version_info[0], sys.version_info[1])) if getHelpPath() == '': setHelpPath(u"%s/Resources/doc" % gdal_base_path)
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") myRasterPath = myTempPath + "edge_problem.asc" zs = QgsZonalStatistics(myVector, myRasterPath, "", 1) 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 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 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
def getAllInstalled(self, testLoad=True): """ Build the localCache """ self.localCache = {} # reversed list of the plugin paths: first system plugins -> then user plugins -> finally custom path(s) pluginPaths = list(plugin_paths) pluginPaths.reverse() for pluginsPath in pluginPaths: isTheSystemDir = (pluginPaths.index(pluginsPath) == 0 ) # The curent dir is the system plugins dir if isTheSystemDir: # temporarily add the system path as the first element to force loading the readonly plugins, even if masked by user ones. sys.path = [pluginsPath] + sys.path try: pluginDir = QDir(pluginsPath) pluginDir.setFilter(QDir.AllDirs) for key in pluginDir.entryList(): if key not in [".", ".."]: path = QDir.convertSeparators(pluginsPath + "/" + key) # readOnly = not QFileInfo(pluginsPath).isWritable() # On windows testing the writable status isn't reliable. readOnly = isTheSystemDir # Assume only the system plugins are not writable. # only test those not yet loaded. Loaded plugins already proved they're o.k. # failedToLoad = settings.value("/PythonPlugins/watchDog/" + key) is not None testLoadThis = testLoad and key not in qgis.utils.plugins plugin = self.getInstalledPlugin(key, path=path, readOnly=readOnly, testLoad=testLoadThis) self.localCache[key] = plugin if key in self.localCache.keys() and compareVersions( self.localCache[key]["version_installed"], plugin["version_installed"]) == 1: # An obsolete plugin in the "user" location is masking a newer one in the "system" location! self.obsoletePlugins += [key] except: # it's not necessary to stop if one of the dirs is inaccessible pass if isTheSystemDir: # remove the temporarily added path sys.path.remove(pluginsPath)
def batchRun(self): exts = re.sub('\).*$', '', re.sub('^.*\(', '', self.formatCombo.currentText())).split(" ") if len(exts) > 0 and exts[0] != "*" and exts[0] != "*.*": outExt = exts[0].replace("*", "") else: outExt = ".tif" self.base.enableRun(False) self.base.setCursor(Qt.WaitCursor) inDir = self.getInputFileName() outDir = self.getOutputFileName() extensions = Utils.getRasterExtensions() workDir = QDir(inDir) workDir.setFilter(QDir.Files | QDir.NoSymLinks | QDir.NoDotAndDotDot) workDir.setNameFilters(extensions) files = workDir.entryList() self.inFiles = [] self.outFiles = [] for f in files: self.inFiles.append(inDir + "/" + f) if outDir is not None: outFile = re.sub("\.[a-zA-Z0-9]{2,4}", outExt, f) self.outFiles.append(outDir + "/" + outFile) self.errors = [] self.batchIndex = 0 self.batchTotal = len(self.inFiles) self.setProgressRange(self.batchTotal) self.runItem(self.batchIndex, self.batchTotal)
def defaultOutputFolder(): folder = os.path.join(userFolder(), "outputs") if not QDir(folder).exists(): QDir().mkpath(folder) return unicode(QDir.toNativeSeparators(folder))
def userFolder(): userDir = os.path.join(QgsApplication.qgisSettingsDirPath(), 'processing') if not QDir(userDir).exists(): QDir().mkpath(userDir) return unicode(QDir.toNativeSeparators(userDir))
def getInstalledPlugin(self, key, path, readOnly, testLoad=True): """ 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: cp.readfp(codecs.open(metadataFile, "r", "utf8")) 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(QGis.QGIS_VERSION, qgisMinimumVersion, qgisMaximumVersion): error = "incompatible" errorDetails = "%s - %s" % (qgisMinimumVersion, qgisMaximumVersion) elif testLoad: # only testLoad if compatible version try: pkg = __import__(key) reload(pkg) pkg.classFactory(iface) except Exception as e: error = "broken" errorDetails = unicode(e.args[0]) except SystemExit as e: error = "broken" errorDetails = QCoreApplication.translate( "QgsPluginInstaller", "The plugin exited with error status: {0}").format( e.args[0]) except: error = "broken" errorDetails = QCoreApplication.translate( "QgsPluginInstaller", "Unknown error") 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 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": pluginMetadata("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"], "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 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(testLoad=True) 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 = QSettings() settings.setValue("/PythonPlugins/" + plugin["id"], True) else: settings = QSettings() 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 QgsMessageBar.CRITICAL or QgsMessageBar.INFO msg = "<b>%s:</b>%s" % (infoString[0], infoString[1]) iface.pluginManagerInterface().pushMessage(msg, level)