def execute(self):
     filename = QFileDialog.getOpenFileName(
         self.toolbox,
         self.tr("Open model", "AddModelFromFileAction"),
         None,
         self.tr("Processing model files (*.model *.MODEL)", "AddModelFromFileAction"),
     )
     if filename:
         try:
             ModelerAlgorithm.fromFile(filename)
         except WrongModelException:
             QMessageBox.warning(
                 self.toolbox,
                 self.tr("Error reading model", "AddModelFromFileAction"),
                 self.tr("The selected file does not contain a valid model", "AddModelFromFileAction"),
             )
             return
         except:
             QMessageBox.warning(
                 self.toolbox,
                 self.tr("Error reading model", "AddModelFromFileAction"),
                 self.tr("Cannot read file", "AddModelFromFileAction"),
             )
         destFilename = os.path.join(ModelerUtils.modelsFolder(), os.path.basename(filename))
         shutil.copyfile(filename, destFilename)
         self.toolbox.updateProvider("model")
    def __init__(self, resourceType):
        super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow())
        self.setupUi(self)
        self.manager = QgsNetworkAccessManager.instance()

        repoUrl = ProcessingConfig.getSetting(ProcessingConfig.MODELS_SCRIPTS_REPO)

        self.resourceType = resourceType
        if self.resourceType == self.MODELS:
            self.folder = ModelerUtils.modelsFolders()[0]
            self.urlBase = '{}/models/'.format(repoUrl)
            self.icon = QIcon(os.path.join(pluginPath, 'images', 'model.png'))
        elif self.resourceType == self.SCRIPTS:
            self.folder = ScriptUtils.scriptsFolders()[0]
            self.urlBase = '{}/scripts/'.format(repoUrl)
            self.icon = QIcon(os.path.join(pluginPath, 'images', 'script.png'))
        else:
            self.folder = RUtils.RScriptsFolders()[0]
            self.urlBase = '{}/rscripts/'.format(repoUrl)
            self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.svg'))

        self.lastSelectedItem = None
        self.updateProvider = False
        self.populateTree()
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)
        self.tree.currentItemChanged.connect(self.currentItemChanged)
Exemple #3
0
    def __init__(self, resourceType):
        super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow())
        self.setupUi(self)

        if hasattr(self.leFilter, 'setPlaceholderText'):
            self.leFilter.setPlaceholderText(self.tr('Search...'))

        self.manager = QgsNetworkAccessManager.instance()

        repoUrl = ProcessingConfig.getSetting(ProcessingConfig.MODELS_SCRIPTS_REPO)

        self.resourceType = resourceType
        if self.resourceType == self.MODELS:
            self.folder = ModelerUtils.modelsFolders()[0]
            self.urlBase = '{}/models/'.format(repoUrl)
            self.icon = QgsApplication.getThemeIcon("/processingModel.svg")
        elif self.resourceType == self.SCRIPTS:
            self.folder = ScriptUtils.scriptsFolders()[0]
            self.urlBase = '{}/scripts/'.format(repoUrl)
            self.icon = QgsApplication.getThemeIcon("/processingScript.svg")

        self.lastSelectedItem = None
        self.updateProvider = False
        self.data = None

        self.populateTree()
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)
        self.tree.currentItemChanged.connect(self.currentItemChanged)
        self.leFilter.textChanged.connect(self.fillTree)
Exemple #4
0
    def saveModel(self, saveAs):
        if str(self.textGroup.text()).strip() == '' \
                or str(self.textName.text()).strip() == '':
            QMessageBox.warning(
                self, self.tr('Warning'), self.tr('Please enter group and model names before saving')
            )
            return
        self.model.setName(str(self.textName.text()))
        self.model.setGroup(str(self.textGroup.text()))
        if self.model.sourceFilePath() and not saveAs:
            filename = self.model.sourceFilePath()
        else:
            filename, filter = QFileDialog.getSaveFileName(self,
                                                           self.tr('Save Model'),
                                                           ModelerUtils.modelsFolders()[0],
                                                           self.tr('Processing models (*.model3)'))
            if filename:
                if not filename.endswith('.model3'):
                    filename += '.model3'
                self.model.setSourceFilePath(filename)
        if filename:
            if not self.model.toFile(filename):
                if saveAs:
                    QMessageBox.warning(self, self.tr('I/O error'),
                                        self.tr('Unable to save edits. Reason:\n {0}').format(str(sys.exc_info()[1])))
                else:
                    QMessageBox.warning(self, self.tr("Can't save model"), QCoreApplication.translate('QgsPluginInstallerInstallingDialog', (
                        "This model can't be saved in its original location (probably you do not "
                        "have permission to do it). Please, use the 'Save as…' option."))
                    )
                return
            self.update_model.emit()
            self.bar.pushMessage("", "Model was correctly saved", level=Qgis.Success, duration=5)

            self.hasChanged = False
    def __init__(self, resourceType):
        super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow())
        self.setupUi(self)
        self.manager = QgsNetworkAccessManager.instance()

        self.resourceType = resourceType
        if self.resourceType == self.MODELS:
            self.folder = ModelerUtils.modelsFolder()
            self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/'
            self.icon = QIcon(os.path.join(pluginPath, 'images', 'model.png'))
        elif self.resourceType == self.SCRIPTS:
            self.folder = ScriptUtils.scriptsFolder()
            self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/'
            self.icon = QIcon(os.path.join(pluginPath, 'images', 'script.png'))
        else:
            self.folder = RUtils.RScriptsFolder()
            self.urlBase = 'https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/'
            self.icon = QIcon(os.path.join(pluginPath, 'images', 'r.png'))

        self.lastSelectedItem = None
        self.updateToolbox = False
        self.populateTree()
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)
        self.tree.currentItemChanged.connect(self.currentItemChanged)
Exemple #6
0
    def saveModel(self, saveAs):
        if not self.can_save():
            return
        self.model.setName(str(self.textName.text()))
        self.model.setGroup(str(self.textGroup.text()))
        if self.model.sourceFilePath() and not saveAs:
            filename = self.model.sourceFilePath()
        else:
            filename, filter = QFileDialog.getSaveFileName(self,
                                                           self.tr('Save Model'),
                                                           ModelerUtils.modelsFolders()[0],
                                                           self.tr('Processing models (*.model3 *.MODEL3)'))
            if filename:
                if not filename.endswith('.model3'):
                    filename += '.model3'
                self.model.setSourceFilePath(filename)
        if filename:
            if not self.model.toFile(filename):
                if saveAs:
                    QMessageBox.warning(self, self.tr('I/O error'),
                                        self.tr('Unable to save edits. Reason:\n {0}').format(str(sys.exc_info()[1])))
                else:
                    QMessageBox.warning(self, self.tr("Can't save model"), QCoreApplication.translate('QgsPluginInstallerInstallingDialog', (
                        "This model can't be saved in its original location (probably you do not "
                        "have permission to do it). Please, use the 'Save as…' option."))
                    )
                return
            self.update_model.emit()
            if saveAs:
                self.bar.pushMessage("", self.tr("Model was correctly saved to <a href=\"{}\">{}</a>").format(QUrl.fromLocalFile(filename).toString(), QDir.toNativeSeparators(filename)), level=Qgis.Success, duration=5)
            else:
                self.bar.pushMessage("", self.tr("Model was correctly saved"), level=Qgis.Success, duration=5)

            self.hasChanged = False
 def loadAlgorithms(self):
     self.algs = []
     folders = ModelerUtils.modelsFolders()
     for f in folders:
         self.loadFromFolder(f)
     for a in self.algs:
         self.addAlgorithm(a)
Exemple #8
0
 def openModel(self):
     filename, selected_filter = QFileDialog.getOpenFileName(self,
                                                             self.tr('Open Model'),
                                                             ModelerUtils.modelsFolders()[0],
                                                             self.tr('Processing models (*.model3 *.MODEL3)'))
     if filename:
         self.loadModel(filename)
    def openModel(self):
        filename = unicode(QFileDialog.getOpenFileName(self,
                                                       self.tr('Open Model'), ModelerUtils.modelsFolder(),
                                                       self.tr('Processing models (*.model *.MODEL)')))
        if filename:
            try:
                alg = ModelerAlgorithm.fromFile(filename)
                self.alg = alg
                self.alg.setModelerView(self)
                self.textGroup.setText(alg.group)
                self.textName.setText(alg.name)
                self.repaintModel()

                self.view.centerOn(0, 0)
                self.hasChanged = False
            except WrongModelException as e:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                       self.tr('Could not load model %s\n%s') % (filename, e.msg))
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
            except Exception as e:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                       self.tr('Could not load model %s\n%s') % (filename, e.args[0]))
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
Exemple #10
0
    def openModel(self):
        filename, selected_filter = QFileDialog.getOpenFileName(self,
                                                                self.tr('Open Model'),
                                                                ModelerUtils.modelsFolders()[0],
                                                                self.tr('Processing models (*.model *.MODEL)'))
        if filename:
            try:
                alg = ModelerAlgorithm.fromFile(filename)
                self.alg = alg
                self.alg.setModelerView(self)
                self.textGroup.setText(alg._group)
                self.textName.setText(alg._name)
                self.repaintModel()

                self.view.centerOn(0, 0)
                self.hasChanged = False
            except WrongModelException as e:
                QgsMessageLog.logMessage(self.tr('Could not load model {0}\n{1}').format(filename, e.msg),
                                         self.tr('Processing'),
                                         QgsMessageLog.CRITICAL)
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
            except Exception as e:
                QgsMessageLog.logMessage(self.tr('Could not load model {0}\n{1}').format(filename, e.args[0]),
                                         self.tr('Processing'), QgsMessageLog.CRITICAL)
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
Exemple #11
0
    def __init__(self, resourceType):
        super(GetScriptsAndModelsDialog, self).__init__(iface.mainWindow())
        self.setupUi(self)

        if hasattr(self.leFilter, "setPlaceholderText"):
            self.leFilter.setPlaceholderText(self.tr("Search..."))

        self.manager = QgsNetworkAccessManager.instance()

        self.resourceType = resourceType
        if self.resourceType == self.MODELS:
            self.folder = ModelerUtils.modelsFolders()[0]
            self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/"
            self.icon = QIcon(os.path.join(pluginPath, "images", "model.png"))
        elif self.resourceType == self.SCRIPTS:
            self.folder = ScriptUtils.scriptsFolders()[0]
            self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/"
            self.icon = QIcon(os.path.join(pluginPath, "images", "script.png"))
        else:
            self.folder = RUtils.RScriptsFolders()[0]
            self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/rscripts/"
            self.icon = QIcon(os.path.join(pluginPath, "images", "r.svg"))

        self.lastSelectedItem = None
        self.updateProvider = False
        self.data = None

        self.populateTree()
        self.buttonBox.accepted.connect(self.okPressed)
        self.buttonBox.rejected.connect(self.cancelPressed)
        self.tree.currentItemChanged.connect(self.currentItemChanged)
        self.leFilter.textChanged.connect(self.fillTree)
    def execute(self):
        settings = QSettings()
        lastDir = settings.value('Processing/lastModelsDir', '')
        filename = QFileDialog.getOpenFileName(self.toolbox,
                                               self.tr('Open model', 'AddModelFromFileAction'), lastDir,
                                               self.tr('Processing model files (*.model *.MODEL)', 'AddModelFromFileAction'))
        if filename:
            try:
                settings.setValue('Processing/lastModelsDir',
                                  QFileInfo(filename).absoluteDir().absolutePath())

                ModelerAlgorithm.fromFile(filename)
            except WrongModelException:
                QMessageBox.warning(
                    self.toolbox,
                    self.tr('Error reading model', 'AddModelFromFileAction'),
                    self.tr('The selected file does not contain a valid model', 'AddModelFromFileAction'))
                return
            except:
                QMessageBox.warning(self.toolbox,
                                    self.tr('Error reading model', 'AddModelFromFileAction'),
                                    self.tr('Cannot read file', 'AddModelFromFileAction'))
                return
            destFilename = os.path.join(ModelerUtils.modelsFolder(), os.path.basename(filename))
            shutil.copyfile(filename, destFilename)
            self.toolbox.updateProvider('model')
 def execute(self, progress):
     self.alg = ModelerUtils.getAlgorithm(self.description["algname"]).getCopy()
     for name, value in self.description["parameters"].iteritems():
         self.alg.setParameterValue(name, value)
     for name, value in self.description["outputs"].iteritems():
         self.alg.setOutputValue(name, value)
     self.alg.execute(progress)
     self.outputs = self.alg.outputs
