Skip to content
Permalink
Browse files
Move more algList functionality to QgsProcessingRegistry
  • Loading branch information
nyalldawson committed Apr 7, 2017
1 parent 2a1a715 commit 4970bb4cd5a0d265a8cc19482b14f6e7ee8570d0
Showing with 218 additions and 210 deletions.
  1. +1 −1 doc/api_break.dox
  2. +13 −0 python/core/processing/qgsprocessingregistry.sip
  3. +16 −15 python/plugins/processing/algs/gdal/GdalAlgorithmProvider.py
  4. +3 −1 python/plugins/processing/algs/grass7/Grass7AlgorithmProvider.py
  5. +3 −1 python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
  6. +5 −2 python/plugins/processing/algs/r/RAlgorithmProvider.py
  7. +6 −2 python/plugins/processing/algs/saga/SagaAlgorithmProvider.py
  8. +1 −3 python/plugins/processing/core/AlgorithmProvider.py
  9. +16 −35 python/plugins/processing/core/Processing.py
  10. +0 −20 python/plugins/processing/core/alglist.py
  11. +4 −5 python/plugins/processing/gui/CommanderWindow.py
  12. +3 −4 python/plugins/processing/gui/ConfigDialog.py
  13. +38 −39 python/plugins/processing/gui/ProcessingToolbox.py
  14. +2 −1 python/plugins/processing/gui/TestTools.py
  15. +16 −19 python/plugins/processing/gui/menus.py
  16. +2 −3 python/plugins/processing/modeler/ModelerAlgorithm.py
  17. +5 −1 python/plugins/processing/modeler/ModelerAlgorithmProvider.py
  18. +5 −8 python/plugins/processing/modeler/ModelerDialog.py
  19. +3 −3 python/plugins/processing/preconfigured/PreconfiguredAlgorithm.py
  20. +5 −1 python/plugins/processing/preconfigured/PreconfiguredAlgorithmProvider.py
  21. +5 −4 python/plugins/processing/script/ScriptAlgorithmProvider.py
  22. +1 −1 python/plugins/processing/script/ScriptSelector.py
  23. +5 −2 python/plugins/processing/tests/AlgorithmsTestBase.py
  24. +8 −37 python/plugins/processing/tools/general.py
  25. +2 −1 python/plugins/processing/tools/help.py
  26. +2 −1 python/plugins/processing/tools/translation.py
  27. +23 −0 src/core/processing/qgsprocessingregistry.cpp
  28. +13 −0 src/core/processing/qgsprocessingregistry.h
  29. +12 −0 tests/src/core/testqgsprocessing.cpp
@@ -2169,7 +2169,7 @@ need to update their use of the progress argument to utilize the QgsProcessingFe
- Similarly, Python processing scripts no longer have access to a progress variable for reporting their progress. Instead they have a feedback
object of type QgsProcessingFeedback, and will need to adapt their use of progress reporting to the QgsProcessingFeedback API.
- SilentProgress was removed. Use the base QgsProcessingFeedback class instead.

- Processing.algs was removed. QgsApplication.processingRegistry().algorithms() instead.

