Ejemplo n.º 1
0
def load(fileName, name=None, crs=None, style=None, isRaster=False):
    """Loads a layer/table into the current project, given its file.
    """

    if fileName is None:
        return
    prjSetting = None
    settings = QgsSettings()
    if crs is not None:
        prjSetting = settings.value('/Projections/defaultBehavior')
        settings.setValue('/Projections/defaultBehavior', '')
    if name is None:
        name = os.path.split(fileName)[1]

    if isRaster:
        qgslayer = QgsRasterLayer(fileName, name)
        if qgslayer.isValid():
            if crs is not None and qgslayer.crs() is None:
                qgslayer.setCrs(crs, False)
            if style is None:
                style = ProcessingConfig.getSetting(
                    ProcessingConfig.RASTER_STYLE)
            qgslayer.loadNamedStyle(style)
            QgsProject.instance().addMapLayers([qgslayer])
        else:
            if prjSetting:
                settings.setValue('/Projections/defaultBehavior', prjSetting)
            raise RuntimeError(
                QCoreApplication.translate(
                    'dataobject',
                    'Could not load layer: {0}\nCheck the processing framework log to look for errors.'
                ).format(fileName))
    else:
        qgslayer = QgsVectorLayer(fileName, name, 'ogr')
        if qgslayer.isValid():
            if crs is not None and qgslayer.crs() is None:
                qgslayer.setCrs(crs, False)
            if style is None:
                if qgslayer.geometryType() == QgsWkbTypes.PointGeometry:
                    style = ProcessingConfig.getSetting(
                        ProcessingConfig.VECTOR_POINT_STYLE)
                elif qgslayer.geometryType() == QgsWkbTypes.LineGeometry:
                    style = ProcessingConfig.getSetting(
                        ProcessingConfig.VECTOR_LINE_STYLE)
                else:
                    style = ProcessingConfig.getSetting(
                        ProcessingConfig.VECTOR_POLYGON_STYLE)
            qgslayer.loadNamedStyle(style)
            QgsProject.instance().addMapLayers([qgslayer])

    if prjSetting:
        settings.setValue('/Projections/defaultBehavior', prjSetting)

    return qgslayer
def createMenus():
    for alg in QgsApplication.processingRegistry().algorithms():
        menuPath = ProcessingConfig.getSetting("MENU_" + alg.id())
        addButton = ProcessingConfig.getSetting("BUTTON_" + alg.id())
        icon = ProcessingConfig.getSetting("ICON_" + alg.id())
        if icon and os.path.exists(icon):
            icon = QIcon(icon)
        else:
            icon = None
        if menuPath:
            paths = menuPath.split("/")
            addAlgorithmEntry(alg, paths[0], paths[-1], addButton=addButton, icon=icon)
Ejemplo n.º 3
0
def handleAlgorithmResults(alg, context, feedback=None, showResults=True):
    wrongLayers = []
    if feedback is None:
        feedback = QgsProcessingFeedback()
    feedback.setProgressText(QCoreApplication.translate('Postprocessing', 'Loading resulting layers'))
    i = 0
    for l, details in context.layersToLoadOnCompletion().items():
        if feedback.isCanceled():
            return False

        if len(context.layersToLoadOnCompletion()) > 2:
            # only show progress feedback if we're loading a bunch of layers
            feedback.setProgress(100 * i / float(len(context.layersToLoadOnCompletion())))

        try:
            layer = QgsProcessingUtils.mapLayerFromString(l, context)
            if layer is not None:
                if not ProcessingConfig.getSetting(ProcessingConfig.USE_FILENAME_AS_LAYER_NAME):
                    layer.setName(details.name)

                style = None
                if details.outputName:
                    style = RenderingStyles.getStyle(alg.id(), details.outputName)
                if style is None:
                    if layer.type() == QgsMapLayer.RasterLayer:
                        style = ProcessingConfig.getSetting(ProcessingConfig.RASTER_STYLE)
                    else:
                        if layer.geometryType() == QgsWkbTypes.PointGeometry:
                            style = ProcessingConfig.getSetting(ProcessingConfig.VECTOR_POINT_STYLE)
                        elif layer.geometryType() == QgsWkbTypes.LineGeometry:
                            style = ProcessingConfig.getSetting(ProcessingConfig.VECTOR_LINE_STYLE)
                        else:
                            style = ProcessingConfig.getSetting(ProcessingConfig.VECTOR_POLYGON_STYLE)
                if style:
                    layer.loadNamedStyle(style)
                details.project.addMapLayer(context.temporaryLayerStore().takeMapLayer(layer))
            else:
                wrongLayers.append(str(l))
        except Exception:
            QgsMessageLog.logMessage(QCoreApplication.translate('Postprocessing', "Error loading result layer:") + "\n" + traceback.format_exc(), 'Processing', Qgis.Critical)
            wrongLayers.append(str(l))
        i += 1

    feedback.setProgress(100)

    if wrongLayers:
        msg = QCoreApplication.translate('Postprocessing', "The following layers were not correctly generated.")
        msg += "<ul>" + "".join(["<li>%s</li>" % lay for lay in wrongLayers]) + "</ul>"
        msg += QCoreApplication.translate('Postprocessing', "You can check the 'Log Messages Panel' in QGIS main window to find more information about the execution of the algorithm.")
        feedback.reportError(msg)

    return len(wrongLayers) == 0
    def grassHelpPath():
        helpPath = ProcessingConfig.getSetting(Grass7Utils.GRASS_HELP_PATH)

        if helpPath is None:
            if isWindows() or isMac():
                if Grass7Utils.path is not None:
                    localPath = os.path.join(Grass7Utils.path, 'docs/html')
                    if os.path.exists(localPath):
                        helpPath = os.path.abspath(localPath)
            else:
                searchPaths = [
                    '/usr/share/doc/grass-doc/html', '/opt/grass/docs/html',
                    '/usr/share/doc/grass/docs/html'
                ]
                for path in searchPaths:
                    if os.path.exists(path):
                        helpPath = os.path.abspath(path)
                        break

        if helpPath is not None:
            return helpPath
        elif Grass7Utils.version:
            version = Grass7Utils.version.replace('.', '')[:2]
            return 'https://grass.osgeo.org/grass{}/manuals/'.format(version)
        else:
            # GRASS not available!
            return 'https://grass.osgeo.org/grass72/manuals/'
    def addRecentAlgorithms(self, updating):
        showRecent = ProcessingConfig.getSetting(
            ProcessingConfig.SHOW_RECENT_ALGORITHMS)
        if showRecent:
            recent = ProcessingLog.getRecentAlgorithms()
            if len(recent) != 0:
                found = False
                if updating:
                    recentItem = self.algorithmTree.topLevelItem(0)
                    if recentItem.text(0) == self.tr('Recently used'):
                        treeWidget = recentItem.treeWidget()
                        treeWidget.takeTopLevelItem(
                            treeWidget.indexOfTopLevelItem(recentItem))

                recentItem = QTreeWidgetItem()
                recentItem.setText(0, self.tr('Recently used'))
                for algname in recent:
                    alg = QgsApplication.processingRegistry(
                    ).createAlgorithmById(algname)
                    if alg is not None:
                        algItem = TreeAlgorithmItem(alg)
                        recentItem.addChild(algItem)
                        found = True
                if found:
                    self.algorithmTree.insertTopLevelItem(0, recentItem)
                    recentItem.setExpanded(True)

            self.algorithmTree.setWordWrap(True)
