[processing] New c++ QgsProcessingRegistry class

Intended as a registry for the various processing components,
including providers, algorithms and various parameters and outputs.

Currently handles only registration of providers, as a step toward
removing processing's algList (this requires first porting
the algorithm class to c++)

A QgsProcessingRegistry instance is attached to QgsApplication,
and is retrieved by QgsApplication::processingRegistry()
This commit is contained in:
Nyall Dawson 2017-01-09 09:59:35 +10:00
parent bb24dfe245
commit dca697b427
15 changed files with 312 additions and 65 deletions

View File

@ -260,6 +260,7 @@
%Include layertree/qgslayertreeutils.sip
%Include processing/qgsprocessingprovider.sip
%Include processing/qgsprocessingregistry.sip
%Include raster/qgsbilinearrasterresampler.sip
%Include raster/qgsbrightnesscontrastfilter.sip

View File

@ -0,0 +1,72 @@
/**
* \class QgsProcessingRegistry
* \ingroup core
* Registry for various processing components, including providers, algorithms
* and various parameters and outputs.
*
* QgsProcessingRegistry is not usually directly created, but rather accessed through
* QgsApplication::processingRegistry().
* \note added in QGIS 3.0
*/
class QgsProcessingRegistry : QObject
{
%TypeHeaderCode
#include <qgsprocessingregistry.h>
%End
public:
/**
* Constructor for QgsProcessingRegistry.
*/
QgsProcessingRegistry( QObject* parent /TransferThis/ = nullptr );
~QgsProcessingRegistry();
/**
* Get list of available providers.
*/
QList<QgsProcessingProvider*> providers() const;
/**
* Add a processing provider to the registry. Ownership of the provider is transferred to the registry.
* Returns false if the provider could not be added (eg if a provider with a duplicate ID already exists
* in the registry).
* @see removeProvider()
*/
bool addProvider( QgsProcessingProvider* provider /Transfer/ );
/**
* Removes a provider implementation from the registry (the provider object is deleted).
* Returns false if the provider could not be removed (eg provider does not exist in the registry).
* @see addProvider()
*/
bool removeProvider( QgsProcessingProvider* provider );
/**
* Removes a provider implementation from the registry (the provider object is deleted).
* Returns false if the provider could not be removed (eg provider does not exist in the registry).
* @see addProvider()
*/
bool removeProvider( const QString& providerId );
/**
* Returns a matching provider by provider ID.
*/
QgsProcessingProvider* providerById( const QString& id );
signals:
//! Emitted when a provider has been added to the registry.
void providerAdded( const QString& id );
//! Emitted when a provider is removed from the registry
void providerRemoved( const QString& id );
private:
//! Registry cannot be copied
QgsProcessingRegistry( const QgsProcessingRegistry& other );
//! Registry cannot be copied
//QgsProcessingRegistry& operator=( const QgsProcessingRegistry& other );
};

View File

@ -442,6 +442,13 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv)
*/
static QgsMessageLog* messageLog();
/**
* Returns the application's processing registry, used for managing processing providers,
* algorithms, and various parameters and outputs.
* @note added in QGIS 3.0
*/
static QgsProcessingRegistry* processingRegistry();
%If(ANDROID)
//dummy method to workaround sip generation issue issue
bool x11EventFilter ( XEvent * event );

View File

@ -38,7 +38,8 @@ from qgis.PyQt.QtWidgets import QApplication
from qgis.PyQt.QtGui import QCursor
from qgis.utils import iface
from qgis.core import QgsMessageLog
from qgis.core import (QgsMessageLog,
QgsApplication)
import processing
from processing.core.AlgorithmProvider import AlgorithmProvider
@ -87,7 +88,7 @@ class Processing(object):
"""Use this method to add algorithms from external providers.
"""
if provider.id() in [p.id() for p in algList.providers]:
if provider.id() in [p.id() for p in QgsApplication.processingRegistry().providers()]:
return
try:
provider.initializeSettings()
@ -128,11 +129,6 @@ class Processing(object):
# before I find out how to properly avoid that.
pass
@staticmethod
def providerById(id):
"""Returns the provider with the given id."""
return algList.providerById(id)
@staticmethod
def activateProvider(providerOrName, activate=True):
provider_id = providerOrName.id() if isinstance(providerOrName, AlgorithmProvider) else providerOrName
@ -155,7 +151,7 @@ class Processing(object):
@staticmethod
def addScripts(folder):
Processing.initialize()
provider = Processing.providerById("qgis")
provider = QgsApplication.processingRegistry().providerById("qgis")
scripts = ScriptUtils.loadFromFolder(folder)
# fix_print_with_import
print(scripts)
@ -168,7 +164,7 @@ class Processing(object):
@staticmethod
def removeScripts(folder):
provider = Processing.providerById("qgis")
provider = QgsApplication.processingRegistry().providerById("qgis")
for alg in provider.externalAlgs[::-1]:
path = os.path.dirname(alg.descriptionFile)
if path == folder:

