mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-05 00:09:32 -04:00
Address PR review comments and add model tests
This commit is contained in:
parent
5a32a7558d
commit
7cab873eac
@ -146,7 +146,7 @@ Returns icon for point cloud layer
|
||||
const QgsLayerMetadata &layerMetadata() const;
|
||||
%Docstring
|
||||
Returns layer's metadata, it may be a default constructed metadata
|
||||
if metadata are not explicitly set.
|
||||
if metadata is not explicitly set.
|
||||
|
||||
.. versionadded:: 3.28
|
||||
%End
|
||||
|
@ -121,10 +121,6 @@ Returns the metadata standard URI (usually "http://mrcc.com/qgis.dtd")
|
||||
Sets the metadata standard URI to ``standardUri``.
|
||||
%End
|
||||
|
||||
QIcon layerTypeIcon() const;
|
||||
%Docstring
|
||||
Returns the icon for the layer type.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
@ -182,6 +178,8 @@ Layer metadata provider backend interface.
|
||||
%End
|
||||
public:
|
||||
|
||||
virtual ~QgsAbstractLayerMetadataProvider();
|
||||
|
||||
virtual QString id() const = 0;
|
||||
%Docstring
|
||||
Returns the id of the layer metadata provider implementation, usually the name of the data provider
|
||||
@ -200,8 +198,6 @@ Searches for metadata optionally filtering by search string and geographic exten
|
||||
:return: a :py:class:`QgsLayerMetadataSearchResult` object with a list of metadata and errors
|
||||
%End
|
||||
|
||||
virtual ~QgsAbstractLayerMetadataProvider();
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
@ -115,8 +115,6 @@ Constructor for Constraint.
|
||||
Constructor for QgsLayerMetadata.
|
||||
%End
|
||||
|
||||
~QgsLayerMetadata( );
|
||||
|
||||
QgsLayerMetadata( const QgsLayerMetadata &other );
|
||||
%Docstring
|
||||
Copy constructor for :py:class:`QgsLayerMetadataProviderResult` from ``other``.
|
||||
|
@ -25,6 +25,12 @@ Contains utility functions for working with icons.
|
||||
static QIcon iconForWkbType( QgsWkbTypes::Type type );
|
||||
%Docstring
|
||||
Returns the icon for a vector layer whose geometry ``type`` is provided.
|
||||
%End
|
||||
|
||||
static QIcon iconForGeometryType( QgsWkbTypes::GeometryType typeGroup );
|
||||
%Docstring
|
||||
Returns the icon for a vector layer whose geometry ``typeGroup`` is provided.
|
||||
1since QGIS 3.28
|
||||
%End
|
||||
|
||||
static QIcon iconPoint();
|
||||
|
@ -20,6 +20,9 @@ This class provides common functionality and the interface for all
|
||||
source select dialogs used by data providers to configure data sources
|
||||
and add layers.
|
||||
|
||||
The implementation is generic enough to handle other layer search and
|
||||
selection widgets.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
@ -28,6 +28,7 @@ This is the interface for those who want to add entries to the :py:class:`QgsDat
|
||||
OrderDatabaseProvider,
|
||||
OrderRemoteProvider,
|
||||
OrderGeoCmsProvider,
|
||||
OrderSearchProvider,
|
||||
OrderOtherProvider,
|
||||
};
|
||||
|
||||
|
@ -105,6 +105,7 @@
|
||||
%Include auto_generated/qgslayermetadatasearchwidget.sip
|
||||
%Include auto_generated/qgslayermetadataresultsmodel.sip
|
||||
%Include auto_generated/qgslayermetadataresultsproxymodel.sip
|
||||
%Include auto_generated/qgslayermetadatasourceselectprovider.sip
|
||||
%Include auto_generated/qgslegendfilterbutton.sip
|
||||
%Include auto_generated/qgslegendpatchshapebutton.sip
|
||||
%Include auto_generated/qgslegendpatchshapewidget.sip
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "qgsfeedback.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgisapp.h"
|
||||
#include "qgsiconutils.h"
|
||||
#include <QIcon>
|
||||
|
||||
QgsLayerMetadataLocatorFilter::QgsLayerMetadataLocatorFilter( QObject *parent )
|
||||
: QgsLocatorFilter( parent )
|
||||
@ -44,7 +46,7 @@ void QgsLayerMetadataLocatorFilter::fetchResults( const QString &string, const Q
|
||||
QgsLocatorResult result;
|
||||
result.displayString = metadata.identifier();
|
||||
result.description = metadata.title();
|
||||
result.icon = metadata.layerTypeIcon();
|
||||
result.icon = QgsIconUtils::iconForGeometryType( metadata.geometryType() );
|
||||
result.userData = QVariant::fromValue( metadata );
|
||||
emit resultFetched( result );
|
||||
}
|
||||
@ -69,6 +71,7 @@ void QgsLayerMetadataLocatorFilter::triggerResult( const QgsLocatorResult &resul
|
||||
case QgsMapLayerType::MeshLayer:
|
||||
{
|
||||
QgisApp::instance()->addMeshLayer( metadataResult.uri(), metadataResult.identifier(), metadataResult.dataProviderName() );
|
||||
break;
|
||||
}
|
||||
default: // unsupported
|
||||
{
|
||||
|
@ -145,7 +145,7 @@ class CORE_EXPORT QgsLayerItem : public QgsDataItem
|
||||
|
||||
/**
|
||||
* Returns layer's metadata, it may be a default constructed metadata
|
||||
* if metadata are not explicitly set.
|
||||
* if metadata is not explicitly set.
|
||||
* \since QGIS 3.28
|
||||
*/
|
||||
const QgsLayerMetadata &layerMetadata() const;
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include "qgsprovidermetadata.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsfeedback.h"
|
||||
#include "qgsiconutils.h"
|
||||
#include <QIcon>
|
||||
|
||||
QList<QgsLayerMetadataProviderResult> QgsLayerMetadataSearchResults::metadata() const
|
||||
{
|
||||
@ -118,24 +116,4 @@ void QgsLayerMetadataProviderResult::setStandardUri( const QString &standardUri
|
||||
mStandardUri = standardUri;
|
||||
}
|
||||
|
||||
QIcon QgsLayerMetadataProviderResult::layerTypeIcon() const
|
||||
{
|
||||
if ( layerType() == QgsMapLayerType::VectorLayer )
|
||||
{
|
||||
switch ( geometryType() )
|
||||
{
|
||||
case QgsWkbTypes::NullGeometry:
|
||||
return QgsIconUtils::iconTable();
|
||||
case QgsWkbTypes::PointGeometry:
|
||||
return QgsIconUtils::iconPoint();
|
||||
case QgsWkbTypes::LineGeometry:
|
||||
return QgsIconUtils::iconLine();
|
||||
case QgsWkbTypes::PolygonGeometry:
|
||||
return QgsIconUtils::iconPolygon();
|
||||
default:
|
||||
return QgsIconUtils::iconDefaultLayer();
|
||||
}
|
||||
}
|
||||
return QgsIconUtils::iconForLayerType( layerType() );
|
||||
}
|
||||
|
||||
|
@ -142,10 +142,6 @@ class CORE_EXPORT QgsLayerMetadataProviderResult: public QgsLayerMetadata
|
||||
*/
|
||||
void setStandardUri( const QString &standardUri );
|
||||
|
||||
/**
|
||||
* Returns the icon for the layer type.
|
||||
*/
|
||||
QIcon layerTypeIcon() const;
|
||||
|
||||
private:
|
||||
|
||||
@ -223,6 +219,8 @@ class CORE_EXPORT QgsAbstractLayerMetadataProvider
|
||||
|
||||
public:
|
||||
|
||||
virtual ~QgsAbstractLayerMetadataProvider() = default;
|
||||
|
||||
/**
|
||||
* Returns the id of the layer metadata provider implementation, usually the name of the data provider
|
||||
* but it may be another unique identifier.
|
||||
@ -239,8 +237,6 @@ class CORE_EXPORT QgsAbstractLayerMetadataProvider
|
||||
*/
|
||||
virtual QgsLayerMetadataSearchResults search( const QgsMetadataSearchContext &searchContext, const QString &searchString = QString(), const QgsRectangle &geographicExtent = QgsRectangle(), QgsFeedback *feedback = nullptr ) const = 0;
|
||||
|
||||
virtual ~QgsAbstractLayerMetadataProvider() = default;
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSABSTRACTLAYERMETADATAPROVIDER_H
|
||||
|
@ -428,11 +428,6 @@ bool QgsLayerMetadata::operator==( const QgsLayerMetadata &other ) const
|
||||
|
||||
bool QgsLayerMetadata::contains( const QString &searchString ) const
|
||||
{
|
||||
if ( searchString.isEmpty() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( title().contains( searchString, Qt::CaseInsensitive ) ||
|
||||
identifier().contains( searchString, Qt::CaseInsensitive ) ||
|
||||
abstract().contains( searchString, Qt::CaseInsensitive ) )
|
||||
|
@ -172,11 +172,6 @@ class CORE_EXPORT QgsLayerMetadata : public QgsAbstractMetadataBase
|
||||
*/
|
||||
QgsLayerMetadata() = default;
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~QgsLayerMetadata( ) = default;
|
||||
|
||||
/**
|
||||
* Copy constructor for QgsLayerMetadataProviderResult from \a other.
|
||||
* \since QGIS 3.28
|
||||
|
@ -25,7 +25,12 @@
|
||||
QIcon QgsIconUtils::iconForWkbType( QgsWkbTypes::Type type )
|
||||
{
|
||||
const QgsWkbTypes::GeometryType geomType = QgsWkbTypes::geometryType( QgsWkbTypes::Type( type ) );
|
||||
switch ( geomType )
|
||||
return iconForGeometryType( geomType );
|
||||
}
|
||||
|
||||
QIcon QgsIconUtils::iconForGeometryType( QgsWkbTypes::GeometryType typeGroup )
|
||||
{
|
||||
switch ( typeGroup )
|
||||
{
|
||||
case QgsWkbTypes::NullGeometry:
|
||||
return iconTable();
|
||||
|
@ -40,6 +40,12 @@ class CORE_EXPORT QgsIconUtils
|
||||
*/
|
||||
static QIcon iconForWkbType( QgsWkbTypes::Type type );
|
||||
|
||||
/**
|
||||
* Returns the icon for a vector layer whose geometry \a typeGroup is provided.
|
||||
* 1since QGIS 3.28
|
||||
*/
|
||||
static QIcon iconForGeometryType( QgsWkbTypes::GeometryType typeGroup );
|
||||
|
||||
/**
|
||||
* Returns an icon representing point geometries.
|
||||
*/
|
||||
|
@ -530,6 +530,7 @@ set(QGIS_GUI_SRCS
|
||||
qgskeyvaluewidget.cpp
|
||||
qgslayermetadatasearchwidget.cpp
|
||||
qgslayermetadataresultsmodel.cpp
|
||||
qgslayermetadatasourceselectprovider.cpp
|
||||
qgslayermetadataresultsproxymodel.cpp
|
||||
qgslistwidget.cpp
|
||||
qgslegendfilterbutton.cpp
|
||||
@ -795,6 +796,7 @@ set(QGIS_GUI_HDRS
|
||||
qgslayermetadatasearchwidget.h
|
||||
qgslayermetadataresultsmodel.h
|
||||
qgslayermetadataresultsproxymodel.h
|
||||
qgslayermetadatasourceselectprovider.h
|
||||
qgslegendfilterbutton.h
|
||||
qgslegendpatchshapebutton.h
|
||||
qgslegendpatchshapewidget.h
|
||||
|
@ -38,6 +38,10 @@ class QgsBrowserModel;
|
||||
* This class provides common functionality and the interface for all
|
||||
* source select dialogs used by data providers to configure data sources
|
||||
* and add layers.
|
||||
*
|
||||
* The implementation is generic enough to handle other layer search and
|
||||
* selection widgets.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class GUI_EXPORT QgsAbstractDataSourceWidget : public QDialog
|
||||
|
@ -67,43 +67,7 @@ QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QgsBrowserGuiModel *brow
|
||||
connect( mBrowserWidget, &QgsBrowserDockWidget::connectionsChanged, this, &QgsDataSourceManagerDialog::connectionsChanged );
|
||||
connect( this, &QgsDataSourceManagerDialog::updateProjectHome, mBrowserWidget->browserWidget(), &QgsBrowserWidget::updateProjectHome );
|
||||
|
||||
// METADATA Add the metadata search widget as the second stacked widget
|
||||
mLayerMetadataSearchWidget = new QgsLayerMetadataSearchWidget( mMapCanvas, this );
|
||||
connect( mLayerMetadataSearchWidget, &QgsLayerMetadataSearchWidget::rejected, this, &QgsDataSourceManagerDialog::reject );
|
||||
ui->mOptionsStackedWidget->addWidget( mLayerMetadataSearchWidget );
|
||||
mPageNames.append( QStringLiteral( "metadata" ) );
|
||||
|
||||
connect( mLayerMetadataSearchWidget, &QgsLayerMetadataSearchWidget::addLayers, this, [ = ]( const QList< QgsLayerMetadataProviderResult > &metadataResults )
|
||||
{
|
||||
for ( const QgsLayerMetadataProviderResult &metadata : std::as_const( metadataResults ) )
|
||||
{
|
||||
switch ( metadata.layerType() )
|
||||
{
|
||||
case QgsMapLayerType::VectorLayer:
|
||||
{
|
||||
emit addVectorLayer( metadata.uri(), metadata.identifier(), metadata.dataProviderName() );
|
||||
break;
|
||||
};
|
||||
case QgsMapLayerType::RasterLayer:
|
||||
{
|
||||
emit addRasterLayer( metadata.uri(), metadata.identifier(), metadata.dataProviderName() );
|
||||
break;
|
||||
}
|
||||
case QgsMapLayerType::MeshLayer:
|
||||
{
|
||||
emit addMeshLayer( metadata.uri(), metadata.identifier(), metadata.dataProviderName() );
|
||||
break;
|
||||
}
|
||||
default: // Unsupported!
|
||||
{
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Add provider dialogs
|
||||
// Add registered source select dialogs
|
||||
const QList<QgsSourceSelectProvider *> sourceSelectProviders = QgsGui::sourceSelectProviderRegistry()->providers( );
|
||||
for ( QgsSourceSelectProvider *provider : sourceSelectProviders )
|
||||
{
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "qgsmaptoolshaperegistry.h"
|
||||
#include "qgssettingsregistrygui.h"
|
||||
#include "qgshistoryproviderregistry.h"
|
||||
#include "qgslayermetadatasourceselectprovider.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QToolButton>
|
||||
@ -293,6 +294,7 @@ QgsGui::QgsGui()
|
||||
mProjectStorageGuiRegistry->initializeFromProviderGuiRegistry( mProviderGuiRegistry );
|
||||
mDataItemGuiProviderRegistry->initializeFromProviderGuiRegistry( mProviderGuiRegistry );
|
||||
mSourceSelectProviderRegistry->initializeFromProviderGuiRegistry( mProviderGuiRegistry );
|
||||
mSourceSelectProviderRegistry->addProvider( new QgsLayerMetadataSourceSelectProvider() );
|
||||
mSubsetStringEditorProviderRegistry->initializeFromProviderGuiRegistry( mProviderGuiRegistry );
|
||||
mProviderSourceWidgetProviderRegistry->initializeFromProviderGuiRegistry( mProviderGuiRegistry );
|
||||
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslayermetadataproviderregistry.h"
|
||||
#include "qgslayermetadataformatter.h"
|
||||
#include "qgsiconutils.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsprovidermetadata.h"
|
||||
#include <QIcon>
|
||||
|
||||
QgsLayerMetadataResultsModel::QgsLayerMetadataResultsModel( const QgsMetadataSearchContext &searchContext, QObject *parent )
|
||||
@ -60,7 +63,11 @@ QVariant QgsLayerMetadataResultsModel::data( const QModelIndex &index, int role
|
||||
case Sections::Abstract:
|
||||
return mResult.metadata().at( index.row() ).abstract();
|
||||
case Sections::DataProviderName:
|
||||
return mResult.metadata().at( index.row() ).dataProviderName();
|
||||
{
|
||||
const QString providerName { mResult.metadata().at( index.row() ).dataProviderName() };
|
||||
QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerName ) };
|
||||
return md ? md->description() : providerName;
|
||||
}
|
||||
case Sections::GeometryType:
|
||||
return QgsWkbTypes::geometryDisplayString( mResult.metadata().at( index.row() ).geometryType() );
|
||||
default:
|
||||
@ -80,7 +87,7 @@ QVariant QgsLayerMetadataResultsModel::data( const QModelIndex &index, int role
|
||||
{
|
||||
if ( index.column() == 0 )
|
||||
{
|
||||
return mResult.metadata().at( index.row() ).layerTypeIcon();
|
||||
return QgsIconUtils::iconForGeometryType( mResult.metadata().at( index.row() ).geometryType() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -20,18 +20,20 @@
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsprojectviewsettings.h"
|
||||
|
||||
QgsLayerMetadataSearchWidget::QgsLayerMetadataSearchWidget( const QgsMapCanvas *mapCanvas, QWidget *parent )
|
||||
: QWidget( parent )
|
||||
, mMapCanvas( mapCanvas )
|
||||
|
||||
QgsLayerMetadataSearchWidget::QgsLayerMetadataSearchWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
|
||||
: QgsAbstractDataSourceWidget( parent, fl, widgetMode )
|
||||
{
|
||||
|
||||
setupUi( this );
|
||||
setupButtons( mButtonBox );
|
||||
|
||||
QgsMetadataSearchContext searchContext;
|
||||
searchContext.transformContext = QgsProject::instance()->transformContext();
|
||||
|
||||
QgsLayerMetadataResultsModel *sourceModel = new QgsLayerMetadataResultsModel( searchContext, this );
|
||||
mSourceModel = new QgsLayerMetadataResultsModel( searchContext, this );
|
||||
mProxyModel = new QgsLayerMetadataResultsProxyModel( this );
|
||||
mProxyModel->setSourceModel( sourceModel );
|
||||
mProxyModel->setSourceModel( mSourceModel );
|
||||
mMetadataTableView->setModel( mProxyModel );
|
||||
mMetadataTableView->setSortingEnabled( true );
|
||||
mMetadataTableView->sortByColumn( 0, Qt::SortOrder::AscendingOrder );
|
||||
@ -61,8 +63,8 @@ QgsLayerMetadataSearchWidget::QgsLayerMetadataSearchWidget( const QgsMapCanvas *
|
||||
}
|
||||
};
|
||||
|
||||
connect( sourceModel, &QgsLayerMetadataResultsModel::progressChanged, mProgressBar, &QProgressBar::setValue );
|
||||
connect( sourceModel, &QgsLayerMetadataResultsModel::progressChanged, this, [ = ]( int progress )
|
||||
connect( mSourceModel, &QgsLayerMetadataResultsModel::progressChanged, mProgressBar, &QProgressBar::setValue );
|
||||
connect( mSourceModel, &QgsLayerMetadataResultsModel::progressChanged, this, [ = ]( int progress )
|
||||
{
|
||||
if ( progress == 100 )
|
||||
{
|
||||
@ -71,66 +73,29 @@ QgsLayerMetadataSearchWidget::QgsLayerMetadataSearchWidget( const QgsMapCanvas *
|
||||
}
|
||||
} );
|
||||
|
||||
connect( mAbortPushButton, &QPushButton::clicked, sourceModel, [ = ]( bool )
|
||||
connect( mAbortPushButton, &QPushButton::clicked, mSourceModel, [ = ]( bool )
|
||||
{
|
||||
if ( ! mIsLoading )
|
||||
{
|
||||
mIsLoading = true;
|
||||
sourceModel->reloadAsync( );
|
||||
mSourceModel->reloadAsync( );
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceModel->cancel();
|
||||
mSourceModel->cancel();
|
||||
mIsLoading = false;
|
||||
}
|
||||
updateLoadBtn();
|
||||
} );
|
||||
|
||||
|
||||
// Setup buttons
|
||||
mButtonBox->setStandardButtons( QDialogButtonBox::Apply | QDialogButtonBox::Close | QDialogButtonBox::Help );
|
||||
#ifdef Q_OS_MACX
|
||||
mButtonBox->setStyleSheet( "* { button-layout: 2 }" );
|
||||
#endif
|
||||
mAddButton = mButtonBox->button( QDialogButtonBox::Apply );
|
||||
mAddButton->setText( tr( "&Add" ) );
|
||||
mAddButton->setToolTip( tr( "Add selected layers to map" ) );
|
||||
mAddButton->setEnabled( false );
|
||||
connect( mAddButton, &QPushButton::clicked, this, [ = ]( bool )
|
||||
{
|
||||
const QModelIndexList &selectedIndexes { mMetadataTableView->selectionModel()->selectedRows() };
|
||||
if ( ! selectedIndexes.isEmpty() )
|
||||
{
|
||||
QList< QgsLayerMetadataProviderResult > layersToAdd;
|
||||
for ( const auto &selectedIndex : std::as_const( selectedIndexes ) )
|
||||
{
|
||||
layersToAdd.push_back( sourceModel->data( mProxyModel->mapToSource( selectedIndex ), QgsLayerMetadataResultsModel::Roles::Metadata ).value<QgsLayerMetadataProviderResult>() );
|
||||
}
|
||||
emit addLayers( layersToAdd );
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
connect( mMetadataTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [ = ]( const QItemSelection &, const QItemSelection & )
|
||||
{
|
||||
mAddButton->setEnabled( mMetadataTableView->selectionModel()->hasSelection() );
|
||||
emit enableButtons( mMetadataTableView->selectionModel()->hasSelection() );
|
||||
} );
|
||||
|
||||
QPushButton *closeButton = mButtonBox->button( QDialogButtonBox::Close );
|
||||
closeButton->setToolTip( tr( "Close this dialog without adding any layer" ) );
|
||||
connect( closeButton, &QPushButton::clicked, this, &QgsLayerMetadataSearchWidget::rejected );
|
||||
|
||||
connect( mSearchFilterLineEdit, &QLineEdit::textEdited, mProxyModel, &QgsLayerMetadataResultsProxyModel::setFilterString );
|
||||
connect( mExtentFilterComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsLayerMetadataSearchWidget::updateExtentFilter );
|
||||
|
||||
if ( mMapCanvas )
|
||||
{
|
||||
connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, [ = ]
|
||||
{
|
||||
updateExtentFilter( mExtentFilterComboBox->currentIndex() );
|
||||
} );
|
||||
}
|
||||
|
||||
connect( QgsProject::instance(), &QgsProject::layersAdded, this, [ = ]( const QList<QgsMapLayer *> & )
|
||||
{
|
||||
updateExtentFilter( mExtentFilterComboBox->currentIndex() );
|
||||
@ -142,18 +107,30 @@ QgsLayerMetadataSearchWidget::QgsLayerMetadataSearchWidget( const QgsMapCanvas *
|
||||
} );
|
||||
|
||||
// Start loading metadata in the model
|
||||
sourceModel->reloadAsync();
|
||||
mSourceModel->reloadAsync();
|
||||
mIsLoading = true;
|
||||
|
||||
}
|
||||
|
||||
void QgsLayerMetadataSearchWidget::setMapCanvas( QgsMapCanvas *newMapCanvas )
|
||||
{
|
||||
if ( newMapCanvas && mapCanvas() != newMapCanvas )
|
||||
{
|
||||
connect( newMapCanvas, &QgsMapCanvas::extentsChanged, this, [ = ]
|
||||
{
|
||||
updateExtentFilter( mExtentFilterComboBox->currentIndex() );
|
||||
} );
|
||||
}
|
||||
QgsAbstractDataSourceWidget::setMapCanvas( newMapCanvas );
|
||||
}
|
||||
|
||||
void QgsLayerMetadataSearchWidget::updateExtentFilter( int index )
|
||||
{
|
||||
if ( index == 1 && mMapCanvas )
|
||||
if ( index == 1 && mapCanvas() )
|
||||
{
|
||||
QgsCoordinateTransform ct( mMapCanvas->mapSettings().destinationCrs(), QgsCoordinateReferenceSystem::fromEpsgId( 4326 ), QgsProject::instance()->transformContext() );
|
||||
QgsCoordinateTransform ct( mapCanvas()->mapSettings().destinationCrs(), QgsCoordinateReferenceSystem::fromEpsgId( 4326 ), QgsProject::instance()->transformContext() );
|
||||
ct.setBallparkTransformsAreAppropriate( true );
|
||||
mProxyModel->setFilterExtent( ct.transformBoundingBox( mMapCanvas->extent() ) );
|
||||
mProxyModel->setFilterExtent( ct.transformBoundingBox( mapCanvas()->extent() ) );
|
||||
}
|
||||
else if ( index == 2 )
|
||||
{
|
||||
@ -167,3 +144,48 @@ void QgsLayerMetadataSearchWidget::updateExtentFilter( int index )
|
||||
mProxyModel->setFilterExtent( QgsRectangle( ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayerMetadataSearchWidget::refresh()
|
||||
{
|
||||
mSourceModel->reloadAsync();
|
||||
}
|
||||
|
||||
void QgsLayerMetadataSearchWidget::addButtonClicked()
|
||||
{
|
||||
const QModelIndexList &selectedIndexes { mMetadataTableView->selectionModel()->selectedRows() };
|
||||
if ( ! selectedIndexes.isEmpty() )
|
||||
{
|
||||
for ( const auto &selectedIndex : std::as_const( selectedIndexes ) )
|
||||
{
|
||||
const QgsLayerMetadataProviderResult metadataResult { mSourceModel->data( mProxyModel->mapToSource( selectedIndex ), QgsLayerMetadataResultsModel::Roles::Metadata ).value<QgsLayerMetadataProviderResult>() };
|
||||
switch ( metadataResult.layerType() )
|
||||
{
|
||||
case QgsMapLayerType::RasterLayer:
|
||||
{
|
||||
emit addRasterLayer( metadataResult.uri(), metadataResult.identifier(), metadataResult.dataProviderName() );
|
||||
break;
|
||||
}
|
||||
case QgsMapLayerType::VectorLayer:
|
||||
{
|
||||
emit addVectorLayer( metadataResult.uri(), metadataResult.identifier(), metadataResult.dataProviderName() );
|
||||
break;
|
||||
}
|
||||
case QgsMapLayerType::MeshLayer:
|
||||
{
|
||||
emit addMeshLayer( metadataResult.uri(), metadataResult.identifier(), metadataResult.dataProviderName() );
|
||||
}
|
||||
default: // unsupported
|
||||
{
|
||||
// Ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLayerMetadataSearchWidget::reset()
|
||||
{
|
||||
mSearchFilterLineEdit->clear();
|
||||
mExtentFilterComboBox->setCurrentIndex( 0 );
|
||||
}
|
||||
|
@ -21,9 +21,11 @@
|
||||
#include "ui_qgslayermetadatasearchwidget.h"
|
||||
#include "qgsfeedback.h"
|
||||
#include "qgsabstractlayermetadataprovider.h"
|
||||
#include "qgsabstractdatasourcewidget.h"
|
||||
|
||||
class QgsMapCanvas;
|
||||
class QgsLayerMetadataResultsProxyModel;
|
||||
class QgsLayerMetadataResultsModel;
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
@ -31,7 +33,7 @@ class QgsLayerMetadataResultsProxyModel;
|
||||
* It is designed to be embedded in the data source manager dialog.
|
||||
* \since QGIS 3.28
|
||||
*/
|
||||
class GUI_EXPORT QgsLayerMetadataSearchWidget : public QWidget, private Ui::QgsLayerMetadataSearchWidget
|
||||
class GUI_EXPORT QgsLayerMetadataSearchWidget : public QgsAbstractDataSourceWidget, private Ui::QgsLayerMetadataSearchWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -41,28 +43,24 @@ class GUI_EXPORT QgsLayerMetadataSearchWidget : public QWidget, private Ui::QgsL
|
||||
* \param mapCanvas optional map canvas
|
||||
* \param parent optional parent
|
||||
*/
|
||||
explicit QgsLayerMetadataSearchWidget( const QgsMapCanvas *mapCanvas = nullptr, QWidget *parent = nullptr );
|
||||
explicit QgsLayerMetadataSearchWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::WindowFlags(), QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::None );
|
||||
|
||||
signals:
|
||||
|
||||
//! Emitted when the close button is clicked.
|
||||
void rejected();
|
||||
|
||||
//! Emitted when layers have been selected for addition
|
||||
void addLayers( const QList< QgsLayerMetadataProviderResult > &metadataResults );
|
||||
void setMapCanvas( QgsMapCanvas *mapCanvas ) override;
|
||||
|
||||
public slots:
|
||||
|
||||
//! Updates the extent filter based on the combo box current item \a index.
|
||||
void updateExtentFilter( int index );
|
||||
|
||||
void refresh() override;
|
||||
void addButtonClicked() override;
|
||||
void reset() override;
|
||||
|
||||
private:
|
||||
|
||||
const QgsMapCanvas *mMapCanvas = nullptr;
|
||||
QgsLayerMetadataResultsProxyModel *mProxyModel = nullptr;
|
||||
bool mIsLoading = false;
|
||||
QPushButton *mAddButton = nullptr;
|
||||
|
||||
QgsLayerMetadataResultsModel *mSourceModel = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
50
src/gui/qgslayermetadatasourceselectprovider.cpp
Normal file
50
src/gui/qgslayermetadatasourceselectprovider.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/***************************************************************************
|
||||
qgslayermetadatasourceselectprovider.cpp - QgsLayerMetadataSourceSelectProvider
|
||||
|
||||
---------------------
|
||||
begin : 6.9.2022
|
||||
copyright : (C) 2022 by Alessandro Pasotti
|
||||
email : elpaso at itopen dot it
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgslayermetadatasourceselectprovider.h"
|
||||
#include "qgslayermetadatasearchwidget.h"
|
||||
#include "qgsapplication.h"
|
||||
|
||||
QgsLayerMetadataSourceSelectProvider::QgsLayerMetadataSourceSelectProvider()
|
||||
: QgsSourceSelectProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString QgsLayerMetadataSourceSelectProvider::providerKey() const
|
||||
{
|
||||
return QStringLiteral( "layermetadata" );
|
||||
|
||||
}
|
||||
|
||||
QString QgsLayerMetadataSourceSelectProvider::text() const
|
||||
{
|
||||
return QObject::tr( "Layer Metadata" );
|
||||
}
|
||||
|
||||
QIcon QgsLayerMetadataSourceSelectProvider::icon() const
|
||||
{
|
||||
return QgsApplication::getThemeIcon( QStringLiteral( "search.svg" ) );
|
||||
}
|
||||
|
||||
QgsAbstractDataSourceWidget *QgsLayerMetadataSourceSelectProvider::createDataSourceWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode ) const
|
||||
{
|
||||
return new QgsLayerMetadataSearchWidget( parent, fl, widgetMode );
|
||||
}
|
||||
|
||||
int QgsLayerMetadataSourceSelectProvider::ordering() const
|
||||
{
|
||||
return OrderSearchProvider;
|
||||
}
|
43
src/gui/qgslayermetadatasourceselectprovider.h
Normal file
43
src/gui/qgslayermetadatasourceselectprovider.h
Normal file
@ -0,0 +1,43 @@
|
||||
/***************************************************************************
|
||||
qgslayermetadatasourceselectprovider.h - QgsLayerMetadataSourceSelectProvider
|
||||
|
||||
---------------------
|
||||
begin : 6.9.2022
|
||||
copyright : (C) 2022 by Alessandro Pasotti
|
||||
email : elpaso at itopen dot it
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSLAYERMETADATASOURCESELECTPROVIDER_H
|
||||
#define QGSLAYERMETADATASOURCESELECTPROVIDER_H
|
||||
|
||||
#include "qgssourceselectprovider.h"
|
||||
#include "qgis_gui.h"
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \brief Source select provider for layer metadata.
|
||||
*
|
||||
* \since QGIS 3.28
|
||||
*/
|
||||
class GUI_EXPORT QgsLayerMetadataSourceSelectProvider : public QgsSourceSelectProvider
|
||||
{
|
||||
|
||||
public:
|
||||
QgsLayerMetadataSourceSelectProvider();
|
||||
|
||||
// QgsSourceSelectProvider interface
|
||||
public:
|
||||
QString providerKey() const override;
|
||||
QString text() const override;
|
||||
QIcon icon() const override;
|
||||
QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode ) const override;
|
||||
int ordering() const override;
|
||||
};
|
||||
|
||||
#endif // QGSLAYERMETADATASOURCESELECTPROVIDER_H
|
@ -43,7 +43,8 @@ class GUI_EXPORT QgsSourceSelectProvider
|
||||
OrderDatabaseProvider = 1000, //!< Starting point for database providers (e.g. Postgres)
|
||||
OrderRemoteProvider = 2000, //!< Starting point for remote (online) providers (e.g. WMS)
|
||||
OrderGeoCmsProvider = 3000, //!< Starting point for GeoCMS type providers (e.g. GeoNode)
|
||||
OrderOtherProvider = 4000, //!< Starting point for other providers (e.g. plugin based providers)
|
||||
OrderSearchProvider = 4000, //!< Starting point for search providers (e.g. Layer Metadata)
|
||||
OrderOtherProvider = 5000, //!< Starting point for other providers (e.g. plugin based providers)
|
||||
};
|
||||
|
||||
virtual ~QgsSourceSelectProvider() = default;
|
||||
|
@ -116,15 +116,6 @@
|
||||
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Metadata</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/propertyicons/metadata.svg</normaloff>:/images/themes/default/propertyicons/metadata.svg</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -24,7 +24,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mSearchFilterLineEdit"/>
|
||||
<widget class="QgsFilterLineEdit" name="mSearchFilterLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
@ -74,12 +74,19 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="mButtonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::Help</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsFilterLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>qgsfilterlineedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -145,6 +145,7 @@ ADD_PYTHON_TEST(PyQgsLabelThinningSettings test_qgslabelthinningsettings.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerMetadata test_qgslayermetadata.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerMetadataProviderPython test_qgslayermetadataprovider_python.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerMetadataProviderOgr test_qgslayermetadataprovider_ogr.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerMetadataResultsModel test_qgslayermetadataresultsmodel.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerTreeMapCanvasBridge test_qgslayertreemapcanvasbridge.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerTree test_qgslayertree.py)
|
||||
ADD_PYTHON_TEST(PyQgsLayerTreeView test_qgslayertreeview.py)
|
||||
|
130
tests/src/python/test_qgslayermetadataresultsmodel.py
Normal file
130
tests/src/python/test_qgslayermetadataresultsmodel.py
Normal file
@ -0,0 +1,130 @@
|
||||
# coding=utf-8
|
||||
""""Base test for layer metadata models
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
"""
|
||||
|
||||
__author__ = 'elpaso@itopen.it'
|
||||
__date__ = '2022-08-19'
|
||||
__copyright__ = 'Copyright 2022, ItOpen'
|
||||
|
||||
import os
|
||||
from osgeo import ogr
|
||||
|
||||
from qgis.core import (
|
||||
QgsVectorLayer,
|
||||
QgsProviderRegistry,
|
||||
QgsWkbTypes,
|
||||
QgsLayerMetadata,
|
||||
QgsProviderMetadata,
|
||||
QgsBox3d,
|
||||
QgsRectangle,
|
||||
QgsMetadataSearchContext,
|
||||
)
|
||||
|
||||
from qgis.gui import (
|
||||
QgsLayerMetadataResultsModel,
|
||||
QgsLayerMetadataResultsProxyModel,
|
||||
)
|
||||
|
||||
from qgis.PyQt.QtTest import QAbstractItemModelTester
|
||||
|
||||
from qgis.PyQt.QtCore import QCoreApplication, QTemporaryDir, QVariant, Qt
|
||||
from utilities import compareWkt, unitTestDataPath
|
||||
from qgis.testing import start_app, TestCase
|
||||
import unittest
|
||||
|
||||
QGIS_APP = start_app()
|
||||
NUM_LAYERS = 20
|
||||
|
||||
|
||||
class TestQgsLayerMetadataResultModels(TestCase):
|
||||
"""Base test for layer metadata provider models
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Run before all tests"""
|
||||
|
||||
QCoreApplication.setOrganizationName("QGIS_Test")
|
||||
QCoreApplication.setOrganizationDomain(cls.__name__)
|
||||
QCoreApplication.setApplicationName(cls.__name__)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
self.temp_dir = QTemporaryDir()
|
||||
self.temp_path = self.temp_dir.path()
|
||||
self.temp_gpkg = os.path.join(self.temp_path, 'test.gpkg')
|
||||
|
||||
ds = ogr.GetDriverByName('GPKG').CreateDataSource(self.temp_gpkg)
|
||||
|
||||
md = QgsProviderRegistry.instance().providerMetadata('ogr')
|
||||
self.assertIsNotNone(md)
|
||||
self.assertTrue(bool(md.providerCapabilities() & QgsProviderMetadata.ProviderCapability.SaveLayerMetadata))
|
||||
self.conn = md.createConnection(self.temp_gpkg, {})
|
||||
self.conn.store('test_conn')
|
||||
|
||||
for i in range(NUM_LAYERS):
|
||||
lyr = ds.CreateLayer("layer_%s" % i, geom_type=ogr.wkbPoint, options=['SPATIAL_INDEX=NO'])
|
||||
lyr.CreateField(ogr.FieldDefn('text_field', ogr.OFTString))
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f['text_field'] = 'foo'
|
||||
f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(%s %s)' % (i, i + 0.01)))
|
||||
lyr.CreateFeature(f)
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f['text_field'] = 'bar'
|
||||
f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(%s %s)' % (i + 0.03, i + 0.04)))
|
||||
lyr.CreateFeature(f)
|
||||
f = None
|
||||
|
||||
ds = None
|
||||
|
||||
for t in self.conn.tables():
|
||||
layer_uri = self.conn.tableUri('', t.tableName())
|
||||
vl = QgsVectorLayer(layer_uri, t.tableName(), 'ogr')
|
||||
self.assertTrue(vl.isValid())
|
||||
metadata = vl.metadata()
|
||||
ext = QgsLayerMetadata.Extent()
|
||||
spatial_ext = QgsLayerMetadata.SpatialExtent()
|
||||
spatial_ext.bounds = QgsBox3d(vl.extent())
|
||||
spatial_ext.crs = vl.crs()
|
||||
ext.setSpatialExtents([spatial_ext])
|
||||
metadata.setExtent(ext)
|
||||
metadata.setIdentifier(t.tableName())
|
||||
self.assertTrue(md.saveLayerMetadata(layer_uri, metadata)[0])
|
||||
|
||||
def testModels(self):
|
||||
|
||||
search_context = QgsMetadataSearchContext()
|
||||
model = QgsLayerMetadataResultsModel(search_context)
|
||||
proxy_model = QgsLayerMetadataResultsProxyModel()
|
||||
proxy_model.setSourceModel(model)
|
||||
tester = QAbstractItemModelTester(proxy_model, QAbstractItemModelTester.FailureReportingMode.Fatal)
|
||||
model.reload()
|
||||
proxy_model.setFilterString('_1')
|
||||
self.assertEqual(proxy_model.rowCount(), 11)
|
||||
proxy_model.setFilterString('_11')
|
||||
self.assertEqual(proxy_model.rowCount(), 1)
|
||||
metadata = proxy_model.data(proxy_model.index(0, 0), QgsLayerMetadataResultsModel.Roles.Metadata)
|
||||
self.assertEqual(metadata.identifier(), 'layer_11')
|
||||
proxy_model.setFilterString('')
|
||||
self.assertEqual(proxy_model.rowCount(), 20)
|
||||
proxy_model.setFilterExtent(QgsRectangle(0, 0, 2, 2.001))
|
||||
self.assertEqual(proxy_model.rowCount(), 2)
|
||||
model.reload()
|
||||
self.assertEqual(proxy_model.rowCount(), 2)
|
||||
proxy_model.setFilterExtent(QgsRectangle())
|
||||
metadata = proxy_model.data(proxy_model.index(0, 0), QgsLayerMetadataResultsModel.Roles.Metadata)
|
||||
self.assertEqual(metadata.identifier(), 'layer_0')
|
||||
proxy_model.sort(0, Qt.DescendingOrder)
|
||||
metadata = proxy_model.data(proxy_model.index(0, 0), QgsLayerMetadataResultsModel.Roles.Metadata)
|
||||
self.assertEqual(metadata.identifier(), 'layer_9')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user