Ejemplo n.º 6
0
def executeSaga(feedback):
    if isWindows():
        command = ['cmd.exe', '/C ', sagaBatchJobFilename()]
    else:
        os.chmod(sagaBatchJobFilename(), stat.S_IEXEC |
                 stat.S_IREAD | stat.S_IWRITE)
        command = ["'" + sagaBatchJobFilename() + "'"]
    loglines = []
    loglines.append(QCoreApplication.translate('SagaUtils', 'SAGA execution console output'))
    with subprocess.Popen(
        command,
        shell=True,
        stdout=subprocess.PIPE,
        stdin=subprocess.DEVNULL,
        stderr=subprocess.STDOUT,
        universal_newlines=True,
    ) as proc:
        try:
            for line in iter(proc.stdout.readline, ''):
                if '%' in line:
                    s = ''.join([x for x in line if x.isdigit()])
                    try:
                        feedback.setProgress(int(s))
                    except:
                        pass
                else:
                    line = line.strip()
                    if line != '/' and line != '-' and line != '\\' and line != '|':
                        loglines.append(line)
                        feedback.pushConsoleInfo(line)
        except:
            pass

    if ProcessingConfig.getSetting(SAGA_LOG_CONSOLE):
        QgsMessageLog.logMessage('\n'.join(loglines), 'Processing', Qgis.Info)
    def selectFile(self):
        output = self.alg.parameterDefinition('OUTPUT')
        fileFilter = getFileFilter(output)

        settings = QgsSettings()
        if settings.contains('/Processing/LastOutputPath'):
            path = settings.value('/Processing/LastOutputPath')
        else:
            path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER)
        lastEncoding = settings.value('/Processing/encoding', 'System')
        fileDialog = QgsEncodingFileDialog(self, self.tr('Save file'), path,
                                           fileFilter, lastEncoding)
        fileDialog.setFileMode(QFileDialog.AnyFile)
        fileDialog.setAcceptMode(QFileDialog.AcceptSave)
        fileDialog.setOption(QFileDialog.DontConfirmOverwrite, False)
        if fileDialog.exec_() == QDialog.Accepted:
            files = fileDialog.selectedFiles()
            encoding = str(fileDialog.encoding())
            output.encoding = encoding
            filename = str(files[0])
            selectedFileFilter = str(fileDialog.selectedNameFilter())
            if not filename.lower().endswith(
                    tuple(re.findall("\\*(\\.[a-z]{1,10})", fileFilter))):
                ext = re.search("\\*(\\.[a-z]{1,10})", selectedFileFilter)
                if ext:
                    filename = filename + ext.group(1)
            self.leOutputFile.setText(filename)
            settings.setValue('/Processing/LastOutputPath',
                              os.path.dirname(filename))
            settings.setValue('/Processing/encoding', encoding)