Exemple #14
0
 def checkBeforeOpeningParametersDialog(self):
     for alg in self.algs.values():
         algInstance = ModelerUtils.getAlgorithm(alg.consoleName)
         if algInstance is None:
             return (
                 "The model you are trying to run contains an algorithm that is not available: <i>%s</i>"
                 % alg.consoleName
             )
 def load(self):
     ProcessingConfig.settingIcons[self.name()] = self.icon()
     ProcessingConfig.addSetting(Setting(self.name(),
                                         ModelerUtils.MODELS_FOLDER, self.tr('Models folder', 'ModelerAlgorithmProvider'),
                                         ModelerUtils.defaultModelsFolder(), valuetype=Setting.MULTIPLE_FOLDERS))
     ProviderActions.registerProviderActions(self, self.actions)
     ProviderContextMenuActions.registerProviderContextMenuActions(self.contextMenuActions)
     ProcessingConfig.readSettings()
     self.refreshAlgorithms()
     return True
 def loadAlgorithms(self):
     if self.isLoading:
         return
     self.isLoading = True
     self.algs = []
     folders = ModelerUtils.modelsFolders()
     for f in folders:
         self.loadFromFolder(f)
     for a in self.algs:
         self.addAlgorithm(a)
     self.isLoading = False
 def initializeSettings(self):
     AlgorithmProvider.initializeSettings(self)
     ProcessingConfig.addSetting(
         Setting(
             self.getDescription(),
             ModelerUtils.MODELS_FOLDER,
             self.tr("Models folder", "ModelerAlgorithmProvider"),
             ModelerUtils.defaultModelsFolder(),
             valuetype=Setting.MULTIPLE_FOLDERS,
         )
     )
 def addAlgorithm(self):
     item = self.algorithmTree.currentItem()
     if isinstance(item, TreeAlgorithmItem):
         alg = ModelerUtils.getAlgorithm(item.alg.commandLineName())
         alg = alg.getCopy()#copy.deepcopy(alg)
         
         # create a tab for this algorithm
         stepDialog = StepDialog(alg, self)      
         self.canvasTabWidget.addTab(stepDialog, alg.name)
         
         # add this step to the workflow 
         self.workflow.addStep(alg, stepDialog.getMode(), stepDialog.getInstructions())
Exemple #19
0
 def _dropEvent(event):
     if event.mimeData().hasText():
         text = event.mimeData().text()
         if text in ModelerParameterDefinitionDialog.paramTypes:
             self.addInputOfType(text, event.pos())
         else:
             alg = ModelerUtils.getAlgorithm(text)
             if alg is not None:
                 self._addAlgorithm(alg.getCopy(), event.pos())
         event.accept()
     else:
         event.ignore()
 def execute(self):
     filename = QtGui.QFileDialog.getOpenFileName(self.toolbox, 'model files', None,
             '*.model')
     if filename:
         try:
             model = ModelerAlgorithm()
             model.openModel(filename)
         except WrongModelException:
             QtGui.QMessageBox.warning(self.toolbox, "Error reading model", "The selected file does not contain a valid model")
             return
         destFilename = os.path.join(ModelerUtils.modelsFolder(), os.path.basename(filename))
         shutil.copyfile(filename,destFilename)
         self.toolbox.updateProvider('script')
Exemple #21
0
    def saveModel(self, saveAs):
        if unicode(self.textGroup.text()).strip() == "" or unicode(self.textName.text()).strip() == "":
            QMessageBox.warning(self, self.tr("Warning"), self.tr("Please enter group and model names before saving"))
            return
        self.alg.name = unicode(self.textName.text())
        self.alg.group = unicode(self.textGroup.text())
        if self.alg.descriptionFile is not None and not saveAs:
            filename = self.alg.descriptionFile
        else:
            filename = unicode(
                QFileDialog.getSaveFileName(
                    self,
                    self.tr("Save Model"),
                    ModelerUtils.defaultModelsFolder(),
                    self.tr("Processing models (*.model)"),
                )
            )
            if filename:
                if not filename.endswith(".model"):
                    filename += ".model"
                self.alg.descriptionFile = filename
        if filename:
            text = self.alg.toJson()
            try:
                fout = codecs.open(filename, "w", encoding="utf-8")
            except:
                if saveAs:
                    QMessageBox.warning(
                        self,
                        self.tr("I/O error"),
                        self.tr("Unable to save edits. Reason:\n %s") % unicode(sys.exc_info()[1]),
                    )
                else:
                    QMessageBox.warning(
                        self,
                        self.tr("Can't save model"),
                        self.tr(
                            "This model can't be saved in its "
                            "original location (probably you do not "
                            "have permission to do it). Please, use "
                            "the 'Save as...' option."
                        ),
                    )
                return
            fout.write(text)
            fout.close()
            self.update = True
            QMessageBox.information(self, self.tr("Model saved"), self.tr("Model was correctly saved."))

            self.hasChanged = False
Exemple #22
0
 def __init__(self, resourceType):
     QDialog.__init__(self, iface.mainWindow())
     self.resourceType = resourceType
     if self.resourceType == self.MODELS:
         self.folder = ModelerUtils.modelsFolder()
         self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/models/"
         self.icon = QtGui.QIcon(os.path.dirname(__file__) + '/../images/model.png')
     else:
         self.folder = ScriptUtils.scriptsFolder()
         self.urlBase = "https://raw.githubusercontent.com/qgis/QGIS-Processing/master/scripts/"
         self.icon = QtGui.QIcon(os.path.dirname(__file__) + '/../images/script.png')
     self.lastSelectedItem = None
     self.setupUi(self)
     self.populateTree()
     self.updateToolbox = False
     self.buttonBox.accepted.connect(self.okPressed)
     self.buttonBox.rejected.connect(self.cancelPressed)
     self.tree.currentItemChanged .connect(self.currentItemChanged)
    def __init__(self):
        self.provider = PermaclimAlgorithmProvider()
        return
        settings = QSettings()
        version_settings = settings.value( "/version", '')
        current_version = version()

        if version_settings != current_version:
            settings.setValue("/version", current_version)

            models_src_path = os.path.join(cmd_folder, 'models')
            models_dst_path = ModelerUtils.modelsFolder()

            for name in os.listdir(models_src_path):
                file_src_path = os.path.join(models_src_path, name)
                file_dst_path = os.path.join(models_dst_path, name)
                if os.path.exists(file_dst_path):
                    shutil.move(file_dst_path, file_dst_path+'.old')
                shutil.copy(file_src_path, file_dst_path)
Exemple #24
0
    def saveModel(self, saveAs):
        if str(self.textGroup.text()).strip() == '' \
                or str(self.textName.text()).strip() == '':
            QMessageBox.warning(
                self, self.tr('Warning'), self.tr('Please enter group and model names before saving')
            )
            return
        self.alg.name = str(self.textName.text())
        self.alg.group = str(self.textGroup.text())
        if self.alg.descriptionFile is not None and not saveAs:
            filename = self.alg.descriptionFile
        else:
            filename, filter = QFileDialog.getSaveFileName(self,
                                                           self.tr('Save Model'),
                                                           ModelerUtils.modelsFolders()[0],
                                                           self.tr('Processing models (*.model)'))
            if filename:
                if not filename.endswith('.model'):
                    filename += '.model'
                self.alg.descriptionFile = filename
        if filename:
            text = self.alg.toJson()
            try:
                fout = codecs.open(filename, 'w', encoding='utf-8')
            except:
                if saveAs:
                    QMessageBox.warning(self, self.tr('I/O error'),
                                        self.tr('Unable to save edits. Reason:\n %s') % str(sys.exc_info()[1]))
                else:
                    QMessageBox.warning(self, self.tr("Can't save model"),
                                        self.tr("This model can't be saved in its "
                                                "original location (probably you do not "
                                                "have permission to do it). Please, use "
                                                "the 'Save as...' option."))
                return
            fout.write(text)
            fout.close()
            self.update = True
            QMessageBox.information(self, self.tr('Model saved'),
                                    self.tr('Model was correctly saved.'))

            self.hasChanged = False
    def execute(self):
        settings = QgsSettings()
        lastDir = settings.value('Processing/lastModelsDir', '')
        filename, selected_filter = QFileDialog.getOpenFileName(self.toolbox,
                                                                self.tr('Open Model', 'AddModelFromFileAction'), lastDir,
                                                                self.tr('Processing models (*.model3 *.MODEL3)', 'AddModelFromFileAction'))
        if filename:
            settings.setValue('Processing/lastModelsDir',
                              QFileInfo(filename).absoluteDir().absolutePath())

            alg = QgsProcessingModelAlgorithm()
            if not alg.fromFile(filename):
                QMessageBox.warning(
                    self.toolbox,
                    self.tr('Open Model', 'AddModelFromFileAction'),
                    self.tr('The selected file does not contain a valid model', 'AddModelFromFileAction'))
                return
            destFilename = os.path.join(ModelerUtils.modelsFolders()[0], os.path.basename(filename))
            shutil.copyfile(filename, destFilename)
            QgsApplication.processingRegistry().providerById('model').refreshAlgorithms()
