Skip to content
Permalink
Browse files

Avoid style dock flashing when editing layers

Also prevent a lot of duplicate style dock updates, and fix
the style dock losing connection to layer style changes
  • Loading branch information
nyalldawson committed Jun 27, 2016
1 parent df579a5 commit c3c5c431904c37c76101edbcc54d8c2796df078a
@@ -618,6 +618,11 @@ class QgsMapLayer : QObject
/** Time stamp of data source in the moment when data/metadata were loaded by provider */
virtual QDateTime timestamp() const;

/** Triggers an emission of the styleChanged() signal.
* @note added in QGIS 2.16
*/
void emitStyleChanged();

signals:

//! @deprecated in 2.4 - not emitted anymore
@@ -649,9 +654,19 @@ class QgsMapLayer : QObject
/** Signal emitted when the blend mode is changed, through QgsMapLayer::setBlendMode() */
void blendModeChanged( QPainter::CompositionMode blendMode );

/** Signal emitted when renderer is changed */
/** Signal emitted when renderer is changed.
* @see styleChanged()
*/
void rendererChanged();

/** Signal emitted whenever a change affects the layer's style. Ie this may be triggered
* by renderer changes, label style changes, or other style changes such as blend
* mode or layer opacity changes.
* @note added in QGIS 2.16
* @see rendererChanged()
*/
void styleChanged();

/**
* Signal emitted when legend of the layer has changed
* @note added in 2.6
@@ -11345,10 +11345,14 @@ void QgisApp::showLayerProperties( QgsMapLayer *ml )
vlp->addPropertiesPageFactory( factory );
}

mMapStyleWidget->blockUpdates( true );
if ( vlp->exec() )
{
activateDeactivateLayerRelatedActions( ml );
mMapStyleWidget->updateCurrentWidgetLayer();
}
mMapStyleWidget->blockUpdates( false );

delete vlp; // delete since dialog cannot be reused without updating code
}
else if ( ml->type() == QgsMapLayer::PluginLayer )
@@ -511,7 +511,7 @@ void QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor( const QColor& color
return;

QString layerId = action->property( "layerId" ).toString();
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) );
QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) );
if ( !layer )
return;

@@ -545,6 +545,7 @@ void QgsAppLayerTreeViewMenuProvider::setVectorSymbolColor( const QColor& color
}

layer->triggerRepaint();
layer->emitStyleChanged();
mView->refreshLayerSymbology( layer->id() );
}

@@ -573,6 +574,10 @@ void QgsAppLayerTreeViewMenuProvider::editSymbolLegendNodeSymbol()
if ( dlg.exec() )
{
node->setSymbol( symbol.take() );
if ( vlayer )
{
vlayer->emitStyleChanged();
}
}
}

@@ -596,4 +601,8 @@ void QgsAppLayerTreeViewMenuProvider::setSymbolLegendNodeColor( const QColor &co
QgsSymbolV2* newSymbol = originalSymbol->clone();
newSymbol->setColor( color );
node->setSymbol( newSymbol );
if ( QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) ) )
{
layer->emitStyleChanged();
}
}
@@ -95,13 +95,37 @@ void QgsLayerStylingWidget::setPageFactories( QList<QgsLayerStylingPanelFactory
mPageFactories.append( mStyleManagerFactory );
}

void QgsLayerStylingWidget::blockUpdates( bool blocked )
{
if ( !mCurrentLayer )
return;

if ( blocked )
{
disconnect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );
}
else
{
connect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );
}
}

void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
{
if ( layer == mCurrentLayer )
return;

if ( mCurrentLayer )
{
disconnect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );
}

if ( !layer || !layer->isSpatial() )
{
mLayerCombo->setLayer( nullptr );
mStackedWidget->setCurrentIndex( mNotSupportedPage );
mLastStyleXml.clear();
mCurrentLayer = nullptr;
return;
}

@@ -112,9 +136,10 @@ void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
}

mCurrentLayer = layer;
connect( mCurrentLayer, SIGNAL( repaintRequested() ), this, SLOT( updateCurrentWidgetLayer() ) );
connect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );

int lastPage = mOptionsListWidget->currentIndex().row();
mOptionsListWidget->blockSignals( true );
mOptionsListWidget->clear();
mUserPages.clear();
if ( layer->type() == QgsMapLayer::VectorLayer )
@@ -140,6 +165,7 @@ void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
}
}
mOptionsListWidget->addItem( new QListWidgetItem( QgsApplication::getThemeIcon( "mActionHistory.svg" ), "" ) );
mOptionsListWidget->blockSignals( false );

if ( sameLayerType )
{
@@ -164,7 +190,7 @@ void QgsLayerStylingWidget::apply()
if ( !mCurrentLayer )
return;

disconnect( mCurrentLayer, SIGNAL( repaintRequested() ), this, SLOT( updateCurrentWidgetLayer() ) );
disconnect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );

QString undoName = "Style Change";

@@ -213,7 +239,7 @@ void QgsLayerStylingWidget::apply()
mMapCanvas->clearCache();
mMapCanvas->refresh();
}
disconnect( mCurrentLayer, SIGNAL( repaintRequested() ), this, SLOT( updateCurrentWidgetLayer() ) );
connect( mCurrentLayer, SIGNAL( styleChanged() ), this, SLOT( updateCurrentWidgetLayer() ) );
}

void QgsLayerStylingWidget::autoApply()
@@ -374,8 +400,7 @@ void QgsLayerStylingWidget::layerAboutToBeRemoved( QgsMapLayer* layer )
if ( layer == mCurrentLayer )
{
mAutoApplyTimer->stop();
mStackedWidget->setCurrentIndex( mNotSupportedPage );
mCurrentLayer = nullptr;
setLayer( nullptr );
}
}

@@ -72,6 +72,13 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty

void setPageFactories( QList<QgsLayerStylingPanelFactory*> factories );

/** Sets whether updates of the styling widget are blocked. This can be called to prevent
* the widget being refreshed multiple times when a batch of layer style changes are
* about to be applied
* @param blocked set to true to block updates, or false to re-allow updates
*/
void blockUpdates( bool blocked );