Ejemplo n.º 8
0
    def loadVectorLayer(self, name, layer, external=False):
        """
        Creates a dedicated command to load a vector into
        temporary GRASS DB.
        :param name: name of the parameter
        :param layer: QgsMapLayer for the vector layer.
        :param external: use v.external (v.in.ogr if False).
        """
        # TODO: support multiple input formats
        if external is None:
            external = ProcessingConfig.getSetting(
                Grass7Utils.GRASS_USE_VEXTERNAL)

        # safety check: we can only use external for ogr layers which support random read
        if external:
            ds = ogr.Open(layer.source())
            if ds is not None:
                ogr_layer = ds.GetLayer()
                if ogr_layer is None or not ogr_layer.TestCapability(
                        ogr.OLCRandomRead):
                    external = False
            else:
                external = False

        self.inputLayers.append(layer)
        self.setSessionProjectionFromLayer(layer)
        destFilename = 'vector_{}'.format(os.path.basename(getTempFilename()))
        self.exportedLayers[name] = destFilename
        command = '{0}{1}{2} input="{3}" output="{4}" --overwrite -o'.format(
            'v.external' if external else 'v.in.ogr',
            ' min_area={}'.format(self.minArea) if not external else '',
            ' snap={}'.format(self.snapTolerance) if not external else '',
            os.path.normpath(layer.source()), destFilename)
        self.commands.append(command)
    def textChanged(self):
        text = self.searchBox.text().strip(' ').lower()
        for item in list(self.disabledProviderItems.values()):
            item.setHidden(True)
        self._filterItem(self.algorithmTree.invisibleRootItem(),
                         [t for t in text.split(' ') if t])
        if text:
            self.algorithmTree.expandAll()
            self.disabledWithMatchingAlgs = []
            for provider in QgsApplication.processingRegistry().providers():
                if not provider.isActive():
                    for alg in provider.algorithms():
                        if text in alg.name():
                            self.disabledWithMatchingAlgs.append(provider.id())
                            break
            showTip = ProcessingConfig.getSetting(
                ProcessingConfig.SHOW_PROVIDERS_TOOLTIP)
            if showTip:
                self.txtDisabled.setVisible(bool(
                    self.disabledWithMatchingAlgs))

            if self.algorithmTree.currentItem(
            ) is None or self.algorithmTree.currentItem().isHidden():
                # if previously selected item was hidden, auto select the first visible algorithm
                first_visible = self._findFirstVisibleAlgorithm(
                    self.algorithmTree.invisibleRootItem())
                if first_visible is not None:
                    self.algorithmTree.setCurrentItem(first_visible)
        else:
            self.algorithmTree.collapseAll()
            self.algorithmTree.invisibleRootItem().child(0).setExpanded(True)
            self.txtDisabled.setVisible(False)
Ejemplo n.º 10
0
    def finish(self, successful, result, context, feedback):
        keepOpen = not successful or ProcessingConfig.getSetting(
            ProcessingConfig.KEEP_DIALOG_OPEN)

        if self.iterateParam is None:

            # add html results to results dock
            for out in self.algorithm().outputDefinitions():
                if isinstance(out, QgsProcessingOutputHtml) and out.name(
                ) in result and result[out.name()]:
                    resultsList.addResult(icon=self.algorithm().icon(),
                                          name=out.description(),
                                          timestamp=time.localtime(),
                                          result=result[out.name()])

            if not handleAlgorithmResults(self.algorithm(), context, feedback,
                                          not keepOpen):
                self.resetGui()
                return

        self.setExecuted(True)
        self.setResults(result)
        self.setInfo(self.tr('Algorithm \'{0}\' finished').format(
            self.algorithm().displayName()),
                     escapeHtml=False)

        if not keepOpen:
            self.close()
        else:
            self.resetGui()
            if self.algorithm().hasHtmlOutputs():
                self.setInfo(self.tr(
                    'HTML output has been generated by this algorithm.'
                    '\nOpen the results dialog to check it.'),
                             escapeHtml=False)
