Skip to content

Commit

Permalink
Optionally load all stored styles from DB with correct names.
Browse files Browse the repository at this point in the history
Fixes #37434

Funded by: Ministère des Forêts, de la Faune et des Parcs - Québec
  • Loading branch information
elpaso committed Nov 7, 2022
1 parent b7a6082 commit 9c2923a
Show file tree
Hide file tree
Showing 24 changed files with 169 additions and 37 deletions.
11 changes: 7 additions & 4 deletions python/core/auto_generated/providers/qgsprovidermetadata.sip.in
Expand Up @@ -611,15 +611,18 @@ Loads a layer style defined by ``uri``
.. versionadded:: 3.10
%End

virtual QString loadStyle( const QString &uri, QString &name, QString &errCause );
virtual QString loadStoredStyle( const QString &uri, QString &styleName, QString &errCause );
%Docstring
Loads a layer style defined by ``uri``.
Loads a layer style from the provider storage, reporting its name.

:param name: the name of the style if available, empty otherwise.
:param providerKey: name of the data provider
:param uri: data source uri
:param styleName: the name of the style if available, empty otherwise
:param errCause: report errors

:return: the style QML (XML)

.. versionadded:: 3.28
.. versionadded:: 3.30
%End

virtual bool saveLayerMetadata( const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage /Out/ ) throw( QgsNotSupportedException );
Expand Down
11 changes: 7 additions & 4 deletions python/core/auto_generated/providers/qgsproviderregistry.sip.in
Expand Up @@ -253,15 +253,18 @@ Loads a layer style defined by ``uri``
.. versionadded:: 3.10
%End

QString loadStyle( const QString &providerKey, const QString &uri, QString &name, QString &errCause );
QString loadStoredStyle( const QString &providerKey, const QString &uri, QString &styleName, QString &errCause );
%Docstring
Loads a layer style defined by ``uri``.
Loads a layer style from the provider storage, reporting its name.

:param name: the name of the style if available, empty otherwise.
:param providerKey: name of the data provider
:param uri: data source uri
:param styleName: the name of the style if available, empty otherwise
:param errCause: report errors

:return: the style QML (XML)

.. versionadded:: 3.28
.. versionadded:: 3.30
%End

bool saveLayerMetadata( const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage /Out/ ) throw( QgsNotSupportedException );
Expand Down
Expand Up @@ -86,6 +86,8 @@ Constructor for LayerOptions with ``transformContext``.
QgsCoordinateTransformContext transformContext;

bool loadDefaultStyle;

bool loadAllStoredStyle;
};

QgsMapLayer *toLayer( const LayerOptions &options ) const /Factory/;
Expand Down
2 changes: 2 additions & 0 deletions python/core/auto_generated/qgsmaplayerfactory.sip.in
Expand Up @@ -54,6 +54,8 @@ Constructor for LayerOptions with ``transformContext``.
QgsCoordinateTransformContext transformContext;

bool loadDefaultStyle;

bool loadAllStoredStyles;
};

static QgsMapLayer *createLayer( const QString &uri, const QString &name, QgsMapLayerType type, const LayerOptions &options,
Expand Down
2 changes: 2 additions & 0 deletions python/core/auto_generated/vector/qgsvectorlayer.sip.in
Expand Up @@ -371,6 +371,8 @@ Constructor for LayerOptions.
bool skipCrsValidation;

bool forceReadOnly;

bool loadAllStoredStyles;
};

struct DeleteContext
Expand Down
1 change: 1 addition & 0 deletions src/app/layers/qgsapplayerhandling.cpp
Expand Up @@ -738,6 +738,7 @@ QList<QgsMapLayer *> QgsAppLayerHandling::addSublayers( const QList<QgsProviderS
{
QgsProviderSublayerDetails::LayerOptions options( QgsProject::instance()->transformContext() );
options.loadDefaultStyle = false;
options.loadAllStoredStyle = true;

std::unique_ptr<QgsMapLayer> layer( sublayer.toLayer( options ) );
if ( !layer )
Expand Down
12 changes: 6 additions & 6 deletions src/core/providers/ogr/qgsogrprovidermetadata.cpp
Expand Up @@ -675,10 +675,10 @@ bool LoadDataSourceLayerStylesAndLayer( const QString &uri,
QString QgsOgrProviderMetadata::loadStyle( const QString &uri, QString &errCause )
{
QString name;
return loadStyle( uri, name, errCause );
return loadStoredStyle( uri, name, errCause );
}

QString QgsOgrProviderMetadata::loadStyle( const QString &uri, QString &name, QString &errCause )
QString QgsOgrProviderMetadata::loadStoredStyle( const QString &uri, QString &styleName, QString &errCause )
{
QgsOgrLayerUniquePtr layerStyles;
QgsOgrLayerUniquePtr userLayer;
Expand Down Expand Up @@ -716,8 +716,8 @@ QString QgsOgrProviderMetadata::loadStyle( const QString &uri, QString &name, QS
{
styleQML = QString::fromUtf8(
OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, "styleQML" ) ) );
name = QString::fromUtf8(
OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, "styleName" ) ) );
styleName = QString::fromUtf8(
OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, "styleName" ) ) );
break;
}

