3

I try to run a qgis native algorithm in a qgis plugin and I can't make it work. I follow espescially this answer on a GIS SE question. I will add my whole code at the end of the question, since I do not know where the fault is located at and I'm new to pyqgis.

If I start my plugin I can add a vectorlayer from the layerslist and choose the output destination. Those are supposed to be the input and output of the algorithm. But when I run it I just get an errormessage from QGIS, but the errorlog contains no python errors, even though it says so. So I am stuck at that point. On top of it, after closing QGIS, the desktop shortcut didn't work anymore, because the .exe was not found (it was supposed to be located at C:\OSGeo4W64\bin, but it is not anymore. It seems to be deleted somehow).

Heres the code. At first I import everything, what I think is needed and with the function "IntersectionsToNodes" I try running the algorithm. I use QGIS 3.2.

import os.path
import sys

from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QAction, QFileDialog
from qgis.core import *
from qgis.analysis import QgsNativeAlgorithms

#Access the processing algorithm
QgsApplication.setPrefixPath('C:/OSGeo4W64/apps/qgis', True)
qgs = QgsApplication([],False)
qgs.initQgis()

#Folder location of processing plugin
sys.path.append('C:/OSGeo4W64/apps/qgis/python/plugins')

import processing
from processing.core.Processing import Processing
Processing.initialize()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())

# Initialize Qt resources from file resources.py
# Import the code for the dialog
from .befahrungsplanung_dialog import BefahrungsplanungDialog


class Befahrungsplanung:
    """QGIS Plugin Implementation."""

def __init__(self, iface):
    """Constructor.

    :param iface: An interface instance that will be passed to this class
        which provides the hook by which you can manipulate the QGIS
        application at run time.
    :type iface: QgsInterface
    """
    # Save reference to the QGIS interface
    self.iface = iface
    # initialize plugin directory
    self.plugin_dir = os.path.dirname(__file__)
    # initialize locale
    locale = QSettings().value('locale/userLocale')[0:2]
    locale_path = os.path.join(
        self.plugin_dir,
        'i18n',
        'Befahrungsplanung_{}.qm'.format(locale))

    if os.path.exists(locale_path):
        self.translator = QTranslator()
        self.translator.load(locale_path)

        if qVersion() > '4.3.3':
            QCoreApplication.installTranslator(self.translator)

    # Create the dialog (after translation) and keep reference
    self.dlg = BefahrungsplanungDialog()

    # Declare instance attributes
    self.actions = []
    self.menu = self.tr(u'&Befahrungsplanung')
    # TODO: We are going to let the user set this up in a future iteration
    self.toolbar = self.iface.addToolBar(u'Befahrungsplanung')
    self.toolbar.setObjectName(u'Befahrungsplanung')

    self.dlg.directory.clear()
    self.dlg.push_directory.clicked.connect(self.output)
    self.dlg.button_box.clicked.connect(self.IntersectionsToNodes)

# noinspection PyMethodMayBeStatic
def tr(self, message):
    """Get the translation for a string using Qt translation API.

    We implement this ourselves since we do not inherit QObject.

    :param message: String for translation.
    :type message: str, QString

    :returns: Translated version of message.
    :rtype: QString
    """
    # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
    return QCoreApplication.translate('Befahrungsplanung', message)

def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
    """Add a toolbar icon to the toolbar.

    :param icon_path: Path to the icon for this action. Can be a resource
        path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
    :type icon_path: str

    :param text: Text that should be shown in menu items for this action.
    :type text: str

    :param callback: Function to be called when the action is triggered.
    :type callback: function

    :param enabled_flag: A flag indicating if the action should be enabled
        by default. Defaults to True.
    :type enabled_flag: bool

    :param add_to_menu: Flag indicating whether the action should also
        be added to the menu. Defaults to True.
    :type add_to_menu: bool

    :param add_to_toolbar: Flag indicating whether the action should also
        be added to the toolbar. Defaults to True.
    :type add_to_toolbar: bool

    :param status_tip: Optional text to show in a popup when mouse pointer
        hovers over the action.
    :type status_tip: str

    :param parent: Parent widget for the new action. Defaults None.
    :type parent: QWidget

    :param whats_this: Optional text to show in the status bar when the
        mouse pointer hovers over the action.

    :returns: The action that was created. Note that the action is also
        added to self.actions list.
    :rtype: QAction
    """

    icon = QIcon(icon_path)
    action = QAction(icon, text, parent)
    action.triggered.connect(callback)
    action.setEnabled(enabled_flag)

    if status_tip is not None:
        action.setStatusTip(status_tip)

    if whats_this is not None:
        action.setWhatsThis(whats_this)

    if add_to_toolbar:
        self.toolbar.addAction(action)

    if add_to_menu:
        self.iface.addPluginToMenu(
            self.menu,
            action)

    self.actions.append(action)

    return action

