Skip to content

Commit

Permalink
Add a QgsProviderMetadata:suggestGroupNameForUri() method and impleme…
Browse files Browse the repository at this point in the history
…nt it for WFS to have WFS sublayers put in a group
  • Loading branch information
rouault committed Jan 3, 2023
1 parent 8dc2608 commit 541da34
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 19 deletions.
10 changes: 10 additions & 0 deletions python/core/auto_generated/providers/qgsprovidermetadata.sip.in
Expand Up @@ -394,6 +394,16 @@ The optional ``feedback`` argument can be used to provide cancellation support f
different providers).

.. versionadded:: 3.22
%End

virtual QString suggestGroupNameForUri( const QString &uri ) const;
%Docstring
Returns a name that can be used as a group name for sublayers got from
the specified ``uri``.

The default implementation returns an empty string.

.. versionadded:: 3.30
%End

virtual QgsDataProvider *createProvider( const QString &uri,
Expand Down
6 changes: 6 additions & 0 deletions python/gui/auto_generated/qgsprovidersublayersdialog.sip.in
Expand Up @@ -56,6 +56,7 @@ Dialog for selecting provider sublayers.
public:

QgsProviderSublayersDialog( const QString &uri,
const QString &providerKey,
const QString &filePath,
const QList< QgsProviderSublayerDetails> initialDetails = QList< QgsProviderSublayerDetails>(),
const QList< QgsMapLayerType > &acceptableTypes = QList< QgsMapLayerType >(),
Expand Down Expand Up @@ -85,6 +86,11 @@ Returns the list of selected non-layer items (e.g. embedded QGIS project items).
QString groupName() const;
%Docstring
Returns an appropriate name for the layer group.
%End

void setGroupName( const QString &groupNameIn );
%Docstring
Sets an appropriate name for the layer group.
%End

signals:
Expand Down
12 changes: 8 additions & 4 deletions src/app/layers/qgsapplayerhandling.cpp
Expand Up @@ -1337,15 +1337,16 @@ T *QgsAppLayerHandling::addLayerPrivate( QgsMapLayerType type, const QString &ur
// Not all providers implement decodeUri(), so use original uri if uriElements is empty
const QString updatedUri = uriElements.isEmpty() ? uri : QgsProviderRegistry::instance()->encodeUri( providerKey, uriElements );

const bool canQuerySublayers = QgsProviderRegistry::instance()->providerMetadata( providerKey ) &&
( QgsProviderRegistry::instance()->providerMetadata( providerKey )->capabilities() & QgsProviderMetadata::QuerySublayers );
QgsProviderMetadata *providerMetadata = QgsProviderRegistry::instance()->providerMetadata( providerKey );
const bool canQuerySublayers = providerMetadata &&
( providerMetadata->capabilities() & QgsProviderMetadata::QuerySublayers );

T *result = nullptr;
if ( canQuerySublayers )
{
// query sublayers
QList< QgsProviderSublayerDetails > sublayers = QgsProviderRegistry::instance()->providerMetadata( providerKey ) ?
QgsProviderRegistry::instance()->providerMetadata( providerKey )->querySublayers( updatedUri, Qgis::SublayerQueryFlag::IncludeSystemTables )
QList< QgsProviderSublayerDetails > sublayers = providerMetadata ?
providerMetadata->querySublayers( updatedUri, Qgis::SublayerQueryFlag::IncludeSystemTables )
: QgsProviderRegistry::instance()->querySublayers( updatedUri );

// filter out non-matching sublayers
Expand Down Expand Up @@ -1373,6 +1374,9 @@ T *QgsAppLayerHandling::addLayerPrivate( QgsMapLayerType type, const QString &ur
case SublayerHandling::AskUser:
{
QgsProviderSublayersDialog dlg( updatedUri, path, sublayers, {type}, QgisApp::instance() );
QString groupName = providerMetadata->suggestGroupNameForUri( uri );
if ( !groupName.isEmpty() )
dlg.setGroupName( groupName );
if ( dlg.exec() )
{
const QList< QgsProviderSublayerDetails > selectedLayers = dlg.selectedLayers();
Expand Down
5 changes: 5 additions & 0 deletions src/core/providers/qgsprovidermetadata.cpp
Expand Up @@ -77,6 +77,11 @@ QString QgsProviderMetadata::library() const
return mLibrary;
}

QString QgsProviderMetadata::suggestGroupNameForUri( const QString & /*uri*/ ) const
{
return QString();
}

QgsProviderMetadata::CreateDataProviderFunction QgsProviderMetadata::createFunction() const
{
return mCreateFunction;
Expand Down
10 changes: 10 additions & 0 deletions src/core/providers/qgsprovidermetadata.h
Expand Up @@ -457,6 +457,16 @@ class CORE_EXPORT QgsProviderMetadata : public QObject
*/
virtual QList< QgsProviderSublayerDetails > querySublayers( const QString &uri, Qgis::SublayerQueryFlags flags = Qgis::SublayerQueryFlags(), QgsFeedback *feedback = nullptr ) const;

/**
* Returns a name that can be used as a group name for sublayers got from
* the specified \a uri.
*
* The default implementation returns an empty string.
*
* \since QGIS 3.30
*/
virtual QString suggestGroupNameForUri( const QString &uri ) const;

/**
* Class factory to return a pointer to a newly created QgsDataProvider object
*
Expand Down
43 changes: 29 additions & 14 deletions src/gui/qgsprovidersublayersdialog.cpp
Expand Up @@ -111,21 +111,31 @@ void QgsProviderSublayerDialogModel::setGeometryTypesResolved( bool resolved )
emit dataChanged( index( 0, 0 ), index( rowCount( QModelIndex() ), columnCount() ) );
}

QgsProviderSublayersDialog::QgsProviderSublayersDialog( const QString &uri, const QString &filePath, const QList<QgsProviderSublayerDetails> initialDetails, const QList<QgsMapLayerType> &acceptableTypes, QWidget *parent, Qt::WindowFlags fl )
QgsProviderSublayersDialog::QgsProviderSublayersDialog( const QString &uri, const QString &filePathIn, const QList<QgsProviderSublayerDetails> initialDetails, const QList<QgsMapLayerType> &acceptableTypes, QWidget *parent, Qt::WindowFlags fl )
: QDialog( parent, fl )
{
setupUi( this );
QgsGui::enableAutoGeometryRestore( this );

const QFileInfo fileInfo( filePath );
mFilePath = ( fileInfo.isFile() || fileInfo.isDir() ) && fileInfo.exists() ? filePath : QString();
const QString fileName = !mFilePath.isEmpty() ? QgsProviderUtils::suggestLayerNameFromFilePath( mFilePath ) : QString();
const QFileInfo fileInfo( filePathIn );
const QString filePath = ( fileInfo.isFile() || fileInfo.isDir() ) && fileInfo.exists() ? filePathIn : QString();
const QString fileName = !filePath.isEmpty() ? QgsProviderUtils::suggestLayerNameFromFilePath( filePath ) : QString();

if ( !fileName.isEmpty() )
{
mGroupName = fileName;
const QgsSettings settings;
if ( settings.value( QStringLiteral( "qgis/formatLayerName" ), false ).toBool() )
{
mGroupName = QgsMapLayer::formatLayerName( mGroupName );
}
}

setWindowTitle( fileName.isEmpty() ? tr( "Select Items to Add" ) : QStringLiteral( "%1 | %2" ).arg( tr( "Select Items to Add" ), fileName ) );

mLblFilePath->setText( QStringLiteral( "<a href=\"%1\">%2</a>" )
.arg( QUrl::fromLocalFile( mFilePath ).toString(), QDir::toNativeSeparators( QFileInfo( mFilePath ).canonicalFilePath() ) ) );
mLblFilePath->setVisible( !mFilePath.isEmpty() );
.arg( QUrl::fromLocalFile( filePath ).toString(), QDir::toNativeSeparators( QFileInfo( filePath ).canonicalFilePath() ) ) );
mLblFilePath->setVisible( !filePath.isEmpty() );
mLblFilePath->setWordWrap( true );
mLblFilePath->setTextInteractionFlags( Qt::TextBrowserInteraction );
connect( mLblFilePath, &QLabel::linkActivated, this, [ = ]( const QString & link )
Expand All @@ -149,6 +159,7 @@ QgsProviderSublayersDialog::QgsProviderSublayersDialog( const QString &uri, cons
const QgsSettings settings;
const bool addToGroup = settings.value( QStringLiteral( "/qgis/openSublayersInGroup" ), false ).toBool();
mCbxAddToGroup->setChecked( addToGroup );
mCbxAddToGroup->setVisible( !fileName.isEmpty() );

// resize columns
const QByteArray ba = settings.value( "/Windows/SubLayers/headerState" ).toByteArray();
Expand Down Expand Up @@ -262,19 +273,23 @@ QList<QgsProviderSublayerModel::NonLayerItem> QgsProviderSublayersDialog::select
return selectedItems;
}

QString QgsProviderSublayersDialog::groupName() const
void QgsProviderSublayersDialog::setGroupName( const QString &groupNameIn )
{
if ( !mCbxAddToGroup->isChecked() )
return QString();

QString res = QgsProviderUtils::suggestLayerNameFromFilePath( mFilePath );

mGroupName = groupNameIn;
const QgsSettings settings;
if ( settings.value( QStringLiteral( "qgis/formatLayerName" ), false ).toBool() )
{
res = QgsMapLayer::formatLayerName( res );
mGroupName = QgsMapLayer::formatLayerName( mGroupName );
}
return res;

mCbxAddToGroup->setVisible( !mGroupName.isEmpty() );
}

QString QgsProviderSublayersDialog::groupName() const
{
if ( !mCbxAddToGroup->isChecked() )
return QString();
return mGroupName;
}

void QgsProviderSublayersDialog::treeSelectionChanged( const QItemSelection &selected, const QItemSelection & )
Expand Down
7 changes: 6 additions & 1 deletion src/gui/qgsprovidersublayersdialog.h
Expand Up @@ -106,6 +106,11 @@ class GUI_EXPORT QgsProviderSublayersDialog : public QDialog, private Ui::QgsPro
*/
QString groupName() const;

/**
* Sets an appropriate name for the layer group.
*/
void setGroupName( const QString &groupNameIn );

signals:

/**
Expand All @@ -122,7 +127,7 @@ class GUI_EXPORT QgsProviderSublayersDialog : public QDialog, private Ui::QgsPro
QgsProviderSublayerDialogModel *mModel = nullptr;
QgsProviderSublayerProxyModel *mProxyModel = nullptr;
QPointer< QgsProviderSublayerTask > mTask;
QString mFilePath;
QString mGroupName;
bool mBlockSelectionChanges = false;

};
Expand Down
7 changes: 7 additions & 0 deletions src/providers/wfs/qgswfsprovidermetadata.cpp
Expand Up @@ -179,6 +179,13 @@ QString QgsWFSProvider::buildGeometryCollectionFilter( const QgsWfsCapabilities:
return doc.toString();
}

QString QgsWfsProviderMetadata::suggestGroupNameForUri( const QString &uri ) const
{
QgsWFSDataSourceURI wfsUri( uri );
return wfsUri.typeName();
}


QList<QgsProviderSublayerDetails> QgsWfsProviderMetadata::querySublayers( const QString &uri, Qgis::SublayerQueryFlags flags, QgsFeedback *feedback ) const
{
QList<QgsProviderSublayerDetails> res;
Expand Down
1 change: 1 addition & 0 deletions src/providers/wfs/qgswfsprovidermetadata.h
Expand Up @@ -35,6 +35,7 @@ class QgsWfsProviderMetadata final: public QgsProviderMetadata
QList< QgsMapLayerType > supportedLayerTypes() const override;
QgsProviderMetadata::ProviderMetadataCapabilities capabilities() const override;
QList< QgsProviderSublayerDetails > querySublayers( const QString &uri, Qgis::SublayerQueryFlags flags = Qgis::SublayerQueryFlags(), QgsFeedback *feedback = nullptr ) const override;
QString suggestGroupNameForUri( const QString &uri ) const override;
};

#endif // QGSWFSPROVIDERMETADATA_H

0 comments on commit 541da34

Please sign in to comment.