mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	First steps to model/save restore in c++
Models now save to QVariantMap, using QgsXmlUtils to save to an xml based format (with extension .model3)
This commit is contained in:
		
							parent
							
								
									179a377da0
								
							
						
					
					
						commit
						9a2f14b931
					
				@ -139,6 +139,20 @@ class QgsProcessingModelAlgorithm : QgsProcessingAlgorithm
 | 
			
		||||
.. seealso:: setOutputChildId()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Saves this source to a QVariant.
 | 
			
		||||
.. seealso:: loadVariant()
 | 
			
		||||
 :rtype: QVariant
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        bool loadVariant( const QVariantMap &map );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Loads this source from a QVariantMap.
 | 
			
		||||
.. seealso:: toVariant()
 | 
			
		||||
 :rtype: bool
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Component
 | 
			
		||||
@ -192,6 +206,18 @@ Copies are protected to avoid slicing
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void saveCommonProperties( QVariantMap &map ) const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Saves the component properties to a QVariantMap.
 | 
			
		||||
.. seealso:: restoreCommonProperties()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        void restoreCommonProperties( const QVariantMap &map );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Restores the component properties from a QVariantMap.
 | 
			
		||||
.. seealso:: saveCommonProperties()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class ModelParameter : QgsProcessingModelAlgorithm::Component
 | 
			
		||||
@ -227,6 +253,20 @@ Copies are protected to avoid slicing
 | 
			
		||||
.. seealso:: parameterName()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Saves this parameter to a QVariant.
 | 
			
		||||
.. seealso:: loadVariant()
 | 
			
		||||
 :rtype: QVariant
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        bool loadVariant( const QVariantMap &map );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Loads this parameter from a QVariantMap.
 | 
			
		||||
.. seealso:: toVariant()
 | 
			
		||||
 :rtype: bool
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -273,6 +313,20 @@ Copies are protected to avoid slicing
 | 
			
		||||
.. seealso:: outputName()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Saves this output to a QVariant.
 | 
			
		||||
.. seealso:: loadVariant()
 | 
			
		||||
 :rtype: QVariant
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        bool loadVariant( const QVariantMap &map );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Loads this output from a QVariantMap.
 | 
			
		||||
.. seealso:: toVariant()
 | 
			
		||||
 :rtype: bool
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class ChildAlgorithm : QgsProcessingModelAlgorithm::Component
 | 
			
		||||
@ -461,6 +515,20 @@ Copies are protected to avoid slicing
 | 
			
		||||
.. seealso:: modelOutputs()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Saves this child to a QVariant.
 | 
			
		||||
.. seealso:: loadVariant()
 | 
			
		||||
 :rtype: QVariant
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
        bool loadVariant( const QVariant &child );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Loads this child from a QVariant.
 | 
			
		||||
.. seealso:: toVariant()
 | 
			
		||||
 :rtype: bool
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    QgsProcessingModelAlgorithm( const QString &name = QString(), const QString &group = QString() );
 | 
			
		||||
@ -484,6 +552,18 @@ Copies are protected to avoid slicing
 | 
			
		||||
     virtual QVariantMap processAlgorithm( const QVariantMap ¶meters,
 | 
			
		||||
                                  QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const;
 | 
			
		||||
 | 
			
		||||
    void setName( const QString &name );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Sets the model ``name``.
 | 
			
		||||
.. seealso:: name()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    void setGroup( const QString &group );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Sets the model ``group``.
 | 
			
		||||
.. seealso:: group()
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    QMap<QString, QgsProcessingModelAlgorithm::ChildAlgorithm> childAlgorithms() const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Returns the map of child algorithms contained in the model. The keys
 | 
			
		||||
@ -651,6 +731,20 @@ Copies are protected to avoid slicing
 | 
			
		||||
 :rtype: QgsProcessingModelAlgorithm.ModelParameter
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    bool toFile( const QString &path ) const;
 | 
			
		||||
%Docstring
 | 
			
		||||
 Writes the model to a file, at the specified ``path``.
 | 
			
		||||
.. seealso:: fromFile()
 | 
			
		||||
 :rtype: bool
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    bool fromFile( const QString &path );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Reads the model from a file, at the specified ``path``.
 | 
			
		||||
.. seealso:: toFile()
 | 
			
		||||
 :rtype: bool
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -56,22 +56,16 @@ class AddModelFromFileAction(ToolboxAction):
 | 
			
		||||
                                                                self.tr('Open model', 'AddModelFromFileAction'), lastDir,
 | 
			
		||||
                                                                self.tr('Processing model files (*.model *.MODEL)', 'AddModelFromFileAction'))
 | 
			
		||||
        if filename:
 | 
			
		||||
            try:
 | 
			
		||||
                settings.setValue('Processing/lastModelsDir',
 | 
			
		||||
                                  QFileInfo(filename).absoluteDir().absolutePath())
 | 
			
		||||
            settings.setValue('Processing/lastModelsDir',
 | 
			
		||||
                              QFileInfo(filename).absoluteDir().absolutePath())
 | 
			
		||||
 | 
			
		||||
                ModelerAlgorithm.fromFile(filename)
 | 
			
		||||
            except WrongModelException:
 | 
			
		||||
            alg = ModelerAlgorithm()
 | 
			
		||||
            if not alg.fromFile(filename):
 | 
			
		||||
                QMessageBox.warning(
 | 
			
		||||
                    self.toolbox,
 | 
			
		||||
                    self.tr('Error reading model', 'AddModelFromFileAction'),
 | 
			
		||||
                    self.tr('The selected file does not contain a valid model', 'AddModelFromFileAction'))
 | 
			
		||||
                return
 | 
			
		||||
            except:
 | 
			
		||||
                QMessageBox.warning(self.toolbox,
 | 
			
		||||
                                    self.tr('Error reading model', 'AddModelFromFileAction'),
 | 
			
		||||
                                    self.tr('Cannot read file', 'AddModelFromFileAction'))
 | 
			
		||||
                return
 | 
			
		||||
            destFilename = os.path.join(ModelerUtils.modelsFolders()[0], os.path.basename(filename))
 | 
			
		||||
            shutil.copyfile(filename, destFilename)
 | 
			
		||||
            QgsApplication.processingRegistry().providerById('model').refreshAlgorithms()
 | 
			
		||||
 | 
			
		||||
