QGIS/python/plugins/processing/modeler/ProjectProvider.py
olivierdalang 340631f850 fix #19824 where modifications to project models were not saved
Models definitions are now stored in a dict rather than list
which allows for less verbose code to reference models by name
2018-09-15 14:53:40 +10:00

167 lines
5.5 KiB
Python

# -*- coding: utf-8 -*-
"""
***************************************************************************
ProjectProvider.py
------------------------
Date : July 2018
Copyright : (C) 2018 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. *
* *
***************************************************************************
"""
__author__ = 'Nyall Dawson'
__date__ = 'July 2018'
__copyright__ = '(C) 2018, Nyall Dawson'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import (Qgis,
QgsApplication,
QgsProcessingProvider,
QgsMessageLog,
QgsProcessingModelAlgorithm,
QgsProject,
QgsXmlUtils)
PROJECT_PROVIDER_ID = 'project'
class ProjectProvider(QgsProcessingProvider):
def __init__(self, project=None):
super().__init__()
if project is None:
self.project = QgsProject.instance()
else:
self.project = project
self.model_definitions = {} # dict of models in project
self.is_loading = False
# must reload models if providers list is changed - previously unavailable algorithms
# which models depend on may now be available
QgsApplication.processingRegistry().providerAdded.connect(self.on_provider_added)
self.project.readProject.connect(self.read_project)
self.project.writeProject.connect(self.write_project)
self.project.cleared.connect(self.clear)
def on_provider_added(self, _):
self.refreshAlgorithms()
def load(self):
self.refreshAlgorithms()
return True
def clear(self):
"""
Remove all algorithms from the provider
"""
self.model_definitions = {}
self.refreshAlgorithms()
def add_model(self, model):
"""
Adds a model to the provider
:type model: QgsProcessingModelAlgorithm
:param model: model to add
"""
definition = model.toVariant()
self.model_definitions[model.name()] = definition
self.refreshAlgorithms()
def remove_model(self, model):
"""
Removes a model from the project
:type model: QgsProcessingModelAlgorithm
:param model: model to remove
"""
if model is None:
return
if model.name() in self.model_definitions:
del self.model_definitions[model.name()]
self.refreshAlgorithms()
def read_project(self, doc):
"""
Reads the project model definitions from the project DOM document
:param doc: DOM document
"""
self.model_definitions = {}
project_models_nodes = doc.elementsByTagName('projectModels')
if project_models_nodes:
project_models_node = project_models_nodes.at(0)
model_nodes = project_models_node.childNodes()
for n in range(model_nodes.count()):
model_element = model_nodes.at(n).toElement()
definition = QgsXmlUtils.readVariant(model_element)
algorithm = QgsProcessingModelAlgorithm()
if algorithm.loadVariant(definition):
self.model_definitions[algorithm.name()] = definition
self.refreshAlgorithms()
def write_project(self, doc):
"""
Writes out the project model definitions into the project DOM document
:param doc: DOM document
"""
qgis_nodes = doc.elementsByTagName('qgis')
if not qgis_nodes:
return
qgis_node = qgis_nodes.at(0)
project_models_node = doc.createElement('projectModels')
for a in self.algorithms():
definition = a.toVariant()
element = QgsXmlUtils.writeVariant(definition, doc)
project_models_node.appendChild(element)
qgis_node.appendChild(project_models_node)
def name(self):
return self.tr('Project models', 'ProjectProvider')
def longName(self):
return self.tr('Models embedded in the current project', 'ProjectProvider')
def id(self):
return PROJECT_PROVIDER_ID
def icon(self):
return QgsApplication.getThemeIcon("/mIconQgsProjectFile.svg")
def svgIconPath(self):
return QgsApplication.iconPath("mIconQgsProjectFile.svg")
def supportsNonFileBasedOutput(self):
return True
def loadAlgorithms(self):
if self.is_loading:
return
self.is_loading = True
for definition in self.model_definitions.values():
algorithm = QgsProcessingModelAlgorithm()
if algorithm.loadVariant(definition):
self.addAlgorithm(algorithm)
else:
QgsMessageLog.logMessage(
self.tr('Could not load model from project', 'ProjectProvider'),
self.tr('Processing'), Qgis.Critical)
self.is_loading = False