Triangulation {#qgis_api_break_3_0_Triangulation}
-------------
@@ -67,6 +67,19 @@ class QgsProcessingRegistry : QObject
Returns a matching provider by provider ID.
%End

QList< QgsProcessingAlgorithm * > algorithms() const;
%Docstring
Returns a list of all available algorithms from registered providers.
\see algorithmById()
%End

QgsProcessingAlgorithm * algorithmById( const QString& id ) const;
%Docstring
Finds an algorithm by its ID. If no matching algorithm is found, a nullptr
is returned.
\see algorithms()
%End

signals:

void providerAdded( const QString &id );
@@ -98,6 +98,7 @@ class GdalAlgorithmProvider(AlgorithmProvider):

def __init__(self):
super().__init__()
self.algs = []

def load(self):
AlgorithmProvider.load(self)
@@ -126,21 +127,21 @@ def svgIconPath(self):
return QgsApplication.iconPath("providerGdal.svg")

def loadAlgorithms(self):
algs = [nearblack(), information(), warp(), translate(),
rgb2pct(), pct2rgb(), merge(), buildvrt(), polygonize(), gdaladdo(),
ClipByExtent(), ClipByMask(), contour(), rasterize(), proximity(),
sieve(), fillnodata(), ExtractProjection(), gdal2xyz(),
hillshade(), slope(), aspect(), tri(), tpi(), roughness(),
ColorRelief(), GridInvDist(), GridAverage(), GridNearest(),
GridDataMetrics(), gdaltindex(), gdalcalc(), rasterize_over(),
retile(), gdal2tiles(), AssignProjection(),
# ----- OGR tools -----
OgrInfo(), Ogr2Ogr(), Ogr2OgrClip(), Ogr2OgrClipExtent(),
Ogr2OgrToPostGis(), Ogr2OgrToPostGisList(), Ogr2OgrPointsOnLines(),
Ogr2OgrBuffer(), Ogr2OgrDissolve(), OneSideBuffer(),
OffsetCurve(), Ogr2OgrTableToPostGisList(), OgrSql(),
]
for a in algs:
self.algs = [nearblack(), information(), warp(), translate(),
rgb2pct(), pct2rgb(), merge(), buildvrt(), polygonize(), gdaladdo(),
ClipByExtent(), ClipByMask(), contour(), rasterize(), proximity(),
sieve(), fillnodata(), ExtractProjection(), gdal2xyz(),
hillshade(), slope(), aspect(), tri(), tpi(), roughness(),
ColorRelief(), GridInvDist(), GridAverage(), GridNearest(),
GridDataMetrics(), gdaltindex(), gdalcalc(), rasterize_over(),
retile(), gdal2tiles(), AssignProjection(),
# ----- OGR tools -----
OgrInfo(), Ogr2Ogr(), Ogr2OgrClip(), Ogr2OgrClipExtent(),
Ogr2OgrToPostGis(), Ogr2OgrToPostGisList(), Ogr2OgrPointsOnLines(),
Ogr2OgrBuffer(), Ogr2OgrDissolve(), OneSideBuffer(),
OffsetCurve(), Ogr2OgrTableToPostGisList(), OgrSql(),
]
for a in self.algs:
self.addAlgorithm(a)

def supportedOutputRasterLayerExtensions(self):
@@ -44,6 +44,7 @@ class Grass7AlgorithmProvider(AlgorithmProvider):

def __init__(self):
super().__init__()
self.algs = []

def load(self):
AlgorithmProvider.load(self)
@@ -96,7 +97,8 @@ def createAlgsList(self):
return algs

def loadAlgorithms(self):
for a in self.createAlgsList():
self.algs = self.createAlgsList()
for a in self.algs:
self.addAlgorithm(a)

def name(self):
@@ -192,6 +192,7 @@ class QGISAlgorithmProvider(AlgorithmProvider):

def __init__(self):
super().__init__()
self.algs = []
self.externalAlgs = []

def getAlgs(self):
@@ -291,7 +292,8 @@ def svgIconPath(self):
return QgsApplication.iconPath("providerQgis.svg")

def loadAlgorithms(self):
for a in self.getAlgs():
self.algs = self.getAlgs()
for a in self.algs:
self.addAlgorithm(a)
for a in self.externalAlgs:
self.addAlgorithm(a)
@@ -50,6 +50,7 @@ class RAlgorithmProvider(AlgorithmProvider):

def __init__(self):
super().__init__()
self.algs = []
self.activate = False
self.actions.append(CreateNewScriptAction(
'Create new R script', CreateNewScriptAction.SCRIPT_R))
@@ -100,12 +101,14 @@ def id(self):

def loadAlgorithms(self):
folders = RUtils.RScriptsFolders()

self.algs = []
for f in folders:
self.loadFromFolder(f)

folder = os.path.join(os.path.dirname(__file__), 'scripts')
self.loadFromFolder(folder)
for a in self.algs:
self.addAlgorithm(a)

def loadFromFolder(self, folder):
if not os.path.exists(folder):
@@ -117,7 +120,7 @@ def loadFromFolder(self, folder):
fullpath = os.path.join(path, descriptionFile)
alg = RAlgorithm(fullpath)
if alg.name().strip() != '':
self.addAlgorithm(alg)
self.algs.append(alg)
except WrongScriptException as e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, e.msg)
except Exception as e:
@@ -46,6 +46,7 @@ class SagaAlgorithmProvider(AlgorithmProvider):
def __init__(self):
super().__init__()
self.activate = True
self.algs = []

