def tempFolderInTempFolder(namespace=None): namespace = namespace or _callerName().split(".")[0] path = tempFolder(namespace) folder = os.path.join(path, str(uuid.uuid4()).replace("-", "")) if not QDir(folder).exists(): QDir().mkpath(folder) return folder
def readSettings(settings_path=None): global _settings ''' Reads the settings corresponding to the plugin from where the method is called. This function has to be called in the __init__ method of the plugin class. Settings are stored in a settings.json file in the plugin folder. Here is an eample of such a file: [ {"name":"mysetting", "label": "My setting", "description": "A setting to customize my plugin", "type": "string", "default": "dummy string", "group": "Group 1" "onEdit": "def f():\\n\\tprint "Value edited in settings dialog" "onChange": "def f():\\n\\tprint "New settings value has been saved" }, {"name":"anothersetting", "label": "Another setting", "description": "Another setting to customize my plugin", "type": "number", "default": 0, "group": "Group 2" }, {"name":"achoicesetting", "label": "A choice setting", "description": "A setting to select from a set of possible options", "type": "choice", "default": "option 1", "options":["option 1", "option 2", "option 3"], "group": "Group 2" } ] Available types for settings are: string, bool, number, choice, crs and text (a multiline string) The onEdit property contains a function that will be executed when the user edits the value in the settings dialog. It shouldl return false if, after it has been executed, the setting should not be modified and should recover its original value. The onEdit property contains a function that will be executed when the setting is changed after closing the settings dialog, or programatically by callin the setPluginSetting method Both onEdit and onChange are optional properties ''' namespace = _callerName().split(".")[0] settings_path = settings_path or os.path.join( os.path.dirname(_callerPath()), "settings.json") with open(settings_path) as f: _settings[namespace] = json.load(f)
def setPluginSetting(name, value, namespace=None): ''' Sets the value of a plugin setting. :param name: the name of the setting. It is not the full path, but just the last name of it :param value: the value to set for the plugin setting :param namespace: The namespace. If not passed or None, the namespace will be inferred from the caller method. Normally, this should not be passed, since it suffices to let this function find out the plugin from where it is being called, and it will automatically use the corresponding plugin namespace ''' namespace = namespace or _callerName().split(".")[0] settings.setValue(namespace + "/" + name, value)
def askForFiles(parent, msg=None, isSave=False, allowMultiple=False, exts="*"): ''' Asks for a file or files, opening the corresponding dialog with the last path that was selected when this same function was invoked from the calling method. :param parent: The parent window :param msg: The message to use for the dialog title :param isSave: true if we are asking for file to save :param allowMultiple: True if should allow multiple files to be selected. Ignored if isSave == True :param exts: Extensions to allow in the file dialog. Can be a single string or a list of them. Use "*" to add an option that allows all files to be selected :returns: A string with the selected filepath or an array of them, depending on whether allowMultiple is True of False ''' msg = msg or 'Select file' caller = _callerName().split(".") name = "/".join([LAST_PATH, caller[-1]]) namespace = caller[0] path = pluginSetting(name, namespace) f = None if not isinstance(exts, list): exts = [exts] extString = ";; ".join([ " %s files (*.%s)" % (e.upper(), e) if e != "*" else "All files (*.*)" for e in exts ]) if allowMultiple: ret = QtWidgets.QFileDialog.getOpenFileNames(parent, msg, path, '*.' + extString) if ret: f = ret[0] else: f = ret = None else: if isSave: ret = QtWidgets.QFileDialog.getSaveFileName( parent, msg, path, '*.' + extString) or None if ret is not None and not ret.endswith(exts[0]): ret += "." + exts[0] else: ret = QtWidgets.QFileDialog.getOpenFileName( parent, msg, path, '*.' + extString) or None f = ret if f is not None: setPluginSetting(name, os.path.dirname(f), namespace) return ret
def askForFolder(parent, msg=None): ''' Asks for a folder, opening the corresponding dialog with the last path that was selected when this same function was invoked from the calling method :param parent: The parent window :param msg: The message to use for the dialog title ''' msg = msg or 'Select folder' caller = _callerName().split(".") name = "/".join([LAST_PATH, caller[-1]]) namespace = caller[0] path = pluginSetting(name, namespace) folder = QtWidgets.QFileDialog.getExistingDirectory(parent, msg, path) if folder: setPluginSetting(name, folder, namespace) return folder
def addAboutMenu(menuName, parentMenuFunction=None): ''' Adds an 'about...' menu to the plugin menu. This method should be called from the initGui() method of the plugin :param menuName: The name of the plugin menu in which the about menu is to be added ''' parentMenuFunction = parentMenuFunction or iface.addPluginToMenu namespace = _callerName().split(".")[0] aboutAction = QAction( QgsApplication.getThemeIcon('/mActionHelpContents.svg'), "About...", iface.mainWindow()) aboutAction.setObjectName(namespace + "about") aboutAction.triggered.connect(lambda: openAboutDialog(namespace)) parentMenuFunction(menuName, aboutAction) global _aboutActions _aboutActions[menuName] = aboutAction
def addAboutMenu(menuName, parentMenuFunction=None): ''' Adds an 'about...' menu to the plugin menu. This method should be called from the initGui() method of the plugin :param menuName: The name of the plugin menu in which the about menu is to be added ''' parentMenuFunction = parentMenuFunction or iface.addPluginToMenu namespace = _callerName().split(".")[0] icon = QtGui.QIcon( os.path.join(os.path.dirname(os.path.dirname(__file__)), "icons", "help.png")) aboutAction = QtWidgets.QAction(icon, "About...", iface.mainWindow()) aboutAction.setObjectName(namespace + "about") aboutAction.triggered.connect(lambda: openAboutDialog(namespace)) parentMenuFunction(menuName, aboutAction) global _aboutActions _aboutActions[menuName] = aboutAction
def addSettingsMenu(menuName, parentMenuFunction=None): ''' Adds a 'open settings...' menu to the plugin menu. This method should be called from the initGui() method of the plugin :param menuName: The name of the plugin menu in which the settings menu is to be added :param parentMenuFunction: a function from QgisInterface to indicate where to put the container plugin menu. If not passed, it uses addPluginToMenu ''' parentMenuFunction = parentMenuFunction or iface.addPluginToMenu namespace = _callerName().split(".")[0] settingsAction = QAction( QgsApplication.getThemeIcon('/mActionOptions.svg'), "Plugin Settings...", iface.mainWindow()) settingsAction.setObjectName(namespace + "settings") settingsAction.triggered.connect(lambda: openSettingsDialog(namespace)) parentMenuFunction(menuName, settingsAction) global _settingActions _settingActions[menuName] = settingsAction
def addHelpMenu(menuName, parentMenuFunction=None): ''' Adds a help menu to the plugin menu. This method should be called from the initGui() method of the plugin :param menuName: The name of the plugin menu in which the about menu is to be added. ''' parentMenuFunction = parentMenuFunction or iface.addPluginToMenu namespace = _callerName().split(".")[0] path = "file://{}".format( os.path.join(os.path.dirname(_callerPath()), "docs", "html", "index.html")) helpAction = QAction(QgsApplication.getThemeIcon('/mActionHelpAPI.png'), "Plugin help...", iface.mainWindow()) helpAction.setObjectName(namespace + "help") helpAction.triggered.connect(lambda: openHelp(path)) parentMenuFunction(menuName, helpAction) global _helpActions _helpActions[menuName] = helpAction
def pluginSetting(name, namespace=None, typ=None): ''' Returns the value of a plugin setting. :param name: the name of the setting. It is not the full path, but just the last name of it :param namespace: The namespace. If not passed or None, the namespace will be inferred from the caller method. Normally, this should not be passed, since it suffices to let this function find out the plugin from where it is being called, and it will automatically use the corresponding plugin namespace ''' def _find_in_cache(name, key): for setting in _settings[namespace]: if setting["name"] == name: return setting[key] return None def _type_map(t): """Return setting python type""" if t == BOOL: return bool elif t == NUMBER: return float else: return unicode namespace = namespace or _callerName().split(".")[0] full_name = namespace + "/" + name if settings.contains(full_name): if typ is None: typ = _type_map(_find_in_cache(name, 'type')) v = settings.value(full_name, None, type=typ) try: if isinstance(v, QPyNullVariant): v = None except: pass return v else: return _find_in_cache(name, 'default')
def tempFilename(ext=None, namespace=None): namespace = namespace or _callerName().split(".")[0] ext = "." + ext if ext is not None else "" filename = os.path.join(tempFolder(namespace), str(time.time()) + ext) return filename
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 removeTempFolder(namespace=None): namespace = namespace or _callerName().split(".")[0] shutil.rmtree(tempFolder(namespace))
def pluginSettings(namespace=None): namespace = namespace or _callerName().split(".")[0] return _settings.get(namespace, {})