Ejemplo n.º 11
0
 def getRecentAlgorithms():
     recentAlgsSetting = ProcessingConfig.getSetting(
         ProcessingConfig.RECENT_ALGORITHMS)
     try:
         ProcessingLog.recentAlgs = recentAlgsSetting.split(';')
     except:
         pass
     return ProcessingLog.recentAlgs
    def disabledProviders(self):
        showTip = ProcessingConfig.getSetting(
            ProcessingConfig.SHOW_PROVIDERS_TOOLTIP)
        if not showTip or self.tipWasClosed:
            return False

        for provider in QgsApplication.processingRegistry().providers():
            if not provider.isActive():
                return True

        return False
    def grassPath():
        """
        Find GRASS path on the operating system.
        Sets global variable Grass7Utils.path
        """
        if Grass7Utils.path is not None:
            return Grass7Utils.path

        if not isWindows() and not isMac():
            return ''

        folder = ProcessingConfig.getSetting(Grass7Utils.GRASS_FOLDER) or ''
        if not os.path.exists(folder):
            folder = None

        if folder is None:
            # Under MS-Windows, we use OSGEO4W or QGIS Path for folder
            if isWindows():
                if "OSGEO4W_ROOT" in os.environ:
                    testfolder = os.path.join(str(os.environ['OSGEO4W_ROOT']),
                                              "apps")
                else:
                    testfolder = str(QgsApplication.prefixPath())
                testfolder = os.path.join(testfolder, 'grass')
                if os.path.isdir(testfolder):
                    for subfolder in os.listdir(testfolder):
                        if subfolder.startswith('grass-7'):
                            folder = os.path.join(testfolder, subfolder)
                            break
            elif isMac():
                # For MacOSX, we scan some well-known directories
                # Start with QGIS bundle
                for version in ['', '7', '70', '71', '72', '74']:
                    testfolder = os.path.join(str(QgsApplication.prefixPath()),
                                              'grass{}'.format(version))
                    if os.path.isdir(testfolder):
                        folder = testfolder
                        break
                    # If nothing found, try standalone GRASS installation
                    if folder is None:
                        for version in ['0', '1', '2', '4']:
                            testfolder = '/Applications/GRASS-7.{}.app/Contents/MacOS'.format(
                                version)
                            if os.path.isdir(testfolder):
                                folder = testfolder
                                break

        if folder is not None:
            Grass7Utils.path = folder

        return folder or ''
    def executeAlgorithm(self):
        item = self.algorithmTree.currentItem()
        if isinstance(item, TreeAlgorithmItem):
            alg = QgsApplication.processingRegistry().createAlgorithmById(
                item.alg.id())
            if not alg:
                return

            ok, message = alg.canExecute()
            if not ok:
                dlg = MessageDialog()
                dlg.setTitle(self.tr('Error executing algorithm'))
                dlg.setMessage(
                    self.tr('<h3>This algorithm cannot '
                            'be run :-( </h3>\n{0}').format(message))
                dlg.exec_()
                return

            if alg.countVisibleParameters() > 0:
                dlg = alg.createCustomParametersWidget(self)

                if not dlg:
                    dlg = AlgorithmDialog(alg)
                canvas = iface.mapCanvas()
                prevMapTool = canvas.mapTool()
                dlg.show()
                dlg.exec_()
                if canvas.mapTool() != prevMapTool:
                    try:
                        canvas.mapTool().reset()
                    except:
                        pass
                    canvas.setMapTool(prevMapTool)
                if dlg.wasExecuted():
                    showRecent = ProcessingConfig.getSetting(
                        ProcessingConfig.SHOW_RECENT_ALGORITHMS)
                    if showRecent:
                        self.addRecentAlgorithms(True)
            else:
                feedback = MessageBarProgress()
                context = dataobjects.createContext(feedback)
                parameters = {}
                ret, results = execute(alg, parameters, context, feedback)
                handleAlgorithmResults(alg, context, feedback)
                feedback.close()
    def selectFile(self):
        file_filter = getFileFilter(self.parameter)
        settings = QgsSettings()
        if isinstance(self.parameter, QgsProcessingParameterFeatureSink):
            last_ext_path = '/Processing/LastVectorOutputExt'
            last_ext = settings.value(last_ext_path, '.gpkg')
        elif isinstance(self.parameter,
                        QgsProcessingParameterRasterDestination):
            last_ext_path = '/Processing/LastRasterOutputExt'
            last_ext = settings.value(last_ext_path, '.tif')
        else:
            last_ext_path = None
            last_ext = None

        # get default filter
        filters = file_filter.split(';;')
        try:
            last_filter = [
                f for f in filters if '*{}'.format(last_ext) in f.lower()
            ][0]
        except:
            last_filter = None

        if settings.contains('/Processing/LastOutputPath'):
            path = settings.value('/Processing/LastOutputPath')
        else:
            path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER)

        filename, filter = QFileDialog.getSaveFileName(self,
                                                       self.tr("Save file"),
                                                       path, file_filter,
                                                       last_filter)
        if filename:
            self.use_temporary = False
            if not filename.lower().endswith(
                    tuple(re.findall("\\*(\\.[a-z]{1,10})", file_filter))):
                ext = re.search("\\*(\\.[a-z]{1,10})", filter)
                if ext:
                    filename += ext.group(1)
            self.leText.setText(filename)
            settings.setValue('/Processing/LastOutputPath',
                              os.path.dirname(filename))
            if not last_ext_path is None:
                settings.setValue(last_ext_path,
                                  os.path.splitext(filename)[1].lower())
Ejemplo n.º 16
0
 def useLayerExtent(self):
     CANVAS_KEY = 'Use canvas extent'
     extentsDict = {}
     extentsDict[CANVAS_KEY] = {"extent": iface.mapCanvas().extent(),
                                "authid": iface.mapCanvas().mapSettings().destinationCrs().authid()}
     extents = [CANVAS_KEY]
     layers = QgsProcessingUtils.compatibleLayers(QgsProject.instance())
     for layer in layers:
         authid = layer.crs().authid()
         if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF) \
                 and authid is not None:
             layerName = u'{} [{}]'.format(layer.name(), authid)
         else:
             layerName = layer.name()
         extents.append(layerName)
         extentsDict[layerName] = {"extent": layer.extent(), "authid": authid}
     (item, ok) = QInputDialog.getItem(self, self.tr('Select Extent'),
                                       self.tr('Use extent from'), extents, False)
     if ok:
         self.setValueFromRect(QgsReferencedRectangle(extentsDict[item]["extent"], QgsCoordinateReferenceSystem(extentsDict[item]["authid"])))