def load(self):
AlgorithmProvider.load(self)
@@ -85,21 +86,24 @@ def loadAlgorithms(self):
self.tr('Problem with SAGA installation: unsupported SAGA version found.'))
return

self.algs = []
folder = SagaUtils.sagaDescriptionPath()
for descriptionFile in os.listdir(folder):
if descriptionFile.endswith('txt'):
try:
alg = SagaAlgorithm(os.path.join(folder, descriptionFile))
if alg.name().strip() != '':
self.addAlgorithm(alg)
self.algs.append(alg)
else:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('Could not open SAGA algorithm: {}'.format(descriptionFile)))
except Exception as e:
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
self.tr('Could not open SAGA algorithm: {}\n{}'.format(descriptionFile, str(e))))

self.addAlgorithm(SplitRGBBands())
self.algs.append(SplitRGBBands())
for a in self.algs:
self.addAlgorithm(a)

def name(self):
version = SagaUtils.getInstalledVersion()
@@ -26,10 +26,8 @@
__revision__ = '$Format:%H$'

from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessingProvider,
QgsVectorFileWriter)
from qgis.core import (QgsProcessingProvider)
from processing.core.ProcessingConfig import Setting, ProcessingConfig
from processing.tools import dataobjects


class AlgorithmProvider(QgsProcessingProvider):
@@ -62,38 +62,31 @@
from processing.script.ScriptAlgorithmProvider import ScriptAlgorithmProvider # NOQA
from processing.preconfigured.PreconfiguredAlgorithmProvider import PreconfiguredAlgorithmProvider # NOQA

# workaround SIP bindings losing subclasses during transfer to QgsProcessingRegistry
PROVIDERS = []

class Processing(object):

providers = []

# Same structure as algs in algList
actions = {}

# All the registered context menu actions for the toolbox
contextMenuActions = []

@staticmethod
def algs():
"""Use this method to get algorithms for wps4server.
"""
return algList.algs

@staticmethod
def addProvider(provider, updateList=True):
def addProvider(provider):
"""Use this method to add algorithms from external providers.
"""

