Skip to content

Commit

Permalink
Merge pull request #4111 from nyalldawson/refresh_layers
Browse files Browse the repository at this point in the history
[FEATURE] Allow layers to be automatically refreshed at a specified interval
  • Loading branch information
nyalldawson committed Feb 13, 2017
2 parents 787c846 + 38f87a6 commit f2ac60a
Show file tree
Hide file tree
Showing 19 changed files with 569 additions and 25 deletions.
20 changes: 9 additions & 11 deletions python/core/qgsmaplayer.sip
Expand Up @@ -603,6 +603,11 @@ class QgsMapLayer : QObject
*/
bool hasScaleBasedVisibility() const;

bool hasAutoRefreshEnabled() const;
int autoRefreshInterval() const;
void setAutoRefreshInterval( int interval );
void setAutoRefreshEnabled( bool enabled );

public slots:

/** Event handler for when a coordinate transform fails due to bad vertex error */
Expand Down Expand Up @@ -634,13 +639,7 @@ class QgsMapLayer : QObject
*/
void setScaleBasedVisibility( const bool enabled );

/**
* Will advice the map canvas (and any other interested party) that this layer requires to be repainted.
* Will emit a repaintRequested() signal.
*
* @note in 2.6 function moved from vector/raster subclasses to QgsMapLayer
*/
void triggerRepaint();
void triggerRepaint( bool deferredUpdate = false );

/** \brief Obtain Metadata for this layer */
virtual QString metadata() const;
Expand Down Expand Up @@ -687,10 +686,7 @@ class QgsMapLayer : QObject
/** Emit a signal that layer's CRS has been reset */
void crsChanged();

/** By emitting this signal the layer tells that either appearance or content have been changed
* and any view showing the rendered layer should refresh itself.
*/
void repaintRequested();
void repaintRequested( bool deferredUpdate = false );

/** This is used to send a request that any mapcanvas using this layer update its extents */
void recalculateExtents() const;
Expand Down Expand Up @@ -739,6 +735,8 @@ class QgsMapLayer : QObject
*/
void willBeDeleted();

void autoRefreshIntervalChanged( int interval );

protected:
/** Set the extent */
virtual void setExtent( const QgsRectangle &rect );
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Expand Up @@ -10408,7 +10408,7 @@ void QgisApp::layersWereAdded( const QList<QgsMapLayer *>& theLayers )

if ( provider )
{
connect( provider, &QgsDataProvider::dataChanged, layer, &QgsMapLayer::triggerRepaint );
connect( provider, &QgsDataProvider::dataChanged, layer, [layer] { layer->triggerRepaint(); } );
connect( provider, &QgsDataProvider::dataChanged, mMapCanvas, &QgsMapCanvas::refresh );
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/app/qgsrasterlayerproperties.cpp
Expand Up @@ -139,6 +139,8 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
// enable or disable Build Pyramids button depending on selection in pyramid list
connect( lbxPyramidResolutions, SIGNAL( itemSelectionChanged() ), this, SLOT( toggleBuildPyramidsButton() ) );

connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );

// set up the scale based layer visibility stuff....
mScaleRangeWidget->setMapCanvas( mMapCanvas );
chkUseScaleDependentRendering->setChecked( lyr->hasScaleBasedVisibility() );
Expand Down Expand Up @@ -713,6 +715,10 @@ void QgsRasterLayerProperties::sync()
leNoDataValue->insert( QLatin1String( "" ) );
}

mRefreshLayerCheckBox->setChecked( mRasterLayer->hasAutoRefreshEnabled() );
mRefreshLayerIntervalSpinBox->setEnabled( mRasterLayer->hasAutoRefreshEnabled() );
mRefreshLayerIntervalSpinBox->setValue( mRasterLayer->autoRefreshInterval() / 1000.0 );

populateTransparencyTable( mRasterLayer->renderer() );

QgsDebugMsg( "populate colormap tab" );
Expand Down Expand Up @@ -940,6 +946,9 @@ void QgsRasterLayerProperties::apply()
mRasterLayer->setMaximumScale( 1.0 / mScaleRangeWidget->minimumScale() );
mRasterLayer->setMinimumScale( 1.0 / mScaleRangeWidget->maximumScale() );

mRasterLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
mRasterLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );

//update the legend pixmap
// pixmapLegend->setPixmap( mRasterLayer->legendAsPixmap() );
// pixmapLegend->setScaledContents( true );
Expand Down
10 changes: 10 additions & 0 deletions src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -322,6 +322,9 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
}

mLayersDependenciesTreeView->setModel( mLayersDependenciesTreeModel.get() );

connect( mRefreshLayerCheckBox, &QCheckBox::toggled, mRefreshLayerIntervalSpinBox, &QDoubleSpinBox::setEnabled );

} // QgsVectorLayerProperties ctor


Expand Down Expand Up @@ -446,6 +449,10 @@ void QgsVectorLayerProperties::syncToLayer()