def initGui(self):
    """Create the menu entries and toolbar icons inside the QGIS GUI."""

    icon_path = ':/plugins/befahrungsplanung/icon.png'
    self.add_action(
        icon_path,
        text=self.tr(u'Befahrungsplanung'),
        callback=self.run,
        parent=self.iface.mainWindow())
    self.layerlist()

def unload(self):
    """Removes the plugin menu item and icon from QGIS GUI."""
    for action in self.actions:
        self.iface.removePluginMenu(
            self.tr(u'&Befahrungsplanung'),
            action)
        self.iface.removeToolBarIcon(action)
    # remove the toolbar
    del self.toolbar

def run(self):
    """Run method that performs all the real work"""
    # show the dialog
    self.dlg.show()
    # Run the dialog event loop
    result = self.dlg.exec_()
    # See if OK was pressed
    if result:
        # Do something useful here - delete the line containing pass and
        # substitute with your code.
        pass

def layerlist(self):
    """Load all linevector layers"""
    self.dlg.layerlist.clear()
    layers = [layer for layer in QgsProject.instance().mapLayers().values()]
    vector_layers = []
    for layer in layers:
        if layer.type() == QgsMapLayer.VectorLayer and layer.geometryType() == QgsWkbTypes.LineGeometry:
            vector_layers.append(layer.name())
    self.dlg.layerlist.addItems(vector_layers)

def output(self):
    """Choose Shapefile or Geopackage as Output File"""
    filename = str(QFileDialog.getSaveFileName(self.dlg,
                                                "Output Datei auswählen ",
                                                "",
                                                "shapefile (*.shp);;geopackage (*.gpkg)")[0])
    self.dlg.directory.setText(filename)

def IntersectionsToNodes(self):
    """Transforms all intersections in the selected layer into nodes"""

    layers = self.iface.legendInterface().layers()
    inputIndex = self.dlg.layerlist.currentIndex()
    input = layers[inputIndex]

    filename = self.dlg.directory.text()
    output = open(filename, 'w')

    params = {
        'INPUT' : input,
        'LINES' : input,
        'OUTPUT' : output
    }

    res = processing.run('native:splitwithlines', params)
    res['OUTPUT']
    #processing.algorithmHelp("qgis:splitwithlines")

1 Answer 1

3

I found a solution to my own question. I made it way too complicated in the beginning.

If you are working in the QGIS interface (as I do with a plugin for QGIS), all you have to do is to import processing to make the QGIS native algorithms work. I added the whole reworked and working code for comparrison issues.

import os.path
from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QAction, QFileDialog
from qgis.core import *
import processing

# Initialize Qt resources from file resources.py
# Import the code for the dialog
from .befahrungsplanung_dialog import BefahrungsplanungDialog


class Befahrungsplanung:
"""QGIS Plugin Implementation."""

def __init__(self, iface):
    """Constructor.

    :param iface: An interface instance that will be passed to this class
        which provides the hook by which you can manipulate the QGIS
        application at run time.
    :type iface: QgsInterface
    """
    # Save reference to the QGIS interface
    self.iface = iface
    # initialize plugin directory
    self.plugin_dir = os.path.dirname(__file__)
    # initialize locale
    locale = QSettings().value('locale/userLocale')[0:2]
    locale_path = os.path.join(
        self.plugin_dir,
        'i18n',
        'Befahrungsplanung_{}.qm'.format(locale))

    if os.path.exists(locale_path):
        self.translator = QTranslator()
        self.translator.load(locale_path)

        if qVersion() > '4.3.3':
            QCoreApplication.installTranslator(self.translator)

    # Create the dialog (after translation) and keep reference
    self.dlg = BefahrungsplanungDialog()

    # Declare instance attributes
    self.actions = []
    self.menu = self.tr(u'&Befahrungsplanung')
    # TODO: We are going to let the user set this up in a future iteration
    self.toolbar = self.iface.addToolBar(u'Befahrungsplanung')
    self.toolbar.setObjectName(u'Befahrungsplanung')

    self.dlg.directory.clear()
    self.dlg.push_directory.clicked.connect(self.output)
    self.dlg.button_box.clicked.connect(self.IntersectionsToNodes)