if provider.id() in [p.id() for p in QgsApplication.processingRegistry().providers()]:
if QgsApplication.processingRegistry().providerById(provider.id()):
return
try:
if provider.load():
Processing.providers.append(provider)
ProcessingConfig.readSettings()
provider.refreshAlgorithms()
Processing.actions[provider.id()] = provider.actions
Processing.contextMenuActions.extend(provider.contextMenuActions)
algList.addProvider(provider)
QgsApplication.processingRegistry().addProvider(provider)
PROVIDERS.append(provider)
except:
ProcessingLog.addToLog(
ProcessingLog.LOG_ERROR,
@@ -110,22 +103,12 @@ def removeProvider(provider):
This method should be called when unloading a plugin that
contributes a provider.
"""
try:
provider.unload()
for p in Processing.providers:
if p.id() == provider.id():
Processing.providers.remove(p)
algList.removeProvider(provider.id())
if provider.id() in Processing.actions:
del Processing.actions[provider.id()]
for act in provider.contextMenuActions:
Processing.contextMenuActions.remove(act)
except:
# This try catch block is here to avoid problems if the
# plugin with a provider is unloaded after the Processing
# framework itself has been unloaded. It is a quick fix
# before I find out how to properly avoid that.
pass
provider.unload()
if provider.id() in Processing.actions:
del Processing.actions[provider.id()]
for act in provider.contextMenuActions:
Processing.contextMenuActions.remove(act)
QgsApplication.processingRegistry().removeProvider(provider.id())

@staticmethod
def activateProvider(providerOrName, activate=True):
@@ -136,7 +119,7 @@ def activateProvider(providerOrName, activate=True):

@staticmethod
def initialize():
if "model" in [p.id() for p in Processing.providers]:
if "model" in [p.id() for p in QgsApplication.processingRegistry().providers()]:
return
# Add the basic providers
for c in AlgorithmProvider.__subclasses__():
@@ -145,6 +128,7 @@ def initialize():
ProcessingConfig.initialize()
ProcessingConfig.readSettings()
RenderingStyles.loadStyles()
Processing.updateAlgsList()

@staticmethod
def addScripts(folder):
@@ -177,24 +161,21 @@ def updateAlgsList():
update.
"""
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
for p in Processing.providers:
for p in QgsApplication.processingRegistry().providers():
Processing.reloadProvider(p.id())
QApplication.restoreOverrideCursor()

@staticmethod
def reloadProvider(provider_id):
algList.reloadProvider(provider_id)

@staticmethod
def getAlgorithm(name):
return algList.getAlgorithm(name)

@staticmethod
def runAlgorithm(algOrName, onFinish, *args, **kwargs):
if isinstance(algOrName, GeoAlgorithm):
alg = algOrName
else:
alg = Processing.getAlgorithm(algOrName)
alg = QgsApplication.processingRegistry().algorithmById(algOrName)
if alg is None:
# fix_print_with_import
print('Error: Algorithm not found\n')
@@ -33,32 +33,12 @@ class AlgorithmList(QObject):

providerUpdated = pyqtSignal(str)

# A dictionary of algorithms. Keys are names of providers
# and values are list with all algorithms from that provider
algs = {}

def removeProvider(self, provider_id):
if provider_id in self.algs:
del self.algs[provider_id]

QgsApplication.processingRegistry().removeProvider(provider_id)

def reloadProvider(self, provider_id):
for p in QgsApplication.processingRegistry().providers():
if p.id() == provider_id:
p.refreshAlgorithms()
self.algs[p.id()] = {a.id(): a for a in p.algorithms()}
self.providerUpdated.emit(p.id())
break

def addProvider(self, provider):
if QgsApplication.processingRegistry().addProvider(provider):
self.algs[provider.id()] = {a.id(): a for a in provider.algorithms()}

def getAlgorithm(self, name):
for provider in list(self.algs.values()):
if name in provider:
return provider[name]


algList = AlgorithmList()
@@ -32,7 +32,7 @@
from qgis.PyQt.QtWidgets import QDialog, QLabel, QSpacerItem, QHBoxLayout, QVBoxLayout, QSizePolicy, QComboBox, QCompleter
from qgis.PyQt.QtCore import QSortFilterProxyModel
from qgis.utils import iface
from processing.core.alglist import algList
from qgis.core import (QgsApplication)
from processing.gui.MessageDialog import MessageDialog
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.tools.system import userFolder, mkdir
@@ -99,9 +99,8 @@ def fillCombo(self):
self.combo.clear()

# Add algorithms
for provider in list(algList.algs.values()):
for alg in provider:
self.combo.addItem('Processing algorithm: ' + alg)
for alg in QgsApplication.processingRegistry().algorithms():
self.combo.addItem('Processing algorithm: ' + alg)

# Add functions
for command in dir(self.commands):
@@ -152,7 +151,7 @@ def run(self):
s = str(self.combo.currentText())
if s.startswith('Processing algorithm: '):
algName = s[len('Processing algorithm: '):]
alg = algList.getAlgorithm(algName)
alg = QgsApplication.processingRegistry().algorithmById(algName)
if alg is not None:
self.close()
self.runAlgorithm(alg)
@@ -223,8 +223,7 @@ def fillTreeUsingProviders(self):
widget.setLayout(layout)
self.tree.setIndexWidget(emptyItem.index(), widget)

providers = Processing.providers
for provider in providers:
for provider in QgsApplication.processingRegistry().providers():
providerDescription = provider.name()
groupItem = QStandardItem(providerDescription)
icon = provider.icon()
@@ -266,8 +265,7 @@ def fillTreeUsingProviders(self):
self.adjustColumns()

def resetMenusToDefaults(self):
providers = Processing.providers
for provider in providers:
for provider in QgsApplication.processingRegistry().providers():
for alg in provider.algorithms():
d = defaultMenuEntries.get(alg.id(), "")
setting = ProcessingConfig.settings["MENU_" + alg.id()]
@@ -289,6 +287,7 @@ def accept(self):
self.tr('Wrong value for parameter "{0}":\n\n{1}').format(setting.description, str(e)))
return
setting.save(qsettings)

Processing.updateAlgsList()
settingsWatcher.settingsChanged.emit()

Loading

0 comments on commit 4970bb4

Please sign in to comment.