Exemple #26
0
    def openModel(self):
        filename, selected_filter = QFileDialog.getOpenFileName(self,
                                                                self.tr('Open Model'),
                                                                ModelerUtils.modelsFolders()[0],
                                                                self.tr('Processing models (*.model3 *.MODEL3)'))
        if filename:
            alg = QgsProcessingModelAlgorithm()
            if alg.fromFile(filename):
                self.model = alg
                self.model.setProvider(QgsApplication.processingRegistry().providerById('model'))
                self.textGroup.setText(alg.group())
                self.textName.setText(alg.name())
                self.repaintModel()

                self.view.centerOn(0, 0)
                self.hasChanged = False
            else:
                QgsMessageLog.logMessage(self.tr('Could not load model {0}').format(filename),
                                         self.tr('Processing'),
                                         QgsMessageLog.CRITICAL)
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
Exemple #27
0
 def algorithm(self):
     if self._algInstance is None:
         self._algInstance = ModelerUtils.getAlgorithm(self.consoleName).getCopy();
     return self._algInstance
class WorkflowSetupDialog(QDialog, FORM_CLASS):
    __qgisModelPath__ = ModelerUtils.modelsFolders()[0]
    ON_FLAGS_HALT, ON_FLAGS_WARN, ON_FLAGS_IGNORE = range(3)
    onFlagsDisplayNameMap = {
        ON_FLAGS_HALT:
        QCoreApplication.translate('WorkflowSetupDialog', "Halt"),
        ON_FLAGS_WARN:
        QCoreApplication.translate('WorkflowSetupDialog', "Warn"),
        ON_FLAGS_IGNORE:
        QCoreApplication.translate('WorkflowSetupDialog', "Ignore")
    }
    onFlagsValueMap = {
        ON_FLAGS_HALT: "halt",
        ON_FLAGS_WARN: "warn",
        ON_FLAGS_IGNORE: "ignore"
    }
    MODEL_NAME_HEADER, MODEL_SOURCE_HEADER, ON_FLAGS_HEADER, LOAD_OUT_HEADER = range(
        4)

    def __init__(self, parent=None):
        """
        Class constructor.
        :param headerMap: (dict) a map from each header to be shown and type of
                           cell content (e.g. widget or item).
        :param parent: (QtWidgets.*) any widget parent to current instance.
        """
        super(WorkflowSetupDialog, self).__init__(parent)
        self.parent = parent
        self.setupUi(self)
        self.messageBar = QgsMessageBar(self)
        self.orderedTableWidget.setHeaders({
            self.MODEL_NAME_HEADER: {
                "header": self.tr("Model name"),
                "type": "widget",
                "widget": self.modelNameWidget,
                "setter": "setText",
                "getter": "text"
            },
            self.MODEL_SOURCE_HEADER: {
                "header": self.tr("Model source"),
                "type": "widget",
                "widget": self.modelWidget,
                "setter": "setText",
                "getter": "text"
            },
            self.ON_FLAGS_HEADER: {
                "header": self.tr("On flags"),
                "type": "widget",
                "widget": self.onFlagsWidget,
                "setter": "setCurrentIndex",
                "getter": "currentIndex"
            },
            self.LOAD_OUT_HEADER: {
                "header": self.tr("Load output"),
                "type": "widget",
                "widget": self.loadOutputWidget,
                "setter": "setChecked",
                "getter": "isChecked"
            }
        })
        self.orderedTableWidget.setHeaderDoubleClickBehaviour("replicate")

    def resizeTable(self):
        """
        Adjusts table columns sizes.
        """
        dSize = self.orderedTableWidget.geometry().width() - \
                self.orderedTableWidget.horizontalHeader().geometry().width()
        onFlagsColSize = self.orderedTableWidget.sectionSize(2)
        loadOutColSize = self.orderedTableWidget.sectionSize(3)
        missingBarSize = self.geometry().size().width() - dSize\
                         - onFlagsColSize - loadOutColSize
        # the "-11" is empiric: it makes it fit header to table
        self.orderedTableWidget.tableWidget.horizontalHeader().resizeSection(
            0,
            int(0.4 * missingBarSize) - 11)
        self.orderedTableWidget.tableWidget.horizontalHeader().resizeSection(
            1, missingBarSize - int(0.4 * missingBarSize) - 11)

    def resizeEvent(self, e):
        """
        Reimplementation in order to use this window's resize event.
        On this object, this method makes sure that message bar is always the
        same size as the window.
        :param e: (QResizeEvent) resize event.
        """
        self.messageBar.resize(
            QSize(
                self.geometry().size().width(),
                40  # this felt nicer than the original height (30)
            ))
        self.resizeTable()

    def confirmAction(self, msg, showCancel=True):
        """
        Raises a message box for confirmation before executing an action.
        :param msg: (str) message to be exposed.
        :param showCancel: (bool) whether Cancel button should be exposed.
        :return: (bool) whether action was confirmed.
        """
        if showCancel:
            return QMessageBox.question(self, self.tr('Confirm Action'), msg,
                                        QMessageBox.Ok
                                        | QMessageBox.Cancel) == QMessageBox.Ok
        else:
            return QMessageBox.question(self, self.tr('Confirm Action'), msg,
                                        QMessageBox.Ok) == QMessageBox.Ok

    def clear(self):
        """
        Clears all input data from GUI.
        """
        self.authorLineEdit.setText("")
        self.nameLineEdit.setText("")
        self.versionLineEdit.setText("")
        self.orderedTableWidget.clear()

    def modelNameWidget(self, name=None):
        """
        Gets a new instance of model name's setter widget.
        :param name: (str) model name to be filled.
        :return: (QLineEdit) widget for model's name setting.
        """
        # no need to pass parenthood as it will be set to the table when added
        # to a cell
        le = QLineEdit()
        # setPlace"h"older, with a lower case "h"...
        le.setPlaceholderText(self.tr("Set a name for the model..."))
        if name is not None:
            le.setText(name)
        le.setFrame(False)
        return le

    def modelWidget(self, filepath=None):
        """
        Gets a new instance of model settter's widget.
        :parma filepath: (str) path to a model.
        :return: (SelectFileWidget) DSGTools custom file selection widget.
        """
        widget = SelectFileWidget()
        widget.label.hide()
        widget.selectFilePushButton.setText("...")
        widget.selectFilePushButton.setMaximumWidth(32)
        widget.lineEdit.setPlaceholderText(self.tr("Select a model..."))
        widget.lineEdit.setFrame(False)
        widget.setCaption(self.tr("Select a QGIS Processing model file"))
        widget.setFilter(
            self.tr("Select a QGIS Processing model (*.model *.model3)"))
        # defining setter and getter methods for composed widgets into OTW
        widget.setText = widget.lineEdit.setText
        widget.text = widget.lineEdit.text
        if filepath is not None:
            widget.setText(filepath)
        return widget

    def onFlagsWidget(self, option=None):
        """
        Gets a new instance for the widget that sets model's behaviour when
        flags are raised.
        :param option: (str) on flags raised behaviour (non translatable text).
        :return: (QComboBox) model's behaviour selection widget. 
        """
        combo = QComboBox()
        combo.addItems([
            self.onFlagsDisplayNameMap[self.ON_FLAGS_HALT],
            self.onFlagsDisplayNameMap[self.ON_FLAGS_WARN],
            self.onFlagsDisplayNameMap[self.ON_FLAGS_IGNORE]
        ])
        if option is not None:
            optIdx = None
            for idx, txt in self.onFlagsValueMap.items():
                if option == txt:
                    optIdx = idx
                    break
            optIdx = optIdx if optIdx is not None else 0
            combo.setCurrentIndex(optIdx)
        return combo

    def loadOutputWidget(self, option=None):
        """
        Gets a new instance for the widget that sets output layer loading
        definitions.
        :param option: (bool) if output should be loaded.
        :return: (QWidget) widget for output layer loading behaviour
                 definition.
        """
        cb = QCheckBox()
        cb.setStyleSheet("margin:auto;")
        if option is not None:
            cb.setChecked(option)
        return cb

    def now(self):
        """
        Gets time and date from the system. Format: "dd/mm/yyyy HH:MM:SS".
        :return: (str) current's date and time
        """
        paddle = lambda n: str(n) if n > 9 else "0{0}".format(n)
        now = datetime.now()
        return "{day}/{month}/{year} {hour}:{minute}:{second}".format(
            year=now.year,
            month=paddle(now.month),
            day=paddle(now.day),
            hour=paddle(now.hour),
            minute=paddle(now.minute),
            second=paddle(now.second))

    def workflowName(self):
        """
        Reads filled workflow name from GUI.
        :return: (str) workflow's name.
        """
        return self.nameLineEdit.text().strip()

    def setWorkflowName(self, name):
        """
        Sets workflow name to GUI.
        :param name: (str) workflow's name.
        """
        self.nameLineEdit.setText(name)

    def author(self):
        """
        Reads filled workflow name from GUI.
        :return: (str) workflow's author.
        """
        return self.authorLineEdit.text().strip()

    def setWorkflowAuthor(self, author):
        """
        Sets workflow author name to GUI.
        :param author: (str) workflow's author name.
        """
        self.authorLineEdit.setText(author)

    def version(self):
        """
        Reads filled workflow name from GUI.
        :return: (str) workflow's version.
        """
        return self.versionLineEdit.text().strip()

    def setWorkflowVersion(self, version):
        """
        Sets workflow version to GUI.
        :param version: (str) workflow's version.
        """
        self.versionLineEdit.setText(version)

    def modelCount(self):
        """
        Reads the amount of models (rows added) the user intend to use.
        :return: (int) model count.
        """
        return self.orderedTableWidget.rowCount()

    def readRow(self, row):
        """
        Reads a row's contents and set it as a DsgToolsProcessingModel set of
        parameters.
        :return: (dict) parameters map.
        """
        contents = self.orderedTableWidget.row(row)
        filepath = contents[self.MODEL_SOURCE_HEADER].strip()
        onFlagsIdx = contents[self.ON_FLAGS_HEADER]
        name = contents[self.MODEL_NAME_HEADER].strip()
        loadOutput = contents[self.LOAD_OUT_HEADER]
        if not os.path.exists(filepath):
            xml = ""
        else:
            with open(filepath, "r", encoding="utf-8") as f:
                xml = f.read()
        return {
            "displayName": name,
            "flags": {
                "onFlagsRaised": self.onFlagsValueMap[onFlagsIdx],
                "loadOutput": loadOutput
            },
            "source": {
                "type": "xml",
                "data": xml
            },
            "metadata": {
                "originalName": os.path.basename(filepath)
            }
        }

    def setModelToRow(self, row, model):
        """
        Reads model's parameters from model parameters default map.
        :param row: (int) row to have its widgets filled with model's
                    parameters.
        :param model: (DsgToolsProcessingModel) model object.
        """
        # all model files handled by this tool are read/written on QGIS model dir
        data = model.data()
        if model.source() == "file" and os.path.exists(data):
            with open(data, "r", encoding="utf-8") as f:
                xml = f.read()
            originalName = os.path.basename(data)
        elif model.source() == "xml":
            xml = data
            meta = model.metadata()
            originalName = model.originalName() if model.originalName() \
                            else "temp_{0}.model3".format(hash(time()))
        else:
            return False
        path = os.path.join(self.__qgisModelPath__, originalName)
        msg = self.tr(
            "Model '{0}' is already imported would you like to overwrite it?"
        ).format(path)
        if os.path.exists(path) and self.confirmAction(msg):
            os.remove(path)
        if not os.path.exists(path):
            with open(path, "w") as f:
                f.write(xml)
        self.orderedTableWidget.addRow(
            contents={
                self.MODEL_NAME_HEADER: model.displayName(),
                self.MODEL_SOURCE_HEADER: path,
                self.ON_FLAGS_HEADER: {
                    "halt": self.ON_FLAGS_HALT,
                    "warn": self.ON_FLAGS_WARN,
                    "ignore": self.ON_FLAGS_IGNORE
                }[model.onFlagsRaised()],
                self.LOAD_OUT_HEADER: model.loadOutput()
            })
        return True

    def validateRowContents(self, contents):
        """
        Checks if all attributes read from a row are valid.
        :param contents: (dict) map to (already read) row contents.
        :return: (str) invalidation reason
        """
        if contents["displayName"] == "":
            return self.tr("Missing model's name.")
        if contents["source"]["data"] == "":
            return self.tr("Model is empty or file was not found.")
        return ""

    def models(self):
        """
        Reads all table contents and sets it as a DsgToolsProcessingAlgorithm's
        set of parameters.
        :return: (dict) map to each model's set of parameters.
        """
        models = dict()
        for row in range(self.modelCount()):
            contents = self.readRow(row)
            models[contents["displayName"]] = contents
        return models

    def validateModels(self):
        """
        Check if each row on table has a valid input.
        :return: (str) invalidation reason.
        """
        for row in range(self.modelCount()):
            msg = self.validateRowContents(self.readRow(row))
            if msg:
                return "Row {row}: '{error}'".format(row=row + 1, error=msg)
        if len(self.models()) != self.modelCount():
            return self.tr("Check if no model name is repeated.")
        return ""

    def workflowParameterMap(self):
        """
        Generates a Workflow map from input data.
        """
        return {
            "displayName": self.workflowName(),
            "models": self.models(),
            "metadata": {
                "author": self.author(),
                "version": self.version(),
                "lastModified": self.now()
            }
        }

    def currentWorkflow(self):
        """
        Returns current workflow object as read from GUI.
        :return: (QualityAssuranceWorkflow) current workflow object.
        """
        try:
            return QualityAssuranceWorkflow(self.workflowParameterMap())
        except:
            return None

    def validate(self):
        """
        Checks if all filled data generates a valid Workflow object.
        :return: (bool) validation status.
        """
        if self.workflowName() == "":
            return self.tr("Workflow's name needs to be filled.")
        if self.author() == "":
            return self.tr("Workflow's author needs to be filled.")
        if self.version() == "":
            return self.tr("Workflow's version needs to be filled.")
        msg = self.validateModels()
        if msg != "":
            return msg
        return ""

    def exportWorkflow(self, filepath):
        """
        Exports current data to a JSON file.
        :param filepath: (str) output file directory.
        """
        QualityAssuranceWorkflow(self.workflowParameterMap()).export(filepath)

    @pyqtSlot(bool, name="on_exportPushButton_clicked")
    def export(self):
        """
        Exports current input data as a workflow JSON, IF input is valid.
        :return: (bool) operation success.
        """
        msg = self.validate()
        if msg != "":
            self.messageBar.pushMessage(self.tr('Invalid workflow'),
                                        msg,
                                        level=Qgis.Warning,
                                        duration=5)
            return False
        fd = QFileDialog()
        filename = fd.getSaveFileName(
            caption=self.tr("Export DSGTools Workflow"),
            filter=self.tr("DSGTools Workflow (*.workflow)"))
        filename = filename[0] if isinstance(filename, tuple) else ""
        if filename == "":
            return False
        filename = filename if filename.lower().endswith(".workflow") \
                    else "{0}.workflow".format(filename)
        try:
            self.exportWorkflow(filename)
        except Exception as e:
            self.messageBar.pushMessage(
                self.tr('Invalid workflow'),
                self.tr(
                    "Unable to export workflow to '{fp}' ({error}).").format(
                        fp=filename, error=str(e)),
                level=Qgis.Warning,
                duration=5)
            return False
        result = os.path.exists(filename)
        msg = (self.tr("Workflow exported to {fp}") if result else \
                self.tr("Unable to export workflow to '{fp}'")).format(fp=filename)
        lvl = Qgis.Success if result else Qgis.Warning
        self.messageBar.pushMessage(self.tr('Workflow exportation'),
                                    msg,
                                    level=lvl,
                                    duration=5)
        return result

    def importWorkflow(self, filepath):
        """
        Sets workflow contents from an imported DSGTools Workflow dump file.
        :param filepath: (str) workflow file to be imported.
        """
        with open(filepath, "r", encoding="utf-8") as f:
            xml = json.load(f)
        workflow = QualityAssuranceWorkflow(xml)
        self.clear()
        self.setWorkflowAuthor(workflow.author())
        self.setWorkflowVersion(workflow.version())
        self.setWorkflowName(workflow.displayName())
        for row, modelParam in enumerate(xml["models"].values()):
            self.setModelToRow(row, DsgToolsProcessingModel(modelParam, ""))

    @pyqtSlot(bool, name="on_importPushButton_clicked")
    def import_(self):
        """
        Request a file for Workflow importation and sets it to GUI.
        :return: (bool) operation status.
        """
        fd = QFileDialog()
        filename = fd.getOpenFileName(
            caption=self.tr('Select a Workflow file'),
            filter=self.tr('DSGTools Workflow (*.workflow *.json)'))
        filename = filename[0] if isinstance(filename, tuple) else ""
        if not filename:
            return False
        try:
            self.importWorkflow(filename)
        except Exception as e:
            self.messageBar.pushMessage(
                self.tr('Invalid workflow'),
                self.tr(
                    "Unable to export workflow to '{fp}' ({error}).").format(
                        fp=filename, error=str(e)),
                level=Qgis.Critical,
                duration=5)
            return False
        self.messageBar.pushMessage(
            self.tr('Success'),
            self.tr("Workflow '{fp}' imported!").format(fp=filename),
            level=Qgis.Info,
            duration=5)
        return True

    @pyqtSlot(bool, name="on_okPushButton_clicked")
    def ok(self):
        """
        Closes dialog and checks if current workflow is valid.
        """
        msg = self.validate()
        if msg == "" and self.currentWorkflow():
            self.done(1)
        else:
            self.messageBar.pushMessage(self.tr('Invalid workflow'),
                                        self.validate(),
                                        level=Qgis.Warning,
                                        duration=5)

    @pyqtSlot(bool, name="on_cancelPushButton_clicked")
    def cancel(self):
        """
        Restores GUI to last state and closes it.
        """
        self.done(0)
 def modelsFolder(self):
     return ModelerUtils.modelsFolders()[0]
 def modelsFolder(self):
     return ModelerUtils.modelsFolders()[0]