# noinspection PyMethodMayBeStatic
def tr(self, message):
    """Get the translation for a string using Qt translation API.

    We implement this ourselves since we do not inherit QObject.

    :param message: String for translation.
    :type message: str, QString

    :returns: Translated version of message.
    :rtype: QString
    """
    # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
    return QCoreApplication.translate('Befahrungsplanung', message)

def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None):
    """Add a toolbar icon to the toolbar.

    :param icon_path: Path to the icon for this action. Can be a resource
        path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
    :type icon_path: str

    :param text: Text that should be shown in menu items for this action.
    :type text: str

    :param callback: Function to be called when the action is triggered.
    :type callback: function

    :param enabled_flag: A flag indicating if the action should be enabled
        by default. Defaults to True.
    :type enabled_flag: bool

    :param add_to_menu: Flag indicating whether the action should also
        be added to the menu. Defaults to True.
    :type add_to_menu: bool

    :param add_to_toolbar: Flag indicating whether the action should also
        be added to the toolbar. Defaults to True.
    :type add_to_toolbar: bool

    :param status_tip: Optional text to show in a popup when mouse pointer
        hovers over the action.
    :type status_tip: str

    :param parent: Parent widget for the new action. Defaults None.
    :type parent: QWidget

    :param whats_this: Optional text to show in the status bar when the
        mouse pointer hovers over the action.

    :returns: The action that was created. Note that the action is also
        added to self.actions list.
    :rtype: QAction
    """

    icon = QIcon(icon_path)
    action = QAction(icon, text, parent)
    action.triggered.connect(callback)
    action.setEnabled(enabled_flag)

    if status_tip is not None:
        action.setStatusTip(status_tip)

    if whats_this is not None:
        action.setWhatsThis(whats_this)

    if add_to_toolbar:
        self.toolbar.addAction(action)

    if add_to_menu:
        self.iface.addPluginToMenu(
            self.menu,
            action)

    self.actions.append(action)

    return action

def initGui(self):
    """Create the menu entries and toolbar icons inside the QGIS GUI."""

    icon_path = ':/plugins/befahrungsplanung/icon.png'
    self.add_action(
        icon_path,
        text=self.tr(u'Befahrungsplanung'),
        callback=self.run,
        parent=self.iface.mainWindow())
    self.layerlist()

def unload(self):
    """Removes the plugin menu item and icon from QGIS GUI."""
    for action in self.actions:
        self.iface.removePluginMenu(
            self.tr(u'&Befahrungsplanung'),
            action)
        self.iface.removeToolBarIcon(action)
    # remove the toolbar
    del self.toolbar

def run(self):
    """Run method that performs all the real work"""
    # show the dialog
    self.dlg.show()
    # Run the dialog event loop
    result = self.dlg.exec_()
    # See if OK was pressed
    if result:
        # Do something useful here - delete the line containing pass and
        # substitute with your code.
        pass

def layerlist(self):
    """Load all linevector layers"""
    self.dlg.layerlist.clear()
    layers = [layer for layer in QgsProject.instance().mapLayers().values()]
    vector_layers = []
    for layer in layers:
        if layer.type() == QgsMapLayer.VectorLayer and layer.geometryType() == QgsWkbTypes.LineGeometry:
            vector_layers.append(layer.name())
    self.dlg.layerlist.addItems(vector_layers)

def output(self):
    """Choose Shapefile or Geopackage as Output File"""
    filename = str(QFileDialog.getSaveFileName(self.dlg,
                                                "Output Datei auswählen ",
                                                "",
                                                "shapefile (*.shp);;geopackage (*.gpkg)")[0])
    self.dlg.directory.setText(filename)

def IntersectionsToNodes(self):
    """Transforms all intersections of the selected layer in the function layerslist into nodes"""

    layers = [layer for layer in QgsProject.instance().mapLayers().values()]
    inputIndex = self.dlg.layerlist.currentIndex()
    input = layers[inputIndex]

    output = self.dlg.directory.text()

    params = {
        'INPUT' : input,
        'LINES' : input,
        'OUTPUT' : output
    }

    res = processing.run('native:splitwithlines', params)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.