signals:
void styleChanged( QgsMapLayer* layer );

@@ -81,9 +88,10 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty
void autoApply();
void undo();
void redo();
void updateCurrentWidgetLayer();

private slots:
void updateCurrentWidgetLayer();

void layerAboutToBeRemoved( QgsMapLayer* layer );
void liveApplyToggled( bool value );

@@ -147,6 +147,7 @@ void QgsMapLayer::setBlendMode( QPainter::CompositionMode blendMode )
{
mBlendMode = blendMode;
emit blendModeChanged( blendMode );
emit styleChanged();
}

/** Read blend mode for layer */
@@ -1707,6 +1708,11 @@ QString QgsMapLayer::metadata()
return QString();
}

void QgsMapLayer::emitStyleChanged()
{
emit styleChanged();
}

void QgsMapLayer::setExtent( const QgsRectangle &r )
{
mExtent = r;
@@ -638,6 +638,11 @@ class CORE_EXPORT QgsMapLayer : public QObject
/** Time stamp of data source in the moment when data/metadata were loaded by provider */
virtual QDateTime timestamp() const { return QDateTime() ; }

/** Triggers an emission of the styleChanged() signal.
* @note added in QGIS 2.16
*/
void emitStyleChanged();

signals:

//! @deprecated in 2.4 - not emitted anymore
@@ -669,9 +674,19 @@ class CORE_EXPORT QgsMapLayer : public QObject
/** Signal emitted when the blend mode is changed, through QgsMapLayer::setBlendMode() */
void blendModeChanged( QPainter::CompositionMode blendMode );

/** Signal emitted when renderer is changed */
/** Signal emitted when renderer is changed.
* @see styleChanged()
*/
void rendererChanged();

/** Signal emitted whenever a change affects the layer's style. Ie this may be triggered
* by renderer changes, label style changes, or other style changes such as blend
* mode or layer opacity changes.
* @note added in QGIS 2.16
* @see rendererChanged()
*/
void styleChanged();

/**
* Signal emitted when legend of the layer has changed
* @note added in 2.6
@@ -1244,10 +1244,9 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
layer->setCustomProperty( "labeling/zIndex", zIndex );

writeDataDefinedPropertyMap( layer, nullptr, dataDefinedProperties );
layer->emitStyleChanged();
}



void QgsPalLayerSettings::readXml( QDomElement& elem )
{
enabled = true;
@@ -659,6 +659,7 @@ void QgsVectorLayer::setDiagramRenderer( QgsDiagramRendererV2* r )
delete mDiagramRenderer;
mDiagramRenderer = r;
emit rendererChanged();
emit styleChanged();
}

QGis::GeometryType QgsVectorLayer::geometryType() const
@@ -2964,6 +2965,7 @@ void QgsVectorLayer::setRendererV2( QgsFeatureRendererV2 *r )
mSymbolFeatureCountMap.clear();

emit rendererChanged();
emit styleChanged();
}
}

@@ -3469,6 +3471,7 @@ void QgsVectorLayer::setFeatureBlendMode( QPainter::CompositionMode featureBlend
{
mFeatureBlendMode = featureBlendMode;
emit featureBlendModeChanged( featureBlendMode );
emit styleChanged();
}

/** Read blend mode for layer */
@@ -3482,6 +3485,7 @@ void QgsVectorLayer::setLayerTransparency( int layerTransparency )
{
mLayerTransparency = layerTransparency;
emit layerTransparencyChanged( layerTransparency );
emit styleChanged();
}

/** Read transparency for layer */
@@ -936,6 +936,7 @@ void QgsRasterLayer::setContrastEnhancement( QgsContrastEnhancement::ContrastEnh
qDeleteAll( myEnhancements );

emit repaintRequested();
emit styleChanged();
}

void QgsRasterLayer::setDefaultContrastEnhancement()
@@ -1076,6 +1077,7 @@ void QgsRasterLayer::setRenderer( QgsRasterRenderer* theRenderer )
if ( !theRenderer ) { return; }
mPipe.set( theRenderer );
emit rendererChanged();
emit styleChanged();
}