mForceRasterCheckBox->setChecked( mLayer->renderer() && mLayer->renderer()->forceRasterRender() );

mRefreshLayerCheckBox->setChecked( mLayer->hasAutoRefreshEnabled() );
mRefreshLayerIntervalSpinBox->setEnabled( mLayer->hasAutoRefreshEnabled() );
mRefreshLayerIntervalSpinBox->setValue( mLayer->autoRefreshInterval() / 1000.0 );

// load appropriate symbology page (V1 or V2)
updateSymbologyPage();

Expand Down Expand Up @@ -583,6 +590,9 @@ void QgsVectorLayerProperties::apply()
if ( mLayer->renderer() )
mLayer->renderer()->setForceRasterRender( mForceRasterCheckBox->isChecked() );

mLayer->setAutoRefreshInterval( mRefreshLayerIntervalSpinBox->value() * 1000.0 );
mLayer->setAutoRefreshEnabled( mRefreshLayerCheckBox->isChecked() );

mOldJoins = mLayer->vectorJoins();

//save variables
Expand Down
2 changes: 1 addition & 1 deletion src/browser/qgsbrowser.cpp
Expand Up @@ -439,7 +439,7 @@ void QgsBrowser::updateCurrentTab()
QgsRasterLayer *rlayer = qobject_cast< QgsRasterLayer * >( mLayer );
if ( rlayer )
{
connect( rlayer->dataProvider(), &QgsRasterDataProvider::dataChanged, rlayer, &QgsRasterLayer::triggerRepaint );
connect( rlayer->dataProvider(), &QgsRasterDataProvider::dataChanged, rlayer, [rlayer] { rlayer->triggerRepaint(); } );
connect( rlayer->dataProvider(), &QgsRasterDataProvider::dataChanged, mapCanvas, &QgsMapCanvas::refresh );
}
}
Expand Down
45 changes: 43 additions & 2 deletions src/core/qgsmaplayer.cpp
Expand Up @@ -83,6 +83,7 @@ QgsMapLayer::QgsMapLayer( QgsMapLayer::LayerType type,
mScaleBasedVisibility = false;

connect( mStyleManager, &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMapLayer::styleChanged );
connect( &mRefreshTimer, &QTimer::timeout, this, [=] { triggerRepaint( true ); } );
}

QgsMapLayer::~QgsMapLayer()
Expand Down Expand Up @@ -420,6 +421,9 @@ bool QgsMapLayer::readLayerXml( const QDomElement& layerElement, const QgsProjec
setMinimumScale( layerElement.attribute( QStringLiteral( "minimumScale" ) ).toDouble() );
setMaximumScale( layerElement.attribute( QStringLiteral( "maximumScale" ) ).toDouble() );

setAutoRefreshInterval( layerElement.attribute( QStringLiteral( "autoRefreshTime" ), 0 ).toInt() );
setAutoRefreshEnabled( layerElement.attribute( QStringLiteral( "autoRefreshEnabled" ), QStringLiteral( "0" ) ).toInt() );

QDomNode extentNode = layerElement.namedItem( QStringLiteral( "extent" ) );
if ( !extentNode.isNull() )
{
Expand Down Expand Up @@ -537,6 +541,9 @@ bool QgsMapLayer::writeLayerXml( QDomElement& layerElement, QDomDocument& docume
layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent, document ) );
}

layerElement.setAttribute( QStringLiteral( "autoRefreshTime" ), QString::number( mRefreshTimer.interval() ) );
layerElement.setAttribute( QStringLiteral( "autoRefreshEnabled" ), mRefreshTimer.isActive() ? 1 : 0 );

// ID
QDomElement layerId = document.createElement( QStringLiteral( "id" ) );
QDomText layerIdText = document.createTextNode( id() );
Expand Down Expand Up @@ -857,6 +864,40 @@ bool QgsMapLayer::hasScaleBasedVisibility() const
return mScaleBasedVisibility;
}

bool QgsMapLayer::hasAutoRefreshEnabled() const
{
return mRefreshTimer.isActive();
}

int QgsMapLayer::autoRefreshInterval() const
{
return mRefreshTimer.interval();
}

void QgsMapLayer::setAutoRefreshInterval( int interval )
{
if ( interval <= 0 )
{
mRefreshTimer.stop();
mRefreshTimer.setInterval( 0 );
}
else
{
mRefreshTimer.setInterval( interval );
}
emit autoRefreshIntervalChanged( mRefreshTimer.isActive() ? mRefreshTimer.interval() : 0 );
}

void QgsMapLayer::setAutoRefreshEnabled( bool enabled )
{
if ( !enabled )
mRefreshTimer.stop();
else if ( mRefreshTimer.interval() > 0 )
mRefreshTimer.start();

emit autoRefreshIntervalChanged( mRefreshTimer.isActive() ? mRefreshTimer.interval() : 0 );
}