Exemple #31
0
 def _loadAlgorithms(self):
     folder = ModelerUtils.modelsFolder()
     self.loadFromFolder(folder)
 def initializeSettings(self):
     AlgorithmProvider.initializeSettings(self)
     ProcessingConfig.addSetting(
         Setting(self.getDescription(), ModelerUtils.MODELS_FOLDER,
                 'Models folder', ModelerUtils.modelsFolder()))
Exemple #33
0
class DataValidationTool(QWidget, FORM_CLASS):
    """
    Toolbar for fast usage of processing methods. It is assumed that the models
    have all of its child algorithm's variable's well defined and the only 
    variables expected on input are the output layers, whenever needed and as 
    many as it may be. 
    """
    __dsgToolsModelPath__ = os.path.join(
        os.path.dirname(__file__), "..", "..", "..", "..", "core", "Misc", "QGIS_Models"
    )
    __qgisModelPath__ = ModelerUtils.modelsFolders()[0]
    modelAdded = pyqtSignal(str)
    modelRemoved = pyqtSignal(str)

    def __init__(self, iface, parent=None):
        """
        Class constructor.
        :param iface: A QGIS interface instance.
        :param parent: (QtWidgets) widget parent to new instance of DataValidationTool.
        """
        super(DataValidationTool, self).__init__(parent)
        self.parent = parent
        self.setupUi(self)
        self.iface = iface
        self.dsgToolsOptions = Options(self)
        # self.dsgToolsOptions.modelPathChanged.connect(self.resetModelList)
        self.activateTool()
        self.addShortcut()
        self.resetModelList()
        self._feedback = QgsProcessingFeedback()
        self._context = QgsProcessingContext()
        self._newModels = []

    def _widgets(self):
        """
        Gets a list of all [important] widgets.
        :return: (list-of-QtWidgets) all widgets this object parents.
        """
        return [
            self.validationPushButton,
            self.modelComboBox,
            self.addModelPushButton,
            self.removeModelPushButton,
            self.runModelPushButton,
            self.splitter
        ]

    def options(self):
        """
        Reads tool parameters.
        :return: (dict) map of parameters for Validation Toolbar.
        """
        return self.dsgToolsOptions.validationToolbarConfig()

    def model(self, idx=None):
        """
        Gets current model name or the model from an index.
        :param idx: (int) order in model combo box.
        :return: (str) model name.
        """
        if idx is not None and (self.modelComboBox.count() < idx or idx < 1):
            return ""
        return self.modelComboBox.currentText()

    def modelPath(self, idx=None):
        """
        Gets a model's path from its index.
        :param idx: (int) order in model combo box.
        :return: (str) model path.
        """
        model = self.model(idx)
        return os.path.join(self.defaultModelPath(), model) if model else ""

    def defaultModelPath(self):
        """
        Gets the directory used to read and save the models shown on toolbar.
        :return: (str) default models path.
        """
        return self.options()["defaultModelPath"]

    def resetModelList(self):
        """
        Clear models listed and look refill it with current models.
        """
        self.modelComboBox.clear()
        self.modelComboBox.addItem(self.tr("Select a model..."))
        models = []
        for file_ in os.listdir(self.defaultModelPath()):
            if file_.endswith('.model') or file_.endswith('.model3'):
                models.append(file_)
        if models:
            self.modelComboBox.addItems(models)

    @pyqtSlot(bool, name='on_validationPushButton_toggled')
    def activateTool(self, toggled=None):
        """
        Shows/hides the toolbar.
        :param toggled: (bool) toolbar status.
        """
        if toggled is None:
            toggled = self.validationPushButton.isChecked()
        if toggled:
            self.splitter.show()
        else:
            self.splitter.hide()

    def confirmAction(self, msg, showCancel=True):
        """
        Raises a message box for confirmation before executing an action.
        :param msg: (str) message to be exposed.
        :param showCancel: (bool) whether Cancel button should be exposed.
        :return: (bool) whether action was confirmed.
        """
        if showCancel:
            return QMessageBox.question(
                self, self.tr('Confirm Action'), msg,
                QMessageBox.Ok|QMessageBox.Cancel
            ) == QMessageBox.Ok
        else:
            return QMessageBox.question(
                self, self.tr('Confirm Action'), msg,
                QMessageBox.Ok
            ) == QMessageBox.Ok

    def modelExists(self, modelName):
        """
        Checks if model from modelPath exists (by name).
        :param modelName: (str) model name to be checked if exists.
        :return: (str) whether model exists into default directory.
        """
        return os.path.exists(
            os.path.join(self.defaultModelPath(), os.path.basename(modelName))
        )

    def setActiveModel(self, modelName):
        """
        Sets a model as current selected, if found on default directory.
        :param modelName: (str) model name to be set as active.
        :return: (bool) whether model was set.
        """
        idx = self.modelComboBox.findText(modelName)
        if idx >= 0:
            self.modelComboBox.setCurrentIndex(idx)
            return True
        return False

    @pyqtSlot(int, name='on_modelComboBox_currentIndexChanged')
    def modelIsValid(self, idx):
        """
        Checks if a model is valid and sets GUI buttons enabled if so.
        :param idx: (int) index for the model to be checked.
        """
        enabled = idx > 0
        self.removeModelPushButton.setEnabled(enabled)
        self.runModelPushButton.setEnabled(enabled)
        return enabled

    def addLayerToGroup(self, layer, groupname, subgroupname=None):
        """
        Adds a layer to a group into layer panel.
        :param layer: (QgsMapLayer) layer to be added to canvas.
        :param groupname: (str) name for group to nest the layer.
        :param subgroupname: (str) name for the subgroup to be added.
        """
        root = QgsProject.instance().layerTreeRoot()
        for g in root.children():
            if g.name() == groupname:
                group = g
                break
        else:
            group = root.addGroup(groupname)
        if subgroupname is not None:
            for sg in group.children():
                if sg.name() == subgroupname:
                    subgroup = sg
                    break
            else:
                subgroup = group.addGroup(subgroupname)
        QgsProject.instance().addMapLayer(layer, False)
        subgroup.insertChildNode(1, QgsLayerTreeLayer(layer))

    @pyqtSlot(bool, name='on_updatePushButton_clicked')
    def updateModelList(self):
        """
        Checks current default path for models and refreshes current displayed
        list. If current selection is found, it is kept as active.
        """
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        currentModel = self.model()
        self.resetModelList()
        self.setActiveModel(currentModel)
        QApplication.restoreOverrideCursor()

    @pyqtSlot(bool, name='on_addModelPushButton_clicked')
    def registerModel(self, modelPath=None):
        """
        Registers a model to the model runner. This application register all
        new models to a default directory.
        :param modelPath: (str) path to the model to be registered.
        """
        if modelPath is None or not isinstance(modelPath, str):
            fd = QFileDialog()
            modelPathList = fd.getOpenFileNames(
                caption=self.tr('Select a QGIS processing model to be added'),
                filter=self.tr('QGIS Processing Model (*.model *.model3)')
            )
            modelPathList = modelPathList[0] if modelPathList else modelPathList
            if modelPathList == []:
                return
        msg = self.tr(
            "Model seems to be already registered, would you like to overwrite"
            " it?"
        )
        for modelPath in modelPathList:
            modelName = os.path.basename(modelPath)
            if self.modelExists(modelName) and not self.confirmAction(msg):
                QgsMessageLog.logMessage(
                    self.tr("Model {model} was not imported.").format(model=modelName),
                    'DSGTools Plugin',
                    Qgis.Info
                )
                return
            dest = os.path.join(self.defaultModelPath(), modelName)
            copy(modelPath, dest)
            if os.path.exists(dest):
                self.modelComboBox.addItem(modelName)
                self._newModels.append(dest)
                self.setActiveModel(modelName)
                self.modelAdded.emit(modelName)
                QgsMessageLog.logMessage(
                    self.tr("Model {model} imported to {dest}.").format(model=modelName, dest=dest),
                    'DSGTools Plugin',
                    Qgis.Info
                )


    @pyqtSlot(bool, name='on_removeModelPushButton_clicked')
    def unregisterModel(self, modelName=None):
        """
        Unregisters a model to the model runner. Removes the model from the 
        default directory.
        :param modelName: (str) basename for the model to be removed.
        """
        if self.modelComboBox.currentIndex() < 1:
            return
        if not modelName or isinstance(modelName, bool):
            modelName = self.model()
            modelPath = self.modelPath()
        else:
            modelPath = os.path.join(self.defaultModelPath(), modelName)
        msg = self.tr("Remove model '{modelName}'?".format(modelName=modelName))
        if self.confirmAction(msg) and self.modelExists(modelName):
            try:
                os.remove(modelPath)
                if not os.path.exists(modelPath):
                    self.modelComboBox.removeItem(self.modelComboBox.findText(modelName))
                    self.modelRemoved.emit(modelName)
            except Exception as e:
                msg = self.tr("Unable to remove '{model}':\n{error}.").format(
                    model=modelName, error=", ".join(map(str, e.args))
                )
                self.confirmAction(msg, showCancel=False)

    @pyqtSlot(bool, name='on_runModelPushButton_clicked')
    def runModel(self, modelName=None):
        """
        Executes chosen model, if possible.
        :param modelPath: (str) path to the model to be registered.
        """
        if self.modelComboBox.currentIndex() < 1:
            return
        if not modelName or isinstance(modelName, bool):
            modelName = self.model()
            modelPath = self.modelPath()
        else:
            modelPath = os.path.join(self.defaultModelPath(), modelName)
        alg = QgsProcessingModelAlgorithm()
        if not self.modelExists(modelName):
            # if model was manually removed and combo box was not refreshed
            self.iface.messageBar().pushMessage(
                self.tr('Failed'), 
                self.tr("model {model} seems to have been deleted.").format(model=modelName),
                level=Qgis.Critical,
                duration=5
            )
            return
        alg.fromFile(modelPath)
        alg.initAlgorithm()
        # as this tool assumes that every parameter is pre-set, only output shall
        # be passed on - ALL outputs from this tool is set to memory layers.
        param = {vl.name() : "memory:" for vl in alg.parameterDefinitions()}
        msg = self.tr("Would you like to run {model}").format(model=modelName)
        if self.options()["checkBeforeRunModel"] and not self.confirmAction(msg):
            return
        try:
            out = processing.run(alg, param)
            self.iface.messageBar().pushMessage(
                self.tr('Sucess'), 
                self.tr("model {model} finished.").format(model=modelName),
                level=Qgis.Info,
                duration=5
            )
            QgsMessageLog.logMessage(
                    self.tr(
                        "Model {model} finished running with no errors. You may"
                        " check model output on Processing log tab."
                    ).format(model=modelName),
                    'DSGTools Plugin',
                    Qgis.Info
                )
            if not self.options()["loadModelOutput"]:
                return
            for var, value in out.items():
                if isinstance(value, QgsMapLayer):
                    value.setName(
                        "{model} {layername}".format(model=modelName, layername=var)
                    )
                    self.addLayerToGroup(
                        value, "DSGTools Validation Toolbar Output", modelName
                    )
        except Exception as e:
            msg = self.tr(
                "Unable to run (check Processing tab for details on model "
                "execution log) {model}:\n{error}"
            ).format(model=modelName, error=str(e))
            self.iface.messageBar().pushMessage(
                self.tr("Model {model} failed").format(model=modelName), 
                self.tr("check log for more information."),
                level=Qgis.Critical,
                duration=5
            )
            QgsMessageLog.logMessage(msg, 'DSGTools Plugin',Qgis.Info)

    def unload(self):
        """
        Method called whenever tool is being destructed. Blocks signals and clears
        all objects that it parents.
        """
        if self.options()["removeModelsOnExit"]:
            for model in self._newModels:
                if os.path.exists(model):
                    os.remove(model)
        for w in self._widgets():
            w.blockSignals(True)
            del w
        self.iface.unregisterMainWindowAction(self.runAction)    

    def addShortcut(self):
        """
        Adds the action to main menu allowing QGIS to assign a shortcut for run.
        """
        self.runAction = QAction(
            QIcon(':/plugins/DsgTools/icons/runModel.png'),
            self.tr('DSGTools: Validation Toolbar - Run Processing Model'),
            self.parent
        )
        self.runAction.triggered.connect(self.runModel)
        if self.parent:
            self.parent.addAction(self.runAction)
        self.iface.registerMainWindowAction(self.runAction, '')