Ejemplo n.º 17
0
def createContext(feedback=None):
    """
    Creates a default processing context
    """
    context = QgsProcessingContext()
    context.setProject(QgsProject.instance())
    context.setFeedback(feedback)

    invalid_features_method = ProcessingConfig.getSetting(
        ProcessingConfig.FILTER_INVALID_GEOMETRIES)
    if invalid_features_method is None:
        invalid_features_method = QgsFeatureRequest.GeometryAbortOnInvalid
    context.setInvalidGeometryCheck(invalid_features_method)

    settings = QgsSettings()
    context.setDefaultEncoding(settings.value("/Processing/encoding",
                                              "System"))

    context.setExpressionContext(createExpressionContext())

    return context
    def saveToGeopackage(self):
        file_filter = self.tr('GeoPackage files (*.gpkg);;All files (*.*)',
                              'OutputFile')

        settings = QgsSettings()
        if settings.contains('/Processing/LastOutputPath'):
            path = settings.value('/Processing/LastOutputPath')
        else:
            path = ProcessingConfig.getSetting(ProcessingConfig.OUTPUT_FOLDER)

        filename, filter = QFileDialog.getSaveFileName(
            self,
            self.tr("Save to GeoPackage"),
            path,
            file_filter,
            options=QFileDialog.DontConfirmOverwrite)

        if not filename:
            return

        layer_name, ok = QInputDialog.getText(
            self,
            self.tr('Save to GeoPackage'),
            self.tr('Layer name'),
            text=self.parameter.name().lower())
        if ok:
            self.use_temporary = False
            if not filename.lower().endswith('.gpkg'):
                filename += '.gpkg'
            settings.setValue('/Processing/LastOutputPath',
                              os.path.dirname(filename))

            uri = QgsDataSourceUri()
            uri.setDatabase(filename)
            uri.setDataSource(
                '', layer_name, 'geom' if
                isinstance(self.parameter, QgsProcessingParameterFeatureSink)
                and self.parameter.hasGeometry() else None)
            self.leText.setText("ogr:" + uri.uri())
    def accept(self):
        keepOpen = ProcessingConfig.getSetting(
            ProcessingConfig.KEEP_DIALOG_OPEN)
        parameters = self.getParamValues()
        if parameters:
            with OverrideCursor(Qt.WaitCursor):
                self.feedback = FieldCalculatorFeedback(self)
                self.feedback.progressChanged.connect(self.setPercentage)

                context = dataobjects.createContext()
                ProcessingLog.addToLog(
                    self.alg.asPythonCommand(parameters, context))

                self.executed, results = execute(self.alg, parameters, context,
                                                 self.feedback)
                self.setPercentage(0)

                if self.executed:
                    handleAlgorithmResults(self.alg, context, self.feedback,
                                           not keepOpen)
                self._wasExecuted = self.executed or self._wasExecuted
                if not keepOpen:
                    QDialog.reject(self)
Ejemplo n.º 20
0
def scriptsFolders():
    folder = ProcessingConfig.getSetting(SCRIPTS_FOLDERS)
    if folder is not None:
        return folder.split(";")
    else:
        return [ScriptUtils.defaultScriptsFolder()]
Ejemplo n.º 21
0
 def modelsFolders():
     folder = ProcessingConfig.getSetting(ModelerUtils.MODELS_FOLDER)
     if folder is not None:
         return folder.split(';')
     else:
         return [ModelerUtils.defaultModelsFolder()]
    def executeGrass(commands, feedback, outputCommands=None):
        loglines = []
        loglines.append(Grass7Utils.tr('GRASS GIS 7 execution console output'))
        grassOutDone = False
        command, grassenv = Grass7Utils.prepareGrassExecution(commands)
        #QgsMessageLog.logMessage('exec: {}'.format(command), 'DEBUG', Qgis.Info)

        # For MS-Windows, we need to hide the console window.
        if isWindows():
            si = subprocess.STARTUPINFO()
            si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            si.wShowWindow = subprocess.SW_HIDE

        with subprocess.Popen(command,
                              shell=True if isMac() else False,
                              stdout=subprocess.PIPE,
                              stdin=subprocess.DEVNULL,
                              stderr=subprocess.STDOUT,
                              universal_newlines=True,
                              env=grassenv,
                              startupinfo=si if isWindows() else None) as proc:
            for line in iter(proc.stdout.readline, ''):
                if 'GRASS_INFO_PERCENT' in line:
                    try:
                        feedback.setProgress(
                            int(line[len('GRASS_INFO_PERCENT') + 2:]))
                    except:
                        pass
                else:
                    if 'r.out' in line or 'v.out' in line:
                        grassOutDone = True
                    loglines.append(line)
                    feedback.pushConsoleInfo(line)

        # Some GRASS scripts, like r.mapcalculator or r.fillnulls, call
        # other GRASS scripts during execution. This may override any
        # commands that are still to be executed by the subprocess, which
        # are usually the output ones. If that is the case runs the output
        # commands again.
        if not grassOutDone and outputCommands:
            command, grassenv = Grass7Utils.prepareGrassExecution(
                outputCommands)
            with subprocess.Popen(
                    command,
                    shell=True if isMac() else False,
                    stdout=subprocess.PIPE,
                    stdin=subprocess.DEVNULL,
                    stderr=subprocess.STDOUT,
                    universal_newlines=True,
                    env=grassenv,
                    startupinfo=si if isWindows() else None) as proc:
                for line in iter(proc.stdout.readline, ''):
                    if 'GRASS_INFO_PERCENT' in line:
                        try:
                            feedback.setProgress(
                                int(line[len('GRASS_INFO_PERCENT') + 2:]))
                        except:
                            pass
                    else:
                        loglines.append(line)
                        feedback.pushConsoleInfo(line)

        if ProcessingConfig.getSetting(Grass7Utils.GRASS_LOG_CONSOLE):
            QgsMessageLog.logMessage('\n'.join(loglines), 'Processing',
                                     Qgis.Info)
