diff --git a/images/images.qrc b/images/images.qrc index 8e67eddcec90..14c43a6eaca8 100644 --- a/images/images.qrc +++ b/images/images.qrc @@ -1009,6 +1009,7 @@ themes/default/mActionTextInsideRect.svg themes/default/mIconLabelingRules.svg themes/default/mIconStac.svg + themes/default/stacked-diagram.svg qgis_tips/symbol_levels.png diff --git a/images/themes/default/propertyicons/meshvectors.svg b/images/themes/default/propertyicons/meshvectors.svg index b2659f1e7f38..ad8c3e722ab0 100644 --- a/images/themes/default/propertyicons/meshvectors.svg +++ b/images/themes/default/propertyicons/meshvectors.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/themes/default/stacked-diagram.svg b/images/themes/default/stacked-diagram.svg new file mode 100644 index 000000000000..117ab3be2de0 --- /dev/null +++ b/images/themes/default/stacked-diagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index 0f59f8308705..b8201f90ad7d 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -6228,6 +6228,9 @@ QgsProcessingAlgorithm.Flag.FlagRequiresProject = Qgis.ProcessingAlgorithmFlag.RequiresProject QgsProcessingAlgorithm.FlagRequiresProject.is_monkey_patched = True QgsProcessingAlgorithm.FlagRequiresProject.__doc__ = "The algorithm requires that a valid QgsProject is available from the processing context in order to execute" +QgsProcessingAlgorithm.SecurityRisk = Qgis.ProcessingAlgorithmFlag.SecurityRisk +QgsProcessingAlgorithm.SecurityRisk.is_monkey_patched = True +QgsProcessingAlgorithm.SecurityRisk.__doc__ = "The algorithm represents a potential security risk if executed with untrusted inputs. \n.. versionadded:: 3.40" QgsProcessingAlgorithm.FlagDeprecated = Qgis.ProcessingAlgorithmFlag.Deprecated QgsProcessingAlgorithm.Flag.FlagDeprecated = Qgis.ProcessingAlgorithmFlag.Deprecated QgsProcessingAlgorithm.FlagDeprecated.is_monkey_patched = True @@ -6296,6 +6299,10 @@ Available as ``QgsProcessingAlgorithm.FlagRequiresProject`` in older QGIS releases. +* ``SecurityRisk``: The algorithm represents a potential security risk if executed with untrusted inputs. + + .. versionadded:: 3.40 + * ``Deprecated``: Algorithm is deprecated Available as ``QgsProcessingAlgorithm.FlagDeprecated`` in older QGIS releases. diff --git a/python/PyQt6/core/auto_generated/diagram/qgsdiagram.sip.in b/python/PyQt6/core/auto_generated/diagram/qgsdiagram.sip.in index 3198a5e9ef4d..39ba28e4a10c 100644 --- a/python/PyQt6/core/auto_generated/diagram/qgsdiagram.sip.in +++ b/python/PyQt6/core/auto_generated/diagram/qgsdiagram.sip.in @@ -27,9 +27,9 @@ Base class for all diagram types. sipType = sipType_QgsHistogramDiagram; else if ( sipCpp->diagramName() == QLatin1String( "Text" ) ) sipType = sipType_QgsTextDiagram; - else if ( sipCpp->diagramName() == QLatin1String( "StackedBar" ) ) - sipType = sipType_QgsStackedBarDiagram; else if ( sipCpp->diagramName() == QLatin1String( "Stacked" ) ) + sipType = sipType_QgsStackedBarDiagram; + else if ( sipCpp->diagramName() == QLatin1String( "StackedDiagram" ) ) sipType = sipType_QgsStackedDiagram; else sipType = NULL; diff --git a/python/PyQt6/core/auto_generated/layertree/qgscolorramplegendnode.sip.in b/python/PyQt6/core/auto_generated/layertree/qgscolorramplegendnode.sip.in index 5ff845be34ef..ca6ff9325755 100644 --- a/python/PyQt6/core/auto_generated/layertree/qgscolorramplegendnode.sip.in +++ b/python/PyQt6/core/auto_generated/layertree/qgscolorramplegendnode.sip.in @@ -23,7 +23,8 @@ A legend node which renders a color ramp. public: QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp /Transfer/, - const QString &minimumLabel, const QString &maximumLabel, QObject *parent /TransferThis/ = 0 ); + const QString &minimumLabel, const QString &maximumLabel, QObject *parent /TransferThis/ = 0, + const QString &key = QString(), const QString &parentKey = QString() ); %Docstring Constructor for QgsColorRampLegendNode. @@ -32,11 +33,14 @@ Constructor for QgsColorRampLegendNode. :param minimumLabel: label text to render for the minimum value in the ramp :param maximumLabel: label text to render for the maximum value in the ramp :param parent: attach a parent QObject to the legend node. +:param key: rule key. optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.40) +:param parentKey: rule key of parent (since QGIS 3.40) %End QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp /Transfer/, const QgsColorRampLegendNodeSettings &settings, double minimumValue, - double maximumValue, QObject *parent /TransferThis/ = 0 ); + double maximumValue, QObject *parent /TransferThis/ = 0, + const QString &key = QString(), const QString &parentKey = QString() ); %Docstring Constructor for QgsColorRampLegendNode. @@ -46,6 +50,8 @@ Constructor for QgsColorRampLegendNode. :param minimumValue: value associated with minimum of ramp :param maximumValue: value associated with maximum of ramp :param parent: attach a parent QObject to the legend node. +:param key: rule key. optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.40) +:param parentKey: rule key of parent (since QGIS 3.40) %End diff --git a/python/PyQt6/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in b/python/PyQt6/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in index c0b284923f37..e21b95ef9768 100644 --- a/python/PyQt6/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in +++ b/python/PyQt6/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in @@ -582,7 +582,8 @@ Implementation of legend node interface for displaying raster legend entries %End public: - QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent /TransferThis/ = 0, bool isCheckable = false, const QString &ruleKey = QString() ); + QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent /TransferThis/ = 0, + bool isCheckable = false, const QString &ruleKey = QString(), const QString &parentRuleKey = QString() ); %Docstring Constructor for QgsRasterSymbolLegendNode. @@ -592,6 +593,7 @@ Constructor for QgsRasterSymbolLegendNode. :param parent: attach a parent QObject to the legend node. :param isCheckable: set to ``True`` to enable the checkbox for the node (since QGIS 3.18) :param ruleKey: optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.18) +:param parentRuleKey: rule key of parent (since QGIS 3.40) %End virtual Qt::ItemFlags flags() const; diff --git a/python/PyQt6/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in b/python/PyQt6/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in index bdaa3285fffa..fabbecbc9f5d 100644 --- a/python/PyQt6/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in +++ b/python/PyQt6/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in @@ -32,6 +32,8 @@ Constructor for QgsProcessingModelAlgorithm. virtual void initAlgorithm( const QVariantMap &configuration = QVariantMap() ); //#spellok + virtual Qgis::ProcessingAlgorithmFlags flags() const; + virtual QString name() const; virtual QString displayName() const; diff --git a/python/PyQt6/core/auto_generated/qgis.sip.in b/python/PyQt6/core/auto_generated/qgis.sip.in index 4de51989d532..7f7611f34e52 100644 --- a/python/PyQt6/core/auto_generated/qgis.sip.in +++ b/python/PyQt6/core/auto_generated/qgis.sip.in @@ -1922,6 +1922,7 @@ The development version SkipGenericModelLogging, NotAvailableInStandaloneTool, RequiresProject, + SecurityRisk, Deprecated, }; diff --git a/python/PyQt6/core/class_map.yaml b/python/PyQt6/core/class_map.yaml index 45eb580b62a2..60808d305fd7 100644 --- a/python/PyQt6/core/class_map.yaml +++ b/python/PyQt6/core/class_map.yaml @@ -1,10 +1,10 @@ -Qgis.defaultProjectScales: src/core/qgis.h#L5607 +Qgis.defaultProjectScales: src/core/qgis.h#L5608 Qgis.devVersion: src/core/qgis.h#L89 -Qgis.geosVersion: src/core/qgis.h#L5642 -Qgis.geosVersionInt: src/core/qgis.h#L5614 -Qgis.geosVersionMajor: src/core/qgis.h#L5621 -Qgis.geosVersionMinor: src/core/qgis.h#L5628 -Qgis.geosVersionPatch: src/core/qgis.h#L5635 +Qgis.geosVersion: src/core/qgis.h#L5643 +Qgis.geosVersionInt: src/core/qgis.h#L5615 +Qgis.geosVersionMajor: src/core/qgis.h#L5622 +Qgis.geosVersionMinor: src/core/qgis.h#L5629 +Qgis.geosVersionPatch: src/core/qgis.h#L5636 Qgis.releaseName: src/core/qgis.h#L79 Qgis.version: src/core/qgis.h#L65 Qgis.versionInt: src/core/qgis.h#L72 @@ -2378,15 +2378,15 @@ QgsColorRamp.properties: src/core/qgscolorramp.h#L89 QgsColorRamp.type: src/core/qgscolorramp.h#L73 QgsColorRamp.value: src/core/qgscolorramp.h#L61 QgsColorRamp: src/core/qgscolorramp.h#L28 -QgsColorRampLegendNode.data: src/core/layertree/qgscolorramplegendnode.h#L64 -QgsColorRampLegendNode.drawSymbol: src/core/layertree/qgscolorramplegendnode.h#L65 -QgsColorRampLegendNode.drawSymbolText: src/core/layertree/qgscolorramplegendnode.h#L66 -QgsColorRampLegendNode.exportSymbolToJson: src/core/layertree/qgscolorramplegendnode.h#L67 -QgsColorRampLegendNode.iconSize: src/core/layertree/qgscolorramplegendnode.h#L81 -QgsColorRampLegendNode.ramp: src/core/layertree/qgscolorramplegendnode.h#L86 -QgsColorRampLegendNode.setIconSize: src/core/layertree/qgscolorramplegendnode.h#L74 -QgsColorRampLegendNode.setSettings: src/core/layertree/qgscolorramplegendnode.h#L100 -QgsColorRampLegendNode.settings: src/core/layertree/qgscolorramplegendnode.h#L93 +QgsColorRampLegendNode.data: src/core/layertree/qgscolorramplegendnode.h#L70 +QgsColorRampLegendNode.drawSymbol: src/core/layertree/qgscolorramplegendnode.h#L71 +QgsColorRampLegendNode.drawSymbolText: src/core/layertree/qgscolorramplegendnode.h#L72 +QgsColorRampLegendNode.exportSymbolToJson: src/core/layertree/qgscolorramplegendnode.h#L73 +QgsColorRampLegendNode.iconSize: src/core/layertree/qgscolorramplegendnode.h#L87 +QgsColorRampLegendNode.ramp: src/core/layertree/qgscolorramplegendnode.h#L92 +QgsColorRampLegendNode.setIconSize: src/core/layertree/qgscolorramplegendnode.h#L80 +QgsColorRampLegendNode.setSettings: src/core/layertree/qgscolorramplegendnode.h#L106 +QgsColorRampLegendNode.settings: src/core/layertree/qgscolorramplegendnode.h#L99 QgsColorRampLegendNode: src/core/layertree/qgscolorramplegendnode.h#L32 QgsColorRampLegendNodeSettings.direction: src/core/layertree/qgscolorramplegendnodesettings.h#L64 QgsColorRampLegendNodeSettings.maximumLabel: src/core/layertree/qgscolorramplegendnodesettings.h#L102 @@ -3102,10 +3102,10 @@ QgsDataDefinedSizeLegend.updateFromSymbolAndProperty: src/core/qgsdatadefinedsiz QgsDataDefinedSizeLegend.verticalAlignment: src/core/qgsdatadefinedsizelegend.h#L126 QgsDataDefinedSizeLegend.writeXml: src/core/qgsdatadefinedsizelegend.h#L165 QgsDataDefinedSizeLegend: src/core/qgsdatadefinedsizelegend.h#L41 -QgsDataDefinedSizeLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L804 -QgsDataDefinedSizeLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L799 -QgsDataDefinedSizeLegendNode.draw: src/core/layertree/qgslayertreemodellegendnode.h#L801 -QgsDataDefinedSizeLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L790 +QgsDataDefinedSizeLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L807 +QgsDataDefinedSizeLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L802 +QgsDataDefinedSizeLegendNode.draw: src/core/layertree/qgslayertreemodellegendnode.h#L804 +QgsDataDefinedSizeLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L793 QgsDataItem.__repr__: src/core/browser/qgsdataitem.h#L97 QgsDataItem.acceptDrop: src/core/browser/qgsdataitem.h#L215 QgsDataItem.addChildItem: src/core/browser/qgsdataitem.h#L159 @@ -11851,63 +11851,64 @@ QgsProcessingFeedback.textLog: src/core/processing/qgsprocessingfeedback.h#L165 QgsProcessingFeedback: src/core/processing/qgsprocessingfeedback.h#L37 QgsProcessingLayerPostProcessorInterface.postProcessLayer: src/core/processing/qgsprocessingcontext.h#L875 QgsProcessingLayerPostProcessorInterface: src/core/processing/qgsprocessingcontext.h#L855 -QgsProcessingModelAlgorithm.VariableDefinition: src/core/processing/models/qgsprocessingmodelalgorithm.h#L465 -QgsProcessingModelAlgorithm.activateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L157 -QgsProcessingModelAlgorithm.addChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L123 -QgsProcessingModelAlgorithm.addGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L349 -QgsProcessingModelAlgorithm.addModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L202 -QgsProcessingModelAlgorithm.asPythonCode: src/core/processing/models/qgsprocessingmodelalgorithm.h#L448 -QgsProcessingModelAlgorithm.asPythonCommand: src/core/processing/models/qgsprocessingmodelalgorithm.h#L61 -QgsProcessingModelAlgorithm.canExecute: src/core/processing/models/qgsprocessingmodelalgorithm.h#L60 -QgsProcessingModelAlgorithm.changeParameterName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L227 -QgsProcessingModelAlgorithm.childAlgorithmsDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L234 -QgsProcessingModelAlgorithm.createExpressionContext: src/core/processing/models/qgsprocessingmodelalgorithm.h#L62 -QgsProcessingModelAlgorithm.createExpressionContextScopeForChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L509 -QgsProcessingModelAlgorithm.createInstance: src/core/processing/models/qgsprocessingmodelalgorithm.h#L590 -QgsProcessingModelAlgorithm.deactivateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L149 -QgsProcessingModelAlgorithm.designerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L545 -QgsProcessingModelAlgorithm.displayName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L51 -QgsProcessingModelAlgorithm.fromFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L378 -QgsProcessingModelAlgorithm.group: src/core/processing/models/qgsprocessingmodelalgorithm.h#L52 -QgsProcessingModelAlgorithm.groupId: src/core/processing/models/qgsprocessingmodelalgorithm.h#L53 -QgsProcessingModelAlgorithm.helpUrl: src/core/processing/models/qgsprocessingmodelalgorithm.h#L58 -QgsProcessingModelAlgorithm.icon: src/core/processing/models/qgsprocessingmodelalgorithm.h#L54 +QgsProcessingModelAlgorithm.VariableDefinition: src/core/processing/models/qgsprocessingmodelalgorithm.h#L466 +QgsProcessingModelAlgorithm.activateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L158 +QgsProcessingModelAlgorithm.addChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L124 +QgsProcessingModelAlgorithm.addGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L350 +QgsProcessingModelAlgorithm.addModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L203 +QgsProcessingModelAlgorithm.asPythonCode: src/core/processing/models/qgsprocessingmodelalgorithm.h#L449 +QgsProcessingModelAlgorithm.asPythonCommand: src/core/processing/models/qgsprocessingmodelalgorithm.h#L62 +QgsProcessingModelAlgorithm.canExecute: src/core/processing/models/qgsprocessingmodelalgorithm.h#L61 +QgsProcessingModelAlgorithm.changeParameterName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L228 +QgsProcessingModelAlgorithm.childAlgorithmsDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L235 +QgsProcessingModelAlgorithm.createExpressionContext: src/core/processing/models/qgsprocessingmodelalgorithm.h#L63 +QgsProcessingModelAlgorithm.createExpressionContextScopeForChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L510 +QgsProcessingModelAlgorithm.createInstance: src/core/processing/models/qgsprocessingmodelalgorithm.h#L591 +QgsProcessingModelAlgorithm.deactivateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L150 +QgsProcessingModelAlgorithm.designerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L546 +QgsProcessingModelAlgorithm.displayName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L52 +QgsProcessingModelAlgorithm.flags: src/core/processing/models/qgsprocessingmodelalgorithm.h#L50 +QgsProcessingModelAlgorithm.fromFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L379 +QgsProcessingModelAlgorithm.group: src/core/processing/models/qgsprocessingmodelalgorithm.h#L53 +QgsProcessingModelAlgorithm.groupId: src/core/processing/models/qgsprocessingmodelalgorithm.h#L54 +QgsProcessingModelAlgorithm.helpUrl: src/core/processing/models/qgsprocessingmodelalgorithm.h#L59 +QgsProcessingModelAlgorithm.icon: src/core/processing/models/qgsprocessingmodelalgorithm.h#L55 QgsProcessingModelAlgorithm.initAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L48 -QgsProcessingModelAlgorithm.loadVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L396 -QgsProcessingModelAlgorithm.modelNameMatchesFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L439 -QgsProcessingModelAlgorithm.modelParameterFromChildIdAndOutputName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L565 -QgsProcessingModelAlgorithm.name: src/core/processing/models/qgsprocessingmodelalgorithm.h#L50 -QgsProcessingModelAlgorithm.otherParametersDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L242 -QgsProcessingModelAlgorithm.outputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L324 -QgsProcessingModelAlgorithm.processAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L592 -QgsProcessingModelAlgorithm.removeChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L140 -QgsProcessingModelAlgorithm.removeGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L366 -QgsProcessingModelAlgorithm.removeModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L218 -QgsProcessingModelAlgorithm.safeName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L574 -QgsProcessingModelAlgorithm.setChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L111 -QgsProcessingModelAlgorithm.setChildAlgorithms: src/core/processing/models/qgsprocessingmodelalgorithm.h#L103 -QgsProcessingModelAlgorithm.setDesignerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L558 -QgsProcessingModelAlgorithm.setGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L74 -QgsProcessingModelAlgorithm.setHelpContent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L417 -QgsProcessingModelAlgorithm.setName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L68 -QgsProcessingModelAlgorithm.setOutputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L332 -QgsProcessingModelAlgorithm.setOutputOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L316 -QgsProcessingModelAlgorithm.setParameterComponent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L269 -QgsProcessingModelAlgorithm.setParameterComponents: src/core/processing/models/qgsprocessingmodelalgorithm.h#L260 -QgsProcessingModelAlgorithm.setParameterOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L297 -QgsProcessingModelAlgorithm.setSourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L429 -QgsProcessingModelAlgorithm.setVariables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L532 -QgsProcessingModelAlgorithm.shortDescription: src/core/processing/models/qgsprocessingmodelalgorithm.h#L57 -QgsProcessingModelAlgorithm.shortHelpString: src/core/processing/models/qgsprocessingmodelalgorithm.h#L56 -QgsProcessingModelAlgorithm.sourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L423 -QgsProcessingModelAlgorithm.svgIconPath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L55 -QgsProcessingModelAlgorithm.toFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L372 -QgsProcessingModelAlgorithm.toVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L387 -QgsProcessingModelAlgorithm.updateDestinationParameters: src/core/processing/models/qgsprocessingmodelalgorithm.h#L339 -QgsProcessingModelAlgorithm.updateModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L210 -QgsProcessingModelAlgorithm.validate: src/core/processing/models/qgsprocessingmodelalgorithm.h#L83 -QgsProcessingModelAlgorithm.validateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L194 -QgsProcessingModelAlgorithm.variables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L521 +QgsProcessingModelAlgorithm.loadVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L397 +QgsProcessingModelAlgorithm.modelNameMatchesFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L440 +QgsProcessingModelAlgorithm.modelParameterFromChildIdAndOutputName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L566 +QgsProcessingModelAlgorithm.name: src/core/processing/models/qgsprocessingmodelalgorithm.h#L51 +QgsProcessingModelAlgorithm.otherParametersDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L243 +QgsProcessingModelAlgorithm.outputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L325 +QgsProcessingModelAlgorithm.processAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L593 +QgsProcessingModelAlgorithm.removeChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L141 +QgsProcessingModelAlgorithm.removeGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L367 +QgsProcessingModelAlgorithm.removeModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L219 +QgsProcessingModelAlgorithm.safeName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L575 +QgsProcessingModelAlgorithm.setChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L112 +QgsProcessingModelAlgorithm.setChildAlgorithms: src/core/processing/models/qgsprocessingmodelalgorithm.h#L104 +QgsProcessingModelAlgorithm.setDesignerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L559 +QgsProcessingModelAlgorithm.setGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L75 +QgsProcessingModelAlgorithm.setHelpContent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L418 +QgsProcessingModelAlgorithm.setName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L69 +QgsProcessingModelAlgorithm.setOutputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L333 +QgsProcessingModelAlgorithm.setOutputOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L317 +QgsProcessingModelAlgorithm.setParameterComponent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L270 +QgsProcessingModelAlgorithm.setParameterComponents: src/core/processing/models/qgsprocessingmodelalgorithm.h#L261 +QgsProcessingModelAlgorithm.setParameterOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L298 +QgsProcessingModelAlgorithm.setSourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L430 +QgsProcessingModelAlgorithm.setVariables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L533 +QgsProcessingModelAlgorithm.shortDescription: src/core/processing/models/qgsprocessingmodelalgorithm.h#L58 +QgsProcessingModelAlgorithm.shortHelpString: src/core/processing/models/qgsprocessingmodelalgorithm.h#L57 +QgsProcessingModelAlgorithm.sourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L424 +QgsProcessingModelAlgorithm.svgIconPath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L56 +QgsProcessingModelAlgorithm.toFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L373 +QgsProcessingModelAlgorithm.toVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L388 +QgsProcessingModelAlgorithm.updateDestinationParameters: src/core/processing/models/qgsprocessingmodelalgorithm.h#L340 +QgsProcessingModelAlgorithm.updateModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L211 +QgsProcessingModelAlgorithm.validate: src/core/processing/models/qgsprocessingmodelalgorithm.h#L84 +QgsProcessingModelAlgorithm.validateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L195 +QgsProcessingModelAlgorithm.variables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L522 QgsProcessingModelAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L37 QgsProcessingModelChildAlgorithm.addParameterSources: src/core/processing/models/qgsprocessingmodelchildalgorithm.h#L177 QgsProcessingModelChildAlgorithm.algorithm: src/core/processing/models/qgsprocessingmodelchildalgorithm.h#L150 @@ -14642,14 +14643,14 @@ QgsRasterSingleColorRenderer.setColor: src/core/raster/qgsrastersinglecolorrende QgsRasterSingleColorRenderer.setInputBand: src/core/raster/qgsrastersinglecolorrenderer.h#L69 QgsRasterSingleColorRenderer.writeXml: src/core/raster/qgsrastersinglecolorrenderer.h#L66 QgsRasterSingleColorRenderer: src/core/raster/qgsrastersinglecolorrenderer.h#L34 -QgsRasterSymbolLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L706 -QgsRasterSymbolLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L686 -QgsRasterSymbolLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L688 -QgsRasterSymbolLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L689 -QgsRasterSymbolLegendNode.flags: src/core/layertree/qgslayertreemodellegendnode.h#L685 -QgsRasterSymbolLegendNode.isCheckable: src/core/layertree/qgslayertreemodellegendnode.h#L703 -QgsRasterSymbolLegendNode.ruleKey: src/core/layertree/qgslayertreemodellegendnode.h#L696 -QgsRasterSymbolLegendNode.setData: src/core/layertree/qgslayertreemodellegendnode.h#L687 +QgsRasterSymbolLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L708 +QgsRasterSymbolLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L688 +QgsRasterSymbolLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L690 +QgsRasterSymbolLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L691 +QgsRasterSymbolLegendNode.flags: src/core/layertree/qgslayertreemodellegendnode.h#L687 +QgsRasterSymbolLegendNode.isCheckable: src/core/layertree/qgslayertreemodellegendnode.h#L705 +QgsRasterSymbolLegendNode.ruleKey: src/core/layertree/qgslayertreemodellegendnode.h#L698 +QgsRasterSymbolLegendNode.setData: src/core/layertree/qgslayertreemodellegendnode.h#L689 QgsRasterSymbolLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L668 QgsRasterTransparency.QgsRasterTransparency.__repr__: src/core/raster/qgsrastertransparency.h#L145 QgsRasterTransparency.QgsRasterTransparency.__repr__: src/core/raster/qgsrastertransparency.h#L228 @@ -18382,11 +18383,11 @@ QgsVectorFileWriterTask.finished: src/core/qgsvectorfilewritertask.h#L75 QgsVectorFileWriterTask.run: src/core/qgsvectorfilewritertask.h#L74 QgsVectorFileWriterTask.writeComplete: src/core/qgsvectorfilewritertask.h#L57 QgsVectorFileWriterTask: src/core/qgsvectorfilewritertask.h#L34 -QgsVectorLabelLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L861 -QgsVectorLabelLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L841 -QgsVectorLabelLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L850 -QgsVectorLabelLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L858 -QgsVectorLabelLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L822 +QgsVectorLabelLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L864 +QgsVectorLabelLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L844 +QgsVectorLabelLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L853 +QgsVectorLabelLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L861 +QgsVectorLabelLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L825 QgsVectorLayer.QgsVectorLayer.DeleteContext: src/core/vector/qgsvectorlayer.h#L542 QgsVectorLayer.QgsVectorLayer.LayerOptions: src/core/vector/qgsvectorlayer.h#L429 QgsVectorLayer.QgsVectorLayer.LayerOptions: src/core/vector/qgsvectorlayer.h#L439 @@ -19374,13 +19375,13 @@ QgsWkbTypes.translatedDisplayString: src/core/geometry/qgswkbtypes.h#L1021 QgsWkbTypes.wkbDimensions: src/core/geometry/qgswkbtypes.h#L904 QgsWkbTypes.zmType: src/core/geometry/qgswkbtypes.h#L790 QgsWkbTypes: src/core/geometry/qgswkbtypes.h#L41 -QgsWmsLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L758 -QgsWmsLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L742 -QgsWmsLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L744 -QgsWmsLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L746 -QgsWmsLegendNode.getLegendGraphicBlocking: src/core/layertree/qgslayertreemodellegendnode.h#L754 -QgsWmsLegendNode.invalidateMapBasedData: src/core/layertree/qgslayertreemodellegendnode.h#L748 -QgsWmsLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L727 +QgsWmsLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L761 +QgsWmsLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L745 +QgsWmsLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L747 +QgsWmsLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L749 +QgsWmsLegendNode.getLegendGraphicBlocking: src/core/layertree/qgslayertreemodellegendnode.h#L757 +QgsWmsLegendNode.invalidateMapBasedData: src/core/layertree/qgslayertreemodellegendnode.h#L751 +QgsWmsLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L730 QgsXmlUtils.readBox3D: src/core/qgsxmlutils.h#L58 QgsXmlUtils.readMapUnits: src/core/qgsxmlutils.h#L48 QgsXmlUtils.readRectangle: src/core/qgsxmlutils.h#L50 diff --git a/python/PyQt6/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in b/python/PyQt6/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in index 4ce0ef752282..8073617b9f01 100644 --- a/python/PyQt6/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in +++ b/python/PyQt6/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in @@ -88,7 +88,7 @@ whenever this signal is emitted. virtual ~QgsCreateAnnotationItemMapToolInterface(); - virtual QgsCreateAnnotationItemMapToolHandler *handler() = 0; + virtual QgsCreateAnnotationItemMapToolHandler *handler() const = 0; %Docstring Returns the handler object for the map tool. %End diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index db67ec7a24bb..095bf396602b 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -6171,6 +6171,9 @@ QgsProcessingAlgorithm.Flag.FlagRequiresProject = Qgis.ProcessingAlgorithmFlag.RequiresProject QgsProcessingAlgorithm.FlagRequiresProject.is_monkey_patched = True QgsProcessingAlgorithm.FlagRequiresProject.__doc__ = "The algorithm requires that a valid QgsProject is available from the processing context in order to execute" +QgsProcessingAlgorithm.SecurityRisk = Qgis.ProcessingAlgorithmFlag.SecurityRisk +QgsProcessingAlgorithm.SecurityRisk.is_monkey_patched = True +QgsProcessingAlgorithm.SecurityRisk.__doc__ = "The algorithm represents a potential security risk if executed with untrusted inputs. \n.. versionadded:: 3.40" QgsProcessingAlgorithm.FlagDeprecated = Qgis.ProcessingAlgorithmFlag.Deprecated QgsProcessingAlgorithm.Flag.FlagDeprecated = Qgis.ProcessingAlgorithmFlag.Deprecated QgsProcessingAlgorithm.FlagDeprecated.is_monkey_patched = True @@ -6239,6 +6242,10 @@ Available as ``QgsProcessingAlgorithm.FlagRequiresProject`` in older QGIS releases. +* ``SecurityRisk``: The algorithm represents a potential security risk if executed with untrusted inputs. + + .. versionadded:: 3.40 + * ``Deprecated``: Algorithm is deprecated Available as ``QgsProcessingAlgorithm.FlagDeprecated`` in older QGIS releases. diff --git a/python/core/auto_generated/diagram/qgsdiagram.sip.in b/python/core/auto_generated/diagram/qgsdiagram.sip.in index 3198a5e9ef4d..39ba28e4a10c 100644 --- a/python/core/auto_generated/diagram/qgsdiagram.sip.in +++ b/python/core/auto_generated/diagram/qgsdiagram.sip.in @@ -27,9 +27,9 @@ Base class for all diagram types. sipType = sipType_QgsHistogramDiagram; else if ( sipCpp->diagramName() == QLatin1String( "Text" ) ) sipType = sipType_QgsTextDiagram; - else if ( sipCpp->diagramName() == QLatin1String( "StackedBar" ) ) - sipType = sipType_QgsStackedBarDiagram; else if ( sipCpp->diagramName() == QLatin1String( "Stacked" ) ) + sipType = sipType_QgsStackedBarDiagram; + else if ( sipCpp->diagramName() == QLatin1String( "StackedDiagram" ) ) sipType = sipType_QgsStackedDiagram; else sipType = NULL; diff --git a/python/core/auto_generated/layertree/qgscolorramplegendnode.sip.in b/python/core/auto_generated/layertree/qgscolorramplegendnode.sip.in index 5ff845be34ef..ca6ff9325755 100644 --- a/python/core/auto_generated/layertree/qgscolorramplegendnode.sip.in +++ b/python/core/auto_generated/layertree/qgscolorramplegendnode.sip.in @@ -23,7 +23,8 @@ A legend node which renders a color ramp. public: QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp /Transfer/, - const QString &minimumLabel, const QString &maximumLabel, QObject *parent /TransferThis/ = 0 ); + const QString &minimumLabel, const QString &maximumLabel, QObject *parent /TransferThis/ = 0, + const QString &key = QString(), const QString &parentKey = QString() ); %Docstring Constructor for QgsColorRampLegendNode. @@ -32,11 +33,14 @@ Constructor for QgsColorRampLegendNode. :param minimumLabel: label text to render for the minimum value in the ramp :param maximumLabel: label text to render for the maximum value in the ramp :param parent: attach a parent QObject to the legend node. +:param key: rule key. optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.40) +:param parentKey: rule key of parent (since QGIS 3.40) %End QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp /Transfer/, const QgsColorRampLegendNodeSettings &settings, double minimumValue, - double maximumValue, QObject *parent /TransferThis/ = 0 ); + double maximumValue, QObject *parent /TransferThis/ = 0, + const QString &key = QString(), const QString &parentKey = QString() ); %Docstring Constructor for QgsColorRampLegendNode. @@ -46,6 +50,8 @@ Constructor for QgsColorRampLegendNode. :param minimumValue: value associated with minimum of ramp :param maximumValue: value associated with maximum of ramp :param parent: attach a parent QObject to the legend node. +:param key: rule key. optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.40) +:param parentKey: rule key of parent (since QGIS 3.40) %End diff --git a/python/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in b/python/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in index f2b7406ccbd8..fadc70328f35 100644 --- a/python/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in +++ b/python/core/auto_generated/layertree/qgslayertreemodellegendnode.sip.in @@ -582,7 +582,8 @@ Implementation of legend node interface for displaying raster legend entries %End public: - QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent /TransferThis/ = 0, bool isCheckable = false, const QString &ruleKey = QString() ); + QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent /TransferThis/ = 0, + bool isCheckable = false, const QString &ruleKey = QString(), const QString &parentRuleKey = QString() ); %Docstring Constructor for QgsRasterSymbolLegendNode. @@ -592,6 +593,7 @@ Constructor for QgsRasterSymbolLegendNode. :param parent: attach a parent QObject to the legend node. :param isCheckable: set to ``True`` to enable the checkbox for the node (since QGIS 3.18) :param ruleKey: optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.18) +:param parentRuleKey: rule key of parent (since QGIS 3.40) %End virtual Qt::ItemFlags flags() const; diff --git a/python/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in b/python/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in index bdaa3285fffa..fabbecbc9f5d 100644 --- a/python/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in +++ b/python/core/auto_generated/processing/models/qgsprocessingmodelalgorithm.sip.in @@ -32,6 +32,8 @@ Constructor for QgsProcessingModelAlgorithm. virtual void initAlgorithm( const QVariantMap &configuration = QVariantMap() ); //#spellok + virtual Qgis::ProcessingAlgorithmFlags flags() const; + virtual QString name() const; virtual QString displayName() const; diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index 8d685aaa33f7..fdbaad9f57a2 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -1922,6 +1922,7 @@ The development version SkipGenericModelLogging, NotAvailableInStandaloneTool, RequiresProject, + SecurityRisk, Deprecated, }; diff --git a/python/core/class_map.yaml b/python/core/class_map.yaml index f6be2bf81ef7..ce18b6019ffe 100644 --- a/python/core/class_map.yaml +++ b/python/core/class_map.yaml @@ -1,10 +1,10 @@ -Qgis.defaultProjectScales: src/core/qgis.h#L5607 +Qgis.defaultProjectScales: src/core/qgis.h#L5608 Qgis.devVersion: src/core/qgis.h#L89 -Qgis.geosVersion: src/core/qgis.h#L5642 -Qgis.geosVersionInt: src/core/qgis.h#L5614 -Qgis.geosVersionMajor: src/core/qgis.h#L5621 -Qgis.geosVersionMinor: src/core/qgis.h#L5628 -Qgis.geosVersionPatch: src/core/qgis.h#L5635 +Qgis.geosVersion: src/core/qgis.h#L5643 +Qgis.geosVersionInt: src/core/qgis.h#L5615 +Qgis.geosVersionMajor: src/core/qgis.h#L5622 +Qgis.geosVersionMinor: src/core/qgis.h#L5629 +Qgis.geosVersionPatch: src/core/qgis.h#L5636 Qgis.releaseName: src/core/qgis.h#L79 Qgis.version: src/core/qgis.h#L65 Qgis.versionInt: src/core/qgis.h#L72 @@ -2378,15 +2378,15 @@ QgsColorRamp.properties: src/core/qgscolorramp.h#L89 QgsColorRamp.type: src/core/qgscolorramp.h#L73 QgsColorRamp.value: src/core/qgscolorramp.h#L61 QgsColorRamp: src/core/qgscolorramp.h#L28 -QgsColorRampLegendNode.data: src/core/layertree/qgscolorramplegendnode.h#L64 -QgsColorRampLegendNode.drawSymbol: src/core/layertree/qgscolorramplegendnode.h#L65 -QgsColorRampLegendNode.drawSymbolText: src/core/layertree/qgscolorramplegendnode.h#L66 -QgsColorRampLegendNode.exportSymbolToJson: src/core/layertree/qgscolorramplegendnode.h#L67 -QgsColorRampLegendNode.iconSize: src/core/layertree/qgscolorramplegendnode.h#L81 -QgsColorRampLegendNode.ramp: src/core/layertree/qgscolorramplegendnode.h#L86 -QgsColorRampLegendNode.setIconSize: src/core/layertree/qgscolorramplegendnode.h#L74 -QgsColorRampLegendNode.setSettings: src/core/layertree/qgscolorramplegendnode.h#L100 -QgsColorRampLegendNode.settings: src/core/layertree/qgscolorramplegendnode.h#L93 +QgsColorRampLegendNode.data: src/core/layertree/qgscolorramplegendnode.h#L70 +QgsColorRampLegendNode.drawSymbol: src/core/layertree/qgscolorramplegendnode.h#L71 +QgsColorRampLegendNode.drawSymbolText: src/core/layertree/qgscolorramplegendnode.h#L72 +QgsColorRampLegendNode.exportSymbolToJson: src/core/layertree/qgscolorramplegendnode.h#L73 +QgsColorRampLegendNode.iconSize: src/core/layertree/qgscolorramplegendnode.h#L87 +QgsColorRampLegendNode.ramp: src/core/layertree/qgscolorramplegendnode.h#L92 +QgsColorRampLegendNode.setIconSize: src/core/layertree/qgscolorramplegendnode.h#L80 +QgsColorRampLegendNode.setSettings: src/core/layertree/qgscolorramplegendnode.h#L106 +QgsColorRampLegendNode.settings: src/core/layertree/qgscolorramplegendnode.h#L99 QgsColorRampLegendNode: src/core/layertree/qgscolorramplegendnode.h#L32 QgsColorRampLegendNodeSettings.direction: src/core/layertree/qgscolorramplegendnodesettings.h#L64 QgsColorRampLegendNodeSettings.maximumLabel: src/core/layertree/qgscolorramplegendnodesettings.h#L102 @@ -3102,10 +3102,10 @@ QgsDataDefinedSizeLegend.updateFromSymbolAndProperty: src/core/qgsdatadefinedsiz QgsDataDefinedSizeLegend.verticalAlignment: src/core/qgsdatadefinedsizelegend.h#L126 QgsDataDefinedSizeLegend.writeXml: src/core/qgsdatadefinedsizelegend.h#L165 QgsDataDefinedSizeLegend: src/core/qgsdatadefinedsizelegend.h#L41 -QgsDataDefinedSizeLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L804 -QgsDataDefinedSizeLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L799 -QgsDataDefinedSizeLegendNode.draw: src/core/layertree/qgslayertreemodellegendnode.h#L801 -QgsDataDefinedSizeLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L790 +QgsDataDefinedSizeLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L807 +QgsDataDefinedSizeLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L802 +QgsDataDefinedSizeLegendNode.draw: src/core/layertree/qgslayertreemodellegendnode.h#L804 +QgsDataDefinedSizeLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L793 QgsDataItem.__repr__: src/core/browser/qgsdataitem.h#L97 QgsDataItem.acceptDrop: src/core/browser/qgsdataitem.h#L215 QgsDataItem.addChildItem: src/core/browser/qgsdataitem.h#L159 @@ -11851,63 +11851,64 @@ QgsProcessingFeedback.textLog: src/core/processing/qgsprocessingfeedback.h#L165 QgsProcessingFeedback: src/core/processing/qgsprocessingfeedback.h#L37 QgsProcessingLayerPostProcessorInterface.postProcessLayer: src/core/processing/qgsprocessingcontext.h#L875 QgsProcessingLayerPostProcessorInterface: src/core/processing/qgsprocessingcontext.h#L855 -QgsProcessingModelAlgorithm.VariableDefinition: src/core/processing/models/qgsprocessingmodelalgorithm.h#L465 -QgsProcessingModelAlgorithm.activateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L157 -QgsProcessingModelAlgorithm.addChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L123 -QgsProcessingModelAlgorithm.addGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L349 -QgsProcessingModelAlgorithm.addModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L202 -QgsProcessingModelAlgorithm.asPythonCode: src/core/processing/models/qgsprocessingmodelalgorithm.h#L448 -QgsProcessingModelAlgorithm.asPythonCommand: src/core/processing/models/qgsprocessingmodelalgorithm.h#L61 -QgsProcessingModelAlgorithm.canExecute: src/core/processing/models/qgsprocessingmodelalgorithm.h#L60 -QgsProcessingModelAlgorithm.changeParameterName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L227 -QgsProcessingModelAlgorithm.childAlgorithmsDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L234 -QgsProcessingModelAlgorithm.createExpressionContext: src/core/processing/models/qgsprocessingmodelalgorithm.h#L62 -QgsProcessingModelAlgorithm.createExpressionContextScopeForChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L509 -QgsProcessingModelAlgorithm.createInstance: src/core/processing/models/qgsprocessingmodelalgorithm.h#L590 -QgsProcessingModelAlgorithm.deactivateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L149 -QgsProcessingModelAlgorithm.designerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L545 -QgsProcessingModelAlgorithm.displayName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L51 -QgsProcessingModelAlgorithm.fromFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L378 -QgsProcessingModelAlgorithm.group: src/core/processing/models/qgsprocessingmodelalgorithm.h#L52 -QgsProcessingModelAlgorithm.groupId: src/core/processing/models/qgsprocessingmodelalgorithm.h#L53 -QgsProcessingModelAlgorithm.helpUrl: src/core/processing/models/qgsprocessingmodelalgorithm.h#L58 -QgsProcessingModelAlgorithm.icon: src/core/processing/models/qgsprocessingmodelalgorithm.h#L54 +QgsProcessingModelAlgorithm.VariableDefinition: src/core/processing/models/qgsprocessingmodelalgorithm.h#L466 +QgsProcessingModelAlgorithm.activateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L158 +QgsProcessingModelAlgorithm.addChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L124 +QgsProcessingModelAlgorithm.addGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L350 +QgsProcessingModelAlgorithm.addModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L203 +QgsProcessingModelAlgorithm.asPythonCode: src/core/processing/models/qgsprocessingmodelalgorithm.h#L449 +QgsProcessingModelAlgorithm.asPythonCommand: src/core/processing/models/qgsprocessingmodelalgorithm.h#L62 +QgsProcessingModelAlgorithm.canExecute: src/core/processing/models/qgsprocessingmodelalgorithm.h#L61 +QgsProcessingModelAlgorithm.changeParameterName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L228 +QgsProcessingModelAlgorithm.childAlgorithmsDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L235 +QgsProcessingModelAlgorithm.createExpressionContext: src/core/processing/models/qgsprocessingmodelalgorithm.h#L63 +QgsProcessingModelAlgorithm.createExpressionContextScopeForChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L510 +QgsProcessingModelAlgorithm.createInstance: src/core/processing/models/qgsprocessingmodelalgorithm.h#L591 +QgsProcessingModelAlgorithm.deactivateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L150 +QgsProcessingModelAlgorithm.designerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L546 +QgsProcessingModelAlgorithm.displayName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L52 +QgsProcessingModelAlgorithm.flags: src/core/processing/models/qgsprocessingmodelalgorithm.h#L50 +QgsProcessingModelAlgorithm.fromFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L379 +QgsProcessingModelAlgorithm.group: src/core/processing/models/qgsprocessingmodelalgorithm.h#L53 +QgsProcessingModelAlgorithm.groupId: src/core/processing/models/qgsprocessingmodelalgorithm.h#L54 +QgsProcessingModelAlgorithm.helpUrl: src/core/processing/models/qgsprocessingmodelalgorithm.h#L59 +QgsProcessingModelAlgorithm.icon: src/core/processing/models/qgsprocessingmodelalgorithm.h#L55 QgsProcessingModelAlgorithm.initAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L48 -QgsProcessingModelAlgorithm.loadVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L396 -QgsProcessingModelAlgorithm.modelNameMatchesFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L439 -QgsProcessingModelAlgorithm.modelParameterFromChildIdAndOutputName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L565 -QgsProcessingModelAlgorithm.name: src/core/processing/models/qgsprocessingmodelalgorithm.h#L50 -QgsProcessingModelAlgorithm.otherParametersDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L242 -QgsProcessingModelAlgorithm.outputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L324 -QgsProcessingModelAlgorithm.processAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L592 -QgsProcessingModelAlgorithm.removeChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L140 -QgsProcessingModelAlgorithm.removeGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L366 -QgsProcessingModelAlgorithm.removeModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L218 -QgsProcessingModelAlgorithm.safeName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L574 -QgsProcessingModelAlgorithm.setChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L111 -QgsProcessingModelAlgorithm.setChildAlgorithms: src/core/processing/models/qgsprocessingmodelalgorithm.h#L103 -QgsProcessingModelAlgorithm.setDesignerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L558 -QgsProcessingModelAlgorithm.setGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L74 -QgsProcessingModelAlgorithm.setHelpContent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L417 -QgsProcessingModelAlgorithm.setName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L68 -QgsProcessingModelAlgorithm.setOutputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L332 -QgsProcessingModelAlgorithm.setOutputOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L316 -QgsProcessingModelAlgorithm.setParameterComponent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L269 -QgsProcessingModelAlgorithm.setParameterComponents: src/core/processing/models/qgsprocessingmodelalgorithm.h#L260 -QgsProcessingModelAlgorithm.setParameterOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L297 -QgsProcessingModelAlgorithm.setSourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L429 -QgsProcessingModelAlgorithm.setVariables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L532 -QgsProcessingModelAlgorithm.shortDescription: src/core/processing/models/qgsprocessingmodelalgorithm.h#L57 -QgsProcessingModelAlgorithm.shortHelpString: src/core/processing/models/qgsprocessingmodelalgorithm.h#L56 -QgsProcessingModelAlgorithm.sourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L423 -QgsProcessingModelAlgorithm.svgIconPath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L55 -QgsProcessingModelAlgorithm.toFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L372 -QgsProcessingModelAlgorithm.toVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L387 -QgsProcessingModelAlgorithm.updateDestinationParameters: src/core/processing/models/qgsprocessingmodelalgorithm.h#L339 -QgsProcessingModelAlgorithm.updateModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L210 -QgsProcessingModelAlgorithm.validate: src/core/processing/models/qgsprocessingmodelalgorithm.h#L83 -QgsProcessingModelAlgorithm.validateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L194 -QgsProcessingModelAlgorithm.variables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L521 +QgsProcessingModelAlgorithm.loadVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L397 +QgsProcessingModelAlgorithm.modelNameMatchesFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L440 +QgsProcessingModelAlgorithm.modelParameterFromChildIdAndOutputName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L566 +QgsProcessingModelAlgorithm.name: src/core/processing/models/qgsprocessingmodelalgorithm.h#L51 +QgsProcessingModelAlgorithm.otherParametersDependOnParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L243 +QgsProcessingModelAlgorithm.outputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L325 +QgsProcessingModelAlgorithm.processAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L593 +QgsProcessingModelAlgorithm.removeChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L141 +QgsProcessingModelAlgorithm.removeGroupBox: src/core/processing/models/qgsprocessingmodelalgorithm.h#L367 +QgsProcessingModelAlgorithm.removeModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L219 +QgsProcessingModelAlgorithm.safeName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L575 +QgsProcessingModelAlgorithm.setChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L112 +QgsProcessingModelAlgorithm.setChildAlgorithms: src/core/processing/models/qgsprocessingmodelalgorithm.h#L104 +QgsProcessingModelAlgorithm.setDesignerParameterValues: src/core/processing/models/qgsprocessingmodelalgorithm.h#L559 +QgsProcessingModelAlgorithm.setGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L75 +QgsProcessingModelAlgorithm.setHelpContent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L418 +QgsProcessingModelAlgorithm.setName: src/core/processing/models/qgsprocessingmodelalgorithm.h#L69 +QgsProcessingModelAlgorithm.setOutputGroup: src/core/processing/models/qgsprocessingmodelalgorithm.h#L333 +QgsProcessingModelAlgorithm.setOutputOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L317 +QgsProcessingModelAlgorithm.setParameterComponent: src/core/processing/models/qgsprocessingmodelalgorithm.h#L270 +QgsProcessingModelAlgorithm.setParameterComponents: src/core/processing/models/qgsprocessingmodelalgorithm.h#L261 +QgsProcessingModelAlgorithm.setParameterOrder: src/core/processing/models/qgsprocessingmodelalgorithm.h#L298 +QgsProcessingModelAlgorithm.setSourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L430 +QgsProcessingModelAlgorithm.setVariables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L533 +QgsProcessingModelAlgorithm.shortDescription: src/core/processing/models/qgsprocessingmodelalgorithm.h#L58 +QgsProcessingModelAlgorithm.shortHelpString: src/core/processing/models/qgsprocessingmodelalgorithm.h#L57 +QgsProcessingModelAlgorithm.sourceFilePath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L424 +QgsProcessingModelAlgorithm.svgIconPath: src/core/processing/models/qgsprocessingmodelalgorithm.h#L56 +QgsProcessingModelAlgorithm.toFile: src/core/processing/models/qgsprocessingmodelalgorithm.h#L373 +QgsProcessingModelAlgorithm.toVariant: src/core/processing/models/qgsprocessingmodelalgorithm.h#L388 +QgsProcessingModelAlgorithm.updateDestinationParameters: src/core/processing/models/qgsprocessingmodelalgorithm.h#L340 +QgsProcessingModelAlgorithm.updateModelParameter: src/core/processing/models/qgsprocessingmodelalgorithm.h#L211 +QgsProcessingModelAlgorithm.validate: src/core/processing/models/qgsprocessingmodelalgorithm.h#L84 +QgsProcessingModelAlgorithm.validateChildAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L195 +QgsProcessingModelAlgorithm.variables: src/core/processing/models/qgsprocessingmodelalgorithm.h#L522 QgsProcessingModelAlgorithm: src/core/processing/models/qgsprocessingmodelalgorithm.h#L37 QgsProcessingModelChildAlgorithm.addParameterSources: src/core/processing/models/qgsprocessingmodelchildalgorithm.h#L177 QgsProcessingModelChildAlgorithm.algorithm: src/core/processing/models/qgsprocessingmodelchildalgorithm.h#L150 @@ -14642,14 +14643,14 @@ QgsRasterSingleColorRenderer.setColor: src/core/raster/qgsrastersinglecolorrende QgsRasterSingleColorRenderer.setInputBand: src/core/raster/qgsrastersinglecolorrenderer.h#L69 QgsRasterSingleColorRenderer.writeXml: src/core/raster/qgsrastersinglecolorrenderer.h#L66 QgsRasterSingleColorRenderer: src/core/raster/qgsrastersinglecolorrenderer.h#L34 -QgsRasterSymbolLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L706 -QgsRasterSymbolLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L686 -QgsRasterSymbolLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L688 -QgsRasterSymbolLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L689 -QgsRasterSymbolLegendNode.flags: src/core/layertree/qgslayertreemodellegendnode.h#L685 -QgsRasterSymbolLegendNode.isCheckable: src/core/layertree/qgslayertreemodellegendnode.h#L703 -QgsRasterSymbolLegendNode.ruleKey: src/core/layertree/qgslayertreemodellegendnode.h#L696 -QgsRasterSymbolLegendNode.setData: src/core/layertree/qgslayertreemodellegendnode.h#L687 +QgsRasterSymbolLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L708 +QgsRasterSymbolLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L688 +QgsRasterSymbolLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L690 +QgsRasterSymbolLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L691 +QgsRasterSymbolLegendNode.flags: src/core/layertree/qgslayertreemodellegendnode.h#L687 +QgsRasterSymbolLegendNode.isCheckable: src/core/layertree/qgslayertreemodellegendnode.h#L705 +QgsRasterSymbolLegendNode.ruleKey: src/core/layertree/qgslayertreemodellegendnode.h#L698 +QgsRasterSymbolLegendNode.setData: src/core/layertree/qgslayertreemodellegendnode.h#L689 QgsRasterSymbolLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L668 QgsRasterTransparency.QgsRasterTransparency.__repr__: src/core/raster/qgsrastertransparency.h#L145 QgsRasterTransparency.QgsRasterTransparency.__repr__: src/core/raster/qgsrastertransparency.h#L228 @@ -18383,11 +18384,11 @@ QgsVectorFileWriterTask.finished: src/core/qgsvectorfilewritertask.h#L75 QgsVectorFileWriterTask.run: src/core/qgsvectorfilewritertask.h#L74 QgsVectorFileWriterTask.writeComplete: src/core/qgsvectorfilewritertask.h#L57 QgsVectorFileWriterTask: src/core/qgsvectorfilewritertask.h#L34 -QgsVectorLabelLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L861 -QgsVectorLabelLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L841 -QgsVectorLabelLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L850 -QgsVectorLabelLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L858 -QgsVectorLabelLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L822 +QgsVectorLabelLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L864 +QgsVectorLabelLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L844 +QgsVectorLabelLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L853 +QgsVectorLabelLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L861 +QgsVectorLabelLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L825 QgsVectorLayer.QgsVectorLayer.DeleteContext: src/core/vector/qgsvectorlayer.h#L542 QgsVectorLayer.QgsVectorLayer.LayerOptions: src/core/vector/qgsvectorlayer.h#L429 QgsVectorLayer.QgsVectorLayer.LayerOptions: src/core/vector/qgsvectorlayer.h#L439 @@ -19375,13 +19376,13 @@ QgsWkbTypes.translatedDisplayString: src/core/geometry/qgswkbtypes.h#L1021 QgsWkbTypes.wkbDimensions: src/core/geometry/qgswkbtypes.h#L904 QgsWkbTypes.zmType: src/core/geometry/qgswkbtypes.h#L790 QgsWkbTypes: src/core/geometry/qgswkbtypes.h#L41 -QgsWmsLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L758 -QgsWmsLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L742 -QgsWmsLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L744 -QgsWmsLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L746 -QgsWmsLegendNode.getLegendGraphicBlocking: src/core/layertree/qgslayertreemodellegendnode.h#L754 -QgsWmsLegendNode.invalidateMapBasedData: src/core/layertree/qgslayertreemodellegendnode.h#L748 -QgsWmsLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L727 +QgsWmsLegendNode.__repr__: src/core/layertree/qgslayertreemodellegendnode.h#L761 +QgsWmsLegendNode.data: src/core/layertree/qgslayertreemodellegendnode.h#L745 +QgsWmsLegendNode.drawSymbol: src/core/layertree/qgslayertreemodellegendnode.h#L747 +QgsWmsLegendNode.exportSymbolToJson: src/core/layertree/qgslayertreemodellegendnode.h#L749 +QgsWmsLegendNode.getLegendGraphicBlocking: src/core/layertree/qgslayertreemodellegendnode.h#L757 +QgsWmsLegendNode.invalidateMapBasedData: src/core/layertree/qgslayertreemodellegendnode.h#L751 +QgsWmsLegendNode: src/core/layertree/qgslayertreemodellegendnode.h#L730 QgsXmlUtils.readBox3D: src/core/qgsxmlutils.h#L58 QgsXmlUtils.readMapUnits: src/core/qgsxmlutils.h#L48 QgsXmlUtils.readRectangle: src/core/qgsxmlutils.h#L50 diff --git a/python/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in b/python/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in index 4ce0ef752282..8073617b9f01 100644 --- a/python/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in +++ b/python/gui/auto_generated/annotations/qgscreateannotationitemmaptool.sip.in @@ -88,7 +88,7 @@ whenever this signal is emitted. virtual ~QgsCreateAnnotationItemMapToolInterface(); - virtual QgsCreateAnnotationItemMapToolHandler *handler() = 0; + virtual QgsCreateAnnotationItemMapToolHandler *handler() const = 0; %Docstring Returns the handler object for the map tool. %End diff --git a/python/plugins/db_manager/db_plugins/vlayers/sql_dictionary.py b/python/plugins/db_manager/db_plugins/vlayers/sql_dictionary.py index 26c935b7c0e4..0b177b52ce9e 100644 --- a/python/plugins/db_manager/db_plugins/vlayers/sql_dictionary.py +++ b/python/plugins/db_manager/db_plugins/vlayers/sql_dictionary.py @@ -123,14 +123,14 @@ "to_string", "tostring", "to_datetime", "todatetime", "to_date", "todate", "to_time", "totime", "to_interval", "tointerval", "regexp_match", "now", "_now", "age", "year", "month", "week", "day", "hour", "minute", "second", "day_of_week", "title", "levenshtein", "longest_common_substring", "hamming_distance", "wordwrap", "regexp_replace", "regexp_substr", "concat", - "strpos", "_left", "_right", "rpad", "lpad", "format", "format_number", "format_date", "color_rgb", "color_rgba", "ramp_color", - "color_hsl", "color_hsla", "color_hsv", "color_hsva", "color_cmyk", "color_cmyka", "color_part", "darker", "lighter", + "strpos", "_left", "_right", "rpad", "lpad", "format", "format_number", "format_date", "color_rgb", "color_rgba", "color_rgbf", "ramp_color", "ramp_color_object", + "color_hsl", "color_hsla", "color_hslf", "color_hsv", "color_hsva", "color_hsvf", "color_cmyk", "color_cmyka", "color_cmykf", "color_part", "darker", "lighter", "set_color_part", "point_n", "start_point", "end_point", "nodes_to_points", "segments_to_lines", "make_point", "make_point_m", "make_line", "make_polygon", "x_min", "xmin", "x_max", "xmax", "y_min", "ymin", "y_max", "ymax", "geom_from_wkt", "geomFromWKT", "geom_from_gml", "relate", "intersects_bbox", "bbox", "translate", "buffer", "point_on_surface", "reverse", "exterior_ring", "interior_ring_n", "geometry_n", "bounds", "num_points", "num_interior_rings", "num_rings", "num_geometries", "bounds_width", "bounds_height", "is_closed", "convex_hull", "sym_difference", "combine", "_union", "geom_to_wkt", "geomToWKT", - "transform", "uuid", "_uuid", "layer_property", "var", "_specialcol_", "project_color"] + "transform", "uuid", "_uuid", "layer_property", "var", "_specialcol_", "project_color", "project_color_object"] # constants diff --git a/python/plugins/processing/algs/qgis/FieldPyculator.py b/python/plugins/processing/algs/qgis/FieldPyculator.py index a626d0f592c1..72fed984c2b3 100644 --- a/python/plugins/processing/algs/qgis/FieldPyculator.py +++ b/python/plugins/processing/algs/qgis/FieldPyculator.py @@ -22,7 +22,8 @@ import sys from qgis.PyQt.QtCore import QMetaType -from qgis.core import (QgsProcessingException, +from qgis.core import (Qgis, + QgsProcessingException, QgsField, QgsFields, QgsFeatureSink, @@ -47,6 +48,11 @@ class FieldsPyculator(QgisAlgorithm): OUTPUT = 'OUTPUT' RESULT_VAR_NAME = 'value' + def flags(self): + # This algorithm represents a security risk, due to the use + # of the Python "exec" function + return super().flags() | Qgis.ProcessingAlgorithmFlag.SecurityRisk + def group(self): return self.tr('Vector table') diff --git a/python/plugins/processing/algs/qgis/PolarPlot.py b/python/plugins/processing/algs/qgis/PolarPlot.py index a2e2100488a2..07fa5e5e55ee 100644 --- a/python/plugins/processing/algs/qgis/PolarPlot.py +++ b/python/plugins/processing/algs/qgis/PolarPlot.py @@ -52,7 +52,9 @@ def initAlgorithm(self, config=None): self.addParameter(QgsProcessingParameterField(self.NAME_FIELD, self.tr('Category name field'), parentLayerParameterName=self.INPUT)) # FIXME unused? self.addParameter(QgsProcessingParameterField(self.VALUE_FIELD, - self.tr('Value field'), parentLayerParameterName=self.INPUT)) + self.tr('Value field'), + parentLayerParameterName=self.INPUT, + type=QgsProcessingParameterField.DataType.Numeric)) self.addParameter(QgsProcessingParameterFileDestination(self.OUTPUT, self.tr('Polar plot'), self.tr('HTML files (*.html)'))) @@ -89,8 +91,9 @@ def processAlgorithm(self, parameters, context, feedback): values = vector.values(source, valuefieldname) - data = [go.Area(r=values[valuefieldname], - t=np.degrees(np.arange(0.0, 2 * np.pi, 2 * np.pi / len(values[valuefieldname]))))] + data = [go.Barpolar(r=values[valuefieldname], + theta=np.degrees(np.arange(0.0, 2 * np.pi, 2 * np.pi / len(values[valuefieldname]))))] + plt.offline.plot(data, filename=output, auto_open=False) return {self.OUTPUT: output} diff --git a/python/plugins/processing/gui/AlgorithmDialog.py b/python/plugins/processing/gui/AlgorithmDialog.py index bac2f1725e9e..091f61df28d0 100644 --- a/python/plugins/processing/gui/AlgorithmDialog.py +++ b/python/plugins/processing/gui/AlgorithmDialog.py @@ -226,7 +226,7 @@ def runAlgorithm(self): self.feedback.pushInfo('') start_time = time.time() - def elapsed_time(start_time, result): + def elapsed_time(start_time) -> str: delta_t = time.time() - start_time hours = int(delta_t / 3600) minutes = int((delta_t % 3600) / 60) @@ -237,14 +237,14 @@ def elapsed_time(start_time, result): str_seconds = [self.tr("second"), self.tr("seconds")][seconds != 1] if hours > 0: - elapsed = '{0} {1:0.2f} {2} ({3} {4} {5} {6} {7:0.0f} {2})'.format( - result, delta_t, str_seconds, hours, str_hours, minutes, str_minutes, seconds) + elapsed = '{0:0.2f} {1} ({2} {3} {4} {5} {6:0.0f} {1})'.format( + delta_t, str_seconds, hours, str_hours, minutes, str_minutes, seconds) elif minutes > 0: - elapsed = '{0} {1:0.2f} {2} ({3} {4} {5:0.0f} {2})'.format( - result, delta_t, str_seconds, minutes, str_minutes, seconds) + elapsed = '{0:0.2f} {1} ({2} {3} {4:0.0f} {1})'.format( + delta_t, str_seconds, minutes, str_minutes, seconds) else: - elapsed = '{} {:0.2f} {}'.format( - result, delta_t, str_seconds) + elapsed = '{:0.2f} {}'.format( + delta_t, str_seconds) return elapsed @@ -259,7 +259,7 @@ def elapsed_time(start_time, result): self.cancelButton().setEnabled(self.algorithm().flags() & QgsProcessingAlgorithm.Flag.FlagCanCancel) if executeIterating(self.algorithm(), parameters, self.iterateParam, self.context, self.feedback): self.feedback.pushInfo( - self.tr(elapsed_time(start_time, 'Execution completed in'))) + self.tr('Execution completed in {}').format(elapsed_time(start_time))) self.cancelButton().setEnabled(False) self.finish(True, parameters, self.context, self.feedback) else: @@ -282,11 +282,11 @@ def elapsed_time(start_time, result): def on_complete(ok, results): if ok: self.feedback.pushInfo( - self.tr(elapsed_time(start_time, 'Execution completed in'))) + self.tr('Execution completed in {}').format(elapsed_time(start_time))) self.feedback.pushFormattedResults(self.algorithm(), self.context, results) else: self.feedback.reportError( - self.tr(elapsed_time(start_time, 'Execution failed after'))) + self.tr('Execution failed after {}').format(elapsed_time(start_time))) self.feedback.pushInfo('') if self.history_log_id is not None: diff --git a/python/plugins/processing/gui/BatchPanel.py b/python/plugins/processing/gui/BatchPanel.py index 51af139c258d..b3e66e6f42ae 100644 --- a/python/plugins/processing/gui/BatchPanel.py +++ b/python/plugins/processing/gui/BatchPanel.py @@ -23,7 +23,7 @@ import json import warnings from pathlib import Path -from typing import Optional +from typing import Optional, List, Dict from qgis.PyQt import uic from qgis.PyQt.QtWidgets import ( @@ -83,7 +83,8 @@ QgsRasterLayer, QgsProcessingUtils, QgsFileFilterGenerator, - QgsProcessingContext + QgsProcessingContext, + QgsFileUtils ) from qgis.gui import ( QgsProcessingParameterWidgetContext, @@ -440,6 +441,9 @@ def populateByExpression(self, adding=False): class BatchPanel(QgsPanelWidget, WIDGET): PARAMETERS = "PARAMETERS" OUTPUTS = "OUTPUTS" + ROWS = "rows" + FORMAT = "format" + CURRENT_FORMAT = "batch_3.40" def __init__(self, parent, alg): super().__init__(None) @@ -543,22 +547,96 @@ def clear(self): self.wrappers = [] def load(self): - context = dataobjects.createContext() + if self.alg.flags() & Qgis.ProcessingAlgorithmFlag.SecurityRisk: + message_box = QMessageBox() + message_box.setWindowTitle(self.tr("Security warning")) + message_box.setText( + self.tr( + "This algorithm is a potential security risk if executed with unchecked inputs, and may result in system damage or data leaks. Only continue if you trust the source of the file. Continue?")) + message_box.setIcon(QMessageBox.Icon.Warning) + message_box.addButton(QMessageBox.StandardButton.Yes) + message_box.addButton(QMessageBox.StandardButton.No) + message_box.setDefaultButton(QMessageBox.StandardButton.No) + message_box.exec() + if message_box.result() != QMessageBox.StandardButton.Yes: + return + settings = QgsSettings() last_path = settings.value("/Processing/LastBatchPath", QDir.homePath()) - filename, selected_filter = QFileDialog.getOpenFileName(self, - self.tr('Open Batch'), last_path, - self.tr('JSON files (*.json)')) - if filename: - last_path = QFileInfo(filename).path() - settings.setValue('/Processing/LastBatchPath', last_path) - with open(filename) as f: - values = json.load(f) + filters = ';;'.join([self.tr('Batch Processing files (*.batch)'), + self.tr('JSON files (*.json)')]) + filename, _ = QFileDialog.getOpenFileName(self, + self.tr('Open Batch'), + last_path, + filters) + if not filename: + return + + last_path = QFileInfo(filename).path() + settings.setValue('/Processing/LastBatchPath', last_path) + with open(filename) as f: + values = json.load(f) + + if isinstance(values, dict): + if values.get(self.FORMAT) == self.CURRENT_FORMAT: + self.load_batch_file_3_40_version(values) + else: + QMessageBox.critical( + self, + self.tr('Load Batch Parameters'), + self.tr('This file format is unknown and cannot be opened as batch parameters.')) else: - # If the user clicked on the cancel button. + self.load_old_json_batch_file(values) + + def load_batch_file_3_40_version(self, values: Dict): + """ + Loads the newer version 3.40 batch parameter JSON format + """ + context = dataobjects.createContext() + rows: List = values.get(self.ROWS, []) + + self.clear() + for row_number, row in enumerate(rows): + self.addRow() + this_row_params = row[self.PARAMETERS] + this_row_outputs = row[self.OUTPUTS] + + for param in self.alg.parameterDefinitions(): + if param.isDestination(): + continue + if param.name() in this_row_params: + column = self.parameter_to_column[param.name()] + value = this_row_params[param.name()] + wrapper = self.wrappers[row_number][column] + wrapper.setParameterValue(value, context) + + for out in self.alg.destinationParameterDefinitions(): + if out.flags() & QgsProcessingParameterDefinition.Flag.FlagHidden: + continue + if out.name() in this_row_outputs: + column = self.parameter_to_column[out.name()] + value = this_row_outputs[out.name()].strip("'") + widget = self.tblParameters.cellWidget(row_number + 1, column) + widget.setValue(value) + + def load_old_json_batch_file(self, values: List): + """ + Loads the old, insecure batch parameter JSON format + """ + message_box = QMessageBox() + message_box.setWindowTitle(self.tr("Security warning")) + message_box.setText( + self.tr("Opening older QGIS batch Processing files from an untrusted source can harm your computer. Only continue if you trust the source of the file. Continue?")) + message_box.setIcon(QMessageBox.Icon.Warning) + message_box.addButton(QMessageBox.StandardButton.Yes) + message_box.addButton(QMessageBox.StandardButton.No) + message_box.setDefaultButton(QMessageBox.StandardButton.No) + message_box.exec() + if message_box.result() != QMessageBox.StandardButton.Yes: return self.clear() + context = dataobjects.createContext() try: for row, alg in enumerate(values): self.addRow() @@ -585,15 +663,15 @@ def load(self): except TypeError: QMessageBox.critical( self, - self.tr('Error'), - self.tr('An error occurred while reading your file.')) + self.tr('Load Batch Parameters'), + self.tr('An error occurred while reading the batch parameters file.')) def save(self): - toSave = [] + row_parameters = [] context = dataobjects.createContext() for row in range(self.batchRowCount()): - algParams = {} - algOutputs = {} + this_row_params = {} + this_row_outputs = {} alg = self.alg for param in alg.parameterDefinitions(): if param.isDestination(): @@ -602,15 +680,6 @@ def save(self): col = self.parameter_to_column[param.name()] wrapper = self.wrappers[row][col] - # For compatibility with 3.x API, we need to check whether the wrapper is - # the deprecated WidgetWrapper class. If not, it's the newer - # QgsAbstractProcessingParameterWidgetWrapper class - # TODO QGIS 4.0 - remove - if issubclass(wrapper.__class__, WidgetWrapper): - widget = wrapper.widget - else: - widget = wrapper.wrappedWidget() - value = wrapper.parameterValue() if not param.checkValueIsAcceptable(value, context): @@ -618,7 +687,7 @@ def save(self): param.description(), row + 2) self.parent.messageBar().pushMessage("", msg, level=Qgis.MessageLevel.Warning, duration=5) return - algParams[param.name()] = param.valueAsPythonString(value, context) + this_row_params[param.name()] = param.valueAsJsonObject(value, context) for out in alg.destinationParameterDefinitions(): if out.flags() & QgsProcessingParameterDefinition.Flag.FlagHidden: @@ -627,28 +696,34 @@ def save(self): widget = self.tblParameters.cellWidget(row + 1, col) text = widget.getValue() if text.strip() != '': - algOutputs[out.name()] = text.strip() + this_row_outputs[out.name()] = text.strip() else: self.parent.messageBar().pushMessage("", self.tr('Wrong or missing output value: {0} (row {1})').format( out.description(), row + 2), level=Qgis.MessageLevel.Warning, duration=5) return - toSave.append({self.PARAMETERS: algParams, self.OUTPUTS: algOutputs}) + row_parameters.append({self.PARAMETERS: this_row_params, self.OUTPUTS: this_row_outputs}) + + output_json = { + self.FORMAT: self.CURRENT_FORMAT, + self.ROWS: row_parameters + } settings = QgsSettings() last_path = settings.value("/Processing/LastBatchPath", QDir.homePath()) filename, __ = QFileDialog.getSaveFileName(self, self.tr('Save Batch'), last_path, - self.tr('JSON files (*.json)')) - if filename: - if not filename.endswith('.json'): - filename += '.json' - last_path = QFileInfo(filename).path() - settings.setValue('/Processing/LastBatchPath', last_path) - with open(filename, 'w') as f: - json.dump(toSave, f) + self.tr('Batch Processing files (*.batch)')) + if not filename: + return + + filename = QgsFileUtils.ensureFileNameHasExtension(filename, ['batch']) + last_path = QFileInfo(filename).path() + settings.setValue('/Processing/LastBatchPath', last_path) + with open(filename, 'w') as f: + json.dump(output_json, f, indent=2) def setCellWrapper(self, row, column, wrapper, context): self.wrappers[row - 1][column] = wrapper diff --git a/resources/data/qgis-hackfests.json b/resources/data/qgis-hackfests.json index fe3c8861be65..53c69105132a 100644 --- a/resources/data/qgis-hackfests.json +++ b/resources/data/qgis-hackfests.json @@ -27,6 +27,7 @@ { "type": "Feature", "properties": { "year": 2019, "month": "August", "hackfest_number": "23", "place": "Bucharest", "notes": "A lot of us got (temporary) QGIS tattoos here.", "month_int": 8, "day_int": 23, "date_nice": "2019\/08\/23" }, "geometry": { "type": "Point", "coordinates": [ 26.101816993272479, 44.43597873093433 ] } }, { "type": "Feature", "properties": { "year": 2022, "month": "August", "hackfest_number": "24", "place": "Firenze", "notes": "Along with the FOSS4G and SotM. Many pizzas, but hard to find the Hawaii", "month_int": 8, "day_int": 19, "date_nice": "2022\/08\/19" }, "geometry": { "type": "Point", "coordinates": [ 11.2453847, 43.8007724 ] } }, { "type": "Feature", "properties": { "year": 2023, "month": "August", "hackfest_number": "25", "place": "'s-Hertogenbosch", "notes": "Fifth User Conference (sold out), with bossche bollen and jogging in the rain.", "month_int": 4, "day_int": 20, "date_nice": "2023\/04\/20" }, "geometry": { "type": "Point", "coordinates": [ 5.292566, 51.695442 ] } }, -{ "type": "Feature", "properties": { "year": 2023, "month": "November", "hackfest_number": "26", "place": "Wien", "notes": "Aligning with other OSGeo software during OSGeo code sprint. The Big Data from Space (BiDS) conference was our side event ;).", "month_int": 11, "day_int": 6, "date_nice": "2023\/11\/06" }, "geometry": { "type": "Point", "coordinates": [ 16.4144871, 48.2354494 ] } } +{ "type": "Feature", "properties": { "year": 2023, "month": "November", "hackfest_number": "26", "place": "Wien", "notes": "Aligning with other OSGeo software during OSGeo code sprint. The Big Data from Space (BiDS) conference was our side event. ;-)", "month_int": 11, "day_int": 6, "date_nice": "2023\/11\/06" }, "geometry": { "type": "Point", "coordinates": [ 16.4144871, 48.2354494 ] } }, +{ "type": "Feature", "properties": { "year": 2024, "month": "September", "hackfest_number": "27", "place": "Bratislava", "notes": "Along with the 6th User Conference. Many local snacks and drinks provided, including RoĹľky, Kofola and Pipi.", "month_int": 9, "day_int": 11, "date_nice": "2024\/09\/11" }, "geometry": { "type": "Point", "coordinates": [ 17.114705, 48.152071 ] } } ] } diff --git a/resources/function_help/json/project_color_object b/resources/function_help/json/project_color_object new file mode 100644 index 000000000000..f971ac6c2219 --- /dev/null +++ b/resources/function_help/json/project_color_object @@ -0,0 +1,15 @@ +{ + "name": "project_color_object", + "type": "function", + "groups": ["Color"], + "description": "Returns a color from the project's color scheme. Contrary to project_color which returns a color string representation, project_color_object returns a color object.", + "arguments": [{ + "arg": "name", + "description": "a color name" + }], + "examples": [{ + "expression": "project_color_object('Logo color')", + "returns": "RGBA: 0.08,0.55,0.20,1.00" + }], + "tags": ["scheme", "project", "color"] +} diff --git a/resources/function_help/json/ramp_color_object b/resources/function_help/json/ramp_color_object new file mode 100644 index 000000000000..ae35f2a29980 --- /dev/null +++ b/resources/function_help/json/ramp_color_object @@ -0,0 +1,37 @@ +{ + "name": "ramp_color_object", + "type": "function", + "groups": ["Color"], + "description": "Returns a color object from a color ramp. Contrary to ramp_color which returns a color string representation, ramp_color_object returns a color object.", + "variants": [{ + "variant": "Saved ramp variant", + "variant_description": "Returns a color object from a saved ramp", + "arguments": [{ + "arg": "ramp_name", + "description": "the name of the color ramp as a string, for example 'Spectral'" + }, { + "arg": "value", + "description": "the position on the ramp to select the color from as a real number between 0 and 1" + }], + "examples": [{ + "expression": "ramp_color_object('Spectral',0.3)", + "returns": "RGBA: 0.99,0.75,0.45,1.00" + }], + "notes": "The color ramps available vary between QGIS installations. This function may not give the expected results if you move your QGIS project between installations." + }, { + "variant": "Expression-created ramp variant", + "variant_description": "Returns a color object from an expression-created ramp", + "arguments": [{ + "arg": "ramp", + "description": "the color ramp" + }, { + "arg": "value", + "description": "the position on the ramp to select the color from as a real number between 0 and 1" + }], + "examples": [{ + "expression": "ramp_color_object(create_ramp(map(0,color_rgbf(0,0,0),1,color_rgbf(1,0,0))),1)", + "returns": "RGBA: 1.00,0.00,0.00,1.00" + }] + }], + "tags": ["ramp", "color"] +} diff --git a/src/app/labeling/qgslabelpropertydialog.cpp b/src/app/labeling/qgslabelpropertydialog.cpp index 79f0db0c50f0..e64cfafbc091 100644 --- a/src/app/labeling/qgslabelpropertydialog.cpp +++ b/src/app/labeling/qgslabelpropertydialog.cpp @@ -360,12 +360,8 @@ void QgsLabelPropertyDialog::setDataDefinedValues( QgsVectorLayer *vlayer ) //even if the data defined property is set to an expression, as it's useful to show //users what the evaluated property is... - QgsExpressionContext context; - context << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ) - << QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() ) - << QgsExpressionContextUtils::layerScope( vlayer ); + QgsExpressionContext context = QgisApp::instance()->mapCanvas()->createExpressionContext(); + context << QgsExpressionContextUtils::layerScope( vlayer ); context.setFeature( mCurLabelFeat ); const auto constPropertyKeys = mDataDefinedProperties.propertyKeys(); diff --git a/src/app/layout/qgslayoutdesignerdialog.cpp b/src/app/layout/qgslayoutdesignerdialog.cpp index 04a30b31c51b..381f0d6fc3dd 100644 --- a/src/app/layout/qgslayoutdesignerdialog.cpp +++ b/src/app/layout/qgslayoutdesignerdialog.cpp @@ -753,6 +753,7 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla mView->resizeSelectedItems( QgsLayoutAligner::ResizeToSquare ); } ); + connect( mActionPageProperties, &QAction::triggered, this, &QgsLayoutDesignerDialog::showPageProperties ); connect( mActionAddPages, &QAction::triggered, this, &QgsLayoutDesignerDialog::addPages ); connect( mActionUnlockAll, &QAction::triggered, this, &QgsLayoutDesignerDialog::unlockAllItems ); @@ -1921,6 +1922,16 @@ void QgsLayoutDesignerDialog::addPages() } } +void QgsLayoutDesignerDialog::showPageProperties() +{ + QgsLayoutItemPage *page = mLayout->pageCollection()->page( 0 ); + + if ( page ) + { + showItemOptions( page, true ); + } +} + void QgsLayoutDesignerDialog::statusMessageReceived( const QString &message ) { mStatusBar->showMessage( message ); diff --git a/src/app/layout/qgslayoutdesignerdialog.h b/src/app/layout/qgslayoutdesignerdialog.h index cefd2c32f7a1..97325944062d 100644 --- a/src/app/layout/qgslayoutdesignerdialog.h +++ b/src/app/layout/qgslayoutdesignerdialog.h @@ -381,6 +381,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, public Ui::QgsLayoutDesignerB void toggleFullScreen( bool enabled ); void addPages(); + void showPageProperties(); void statusMessageReceived( const QString &message ); void dockVisibilityChanged( bool visible ); void undoRedoOccurredForItems( const QSet< QString > &itemUuids ); diff --git a/src/app/qgspointmarkeritem.cpp b/src/app/qgspointmarkeritem.cpp index f1a6d448aa6e..4136afbb5518 100644 --- a/src/app/qgspointmarkeritem.cpp +++ b/src/app/qgspointmarkeritem.cpp @@ -42,17 +42,17 @@ QgsMapCanvasSymbolItem::~QgsMapCanvasSymbolItem() = default; QgsRenderContext QgsMapCanvasSymbolItem::renderContext( QPainter *painter ) { QgsExpressionContext context; - context << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); + if ( mMapCanvas ) { - context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ) - << new QgsExpressionContextScope( mMapCanvas->expressionContextScope() ); + context = mMapCanvas->createExpressionContext(); } else { - context << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + context << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } //context << QgsExpressionContextUtils::layerScope( mLayer ); context.setFeature( mFeature ); diff --git a/src/app/qgsvectorlayerdigitizingproperties.cpp b/src/app/qgsvectorlayerdigitizingproperties.cpp index 610aef331896..1c4362424123 100644 --- a/src/app/qgsvectorlayerdigitizingproperties.cpp +++ b/src/app/qgsvectorlayerdigitizingproperties.cpp @@ -43,9 +43,8 @@ QgsVectorLayerDigitizingPropertiesPage::QgsVectorLayerDigitizingPropertiesPage( mGeometryPrecisionLineEdit->setValidator( new QDoubleValidator( mGeometryPrecisionLineEdit ) ); const double precision( vlayer->geometryOptions()->geometryPrecision() ); - const bool ok = true; - QString precisionStr( QLocale().toString( precision, ok ) ); - if ( precision == 0.0 || ! ok ) + QString precisionStr( QLocale().toString( precision, 'g', 17 ) ); + if ( precision == 0.0 ) precisionStr = QString(); mGeometryPrecisionLineEdit->setText( precisionStr ); diff --git a/src/app/vertextool/qgsvertextool.cpp b/src/app/vertextool/qgsvertextool.cpp index aff531ec1444..a8208b90bf3a 100644 --- a/src/app/vertextool/qgsvertextool.cpp +++ b/src/app/vertextool/qgsvertextool.cpp @@ -2258,19 +2258,28 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato { // topo editing: add vertex to existing segments when moving/adding a vertex to such segment. - // compute layers we have to add topological point on (modified ones + snapped one) - QSet targetLayers( edits.keyBegin(), edits.keyEnd() ); - if ( mapPointMatch->layer() ) - targetLayers << mapPointMatch->layer(); + const QList targetLayers = canvas()->layers( true ); for ( auto itLayerEdits = edits.begin(); itLayerEdits != edits.end(); ++itLayerEdits ) { - for ( QgsVectorLayer *targetLayer : targetLayers ) + for ( QgsMapLayer *targetLayer : targetLayers ) { + QgsVectorLayer *vectorLayer = qobject_cast( targetLayer ); + + if ( !vectorLayer || !vectorLayer->isEditable() ) + continue; + + if ( !( vectorLayer->geometryType() == Qgis::GeometryType::Polygon || vectorLayer->geometryType() == Qgis::GeometryType::Line ) ) + continue; + // layer's CRS need to be the the same (otherwise we would need to reproject the point and it will not be coincident) - if ( targetLayer->crs() != itLayerEdits.key()->crs() ) + if ( vectorLayer->crs() != itLayerEdits.key()->crs() ) continue; + vectorLayer->beginEditCommand( tr( "Topological points added by 'Vertex Tool'" ) ); + + bool topoPointsAdded = false; + for ( auto itFeatEdit = itLayerEdits->begin(); itFeatEdit != itLayerEdits->end(); ++itFeatEdit ) { for ( QgsPoint point : itFeatEdit->newPoints ) @@ -2278,9 +2287,17 @@ void QgsVertexTool::moveVertex( const QgsPointXY &mapPoint, const QgsPointLocato if ( !point.is3D() ) point.addZValue( defaultZValue() ); - targetLayer->addTopologicalPoints( point ); + int res = vectorLayer->addTopologicalPoints( point ); + + if ( res == 0 ) + topoPointsAdded = true; } } + + if ( topoPointsAdded ) + vectorLayer->endEditCommand(); + else + vectorLayer->destroyEditCommand(); } } } diff --git a/src/core/diagram/qgsdiagram.h b/src/core/diagram/qgsdiagram.h index 8d5f3dd57c2d..5c9df65f31f9 100644 --- a/src/core/diagram/qgsdiagram.h +++ b/src/core/diagram/qgsdiagram.h @@ -48,9 +48,9 @@ class CORE_EXPORT QgsDiagram SIP_NODEFAULTCTORS sipType = sipType_QgsHistogramDiagram; else if ( sipCpp->diagramName() == QLatin1String( "Text" ) ) sipType = sipType_QgsTextDiagram; - else if ( sipCpp->diagramName() == QLatin1String( "StackedBar" ) ) - sipType = sipType_QgsStackedBarDiagram; else if ( sipCpp->diagramName() == QLatin1String( "Stacked" ) ) + sipType = sipType_QgsStackedBarDiagram; + else if ( sipCpp->diagramName() == QLatin1String( "StackedDiagram" ) ) sipType = sipType_QgsStackedDiagram; else sipType = NULL; diff --git a/src/core/diagram/qgsstackedbardiagram.cpp b/src/core/diagram/qgsstackedbardiagram.cpp index 5b8acd864db2..2c65d7b7da7d 100644 --- a/src/core/diagram/qgsstackedbardiagram.cpp +++ b/src/core/diagram/qgsstackedbardiagram.cpp @@ -22,7 +22,7 @@ #include -const QString QgsStackedBarDiagram::DIAGRAM_NAME_STACKED_BAR = QStringLiteral( "StackedBar" ); +const QString QgsStackedBarDiagram::DIAGRAM_NAME_STACKED_BAR = QStringLiteral( "Stacked" ); QgsStackedBarDiagram::QgsStackedBarDiagram() { diff --git a/src/core/diagram/qgsstackeddiagram.cpp b/src/core/diagram/qgsstackeddiagram.cpp index fb64b61bc1df..2f96537c15f5 100644 --- a/src/core/diagram/qgsstackeddiagram.cpp +++ b/src/core/diagram/qgsstackeddiagram.cpp @@ -16,7 +16,7 @@ #include "qgsdiagramrenderer.h" #include "qgsrendercontext.h" -const QString QgsStackedDiagram::DIAGRAM_NAME_STACKED = QStringLiteral( "Stacked" ); +const QString QgsStackedDiagram::DIAGRAM_NAME_STACKED = QStringLiteral( "StackedDiagram" ); QgsStackedDiagram::QgsStackedDiagram() { diff --git a/src/core/expression/qgsexpressioncontextutils.cpp b/src/core/expression/qgsexpressioncontextutils.cpp index 89dba92bce95..43b07ae9cfcb 100644 --- a/src/core/expression/qgsexpressioncontextutils.cpp +++ b/src/core/expression/qgsexpressioncontextutils.cpp @@ -954,6 +954,7 @@ QgsExpressionContextScope *QgsExpressionContextUtils::notificationScope( const Q void QgsExpressionContextUtils::registerContextFunctions() { QgsExpression::registerFunction( new GetNamedProjectColor( nullptr ) ); + QgsExpression::registerFunction( new GetNamedProjectColorObject( nullptr ) ); QgsExpression::registerFunction( new GetSensorData( ) ); QgsExpression::registerFunction( new GetLayoutItemVariables( nullptr ) ); QgsExpression::registerFunction( new GetLayoutMapLayerCredits( nullptr ) ); @@ -1430,4 +1431,3 @@ QgsScopedExpressionFunction *LoadLayerFunction::clone() const return new LoadLayerFunction(); } ///@endcond - diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp index bb6eaf55a11c..add3c78dd654 100644 --- a/src/core/expression/qgsexpressionfunction.cpp +++ b/src/core/expression/qgsexpressionfunction.cpp @@ -6073,7 +6073,7 @@ static QVariant fncColorRgba( const QVariantList &values, const QgsExpressionCon return QgsSymbolLayerUtils::encodeColor( color ); } -QVariant fcnRampColor( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) +QVariant fcnRampColorObject( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) { QgsGradientColorRamp expRamp; const QgsColorRamp *ramp = nullptr; @@ -6095,7 +6095,13 @@ QVariant fcnRampColor( const QVariantList &values, const QgsExpressionContext *, double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ); QColor color = ramp->color( value ); - return QgsSymbolLayerUtils::encodeColor( color ); + return color; +} + +QVariant fcnRampColor( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node ) +{ + QColor color = fcnRampColorObject( values, context, parent, node ).value(); + return color.isValid() ? QgsSymbolLayerUtils::encodeColor( color ) : QVariant(); } static QVariant fcnColorHsl( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) @@ -8572,6 +8578,9 @@ const QList &QgsExpression::Functions() << new QgsStaticExpressionFunction( QStringLiteral( "ramp_color" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "ramp_name" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fcnRampColor, QStringLiteral( "Color" ) ) + << new QgsStaticExpressionFunction( QStringLiteral( "ramp_color_object" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "ramp_name" ) ) + << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), + fcnRampColorObject, QStringLiteral( "Color" ) ) << new QgsStaticExpressionFunction( QStringLiteral( "create_ramp" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "map" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "discrete" ), true, false ), fcnCreateRamp, QStringLiteral( "Color" ) ) diff --git a/src/core/layertree/qgscolorramplegendnode.cpp b/src/core/layertree/qgscolorramplegendnode.cpp index 7dbb85904275..780984813114 100644 --- a/src/core/layertree/qgscolorramplegendnode.cpp +++ b/src/core/layertree/qgscolorramplegendnode.cpp @@ -27,9 +27,11 @@ #include #include -QgsColorRampLegendNode::QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp, const QString &minimumLabel, const QString &maximumLabel, QObject *parent ) +QgsColorRampLegendNode::QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp, const QString &minimumLabel, const QString &maximumLabel, QObject *parent, const QString &key, const QString &parentKey ) : QgsLayerTreeModelLegendNode( nodeLayer, parent ) , mRamp( ramp ) + , mKey( key ) + , mParentKey( parentKey ) { mSettings.setMinimumLabel( minimumLabel ); mSettings.setMaximumLabel( maximumLabel ); @@ -37,12 +39,14 @@ QgsColorRampLegendNode::QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, Qg init( nodeLayer ); } -QgsColorRampLegendNode::QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp, const QgsColorRampLegendNodeSettings &settings, double minimumValue, double maximumValue, QObject *parent ) +QgsColorRampLegendNode::QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp, const QgsColorRampLegendNodeSettings &settings, double minimumValue, double maximumValue, QObject *parent, const QString &key, const QString &parentKey ) : QgsLayerTreeModelLegendNode( nodeLayer, parent ) , mRamp( ramp ) , mSettings( settings ) , mMinimumValue( minimumValue ) , mMaximumValue( maximumValue ) + , mKey( key ) + , mParentKey( parentKey ) { init( nodeLayer ); } @@ -178,7 +182,10 @@ QVariant QgsColorRampLegendNode::data( int role ) const { return QgsLayerTreeModelLegendNode::ColorRampLegend; } - + else if ( role == static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::RuleKey ) ) + return mKey; + else if ( role == static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::ParentRuleKey ) ) + return mParentKey; return QVariant(); } diff --git a/src/core/layertree/qgscolorramplegendnode.h b/src/core/layertree/qgscolorramplegendnode.h index 2c6089235d30..8856770b1bdc 100644 --- a/src/core/layertree/qgscolorramplegendnode.h +++ b/src/core/layertree/qgscolorramplegendnode.h @@ -43,9 +43,12 @@ class CORE_EXPORT QgsColorRampLegendNode : public QgsLayerTreeModelLegendNode * \param minimumLabel label text to render for the minimum value in the ramp * \param maximumLabel label text to render for the maximum value in the ramp * \param parent attach a parent QObject to the legend node. + * \param key rule key. optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.40) + * \param parentKey rule key of parent (since QGIS 3.40) */ QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp SIP_TRANSFER, - const QString &minimumLabel, const QString &maximumLabel, QObject *parent SIP_TRANSFERTHIS = nullptr ); + const QString &minimumLabel, const QString &maximumLabel, QObject *parent SIP_TRANSFERTHIS = nullptr, + const QString &key = QString(), const QString &parentKey = QString() ); /** * Constructor for QgsColorRampLegendNode. @@ -55,10 +58,13 @@ class CORE_EXPORT QgsColorRampLegendNode : public QgsLayerTreeModelLegendNode * \param minimumValue value associated with minimum of ramp * \param maximumValue value associated with maximum of ramp * \param parent attach a parent QObject to the legend node. + * \param key rule key. optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.40) + * \param parentKey rule key of parent (since QGIS 3.40) */ QgsColorRampLegendNode( QgsLayerTreeLayer *nodeLayer, QgsColorRamp *ramp SIP_TRANSFER, const QgsColorRampLegendNodeSettings &settings, double minimumValue, - double maximumValue, QObject *parent SIP_TRANSFERTHIS = nullptr ); + double maximumValue, QObject *parent SIP_TRANSFERTHIS = nullptr, + const QString &key = QString(), const QString &parentKey = QString() ); QVariant data( int role ) const override; @@ -113,7 +119,8 @@ class CORE_EXPORT QgsColorRampLegendNode : public QgsLayerTreeModelLegendNode QgsColorRampLegendNodeSettings mSettings; double mMinimumValue = 0; double mMaximumValue = 0; - + QString mKey; + QString mParentKey; }; diff --git a/src/core/layertree/qgslayertreemodellegendnode.cpp b/src/core/layertree/qgslayertreemodellegendnode.cpp index b6ab65296057..1c9ecea6867a 100644 --- a/src/core/layertree/qgslayertreemodellegendnode.cpp +++ b/src/core/layertree/qgslayertreemodellegendnode.cpp @@ -142,27 +142,26 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &setting size.setHeight( ctx->patchSize.height( ) ); } - if ( ctx && ctx->painter ) + if ( ctx && ctx->painter && ctx->context ) { + const QgsScopedRenderContextScaleToPixels scopedScaleToPixels( *( ctx->context ) ); + const double scaleFactor = ctx->context->scaleFactor(); + const int width = static_cast( size.width() * scaleFactor ); + const int height = static_cast( size.height() * scaleFactor ); + const int y = static_cast( ( ctx->top + ( itemHeight - size.height() ) / 2 ) * scaleFactor ); + int x = 0; + switch ( settings.symbolAlignment() ) { case Qt::AlignLeft: default: - symbolIcon.paint( ctx->painter, - static_cast< int >( ctx->columnLeft ), - static_cast< int >( ctx->top + ( itemHeight - size.height() ) / 2 ), - static_cast< int >( size.width() ), - static_cast< int >( size.height() ) ); + x = static_cast( ctx->columnLeft * scaleFactor ); break; - case Qt::AlignRight: - symbolIcon.paint( ctx->painter, - static_cast< int >( ctx->columnRight - size.width() ), - static_cast< int >( ctx->top + ( itemHeight - size.height() ) / 2 ), - static_cast< int >( size.width() ), - static_cast< int >( size.height() ) ); + x = static_cast( ( ctx->columnRight - size.width() ) * scaleFactor ); break; } + symbolIcon.paint( ctx->painter, x, y, width, height ); } return size; } @@ -1070,12 +1069,13 @@ QJsonObject QgsImageLegendNode::exportSymbolToJson( const QgsLegendSettings &, c // ------------------------------------------------------------------------- -QgsRasterSymbolLegendNode::QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent, bool isCheckable, const QString &ruleKey ) +QgsRasterSymbolLegendNode::QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent, bool isCheckable, const QString &ruleKey, const QString &parentRuleKey ) : QgsLayerTreeModelLegendNode( nodeLayer, parent ) , mColor( color ) , mLabel( label ) , mCheckable( isCheckable ) , mRuleKey( ruleKey ) + , mParentRuleKey( parentRuleKey ) { } @@ -1109,6 +1109,9 @@ QVariant QgsRasterSymbolLegendNode::data( int role ) const case static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::RuleKey ): return mRuleKey; + case static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::ParentRuleKey ): + return mParentRuleKey; + case Qt::CheckStateRole: { if ( !mCheckable ) diff --git a/src/core/layertree/qgslayertreemodellegendnode.h b/src/core/layertree/qgslayertreemodellegendnode.h index cc5d179aa9ef..8f3579da132c 100644 --- a/src/core/layertree/qgslayertreemodellegendnode.h +++ b/src/core/layertree/qgslayertreemodellegendnode.h @@ -679,8 +679,10 @@ class CORE_EXPORT QgsRasterSymbolLegendNode : public QgsLayerTreeModelLegendNode * \param parent attach a parent QObject to the legend node. * \param isCheckable set to TRUE to enable the checkbox for the node (since QGIS 3.18) * \param ruleKey optional identifier to allow a unique ID to be assigned to the node by a renderer (since QGIS 3.18) + * \param parentRuleKey rule key of parent (since QGIS 3.40) */ - QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent SIP_TRANSFERTHIS = nullptr, bool isCheckable = false, const QString &ruleKey = QString() ); + QgsRasterSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QColor &color, const QString &label, QObject *parent SIP_TRANSFERTHIS = nullptr, + bool isCheckable = false, const QString &ruleKey = QString(), const QString &parentRuleKey = QString() ); Qt::ItemFlags flags() const override; QVariant data( int role ) const override; @@ -715,6 +717,7 @@ class CORE_EXPORT QgsRasterSymbolLegendNode : public QgsLayerTreeModelLegendNode QString mLabel; bool mCheckable = false; QString mRuleKey; + QString mParentRuleKey; }; class QgsImageFetcher; diff --git a/src/core/layout/qgslayoutitemlegend.cpp b/src/core/layout/qgslayoutitemlegend.cpp index 3c2803e2f653..eb5a0c6b224c 100644 --- a/src/core/layout/qgslayoutitemlegend.cpp +++ b/src/core/layout/qgslayoutitemlegend.cpp @@ -106,6 +106,8 @@ void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsIt if ( !painter ) return; + const QPointF oldPos = pos(); + ensureModelIsInitialized(); if ( mFilterAskedForUpdate ) @@ -157,8 +159,6 @@ void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsIt QgsLegendRenderer legendRenderer = createRenderer(); legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() ); - const QPointF oldPos = pos(); - //adjust box if width or height is too small if ( mSizeToContents ) { diff --git a/src/core/processing/models/qgsprocessingmodelalgorithm.cpp b/src/core/processing/models/qgsprocessingmodelalgorithm.cpp index d83c86cbfd31..d09266e1352b 100644 --- a/src/core/processing/models/qgsprocessingmodelalgorithm.cpp +++ b/src/core/processing/models/qgsprocessingmodelalgorithm.cpp @@ -45,6 +45,23 @@ void QgsProcessingModelAlgorithm::initAlgorithm( const QVariantMap & ) { } +Qgis::ProcessingAlgorithmFlags QgsProcessingModelAlgorithm::flags() const +{ + Qgis::ProcessingAlgorithmFlags res = QgsProcessingAlgorithm::flags(); + + // don't force algorithm attachment here, that's potentially too expensive + QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin(); + for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt ) + { + if ( childIt->algorithm() && childIt->algorithm()->flags().testFlag( Qgis::ProcessingAlgorithmFlag::SecurityRisk ) ) + { + // security risk flag propagates from child algorithms to model + res |= Qgis::ProcessingAlgorithmFlag::SecurityRisk; + } + } + return res; +} + QString QgsProcessingModelAlgorithm::name() const { return mModelName; diff --git a/src/core/processing/models/qgsprocessingmodelalgorithm.h b/src/core/processing/models/qgsprocessingmodelalgorithm.h index 9f4c1a4e5d62..82f94244ca72 100644 --- a/src/core/processing/models/qgsprocessingmodelalgorithm.h +++ b/src/core/processing/models/qgsprocessingmodelalgorithm.h @@ -47,6 +47,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override; //#spellok + Qgis::ProcessingAlgorithmFlags flags() const override; QString name() const override; QString displayName() const override; QString group() const override; diff --git a/src/core/project/qgsproject.cpp b/src/core/project/qgsproject.cpp index a24a61ef81eb..b7cb65dbfc16 100644 --- a/src/core/project/qgsproject.cpp +++ b/src/core/project/qgsproject.cpp @@ -2936,6 +2936,7 @@ QgsExpressionContextScope *QgsProject::createExpressionContextScope() const mProjectScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "layers" ), layers, true ) ); mProjectScope->addFunction( QStringLiteral( "project_color" ), new GetNamedProjectColor( this ) ); + mProjectScope->addFunction( QStringLiteral( "project_color_object" ), new GetNamedProjectColorObject( this ) ); return createExpressionContextScope(); } @@ -5320,11 +5321,10 @@ void QgsProject::cleanFunctionsFromProject() } /// @cond PRIVATE -GetNamedProjectColor::GetNamedProjectColor( const QgsProject *project ) - : QgsScopedExpressionFunction( QStringLiteral( "project_color" ), 1, QStringLiteral( "Color" ) ) + +QHash< QString, QColor > loadColorsFromProject( const QgsProject *project ) { - if ( !project ) - return; + QHash< QString, QColor > colors; //build up color list from project. Do this in advance for speed QStringList colorStrings = project->readListEntry( QStringLiteral( "Palette" ), QStringLiteral( "/Colors" ) ); @@ -5342,9 +5342,21 @@ GetNamedProjectColor::GetNamedProjectColor( const QgsProject *project ) label = colorLabels.at( colorIndex ); } - mColors.insert( label.toLower(), color ); + colors.insert( label.toLower(), color ); colorIndex++; } + + return colors; +} + + +GetNamedProjectColor::GetNamedProjectColor( const QgsProject *project ) + : QgsScopedExpressionFunction( QStringLiteral( "project_color" ), 1, QStringLiteral( "Color" ) ) +{ + if ( !project ) + return; + + mColors = loadColorsFromProject( project ); } GetNamedProjectColor::GetNamedProjectColor( const QHash &colors ) @@ -5369,6 +5381,37 @@ QgsScopedExpressionFunction *GetNamedProjectColor::clone() const return new GetNamedProjectColor( mColors ); } +GetNamedProjectColorObject::GetNamedProjectColorObject( const QgsProject *project ) + : QgsScopedExpressionFunction( QStringLiteral( "project_color_object" ), 1, QStringLiteral( "Color" ) ) +{ + if ( !project ) + return; + + mColors = loadColorsFromProject( project ); +} + +GetNamedProjectColorObject::GetNamedProjectColorObject( const QHash &colors ) + : QgsScopedExpressionFunction( QStringLiteral( "project_color_object" ), 1, QStringLiteral( "Color" ) ) + , mColors( colors ) +{ +} + +QVariant GetNamedProjectColorObject::func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) +{ + const QString colorName = values.at( 0 ).toString().toLower(); + if ( mColors.contains( colorName ) ) + { + return mColors.value( colorName ); + } + else + return QVariant(); +} + +QgsScopedExpressionFunction *GetNamedProjectColorObject::clone() const +{ + return new GetNamedProjectColorObject( mColors ); +} + // ---------------- GetSensorData::GetSensorData( const QMap &sensorData ) diff --git a/src/core/project/qgsproject.h b/src/core/project/qgsproject.h index daa688003838..0248d8064d8e 100644 --- a/src/core/project/qgsproject.h +++ b/src/core/project/qgsproject.h @@ -2583,9 +2583,29 @@ class GetNamedProjectColor : public QgsScopedExpressionFunction private: QHash< QString, QColor > mColors; +}; + +class GetNamedProjectColorObject : public QgsScopedExpressionFunction +{ + public: + GetNamedProjectColorObject( const QgsProject *project ); + + /** + * Optimized constructor for GetNamedProjectColor when a list of map is already available + * and does not need to be read from a project. + */ + GetNamedProjectColorObject( const QHash< QString, QColor > &colors ); + QVariant func( const QVariantList &values, const QgsExpressionContext *, QgsExpression *, const QgsExpressionNodeFunction * ) override; + QgsScopedExpressionFunction *clone() const override; + + private: + + QHash< QString, QColor > mColors; }; + + class GetSensorData : public QgsScopedExpressionFunction { public: diff --git a/src/core/qgis.h b/src/core/qgis.h index 14ea99d1f3d4..397a5bf681fa 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -3303,6 +3303,7 @@ class CORE_EXPORT Qgis SkipGenericModelLogging SIP_MONKEYPATCH_COMPAT_NAME( FlagSkipGenericModelLogging ) = 1 << 12, //!< When running as part of a model, the generic algorithm setup and results logging should be skipped NotAvailableInStandaloneTool SIP_MONKEYPATCH_COMPAT_NAME( FlagNotAvailableInStandaloneTool ) = 1 << 13, //!< Algorithm should not be available from the standalone "qgis_process" tool. Used to flag algorithms which make no sense outside of the QGIS application, such as "select by..." style algorithms. RequiresProject SIP_MONKEYPATCH_COMPAT_NAME( FlagRequiresProject ) = 1 << 14, //!< The algorithm requires that a valid QgsProject is available from the processing context in order to execute + SecurityRisk = 1 << 15, //!< The algorithm represents a potential security risk if executed with untrusted inputs. \since QGIS 3.40 Deprecated SIP_MONKEYPATCH_COMPAT_NAME( FlagDeprecated ) = HideFromToolbox | HideFromModeler, //!< Algorithm is deprecated }; Q_ENUM( ProcessingAlgorithmFlag ); diff --git a/src/core/qgscolorscheme.cpp b/src/core/qgscolorscheme.cpp index a382e63a2283..d19a5fc474db 100644 --- a/src/core/qgscolorscheme.cpp +++ b/src/core/qgscolorscheme.cpp @@ -22,6 +22,7 @@ #include "qgssymbollayerutils.h" #include "qgsapplication.h" #include "qgssettings.h" +#include "qgscolorutils.h" #include #include @@ -206,7 +207,7 @@ QgsNamedColorList QgsProjectColorScheme::fetchColors( const QString &context, co for ( QStringList::iterator it = colorStrings.begin(); it != colorStrings.end(); ++it ) { - const QColor color = QgsSymbolLayerUtils::decodeColor( *it ); + const QColor color = QgsColorUtils::colorFromString( *it ); QString label; if ( colorLabels.length() > colorIndex ) { diff --git a/src/core/qgsmaplayerlegend.cpp b/src/core/qgsmaplayerlegend.cpp index 59680bd262b8..14486fc9bb47 100644 --- a/src/core/qgsmaplayerlegend.cpp +++ b/src/core/qgsmaplayerlegend.cpp @@ -552,16 +552,17 @@ QList QgsDefaultMeshLayerLegend::createLayerTreeM return nodes; } - nodes << new QgsSimpleLegendNode( nodeLayer, name ); - if ( indexScalar > -1 ) { + const QString scalarNameKey = QStringLiteral( "scalarName" ); + nodes << new QgsSimpleLegendNode( nodeLayer, mLayer->datasetGroupMetadata( indexScalar ).name(), + QIcon(), nullptr, scalarNameKey ); const QgsMeshRendererScalarSettings settings = rendererSettings.scalarSettings( indexScalar ); const QgsColorRampShader shader = settings.colorRampShader(); switch ( shader.colorRampType() ) { case Qgis::ShaderInterpolationMethod::Linear: - if ( ! shader.legendSettings() || shader.legendSettings()->useContinuousLegend() ) + if ( !shader.legendSettings() || shader.legendSettings()->useContinuousLegend() ) { // for interpolated shaders we use a ramp legend node if ( !shader.colorRampItemList().isEmpty() ) @@ -569,7 +570,10 @@ QList QgsDefaultMeshLayerLegend::createLayerTreeM nodes << new QgsColorRampLegendNode( nodeLayer, shader.createColorRamp(), shader.legendSettings() ? *shader.legendSettings() : QgsColorRampLegendNodeSettings(), shader.minimumValue(), - shader.maximumValue() ); + shader.maximumValue(), + nullptr, + QStringLiteral( "scalarLegend" ), + scalarNameKey ); } break; } @@ -582,13 +586,76 @@ QList QgsDefaultMeshLayerLegend::createLayerTreeM settings.colorRampShader().legendSymbologyItems( items ); for ( const QPair< QString, QColor > &item : items ) { - nodes << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first ); + nodes << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first, nullptr, false, + QStringLiteral( "scalarLegend" ) + QUuid::createUuid().toString(), + scalarNameKey + ); } break; } } } + if ( indexVector > -1 ) + { + const QgsMeshRendererVectorSettings settings = rendererSettings.vectorSettings( indexVector ); + const QString vectorNameKey = QStringLiteral( "vectorName" ); + switch ( settings.coloringMethod() ) + { + case QgsInterpolatedLineColor::ColoringMethod::SingleColor: + { + const QColor arrowColor = settings.color(); + const QIcon vectorIcon = QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/meshvectors.svg" ), arrowColor, arrowColor ); + nodes << new QgsSimpleLegendNode( nodeLayer, mLayer->datasetGroupMetadata( indexVector ).name(), + vectorIcon, nullptr, vectorNameKey ); + break; + } + case QgsInterpolatedLineColor::ColoringMethod::ColorRamp: + { + const QIcon vectorIcon = QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/meshvectors.svg" ) ); + nodes << new QgsSimpleLegendNode( nodeLayer, mLayer->datasetGroupMetadata( indexVector ).name(), + vectorIcon, nullptr, vectorNameKey ); + const QgsColorRampShader shader = settings.colorRampShader(); + switch ( shader.colorRampType() ) + { + case Qgis::ShaderInterpolationMethod::Linear: + if ( !shader.legendSettings() || shader.legendSettings()->useContinuousLegend() ) + { + // for interpolated shaders we use a ramp legend node + if ( !shader.colorRampItemList().isEmpty() ) + { + nodes << new QgsColorRampLegendNode( nodeLayer, shader.createColorRamp(), + shader.legendSettings() ? *shader.legendSettings() : QgsColorRampLegendNodeSettings(), + shader.minimumValue(), + shader.maximumValue(), + nullptr, + QStringLiteral( "vectorLegend" ), + vectorNameKey ); + } + break; + } + [[fallthrough]]; + case Qgis::ShaderInterpolationMethod::Discrete: + case Qgis::ShaderInterpolationMethod::Exact: + { + // for all others we use itemised lists + QgsLegendColorList items; + settings.colorRampShader().legendSymbologyItems( items ); + for ( const QPair< QString, QColor > &item : items ) + { + nodes << new QgsRasterSymbolLegendNode( nodeLayer, item.second, item.first, nullptr, false, + QStringLiteral( "vectorLegend" ) + QUuid::createUuid().toString(), + vectorNameKey + ); + } + break; + } + break; + } + } + } + } + return nodes; } diff --git a/src/core/qgsproperty.cpp b/src/core/qgsproperty.cpp index 7078790403e4..da85a5c30150 100644 --- a/src/core/qgsproperty.cpp +++ b/src/core/qgsproperty.cpp @@ -505,7 +505,7 @@ QSet QgsProperty::referencedFields( const QgsExpressionContext &context bool QgsProperty::isProjectColor() const { - const thread_local QRegularExpression rx( QStringLiteral( "^project_color\\('.*'\\)$" ) ); + const thread_local QRegularExpression rx( QStringLiteral( "^project_color(_object|)\\('.*'\\)$" ) ); return d->type == Qgis::PropertyType::Expression && !d->expressionString.isEmpty() && rx.match( d->expressionString ).hasMatch(); } diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 1ae411f4b3c8..d0fab41a0f74 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1067,6 +1067,7 @@ set(QGIS_GUI_HDRS annotations/qgsannotationitemguiregistry.h annotations/qgsannotationitemwidget.h annotations/qgscreateannotationitemmaptool.h + annotations/qgscreateannotationitemmaptool_impl.h annotations/qgsmaptoolmodifyannotation.h attributeformconfig/qgsattributeformcontaineredit.h diff --git a/src/gui/annotations/qgscreateannotationitemmaptool.h b/src/gui/annotations/qgscreateannotationitemmaptool.h index 9fe5c618edad..e6d97355e1cf 100644 --- a/src/gui/annotations/qgscreateannotationitemmaptool.h +++ b/src/gui/annotations/qgscreateannotationitemmaptool.h @@ -113,7 +113,7 @@ class GUI_EXPORT QgsCreateAnnotationItemMapToolInterface /** * Returns the handler object for the map tool. */ - virtual QgsCreateAnnotationItemMapToolHandler *handler() = 0; + virtual QgsCreateAnnotationItemMapToolHandler *handler() const = 0; /** * Returns a reference to the associated map tool. diff --git a/src/gui/annotations/qgscreateannotationitemmaptool_impl.cpp b/src/gui/annotations/qgscreateannotationitemmaptool_impl.cpp index 5ebdf01c1927..f2af1e0876ec 100644 --- a/src/gui/annotations/qgscreateannotationitemmaptool_impl.cpp +++ b/src/gui/annotations/qgscreateannotationitemmaptool_impl.cpp @@ -52,7 +52,7 @@ QgsMapToolCaptureAnnotationItem::QgsMapToolCaptureAnnotationItem( QgsMapCanvas * mToolName = tr( "Annotation tool" ); } -QgsCreateAnnotationItemMapToolHandler *QgsMapToolCaptureAnnotationItem::handler() +QgsCreateAnnotationItemMapToolHandler *QgsMapToolCaptureAnnotationItem::handler() const { return mHandler; } @@ -120,7 +120,7 @@ void QgsCreatePointTextItemMapTool::cadCanvasPressEvent( QgsMapMouseEvent *event mHandler->pushCreatedItem( createdItem.release() ); } -QgsCreateAnnotationItemMapToolHandler *QgsCreatePointTextItemMapTool::handler() +QgsCreateAnnotationItemMapToolHandler *QgsCreatePointTextItemMapTool::handler() const { return mHandler; } @@ -369,7 +369,7 @@ void QgsCreatePictureItemMapTool::keyPressEvent( QKeyEvent *event ) } } -QgsCreateAnnotationItemMapToolHandler *QgsCreatePictureItemMapTool::handler() +QgsCreateAnnotationItemMapToolHandler *QgsCreatePictureItemMapTool::handler() const { return mHandler; } @@ -472,7 +472,7 @@ void QgsCreateRectangleTextItemMapTool::keyPressEvent( QKeyEvent *event ) } } -QgsCreateAnnotationItemMapToolHandler *QgsCreateRectangleTextItemMapTool::handler() +QgsCreateAnnotationItemMapToolHandler *QgsCreateRectangleTextItemMapTool::handler() const { return mHandler; } diff --git a/src/gui/annotations/qgscreateannotationitemmaptool_impl.h b/src/gui/annotations/qgscreateannotationitemmaptool_impl.h index 9f9544ad2f6e..c0884cbe05d2 100644 --- a/src/gui/annotations/qgscreateannotationitemmaptool_impl.h +++ b/src/gui/annotations/qgscreateannotationitemmaptool_impl.h @@ -16,24 +16,32 @@ #define QGSCREATEANNOTATIONITEMMAPTOOLIMPL_H #include "qgis_gui.h" -#include "qgis_sip.h" #include "qgscreateannotationitemmaptool.h" #include "qgsmaptoolcapture.h" -#include "qgssettingstree.h" #define SIP_NO_FILE class QgsSettingsEntryString; class QgsSettingsTreeNode; -///@cond PRIVATE -class QgsMapToolCaptureAnnotationItem: public QgsMapToolCapture, public QgsCreateAnnotationItemMapToolInterface +/** + * \class QgsMapToolCaptureAnnotationItem + * \ingroup gui + * + * \brief A base class to digitize annotation items using QgsMapToolCapture + * + * \note Not available in Python bindings. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsMapToolCaptureAnnotationItem: public QgsMapToolCapture, public QgsCreateAnnotationItemMapToolInterface { Q_OBJECT public: + //! Constructor QgsMapToolCaptureAnnotationItem( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode ); - QgsCreateAnnotationItemMapToolHandler *handler() override; + QgsCreateAnnotationItemMapToolHandler *handler() const override; QgsMapTool *mapTool() override; QgsMapLayer *layer() const override; QgsMapToolCapture::Capabilities capabilities() const override; @@ -45,17 +53,25 @@ class QgsMapToolCaptureAnnotationItem: public QgsMapToolCapture, public QgsCreat }; -class QgsCreatePointTextItemMapTool: public QgsMapToolAdvancedDigitizing, public QgsCreateAnnotationItemMapToolInterface +/** + * \class QgsCreatePointTextItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize point text items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreatePointTextItemMapTool: public QgsMapToolAdvancedDigitizing, public QgsCreateAnnotationItemMapToolInterface { Q_OBJECT public: - + //! Constructor QgsCreatePointTextItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); ~QgsCreatePointTextItemMapTool() override; void cadCanvasPressEvent( QgsMapMouseEvent *event ) override; - QgsCreateAnnotationItemMapToolHandler *handler() override; + QgsCreateAnnotationItemMapToolHandler *handler() const override; QgsMapTool *mapTool() override; private: @@ -65,60 +81,90 @@ class QgsCreatePointTextItemMapTool: public QgsMapToolAdvancedDigitizing, public }; -class QgsCreateMarkerItemMapTool: public QgsMapToolCaptureAnnotationItem +/** + * \class QgsCreateMarkerItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize marker items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreateMarkerItemMapTool: public QgsMapToolCaptureAnnotationItem { Q_OBJECT public: - + //! Constructor QgsCreateMarkerItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); void cadCanvasReleaseEvent( QgsMapMouseEvent *event ) override; }; -class QgsCreateLineItemMapTool: public QgsMapToolCaptureAnnotationItem +/** + * \class QgsCreateLineItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize line items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreateLineItemMapTool: public QgsMapToolCaptureAnnotationItem { Q_OBJECT public: - + //! Constructor QgsCreateLineItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); private slots: void lineCaptured( const QgsCurve *line ) override; }; -class QgsCreatePolygonItemMapTool: public QgsMapToolCaptureAnnotationItem +/** + * \class QgsCreatePolygonItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize polygon items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreatePolygonItemMapTool: public QgsMapToolCaptureAnnotationItem { Q_OBJECT public: - + //! Constructor QgsCreatePolygonItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); private slots: void polygonCaptured( const QgsCurvePolygon *polygon ) override; }; - -class QgsCreateRectangleTextItemMapTool: public QgsMapToolAdvancedDigitizing, public QgsCreateAnnotationItemMapToolInterface +/** + * \class QgsCreateRectangleTextItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize rectangle text items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreateRectangleTextItemMapTool: public QgsMapToolAdvancedDigitizing, public QgsCreateAnnotationItemMapToolInterface { Q_OBJECT public: - + //! Constructor QgsCreateRectangleTextItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); void cadCanvasPressEvent( QgsMapMouseEvent *event ) override; void cadCanvasMoveEvent( QgsMapMouseEvent *event ) override; void keyPressEvent( QKeyEvent *event ) override; - QgsCreateAnnotationItemMapToolHandler *handler() override; + QgsCreateAnnotationItemMapToolHandler *handler() const override; QgsMapTool *mapTool() override; private: - QgsCreateAnnotationItemMapToolHandler *mHandler = nullptr; QRectF mRect; @@ -126,8 +172,15 @@ class QgsCreateRectangleTextItemMapTool: public QgsMapToolAdvancedDigitizing, pu QObjectUniquePtr< QgsRubberBand > mRubberBand; }; - -class QgsCreatePictureItemMapTool: public QgsMapToolAdvancedDigitizing, public QgsCreateAnnotationItemMapToolInterface +/** + * \class QgsCreatePictureItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize picture items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreatePictureItemMapTool: public QgsMapToolAdvancedDigitizing, public QgsCreateAnnotationItemMapToolInterface { Q_OBJECT @@ -135,17 +188,18 @@ class QgsCreatePictureItemMapTool: public QgsMapToolAdvancedDigitizing, public Q static inline QgsSettingsTreeNode *sTreePicture = QgsCreateAnnotationItemMapToolInterface::sTreeAnnotationTools->createChildNode( QStringLiteral( "picture-item" ) ); static const QgsSettingsEntryString *settingLastSourceFolder; + //! Constructor QgsCreatePictureItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); void cadCanvasPressEvent( QgsMapMouseEvent *event ) override; void cadCanvasMoveEvent( QgsMapMouseEvent *event ) override; void keyPressEvent( QKeyEvent *event ) override; - QgsCreateAnnotationItemMapToolHandler *handler() override; + QgsCreateAnnotationItemMapToolHandler *handler() const override; QgsMapTool *mapTool() override; private: - + //! Constructor QgsCreateAnnotationItemMapToolHandler *mHandler = nullptr; QRectF mRect; @@ -153,19 +207,25 @@ class QgsCreatePictureItemMapTool: public QgsMapToolAdvancedDigitizing, public Q QObjectUniquePtr< QgsRubberBand > mRubberBand; }; - -class QgsCreateLineTextItemMapTool: public QgsMapToolCaptureAnnotationItem +/** + * \class QgsCreateLineTextItemMapTool + * \ingroup gui + * + * \brief A map tool to digitize line text items. + * + * \since QGIS 3.40 + */ +class GUI_EXPORT QgsCreateLineTextItemMapTool: public QgsMapToolCaptureAnnotationItem { Q_OBJECT public: - + //! Constructor QgsCreateLineTextItemMapTool( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget ); private slots: void lineCaptured( const QgsCurve *line ) override; }; -///@endcond PRIVATE #endif // QGSCREATEANNOTATIONITEMMAPTOOLIMPL_H diff --git a/src/gui/attributetable/qgsattributetablefiltermodel.cpp b/src/gui/attributetable/qgsattributetablefiltermodel.cpp index 4e479356914f..b39914699dcc 100644 --- a/src/gui/attributetable/qgsattributetablefiltermodel.cpp +++ b/src/gui/attributetable/qgsattributetablefiltermodel.cpp @@ -281,7 +281,7 @@ void QgsAttributeTableFilterModel::setSelectedOnTop( bool selectedOnTop ) if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder ) order = Qt::AscendingOrder; - sort( 0, Qt::AscendingOrder ); + sort( column, order ); invalidate(); } } diff --git a/src/gui/labeling/qgslabelinggui.cpp b/src/gui/labeling/qgslabelinggui.cpp index 22ce101b47e3..a210b3527ad1 100644 --- a/src/gui/labeling/qgslabelinggui.cpp +++ b/src/gui/labeling/qgslabelinggui.cpp @@ -40,11 +40,16 @@ QgsExpressionContext QgsLabelingGui::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( mCanvas ) - expContext << QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() ); + { + expContext = mCanvas->createExpressionContext(); + } + else + { + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ); + } if ( mLayer ) expContext << QgsExpressionContextUtils::layerScope( mLayer ); diff --git a/src/gui/labeling/qgsrulebasedlabelingwidget.cpp b/src/gui/labeling/qgsrulebasedlabelingwidget.cpp index 55197d8785ea..0b7f2fe6dd73 100644 --- a/src/gui/labeling/qgsrulebasedlabelingwidget.cpp +++ b/src/gui/labeling/qgsrulebasedlabelingwidget.cpp @@ -33,23 +33,22 @@ const double ICON_PADDING_FACTOR = 0.16; -static QList _globalProjectAtlasMapLayerScopes( QgsMapCanvas *mapCanvas, const QgsMapLayer *layer ) +QgsExpressionContext QgsLabelingRulePropsWidget::createExpressionContext( QgsMapCanvas *mapCanvas, const QgsMapLayer *layer ) { - QList scopes; - scopes << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); + QgsExpressionContext context; if ( mapCanvas ) { - scopes << QgsExpressionContextUtils::mapSettingsScope( mapCanvas->mapSettings() ) - << new QgsExpressionContextScope( mapCanvas->expressionContextScope() ); + context = mapCanvas->createExpressionContext(); } else { - scopes << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + context << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } - scopes << QgsExpressionContextUtils::layerScope( layer ); - return scopes; + context << QgsExpressionContextUtils::layerScope( layer ); + return context; } @@ -739,7 +738,7 @@ void QgsLabelingRulePropsWidget::testFilter() return; } - QgsExpressionContext context( _globalProjectAtlasMapLayerScopes( mMapCanvas, mLayer ) ); + QgsExpressionContext context( createExpressionContext( mMapCanvas, mLayer ) ); if ( !filter.prepare( &context ) ) { @@ -772,7 +771,7 @@ void QgsLabelingRulePropsWidget::testFilter() void QgsLabelingRulePropsWidget::buildExpression() { - const QgsExpressionContext context( _globalProjectAtlasMapLayerScopes( mMapCanvas, mLayer ) ); + const QgsExpressionContext context( createExpressionContext( mMapCanvas, mLayer ) ); QgsExpressionBuilderDialog dlg( mLayer, editFilter->text(), this, QStringLiteral( "generic" ), context ); diff --git a/src/gui/labeling/qgsrulebasedlabelingwidget.h b/src/gui/labeling/qgsrulebasedlabelingwidget.h index 6139db195f65..078d7929f665 100644 --- a/src/gui/labeling/qgsrulebasedlabelingwidget.h +++ b/src/gui/labeling/qgsrulebasedlabelingwidget.h @@ -195,6 +195,8 @@ class GUI_EXPORT QgsLabelingRulePropsWidget : public QgsPanelWidget, private Ui: void buildExpression(); private: + static QgsExpressionContext createExpressionContext( QgsMapCanvas *mapCanvas, const QgsMapLayer *layer ); + QgsRuleBasedLabeling::Rule *mRule; // borrowed QgsVectorLayer *mLayer = nullptr; diff --git a/src/gui/processing/qgsprocessingalgorithmdialogbase.cpp b/src/gui/processing/qgsprocessingalgorithmdialogbase.cpp index 2fdf1ce19147..391b4e443a65 100644 --- a/src/gui/processing/qgsprocessingalgorithmdialogbase.cpp +++ b/src/gui/processing/qgsprocessingalgorithmdialogbase.cpp @@ -796,6 +796,19 @@ QString QgsProcessingAlgorithmDialogBase::formatHelp( QgsProcessingAlgorithm *al } result += QStringLiteral( "
  • %1