Expand All @@ -731,8 +731,8 @@ QString QgsOgrProviderMetadata::loadStyle( const QString &uri, QString &name, QS
moreRecentTimestamp = ts;
styleQML = QString::fromUtf8(
OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, "styleQML" ) ) );
name = QString::fromUtf8(
OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, "styleName" ) ) );
styleName = QString::fromUtf8(
OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, "styleName" ) ) );
}
}
OGR_L_ResetReading( hLayer );
Expand Down
2 changes: 1 addition & 1 deletion src/core/providers/ogr/qgsogrprovidermetadata.h
Expand Up @@ -66,7 +66,7 @@ class QgsOgrProviderMetadata final: public QgsProviderMetadata
const QString &uiFileContent, bool useAsDefault, QString &errCause ) override;
bool deleteStyleById( const QString &uri, const QString &styleId, QString &errCause ) override;
QString loadStyle( const QString &uri, QString &errCause ) override;
QString loadStyle( const QString &uri, QString &name, QString &errCause ) override;
QString loadStoredStyle( const QString &uri, QString &name, QString &errCause ) override;
int listStyles( const QString &uri, QStringList &ids, QStringList &names,
QStringList &descriptions, QString &errCause ) override;
QString getStyleById( const QString &uri, const QString &styleId, QString &errCause ) override;
Expand Down
4 changes: 2 additions & 2 deletions src/core/providers/qgsprovidermetadata.cpp
Expand Up @@ -272,9 +272,9 @@ QString QgsProviderMetadata::loadStyle( const QString &, QString &errCause )
return QString();
}

QString QgsProviderMetadata::loadStyle( const QString &, QString &, QString &errCause )
QString QgsProviderMetadata::loadStoredStyle( const QString &, QString &, QString &errCause )
{
errCause = QObject::tr( "Provider %1 has no %2 method" ).arg( key(), QStringLiteral( "loadStyle" ) );
errCause = QObject::tr( "Provider %1 has no %2 method" ).arg( key(), QStringLiteral( "loadStoredStyle" ) );
return QString();
}

Expand Down
11 changes: 7 additions & 4 deletions src/core/providers/qgsprovidermetadata.h
Expand Up @@ -656,12 +656,15 @@ class CORE_EXPORT QgsProviderMetadata : public QObject
virtual QString loadStyle( const QString &uri, QString &errCause );

/**
* Loads a layer style defined by \a uri.
* \param name the name of the style if available, empty otherwise.
* Loads a layer style from the provider storage, reporting its name.
* \param providerKey name of the data provider
* \param uri data source uri
* \param styleName the name of the style if available, empty otherwise
* \param errCause report errors
* \returns the style QML (XML)
* \since QGIS 3.28
* \since QGIS 3.30
*/
virtual QString loadStyle( const QString &uri, QString &name, QString &errCause );
virtual QString loadStoredStyle( const QString &uri, QString &styleName, QString &errCause );

/**
* Saves \a metadata to the layer corresponding to the specified \a uri.
Expand Down
4 changes: 2 additions & 2 deletions src/core/providers/qgsproviderregistry.cpp
Expand Up @@ -707,12 +707,12 @@ QString QgsProviderRegistry::loadStyle( const QString &providerKey, const QStrin
return ret;
}

QString QgsProviderRegistry::loadStyle( const QString &providerKey, const QString &uri, QString &name, QString &errCause )
QString QgsProviderRegistry::loadStoredStyle( const QString &providerKey, const QString &uri, QString &styleName, QString &errCause )
{
QString ret;
QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
if ( meta )
ret = meta->loadStyle( uri, name, errCause );
ret = meta->loadStoredStyle( uri, styleName, errCause );
else
{
errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
Expand Down
11 changes: 7 additions & 4 deletions src/core/providers/qgsproviderregistry.h
Expand Up @@ -282,12 +282,15 @@ class CORE_EXPORT QgsProviderRegistry
QString loadStyle( const QString &providerKey, const QString &uri, QString &errCause );

/**
* Loads a layer style defined by \a uri.
* \param name the name of the style if available, empty otherwise.
* Loads a layer style from the provider storage, reporting its name.
* \param providerKey name of the data provider
* \param uri data source uri
* \param styleName the name of the style if available, empty otherwise
* \param errCause report errors
* \returns the style QML (XML)
* \since QGIS 3.28
* \since QGIS 3.30
*/
QString loadStyle( const QString &providerKey, const QString &uri, QString &name, QString &errCause );
QString loadStoredStyle( const QString &providerKey, const QString &uri, QString &styleName, QString &errCause );

