Skip to content
Permalink
Browse files

PG raster set subset signals and app

  • Loading branch information
elpaso committed Mar 4, 2020
1 parent d6821a9 commit 71b9b76788c51fbcf19a82f8ac0186538ddc1fad
@@ -332,6 +332,28 @@ Set contrast enhancement algorithm



virtual QString subsetString() const;
%Docstring
Returns the string (typically sql) used to define a subset of the layer.

:return: The subset string or null QString if not implemented by the provider

.. versionadded:: 3.10
%End

virtual bool setSubsetString( const QString &subset );
%Docstring
Sets the string (typically sql) used to define a subset of the layer

:param subset: The subset string. This may be the where clause of a sql statement
or other definition string specific to the underlying dataprovider
and data store.

:return: ``True``, when setting the subset string was successful, ``False`` otherwise

.. versionadded:: 3.10
%End


void setDefaultContrastEnhancement();
%Docstring
@@ -398,6 +420,16 @@ Sets the coordinate transform context to ``transformContext``
.. versionadded:: 3.8
%End

signals:

void subsetStringChanged();
%Docstring
Emitted when the layer's subset string has changed.

.. versionadded:: 3.10
%End


protected:
virtual bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories );

@@ -10483,7 +10483,50 @@ void QgisApp::layerSubsetString()
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( activeLayer() );
if ( !vlayer )
{
// Try PG raster
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( activeLayer() );
if ( rlayer )
{
QgsRasterDataProvider *provider = rlayer->dataProvider();
if ( provider &&
provider->supportsSubsetString() )
{
// PG raster is the only one for now
if ( provider->name() == QStringLiteral( "postgresraster" ) )
{
// We need a vector for the sql editor
QgsDataSourceUri vectorUri { provider->dataSourceUri() };
vectorUri.setGeometryColumn( QString() );
vectorUri.setSrid( QString() );
QgsVectorLayer vlayer { vectorUri.uri( ), QStringLiteral( "pgrasterlayer" ), QStringLiteral( "postgres" ) };
if ( vlayer.isValid( ) )
{
// launch the query builder
QgsQueryBuilder qb { &vlayer };
QString subsetBefore = vlayer.subsetString();

// Set the sql in the query builder to the same in the prop dialog
// (in case the user has already changed it)
qb.setSql( rlayer->subsetString() );
// Open the query builder and refresh symbology if sql has changed
// Note: repaintRequested is emitted directly from QgsQueryBuilder
// when the sql is set in the layer.
if ( qb.exec() && ( subsetBefore != qb.sql() ) && mLayerTreeView )
{
if ( rlayer->setSubsetString( qb.sql() ) )
{
mLayerTreeView->refreshLayerSymbology( rlayer->id() );
activateDeactivateLayerRelatedActions( rlayer );
}
}
}
}
}
}
return;
}


bool joins = !vlayer->vectorJoins().isEmpty();
if ( vlayer->vectorJoins().size() == 1 )
@@ -253,6 +253,14 @@ QMenu *QgsAppLayerTreeViewMenuProvider::createContextMenu()
}
}

// PG raster: activate filter
if ( rlayer &&
rlayer->dataProvider() &&
rlayer->dataProvider()->supportsSubsetString() )
{
menu->addAction( tr( "&Filter…" ), QgisApp::instance(), &QgisApp::layerSubsetString );
}

