1# -*- coding: utf-8 -*- 2 3""" 4*************************************************************************** 5 ProjectProvider.py 6 ------------------------ 7 Date : July 2018 8 Copyright : (C) 2018 by Nyall Dawson 9 Email : nyall dot dawson at gmail dot com 10*************************************************************************** 11* * 12* This program is free software; you can redistribute it and/or modify * 13* it under the terms of the GNU General Public License as published by * 14* the Free Software Foundation; either version 2 of the License, or * 15* (at your option) any later version. * 16* * 17*************************************************************************** 18""" 19 20__author__ = 'Nyall Dawson' 21__date__ = 'July 2018' 22__copyright__ = '(C) 2018, Nyall Dawson' 23 24from qgis.core import (Qgis, 25 QgsApplication, 26 QgsProcessingProvider, 27 QgsMessageLog, 28 QgsProcessingModelAlgorithm, 29 QgsProject, 30 QgsXmlUtils, 31 QgsRuntimeProfiler) 32 33PROJECT_PROVIDER_ID = 'project' 34 35 36class ProjectProvider(QgsProcessingProvider): 37 38 def __init__(self, project=None): 39 super().__init__() 40 if project is None: 41 self.project = QgsProject.instance() 42 else: 43 self.project = project 44 45 self.model_definitions = {} # dict of models in project 46 self.is_loading = False 47 48 # must reload models if providers list is changed - previously unavailable algorithms 49 # which models depend on may now be available 50 QgsApplication.processingRegistry().providerAdded.connect(self.on_provider_added) 51 52 self.project.readProject.connect(self.read_project) 53 self.project.writeProject.connect(self.write_project) 54 self.project.cleared.connect(self.clear) 55 56 def on_provider_added(self, _): 57 self.refreshAlgorithms() 58 59 def load(self): 60 with QgsRuntimeProfiler.profile('Project Provider'): 61 self.refreshAlgorithms() 62 63 return True 64 65 def clear(self): 66 """ 67 Remove all algorithms from the provider 68 """ 69 self.model_definitions = {} 70 self.refreshAlgorithms() 71 72 def add_model(self, model): 73 """ 74 Adds a model to the provider 75 :type model: QgsProcessingModelAlgorithm 76 :param model: model to add 77 """ 78 definition = model.toVariant() 79 self.model_definitions[model.name()] = definition 80 self.refreshAlgorithms() 81 82 def remove_model(self, model): 83 """ 84 Removes a model from the project 85 :type model: QgsProcessingModelAlgorithm 86 :param model: model to remove 87 """ 88 if model is None: 89 return 90 91 if model.name() in self.model_definitions: 92 del self.model_definitions[model.name()] 93 94 self.refreshAlgorithms() 95 96 def read_project(self, doc): 97 """ 98 Reads the project model definitions from the project DOM document 99 :param doc: DOM document 100 """ 101 self.model_definitions = {} 102 project_models_nodes = doc.elementsByTagName('projectModels') 103 if project_models_nodes: 104 project_models_node = project_models_nodes.at(0) 105 model_nodes = project_models_node.childNodes() 106 for n in range(model_nodes.count()): 107 model_element = model_nodes.at(n).toElement() 108 definition = QgsXmlUtils.readVariant(model_element) 109 algorithm = QgsProcessingModelAlgorithm() 110 if algorithm.loadVariant(definition): 111 self.model_definitions[algorithm.name()] = definition 112 113 self.refreshAlgorithms() 114 115 def write_project(self, doc): 116 """ 117 Writes out the project model definitions into the project DOM document 118 :param doc: DOM document 119 """ 120 qgis_nodes = doc.elementsByTagName('qgis') 121 if not qgis_nodes: 122 return 123 124 qgis_node = qgis_nodes.at(0) 125 project_models_node = doc.createElement('projectModels') 126 127 for a in self.algorithms(): 128 definition = a.toVariant() 129 element = QgsXmlUtils.writeVariant(definition, doc) 130 project_models_node.appendChild(element) 131 qgis_node.appendChild(project_models_node) 132 133 def name(self): 134 return self.tr('Project models', 'ProjectProvider') 135 136 def longName(self): 137 return self.tr('Models embedded in the current project', 'ProjectProvider') 138 139 def id(self): 140 return PROJECT_PROVIDER_ID 141 142 def icon(self): 143 return QgsApplication.getThemeIcon("/mIconQgsProjectFile.svg") 144 145 def svgIconPath(self): 146 return QgsApplication.iconPath("mIconQgsProjectFile.svg") 147 148 def supportsNonFileBasedOutput(self): 149 return True 150 151 def loadAlgorithms(self): 152 if self.is_loading: 153 return 154 self.is_loading = True 155 156 for definition in self.model_definitions.values(): 157 algorithm = QgsProcessingModelAlgorithm() 158 if algorithm.loadVariant(definition): 159 self.addAlgorithm(algorithm) 160 else: 161 QgsMessageLog.logMessage( 162 self.tr('Could not load model from project', 'ProjectProvider'), 163 self.tr('Processing'), Qgis.Critical) 164 165 self.is_loading = False 166