/**
* Saves \a metadata to the layer corresponding to the specified \a uri.
Expand Down
1 change: 1 addition & 0 deletions src/core/providers/qgsprovidersublayerdetails.cpp
Expand Up @@ -23,6 +23,7 @@ QgsMapLayer *QgsProviderSublayerDetails::toLayer( const LayerOptions &options )
{
QgsMapLayerFactory::LayerOptions layerOptions( options.transformContext );
layerOptions.loadDefaultStyle = options.loadDefaultStyle;
layerOptions.loadAllStoredStyles = options.loadAllStoredStyle;
return QgsMapLayerFactory::createLayer( mUri, mName, mType, layerOptions, mProviderKey );
}

Expand Down
14 changes: 14 additions & 0 deletions src/core/providers/qgsprovidersublayerdetails.h
Expand Up @@ -106,6 +106,20 @@ class CORE_EXPORT QgsProviderSublayerDetails

//! Set to TRUE if the default layer style should be loaded
bool loadDefaultStyle = true;

/**
* Controls whether the stored styles will be all loaded.
*
* If TRUE and the layer's provider supports style stored in the
* data source all the available styles will be loaded in addition
* to the default one.
*
* If FALSE (the default), the layer's provider will only load
* the default style.
*
* \since QGIS 3.30
*/
bool loadAllStoredStyle = false;
};

/**
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsmaplayerfactory.cpp
Expand Up @@ -81,6 +81,7 @@ QgsMapLayer *QgsMapLayerFactory::createLayer( const QString &uri, const QString
QgsVectorLayer::LayerOptions vectorOptions;
vectorOptions.transformContext = options.transformContext;
vectorOptions.loadDefaultStyle = options.loadDefaultStyle;
vectorOptions.loadAllStoredStyles = options.loadAllStoredStyles;
return new QgsVectorLayer( uri, name, provider, vectorOptions );
}

Expand Down
14 changes: 14 additions & 0 deletions src/core/qgsmaplayerfactory.h
Expand Up @@ -73,6 +73,20 @@ class CORE_EXPORT QgsMapLayerFactory

//! Set to TRUE if the default layer style should be loaded
bool loadDefaultStyle = true;

/**
* Controls whether the stored styles will be all loaded.
*
* If TRUE and the layer's provider supports style stored in the
* data source all the available styles will be loaded in addition
* to the default one.
*
* If FALSE (the default), the layer's provider will only load
* the default style.
*
* \since QGIS 3.30
*/
bool loadAllStoredStyles = false;
};