@ -365,15 +365,6 @@ class ModelerAlgorithm(QgsProcessingModelAlgorithm):
 | 
			
		||||
            model._name = model.modeler_name
 | 
			
		||||
        return model
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def fromFile(filename):
 | 
			
		||||
        with open(filename) as f:
 | 
			
		||||
            s = f.read()
 | 
			
		||||
        alg = ModelerAlgorithm.fromJson(s)
 | 
			
		||||
        if alg:
 | 
			
		||||
            alg.descriptionFile = filename
 | 
			
		||||
        return alg
 | 
			
		||||
 | 
			
		||||
    def toPython(self):
 | 
			
		||||
        s = ['##%s=name' % self.name()]
 | 
			
		||||
        for param in list(self.parameterComponents().values()):
 | 
			
		||||
 | 
			
		||||
@ -27,10 +27,13 @@ __revision__ = '$Format:%H$'
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from qgis.PyQt.QtXml import QDomDocument
 | 
			
		||||
 | 
			
		||||
from qgis.core import (QgsApplication,
 | 
			
		||||
                       QgsProcessingProvider,
 | 
			
		||||
                       QgsMessageLog,
 | 
			
		||||
                       QgsProcessingUtils)
 | 
			
		||||
                       QgsProcessingUtils,
 | 
			
		||||
                       QgsXmlUtils)
 | 
			
		||||
 | 
			
		||||
from processing.core.ProcessingConfig import ProcessingConfig, Setting
 | 
			
		||||
from processing.modeler.ModelerUtils import ModelerUtils
 | 
			
		||||
@ -98,13 +101,15 @@ class ModelerAlgorithmProvider(QgsProcessingProvider):
 | 
			
		||||
            return
 | 
			
		||||
        for path, subdirs, files in os.walk(folder):
 | 
			
		||||
            for descriptionFile in files:
 | 
			
		||||
                if descriptionFile.endswith('model'):
 | 
			
		||||
                if descriptionFile.endswith('model3'):
 | 
			
		||||
                    try:
 | 
			
		||||
                        fullpath = os.path.join(path, descriptionFile)
 | 
			
		||||
                        alg = ModelerAlgorithm.fromFile(fullpath)
 | 
			
		||||
                        if alg.name():
 | 
			
		||||
                            alg.descriptionFile = fullpath
 | 
			
		||||
                            self.algs.append(alg)
 | 
			
		||||
 | 
			
		||||
                        alg = ModelerAlgorithm()
 | 
			
		||||
                        if alg.fromFile(fullpath):
 | 
			
		||||
                            if alg.name():
 | 
			
		||||
                                alg.descriptionFile = fullpath
 | 
			
		||||
                                self.algs.append(alg)
 | 
			
		||||
                        else:
 | 
			
		||||
                            QgsMessageLog.logMessage(self.tr('Could not load model {0}', 'ModelerAlgorithmProvider').format(descriptionFile),
 | 
			
		||||
                                                     self.tr('Processing'), QgsMessageLog.CRITICAL)
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,8 @@ from qgis.core import (QgsApplication,
 | 
			
		||||
                       QgsSettings,
 | 
			
		||||
                       QgsMessageLog,
 | 
			
		||||
                       QgsProcessingUtils,
 | 
			
		||||
                       QgsProcessingModelAlgorithm)
 | 
			
		||||
                       QgsProcessingModelAlgorithm,
 | 
			
		||||
                       QgsXmlUtils)
 | 
			
		||||
from qgis.gui import QgsMessageBar
 | 
			
		||||
from processing.gui.HelpEditionDialog import HelpEditionDialog
 | 
			
		||||
from processing.gui.AlgorithmDialog import AlgorithmDialog
 | 
			
		||||
@ -52,6 +53,7 @@ from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
 | 
			
		||||
from processing.modeler.ModelerUtils import ModelerUtils
 | 
			
		||||
from processing.modeler.ModelerScene import ModelerScene
 | 
			
		||||
from processing.modeler.WrongModelException import WrongModelException
 | 
			
		||||
from qgis.PyQt.QtXml import QDomDocument
 | 
			
		||||
 | 
			
		||||
pluginPath = os.path.split(os.path.dirname(__file__))[0]
 | 
			
		||||