" ).arg( flags.join( QLatin1String( "
  • " ) ) ); } + if ( algorithm->flags() & Qgis::ProcessingAlgorithmFlag::SecurityRisk ) + { + result += QStringLiteral( "

    %1

    " ).arg( + tr( "Warning: This algorithm is a potential security risk if executed with unchecked inputs, and may result in system damage or data leaks." ) + ); + } + if ( algorithm->flags() & Qgis::ProcessingAlgorithmFlag::KnownIssues ) + { + result += QStringLiteral( "

    %1

    " ).arg( + tr( "Warning: This algorithm has known issues. The results must be carefully validated by the user." ) + ); + } + return result; } diff --git a/src/gui/providers/sensorthings/qgssensorthingssubseteditor.cpp b/src/gui/providers/sensorthings/qgssensorthingssubseteditor.cpp index 5ddde9550ec3..74abc3c8ceb3 100644 --- a/src/gui/providers/sensorthings/qgssensorthingssubseteditor.cpp +++ b/src/gui/providers/sensorthings/qgssensorthingssubseteditor.cpp @@ -55,6 +55,7 @@ QgsSensorThingsSubsetEditor::QgsSensorThingsSubsetEditor( QgsVectorLayer *layer, boldFont.setBold( true ); mLabelComparisons->setFont( boldFont ); mLabelLogical->setFont( boldFont ); + mLabelDate->setFont( boldFont ); mLabelArithmetic->setFont( boldFont ); mButtonEq->setToolTip( tr( "Equal" ) ); diff --git a/src/gui/qgspropertyoverridebutton.cpp b/src/gui/qgspropertyoverridebutton.cpp index 927780959f42..232a5bda3686 100644 --- a/src/gui/qgspropertyoverridebutton.cpp +++ b/src/gui/qgspropertyoverridebutton.cpp @@ -439,7 +439,7 @@ void QgsPropertyOverrideButton::aboutToShowMenu() QPixmap icon = QgsColorButton::createMenuIcon( color.first, mDefinition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha ); QAction *act = mColorsMenu->addAction( color.second ); act->setIcon( icon ); - if ( mProperty.propertyType() == Qgis::PropertyType::Expression && hasExp && mExpressionString == QStringLiteral( "project_color('%1')" ).arg( color.second ) ) + if ( mProperty.propertyType() == Qgis::PropertyType::Expression && hasExp && getColor() == color.second ) { act->setCheckable( true ); act->setChecked( true ); @@ -643,9 +643,9 @@ void QgsPropertyOverrideButton::menuActionTriggered( QAction *action ) } else if ( mColorsMenu->actions().contains( action ) ) // a color name clicked { - if ( mExpressionString != QStringLiteral( "project_color('%1')" ).arg( action->text() ) ) + if ( getColor() != action->text() ) { - mExpressionString = QStringLiteral( "project_color('%1')" ).arg( action->text() ); + mExpressionString = QStringLiteral( "project_color_object('%1')" ).arg( action->text() ); } mProperty.setExpressionString( mExpressionString ); mProperty.setTransformer( nullptr ); @@ -769,12 +769,11 @@ void QgsPropertyOverrideButton::updateGui() { icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpression.svg" ) ); - const thread_local QRegularExpression rx( QStringLiteral( "^project_color\\('(.*)'\\)$" ) ); - QRegularExpressionMatch match = rx.match( mExpressionString ); - if ( match.hasMatch() ) + const QString colorName = getColor(); + if ( !colorName.isEmpty() ) { icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineColorOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineColor.svg" ) ); - deftip = match.captured( 1 ); + deftip = colorName; deftype = tr( "project color" ); } else @@ -925,11 +924,10 @@ void QgsPropertyOverrideButton::updateSiblingWidgets( bool state ) { if ( state && mProperty.isProjectColor() ) { - const thread_local QRegularExpression rx( QStringLiteral( "^project_color\\('(.*)'\\)$" ) ); - QRegularExpressionMatch match = rx.match( mExpressionString ); - if ( match.hasMatch() ) + const QString colorName = getColor(); + if ( !colorName.isEmpty() ) { - cb->linkToProjectColor( match.captured( 1 ) ); + cb->linkToProjectColor( colorName ); } } else @@ -986,3 +984,10 @@ void QgsPropertyOverrideButton::showHelp() { QgsHelp::openHelp( QStringLiteral( "introduction/general_tools.html#data-defined" ) ); } + +QString QgsPropertyOverrideButton::getColor() const +{ + const thread_local QRegularExpression rx( QStringLiteral( "^project_color(_object|)\\('(.*)'\\)$" ) ); + QRegularExpressionMatch match = rx.match( mExpressionString ); + return match.hasMatch() ? match.captured( 2 ) : QString(); +} diff --git a/src/gui/qgspropertyoverridebutton.h b/src/gui/qgspropertyoverridebutton.h index 30482403d3be..3ef21f18ec32 100644 --- a/src/gui/qgspropertyoverridebutton.h +++ b/src/gui/qgspropertyoverridebutton.h @@ -264,6 +264,8 @@ class GUI_EXPORT QgsPropertyOverrideButton: public QToolButton */ void setActivePrivate( bool active ); + // Returns color name if current expression is a reference to a color + QString getColor() const; int mPropertyKey = -1; diff --git a/src/gui/qgstextformatwidget.cpp b/src/gui/qgstextformatwidget.cpp index 1eb0d1da83ee..f28628003c26 100644 --- a/src/gui/qgstextformatwidget.cpp +++ b/src/gui/qgstextformatwidget.cpp @@ -2176,11 +2176,17 @@ QgsExpressionContext QgsTextFormatWidget::createExpressionContext() const return *lExpressionContext; QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( mMapCanvas ) - expContext << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ); + { + expContext = mMapCanvas->createExpressionContext(); + } + else + { + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + } if ( mLayer ) expContext << QgsExpressionContextUtils::layerScope( mLayer ); diff --git a/src/gui/raster/qgsrasterlayerproperties.cpp b/src/gui/raster/qgsrasterlayerproperties.cpp index bd8f68b75749..d598d3a7cff9 100644 --- a/src/gui/raster/qgsrasterlayerproperties.cpp +++ b/src/gui/raster/qgsrasterlayerproperties.cpp @@ -272,17 +272,20 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer *lyr, QgsMapCanv } ); } - mContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); - if ( mCanvas ) { - mContext << QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() ); - // Initialize with layer center - mContext << QgsExpressionContextUtils::mapLayerPositionScope( mRasterLayer->extent().center() ); + mContext = mCanvas->createExpressionContext(); + } + else + { + mContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } + // Initialize with layer center + mContext << QgsExpressionContextUtils::mapLayerPositionScope( mRasterLayer->extent().center() ); mContext << QgsExpressionContextUtils::layerScope( mRasterLayer ); connect( mInsertExpressionButton, &QAbstractButton::clicked, this, [ = ] diff --git a/src/gui/raster/qgsrastertransparencywidget.cpp b/src/gui/raster/qgsrastertransparencywidget.cpp index 5ab2bd27ebc8..005161c2d6de 100644 --- a/src/gui/raster/qgsrastertransparencywidget.cpp +++ b/src/gui/raster/qgsrastertransparencywidget.cpp @@ -82,22 +82,17 @@ void QgsRasterTransparencyWidget::setContext( const QgsSymbolWidgetContext &cont QgsExpressionContext QgsRasterTransparencyWidget::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( QgsMapCanvas *canvas = mContext.mapCanvas() ) { - expContext << QgsExpressionContextUtils::mapSettingsScope( canvas->mapSettings() ) - << new QgsExpressionContextScope( canvas->expressionContextScope() ); - if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( canvas->temporalController() ) ) - { - expContext << generator->createExpressionContextScope(); - } + expContext = canvas->createExpressionContext(); } else { - expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } if ( mRasterLayer ) diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp index fb1fa29d806a..e01a2e0598c8 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp @@ -1343,22 +1343,16 @@ void QgsCategorizedSymbolRendererWidget::keyPressEvent( QKeyEvent *event ) QgsExpressionContext QgsCategorizedSymbolRendererWidget::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); - if ( auto *lMapCanvas = mContext.mapCanvas() ) { - expContext << QgsExpressionContextUtils::mapSettingsScope( lMapCanvas->mapSettings() ) - << new QgsExpressionContextScope( lMapCanvas->expressionContextScope() ); - if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( lMapCanvas->temporalController() ) ) - { - expContext << generator->createExpressionContextScope(); - } + expContext = lMapCanvas->createExpressionContext(); } else { - expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } if ( auto *lVectorLayer = vectorLayer() ) diff --git a/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp b/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp index 9920085c0e1c..35a8c30d7718 100644 --- a/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp +++ b/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp @@ -190,11 +190,17 @@ void QgsDataDefinedSizeLegendWidget::changeSymbol() context.setMapCanvas( mMapCanvas ); QgsExpressionContext ec; - ec << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( mMapCanvas ) - ec << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ); + { + ec = mMapCanvas->createExpressionContext(); + } + else + { + ec << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + } context.setExpressionContext( &ec ); const QString crsAuthId = mMapCanvas ? mMapCanvas->mapSettings().destinationCrs().authid() : QString(); diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp index 2e4c6966ba15..32d1c320d92a 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp @@ -419,22 +419,17 @@ QgsRendererWidget *QgsGraduatedSymbolRendererWidget::create( QgsVectorLayer *lay QgsExpressionContext QgsGraduatedSymbolRendererWidget::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( auto *lMapCanvas = mContext.mapCanvas() ) { - expContext << QgsExpressionContextUtils::mapSettingsScope( lMapCanvas->mapSettings() ) - << new QgsExpressionContextScope( lMapCanvas->expressionContextScope() ); - if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( lMapCanvas->temporalController() ) ) - { - expContext << generator->createExpressionContextScope(); - } + expContext = lMapCanvas->createExpressionContext(); } else { - expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } if ( auto *lVectorLayer = vectorLayer() ) diff --git a/src/gui/symbology/qgsheatmaprendererwidget.cpp b/src/gui/symbology/qgsheatmaprendererwidget.cpp index bdb1d01676aa..fa5532c5d319 100644 --- a/src/gui/symbology/qgsheatmaprendererwidget.cpp +++ b/src/gui/symbology/qgsheatmaprendererwidget.cpp @@ -34,22 +34,17 @@ QgsRendererWidget *QgsHeatmapRendererWidget::create( QgsVectorLayer *layer, QgsS QgsExpressionContext QgsHeatmapRendererWidget::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( auto *lMapCanvas = mContext.mapCanvas() ) { - expContext << QgsExpressionContextUtils::mapSettingsScope( lMapCanvas->mapSettings() ) - << new QgsExpressionContextScope( lMapCanvas->expressionContextScope() ); - if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( lMapCanvas->temporalController() ) ) - { - expContext << generator->createExpressionContextScope(); - } + expContext = lMapCanvas->createExpressionContext(); } else { - expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } if ( auto *lVectorLayer = vectorLayer() ) diff --git a/src/gui/symbology/qgslayerpropertieswidget.cpp b/src/gui/symbology/qgslayerpropertieswidget.cpp index 72b2654b4d94..749b47e25eae 100644 --- a/src/gui/symbology/qgslayerpropertieswidget.cpp +++ b/src/gui/symbology/qgslayerpropertieswidget.cpp @@ -246,22 +246,16 @@ QgsExpressionContext QgsLayerPropertiesWidget::createExpressionContext() const return *lExpressionContext; QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); - if ( auto *lMapCanvas = mContext.mapCanvas() ) { - expContext << QgsExpressionContextUtils::mapSettingsScope( lMapCanvas->mapSettings() ) - << new QgsExpressionContextScope( lMapCanvas->expressionContextScope() ); - if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( lMapCanvas->temporalController() ) ) - { - expContext << generator->createExpressionContextScope(); - } + expContext = lMapCanvas->createExpressionContext(); } else { - expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } expContext << QgsExpressionContextUtils::layerScope( mVectorLayer ); diff --git a/src/gui/symbology/qgsrendererwidget.cpp b/src/gui/symbology/qgsrendererwidget.cpp index d7bc2c63e602..e252500d1362 100644 --- a/src/gui/symbology/qgsrendererwidget.cpp +++ b/src/gui/symbology/qgsrendererwidget.cpp @@ -467,22 +467,16 @@ QgsSymbolWidgetContext QgsDataDefinedValueDialog::context() const QgsExpressionContext QgsDataDefinedValueDialog::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ); if ( auto *lMapCanvas = mContext.mapCanvas() ) { - expContext << QgsExpressionContextUtils::mapSettingsScope( lMapCanvas->mapSettings() ) - << new QgsExpressionContextScope( lMapCanvas->expressionContextScope() ); - - if ( const QgsExpressionContextScopeGenerator *generator = dynamic_cast< const QgsExpressionContextScopeGenerator * >( lMapCanvas->temporalController() ) ) - { - expContext << generator->createExpressionContextScope(); - } + expContext = lMapCanvas->createExpressionContext(); } else { - expContext << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); } if ( auto *lVectorLayer = vectorLayer() ) diff --git a/src/gui/vector/qgsattributesformproperties.cpp b/src/gui/vector/qgsattributesformproperties.cpp index 8eb641dd3cfc..1e4ccabf814d 100644 --- a/src/gui/vector/qgsattributesformproperties.cpp +++ b/src/gui/vector/qgsattributesformproperties.cpp @@ -616,13 +616,6 @@ void QgsAttributesFormProperties::loadAttributeSpecificEditor( QgsAttributesDnDT if ( layout == Qgis::AttributeFormLayout::DragAndDrop ) storeAttributeWidgetEdit(); - // Do not store while initializing! - if ( !mAvailableWidgetsTree->selectedItems().empty() ) - { - storeAttributeTypeDialog(); - storeAttributeContainerEdit(); - } - clearAttributeTypeFrame(); if ( emitter->selectedItems().count() != 1 ) diff --git a/src/gui/vector/qgsdiagramproperties.cpp b/src/gui/vector/qgsdiagramproperties.cpp index a89a9523fe05..2dc6edb4c65d 100644 --- a/src/gui/vector/qgsdiagramproperties.cpp +++ b/src/gui/vector/qgsdiagramproperties.cpp @@ -49,11 +49,18 @@ QgsExpressionContext QgsDiagramProperties::createExpressionContext() const { QgsExpressionContext expContext; - expContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ) - << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ) - << QgsExpressionContextUtils::layerScope( mLayer ); + if ( mMapCanvas ) + { + expContext = mMapCanvas->createExpressionContext(); + } + else + { + expContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + } + expContext << QgsExpressionContextUtils::layerScope( mLayer ); return expContext; } @@ -1064,12 +1071,7 @@ void QgsDiagramProperties::apply() QString QgsDiagramProperties::showExpressionBuilder( const QString &initialExpression ) { - QgsExpressionContext context; - context << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ) - << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() ) - << QgsExpressionContextUtils::layerScope( mLayer ); + QgsExpressionContext context = createExpressionContext(); QgsExpressionBuilderDialog dlg( mLayer, initialExpression, this, QStringLiteral( "generic" ), context ); dlg.setWindowTitle( tr( "Expression Based Attribute" ) ); diff --git a/src/gui/vector/qgsdiagramwidget.cpp b/src/gui/vector/qgsdiagramwidget.cpp index 4cb0bc72ff03..473852a0b214 100644 --- a/src/gui/vector/qgsdiagramwidget.cpp +++ b/src/gui/vector/qgsdiagramwidget.cpp @@ -48,7 +48,7 @@ QgsDiagramWidget::QgsDiagramWidget( QgsVectorLayer *layer, QgsMapCanvas *canvas, mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "text.svg" ) ), tr( "Text Diagram" ), ModeText ); mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "histogram.svg" ) ), tr( "Histogram" ), ModeHistogram ); mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "stacked-bar.svg" ) ), tr( "Stacked Bars" ), ModeStackedBar ); - mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "diagramNone.svg" ) ), tr( "Stacked Diagram" ), ModeStacked ); + mDiagramTypeComboBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "stacked-diagram.svg" ) ), tr( "Stacked Diagram" ), ModeStacked ); connect( mEngineSettingsButton, &QAbstractButton::clicked, this, &QgsDiagramWidget::showEngineConfigDialog ); diff --git a/src/gui/vector/qgsvectorlayerproperties.cpp b/src/gui/vector/qgsvectorlayerproperties.cpp index ead248999eaa..5bbb4ed4703f 100644 --- a/src/gui/vector/qgsvectorlayerproperties.cpp +++ b/src/gui/vector/qgsvectorlayerproperties.cpp @@ -150,11 +150,18 @@ QgsVectorLayerProperties::QgsVectorLayerProperties( connect( this, &QDialog::accepted, this, &QgsVectorLayerProperties::apply ); connect( this, &QDialog::rejected, this, &QgsVectorLayerProperties::rollback ); - mContext << QgsExpressionContextUtils::globalScope() - << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) - << QgsExpressionContextUtils::atlasScope( nullptr ) - << QgsExpressionContextUtils::mapSettingsScope( mCanvas->mapSettings() ) - << QgsExpressionContextUtils::layerScope( mLayer ); + if ( mCanvas ) + { + mContext = mCanvas->createExpressionContext(); + } + else + { + mContext << QgsExpressionContextUtils::globalScope() + << QgsExpressionContextUtils::projectScope( QgsProject::instance() ) + << QgsExpressionContextUtils::atlasScope( nullptr ) + << QgsExpressionContextUtils::mapSettingsScope( QgsMapSettings() ); + } + mContext << QgsExpressionContextUtils::layerScope( mLayer ); mMapTipFieldComboBox->setLayer( lyr ); mDisplayExpressionWidget->setLayer( lyr ); diff --git a/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp b/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp index b490b7fcef0d..3dbc4ae80c19 100644 --- a/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp +++ b/src/providers/virtual/qgsvirtuallayersqlitemodule.cpp @@ -831,7 +831,8 @@ void qgisFunctionWrapper( sqlite3_context *ctxt, int nArgs, sqlite3_value **args sqlite3_result_text( ctxt, ba.constData(), ba.size(), SQLITE_TRANSIENT ); break; } - case QMetaType::Type::User: + + default: { if ( ret.userType() == qMetaTypeId< QgsGeometry>() ) { @@ -844,21 +845,21 @@ void qgisFunctionWrapper( sqlite3_context *ctxt, int nArgs, sqlite3_value **args { sqlite3_result_double( ctxt, ret.value().seconds() ); } + else + { + QBuffer buffer; + buffer.open( QBuffer::ReadWrite ); + QDataStream ds( &buffer ); + // something different from 0 (to distinguish from the first byte of a geometry blob) + char type = 1; + buffer.write( &type, 1 ); + // then the serialized version of the variant + ds << ret; + buffer.close(); + sqlite3_result_blob( ctxt, buffer.buffer().constData(), buffer.buffer().size(), SQLITE_TRANSIENT ); + } break; } - default: - { - QBuffer buffer; - buffer.open( QBuffer::ReadWrite ); - QDataStream ds( &buffer ); - // something different from 0 (to distinguish from the first byte of a geometry blob) - char type = 1; - buffer.write( &type, 1 ); - // then the serialized version of the variant - ds << ret; - buffer.close(); - sqlite3_result_blob( ctxt, buffer.buffer().constData(), buffer.buffer().size(), SQLITE_TRANSIENT ); - } }; } diff --git a/src/ui/layout/qgslayoutdesignerbase.ui b/src/ui/layout/qgslayoutdesignerbase.ui index f8dbcfb31932..c2e095a1bad4 100644 --- a/src/ui/layout/qgslayoutdesignerbase.ui +++ b/src/ui/layout/qgslayoutdesignerbase.ui @@ -182,7 +182,7 @@ 0 0 2180 - 22 + 32 @@ -204,6 +204,7 @@ + @@ -1585,9 +1586,15 @@ &Keyboard Shortcuts... + + + Page Properties… + + + diff --git a/src/ui/mesh/qgsmeshelevationpropertieswidgetbase.ui b/src/ui/mesh/qgsmeshelevationpropertieswidgetbase.ui index f45fbedce54f..ad47e29a21a2 100644 --- a/src/ui/mesh/qgsmeshelevationpropertieswidgetbase.ui +++ b/src/ui/mesh/qgsmeshelevationpropertieswidgetbase.ui @@ -11,7 +11,7 @@ - Raster Elevation Properties + Mesh Elevation Properties @@ -27,7 +27,7 @@ 0 - + Configuration @@ -37,7 +37,7 @@ - + Profile Chart Appearance @@ -46,7 +46,7 @@ - + Style @@ -64,7 +64,7 @@ 0 - + 0 @@ -78,7 +78,7 @@ 0 - + Line style @@ -114,14 +114,14 @@ 0 - + Limit - + Fill style @@ -196,14 +196,14 @@ - + Scale - + 0 @@ -232,7 +232,7 @@ - + Offset @@ -268,7 +268,7 @@ - + Lower @@ -278,7 +278,7 @@ - + Upper @@ -318,7 +318,7 @@ - + 0 @@ -405,6 +405,12 @@ QDoubleSpinBox
    qgsdoublespinbox.h
    + + QgsCollapsibleGroupBox + QGroupBox +
    qgscollapsiblegroupbox.h
    + 1 +
    QgsSymbolButton QToolButton diff --git a/src/ui/qgssensorthingssubseteditorbase.ui b/src/ui/qgssensorthingssubseteditorbase.ui index 2c1987ea7995..1c93e853b62b 100644 --- a/src/ui/qgssensorthingssubseteditorbase.ui +++ b/src/ui/qgssensorthingssubseteditorbase.ui @@ -131,7 +131,7 @@ p, li { white-space: pre-wrap; }
    - + Date @@ -235,6 +235,19 @@ p, li { white-space: pre-wrap; } + + + + Qt::Vertical + + + + 20 + 0 + + + +
    @@ -248,6 +261,25 @@ p, li { white-space: pre-wrap; } 1 + + lstFields + groupBox4 + mButtonEq + mButtonNe + mButtonGt + mButtonGe + mButtonLt + mButtonLe + mButtonAnd + mButtonOr + mButtonNot + mButtonNow + mButtonAdd + mButtonSub + mButtonMul + mButtonDiv + mButtonMod + diff --git a/tests/src/3d/testqgs3drendering.cpp b/tests/src/3d/testqgs3drendering.cpp index 9d2d2529c8fa..e9a6013cc8a4 100644 --- a/tests/src/3d/testqgs3drendering.cpp +++ b/tests/src/3d/testqgs3drendering.cpp @@ -52,6 +52,7 @@ #include "qgsdirectionallightsettings.h" #include "qgsmetalroughmaterialsettings.h" #include "qgspointlightsettings.h" +#include "qgsphongtexturedmaterialsettings.h" #include #include @@ -76,6 +77,7 @@ class TestQgs3DRendering : public QgsTest void testEpsg4978LineRendering(); void testExtrudedPolygons(); void testPhongShading(); + void testExtrudedPolygonsTexturedPhong(); void testExtrudedPolygonsDataDefinedPhong(); void testExtrudedPolygonsDataDefinedGooch(); void testExtrudedPolygonsGoochShading(); @@ -492,6 +494,59 @@ void TestQgs3DRendering::testPhongShading() QGSVERIFYIMAGECHECK( "phong_shading", "phong_shading", img, QString(), 40, QSize( 0, 0 ), 2 ); } +void TestQgs3DRendering::testExtrudedPolygonsTexturedPhong() +{ + // In Qt 5, this test does not work on CI +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if ( QgsTest::isCIRun() ) + { + QSKIP( "fails on CI" ); + } +#endif + + QgsPhongTexturedMaterialSettings materialSettings; + materialSettings.setAmbient( QColor( 26, 26, 26 ) ); + materialSettings.setSpecular( QColor( 10, 10, 10 ) ); + materialSettings.setShininess( 1.0 ); + materialSettings.setDiffuseTexturePath( testDataPath( "/sample_image.png" ) ); + QgsPolygon3DSymbol *symbol3d = new QgsPolygon3DSymbol; + symbol3d->setMaterialSettings( materialSettings.clone() ); + symbol3d->setExtrusionHeight( 10.f ); + QgsVectorLayer3DRenderer *renderer3d = new QgsVectorLayer3DRenderer( symbol3d ); + mLayerBuildings->setRenderer3D( renderer3d ); + + const QgsRectangle fullExtent = mLayerDtm->extent(); + + Qgs3DMapSettings *map = new Qgs3DMapSettings; + map->setCrs( mProject->crs() ); + map->setExtent( fullExtent ); + map->setLayers( QList() << mLayerBuildings << mLayerRgb ); + QgsPointLightSettings defaultLight; + defaultLight.setIntensity( 1.0 ); + defaultLight.setPosition( QgsVector3D( 0, 1000, 0 ) ); + map->setLightSources( { defaultLight.clone() } ); + + QgsFlatTerrainGenerator *flatTerrain = new QgsFlatTerrainGenerator; + flatTerrain->setCrs( map->crs() ); + map->setTerrainGenerator( flatTerrain ); + + QgsOffscreen3DEngine engine; + Qgs3DMapScene *scene = new Qgs3DMapScene( *map, &engine ); + engine.setRootEntity( scene ); + + scene->cameraController()->setLookingAtPoint( QgsVector3D( -60, 10, 360 ), 100, 45, 0 ); + + // When running the test on Travis, it would initially return empty rendered image. + // Capturing the initial image and throwing it away fixes that. Hopefully we will + // find a better fix in the future. + Qgs3DUtils::captureSceneImage( engine, scene ); + QImage img = Qgs3DUtils::captureSceneImage( engine, scene ); + + delete scene; + delete map; + QGSVERIFYIMAGECHECK( "polygon3d_extrusion_textured_phong", "polygon3d_extrusion_textured_phong", img, QString(), 40, QSize( 0, 0 ), 2 ); +} + void TestQgs3DRendering::testExtrudedPolygonsDataDefinedPhong() { QgsPropertyCollection propertyColection; diff --git a/tests/src/analysis/testqgsprocessingmodelalgorithm.cpp b/tests/src/analysis/testqgsprocessingmodelalgorithm.cpp index cd4fd760af22..e6acd88e8919 100644 --- a/tests/src/analysis/testqgsprocessingmodelalgorithm.cpp +++ b/tests/src/analysis/testqgsprocessingmodelalgorithm.cpp @@ -51,6 +51,28 @@ class DummyAlgorithm2 : public QgsProcessingAlgorithm }; + +class DummySecurityRiskAlgorithm : public QgsProcessingAlgorithm +{ + public: + + DummySecurityRiskAlgorithm( const QString &name ) : mName( name ) { } + + void initAlgorithm( const QVariantMap & = QVariantMap() ) override + { + addParameter( new QgsProcessingParameterVectorDestination( QStringLiteral( "vector_dest" ) ) ); + } + QString name() const override { return mName; } + QString displayName() const override { return mName; } + QVariantMap processAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * ) override { return QVariantMap(); } + + Qgis::ProcessingAlgorithmFlags flags() const override { return QgsProcessingAlgorithm::flags() | Qgis::ProcessingAlgorithmFlag::SecurityRisk; } + DummySecurityRiskAlgorithm *createInstance() const override { return new DummySecurityRiskAlgorithm( name() ); } + + QString mName; + +}; + class DummyRaiseExceptionAlgorithm : public QgsProcessingAlgorithm { public: @@ -116,6 +138,7 @@ class DummyProvider4 : public QgsProcessingProvider // clazy:exclude=missing-qob { QVERIFY( addAlgorithm( new DummyAlgorithm2( QStringLiteral( "alg1" ) ) ) ); QVERIFY( addAlgorithm( new DummyRaiseExceptionAlgorithm( QStringLiteral( "raise" ) ) ) ); + QVERIFY( addAlgorithm( new DummySecurityRiskAlgorithm( QStringLiteral( "risky" ) ) ) ); } }; @@ -155,6 +178,7 @@ class TestQgsProcessingModelAlgorithm: public QgsTest void renameModelParameter(); void internalVersion(); void modelChildOrderWithVariables(); + void flags(); private: @@ -2744,5 +2768,26 @@ void TestQgsProcessingModelAlgorithm::modelChildOrderWithVariables() QVERIFY( model.dependsOnChildAlgorithms( QStringLiteral( "c2" ) ).contains( QStringLiteral( "c3" ) ) ); } +void TestQgsProcessingModelAlgorithm::flags() +{ + QgsProcessingModelAlgorithm model( "test", "testGroup" ); + + const QgsProcessingModelParameter stringParam( "a_parameter" ); + model.addModelParameter( new QgsProcessingParameterString( "a_parameter" ), stringParam ); + + QgsProcessingModelChildAlgorithm c1; + c1.setChildId( QStringLiteral( "c1" ) ); + c1.setAlgorithmId( QStringLiteral( "native:stringconcatenation" ) ); + model.addChildAlgorithm( c1 ); + QVERIFY( !model.flags().testFlag( Qgis::ProcessingAlgorithmFlag::SecurityRisk ) ); + + // add algorithm with security risk + QgsProcessingModelChildAlgorithm c2; + c2.setChildId( QStringLiteral( "c2" ) ); + c2.setAlgorithmId( QStringLiteral( "dummy4:risky" ) ); + model.addChildAlgorithm( c2 ); + QVERIFY( model.flags().testFlag( Qgis::ProcessingAlgorithmFlag::SecurityRisk ) ); +} + QGSTEST_MAIN( TestQgsProcessingModelAlgorithm ) #include "testqgsprocessingmodelalgorithm.moc" diff --git a/tests/src/app/testqgsattributetable.cpp b/tests/src/app/testqgsattributetable.cpp index b595a42fb788..b7f1095bb49f 100644 --- a/tests/src/app/testqgsattributetable.cpp +++ b/tests/src/app/testqgsattributetable.cpp @@ -398,6 +398,19 @@ void TestQgsAttributeTable::testSelectedOnTop() QCOMPARE( dlg->mMainView->mFilterModel->index( 1, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 1 ) ); QCOMPARE( dlg->mMainView->mFilterModel->index( 2, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 2 ) ); + dlg->mMainView->setSelectedOnTop( false ); + dlg->mMainView->tableView()->sortByColumn( 1, Qt::DescendingOrder ); + + QCOMPARE( dlg->mMainView->mFilterModel->index( 0, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 3 ) ); + QCOMPARE( dlg->mMainView->mFilterModel->index( 1, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 1 ) ); + QCOMPARE( dlg->mMainView->mFilterModel->index( 2, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 2 ) ); + + tempLayer->selectByIds( QgsFeatureIds() << 2 ); + dlg->mMainView->setSelectedOnTop( true ); + + QCOMPARE( dlg->mMainView->mFilterModel->index( 0, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 2 ) ); + QCOMPARE( dlg->mMainView->mFilterModel->index( 1, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 3 ) ); + QCOMPARE( dlg->mMainView->mFilterModel->index( 2, 0 ).data( static_cast< int >( QgsAttributeTableModel::CustomRole::FeatureId ) ), QVariant( 1 ) ); } void TestQgsAttributeTable::testSortByDisplayExpression() diff --git a/tests/src/app/testqgsvertextool.cpp b/tests/src/app/testqgsvertextool.cpp index cd3a2cfbfabe..dfaa08146f3e 100644 --- a/tests/src/app/testqgsvertextool.cpp +++ b/tests/src/app/testqgsvertextool.cpp @@ -87,6 +87,7 @@ class TestQgsVertexTool : public QObject void testAddVertexTopo(); void testMoveEdgeTopo(); void testAddVertexTopoFirstSegment(); + void testAddVertexTopoMultipleLayers(); void testAvoidIntersectionsWithMultiPolygons(); void testActiveLayerPriority(); void testSelectedFeaturesPriority(); @@ -1182,6 +1183,63 @@ void TestQgsVertexTool::testAddVertexTopoFirstSegment() QgsProject::instance()->setTopologicalEditing( false ); } +void TestQgsVertexTool::testAddVertexTopoMultipleLayers() +{ + // check that when adding a vertex to a segment which is shared by more than one layer + // a topological point is added to all editable layers + + QgsFeature fTmp; + fTmp.setGeometry( QgsGeometry::fromWkt( "POLYGON((1 8, 0 8, 0 5, 1 5, 1 8))" ) ); + const bool resAdd = mLayerPolygon->addFeature( fTmp ); + QVERIFY( resAdd ); + const QgsFeatureId fTmpId = fTmp.id(); + + const bool topologicalEditing = QgsProject::instance()->topologicalEditing(); + QgsProject::instance()->setTopologicalEditing( true ); + QgsSnappingConfig cfg = mCanvas->snappingUtils()->config(); + cfg.setMode( Qgis::SnappingMode::AllLayers ); + cfg.setTolerance( 10 ); + cfg.setTypeFlag( static_cast( Qgis::SnappingType::Vertex | Qgis::SnappingType::Segment ) ); + cfg.setEnabled( true ); + mCanvas->snappingUtils()->setConfig( cfg ); + + QCOMPARE( mLayerPolygon->undoStack()->index(), 2 ); + QCOMPARE( mLayerLine->undoStack()->index(), 1 ); + QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 1 ); + + mouseClick( 1, 3, Qt::LeftButton, Qt::KeyboardModifiers(), true ); + mouseClick( 1, 6, Qt::LeftButton, Qt::KeyboardModifiers(), true ); + + QCOMPARE( mLayerPolygon->undoStack()->index(), 3 ); + QCOMPARE( mLayerLine->undoStack()->index(), 2 ); + QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 2 ); + + QCOMPARE( mLayerPolygon->getFeature( fTmpId ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1 8, 0 8, 0 5, 1 5, 1 6, 1 8))" ) ); + QCOMPARE( mLayerLine->getFeature( mFidLineF1 ).geometry().asWkt( 2 ), QStringLiteral( "LineString (2 1, 1 1, 1 6)" ) ); + QCOMPARE( mLayerMultiPolygon->getFeature( mFidMultiPolygonF1 ).geometry().asWkt( 2 ), QStringLiteral( "MultiPolygon (((1 5, 2 5, 2 6.5, 2 8, 1 8, 1 6.5, 1 6, 1 5),(1.25 5.5, 1.25 6, 1.75 6, 1.75 5.5, 1.25 5.5),(1.25 7, 1.75 7, 1.75 7.5, 1.25 7.5, 1.25 7)),((3 5, 3 6.5, 3 8, 4 8, 4 6.5, 4 5, 3 5),(3.25 5.5, 3.75 5.5, 3.75 6, 3.25 6, 3.25 5.5),(3.25 7, 3.75 7, 3.75 7.5, 3.25 7.5, 3.25 7)))" ) ); + + mLayerPolygon->undoStack()->undo(); + mLayerLine->undoStack()->undo(); + mLayerMultiPolygon->undoStack()->undo(); + + QCOMPARE( mLayerPolygon->undoStack()->index(), 2 ); + QCOMPARE( mLayerLine->undoStack()->index(), 1 ); + QCOMPARE( mLayerMultiPolygon->undoStack()->index(), 1 ); + + QCOMPARE( mLayerPolygon->getFeature( fTmpId ).geometry().asWkt( 2 ), QStringLiteral( "Polygon ((1 8, 0 8, 0 5, 1 5, 1 8))" ) ); + QCOMPARE( mLayerLine->getFeature( mFidLineF1 ).geometry().asWkt( 2 ), QStringLiteral( "LineString (2 1, 1 1, 1 3)" ) ); + QCOMPARE( mLayerMultiPolygon->getFeature( mFidMultiPolygonF1 ).geometry().asWkt( 2 ), QStringLiteral( "MultiPolygon (((1 5, 2 5, 2 6.5, 2 8, 1 8, 1 6.5, 1 5),(1.25 5.5, 1.25 6, 1.75 6, 1.75 5.5, 1.25 5.5),(1.25 7, 1.75 7, 1.75 7.5, 1.25 7.5, 1.25 7)),((3 5, 3 6.5, 3 8, 4 8, 4 6.5, 4 5, 3 5),(3.25 5.5, 3.75 5.5, 3.75 6, 3.25 6, 3.25 5.5),(3.25 7, 3.75 7, 3.75 7.5, 3.25 7.5, 3.25 7)))" ) ); + + // undo to remove temp feature + mLayerPolygon->undoStack()->undo(); + + QCOMPARE( mLayerPolygon->undoStack()->index(), 1 ); + + QgsProject::instance()->setTopologicalEditing( topologicalEditing ); + cfg.setEnabled( false ); + mCanvas->snappingUtils()->setConfig( cfg ); +} + void TestQgsVertexTool::testAvoidIntersections() { // There is one feature in the layer diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index a31965615688..641e592c58f8 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -1888,6 +1888,9 @@ class TestQgsExpression: public QObject // Color functions QTest::newRow( "ramp color" ) << "ramp_color('Spectral',0.3)" << false << QVariant( "253,190,116,255" ); + QTest::newRow( "ramp color error" ) << "ramp_color('NotExistingRamp',0.3)" << true << QVariant(); + QTest::newRow( "ramp color object" ) << "ramp_color_object('Spectral',0.3)" << false << QVariant( QColor::fromRgbF( 0.994, 0.746, 0.454 ) ); + QTest::newRow( "ramp color object error" ) << "ramp_color_object('NotExistingRamp',0.3)" << true << QVariant(); QTest::newRow( "create ramp color, wrong parameter" ) << "create_ramp(1)" << true << QVariant(); QTest::newRow( "create ramp color, no color" ) << "create_ramp(map())" << true << QVariant(); QTest::newRow( "create ramp color, one color" ) << "ramp_color(create_ramp(map(0,'0,0,0')),0.5)" << false << QVariant( "0,0,0,255" ); diff --git a/tests/src/core/testqgsexpressioncontext.cpp b/tests/src/core/testqgsexpressioncontext.cpp index 9191c3190554..cfa86b5ba944 100644 --- a/tests/src/core/testqgsexpressioncontext.cpp +++ b/tests/src/core/testqgsexpressioncontext.cpp @@ -812,6 +812,7 @@ void TestQgsExpressionContext::projectScope() QgsNamedColorList colorList; colorList << qMakePair( QColor( 200, 255, 0 ), QStringLiteral( "vomit yellow" ) ); colorList << qMakePair( QColor( 30, 60, 20 ), QStringLiteral( "murky depths of hades" ) ); + colorList << qMakePair( QColor::fromCmykF( 1., 0.9, 0.8, 0.7 ), QStringLiteral( "cmyk colors" ) ); s.setColors( colorList ); QgsExpressionContext contextColors; contextColors << QgsExpressionContextUtils::projectScope( QgsProject::instance() ); @@ -823,6 +824,16 @@ void TestQgsExpressionContext::projectScope() QCOMPARE( expProjectColorCaseInsensitive.evaluate( &contextColors ).toString(), QString( "30,60,20" ) ); QgsExpression badProjectColor( QStringLiteral( "project_color('dusk falls in san juan del sur')" ) ); QCOMPARE( badProjectColor.evaluate( &contextColors ), QVariant() ); + + QgsExpression expProjectColorObject( QStringLiteral( "project_color_object('murky depths of hades')" ) ); + QCOMPARE( expProjectColorObject.evaluate( &contextColors ), QVariant( QColor::fromRgb( 30, 60, 20 ) ) ); + //matching color names should be case insensitive + QgsExpression expProjectColorObjectCaseInsensitive( QStringLiteral( "project_color_object('Murky Depths of hades')" ) ); + QCOMPARE( expProjectColorObjectCaseInsensitive.evaluate( &contextColors ), QVariant( QColor::fromRgb( 30, 60, 20 ) ) ); + QgsExpression expProjectColorCmyk( QStringLiteral( "project_color_object('cmyk colors')" ) ); + QCOMPARE( expProjectColorCmyk.evaluate( &contextColors ), QVariant( QColor::fromCmykF( 1., 0.9, 0.8, 0.7 ) ) ); + QgsExpression badProjectColorObject( QStringLiteral( "project_color_object('dusk falls in san juan del sur')" ) ); + QCOMPARE( badProjectColorObject.evaluate( &contextColors ), QVariant() ); } void TestQgsExpressionContext::layerScope() diff --git a/tests/src/core/testqgslayertree.cpp b/tests/src/core/testqgslayertree.cpp index 35a7c2dfc14f..ef380b7b433a 100644 --- a/tests/src/core/testqgslayertree.cpp +++ b/tests/src/core/testqgslayertree.cpp @@ -973,18 +973,19 @@ void TestQgsLayerTree::testRasterSymbolNode() const std::unique_ptr< QgsLayerTreeLayer > n = std::make_unique< QgsLayerTreeLayer >( rl.get() ); // not checkable - QgsRasterSymbolLegendNode rasterNode( n.get(), QColor( 255, 0, 0 ), QStringLiteral( "my node" ), nullptr, false, QStringLiteral( "key" ) ); + QgsRasterSymbolLegendNode rasterNode( n.get(), QColor( 255, 0, 0 ), QStringLiteral( "my node" ), nullptr, false, QStringLiteral( "key" ), QStringLiteral( "parentKey" ) ); QVERIFY( !rasterNode.isCheckable() ); QCOMPARE( rasterNode.ruleKey(), QStringLiteral( "key" ) ); QCOMPARE( static_cast< int >( rasterNode.flags() ), static_cast< int >( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) ); QCOMPARE( rasterNode.data( Qt::DisplayRole ).toString(), QStringLiteral( "my node" ) ); QCOMPARE( rasterNode.data( static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::NodeType ) ).toInt(), static_cast< int >( QgsLayerTreeModelLegendNode::RasterSymbolLegend ) ); QCOMPARE( rasterNode.data( static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::RuleKey ) ).toString(), QStringLiteral( "key" ) ); + QCOMPARE( rasterNode.data( static_cast< int >( QgsLayerTreeModelLegendNode::CustomRole::ParentRuleKey ) ).toString(), QStringLiteral( "parentKey" ) ); QCOMPARE( rasterNode.data( Qt::CheckStateRole ), QVariant() ); QVERIFY( !rasterNode.setData( true, Qt::CheckStateRole ) ); // checkable - const QgsRasterSymbolLegendNode rasterNode2( n.get(), QColor( 255, 0, 0 ), QStringLiteral( "my node" ), nullptr, true, QStringLiteral( "key" ) ); + const QgsRasterSymbolLegendNode rasterNode2( n.get(), QColor( 255, 0, 0 ), QStringLiteral( "my node" ), nullptr, true, QStringLiteral( "key" ), QStringLiteral( "parentKey" ) ); QVERIFY( rasterNode2.isCheckable() ); QCOMPARE( static_cast< int >( rasterNode2.flags() ), static_cast< int >( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable ) ); } diff --git a/tests/src/core/testqgslegendrenderer.cpp b/tests/src/core/testqgslegendrenderer.cpp index 5adcd2196fbf..3579a6b134a6 100644 --- a/tests/src/core/testqgslegendrenderer.cpp +++ b/tests/src/core/testqgslegendrenderer.cpp @@ -50,7 +50,7 @@ #include "qgsmarkersymbol.h" #include "qgsfillsymbol.h" #include "qgsheatmaprenderer.h" - +#include "qgsmeshlayer.h" class TestRasterRenderer : public QgsPalettedRasterRenderer { public: @@ -135,6 +135,7 @@ class TestQgsLegendRenderer : public QgsTest void testFilterByExpression(); void testFilterByExpressionWithContext(); void testDiagramAttributeLegend(); + void testDiagramMeshLegend(); void testDiagramSizeLegend(); void testDataDefinedSizeCollapsed(); void testDataDefinedSizeSeparated(); @@ -161,9 +162,9 @@ class TestQgsLegendRenderer : public QgsTest QgsRasterLayer *mRL = nullptr; bool _testLegendColumns( int itemCount, int columnCount, const QString &testName, double symbolSpacing ); - bool _verifyImage( const QImage &image, const QString &testName, int diff = 30 ) + bool _verifyImage( const QImage &image, const QString &testName, int diff = 30, const QSize &sizeTolerance = QSize( 6, 10 ) ) { - return QGSIMAGECHECK( testName, testName, image, QString(), diff, QSize( 6, 10 ) ); + return QGSIMAGECHECK( testName, testName, image, QString(), diff, sizeTolerance ); } static void setStandardTestFont( QgsLegendSettings &settings, const QString &style = QStringLiteral( "Roman" ) ) @@ -1450,6 +1451,79 @@ void TestQgsLegendRenderer::testDiagramAttributeLegend() QgsProject::instance()->removeMapLayer( vl4 ); } +void TestQgsLegendRenderer::testDiagramMeshLegend() +{ + const QString uri_1( QString( TEST_DATA_DIR ) + QStringLiteral( "/mesh/mesh_z_ws_d_vel.nc" ) ); //mesh with dataset group "Bed Elevation", "Water Level", "Depth" and "Velocity" + + QTemporaryDir tempDir; + const QString uri( tempDir.filePath( QStringLiteral( "mesh.nc" ) ) ); + + QFile::copy( uri_1, uri ); + QgsMeshLayer *layer = new QgsMeshLayer( uri, QStringLiteral( "mesh" ), QStringLiteral( "mdal" ) ); + QVERIFY( layer->isValid() ); + QCOMPARE( layer->datasetGroupCount(), 4 ); + + QgsProject::instance()->addMapLayer( layer ); + + int scalarIndex = 0; + int vectorIndex = -1; + + QgsMeshRendererSettings rendererSettings = layer->rendererSettings(); + rendererSettings.setActiveScalarDatasetGroup( scalarIndex ); + rendererSettings.setActiveVectorDatasetGroup( vectorIndex ); + layer->setRendererSettings( rendererSettings ); + + std::unique_ptr< QgsLayerTree > root( std::make_unique() ); + root->addLayer( layer ); + std::unique_ptr legendModel( std::make_unique( root.get() ) ); + + QgsLegendSettings settings; + + setStandardTestFont( settings ); + QImage res = renderLegend( legendModel.get(), settings ); + + QVERIFY( _verifyImage( res, QStringLiteral( "legend_mesh_diagram_no_vector" ), 30, QSize( 8, 12 ) ) ); + + //red vector + QgsMeshLayer *layer2 = layer->clone(); + QgsProject::instance()->removeMapLayer( layer ); + QgsProject::instance()->addMapLayer( layer2 ); + + vectorIndex = 2; + rendererSettings.setActiveVectorDatasetGroup( vectorIndex ); + QgsMeshRendererVectorSettings vectorSettings = rendererSettings.vectorSettings( vectorIndex ); + vectorSettings.setColor( Qt::red ); + rendererSettings.setVectorSettings( vectorIndex, vectorSettings ); + layer2->setRendererSettings( rendererSettings ); + + root = std::make_unique(); + root->addLayer( layer2 ); + legendModel = std::make_unique( root.get() ); + + res = renderLegend( legendModel.get(), settings ); + QVERIFY( _verifyImage( res, QStringLiteral( "legend_mesh_diagram_red_vector" ), 30, QSize( 8, 13 ) ) ); + + //color ramp vector + QgsMeshLayer *layer3 = layer2->clone(); + QgsProject::instance()->removeMapLayer( layer2 ); + QgsProject::instance()->addMapLayer( layer3 ); + + const QgsColorRampShader fcn = rendererSettings.scalarSettings( vectorIndex ).colorRampShader(); + vectorSettings.setColorRampShader( fcn ); + vectorSettings.setColoringMethod( QgsInterpolatedLineColor::ColorRamp ); + rendererSettings.setVectorSettings( vectorIndex, vectorSettings ); + layer3->setRendererSettings( rendererSettings ); + + root = std::make_unique(); + root->addLayer( layer3 ); + legendModel = std::make_unique( root.get() ); + + res = renderLegend( legendModel.get(), settings ); + QVERIFY( _verifyImage( res, QStringLiteral( "legend_mesh_diagram_color_ramp_vector" ), 30, QSize( 8, 19 ) ) ); + + QgsProject::instance()->removeMapLayer( layer3 ); +} + void TestQgsLegendRenderer::testDiagramSizeLegend() { QgsVectorLayer *vl4 = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "Point Layer" ), QStringLiteral( "memory" ) ); diff --git a/tests/src/core/testqgsproperty.cpp b/tests/src/core/testqgsproperty.cpp index 8f6c531a8e0f..1aec57aa930b 100644 --- a/tests/src/core/testqgsproperty.cpp +++ b/tests/src/core/testqgsproperty.cpp @@ -1946,6 +1946,10 @@ void TestQgsProperty::isProjectColor() QVERIFY( p.isProjectColor() ); p = QgsProperty::fromExpression( QStringLiteral( "project_color('burnt pineapple Skin 76')" ), true ); QVERIFY( p.isProjectColor() ); + p = QgsProperty::fromExpression( QStringLiteral( "project_color_object('mine')" ), true ); + QVERIFY( p.isProjectColor() ); + p = QgsProperty::fromExpression( QStringLiteral( "project_color_object('burnt pineapple Skin 76')" ), true ); + QVERIFY( p.isProjectColor() ); p.setActive( false ); QVERIFY( p.isProjectColor() ); } diff --git a/tests/src/python/test_provider_virtual.py b/tests/src/python/test_provider_virtual.py index ad0f6b40f0fd..e19eb4aec134 100644 --- a/tests/src/python/test_provider_virtual.py +++ b/tests/src/python/test_provider_virtual.py @@ -12,7 +12,7 @@ import os import tempfile -from qgis.PyQt.QtCore import QTemporaryDir, QUrl, QVariant +from qgis.PyQt.QtCore import QTemporaryDir, QUrl, QVariant, QMetaType from qgis.core import ( Qgis, QgsFeature, @@ -680,6 +680,19 @@ def test_sql3b(self): self.assertTrue(l4.isValid()) self.assertEqual(l4.dataProvider().wkbType(), QgsWkbTypes.Type.Point) + def test_select_qgis_expression_value_types(self): + query = toPercent("SELECT geom_from_wkt( 'POINT(4 5)' ) as geom, make_interval(1) as years") + l4 = QgsVectorLayer(f"?query={query}&geometry=geom", "tt", "virtual", QgsVectorLayer.LayerOptions(False)) + self.assertTrue(l4.isValid()) + self.assertEqual(l4.dataProvider().wkbType(), QgsWkbTypes.Type.Point) + self.assertEqual([f.name() for f in l4.dataProvider().fields()], ['years']) + self.assertEqual([f.type() for f in l4.dataProvider().fields()], + [QMetaType.Type.Double]) + self.assertEqual([f.attributes() for f in l4.getFeatures()], + [[31557600.0]]) + self.assertEqual([f.geometry().asWkt() for f in l4.getFeatures()], + ['Point (4 5)']) + def test_sql4(self): l2 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr", QgsVectorLayer.LayerOptions(False)) diff --git a/tests/src/python/test_qgscolorramplegendnode.py b/tests/src/python/test_qgscolorramplegendnode.py index b5fef7a89a48..e098032eaaf2 100644 --- a/tests/src/python/test_qgscolorramplegendnode.py +++ b/tests/src/python/test_qgscolorramplegendnode.py @@ -129,10 +129,12 @@ def test_basic(self): layer = QgsVectorLayer('dummy', 'test', 'memory') layer_tree_layer = QgsLayerTreeLayer(layer) - node = QgsColorRampLegendNode(layer_tree_layer, r, 'min_label', 'max_label') + node = QgsColorRampLegendNode(layer_tree_layer, r, 'min_label', 'max_label', None, 'key', 'parentKey') self.assertEqual(node.ramp().color1().name(), '#c80000') self.assertEqual(node.ramp().color2().name(), '#00c800') + self.assertEqual(node.data(QgsLayerTreeModelLegendNode.LegendNodeRoles.RuleKeyRole), 'key') + self.assertEqual(node.data(QgsLayerTreeModelLegendNode.LegendNodeRoles.ParentRuleKeyRole), 'parentKey') node.setIconSize(QSize(11, 12)) self.assertEqual(node.iconSize(), QSize(11, 12)) diff --git a/tests/src/python/test_qgslayoutlegend.py b/tests/src/python/test_qgslayoutlegend.py index 1ab07f27c2a6..953fa8742b05 100644 --- a/tests/src/python/test_qgslayoutlegend.py +++ b/tests/src/python/test_qgslayoutlegend.py @@ -1098,6 +1098,19 @@ def testReferencePoint(self): ) ) + # re-render with filtering to trigger mapHitTest which ends up by calling adjustBoxSize(). + # These last change the box size and therefore position (because our reference point is lower left) + # So check that the legend position is according to what we expect (change also marker size + # so we are sure that it's size and position have correcly been updated) + legend.setLegendFilterByMapEnabled(True) + marker_symbol.setSize(10) + + self.assertTrue( + self.render_layout_check( + 'composer_legend_reference_point_newsize', layout + ) + ) + QgsProject.instance().clear() def test_rulebased_child_filter(self): diff --git a/tests/src/python/test_qgsproject.py b/tests/src/python/test_qgsproject.py index b6f1579bddb7..3184a0ccd355 100644 --- a/tests/src/python/test_qgsproject.py +++ b/tests/src/python/test_qgsproject.py @@ -45,7 +45,7 @@ import unittest from qgis.testing import start_app, QgisTestCase -from utilities import unitTestDataPath +from utilities import unitTestDataPath, getTempfilePath app = start_app() TEST_DATA_DIR = unitTestDataPath() @@ -1610,11 +1610,15 @@ def testSelectionColor(self): def testColorScheme(self): p = QgsProject.instance() spy = QSignalSpy(p.projectColorsChanged) - p.setProjectColors([[QColor(255, 0, 0), 'red'], [QColor(0, 255, 0), 'green']]) + p.setProjectColors([[QColor(255, 0, 0), 'red'], [QColor(0, 255, 0), 'green'], [QColor.fromCmykF(1, 0.9, 0.8, 0.7), 'TestCmyk']]) self.assertEqual(len(spy), 1) scheme = [s for s in QgsApplication.colorSchemeRegistry().schemes() if isinstance(s, QgsProjectColorScheme)][0] - self.assertEqual([[c[0].name(), c[1]] for c in scheme.fetchColors()], - [['#ff0000', 'red'], ['#00ff00', 'green']]) + self.assertEqual([[c[0], c[1]] for c in scheme.fetchColors()], + [[QColor(255, 0, 0), 'red'], [QColor(0, 255, 0), 'green'], [QColor.fromCmykF(1, 0.9, 0.8, 0.7), 'TestCmyk']]) + + project_filepath = getTempfilePath("qgs") + p.write(project_filepath) + # except color changed signal when clearing project p.clear() self.assertEqual(len(spy), 2) @@ -1627,6 +1631,13 @@ def testColorScheme(self): del p self.assertEqual(len(spy), 0) + # Test that write/read doesn't convert color to RGB always + p = QgsProject.instance() + p.read(project_filepath) + scheme = [s for s in QgsApplication.colorSchemeRegistry().schemes() if isinstance(s, QgsProjectColorScheme)][0] + self.assertEqual([[c[0], c[1]] for c in scheme.fetchColors()], + [[QColor(255, 0, 0), 'red'], [QColor(0, 255, 0), 'green'], [QColor.fromCmykF(1, 0.9, 0.8, 0.7), 'TestCmyk']]) + def testTransformContextSignalIsEmitted(self): """Test that when a project transform context changes a transformContextChanged signal is emitted""" diff --git a/tests/src/python/test_qgspropertyoverridebutton.py b/tests/src/python/test_qgspropertyoverridebutton.py index c37b29cadab2..29ce4ae8a8c4 100644 --- a/tests/src/python/test_qgspropertyoverridebutton.py +++ b/tests/src/python/test_qgspropertyoverridebutton.py @@ -51,18 +51,24 @@ def testProjectColor(self): button.menuActionTriggered(color_action.menu().actions()[1]) self.assertTrue(button.toProperty().isActive()) - self.assertEqual(button.toProperty().asExpression(), 'project_color(\'burnt marigold\')') + self.assertEqual(button.toProperty().asExpression(), 'project_color_object(\'burnt marigold\')') button.menuActionTriggered(color_action.menu().actions()[0]) self.assertTrue(button.toProperty().isActive()) - self.assertEqual(button.toProperty().asExpression(), 'project_color(\'color 1\')') + self.assertEqual(button.toProperty().asExpression(), 'project_color_object(\'color 1\')') - button.setToProperty(QgsProperty.fromExpression('project_color(\'burnt marigold\')')) + button.setToProperty(QgsProperty.fromExpression('project_color_object(\'burnt marigold\')')) button.aboutToShowMenu() color_action = [a for a in button.menu().actions() if a.text() == 'Color'][0] self.assertTrue(color_action.isChecked()) self.assertEqual([a.isChecked() for a in color_action.menu().actions()], [False, True]) + button.setToProperty(QgsProperty.fromExpression('project_color(\'color 1\')')) + button.aboutToShowMenu() + color_action = [a for a in button.menu().actions() if a.text() == 'Color'][0] + self.assertTrue(color_action.isChecked()) + self.assertEqual([a.isChecked() for a in color_action.menu().actions()], [True, False]) + # should also see color menu for ColorNoAlpha properties definition = QgsPropertyDefinition('test', 'test', QgsPropertyDefinition.StandardPropertyTemplate.ColorNoAlpha) button = QgsPropertyOverrideButton() diff --git a/tests/testdata/control_images/3d/expected_polygon3d_extrusion_textured_phong/default/expected_polygon3d_extrusion_textured_phong.png b/tests/testdata/control_images/3d/expected_polygon3d_extrusion_textured_phong/default/expected_polygon3d_extrusion_textured_phong.png new file mode 100644 index 000000000000..8fe83dc9a89f Binary files /dev/null and b/tests/testdata/control_images/3d/expected_polygon3d_extrusion_textured_phong/default/expected_polygon3d_extrusion_textured_phong.png differ diff --git a/tests/testdata/control_images/3d/expected_polygon3d_extrusion_textured_phong/qt6/expected_polygon3d_extrusion_textured_phong.png b/tests/testdata/control_images/3d/expected_polygon3d_extrusion_textured_phong/qt6/expected_polygon3d_extrusion_textured_phong.png new file mode 100644 index 000000000000..a13ddfc72a1f Binary files /dev/null and b/tests/testdata/control_images/3d/expected_polygon3d_extrusion_textured_phong/qt6/expected_polygon3d_extrusion_textured_phong.png differ diff --git a/tests/testdata/control_images/composer_legend/expected_composer_legend_reference_point_newsize/expected_composer_legend_reference_point_newsize.png b/tests/testdata/control_images/composer_legend/expected_composer_legend_reference_point_newsize/expected_composer_legend_reference_point_newsize.png new file mode 100644 index 000000000000..bb15a0192439 Binary files /dev/null and b/tests/testdata/control_images/composer_legend/expected_composer_legend_reference_point_newsize/expected_composer_legend_reference_point_newsize.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png b/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png index 62bf04e9cb7e..5409ca13bae9 100644 Binary files a/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png and b/tests/testdata/control_images/legend/expected_legend_diagram_attributes/expected_legend_diagram_attributes_mask.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_mesh_diagram_color_ramp_vector/expected_legend_mesh_diagram_color_ramp_vector.png b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_color_ramp_vector/expected_legend_mesh_diagram_color_ramp_vector.png new file mode 100644 index 000000000000..c7ae78d0dfec Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_color_ramp_vector/expected_legend_mesh_diagram_color_ramp_vector.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_mesh_diagram_color_ramp_vector/expected_legend_mesh_diagram_color_ramp_vector_mask.png b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_color_ramp_vector/expected_legend_mesh_diagram_color_ramp_vector_mask.png new file mode 100644 index 000000000000..94c4bd0000b7 Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_color_ramp_vector/expected_legend_mesh_diagram_color_ramp_vector_mask.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_mesh_diagram_no_vector/expected_legend_mesh_diagram_no_vector.png b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_no_vector/expected_legend_mesh_diagram_no_vector.png new file mode 100644 index 000000000000..698dcc9606ea Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_no_vector/expected_legend_mesh_diagram_no_vector.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_mesh_diagram_no_vector/expected_legend_mesh_diagram_no_vector_mask.png b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_no_vector/expected_legend_mesh_diagram_no_vector_mask.png new file mode 100644 index 000000000000..7fe2124f6d51 Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_no_vector/expected_legend_mesh_diagram_no_vector_mask.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_mesh_diagram_red_vector/expected_legend_mesh_diagram_red_vector.png b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_red_vector/expected_legend_mesh_diagram_red_vector.png new file mode 100644 index 000000000000..c5a2a31852f5 Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_red_vector/expected_legend_mesh_diagram_red_vector.png differ diff --git a/tests/testdata/control_images/legend/expected_legend_mesh_diagram_red_vector/expected_legend_mesh_diagram_red_vector_mask.png b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_red_vector/expected_legend_mesh_diagram_red_vector_mask.png new file mode 100644 index 000000000000..95fd3dad4f0b Binary files /dev/null and b/tests/testdata/control_images/legend/expected_legend_mesh_diagram_red_vector/expected_legend_mesh_diagram_red_vector_mask.png differ