/**
Expand Down
45 changes: 42 additions & 3 deletions src/core/vector/qgsvectorlayer.cpp
Expand Up @@ -160,6 +160,7 @@ QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
, mRefreshRendererTimer( new QTimer( this ) )
{
mShouldValidateCrs = !options.skipCrsValidation;
mLoadAllStoredStyle = options.loadAllStoredStyles;

if ( options.fallbackCrs.isValid() )
setCrs( options.fallbackCrs, false );
Expand Down Expand Up @@ -1756,9 +1757,45 @@ void QgsVectorLayer::setDataSourcePrivate( const QString &dataSource, const QStr
QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
{
// first try to load a user-defined default style - this should always take precedence
QString res = QgsMapLayer::loadDefaultStyle( resultFlag );
QString styleXml = QgsMapLayer::loadDefaultStyle( resultFlag );

if ( resultFlag )
return res;
{
// Try to load all stored styles
if ( mLoadAllStoredStyle )
{
QStringList ids, names, descriptions;
QString errorMessage;
listStylesInDatabase( ids, names, descriptions, errorMessage );
if ( ids.count() == names.count() )
{
const QString currentStyleName { mStyleManager->currentStyle() };
for ( int i = 0; i < ids.count(); ++i )
{
if ( names.at( i ) == currentStyleName )
{
continue;
}
errorMessage.clear();
const QString styleXml { getStyleFromDatabase( ids.at( i ), errorMessage ) };
if ( ! styleXml.isEmpty() && errorMessage.isEmpty() )
{
mStyleManager->addStyle( names.at( i ), QgsMapLayerStyle( styleXml ) );
}
else
{
QgsDebugMsgLevel( QStringLiteral( "Error retrieving style %1 from DB: %2" ).arg( ids.at( i ), errorMessage ), 2 );
}
}
}
else
{
// Something is wery wrong!
QgsDebugMsg( "Number of ids and names differs after fetching styles from DB!" );
}
}
return styleXml ;
}

if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
{
Expand Down Expand Up @@ -5563,8 +5600,10 @@ QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag,
QString styleName;
if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
{
qml = QgsProviderRegistry::instance()->loadStyle( mProviderKey, mDataSource, styleName, errorMsg );
qml = QgsProviderRegistry::instance()->loadStoredStyle( mProviderKey, mDataSource, styleName, errorMsg );
}

// Style was successfully loaded from provider storage
if ( !qml.isEmpty() )
{
QDomDocument myDocument( QStringLiteral( "qgis" ) );
Expand Down
20 changes: 20 additions & 0 deletions src/core/vector/qgsvectorlayer.h
Expand Up @@ -498,6 +498,20 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* \since QGIS 3.28
*/
bool forceReadOnly = false;

/**
* Controls whether the stored styles will be all loaded.
*
* If TRUE and the layer's provider supports style stored in the
* data source all the available styles will be loaded in addition
* to the default one.
*
* If FALSE (the default), the layer's provider will only load
* the default style.
*
* \since QGIS 3.30
*/
bool loadAllStoredStyles = false;
};

/**
Expand Down Expand Up @@ -3062,6 +3076,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte

//! Timer for triggering automatic redraw of the layer based on feature renderer settings (e.g. animated symbols)
QTimer *mRefreshRendererTimer = nullptr;

/**
* Stores the value from LayerOptions.loadAllStoredStyles
*/
bool mLoadAllStoredStyle = false;

};


Expand Down
11 changes: 9 additions & 2 deletions src/providers/mssql/qgsmssqlprovider.cpp
Expand Up @@ -2736,6 +2736,12 @@ bool QgsMssqlProviderMetadata::saveStyle( const QString &uri,
}

QString QgsMssqlProviderMetadata::loadStyle( const QString &uri, QString &errCause )
{
QString styleName;
return loadStoredStyle( uri, styleName, errCause );
}

QString QgsMssqlProviderMetadata::loadStoredStyle( const QString &uri, QString &styleName, QString &errCause )
{
errCause.clear();
const QgsDataSourceUri dsUri( uri );
Expand Down Expand Up @@ -2772,7 +2778,7 @@ QString QgsMssqlProviderMetadata::loadStyle( const QString &uri, QString &errCau
query.clear();
query.setForwardOnly( true );

const QString selectQmlQuery = QString( "SELECT top 1 styleQML"
const QString selectQmlQuery = QString( "SELECT top 1 styleName, styleQML"
" FROM layer_styles"
" WHERE f_table_catalog=%1"
" AND f_table_schema=%2"
Expand All @@ -2794,7 +2800,8 @@ QString QgsMssqlProviderMetadata::loadStyle( const QString &uri, QString &errCau
}
if ( query.isActive() && query.next() )
{
QString style = query.value( 0 ).toString();
styleName = query.value( 0 ).toString();
const QString style = query.value( 1 ).toString();
return style;
}
return QString();
Expand Down
1 change: 1 addition & 0 deletions src/providers/mssql/qgsmssqlprovider.h
Expand Up @@ -303,6 +303,7 @@ class QgsMssqlProviderMetadata final: public QgsProviderMetadata
QString getStyleById( const QString &uri, const QString &styleId, QString &errCause ) override;
int listStyles( const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause ) override;
QString loadStyle( const QString &uri, QString &errCause ) override;
QString loadStoredStyle( const QString &uri, QString &styleName, QString &errCause ) override;
bool styleExists( const QString &uri, const QString &styleId, QString &errorCause ) override;
bool saveStyle( const QString &uri, const QString &qmlStyle, const QString &sldStyle,
const QString &styleName, const QString &styleDescription,
Expand Down

0 comments on commit 9c2923a

Please sign in to comment.