WIDGET, BASE = uic.loadUiType(
 | 
			
		||||
@ -435,25 +437,21 @@ class ModelerDialog(BASE, WIDGET):
 | 
			
		||||
                self, self.tr('Warning'), self.tr('Please enter group and model names before saving')
 | 
			
		||||
            )
 | 
			
		||||
            return
 | 
			
		||||
        self.model._name = str(self.textName.text())
 | 
			
		||||
        self.model._group = str(self.textGroup.text())
 | 
			
		||||
        self.model.setName(str(self.textName.text()))
 | 
			
		||||
        self.model.setGroup(str(self.textGroup.text()))
 | 
			
		||||
        if self.model.descriptionFile is not None and not saveAs:
 | 
			
		||||
            filename = self.model.descriptionFile
 | 
			
		||||
        else:
 | 
			
		||||
            filename, filter = QFileDialog.getSaveFileName(self,
 | 
			
		||||
                                                           self.tr('Save Model'),
 | 
			
		||||
                                                           ModelerUtils.modelsFolders()[0],
 | 
			
		||||
                                                           self.tr('Processing models (*.model)'))
 | 
			
		||||
                                                           self.tr('Processing models (*.model3)'))
 | 
			
		||||
            if filename:
 | 
			
		||||
                if not filename.endswith('.model'):
 | 
			
		||||
                    filename += '.model'
 | 
			
		||||
                if not filename.endswith('.model3'):
 | 
			
		||||
                    filename += '.model3'
 | 
			
		||||
                self.model.descriptionFile = filename
 | 
			
		||||
        if filename:
 | 
			
		||||
            text = self.model.toJson()
 | 
			
		||||
            try:
 | 
			
		||||
                with codecs.open(filename, 'w', encoding='utf-8') as fout:
 | 
			
		||||
                    fout.write(text)
 | 
			
		||||
            except:
 | 
			
		||||
            if not self.model.toFile(filename):
 | 
			
		||||
                if saveAs:
 | 
			
		||||
                    QMessageBox.warning(self, self.tr('I/O error'),
 | 
			
		||||
                                        self.tr('Unable to save edits. Reason:\n {0}').format(str(sys.exc_info()[1])))
 | 
			
		||||