Exemple #34
0
    def fromOldFormatFile(filename):
        def _tr(s):
            return QCoreApplication.translate('ModelerAlgorithm', s)

        hardcodedValues = {}
        modelParameters = []
        modelAlgs = []
        model = ModelerAlgorithm()
        model.descriptionFile = filename
        lines = codecs.open(filename, 'r', encoding='utf-8')
        line = lines.readline().strip('\n').strip('\r')
        try:
            while line != '':
                if line.startswith('PARAMETER:'):
                    paramLine = line[len('PARAMETER:'):]
                    param = getParameterFromString(paramLine)
                    if param:
                        pass
                    else:
                        raise WrongModelException(
                            _tr('Error in parameter line: %s',
                                'ModelerAlgorithm') % line)
                    line = lines.readline().strip('\n')
                    tokens = line.split(',')
                    model.addParameter(
                        ModelerParameter(
                            param, QPointF(float(tokens[0]),
                                           float(tokens[1]))))
                    modelParameters.append(param.name)
                elif line.startswith('VALUE:'):
                    valueLine = line[len('VALUE:'):]
                    tokens = valueLine.split('===')
                    name = tokens[0]
                    value = tokens[1].replace(
                        ModelerAlgorithm.LINE_BREAK_STRING, '\n')
                    hardcodedValues[name] = value
                elif line.startswith('NAME:'):
                    model.name = line[len('NAME:'):]
                elif line.startswith('GROUP:'):
                    model.group = line[len('GROUP:'):]
                elif line.startswith('ALGORITHM:'):
                    algLine = line[len('ALGORITHM:'):]
                    alg = ModelerUtils.getAlgorithm(algLine)
                    if alg is not None:
                        modelAlg = Algorithm(alg.commandLineName())
                        modelAlg.description = alg.name
                        posline = lines.readline().strip('\n').strip('\r')
                        tokens = posline.split(',')
                        modelAlg.pos = QPointF(float(tokens[0]),
                                               float(tokens[1]))
                        # dependenceline = lines.readline().strip('\n').strip('\r')
                        for param in alg.parameters:
                            if not param.hidden:
                                line = lines.readline().strip('\n').strip('\r')
                                if line == unicode(None):
                                    modelAlg.params[param.name] = None
                                else:
                                    tokens = line.split('|')
                                    try:
                                        algIdx = int(tokens[0])
                                    except:
                                        raise WrongModelException(
                                            _tr('Number of parameters in the '
                                                '{} algorithm does not match '
                                                'current Processing '
                                                'implementation'.format(
                                                    alg.name)))
                                    if algIdx == -1:
                                        if tokens[1] in modelParameters:
                                            modelAlg.params[
                                                param.name] = ValueFromInput(
                                                    tokens[1])
                                        else:
                                            modelAlg.params[
                                                param.name] = hardcodedValues[
                                                    tokens[1]]
                                    else:
                                        modelAlg.params[
                                            param.name] = ValueFromOutput(
                                                algIdx, tokens[1])

                        for out in alg.outputs:
                            if not out.hidden:
                                line = lines.readline().strip('\n').strip('\r')
                                if unicode(None) != line:
                                    if '|' in line:
                                        tokens = line.split('|')
                                        name = tokens[0]
                                        tokens = tokens[1].split(',')
                                        pos = QPointF(float(tokens[0]),
                                                      float(tokens[1]))
                                    else:
                                        name = line
                                        pos = None
                                    modelerOutput = ModelerOutput(name)
                                    modelerOutput.pos = pos
                                    modelAlg.outputs[out.name] = modelerOutput

                        model.addAlgorithm(modelAlg)
                        modelAlgs.append(modelAlg.name)
                    else:
                        raise WrongModelException(
                            _tr('Error in algorithm name: %s', ) % algLine)
                line = lines.readline().strip('\n').strip('\r')
            for modelAlg in model.algs.values():
                for name, value in modelAlg.params.iteritems():
                    if isinstance(value, ValueFromOutput):
                        value.alg = modelAlgs[value.alg]
            return model
        except Exception as e:
            if isinstance(e, WrongModelException):
                raise e
            else:
                raise WrongModelException(
                    _tr('Error in model definition line: ') + '%s\n%s' %
                    (line.strip(), traceback.format_exc()))