void QgsMapLayer::setMinimumScale( double scale )
{
mMinScale = scale;
Expand Down Expand Up @@ -1591,9 +1632,9 @@ QgsMapLayerStyleManager* QgsMapLayer::styleManager() const
return mStyleManager;
}

void QgsMapLayer::triggerRepaint()
void QgsMapLayer::triggerRepaint( bool deferredUpdate )
{
emit repaintRequested();
emit repaintRequested( deferredUpdate );
}

QString QgsMapLayer::metadata() const
Expand Down
60 changes: 57 additions & 3 deletions src/core/qgsmaplayer.h
Expand Up @@ -53,6 +53,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
Q_OBJECT

Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
Q_PROPERTY( int autoRefreshInterval READ autoRefreshInterval WRITE setAutoRefreshInterval NOTIFY autoRefreshIntervalChanged )

public:

Expand Down Expand Up @@ -646,6 +647,44 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
bool hasScaleBasedVisibility() const;

/**
* Returns true if auto refresh is enabled for the layer.
* @note added in QGIS 3.0
* @see autoRefreshInterval()
* @see setAutoRefreshEnabled()
*/
bool hasAutoRefreshEnabled() const;

/**
* Returns the auto refresh interval (in milliseconds). Note that
* auto refresh is only active when hasAutoRefreshEnabled() is true.
* @note added in QGIS 3.0
* @see autoRefreshEnabled()
* @see setAutoRefreshInterval()
*/
int autoRefreshInterval() const;

/**
* Sets the auto refresh interval (in milliseconds) for the layer. This
* will cause the layer to be automatically redrawn on a matching interval.
* Note that auto refresh must be enabled by calling setAutoRefreshEnabled().
*
* Note that auto refresh triggers deferred repaints of the layer. Any map
* canvas must be refreshed separately in order to view the refreshed layer.
* @note added in QGIS 3.0
* @see autoRefreshInterval()
* @see setAutoRefreshEnabled()
*/
void setAutoRefreshInterval( int interval );

/**
* Sets whether auto refresh is enabled for the layer.
* @note added in QGIS 3.0
* @see hasAutoRefreshEnabled()
* @see setAutoRefreshInterval()
*/
void setAutoRefreshEnabled( bool enabled );

public slots:

//! Event handler for when a coordinate transform fails due to bad vertex error
Expand Down Expand Up @@ -678,12 +717,14 @@ class CORE_EXPORT QgsMapLayer : public QObject
void setScaleBasedVisibility( const bool enabled );

/**
* Will advice the map canvas (and any other interested party) that this layer requires to be repainted.
* Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
* Will emit a repaintRequested() signal.
* If \a deferredUpdate is true then the layer will only be repainted when the canvas is next
* re-rendered, and will not trigger any canvas redraws itself.
*
* @note in 2.6 function moved from vector/raster subclasses to QgsMapLayer
*/
void triggerRepaint();
void triggerRepaint( bool deferredUpdate = false );

//! \brief Obtain Metadata for this layer
virtual QString metadata() const;
Expand Down Expand Up @@ -732,8 +773,10 @@ class CORE_EXPORT QgsMapLayer : public QObject

/** By emitting this signal the layer tells that either appearance or content have been changed
* and any view showing the rendered layer should refresh itself.
* If \a deferredUpdate is true then the layer will only be repainted when the canvas is next
* re-rendered, and will not trigger any canvas redraws itself.
*/
void repaintRequested();
void repaintRequested( bool deferredUpdate = false );

//! This is used to send a request that any mapcanvas using this layer update its extents
void recalculateExtents() const;
Expand Down Expand Up @@ -782,6 +825,13 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
void willBeDeleted();

/**
* Emitted when the auto refresh interval changes.
* @see setAutoRefreshInterval()
* @note added in QGIS 3.0
*/
void autoRefreshIntervalChanged( int interval );

protected:
//! Set the extent
virtual void setExtent( const QgsRectangle &rect );
Expand Down Expand Up @@ -916,6 +966,10 @@ class CORE_EXPORT QgsMapLayer : public QObject

//! Manager of multiple styles available for a layer (may be null)
QgsMapLayerStyleManager* mStyleManager;

//! Timer for triggering automatic refreshes of the layer
QTimer mRefreshTimer;

};

Q_DECLARE_METATYPE( QgsMapLayer* )
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsvectorlayer.cpp
Expand Up @@ -164,7 +164,7 @@ QgsVectorLayer::QgsVectorLayer( const QString& vectorLayerPath,
setDataSource( vectorLayerPath, baseName, providerKey, loadDefaultStyleFlag );
}

connect( this, &QgsVectorLayer::selectionChanged, this, &QgsVectorLayer::repaintRequested );
connect( this, &QgsVectorLayer::selectionChanged, this, [=] { emit repaintRequested(); } );
connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );

// Default simplify drawing settings
Expand Down

0 comments on commit f2ac60a

Please sign in to comment.