Ejemplo n.º 23
0
    def processAlgorithm(self, parameters, context, feedback):
        if isWindows():
            path = Grass7Utils.grassPath()
            if path == '':
                raise QgsProcessingException(
                    self.tr(
                        'GRASS GIS 7 folder is not configured. Please '
                        'configure it before running GRASS GIS 7 algorithms.'))

        # Create brand new commands lists
        self.commands = []
        self.outputCommands = []
        self.exportedLayers = {}

        # If GRASS session has been created outside of this algorithm then
        # get the list of layers loaded in GRASS otherwise start a new
        # session
        existingSession = Grass7Utils.sessionRunning
        if existingSession:
            self.exportedLayers = Grass7Utils.getSessionLayers()
        else:
            Grass7Utils.startGrassSession()

        # Handle default GRASS parameters
        self.grabDefaultGrassParameters(parameters, context)

        # Handle ext functions for inputs/command/outputs
        for fName in ['Inputs', 'Command', 'Outputs']:
            fullName = 'process{}'.format(fName)
            if self.module and hasattr(self.module, fullName):
                getattr(self.module, fullName)(self, parameters, context,
                                               feedback)
            else:
                getattr(self, fullName)(parameters, context, feedback)

        # Run GRASS
        loglines = []
        loglines.append(self.tr('GRASS GIS 7 execution commands'))
        for line in self.commands:
            feedback.pushCommandInfo(line)
            loglines.append(line)
        if ProcessingConfig.getSetting(Grass7Utils.GRASS_LOG_COMMANDS):
            QgsMessageLog.logMessage("\n".join(loglines),
                                     self.tr('Processing'), Qgis.Info)

        Grass7Utils.executeGrass(self.commands, feedback, self.outputCommands)

        # If the session has been created outside of this algorithm, add
        # the new GRASS GIS 7 layers to it otherwise finish the session
        if existingSession:
            Grass7Utils.addSessionLayers(self.exportedLayers)
        else:
            Grass7Utils.endGrassSession()

        # Return outputs map
        outputs = {}
        for out in self.outputDefinitions():
            outName = out.name()
            if outName in parameters:
                outputs[outName] = parameters[outName]
                if isinstance(out, QgsProcessingOutputHtml):
                    self.convertToHtml(parameters[outName])

        return outputs
    def processAlgorithm(self, parameters, context, feedback):
        commands = list()
        self.exportedLayers = {}

        self.preProcessInputs()
        extent = None
        crs = None

        # 1: Export rasters to sgrd and vectors to shp
        # Tables must be in dbf format. We check that.
        for param in self.parameterDefinitions():
            if isinstance(param, QgsProcessingParameterRasterLayer):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue

                if isinstance(parameters[param.name()], str):
                    if parameters[param.name()].lower().endswith('sdat'):
                        self.exportedLayers[param.name(
                        )] = parameters[param.name()][:-4] + 'sgrd'
                    if parameters[param.name()].lower().endswith('sgrd'):
                        self.exportedLayers[param.name()] = parameters[
                            param.name()]
                    else:
                        layer = self.parameterAsRasterLayer(
                            parameters, param.name(), context)
                        exportCommand = self.exportRasterLayer(
                            param.name(), layer)
                        if exportCommand is not None:
                            commands.append(exportCommand)
                else:
                    if parameters[param.name()].source().lower().endswith(
                            'sdat'):
                        self.exportedLayers[param.name(
                        )] = parameters[param.name()].source()[:-4] + 'sgrd'
                    if parameters[param.name()].source().lower().endswith(
                            'sgrd'):
                        self.exportedLayers[param.name()] = parameters[
                            param.name()].source()
                    else:
                        exportCommand = self.exportRasterLayer(
                            param.name(), parameters[param.name()])
                        if exportCommand is not None:
                            commands.append(exportCommand)
            elif isinstance(param, QgsProcessingParameterFeatureSource):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue

                if not crs:
                    source = self.parameterAsSource(parameters, param.name(),
                                                    context)
                    crs = source.sourceCrs()

                layer_path = self.parameterAsCompatibleSourceLayerPath(
                    parameters,
                    param.name(),
                    context, ['shp'],
                    'shp',
                    feedback=feedback)
                if layer_path:
                    self.exportedLayers[param.name()] = layer_path
                else:
                    raise QgsProcessingException(
                        self.tr('Unsupported file format'))
            elif isinstance(param, QgsProcessingParameterMultipleLayers):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue

                layers = self.parameterAsLayerList(parameters, param.name(),
                                                   context)
                if layers is None or len(layers) == 0:
                    continue
                if param.layerType() == QgsProcessing.TypeRaster:
                    files = []
                    for i, layer in enumerate(layers):
                        if layer.source().lower().endswith('sdat'):
                            files.append(
                                parameters[param.name()].source()[:-4] +
                                'sgrd')
                        if layer.source().lower().endswith('sgrd'):
                            files.append(parameters[param.name()].source())
                        else:
                            exportCommand = self.exportRasterLayer(
                                param.name(), layer)
                            files.append(self.exportedLayers[param.name()])
                            if exportCommand is not None:
                                commands.append(exportCommand)

                    self.exportedLayers[param.name()] = files
                else:
                    temp_params = deepcopy(parameters)
                    for layer in layers:
                        temp_params[param.name()] = layer

                        if not crs:
                            source = self.parameterAsSource(
                                temp_params, param.name(), context)
                            crs = source.sourceCrs()

                        layer_path = self.parameterAsCompatibleSourceLayerPath(
                            temp_params,
                            param.name(),
                            context,
                            'shp',
                            feedback=feedback)
                        if layer_path:
                            if param.name() in self.exportedLayers:
                                self.exportedLayers[param.name()].append(
                                    layer_path)
                            else:
                                self.exportedLayers[param.name()] = [
                                    layer_path
                                ]
                        else:
                            raise QgsProcessingException(
                                self.tr('Unsupported file format'))

        # 2: Set parameters and outputs
        command = self.undecorated_group + ' "' + self.cmdname + '"'
        command += ' ' + ' '.join(self.hardcoded_strings)

        for param in self.parameterDefinitions():
            if not param.name() in parameters or parameters[
                    param.name()] is None:
                continue
            if param.isDestination():
                continue

            if isinstance(param, (QgsProcessingParameterRasterLayer,
                                  QgsProcessingParameterFeatureSource)):
                command += ' -{} "{}"'.format(
                    param.name(), self.exportedLayers[param.name()])
            elif isinstance(param, QgsProcessingParameterMultipleLayers):
                command += ' -{} "{}"'.format(
                    param.name(), ';'.join(self.exportedLayers[param.name()]))
            elif isinstance(param, QgsProcessingParameterBoolean):
                if self.parameterAsBool(parameters, param.name(), context):
                    command += ' -{} true'.format(param.name().strip())
                else:
                    command += ' -{} false'.format(param.name().strip())
            elif isinstance(param, QgsProcessingParameterMatrix):
                tempTableFile = getTempFilename('txt')
                with open(tempTableFile, 'w') as f:
                    f.write('\t'.join([col for col in param.headers()]) + '\n')
                    values = self.parameterAsMatrix(parameters, param.name(),
                                                    context)
                    for i in range(0, len(values), 3):
                        s = values[i] + '\t' + values[i + 1] + '\t' + values[
                            i + 2] + '\n'
                        f.write(s)
                command += ' -{} "{}"'.format(param.name(), tempTableFile)
            elif isinstance(param, QgsProcessingParameterExtent):
                # 'We have to substract/add half cell size, since SAGA is
                # center based, not corner based
                halfcell = self.getOutputCellsize(parameters, context) / 2
                offset = [halfcell, -halfcell, halfcell, -halfcell]
                rect = self.parameterAsExtent(parameters, param.name(),
                                              context)

                values = []
                values.append(rect.xMinimum())
                values.append(rect.xMaximum())
                values.append(rect.yMinimum())
                values.append(rect.yMaximum())

                for i in range(4):
                    command += ' -{} {}'.format(self.extentParamNames[i],
                                                float(values[i]) + offset[i])
            elif isinstance(param, QgsProcessingParameterNumber):
                if param.dataType() == QgsProcessingParameterNumber.Integer:
                    command += ' -{} {}'.format(
                        param.name(),
                        self.parameterAsInt(parameters, param.name(), context))
                else:
                    command += ' -{} {}'.format(
                        param.name(),
                        self.parameterAsDouble(parameters, param.name(),
                                               context))
            elif isinstance(param, QgsProcessingParameterEnum):
                command += ' -{} {}'.format(
                    param.name(),
                    self.parameterAsEnum(parameters, param.name(), context))
            elif isinstance(
                    param,
                (QgsProcessingParameterString, QgsProcessingParameterFile)):
                command += ' -{} "{}"'.format(
                    param.name(),
                    self.parameterAsFile(parameters, param.name(), context))
            elif isinstance(
                    param,
                (QgsProcessingParameterString, QgsProcessingParameterField)):
                command += ' -{} "{}"'.format(
                    param.name(),
                    self.parameterAsString(parameters, param.name(), context))

        output_layers = []
        output_files = {}
        for out in self.destinationParameterDefinitions():
            filePath = self.parameterAsOutputLayer(parameters, out.name(),
                                                   context)
            if isinstance(out, (QgsProcessingParameterRasterDestination,
                                QgsProcessingParameterVectorDestination)):
                output_layers.append(filePath)
            output_files[out.name()] = filePath
            command += ' -{} "{}"'.format(out.name(), filePath)

        commands.append(command)

        # special treatment for RGB algorithm
        # TODO: improve this and put this code somewhere else
        for out in self.destinationParameterDefinitions():
            if isinstance(out, QgsProcessingParameterRasterDestination):
                filename = self.parameterAsOutputLayer(parameters, out.name(),
                                                       context)
                filename2 = os.path.splitext(filename)[0] + '.sgrd'
                if self.cmdname == 'RGB Composite':
                    commands.append(
                        'io_grid_image 0 -IS_RGB -GRID:"{}" -FILE:"{}"'.format(
                            filename2, filename))

        # 3: Run SAGA
        commands = self.editCommands(commands)
        SagaUtils.createSagaBatchJobFileFromSagaCommands(commands)
        loglines = []
        loglines.append(self.tr('SAGA execution commands'))
        for line in commands:
            feedback.pushCommandInfo(line)
            loglines.append(line)
        if ProcessingConfig.getSetting(SagaUtils.SAGA_LOG_COMMANDS):
            QgsMessageLog.logMessage('\n'.join(loglines),
                                     self.tr('Processing'), Qgis.Info)
        SagaUtils.executeSaga(feedback)

        if crs is not None:
            for out in output_layers:
                prjFile = os.path.splitext(out)[0] + '.prj'
                with open(prjFile, 'w') as f:
                    f.write(crs.toWkt())

        result = {}
        for o in self.outputDefinitions():
            if o.name() in output_files:
                result[o.name()] = output_files[o.name()]
        return result
 def isActive(self):
     return ProcessingConfig.getSetting('ACTIVATE_GRASS7')