// change data source is only supported for vectors and rasters
if ( vlayer || rlayer )
{
@@ -21,6 +21,7 @@
#include "qgslayertreeview.h"
#include "qgsquerybuilder.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"


QgsLayerTreeViewFilterIndicatorProvider::QgsLayerTreeViewFilterIndicatorProvider( QgsLayerTreeView *view )
@@ -35,14 +36,41 @@ void QgsLayerTreeViewFilterIndicatorProvider::onIndicatorClicked( const QModelIn
return;

QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( QgsLayerTree::toLayer( node )->layer() );
if ( !vlayer || vlayer->isEditable() )
return;
if ( vlayer && !vlayer->isEditable() )
{
QgsQueryBuilder qb( vlayer );
qb.setSql( vlayer->subsetString() );
if ( qb.exec() )
vlayer->setSubsetString( qb.sql() );
}

// raster
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( QgsLayerTree::toLayer( node )->layer() );
if ( rlayer && rlayer->dataProvider() && rlayer->dataProvider()->supportsSubsetString() )
{
// PG raster is the only one for now
if ( rlayer->dataProvider()->name() == QStringLiteral( "postgresraster" ) )
{
QgsDataSourceUri vectorUri { rlayer->dataProvider()->dataSourceUri() };
vectorUri.setGeometryColumn( QString() );
vectorUri.setSrid( QString() );
QgsVectorLayer vlayer { vectorUri.uri( ), QStringLiteral( "pgrasterlayer" ), QStringLiteral( "postgres" ) };
if ( vlayer.isValid( ) )
{
// launch the query builder
QgsQueryBuilder qb { &vlayer };
QString subsetBefore = vlayer.subsetString();

// launch the query builder
QgsQueryBuilder qb( vlayer );
qb.setSql( vlayer->subsetString() );
if ( qb.exec() )
vlayer->setSubsetString( qb.sql() );
// Set the sql in the query builder to the same in the prop dialog
// (in case the user has already changed it)
qb.setSql( rlayer->subsetString() );
if ( qb.exec() && subsetBefore != qb.sql() )
{
rlayer->setSubsetString( qb.sql() );
}
}
}
}
}

QString QgsLayerTreeViewFilterIndicatorProvider::iconName( QgsMapLayer *layer )
@@ -54,34 +82,55 @@ QString QgsLayerTreeViewFilterIndicatorProvider::iconName( QgsMapLayer *layer )
QString QgsLayerTreeViewFilterIndicatorProvider::tooltipText( QgsMapLayer *layer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return QString();
return QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), vlayer->subsetString().toHtmlEscaped() );
if ( vlayer )
return QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), vlayer->subsetString().toHtmlEscaped() );

// PG raster
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
if ( rlayer && rlayer->dataProvider() && rlayer->dataProvider()->supportsSubsetString() )
return QStringLiteral( "<b>%1:</b><br>%2" ).arg( tr( "Filter" ), rlayer->subsetString().toHtmlEscaped() );

return QString();
}

void QgsLayerTreeViewFilterIndicatorProvider::connectSignals( QgsMapLayer *layer )
{
QgsLayerTreeViewIndicatorProvider::connectSignals( layer );
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
if ( vlayer )
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );

// PG raster
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
if ( rlayer && rlayer->dataProvider() && rlayer->dataProvider()->supportsSubsetString() )
connect( rlayer, &QgsRasterLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );

}

void QgsLayerTreeViewFilterIndicatorProvider::disconnectSignals( QgsMapLayer *layer )
{
QgsLayerTreeViewIndicatorProvider::disconnectSignals( layer );
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
if ( vlayer )
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );

// PG raster
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
if ( rlayer && rlayer->dataProvider() && rlayer->dataProvider()->supportsSubsetString() )
disconnect( rlayer, &QgsRasterLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onLayerChanged );
}

bool QgsLayerTreeViewFilterIndicatorProvider::acceptLayer( QgsMapLayer *layer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return false;
return ! vlayer->subsetString().isEmpty();
if ( vlayer )
return ! vlayer->subsetString().isEmpty();

// PG raster
QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( layer );
if ( rlayer && rlayer->dataProvider() && rlayer->dataProvider()->supportsSubsetString() )
return ! rlayer->subsetString().isEmpty();

return false;
}

@@ -1229,6 +1229,52 @@ void QgsRasterLayer::refreshRendererIfNeeded( QgsRasterRenderer *rasterRenderer,
}
}

QString QgsRasterLayer::subsetString() const
{
if ( !mValid || !mDataProvider )
{
QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
return customProperty( QStringLiteral( "storedSubsetString" ) ).toString();
}
if ( !mDataProvider->supportsSubsetString() )
{
return QString();
}
return mDataProvider->subsetString();
}