View File

@ -25,13 +25,13 @@ __copyright__ = '(C) 2016, Victor Olaya'
__revision__ = '$Format:%H$'
from qgis.core import (QgsApplication,
QgsProcessingRegistry)
from qgis.PyQt.QtCore import QObject, pyqtSignal
class AlgorithmList(QObject):
providerAdded = pyqtSignal(str)
providerRemoved = pyqtSignal(str)
providerUpdated = pyqtSignal(str)
# A dictionary of algorithms. Keys are names of providers
@ -41,13 +41,10 @@ class AlgorithmList(QObject):
providers = []
def removeProvider(self, provider_id):
for p in self.providers:
if p.id() == provider_id:
self.providers.remove(p)
break
if provider_id in self.algs:
del self.algs[provider_id]
self.providerRemoved.emit(provider_id)
QgsApplication.processingRegistry().removeProvider(provider_id)
def reloadProvider(self, provider_id):
for p in self.providers:
@ -58,14 +55,8 @@ class AlgorithmList(QObject):
break
def addProvider(self, provider):
self.providers.append(provider)
self.algs[provider.id()] = {a.commandLineName(): a for a in provider.algs}
self.providerAdded.emit(provider.id())
def providerById(self, id):
for provider in self.providers:
if provider.id() == id:
return provider
if QgsApplication.processingRegistry().addProvider(provider):
self.algs[provider.id()] = {a.commandLineName(): a for a in provider.algs}
def getAlgorithm(self, name):
for provider in list(self.algs.values()):

View File

@ -33,6 +33,8 @@ from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt, QCoreApplication
from qgis.PyQt.QtWidgets import QMenu, QAction, QTreeWidgetItem, QLabel, QMessageBox
from qgis.utils import iface
from qgis.core import (QgsApplication,
QgsProcessingRegistry)
from processing.gui.Postprocessing import handleAlgorithmResults
from processing.core.Processing import Processing
@ -82,8 +84,8 @@ class ProcessingToolbox(BASE, WIDGET):
self.fillTree()
algList.providerRemoved.connect(self.removeProvider)
algList.providerAdded.connect(self.addProvider)
QgsApplication.processingRegistry().providerRemoved.connect(self.removeProvider)
QgsApplication.processingRegistry().providerAdded.connect(self.addProvider)
algList.providerUpdated.connect(self.updateProvider)
settingsWatcher.settingsChanged.connect(self.fillTree)
@ -159,7 +161,7 @@ class ProcessingToolbox(BASE, WIDGET):
self.fillTree()
self.textChanged()
self.showDisabled()
provider = Processing.providerById(id)
provider = QgsApplication.processingRegistry().providerById(id)
if not provider.canBeActivated():
QMessageBox.warning(self, "Activate provider",
"The provider has been activated, but it might need additional configuration.")
@ -376,7 +378,7 @@ class TreeProviderItem(QTreeWidgetItem):
self.tree = tree
self.toolbox = toolbox
self.provider_id = provider_id
self.provider = Processing.providerById(provider_id)
self.provider = QgsApplication.processingRegistry().providerById(provider_id)
self.setIcon(0, self.provider.icon())
self.populate()

View File

