diff --git a/python/gui/auto_generated/qgsmaplayerconfigwidget.sip.in b/python/gui/auto_generated/qgsmaplayerconfigwidget.sip.in index 334c0414920..fe46595e830 100644 --- a/python/gui/auto_generated/qgsmaplayerconfigwidget.sip.in +++ b/python/gui/auto_generated/qgsmaplayerconfigwidget.sip.in @@ -36,6 +36,15 @@ A panel widget that can be shown in the map style dock Keep the loading light as possible for speed in the UI. %End + virtual bool shouldTriggerLayerRepaint() const; +%Docstring +Whether this config widget changes map layer properties in a way that triggerRepaint() should +be called for the layer after applying changes. This is true by default, but some config widgets +(for example 3D rendering config) do not need layer repaint as they do not modify 2D map rendering. + +.. versionadded:: 3.8 +%End + public slots: virtual void apply() = 0; diff --git a/src/app/3d/qgsvectorlayer3drendererwidget.h b/src/app/3d/qgsvectorlayer3drendererwidget.h index 908222e0c23..27ae86bf0fd 100644 --- a/src/app/3d/qgsvectorlayer3drendererwidget.h +++ b/src/app/3d/qgsvectorlayer3drendererwidget.h @@ -66,6 +66,9 @@ class QgsVectorLayer3DRendererWidget : public QgsMapLayerConfigWidget void setDockMode( bool dockMode ) override; + //! Only modifies 3D renderer so we do not want layer repaint (which would trigger unnecessary terrain map update) + bool shouldTriggerLayerRepaint() const override { return false; } + public slots: void apply() override; diff --git a/src/app/qgslayerstylingwidget.cpp b/src/app/qgslayerstylingwidget.cpp index 7102c5562e5..37f2fc191be 100644 --- a/src/app/qgslayerstylingwidget.cpp +++ b/src/app/qgslayerstylingwidget.cpp @@ -271,6 +271,7 @@ void QgsLayerStylingWidget::apply() QWidget *current = mWidgetStack->mainPanel(); bool styleWasChanged = false; + bool triggerRepaint = false; // whether the change needs the layer to be repainted if ( QgsLabelingWidget *widget = qobject_cast( current ) ) { widget->apply(); @@ -286,31 +287,34 @@ void QgsLayerStylingWidget::apply() QgsRendererAbstractMetadata *m = QgsApplication::rendererRegistry()->rendererMetadata( layer->renderer()->type() ); undoName = QStringLiteral( "Style Change - %1" ).arg( m->visibleName() ); styleWasChanged = true; + triggerRepaint = true; } } else if ( QgsRasterTransparencyWidget *widget = qobject_cast( current ) ) { widget->apply(); styleWasChanged = true; + triggerRepaint = true; } else if ( qobject_cast( current ) ) { mRasterStyleWidget->apply(); styleWasChanged = true; + triggerRepaint = true; } else if ( QgsMapLayerConfigWidget *widget = qobject_cast( current ) ) { widget->apply(); styleWasChanged = true; + triggerRepaint = widget->shouldTriggerLayerRepaint(); } - pushUndoItem( undoName ); + pushUndoItem( undoName, triggerRepaint ); if ( styleWasChanged ) { emit styleChanged( mCurrentLayer ); QgsProject::instance()->setDirty( true ); - mCurrentLayer->triggerRepaint(); } connect( mCurrentLayer, &QgsMapLayer::styleChanged, this, &QgsLayerStylingWidget::updateCurrentWidgetLayer ); } @@ -608,25 +612,26 @@ void QgsLayerStylingWidget::liveApplyToggled( bool value ) settings.setValue( QStringLiteral( "UI/autoApplyStyling" ), value ); } -void QgsLayerStylingWidget::pushUndoItem( const QString &name ) +void QgsLayerStylingWidget::pushUndoItem( const QString &name, bool triggerRepaint ) { QString errorMsg; QDomDocument doc( QStringLiteral( "style" ) ); QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) ); doc.appendChild( rootNode ); mCurrentLayer->writeStyle( rootNode, doc, errorMsg, QgsReadWriteContext() ); - mCurrentLayer->undoStackStyles()->push( new QgsMapLayerStyleCommand( mCurrentLayer, name, rootNode, mLastStyleXml ) ); + mCurrentLayer->undoStackStyles()->push( new QgsMapLayerStyleCommand( mCurrentLayer, name, rootNode, mLastStyleXml, triggerRepaint ) ); // Override the last style on the stack mLastStyleXml = rootNode.cloneNode(); } -QgsMapLayerStyleCommand::QgsMapLayerStyleCommand( QgsMapLayer *layer, const QString &text, const QDomNode ¤t, const QDomNode &last ) +QgsMapLayerStyleCommand::QgsMapLayerStyleCommand( QgsMapLayer *layer, const QString &text, const QDomNode ¤t, const QDomNode &last, bool triggerRepaint ) : QUndoCommand( text ) , mLayer( layer ) , mXml( current ) , mLastState( last ) , mTime( QTime::currentTime() ) + , mTriggerRepaint( triggerRepaint ) { } @@ -635,7 +640,8 @@ void QgsMapLayerStyleCommand::undo() QString error; QgsReadWriteContext context = QgsReadWriteContext(); mLayer->readStyle( mLastState, error, context ); - mLayer->triggerRepaint(); + if ( mTriggerRepaint ) + mLayer->triggerRepaint(); } void QgsMapLayerStyleCommand::redo() @@ -643,7 +649,8 @@ void QgsMapLayerStyleCommand::redo() QString error; QgsReadWriteContext context = QgsReadWriteContext(); mLayer->readStyle( mXml, error, context ); - mLayer->triggerRepaint(); + if ( mTriggerRepaint ) + mLayer->triggerRepaint(); } bool QgsMapLayerStyleCommand::mergeWith( const QUndoCommand *other ) @@ -664,6 +671,7 @@ bool QgsMapLayerStyleCommand::mergeWith( const QUndoCommand *other ) mXml = otherCmd->mXml; mTime = otherCmd->mTime; + mTriggerRepaint |= otherCmd->mTriggerRepaint; return true; } diff --git a/src/app/qgslayerstylingwidget.h b/src/app/qgslayerstylingwidget.h index 95de3ff3d48..021f4594246 100644 --- a/src/app/qgslayerstylingwidget.h +++ b/src/app/qgslayerstylingwidget.h @@ -56,7 +56,7 @@ class APP_EXPORT QgsLayerStyleManagerWidgetFactory : public QgsMapLayerConfigWid class APP_EXPORT QgsMapLayerStyleCommand : public QUndoCommand { public: - QgsMapLayerStyleCommand( QgsMapLayer *layer, const QString &text, const QDomNode ¤t, const QDomNode &last ); + QgsMapLayerStyleCommand( QgsMapLayer *layer, const QString &text, const QDomNode ¤t, const QDomNode &last, bool triggerRepaint = true ); /** * Returns unique ID for this kind of undo command. @@ -75,6 +75,7 @@ class APP_EXPORT QgsMapLayerStyleCommand : public QUndoCommand QDomNode mXml; QDomNode mLastState; QTime mTime; + bool mTriggerRepaint = true; }; class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerStylingWidgetBase @@ -129,7 +130,7 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty void liveApplyToggled( bool value ); private: - void pushUndoItem( const QString &name ); + void pushUndoItem( const QString &name, bool triggerRepaint = true ); int mNotSupportedPage; int mLayerPage; QTimer *mAutoApplyTimer = nullptr; diff --git a/src/gui/qgsmaplayerconfigwidget.h b/src/gui/qgsmaplayerconfigwidget.h index 8fe7b0ec5b8..6be200db191 100644 --- a/src/gui/qgsmaplayerconfigwidget.h +++ b/src/gui/qgsmaplayerconfigwidget.h @@ -45,6 +45,14 @@ class GUI_EXPORT QgsMapLayerConfigWidget : public QgsPanelWidget */ QgsMapLayerConfigWidget( QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent = nullptr ); + /** + * Whether this config widget changes map layer properties in a way that triggerRepaint() should + * be called for the layer after applying changes. This is true by default, but some config widgets + * (for example 3D rendering config) do not need layer repaint as they do not modify 2D map rendering. + * \since QGIS 3.8 + */ + virtual bool shouldTriggerLayerRepaint() const { return true; } + public slots: /**