@ -475,28 +473,22 @@ class ModelerDialog(BASE, WIDGET):
 | 
			
		||||
                                                                ModelerUtils.modelsFolders()[0],
 | 
			
		||||
                                                                self.tr('Processing models (*.model *.MODEL)'))
 | 
			
		||||
        if filename:
 | 
			
		||||
            try:
 | 
			
		||||
                alg = ModelerAlgorithm.fromFile(filename)
 | 
			
		||||
            alg = ModelerAlgorithm()
 | 
			
		||||
            if alg.fromFile(filename):
 | 
			
		||||
                self.model = alg
 | 
			
		||||
                self.textGroup.setText(alg._group)
 | 
			
		||||
                self.textName.setText(alg._name)
 | 
			
		||||
                self.textGroup.setText(alg.group())
 | 
			
		||||
                self.textName.setText(alg.name())
 | 
			
		||||
                self.repaintModel()
 | 
			
		||||
 | 
			
		||||
                self.view.centerOn(0, 0)
 | 
			
		||||
                self.hasChanged = False
 | 
			
		||||
            except WrongModelException as e:
 | 
			
		||||
                QgsMessageLog.logMessage(self.tr('Could not load model {0}\n{1}').format(filename, e.msg),
 | 
			
		||||
            else:
 | 
			
		||||
                QgsMessageLog.logMessage(self.tr('Could not load model {0}').format(filename),
 | 
			
		||||
                                         self.tr('Processing'),
 | 
			
		||||
                                         QgsMessageLog.CRITICAL)
 | 
			
		||||
                QMessageBox.critical(self, self.tr('Could not open model'),
 | 
			
		||||
                                     self.tr('The selected model could not be loaded.\n'
 | 
			
		||||
                                             'See the log for more information.'))
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                QgsMessageLog.logMessage(self.tr('Could not load model {0}\n{1}').format(filename, e.args[0]),
 | 
			
		||||
                                         self.tr('Processing'), QgsMessageLog.CRITICAL)
 | 
			
		||||
                QMessageBox.critical(self, self.tr('Could not open model'),
 | 
			
		||||
                                     self.tr('The selected model could not be loaded.\n'
 | 
			
		||||
                                             'See the log for more information.'))
 | 
			
		||||
 | 
			
		||||
    def repaintModel(self, controls=True):
 | 
			
		||||
        self.scene = ModelerScene(self, dialog=self)
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,9 @@
 | 
			
		||||
 | 
			
		||||
#include "qgsprocessingmodelalgorithm.h"
 | 
			
		||||
#include "qgsprocessingregistry.h"
 | 
			
		||||
#include "qgsxmlutils.h"
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
 | 
			
		||||
QgsProcessingModelAlgorithm::ChildAlgorithm::ChildAlgorithm( const QString &algorithmId )
 | 
			
		||||
  : mAlgorithmId( algorithmId )
 | 
			
		||||
@ -78,6 +81,22 @@ QgsProcessingModelAlgorithm::Component::Component( const QString &description )
 | 
			
		||||
  : mDescription( description )
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
void QgsProcessingModelAlgorithm::Component::saveCommonProperties( QVariantMap &map ) const
 | 
			
		||||
{
 | 
			
		||||
  map.insert( QStringLiteral( "component_pos_x" ), mPosition.x() );
 | 
			
		||||
  map.insert( QStringLiteral( "component_pos_y" ), mPosition.y() );
 | 
			
		||||
  map.insert( QStringLiteral( "component_description" ), mDescription );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsProcessingModelAlgorithm::Component::restoreCommonProperties( const QVariantMap &map )
 | 
			
		||||
{
 | 
			
		||||
  QPointF pos;
 | 
			
		||||
  pos.setX( map.value( QStringLiteral( "component_pos_x" ) ).toDouble() );
 | 
			
		||||
  pos.setY( map.value( QStringLiteral( "component_pos_y" ) ).toDouble() );
 | 
			
		||||
  mPosition = pos;
 | 
			
		||||
  mDescription = map.value( QStringLiteral( "component_description" ) ).toString();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList QgsProcessingModelAlgorithm::ChildAlgorithm::dependencies() const
 | 
			
		||||
{
 | 
			
		||||
  return mDependencies;
 | 
			
		||||
@ -113,6 +132,77 @@ void QgsProcessingModelAlgorithm::ChildAlgorithm::setModelOutputs( const QMap<QS
 | 
			
		||||
  mModelOutputs = modelOutputs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant QgsProcessingModelAlgorithm::ChildAlgorithm::toVariant() const
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map;
 | 
			
		||||
  map.insert( QStringLiteral( "id" ), mId );
 | 
			
		||||
  map.insert( QStringLiteral( "alg_id" ), mAlgorithmId );
 | 
			
		||||
  map.insert( QStringLiteral( "active" ), mActive );
 | 
			
		||||
  map.insert( QStringLiteral( "dependencies" ), mDependencies );
 | 
			
		||||
  map.insert( QStringLiteral( "parameters_collapsed" ), mParametersCollapsed );
 | 
			
		||||
  map.insert( QStringLiteral( "outputs_collapsed" ), mOutputsCollapsed );
 | 
			
		||||
 | 
			
		||||
  saveCommonProperties( map );
 | 
			
		||||
 | 
			
		||||
  QVariantMap paramMap;
 | 
			
		||||
  QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource >::const_iterator paramIt = mParams.constBegin();
 | 
			
		||||
  for ( ; paramIt != mParams.constEnd(); ++paramIt )
 | 
			
		||||
  {
 | 
			
		||||
    paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
 | 
			
		||||
  }
 | 
			
		||||
  map.insert( "params", paramMap );
 | 
			
		||||
 | 
			
		||||
  QVariantMap outputMap;
 | 
			
		||||
  QMap< QString, QgsProcessingModelAlgorithm::ModelOutput >::const_iterator outputIt = mModelOutputs.constBegin();
 | 
			
		||||
  for ( ; outputIt != mModelOutputs.constEnd(); ++outputIt )
 | 
			
		||||
  {
 | 
			
		||||
    outputMap.insert( outputIt.key(), outputIt.value().toVariant() );
 | 
			
		||||
  }
 | 
			
		||||
  map.insert( "outputs", outputMap );
 | 
			
		||||
 | 
			
		||||
  return map;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::ChildAlgorithm::loadVariant( const QVariant &child )
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map = child.toMap();
 | 
			
		||||
 | 
			
		||||
  mId = map.value( QStringLiteral( "id" ) ).toString();
 | 
			
		||||
  mAlgorithmId = map.value( QStringLiteral( "alg_id" ) ).toString();
 | 
			
		||||
  mActive = map.value( QStringLiteral( "active" ) ).toBool();
 | 
			
		||||
  mDependencies = map.value( QStringLiteral( "dependencies" ) ).toStringList();
 | 
			
		||||
  mParametersCollapsed = map.value( QStringLiteral( "parameters_collapsed" ) ).toBool();
 | 
			
		||||
  mOutputsCollapsed = map.value( QStringLiteral( "outputs_collapsed" ) ).toBool();
 | 
			
		||||
 | 
			
		||||
  restoreCommonProperties( map );
 | 
			
		||||
 | 
			
		||||
  mParams.clear();
 | 
			
		||||
  QVariantMap paramMap = map.value( QStringLiteral( "params" ) ).toMap();
 | 
			
		||||
  QVariantMap::const_iterator paramIt = paramMap.constBegin();
 | 
			
		||||
  for ( ; paramIt != paramMap.constEnd(); ++paramIt )
 | 
			
		||||
  {
 | 
			
		||||
    ChildParameterSource param;
 | 
			
		||||
    if ( !param.loadVariant( paramIt.value().toMap() ) )
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    mParams.insert( paramIt.key(), param );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mModelOutputs.clear();
 | 
			
		||||
  QVariantMap outputMap = map.value( QStringLiteral( "outputs" ) ).toMap();
 | 
			
		||||
  QVariantMap::const_iterator outputIt = outputMap.constBegin();
 | 
			
		||||
  for ( ; outputIt != outputMap.constEnd(); ++outputIt )
 | 
			
		||||
  {
 | 
			
		||||
    ModelOutput output;
 | 
			
		||||
    if ( !output.loadVariant( outputIt.value().toMap() ) )
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    mModelOutputs.insert( outputIt.key(), output );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::ChildAlgorithm::parametersCollapsed() const
 | 
			
		||||
{
 | 
			
		||||
  return mParametersCollapsed;
 | 
			
		||||
@ -201,6 +291,16 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
 | 
			
		||||
  return QVariantMap();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsProcessingModelAlgorithm::setName( const QString &name )
 | 
			
		||||
{
 | 
			
		||||
  mModelName = name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsProcessingModelAlgorithm::setGroup( const QString &group )
 | 
			
		||||
{
 | 
			
		||||
  mModelGroup = group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QMap<QString, QgsProcessingModelAlgorithm::ChildAlgorithm> QgsProcessingModelAlgorithm::childAlgorithms() const
 | 
			
		||||
{
 | 
			
		||||
  return mChildAlgorithms;
 | 
			
		||||
@ -227,6 +327,99 @@ QgsProcessingModelAlgorithm::ModelParameter &QgsProcessingModelAlgorithm::parame
 | 
			
		||||
  return mParameterComponents[ name ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant QgsProcessingModelAlgorithm::toVariant() const
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map;
 | 
			
		||||
  map.insert( QStringLiteral( "model_name" ), mModelName );
 | 
			
		||||
  map.insert( QStringLiteral( "model_group" ), mModelGroup );
 | 
			
		||||
 | 
			
		||||
  QVariantMap childMap;
 | 
			
		||||
  QMap< QString, ChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 | 
			
		||||
  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 | 
			
		||||
  {
 | 
			
		||||
    childMap.insert( childIt.key(), childIt.value().toVariant() );
 | 
			
		||||
  }
 | 
			
		||||
  map.insert( "children", childMap );
 | 
			
		||||
 | 
			
		||||
  QVariantMap paramMap;
 | 
			
		||||
  QMap< QString, ModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
 | 
			
		||||
  for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
 | 
			
		||||
  {
 | 
			
		||||
    paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
 | 
			
		||||
  }
 | 
			
		||||
  map.insert( "parameters", paramMap );
 | 
			
		||||
 | 
			
		||||
  return map;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::loadVariant( const QVariant &model )
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map = model.toMap();
 | 
			
		||||
 | 
			
		||||
  mModelName = map.value( QStringLiteral( "model_name" ) ).toString();
 | 
			
		||||
  mModelGroup = map.value( QStringLiteral( "model_group" ) ).toString();
 | 
			
		||||
 | 
			
		||||
  mChildAlgorithms.clear();
 | 
			
		||||
  QVariantMap childMap = map.value( QStringLiteral( "children" ) ).toMap();
 | 
			
		||||
  QVariantMap::const_iterator childIt = childMap.constBegin();
 | 
			
		||||
  for ( ; childIt != childMap.constEnd(); ++childIt )
 | 
			
		||||
  {
 | 
			
		||||
    ChildAlgorithm child;
 | 
			
		||||
    if ( !child.loadVariant( childIt.value() ) )
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    mChildAlgorithms.insert( child.childId(), child );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mParameterComponents.clear();
 | 
			
		||||
  QVariantMap paramMap = map.value( QStringLiteral( "parameters" ) ).toMap();
 | 
			
		||||
  QVariantMap::const_iterator paramIt = paramMap.constBegin();
 | 
			
		||||
  for ( ; paramIt != paramMap.constEnd(); ++paramIt )
 | 
			
		||||
  {
 | 
			
		||||
    ModelParameter param;
 | 
			
		||||
    if ( !param.loadVariant( paramIt.value().toMap() ) )
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    mParameterComponents.insert( param.parameterName(), param );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::toFile( const QString &path ) const
 | 
			
		||||
{
 | 
			
		||||
  QDomDocument doc = QDomDocument( "model" );
 | 
			
		||||
  QDomElement elem = QgsXmlUtils::writeVariant( toVariant(), doc );
 | 
			
		||||
  doc.appendChild( elem );
 | 
			
		||||
 | 
			
		||||
  QFile file( path );
 | 
			
		||||
  if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
 | 
			
		||||
  {
 | 
			
		||||
    QTextStream stream( &file );
 | 
			
		||||
    doc.save( stream, 2 );
 | 
			
		||||
    file.close();
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::fromFile( const QString &path )
 | 
			
		||||
{
 | 
			
		||||
  QDomDocument doc;
 | 
			
		||||
 | 
			
		||||
  QFile file( path );
 | 
			
		||||
  if ( file.open( QFile::ReadOnly ) )
 | 
			
		||||
  {
 | 
			
		||||
    if ( !doc.setContent( &file ) )
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    file.close();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QVariant props = QgsXmlUtils::readVariant( doc.firstChildElement() );
 | 
			
		||||
  return loadVariant( props );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsProcessingModelAlgorithm::setChildAlgorithms( const QMap<QString, ChildAlgorithm> &childAlgorithms )
 | 
			
		||||
{
 | 
			
		||||
  mChildAlgorithms = childAlgorithms;
 | 
			
		||||
@ -484,13 +677,91 @@ QgsProcessingModelAlgorithm::ChildParameterSource::Source QgsProcessingModelAlgo
 | 
			
		||||
  return mSource;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant QgsProcessingModelAlgorithm::ChildParameterSource::toVariant() const
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map;
 | 
			
		||||
  map.insert( QStringLiteral( "source" ), mSource );
 | 
			
		||||
  switch ( mSource )
 | 
			
		||||
  {
 | 
			
		||||
    case ModelParameter:
 | 
			
		||||
      map.insert( QStringLiteral( "parameter_name" ), mParameterName );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case ChildOutput:
 | 
			
		||||
      map.insert( QStringLiteral( "child_id" ), mChildId );
 | 
			
		||||
      map.insert( QStringLiteral( "output_name" ), mOutputName );
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case StaticValue:
 | 
			
		||||
      map.insert( QStringLiteral( "static_value" ), mStaticValue );
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  return map;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::ChildParameterSource::loadVariant( const QVariantMap &map )
 | 
			
		||||
{
 | 
			
		||||
  mSource = static_cast< Source >( map.value( QStringLiteral( "source" ) ).toInt() );
 | 
			
		||||
  switch ( mSource )
 | 
			
		||||
  {
 | 
			
		||||
    case ModelParameter:
 | 
			
		||||
      mParameterName = map.value( QStringLiteral( "parameter_name" ) ).toString();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case ChildOutput:
 | 
			
		||||
      mChildId = map.value( QStringLiteral( "child_id" ) ).toString();
 | 
			
		||||
      mOutputName = map.value( QStringLiteral( "output_name" ) ).toString();
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case StaticValue:
 | 
			
		||||
      mStaticValue = map.value( QStringLiteral( "static_value" ) );
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsProcessingModelAlgorithm::ModelOutput::ModelOutput( const QString &description )
 | 
			
		||||
  : QgsProcessingModelAlgorithm::Component( description )
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
QVariant QgsProcessingModelAlgorithm::ModelOutput::toVariant() const
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map;
 | 
			
		||||
  map.insert( QStringLiteral( "child_id" ), mChildId );
 | 
			
		||||
  map.insert( QStringLiteral( "output_name" ), mOutputName );
 | 
			
		||||
  saveCommonProperties( map );
 | 
			
		||||
  return map;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::ModelOutput::loadVariant( const QVariantMap &map )
 | 
			
		||||
{
 | 
			
		||||
  mChildId = map.value( QStringLiteral( "child_id" ) ).toString();
 | 
			
		||||
  mOutputName = map.value( QStringLiteral( "output_name" ) ).toString();
 | 
			
		||||
  restoreCommonProperties( map );
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsProcessingModelAlgorithm::ModelParameter::ModelParameter( const QString ¶meterName )
 | 
			
		||||
  : QgsProcessingModelAlgorithm::Component()
 | 
			
		||||
  , mParameterName( parameterName )
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant QgsProcessingModelAlgorithm::ModelParameter::toVariant() const
 | 
			
		||||
{
 | 
			
		||||
  QVariantMap map;
 | 
			
		||||
  map.insert( QStringLiteral( "name" ), mParameterName );
 | 
			
		||||
 | 
			
		||||
  //TODO - parameter definition
 | 
			
		||||
 | 
			
		||||
  saveCommonProperties( map );
 | 
			
		||||
  return map;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QgsProcessingModelAlgorithm::ModelParameter::loadVariant( const QVariantMap &map )
 | 
			
		||||
{
 | 
			
		||||
  mParameterName = map.value( QStringLiteral( "name" ) ).toString();
 | 
			
		||||
  restoreCommonProperties( map );
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -140,6 +140,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
         */
 | 
			
		||||
        void setOutputName( const QString &name ) { mOutputName = name; mSource = ChildOutput; }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Saves this source to a QVariant.
 | 
			
		||||
         * \see loadVariant()
 | 
			
		||||
         */
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Loads this source from a QVariantMap.
 | 
			
		||||
         * \see toVariant()
 | 
			
		||||
         */
 | 
			
		||||
        bool loadVariant( const QVariantMap &map );
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
 | 
			
		||||
        Source mSource = StaticValue;
 | 
			
		||||
@ -194,6 +206,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
        //! Copies are protected to avoid slicing
 | 
			
		||||
        Component &operator=( const QgsProcessingModelAlgorithm::Component &other ) = default;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Saves the component properties to a QVariantMap.
 | 
			
		||||
         * \see restoreCommonProperties()
 | 
			
		||||
         */
 | 
			
		||||
        void saveCommonProperties( QVariantMap &map ) const;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Restores the component properties from a QVariantMap.
 | 
			
		||||
         * \see saveCommonProperties()
 | 
			
		||||
         */
 | 
			
		||||
        void restoreCommonProperties( const QVariantMap &map );
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
 | 
			
		||||
        //! Position of component within model
 | 
			
		||||
@ -232,6 +256,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
         */
 | 
			
		||||
        void setParameterName( const QString &name ) { mParameterName = name; }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Saves this parameter to a QVariant.
 | 
			
		||||
         * \see loadVariant()
 | 
			
		||||
         */
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Loads this parameter from a QVariantMap.
 | 
			
		||||
         * \see toVariant()
 | 
			
		||||
         */
 | 
			
		||||
        bool loadVariant( const QVariantMap &map );
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
 | 
			
		||||
        QString mParameterName;
 | 
			
		||||
@ -277,6 +313,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
         */
 | 
			
		||||
        void setOutputName( const QString &name ) { mOutputName = name; }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Saves this output to a QVariant.
 | 
			
		||||
         * \see loadVariant()
 | 
			
		||||
         */
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Loads this output from a QVariantMap.
 | 
			
		||||
         * \see toVariant()
 | 
			
		||||
         */
 | 
			
		||||
        bool loadVariant( const QVariantMap &map );
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
 | 
			
		||||
        QString mChildId;
 | 
			
		||||
@ -456,6 +504,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
         */
 | 
			
		||||
        void setModelOutputs( const QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> &outputs );
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Saves this child to a QVariant.
 | 
			
		||||
         * \see loadVariant()
 | 
			
		||||
         */
 | 
			
		||||
        QVariant toVariant() const;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Loads this child from a QVariant.
 | 
			
		||||
         * \see toVariant()
 | 
			
		||||
         */
 | 
			
		||||
        bool loadVariant( const QVariant &child );
 | 
			
		||||
 | 
			
		||||
      private:
 | 
			
		||||
 | 
			
		||||
        QString mId;
 | 
			
		||||
@ -494,6 +554,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
    QVariantMap processAlgorithm( const QVariantMap ¶meters,
 | 
			
		||||
                                  QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const override;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the model \a name.
 | 
			
		||||
     * \see name()
 | 
			
		||||
     */
 | 
			
		||||
    void setName( const QString &name );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the model \a group.
 | 
			
		||||
     * \see group()
 | 
			
		||||
     */
 | 
			
		||||
    void setGroup( const QString &group );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the map of child algorithms contained in the model. The keys
 | 
			
		||||
     * are the child algorithm ids (see QgsProcessingModelAlgorithm::ChildAlgorithm::childId()).
 | 
			
		||||
@ -650,6 +722,18 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
     */
 | 
			
		||||
    QgsProcessingModelAlgorithm::ModelParameter ¶meterComponent( const QString &name );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Writes the model to a file, at the specified \a path.
 | 
			
		||||
     * \see fromFile()
 | 
			
		||||
     */
 | 
			
		||||
    bool toFile( const QString &path ) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reads the model from a file, at the specified \a path.
 | 
			
		||||
     * \see toFile()
 | 
			
		||||
     */
 | 
			
		||||
    bool fromFile( const QString &path );
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
    QString mModelName;
 | 
			
		||||
@ -662,6 +746,24 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
 | 
			
		||||
    void dependsOnChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
 | 
			
		||||
    void dependentChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Saves this model to a QVariantMap, wrapped in a QVariant.
 | 
			
		||||
     * You can use QgsXmlUtils::writeVariant to save it to an XML document.
 | 
			
		||||
     *
 | 
			
		||||
     * \see loadVariant()
 | 
			
		||||
     */
 | 
			
		||||
    QVariant toVariant() const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Loads this model from a QVariantMap, wrapped in a QVariant.
 | 
			
		||||
     * You can use QgsXmlUtils::readVariant to load it from an XML document.
 | 
			
		||||
     *
 | 
			
		||||
     * \see toVariant()
 | 
			
		||||
     */
 | 
			
		||||
    bool loadVariant( const QVariant &model );
 | 
			
		||||
 | 
			
		||||
    friend class TestQgsProcessing;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QGSPROCESSINGMODELALGORITHM_H
 | 
			
		||||
 | 
			
		||||
@ -132,6 +132,19 @@ QDomElement QgsXmlUtils::writeVariant( const QVariant &value, QDomDocument &doc
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case QVariant::StringList:
 | 
			
		||||
    {
 | 
			
		||||
      QStringList list = value.toStringList();
 | 
			
		||||
 | 
			
		||||
      Q_FOREACH ( const QString &value, list )
 | 
			
		||||
      {
 | 
			
		||||
        QDomElement valueElement = writeVariant( value, doc );
 | 
			
		||||
        element.appendChild( valueElement );
 | 
			
		||||
        element.setAttribute( QStringLiteral( "type" ), QStringLiteral( "StringList" ) );
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case QVariant::Int:
 | 
			
		||||
    case QVariant::Bool:
 | 
			
		||||
    case QVariant::Double:
 | 
			
		||||
@ -193,6 +206,17 @@ QVariant QgsXmlUtils::readVariant( const QDomElement &element )
 | 
			
		||||
    }
 | 
			
		||||
    return list;
 | 
			
		||||
  }
 | 
			
		||||
  else if ( type == QLatin1String( "StringList" ) )
 | 
			
		||||
  {
 | 
			
		||||
    QStringList list;
 | 
			
		||||
    QDomNodeList values = element.childNodes();
 | 
			
		||||
    for ( int i = 0; i < values.count(); ++i )
 | 
			
		||||
    {
 | 
			
		||||
      QDomElement elem = values.at( i ).toElement();
 | 
			
		||||
      list.append( readVariant( elem ).toString() );
 | 
			
		||||
    }
 | 
			
		||||
    return list;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return QVariant();
 | 
			
		||||
 | 
			
		||||
@ -32,6 +32,7 @@
 | 
			
		||||
#include "qgsgeometry.h"
 | 
			
		||||
#include "qgsvectorfilewriter.h"
 | 
			
		||||
#include "qgsexpressioncontext.h"
 | 
			
		||||
#include "qgsxmlutils.h"
 | 
			
		||||
 | 
			
		||||
class DummyAlgorithm : public QgsProcessingAlgorithm
 | 
			
		||||
{
 | 
			
		||||
@ -3065,6 +3066,11 @@ void TestQgsProcessing::modelerAlgorithm()
 | 
			
		||||
  QCOMPARE( alg.name(), QStringLiteral( "test" ) );
 | 
			
		||||
  QCOMPARE( alg.displayName(), QStringLiteral( "test" ) );
 | 
			
		||||
  QCOMPARE( alg.group(), QStringLiteral( "testGroup" ) );
 | 
			
		||||
  alg.setName( QStringLiteral( "test2" ) );
 | 
			
		||||
  QCOMPARE( alg.name(), QStringLiteral( "test2" ) );
 | 
			
		||||
  QCOMPARE( alg.displayName(), QStringLiteral( "test2" ) );
 | 
			
		||||
  alg.setGroup( QStringLiteral( "group2" ) );
 | 
			
		||||
  QCOMPARE( alg.group(), QStringLiteral( "group2" ) );
 | 
			
		||||
 | 
			
		||||
  // child algorithms
 | 
			
		||||
  QMap<QString, QgsProcessingModelAlgorithm::ChildAlgorithm> algs;
 | 
			
		||||
@ -3299,6 +3305,90 @@ void TestQgsProcessing::modelerAlgorithm()
 | 
			
		||||
  c10.addParameterSource( "y", QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "p1" ) );
 | 
			
		||||
  alg4.setChildAlgorithm( c10 );
 | 
			
		||||
  QVERIFY( alg4.childAlgorithmsDependOnParameter( "p1" ) );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // to/from XML
 | 
			
		||||
  QgsProcessingModelAlgorithm alg5( "test", "testGroup" );
 | 
			
		||||
  QgsProcessingModelAlgorithm::ChildAlgorithm alg5c1;
 | 
			
		||||
  alg5c1.setChildId( "cx1" );
 | 
			
		||||
  alg5c1.setAlgorithmId( "buffer" );
 | 
			
		||||
  alg5c1.addParameterSource( "x", QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "p1" ) );
 | 
			
		||||
  alg5c1.addParameterSource( "y", QgsProcessingModelAlgorithm::ChildParameterSource::fromChildOutput( "cx2", "out3" ) );
 | 
			
		||||
  alg5c1.addParameterSource( "z", QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( 5 ) );
 | 
			
		||||
  alg5c1.setActive( true );
 | 
			
		||||
  alg5c1.setOutputsCollapsed( true );
 | 
			
		||||
  alg5c1.setParametersCollapsed( true );
 | 
			
		||||
  alg5c1.setDescription( "child 1" );
 | 
			
		||||
  alg5c1.setPosition( QPointF( 1, 2 ) );
 | 
			
		||||
  QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> alg5c1outputs;
 | 
			
		||||
  QgsProcessingModelAlgorithm::ModelOutput alg5c1out1;
 | 
			
		||||
  alg5c1out1.setDescription( QStringLiteral( "my output" ) );
 | 
			
		||||
  alg5c1out1.setPosition( QPointF( 3, 4 ) );
 | 
			
		||||
  alg5c1outputs.insert( QStringLiteral( "a" ), alg5c1out1 );
 | 
			
		||||
  alg5c1.setModelOutputs( alg5c1outputs );
 | 
			
		||||
  alg5.addChildAlgorithm( alg5c1 );
 | 
			
		||||
 | 
			
		||||
  QgsProcessingModelAlgorithm::ChildAlgorithm alg5c2;
 | 
			
		||||
  alg5c2.setChildId( "cx2" );
 | 
			
		||||
  alg5c2.setActive( false );
 | 
			
		||||
  alg5c2.setOutputsCollapsed( false );
 | 
			
		||||
  alg5c2.setParametersCollapsed( false );
 | 
			
		||||
  alg5c2.setDependencies( QStringList() << "a" << "b" );
 | 
			
		||||
  alg5.addChildAlgorithm( alg5c2 );
 | 
			
		||||
 | 
			
		||||
  QMap<QString, QgsProcessingModelAlgorithm::ModelParameter> alg5pComponents;
 | 
			
		||||
  QgsProcessingModelAlgorithm::ModelParameter alg5pc1;
 | 
			
		||||
  alg5pc1.setParameterName( QStringLiteral( "my_param" ) );
 | 
			
		||||
  alg5pc1.setPosition( QPointF( 11, 12 ) );
 | 
			
		||||
  alg5pComponents.insert( QStringLiteral( "my_param" ), alg5pc1 );
 | 
			
		||||
  alg5.setParameterComponents( alg5pComponents );
 | 
			
		||||
 | 
			
		||||
  QDomDocument doc = QDomDocument( "model" );
 | 
			
		||||
  QDomElement elem = QgsXmlUtils::writeVariant( alg5.toVariant(), doc );
 | 
			
		||||
  doc.appendChild( elem );
 | 
			
		||||
 | 
			
		||||
  QgsProcessingModelAlgorithm alg6;
 | 
			
		||||
  QVERIFY( alg6.loadVariant( QgsXmlUtils::readVariant( doc.firstChildElement() ) ) );
 | 
			
		||||
  QCOMPARE( alg6.name(), QStringLiteral( "test" ) );
 | 
			
		||||
  QCOMPARE( alg6.group(), QStringLiteral( "testGroup" ) );
 | 
			
		||||
  QgsProcessingModelAlgorithm::ChildAlgorithm alg6c1 = alg6.childAlgorithm( "cx1" );
 | 
			
		||||
  QCOMPARE( alg6c1.childId(), QStringLiteral( "cx1" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.algorithmId(), QStringLiteral( "buffer" ) );
 | 
			
		||||
  QVERIFY( alg6c1.isActive() );
 | 
			
		||||
  QVERIFY( alg6c1.outputsCollapsed() );
 | 
			
		||||
  QVERIFY( alg6c1.parametersCollapsed() );
 | 
			
		||||
  QCOMPARE( alg6c1.description(), QStringLiteral( "child 1" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.position().x(), 1.0 );
 | 
			
		||||
  QCOMPARE( alg6c1.position().y(), 2.0 );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().count(), 3 );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "x" ).source(), QgsProcessingModelAlgorithm::ChildParameterSource::ModelParameter );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "x" ).parameterName(), QStringLiteral( "p1" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "y" ).source(), QgsProcessingModelAlgorithm::ChildParameterSource::ChildOutput );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "y" ).outputChildId(), QStringLiteral( "cx2" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "y" ).outputName(), QStringLiteral( "out3" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "z" ).source(), QgsProcessingModelAlgorithm::ChildParameterSource::StaticValue );
 | 
			
		||||
  QCOMPARE( alg6c1.parameterSources().value( "z" ).staticValue().toInt(), 5 );
 | 
			
		||||
  QCOMPARE( alg6c1.modelOutputs().count(), 1 );
 | 
			
		||||
  QCOMPARE( alg6c1.modelOutputs().value( QStringLiteral( "a" ) ).description(), QStringLiteral( "my output" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.modelOutput( "a" ).description(), QStringLiteral( "my output" ) );
 | 
			
		||||
  QCOMPARE( alg6c1.modelOutput( "a" ).position().x(), 3.0 );
 | 
			
		||||
  QCOMPARE( alg6c1.modelOutput( "a" ).position().y(), 4.0 );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  QgsProcessingModelAlgorithm::ChildAlgorithm alg6c2 = alg6.childAlgorithm( "cx2" );
 | 
			
		||||
  QCOMPARE( alg6c2.childId(), QStringLiteral( "cx2" ) );
 | 
			
		||||
  QVERIFY( !alg6c2.isActive() );
 | 
			
		||||
  QVERIFY( !alg6c2.outputsCollapsed() );
 | 
			
		||||
  QVERIFY( !alg6c2.parametersCollapsed() );
 | 
			
		||||
  QCOMPARE( alg6c2.dependencies(), QStringList() << "a" << "b" );
 | 
			
		||||
 | 
			
		||||
  QCOMPARE( alg6.parameterComponents().count(), 1 );
 | 
			
		||||
  QCOMPARE( alg6.parameterComponents().value( QStringLiteral( "my_param" ) ).parameterName(), QStringLiteral( "my_param" ) );
 | 
			
		||||
  QCOMPARE( alg6.parameterComponent( "my_param" ).parameterName(), QStringLiteral( "my_param" ) );
 | 
			
		||||
  QCOMPARE( alg6.parameterComponent( "my_param" ).position().x(), 11.0 );
 | 
			
		||||
  QCOMPARE( alg6.parameterComponent( "my_param" ).position().y(), 12.0 );
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QGSTEST_MAIN( TestQgsProcessing )
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user