QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgslayermetadataresultsmodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayermetadataresultsmodel.cpp - QgsLayerMetadataResultsModel
3
4 ---------------------
5 begin : 1.9.2022
6 copyright : (C) 2022 by ale
7 email : [your-email-here]
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
17
18#include "qgsapplication.h"
19#include "qgsfeedback.h"
20#include "qgsiconutils.h"
23#include "qgsprovidermetadata.h"
24#include "qgsproviderregistry.h"
25
26#include <QIcon>
27
28#include "moc_qgslayermetadataresultsmodel.cpp"
29
30QgsLayerMetadataResultsModel::QgsLayerMetadataResultsModel( const QgsMetadataSearchContext &searchContext, QObject *parent )
31 : QAbstractTableModel( parent )
32 , mSearchContext( searchContext )
33{
34 qRegisterMetaType<QgsLayerMetadataSearchResults>( "QgsLayerMetadataSearchResults" );
35 qRegisterMetaType<QgsLayerMetadataProviderResult>( "QgsLayerMetadataProviderResult" );
36}
37
38QgsLayerMetadataResultsModel::~QgsLayerMetadataResultsModel()
39{
40 cancel();
41}
42
43int QgsLayerMetadataResultsModel::rowCount( const QModelIndex &parent ) const
44{
45 return parent.isValid() ? 0 : mResult.metadata().count();
46}
47
48int QgsLayerMetadataResultsModel::columnCount( const QModelIndex &parent ) const
49{
50 return parent.isValid() ? 0 : 5;
51}
52
53QVariant QgsLayerMetadataResultsModel::data( const QModelIndex &index, int role ) const
54{
55 if ( index.isValid() && index.row() < mResult.metadata().count() )
56 {
57 switch ( role )
58 {
59 case Qt::ItemDataRole::DisplayRole:
60 {
61 switch ( index.column() )
62 {
63 case Sections::Identifier:
64 return mResult.metadata().at( index.row() ).identifier();
65 case Sections::Title:
66 return mResult.metadata().at( index.row() ).title();
67 case Sections::Abstract:
68 return mResult.metadata().at( index.row() ).abstract();
69 case Sections::DataProviderName:
70 {
71 const QString providerName { mResult.metadata().at( index.row() ).dataProviderName() };
72 QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerName ) };
73 return md ? md->description() : providerName;
74 }
75 case Sections::GeometryType:
76 {
77 const QList<QgsLayerMetadataProviderResult> metadata = mResult.metadata();
78 const QgsLayerMetadataProviderResult &md { metadata.at( index.row() ) };
80 return tr( "Raster" );
81 return md.geometryType() == Qgis::GeometryType::Unknown ? QgsWkbTypes::geometryDisplayString( Qgis::GeometryType::Null ) : QgsWkbTypes::geometryDisplayString( md.geometryType() );
82 }
83 default:
84 return QVariant();
85 }
86 break;
87 }
88 case Qt::ItemDataRole::ToolTipRole:
89 {
90 const QgsLayerMetadataFormatter formatter { mResult.metadata().at( index.row() ) };
91 return tr( R"HTML(<html><body><!-- metadata headers ---><h3>Identification</h3>%1</body></html>)HTML" )
92 .arg(
94 );
95 break;
96 }
97 case Qt::ItemDataRole::DecorationRole:
98 {
99 if ( index.column() == 0 )
100 {
101 const QList<QgsLayerMetadataProviderResult> metadata = mResult.metadata();
102 const QgsLayerMetadataProviderResult &md { metadata.at( index.row() ) };
104 return QgsApplication::getThemeIcon( QStringLiteral( "mIconRaster.svg" ) );
106 }
107 break;
108 }
109 case static_cast<int>( CustomRole::Metadata ):
110 {
111 return QVariant::fromValue( mResult.metadata().at( index.row() ) );
112 }
113 default:
114 // Ignore
115 break;
116 }
117 }
118 return QVariant();
119}
120
121QVariant QgsLayerMetadataResultsModel::headerData( int section, Qt::Orientation orientation, int role ) const
122{
123 if ( orientation == Qt::Orientation::Horizontal && section < columnCount( createIndex( -1, -1 ) ) )
124 {
125 if ( role == Qt::ItemDataRole::DisplayRole )
126 {
127 switch ( section )
128 {
129 case Sections::Identifier:
130 return tr( "Identifier" );
131 case Sections::Title:
132 return tr( "Title" );
133 case Sections::Abstract:
134 return tr( "Abstract" );
135 case Sections::DataProviderName:
136 return tr( "Provider" );
137 case Sections::GeometryType:
138 return tr( "Layer Type" );
139 }
140 }
141 // other roles here ...
142 }
143 return QAbstractTableModel::headerData( section, orientation, role );
144}
145
146void QgsLayerMetadataResultsModel::reload()
147{
148 cancel();
149 beginResetModel();
150 // Load results from layer metadata providers
151 mResult = QgsLayerMetadataSearchResults();
152 const QList<QgsAbstractLayerMetadataProvider *> providers { QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders() };
153 for ( QgsAbstractLayerMetadataProvider *mdProvider : std::as_const( providers ) )
154 {
155 const QList<QgsLayerMetadataProviderResult> results { mdProvider->search( mSearchContext ).metadata() };
156 for ( const QgsLayerMetadataProviderResult &metadata : std::as_const( results ) )
157 {
158 mResult.addMetadata( metadata );
159 }
160 }
161 endResetModel();
162}
163
164void QgsLayerMetadataResultsModel::reloadAsync()
165{
166 cancel();
167 beginResetModel();
168 // Load results from layer metadata providers
169 mResult = QgsLayerMetadataSearchResults();
170 endResetModel();
171 mFeedback->setProgress( 0 );
172 const QList<QgsAbstractLayerMetadataProvider *> providers { QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders() };
173 for ( QgsAbstractLayerMetadataProvider *mdProvider : std::as_const( providers ) )
174 {
175 auto fetcher = std::make_unique<QgsMetadataResultsFetcher>( mdProvider, mSearchContext, mFeedback.get() );
176 auto thread = std::make_unique<QThread>();
177 fetcher->moveToThread( thread.get() );
178 // Forward signals to the model
179 connect( fetcher.get(), &QgsMetadataResultsFetcher::resultsReady, this, [this]( const QgsLayerMetadataSearchResults &results ) {
180 resultsReady( results );
181 } );
182 connect( thread.get(), &QThread::started, fetcher.get(), &QgsMetadataResultsFetcher::fetchMetadata );
183 mWorkerThreads.push_back( std::move( thread ) );
184 mWorkers.push_back( std::move( fetcher ) );
185 mWorkerThreads.back()->start();
186 }
187}
188
189void QgsLayerMetadataResultsModel::resultsReady( const QgsLayerMetadataSearchResults &results )
190{
191 mFeedback->setProgress( mFeedback->progress() + static_cast<double>( 100 ) / QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders().count() );
192 beginInsertRows( QModelIndex(), mResult.metadata().count(), mResult.metadata().count() + results.metadata().count() - 1 );
193 const QList<QgsLayerMetadataProviderResult> metadata { results.metadata() };
194 for ( const QgsLayerMetadataProviderResult &result : std::as_const( metadata ) )
195 {
196 mResult.addMetadata( result );
197 }
198 endInsertRows();
199}
200
201void QgsLayerMetadataResultsModel::cancel()
202{
203 if ( mFeedback )
204 {
205 mFeedback->cancel();
206 }
207
208 for ( const auto &workerThread : std::as_const( mWorkerThreads ) )
209 {
210 workerThread->quit();
211 workerThread->wait();
212 }
213
214 mWorkers.clear();
215 mWorkerThreads.clear();
216
217 mFeedback = std::make_unique<QgsFeedback>();
218 connect( mFeedback.get(), &QgsFeedback::progressChanged, this, &QgsLayerMetadataResultsModel::progressChanged );
219}
220
221
223
224QgsMetadataResultsFetcher::QgsMetadataResultsFetcher( const QgsAbstractLayerMetadataProvider *metadataProvider, const QgsMetadataSearchContext &searchContext, QgsFeedback *feedback )
225 : mLayerMetadataProvider( metadataProvider )
226 , mSearchContext( searchContext )
227 , mFeedback( feedback )
228{
229}
230
231void QgsMetadataResultsFetcher::fetchMetadata()
232{
233 emit resultsReady( mLayerMetadataProvider->search( mSearchContext, QString(), QgsRectangle(), mFeedback ) );
234}
235
@ Unknown
Unknown types.
Definition qgis.h:362
@ Null
No geometry.
Definition qgis.h:363
@ Raster
Raster layer.
Definition qgis.h:192
Layer metadata provider backend interface.
static QgsLayerMetadataProviderRegistry * layerMetadataProviderRegistry()
Returns registry of available layer metadata provider implementations.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
static QIcon iconForGeometryType(Qgis::GeometryType typeGroup)
Returns the icon for a vector layer whose geometry typeGroup is provided.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QList< QgsAbstractLayerMetadataProvider * > layerMetadataProviders() const
Returns the list of all registered layer metadata providers.
Qgis::GeometryType geometryType() const
Returns the layer geometry type.
Qgis::LayerType layerType() const
Returns the layer type.
Container of result records from a layer metadata search.
QList< QgsLayerMetadataProviderResult > metadata() const
Returns the list of metadata results.
QString description() const
This returns descriptive text for the provider.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
A rectangle specified with double values.
static Q_INVOKABLE QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.