void QgsRasterLayer::showProgress( int theValue )

2 comments on commit c3c5c43

@nirvn

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn replied Jun 27, 2016

@nyalldawson , I'm not sure if it's this commit (going to figure this out in a minute), but editing a categorized, graduated symbol now crashes QGIS when pressing the [ < ] button. The trace is:

`
#0 QMetaObject::activate (sender=0x0, m=, local_signal_index=0, argv=0x7fffffffc310) at kernel/qobject.cpp:3472
#1 0x00007ffff6f2a854 in QgsPanelWidget::panelAccepted (this=0x0, _t1=0x0) at /home/webmaster/dev/cpp/QGIS/bm/src/gui/moc_qgspanelwidget.cxx:110
#2 0x00007ffff6eadc73 in QgsPanelWidget::acceptPanel (this=0x0) at /home/webmaster/dev/cpp/QGIS/src/gui/qgspanelwidget.cpp:76
#3 0x00007ffff6eae013 in QgsPanelWidgetStack::acceptCurrentPanel (this=0x14b6500) at /home/webmaster/dev/cpp/QGIS/src/gui/qgspanelwidget.cpp:145
#4 0x00007ffff6f2aa71 in QgsPanelWidgetStack::qt_static_metacall (_o=0x14b6500, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x7fffffffc460)

at /home/webmaster/dev/cpp/QGIS/bm/src/gui/moc_qgspanelwidget.cxx:219

#5 0x00007ffff58f6010 in QMetaObject::activate (sender=sender@entry=0x14b63c0, m=m@entry=0x7ffff5741f60 QAbstractButton::staticMetaObject,

local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x0) at kernel/qobject.cpp:3567

#6 0x00007ffff52cccb0 in QAbstractButton::pressed (this=this@entry=0x14b63c0) at .moc/release-shared/moc_qabstractbutton.cpp:206
#7 0x00007ffff5002366 in QAbstractButtonPrivate::emitPressed (this=this@entry=0x17aba60) at widgets/qabstractbutton.cpp:562
#8 0x00007ffff5002cd3 in QAbstractButton::mousePressEvent (this=0x14b63c0, e=0x7fffffffca20) at widgets/qabstractbutton.cpp:1098
#9 0x00007ffff4c7f490 in QWidget::event (this=0x14b63c0, event=0x7fffffffca20) at kernel/qwidget.cpp:8385
#10 0x00007ffff4c27fdc in QApplicationPrivate::notify_helper (this=this@entry=0x947f00, receiver=receiver@entry=0x14b63c0, e=e@entry=0x7fffffffca20)

at kernel/qapplication.cpp:4570

#11 0x00007ffff4c2f0d6 in QApplication::notify (this=, receiver=0x14b63c0, e=0x7fffffffca20) at kernel/qapplication.cpp:4113
#12 0x00007ffff5fc5999 in QgsApplication::notify (this=0x7fffffffdae0, receiver=0x14b63c0, event=0x7fffffffca20)

at /home/webmaster/dev/cpp/QGIS/src/core/qgsapplication.cpp:281

#13 0x00007ffff58e190d in QCoreApplication::notifyInternal (this=0x7fffffffdae0, receiver=receiver@entry=0x14b63c0, event=event@entry=0x7fffffffca20)

at kernel/qcoreapplication.cpp:955

#14 0x00007ffff4c2e6dd in QCoreApplication::sendEvent (event=, receiver=)

at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:231

#15 QApplicationPrivate::sendMouseEvent (receiver=receiver@entry=0x14b63c0, event=event@entry=0x7fffffffca20, alienWidget=alienWidget@entry=0x14b63c0,

nativeWidget=nativeWidget@entry=0xce80b0, buttonDown=buttonDown@entry=0x7ffff5753368 <qt_button_down>, lastMouseReceiver=..., spontaneous=true)
at kernel/qapplication.cpp:3178

#16 0x00007ffff4cac3f2 in QETWidget::translateMouseEvent (this=this@entry=0xce80b0, event=event@entry=0x7fffffffcd80) at kernel/qapplication_x11.cpp:4638
#17 0x00007ffff4cabc83 in QApplication::x11ProcessEvent (this=0x7fffffffdae0, event=event@entry=0x7fffffffcd80) at kernel/qapplication_x11.cpp:3626
#18 0x00007ffff4cd5542 in x11EventSourceDispatch (s=0x947960, callback=0x0, user_data=0x0) at kernel/qguieventdispatcher_glib.cpp:146
#19 0x00007fffed33d1a7 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#20 0x00007fffed33d400 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#21 0x00007fffed33d4ac in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#22 0x00007ffff59122ae in QEventDispatcherGlib::processEvents (this=0x8a4d80, flags=...) at kernel/qeventdispatcher_glib.cpp:450
#23 0x00007ffff4cd5616 in QGuiEventDispatcherGlib::processEvents (this=, flags=...) at kernel/qguieventdispatcher_glib.cpp:204
#24 0x00007ffff58e018f in QEventLoop::processEvents (this=this@entry=0x7fffffffd160, flags=...) at kernel/qeventloop.cpp:149
#25 0x00007ffff58e04f5 in QEventLoop::exec (this=this@entry=0x7fffffffd160, flags=...) at kernel/qeventloop.cpp:204
#26 0x00007ffff58e64b9 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1227
#27 0x0000000000409ccd in main (argc=1, argv=0x7fffffffddc8) at /home/webmaster/dev/cpp/QGIS/src/app/main.cpp:1257

`

@nirvn

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn replied Jun 27, 2016

Ok, just confirmed, the build start crashing when including this commit c3c5c43 (Avoid style dock flashing when editing layers).

Steps to reproduce the crash:

  • Load a vector layer, open the style dock
  • Set renderer to categorized, pick a field and classify
  • Edit on one category to edit its symbol
  • Click on the [ < ] back arrow, by which stage you'll see an empty style dock panel
  • Click on the [ < ] back arrow again, boom
Please sign in to comment.
You can’t perform that action at this time.