bool QgsRasterLayer::setSubsetString( const QString &subset )
{
if ( !mValid || !mDataProvider )
{
QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
setCustomProperty( QStringLiteral( "storedSubsetString" ), subset );
return false;
}

if ( !mDataProvider->supportsSubsetString() )
{
return false;
}

if ( subset == mDataProvider->subsetString() )
return true;

bool res = mDataProvider->setSubsetString( subset );

// get the updated data source string from the provider
mDataSource = mDataProvider->dataSourceUri();


if ( res )
{
emit subsetStringChanged();
triggerRepaint();
}

return res;
}

bool QgsRasterLayer::defaultContrastEnhancementSettings(
QgsContrastEnhancement::ContrastEnhancementAlgorithm &myAlgorithm,
QgsRasterMinMaxOrigin::Limits &myLimits ) const
@@ -384,6 +384,23 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
*/
void refreshRendererIfNeeded( QgsRasterRenderer *rasterRenderer, const QgsRectangle &extent ) SIP_SKIP;

/**
* Returns the string (typically sql) used to define a subset of the layer.
* \returns The subset string or null QString if not implemented by the provider
* \since QGIS 3.10
*/
virtual QString subsetString() const;

/**
* Sets the string (typically sql) used to define a subset of the layer
* \param subset The subset string. This may be the where clause of a sql statement
* or other definition string specific to the underlying dataprovider
* and data store.
* \returns TRUE, when setting the subset string was successful, FALSE otherwise
* \since QGIS 3.10
*/
virtual bool setSubsetString( const QString &subset );

/**
* Returns default contrast enhancement settings for that type of raster.
* \note not available in Python bindings
@@ -444,6 +461,15 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
*/
virtual void setTransformContext( const QgsCoordinateTransformContext &transformContext ) override;

signals:

/**
* Emitted when the layer's subset string has changed.
* \since QGIS 3.10
*/
void subsetStringChanged();


protected:
bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ) override;
bool readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories = QgsMapLayer::AllStyleCategories ) override;
@@ -685,6 +685,28 @@ QgsPostgresConn *QgsPostgresRasterProvider::connectionRW()
return mConnectionRW;
}

QString QgsPostgresRasterProvider::subsetString() const
{
return mSqlWhereClause;
}

bool QgsPostgresRasterProvider::setSubsetString( const QString &subset, bool updateFeatureCount )
{
Q_UNUSED( updateFeatureCount )
const QString oldSql { mSqlWhereClause };
mSqlWhereClause = subset;
// Recalculate extent and other metadata calling init()
if ( !init() )
{
// Restore
mSqlWhereClause = oldSql;
init();
return false;
}
mShared->invalidateCache();
return true;
}

void QgsPostgresRasterProvider::disconnectDb()
{
if ( mConnectionRO )
@@ -152,6 +152,11 @@ class QgsPostgresRasterProvider : public QgsRasterDataProvider
QgsPostgresConn *connectionRO() const;
QgsPostgresConn *connectionRW();

bool supportsSubsetString() const override { return true; }

virtual QString subsetString() const override;
virtual bool setSubsetString( const QString &subset, bool updateFeatureCount = true ) override;

bool hasSufficientPermsAndCapabilities();
void disconnectDb();
//! Initialize the raster by fetching metadata and creating spatial indexes.
@@ -176,6 +176,14 @@ QgsPostgresRasterSharedData::TilesResponse QgsPostgresRasterSharedData::tiles( c
return result;
}

void QgsPostgresRasterSharedData::invalidateCache()
{
QMutexLocker locker( &mMutex );
mSpatialIndexes.clear();
mTiles.clear();
mLoadedIndexBounds.clear();
}


QgsPostgresRasterSharedData::Tile const *QgsPostgresRasterSharedData::setTileData( unsigned int overviewFactor, TileIdType tileId, const QByteArray &data )
{
@@ -92,6 +92,11 @@ class QgsPostgresRasterSharedData
*/
TilesResponse tiles( const TilesRequest &request );

/**
* Invalidate the cache, for example when case the subset string changes
*/
void invalidateCache();

private:

//! Protect access to tiles

0 comments on commit 71b9b76

Please sign in to comment.
You can’t perform that action at this time.