Exemple #35
0
class Options(QDialog, FORM_CLASS):
    __dsgToolsModelPath__ = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "..", "..", "..", "core",
                     "Misc", "QGIS_Models"))
    __qgisModelPath__ = ModelerUtils.modelsFolders()[0]

    # # some options signals
    # modelPathChanged = pyqtSignal()

    def __init__(self, parent=None):
        """Constructor."""
        super(Options, self).__init__(parent)
        self.setupUi(self)
        self.setInterfaceWithParametersFromConfig()
        self.setupValidationToolbarConfig()
        # project option still not implemented
        self.removeModelsProjectCheckBox.hide()

    @pyqtSlot(bool)
    def on_addPushButton_clicked(self):
        newValue = self.addParameterLineEdit.text()
        valueList = [
            self.blackListWidget.itemAt(i, 0).text()
            for i in range(self.blackListWidget.count())
        ]
        if newValue == '':
            QMessageBox.warning(self, self.tr('Warning!'),
                                self.tr('Fill in a value before adding!'))
            return
        if newValue in valueList:
            QMessageBox.warning(self, self.tr('Warning!'),
                                self.tr('Value already in black list!'))
            return
        self.blackListWidget.addItem(newValue)
        self.blackListWidget.sortItems(order=Qt.AscendingOrder)
        self.addParameterLineEdit.setText('')

    def getParameters(self):
        freeHandTolerance = self.toleranceQgsDoubleSpinBox.value()
        freeHandSmoothIterations = self.smoothIterationsQgsSpinBox.value()
        freeHandSmoothOffset = self.smoothOffsetQgsDoubleSpinBox.value()
        algIterations = self.algIterationsQgsSpinBox.value()
        minSegmentDistance = self.minSegmentDistanceQgsSpinBox.value()
        valueList = [
            self.blackListWidget.item(i).text()
            for i in range(self.blackListWidget.count())
        ]
        undoPoints = self.undoQgsSpinBox.value()
        decimals = self.decimalQgsSpinBox.value()
        return (freeHandTolerance, freeHandSmoothIterations,
                freeHandSmoothOffset, algIterations, minSegmentDistance,
                valueList, undoPoints, decimals)

    def loadParametersFromConfig(self):
        settings = QSettings()
        settings.beginGroup('PythonPlugins/DsgTools/Options')
        freeHandTolerance = settings.value('freeHandTolerance')
        freeHandSmoothIterations = settings.value('freeHandSmoothIterations')
        freeHandSmoothOffset = settings.value('freeHandSmoothOffset')
        algIterations = settings.value('algIterations')
        minSegmentDistance = settings.value('minSegmentDistance')
        valueList = settings.value('valueList')
        undoPoints = settings.value('undoPoints')
        decimals = settings.value('decimals')
        if valueList:
            valueList = valueList.split(';')
        settings.endGroup()
        return (freeHandTolerance, freeHandSmoothIterations,
                freeHandSmoothOffset, algIterations, minSegmentDistance,
                valueList, undoPoints, decimals)

    def setInterfaceWithParametersFromConfig(self):
        (freeHandTolerance, freeHandSmoothIterations, freeHandSmoothOffset,
         algIterations, minSegmentDistance, valueList, undoPoints,
         decimals) = self.loadParametersFromConfig()
        if freeHandTolerance:
            self.toleranceQgsDoubleSpinBox.setValue(float(freeHandTolerance))
        if freeHandSmoothIterations:
            self.smoothIterationsQgsSpinBox.setValue(
                int(freeHandSmoothIterations))
        if freeHandSmoothOffset:
            self.smoothOffsetQgsDoubleSpinBox.setValue(
                float(freeHandSmoothOffset))
        if algIterations:
            self.algIterationsQgsSpinBox.setValue(int(algIterations))
        if minSegmentDistance:
            self.minSegmentDistanceQgsSpinBox.setValue(int(minSegmentDistance))
        if valueList:
            self.blackListWidget.clear()
            self.blackListWidget.addItems(valueList)
            self.blackListWidget.sortItems(order=Qt.AscendingOrder)
        if undoPoints:
            self.undoQgsSpinBox.setValue(int(undoPoints))

    def storeParametersInConfig(self):
        (freeHandTolerance, freeHandSmoothIterations, freeHandSmoothOffset,
         algIterations, minSegmentDistance, valueList, undoPoints,
         decimals) = self.getParameters()
        settings = QSettings()
        settings.beginGroup('PythonPlugins/DsgTools/Options')
        settings.setValue('freeHandTolerance', freeHandTolerance)
        settings.setValue('freeHandSmoothIterations', freeHandSmoothIterations)
        settings.setValue('freeHandSmoothOffset', freeHandSmoothOffset)
        settings.setValue('algIterations', algIterations)
        settings.setValue('minSegmentDistance', minSegmentDistance)
        settings.setValue('valueList', ';'.join(valueList))
        settings.setValue('undoPoints', undoPoints)
        settings.setValue('decimals', decimals)
        settings.endGroup()

    @pyqtSlot()
    def on_buttonBox_accepted(self):
        self.storeParametersInConfig()
        self.updateValidationToolbarConfig()
        self.close()

    @pyqtSlot(bool)
    def on_removePushButton_clicked(self):
        selectedItems = self.blackListWidget.selectedItems()
        idxList = []
        for i in range(self.blackListWidget.count()):
            if self.blackListWidget.item(i) in selectedItems:
                idxList.append(i)
        idxList.sort(reverse=True)
        for i in idxList:
            self.blackListWidget.takeItem(i)

    def firstTimeConfig(self):
        (freeHandTolerance, freeHandSmoothIterations, freeHandSmoothOffset,
         algIterations, minSegmentDistance, valueList, undoPoints,
         decimals) = self.loadParametersFromConfig()
        if not (freeHandTolerance and freeHandSmoothIterations
                and freeHandSmoothOffset and algIterations and valueList
                and undoPoints and decimals is not None):
            self.storeParametersInConfig()

    def setupModelPath(self):
        """
        Clears all model paths and leaves the default options.
        """
        self.modelPathComboBox.clear()
        self.modelPathComboBox.addItems(
            [self.__dsgToolsModelPath__, self.__qgisModelPath__])

    def setupValidationToolbarConfig(self):
        """
        Sets up Validation Toolbar parameters to DSGTools default values.
        """
        # reset combo box to default as well
        self.setupModelPath()
        settings = QSettings()
        settings.beginGroup('PythonPlugins/DsgTools/Options')
        if settings.value('loadModelOutput') is None:
            settings.setValue('loadModelOutput', True)
        self.loadModelOutputCheckBox.setChecked(
            settings.value('loadModelOutput') in (True, "true"))
        if settings.value('checkBeforeRunModel') is None:
            settings.setValue('checkBeforeRunModel', True)
        self.checkBeforeRunModelCheckBox.setChecked(
            settings.value('checkBeforeRunModel') in (True, "true"))
        if settings.value('removeModelsOnExit') is None:
            settings.setValue('', False)
        self.resetModelsCheckBox.setChecked(
            settings.value('removeModelsOnExit') in (True, "true"))
        if settings.value('removeModelsOnNewProject') is None:
            settings.setValue('removeModelsOnNewProject', False)
        self.removeModelsProjectCheckBox.setChecked(
            settings.value('removeModelsOnNewProject') in (True, "true"))
        if settings.value('defaultModelPath') is None:
            settings.setValue('defaultModelPath',
                              self.modelPathComboBox.currentText())
        idx = self.modelPathComboBox.findText(
            settings.value('defaultModelPath'))
        if idx < 0:
            self.modelPathComboBox.addItem(settings.value('defaultModelPath'))
        self.modelPathComboBox.setCurrentText(
            settings.value('defaultModelPath'))
        settings.endGroup()

    def validationToolbarConfig(self):
        """
        Reads all parameters for Validation Toolbar.
        :return: (dict) set of parameters for Validation Toolbar.
        """
        settings = QSettings()
        settings.beginGroup('PythonPlugins/DsgTools/Options')
        loadModelOutput = settings.value('loadModelOutput')
        checkBeforeRunModel = settings.value('checkBeforeRunModel')
        removeModelsOnExit = settings.value('removeModelsOnExit')
        removeModelsOnNewProject = settings.value('removeModelsOnNewProject')
        defaultModelPath = settings.value('defaultModelPath')
        settings.endGroup()
        return {
            "loadModelOutput": loadModelOutput in (True, "true"),
            "checkBeforeRunModel": checkBeforeRunModel in (True, "true"),
            "removeModelsOnExit": removeModelsOnExit in (True, "true"),
            "removeModelsOnNewProject": removeModelsOnNewProject
            in (True, "true"),
            "defaultModelPath": defaultModelPath
        }

    def updateValidationToolbarConfig(self):
        """
        Updates current Validation Toolbar parameter values from GUI.
        """
        settings = QSettings()
        settings.beginGroup('PythonPlugins/DsgTools/Options')
        settings.setValue('loadModelOutput',
                          self.loadModelOutputCheckBox.isChecked())
        settings.setValue('checkBeforeRunModel',
                          self.checkBeforeRunModelCheckBox.isChecked())
        settings.setValue('removeModelsOnExit',
                          self.resetModelsCheckBox.isChecked())
        settings.setValue('removeModelsOnNewProject',
                          self.removeModelsProjectCheckBox.isChecked())
        # oldModelPath = settings.value('defaultModelPath')
        # newModelPath = self.modelPathComboBox.currentText()
        settings.setValue('defaultModelPath',
                          self.modelPathComboBox.currentText())
        settings.endGroup()
        # if oldModelPath != newModelPath:
        #     self.modelPathChanged.emit()

    def addNewModelPath(self, modelPath, setAsDefault=True):
        """
        Adds a custom model path as an option.
        :param modelPath: (str) path to look for QGIS Processing models.
        :param setAsDefault: (bool) whether current selection should be updated to new model path.
        :return: (int) index for new model path on its selection combo box.
        """
        if not os.path.exists(
                modelPath) or self.modelPathComboBox.findText(modelPath) >= 0:
            return -1
        self.modelPathComboBox.addItem(modelPath)
        idx = self.modelPathComboBox.findText(modelPath)
        if setAsDefault:
            self.modelPathComboBox.setCurrentIndex(idx)
        return idx

    @pyqtSlot(bool, name="on_addModelPathPushButton_clicked")
    def setCustomModelPath(self):
        """
        Adds a custom model path and sets it as default.
        """
        fd = QFileDialog()
        newModelPath = fd.getExistingDirectory(
            caption=self.tr('Select a directory for DSGTools Validation'
                            ' Toolbar to look for QGIS Processing models'))
        newModelPath = newModelPath[0] if isinstance(newModelPath,
                                                     tuple) else newModelPath
        if not newModelPath:
            return
        self.addNewModelPath(newModelPath)