@ -43,7 +43,6 @@ from qgis.PyQt.QtWidgets import (QMenu,
from qgis.core import QgsApplication
from qgis.utils import iface
from processing.core.alglist import algList
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.HelpEditionDialog import HelpEditionDialog
from processing.algs.r.RAlgorithm import RAlgorithm
@ -279,10 +278,10 @@ class ScriptEditorDialog(BASE, WIDGET):
def runAlgorithm(self):
if self.algType == self.SCRIPT_PYTHON:
alg = ScriptAlgorithm(None, self.editor.text())
alg.provider = algList.providerById('script')
alg.provider = QgsApplication.processingRegistry().providerById('script')
if self.algType == self.SCRIPT_R:
alg = RAlgorithm(None, self.editor.text())
alg.provider = algList.providerById('r')
alg.provider = QgsApplication.processingRegistry().providerById('r')
dlg = alg.getCustomParametersDialog()
if not dlg:

View File

@ -8,6 +8,7 @@ from processing.core.ProcessingConfig import ProcessingConfig, Setting
from processing.gui.MessageDialog import MessageDialog
from processing.gui.AlgorithmDialog import AlgorithmDialog
from qgis.utils import iface
from qgis.core import QgsApplication
from processing.gui.MessageBarProgress import MessageBarProgress
from processing.gui.AlgorithmExecutor import runalg
from processing.gui.Postprocessing import handleAlgorithmResults
@ -111,7 +112,7 @@ defaultMenuEntries.update({'gdal:buildvirtualraster': miscMenu,
def initializeMenus():
for provider in algList.providers:
for provider in QgsApplication.processingRegistry().providers():
for alg in provider.algs:
d = defaultMenuEntries.get(alg.commandLineName(), "")
setting = Setting(menusSettingsGroup, "MENU_" + alg.commandLineName(),

View File

@ -272,7 +272,7 @@ class ModelerDialog(BASE, WIDGET):
def editHelp(self):
if self.alg.provider is None:
# Might happen if model is opened from modeler dialog
self.alg.provider = algList.providerById('model')
self.alg.provider = QgsApplication.processingRegistry().providerById('model')
alg = self.alg.getCopy()
dlg = HelpEditionDialog(alg)
dlg.exec_()
@ -287,7 +287,7 @@ class ModelerDialog(BASE, WIDGET):
if self.alg.provider is None:
# Might happen if model is opened from modeler dialog
self.alg.provider = algList.providerById('model')
self.alg.provider = QgsApplication.processingRegistry().providerById('model')
alg = self.alg.getCopy()
dlg = AlgorithmDialog(alg)
dlg.exec_()
@ -640,7 +640,7 @@ class ModelerDialog(BASE, WIDGET):
if len(groups) > 0:
providerItem = QTreeWidgetItem()
provider = algList.providerById(provider_id)
provider = QgsApplication.processingRegistry().providerById(provider_id)
providerItem.setText(0, provider.name())
providerItem.setToolTip(0, provider.name())
providerItem.setIcon(0, provider.icon())

View File

@ -31,7 +31,7 @@ from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QTreeWidgetItem, QFileDialog
from processing.core.alglist import algList
from qgis.core import QgsApplication
pluginPath = os.path.split(os.path.dirname(__file__))[0]
WIDGET, BASE = uic.loadUiType(
@ -47,7 +47,7 @@ class ScriptSelector(BASE, WIDGET):
self.scripts = None
allScripts = defaultdict(list)
alglist = algList.providerById("script").algs
alglist = QgsApplication.processingRegistry().providerById("script").algs
for script in alglist:
allScripts[script.group].append(script)

View File

@ -79,6 +79,7 @@ SET(QGIS_CORE_SRCS
auth/qgsauthmethodregistry.cpp
processing/qgsprocessingprovider.cpp
processing/qgsprocessingregistry.cpp
qgis.cpp
qgsapplication.cpp
@ -562,6 +563,8 @@ SET(QGIS_CORE_MOC_HDRS
composer/qgsgroupungroupitemscommand.h
composer/qgspaperitem.h
processing/qgsprocessingregistry.h
raster/qgsrasterlayer.h
raster/qgsrasterdataprovider.h

View File

@ -0,0 +1,71 @@
/***************************************************************************
qgsprocessingregistry.cpp
--------------------------
begin : December 2016
copyright : (C) 2016 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsprocessingregistry.h"
QgsProcessingRegistry::QgsProcessingRegistry( QObject* parent )
: QObject( parent )
{
}
QgsProcessingRegistry::~QgsProcessingRegistry()
{
Q_FOREACH ( QgsProcessingProvider* p, mProviders )
{
removeProvider( p );
}
}
bool QgsProcessingRegistry::addProvider( QgsProcessingProvider* provider )
{
if ( !provider )
return false;
if ( mProviders.contains( provider->id() ) )
return false;
mProviders[ provider->id()] = provider;
emit providerAdded( provider->id() );
return true;
}
bool QgsProcessingRegistry::removeProvider( QgsProcessingProvider* provider )
{
if ( !provider )
return false;
QString id = provider->id();
if ( !mProviders.contains( id ) )
return false;
delete mProviders.take( id );
emit providerRemoved( id );
return true;
}
bool QgsProcessingRegistry::removeProvider( const QString& providerId )
{
QgsProcessingProvider* p = providerById( providerId );
return removeProvider( p );
}
QgsProcessingProvider* QgsProcessingRegistry::providerById( const QString& id )
{
return mProviders.value( id, nullptr );
}

View File

@ -0,0 +1,101 @@
/***************************************************************************
qgsprocessingregistry.h
------------------------
begin : December 2016
copyright : (C) 2016 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPROCESSINGREGISTRY_H
#define QGSPROCESSINGREGISTRY_H
#include "qgis_core.h"
#include "qgsprocessingprovider.h"
#include <QMap>
/**
* \class QgsProcessingRegistry
* \ingroup core
* Registry for various processing components, including providers, algorithms
* and various parameters and outputs.
*
* QgsProcessingRegistry is not usually directly created, but rather accessed through
* QgsApplication::processingRegistry().
* \note added in QGIS 3.0
*/
class CORE_EXPORT QgsProcessingRegistry : public QObject
{
Q_OBJECT
public:
/**
* Constructor for QgsProcessingRegistry.
*/
QgsProcessingRegistry( QObject* parent = nullptr );
~QgsProcessingRegistry();
//! Registry cannot be copied
QgsProcessingRegistry( const QgsProcessingRegistry& other ) = delete;
//! Registry cannot be copied
QgsProcessingRegistry& operator=( const QgsProcessingRegistry& other ) = delete;
/**
* Get list of available providers.
*/
QList<QgsProcessingProvider*> providers() const { return mProviders.values(); }
/**
* Add a processing provider to the registry. Ownership of the provider is transferred to the registry.
* Returns false if the provider could not be added (eg if a provider with a duplicate ID already exists
* in the registry).
* @see removeProvider()
*/
bool addProvider( QgsProcessingProvider* provider );
/**
* Removes a provider implementation from the registry (the provider object is deleted).
* Returns false if the provider could not be removed (eg provider does not exist in the registry).
* @see addProvider()
*/
bool removeProvider( QgsProcessingProvider* provider );
/**
* Removes a provider implementation from the registry (the provider object is deleted).
* Returns false if the provider could not be removed (eg provider does not exist in the registry).
* @see addProvider()
*/
bool removeProvider( const QString& providerId );
/**
* Returns a matching provider by provider ID.
*/
QgsProcessingProvider* providerById( const QString& id );
signals:
//! Emitted when a provider has been added to the registry.
void providerAdded( const QString& id );
//! Emitted when a provider is removed from the registry
void providerRemoved( const QString& id );
private:
//! Map of available providers by id. This class owns the pointers
QMap<QString, QgsProcessingProvider*> mProviders;
};
#endif // QGSPROCESSINGREGISTRY_H

View File

@ -36,6 +36,7 @@
#include "gps/qgsgpsconnectionregistry.h"
#include "qgspluginlayerregistry.h"
#include "qgsmessagelog.h"
#include "processing/qgsprocessingregistry.h"
#include <QDir>
#include <QFile>
@ -114,20 +115,6 @@ const char* QgsApplication::QGIS_APPLICATION_NAME = "QGIS3";
*/
QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, const QString& customConfigPath, const QString& platformName )
: QApplication( argc, argv, GUIenabled )
, mActionScopeRegistry( nullptr )
, mProfiler( nullptr )
, mTaskManager( nullptr )
, mFieldFormatterRegistry( nullptr )
, mColorSchemeRegistry( nullptr )
, mPaintEffectRegistry( nullptr )
, mRendererRegistry( nullptr )
, mSvgCache( nullptr )
, mSymbolLayerRegistry( nullptr )
, mRasterRendererRegistry( nullptr )
, mGpsConnectionRegistry( nullptr )
, mDataItemProviderRegistry( nullptr )
, mPluginLayerRegistry( nullptr )
, mMessageLog( nullptr )
{
sPlatformName = platformName;
@ -147,6 +134,7 @@ QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, const
mRasterRendererRegistry = new QgsRasterRendererRegistry();
mGpsConnectionRegistry = new QgsGPSConnectionRegistry();
mPluginLayerRegistry = new QgsPluginLayerRegistry();
mProcessingRegistry = new QgsProcessingRegistry();
init( customConfigPath ); // init can also be called directly by e.g. unit tests that don't inherit QApplication.
}
@ -278,6 +266,7 @@ void QgsApplication::init( QString customConfigPath )
QgsApplication::~QgsApplication()
{
delete mProcessingRegistry;
delete mActionScopeRegistry;
delete mTaskManager;
delete mFieldFormatterRegistry;
@ -1608,6 +1597,11 @@ QgsMessageLog* QgsApplication::messageLog()
return instance()->mMessageLog;
}
QgsProcessingRegistry*QgsApplication::processingRegistry()
{
return instance()->mProcessingRegistry;
}
QgsFieldFormatterRegistry* QgsApplication::fieldFormatterRegistry()
{
return instance()->mFieldFormatterRegistry;

View File

@ -37,6 +37,7 @@ class QgsGPSConnectionRegistry;
class QgsDataItemProviderRegistry;
class QgsPluginLayerRegistry;
class QgsMessageLog;
class QgsProcessingRegistry;
/** \ingroup core
* Extends QApplication to provide access to QGIS specific resources such
@ -454,6 +455,13 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
static QgsMessageLog* messageLog();
/**
* Returns the application's processing registry, used for managing processing providers,
* algorithms, and various parameters and outputs.
* @note added in QGIS 3.0
*/
static QgsProcessingRegistry* processingRegistry();
#ifdef ANDROID
//dummy method to workaround sip generation issue issue
bool x11EventFilter( XEvent * event )
@ -584,20 +592,21 @@ class CORE_EXPORT QgsApplication : public QApplication
QMap<QString, QIcon> mIconCache;
QgsActionScopeRegistry* mActionScopeRegistry;
QgsRuntimeProfiler* mProfiler;
QgsTaskManager* mTaskManager;
QgsFieldFormatterRegistry* mFieldFormatterRegistry;
QgsColorSchemeRegistry* mColorSchemeRegistry;
QgsPaintEffectRegistry* mPaintEffectRegistry;
QgsRendererRegistry* mRendererRegistry;
QgsSvgCache* mSvgCache;
QgsSymbolLayerRegistry* mSymbolLayerRegistry;
QgsRasterRendererRegistry* mRasterRendererRegistry;
QgsGPSConnectionRegistry* mGpsConnectionRegistry;
QgsDataItemProviderRegistry* mDataItemProviderRegistry;
QgsPluginLayerRegistry* mPluginLayerRegistry;
QgsMessageLog* mMessageLog;
QgsActionScopeRegistry* mActionScopeRegistry = nullptr;
QgsRuntimeProfiler* mProfiler = nullptr;
QgsTaskManager* mTaskManager = nullptr;
QgsFieldFormatterRegistry* mFieldFormatterRegistry = nullptr;
QgsColorSchemeRegistry* mColorSchemeRegistry = nullptr;
QgsPaintEffectRegistry* mPaintEffectRegistry = nullptr;
QgsRendererRegistry* mRendererRegistry = nullptr;
QgsSvgCache* mSvgCache = nullptr;
QgsSymbolLayerRegistry* mSymbolLayerRegistry = nullptr;
QgsRasterRendererRegistry* mRasterRendererRegistry = nullptr;
QgsGPSConnectionRegistry* mGpsConnectionRegistry = nullptr;
QgsDataItemProviderRegistry* mDataItemProviderRegistry = nullptr;
QgsPluginLayerRegistry* mPluginLayerRegistry = nullptr;
QgsMessageLog* mMessageLog = nullptr;
QgsProcessingRegistry* mProcessingRegistry = nullptr;
QString mNullRepresentation;
};