Skip to content

Commit

Permalink
Move more algList functionality to QgsProcessingRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Apr 7, 2017
1 parent 2a1a715 commit 4970bb4
Show file tree
Hide file tree
Showing 29 changed files with 218 additions and 210 deletions.
2 changes: 1 addition & 1 deletion doc/api_break.dox
Expand Up @@ -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}
-------------
Expand Down
13 changes: 13 additions & 0 deletions python/core/processing/qgsprocessingregistry.sip
Expand Up @@ -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 );
Expand Down
31 changes: 16 additions & 15 deletions python/plugins/processing/algs/gdal/GdalAlgorithmProvider.py
Expand Up @@ -98,6 +98,7 @@ class GdalAlgorithmProvider(AlgorithmProvider):

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

def load(self):
AlgorithmProvider.load(self)
Expand Down Expand Up @@ -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):
Expand Down
Expand Up @@ -44,6 +44,7 @@ class Grass7AlgorithmProvider(AlgorithmProvider):

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

def load(self):
AlgorithmProvider.load(self)
Expand Down Expand Up @@ -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):
Expand Down
4 changes: 3 additions & 1 deletion python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Expand Up @@ -192,6 +192,7 @@ class QGISAlgorithmProvider(AlgorithmProvider):

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

def getAlgs(self):
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 5 additions & 2 deletions python/plugins/processing/algs/r/RAlgorithmProvider.py
Expand Up @@ -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))
Expand Down Expand Up @@ -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):
Expand All @@ -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:
Expand Down
8 changes: 6 additions & 2 deletions python/plugins/processing/algs/saga/SagaAlgorithmProvider.py
Expand Up @@ -46,6 +46,7 @@ class SagaAlgorithmProvider(AlgorithmProvider):
def __init__(self):
super().__init__()
self.activate = True
self.algs = []

def load(self):
AlgorithmProvider.load(self)
Expand Down Expand Up @@ -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()
Expand Down
4 changes: 1 addition & 3 deletions python/plugins/processing/core/AlgorithmProvider.py
Expand Up @@ -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):
Expand Down
51 changes: 16 additions & 35 deletions python/plugins/processing/core/Processing.py
Expand Up @@ -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,
Expand All @@ -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):
Expand All @@ -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__():
Expand All @@ -145,6 +128,7 @@ def initialize():
ProcessingConfig.initialize()
ProcessingConfig.readSettings()
RenderingStyles.loadStyles()
Processing.updateAlgsList()

@staticmethod
def addScripts(folder):
Expand Down Expand Up @@ -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')
Expand Down
20 changes: 0 additions & 20 deletions python/plugins/processing/core/alglist.py
Expand Up @@ -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()
9 changes: 4 additions & 5 deletions python/plugins/processing/gui/CommanderWindow.py
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 3 additions & 4 deletions python/plugins/processing/gui/ConfigDialog.py
Expand Up @@ -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()
Expand Down Expand Up @@ -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()]
Expand All @@ -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()

Expand Down

0 comments on commit 4970bb4

Please sign in to comment.