Ejemplo n.º 26
0
 def isActive(self):
     """Return True if the provider is activated and ready to run algorithms"""
     return ProcessingConfig.getSetting('ACTIVATE_EXAMPLE')
Ejemplo n.º 27
0
def removeMenus():
    for alg in QgsApplication.processingRegistry().algorithms():
        menuPath = ProcessingConfig.getSetting("MENU_" + alg.id())
        if menuPath:
            paths = menuPath.split("/")
            removeAlgorithmEntry(alg, paths[0], paths[-1])
Ejemplo n.º 28
0
    def accept(self):
        feedback = self.createFeedback()
        context = dataobjects.createContext(feedback)

        checkCRS = ProcessingConfig.getSetting(
            ProcessingConfig.WARN_UNMATCHING_CRS)
        try:
            parameters = self.getParameterValues()

            if checkCRS and not self.algorithm().validateInputCrs(
                    parameters, context):
                reply = QMessageBox.question(
                    self, self.tr("Unmatching CRS's"),
                    self.tr('Parameters do not all use the same CRS. This can '
                            'cause unexpected results.\nDo you want to '
                            'continue?'), QMessageBox.Yes | QMessageBox.No,
                    QMessageBox.No)
                if reply == QMessageBox.No:
                    return
            ok, msg = self.algorithm().checkParameterValues(
                parameters, context)
            if msg:
                QMessageBox.warning(self,
                                    self.tr('Unable to execute algorithm'),
                                    msg)
                return
            self.runButton().setEnabled(False)
            self.cancelButton().setEnabled(False)
            buttons = self.mainWidget().iterateButtons
            self.iterateParam = None

            for i in range(len(list(buttons.values()))):
                button = list(buttons.values())[i]
                if button.isChecked():
                    self.iterateParam = list(buttons.keys())[i]
                    break

            self.clearProgress()
            self.setProgressText(
                QCoreApplication.translate('AlgorithmDialog',
                                           'Processing algorithm…'))

            self.setInfo(
                self.tr('AlgorithmDialog',
                        '<b>Algorithm \'{0}\' starting&hellip;</b>').format(
                            self.algorithm().displayName()),
                escapeHtml=False)

            feedback.pushInfo(self.tr('Input parameters:'))
            display_params = []
            for k, v in parameters.items():
                display_params.append("'" + k + "' : " +
                                      self.algorithm().parameterDefinition(
                                          k).valueAsPythonString(v, context))
            feedback.pushCommandInfo('{ ' + ', '.join(display_params) + ' }')
            feedback.pushInfo('')
            start_time = time.time()

            if self.iterateParam:
                # Make sure the Log tab is visible before executing the algorithm
                try:
                    self.showLog()
                    self.repaint()
                except:
                    pass

                self.cancelButton().setEnabled(
                    self.algorithm().flags()
                    & QgsProcessingAlgorithm.FlagCanCancel)
                if executeIterating(self.algorithm(), parameters,
                                    self.iterateParam, context, feedback):
                    feedback.pushInfo(
                        self.tr(
                            'Execution completed in {0:0.2f} seconds'.format(
                                time.time() - start_time)))
                    self.cancelButton().setEnabled(False)
                    self.finish(True, parameters, context, feedback)
                else:
                    self.cancelButton().setEnabled(False)
                    self.resetGui()
            else:
                command = self.algorithm().asPythonCommand(parameters, context)
                if command:
                    ProcessingLog.addToLog(command)
                self.cancelButton().setEnabled(
                    self.algorithm().flags()
                    & QgsProcessingAlgorithm.FlagCanCancel)

                def on_complete(ok, results):
                    if ok:
                        feedback.pushInfo(
                            self.tr('Execution completed in {0:0.2f} seconds'.
                                    format(time.time() - start_time)))
                        feedback.pushInfo(self.tr('Results:'))
                        feedback.pushCommandInfo(pformat(results))
                    else:
                        feedback.reportError(
                            self.tr('Execution failed after {0:0.2f} seconds'.
                                    format(time.time() - start_time)))
                    feedback.pushInfo('')

                    if self.feedback_dialog is not None:
                        self.feedback_dialog.close()
                        self.feedback_dialog.deleteLater()
                        self.feedback_dialog = None

                    self.cancelButton().setEnabled(False)

                    self.finish(ok, results, context, feedback)

                if not (self.algorithm().flags()
                        & QgsProcessingAlgorithm.FlagNoThreading):
                    # Make sure the Log tab is visible before executing the algorithm
                    self.showLog()

                    task = QgsProcessingAlgRunnerTask(self.algorithm(),
                                                      parameters, context,
                                                      feedback)
                    task.executed.connect(on_complete)
                    self.setCurrentTask(task)
                else:
                    self.feedback_dialog = self.createProgressDialog()
                    self.feedback_dialog.show()
                    ok, results = execute(self.algorithm(), parameters,
                                          context, feedback)
                    on_complete(ok, results)

        except AlgorithmDialogBase.InvalidParameterValue as e:
            try:
                self.buttonBox().accepted.connect(
                    lambda e=e: e.widget.setPalette(QPalette()))
                palette = e.widget.palette()
                palette.setColor(QPalette.Base, QColor(255, 255, 0))
                e.widget.setPalette(palette)
            except:
                pass
            self.messageBar().clearWidgets()
            self.messageBar().pushMessage(
                "",
                self.tr("Wrong or missing parameter value: {0}").format(
                    e.parameter.description()),
                level=Qgis.Warning,
                duration=5)