Exemple #36
0
 def _loadAlgorithms(self):
     folders = ModelerUtils.modelsFolders()
     self.algs = []
     for f in folders:
         self.loadFromFolder(f)
Exemple #37
0
 def addAlgorithm(self):
     item = self.algorithmTree.currentItem()
     if isinstance(item, TreeAlgorithmItem):
         alg = ModelerUtils.getAlgorithm(item.alg.commandLineName())
         self._addAlgorithm(alg.getCopy())
    def openModel(self, filename):
        self.algPos = []
        self.paramPos = []
        self.outputOutputs = []
        self.algs = []
        self.algParameters = []
        self.algOutputs = []
        self.paramValues = {}
        self.dependencies = []

        self.descriptionFile = filename
        lines = codecs.open(filename, "r", encoding='utf-8')
        line = lines.readline().strip("\n").strip("\r")
        iAlg = 0
        try:
            while line != "":
                if line.startswith("PARAMETER:"):
                    paramLine = line[len("PARAMETER:"):]
                    param = ParameterFactory.getFromString(paramLine)
                    if param:
                        self.parameters.append(param)
                    else:
                        raise WrongModelException("Error in parameter line: " +
                                                  line)
                    line = lines.readline().strip("\n")
                    tokens = line.split(",")
                    self.paramPos.append(
                        QtCore.QPointF(float(tokens[0]), float(tokens[1])))
                elif line.startswith("VALUE:"):
                    valueLine = line[len("VALUE:"):]
                    tokens = valueLine.split("===")
                    self.paramValues[tokens[0]] = tokens[1].replace(
                        ModelerAlgorithm.LINE_BREAK_STRING, '\n')
                elif line.startswith("NAME:"):
                    self.name = line[len("NAME:"):]
                elif line.startswith("GROUP:"):
                    self.group = line[len("GROUP:"):]
                elif line.startswith("ALGORITHM:"):
                    algParams = {}
                    algOutputs = {}
                    algLine = line[len("ALGORITHM:"):]
                    alg = ModelerUtils.getAlgorithm(algLine)
                    if alg is not None:
                        posline = lines.readline().strip("\n").strip("\r")
                        tokens = posline.split(",")
                        self.algPos.append(
                            QtCore.QPointF(float(tokens[0]), float(tokens[1])))
                        self.algs.append(alg)
                        dependenceline = lines.readline().strip("\n").strip(
                            "\r")
                        dependencies = []
                        if dependenceline != str(None):
                            for index in dependenceline.split(","):
                                try:
                                    dependencies.append(int(index))
                                except:
                                    pass  #a quick fix while I figure out how to solve problems when parsing this
                        for param in alg.parameters:
                            line = lines.readline().strip("\n").strip("\r")
                            if line == str(None):
                                algParams[param.name] = None
                            else:
                                tokens = line.split("|")
                                algParams[param.name] = AlgorithmAndParameter(
                                    int(tokens[0]), tokens[1])
                        outputPos = {}
                        for out in alg.outputs:
                            line = lines.readline().strip("\n").strip("\r")
                            if str(None) != line:
                                if "|" in line:
                                    tokens = line.split("|")
                                    name = tokens[0]
                                    tokens = tokens[1].split(",")
                                    outputPos[out.name] = QtCore.QPointF(
                                        float(tokens[0]), float(tokens[1]))
                                else:
                                    name = line
                                    outputPos[out.name] = None
                                algOutputs[out.name] = name
                                #we add the output to the algorithm, with a name indicating where it comes from
                                #that guarantees that the name is unique
                                output = copy.deepcopy(out)
                                output.description = name
                                output.name = self.getSafeNameForOutput(
                                    iAlg, output)
                                self.addOutput(output)
                            else:
                                algOutputs[out.name] = None
                        self.outputPos.append(outputPos)
                        self.algOutputs.append(algOutputs)
                        self.algParameters.append(algParams)
                        self.dependencies.append(dependencies)
                        iAlg += 1
                    else:
                        raise WrongModelException("Error in algorithm name: " +
                                                  algLine)
                line = lines.readline().strip("\n").strip("\r")
        except Exception, e:
            if isinstance(e, WrongModelException):
                raise e
            else:
                raise WrongModelException("Error in model definition line:" +
                                          line.strip() + " : " +
                                          traceback.format_exc())
Exemple #39
0
    def fromOldFormatFile(filename):
        def _tr(s):
            return QtCore.QCoreApplication.translate('ModelerAlgorithm', s)
        hardcodedValues = {}
        modelParameters = []
        modelAlgs = []
        model = ModelerAlgorithm()
        model.descriptionFile = filename
        lines = codecs.open(filename, 'r', encoding='utf-8')
        line = lines.readline().strip('\n').strip('\r')
        try:
            while line != '':
                if line.startswith('PARAMETER:'):
                    paramLine = line[len('PARAMETER:'):]
                    param = getParameterFromString(paramLine)
                    if param:
                        pass
                    else:
                        raise WrongModelException(
                            _tr('Error in parameter line: %s', 'ModelerAlgorithm') % line)
                    line = lines.readline().strip('\n')
                    tokens = line.split(',')
                    model.addParameter(ModelerParameter(param, QtCore.QPointF(
                                            float(tokens[0]), float(tokens[1]))))
                    modelParameters.append(param.name)
                elif line.startswith('VALUE:'):
                    valueLine = line[len('VALUE:'):]
                    tokens = valueLine.split('===')
                    name = tokens[0]
                    value = tokens[1].replace(ModelerAlgorithm.LINE_BREAK_STRING, '\n')
                    hardcodedValues[name] = value
                elif line.startswith('NAME:'):
                    model.name = line[len('NAME:'):]
                elif line.startswith('GROUP:'):
                    model.group = line[len('GROUP:'):]
                elif line.startswith('ALGORITHM:'):
                    algLine = line[len('ALGORITHM:'):]
                    alg = ModelerUtils.getAlgorithm(algLine)
                    if alg is not None:
                        modelAlg = Algorithm(alg.commandLineName())
                        modelAlg.description = alg.name
                        posline = lines.readline().strip('\n').strip('\r')
                        tokens = posline.split(',')
                        modelAlg.pos = QtCore.QPointF(float(tokens[0]), float(tokens[1]))
                        dependenceline = lines.readline().strip('\n').strip('\r') #unused
                        for param in alg.parameters:
                            if not param.hidden:
                                line = lines.readline().strip('\n').strip('\r')
                                if line == str(None):
                                    modelAlg.params[param.name]  = None
                                else:
                                    tokens = line.split('|')
                                    algIdx = int(tokens[0])
                                    if algIdx == -1:
                                        if tokens[1] in modelParameters:
                                            modelAlg.params[param.name] = ValueFromInput(tokens[1])
                                        else:
                                            modelAlg.params[param.name] = hardcodedValues[tokens[1]]
                                    else:
                                        modelAlg.params[param.name] = ValueFromOutput(algIdx, tokens[1])

                        for out in alg.outputs:
                            if not out.hidden:
                                line = lines.readline().strip('\n').strip('\r')
                                if str(None) != line:
                                    if '|' in line:
                                        tokens = line.split('|')
                                        name = tokens[0]
                                        tokens = tokens[1].split(',')
                                        pos = QtCore.QPointF(
                                                float(tokens[0]), float(tokens[1]))
                                    else:
                                        name = line
                                        pos = None
                                    modelerOutput = ModelerOutput(name)
                                    modelerOutput.pos = pos
                                    modelAlg.outputs[out.name] = modelerOutput

                        model.addAlgorithm(modelAlg)
                        modelAlgs.append(modelAlg.name)
                    else:
                        raise WrongModelException(
                            _tr('Error in algorithm name: %s', ) % algLine)
                line = lines.readline().strip('\n').strip('\r')
            for modelAlg in model.algs.values():
                for name, value in modelAlg.params.iteritems():
                    if isinstance(value, ValueFromOutput):
                        value.alg = modelAlgs[value.alg]
            return model
        except Exception, e:
            if isinstance(e, WrongModelException):
                raise e
            else:
                raise WrongModelException(_tr('Error in model definition line: ') + '%s\n%s' % (line.strip(), traceback.format_exc()))
Exemple #40
0
 def initializeSettings(self):
     AlgorithmProvider.initializeSettings(self)
     ProcessingConfig.addSetting(Setting(self.name(),
                                         ModelerUtils.MODELS_FOLDER, self.tr('Models folder', 'ModelerAlgorithmProvider'),
                                         ModelerUtils.defaultModelsFolder(), valuetype=Setting.MULTIPLE_FOLDERS))
Exemple #41
0
    def openModel(self, filename):
        self.algPos = []
        self.paramPos = []
        self.outputOutputs = []
        self.algs = []
        self.algParameters = []
        self.algOutputs = []
        self.paramValues = {}
        self.dependencies = []
        self.descriptionFile = filename
        lines = codecs.open(filename, 'r', encoding='utf-8')
        line = lines.readline().strip('\n').strip('\r')
        iAlg = 0
        try:
            while line != '':
                if line.startswith('PARAMETER:'):
                    paramLine = line[len('PARAMETER:'):]
                    param = ParameterFactory.getFromString(paramLine)
                    if param:
                        self.parameters.append(param)
                    else:
                        raise WrongModelException('Error in parameter line: ' +
                                                  line)
                    line = lines.readline().strip('\n')
                    tokens = line.split(',')
                    self.paramPos.append(
                        QtCore.QPointF(float(tokens[0]), float(tokens[1])))
                elif line.startswith('VALUE:'):
                    valueLine = line[len('VALUE:'):]
                    tokens = valueLine.split('===')
                    self.paramValues[tokens[0]] = \
                        tokens[1].replace(ModelerAlgorithm.LINE_BREAK_STRING,
                            '\n')
                elif line.startswith('NAME:'):
                    self.name = line[len('NAME:'):]
                elif line.startswith('GROUP:'):
                    self.group = line[len('GROUP:'):]
                    if self.group == '[Test models]':
                        self.showInModeler = False
                        self.showInToolbox = False
                elif line.startswith('ALGORITHM:'):
                    algParams = {}
                    algOutputs = {}
                    algLine = line[len('ALGORITHM:'):]
                    alg = ModelerUtils.getAlgorithm(algLine)
                    if alg is not None:
                        posline = lines.readline().strip('\n').strip('\r')
                        tokens = posline.split(',')
                        self.algPos.append(
                            QtCore.QPointF(float(tokens[0]), float(tokens[1])))
                        self.algs.append(alg)
                        dependenceline = lines.readline().strip('\n').strip(
                            '\r')
                        dependencies = []
                        if dependenceline != str(None):
                            for index in dependenceline.split(','):
                                try:
                                    dependencies.append(int(index))
                                except:
                                    # A quick fix while I figure out
                                    # how to solve problems when
                                    # parsing this
                                    pass
                        for param in alg.parameters:
                            line = lines.readline().strip('\n').strip('\r')
                            if line == str(None):
                                algParams[param.name] = None
                            else:
                                tokens = line.split('|')
                                algParams[param.name] = \
                                    AlgorithmAndParameter(int(tokens[0]),
                                        tokens[1])
                        outputPos = {}
                        for out in alg.outputs:
                            line = lines.readline().strip('\n').strip('\r')
                            if str(None) != line:
                                if '|' in line:
                                    tokens = line.split('|')
                                    name = tokens[0]
                                    tokens = tokens[1].split(',')
                                    outputPos[out.name] = QtCore.QPointF(
                                        float(tokens[0]), float(tokens[1]))
                                else:
                                    name = line
                                    outputPos[out.name] = None
                                algOutputs[out.name] = name

                                # We add the output to the algorithm,
                                # with a name indicating where it comes
                                # from that guarantees that the name is
                                # unique
                                output = copy.deepcopy(out)
                                output.description = name
                                output.name = self.getSafeNameForOutput(
                                    iAlg, output)
                                self.addOutput(output)
                            else:
                                algOutputs[out.name] = None
                        self.outputPos.append(outputPos)
                        self.algOutputs.append(algOutputs)
                        self.algParameters.append(algParams)
                        self.dependencies.append(dependencies)
                        iAlg += 1
                    else:
                        raise WrongModelException('Error in algorithm name: ' +
                                                  algLine)
                line = lines.readline().strip('\n').strip('\r')
        except Exception, e:
            if isinstance(e, WrongModelException):
                raise e
            else:
                raise WrongModelException('Error in model definition line:' +
                                          line.strip() + ' : ' +
                                          traceback.format_exc())
 def _loadAlgorithms(self):
     folder = ModelerUtils.modelsFolder()
     self.loadFromFolder(folder)
     folder = os.path.join(os.path.dirname(__file__), 'models')
     self.loadFromFolder(folder)
Exemple #43
0
    def openModel(self):
        filename, selected_filter = str(QFileDialog.getOpenFileName(self,
                                                                    self.tr('Open Model'), ModelerUtils.modelsFolders()[0],
                                                                    self.tr('Processing models (*.model *.MODEL)')))
        if filename:
            try:
                alg = ModelerAlgorithm.fromFile(filename)
                self.alg = alg
                self.alg.setModelerView(self)
                self.textGroup.setText(alg.group)
                self.textName.setText(alg.name)
                self.repaintModel()

                self.view.centerOn(0, 0)
                self.hasChanged = False
            except WrongModelException as e:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                       self.tr('Could not load model %s\n%s') % (filename, e.msg))
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
            except Exception as e:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                       self.tr('Could not load model %s\n%s') % (filename, e.args[0]))
                QMessageBox.critical(self, self.tr('Could not open model'),
                                     self.tr('The selected model could not be loaded.\n'
                                             'See the log for more information.'))
Exemple #44
0
 def addAlgorithm(self):
     item = self.algorithmTree.currentItem()
     if isinstance(item, TreeAlgorithmItem):
         alg = ModelerUtils.getAlgorithm(item.alg.commandLineName())
         self._addAlgorithm(alg.getCopy())
Exemple #45
0
    def saveModel(self, saveAs) -> bool:
        if not self.validateSave(QgsModelDesignerDialog.SaveAction.SaveAsFile):
            return False

        model_name_matched_file_name = self.model().modelNameMatchesFilePath()
        if self.model().sourceFilePath() and not saveAs:
            filename = self.model().sourceFilePath()
        else:
            if self.model().sourceFilePath():
                initial_path = Path(self.model().sourceFilePath())
            elif self.model().name():
                initial_path = Path(ModelerUtils.modelsFolders()[0]) / (
                    self.model().name() + '.model3')
            else:
                initial_path = Path(ModelerUtils.modelsFolders()[0])

            filename, _ = QFileDialog.getSaveFileName(
                self, self.tr('Save Model'), initial_path.as_posix(),
                self.tr('Processing models (*.model3 *.MODEL3)'))
            if not filename:
                return False

            filename = QgsFileUtils.ensureFileNameHasExtension(
                filename, ['model3'])
            self.model().setSourceFilePath(filename)

            if not self.model().name() or self.model().name() == self.tr(
                    'model'):
                self.setModelName(Path(filename).stem)
            elif saveAs and model_name_matched_file_name:
                # if saving as, and the model name used to match the filename, then automatically update the
                # model name to match the new file name
                self.setModelName(Path(filename).stem)

        if not self.model().toFile(filename):
            if saveAs:
                QMessageBox.warning(
                    self, self.tr('I/O error'),
                    self.tr('Unable to save edits. Reason:\n {0}').format(
                        str(sys.exc_info()[1])))
            else:
                QMessageBox.warning(
                    self, self.tr("Can't save model"),
                    self.
                    tr("This model can't be saved in its original location (probably you do not "
                       "have permission to do it). Please, use the 'Save as…' option."
                       ))
            return False

        self.update_model.emit()
        if saveAs:
            self.messageBar().pushMessage(
                "",
                self.tr("Model was saved to <a href=\"{}\">{}</a>").format(
                    QUrl.fromLocalFile(filename).toString(),
                    QDir.toNativeSeparators(filename)),
                level=Qgis.Success,
                duration=5)

        self.setDirty(False)
        return True
Exemple #46
0
 def checkBeforeOpeningParametersDialog(self):
     for alg in self.algs.values():
         algInstance = ModelerUtils.getAlgorithm(alg.consoleName)
         if algInstance is None:
             return "The model you are trying to run contains an algorithm that is not available: <i>%s</i>" % alg.consoleName
Exemple #47
0
 def algorithm(self):
     if self._algInstance is None:
         self._algInstance = ModelerUtils.getAlgorithm(
             self.consoleName).getCopy()
     return self._algInstance