QGIS API Documentation 3.99.0-Master (357b655ed83)
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#include <QString>
28
29#include "moc_qgslayermetadataresultsmodel.cpp"
30
31using namespace Qt::StringLiterals;
32
33QgsLayerMetadataResultsModel::QgsLayerMetadataResultsModel( const QgsMetadataSearchContext &searchContext, QObject *parent )
34 : QAbstractTableModel( parent )
35 , mSearchContext( searchContext )
36{
37 qRegisterMetaType<QgsLayerMetadataSearchResults>( "QgsLayerMetadataSearchResults" );
38 qRegisterMetaType<QgsLayerMetadataProviderResult>( "QgsLayerMetadataProviderResult" );
39}
40
41QgsLayerMetadataResultsModel::~QgsLayerMetadataResultsModel()
42{
43 cancel();
44}
45
46int QgsLayerMetadataResultsModel::rowCount( const QModelIndex &parent ) const
47{
48 return parent.isValid() ? 0 : mResult.metadata().count();
49}
50
51int QgsLayerMetadataResultsModel::columnCount( const QModelIndex &parent ) const
52{
53 return parent.isValid() ? 0 : 5;
54}
55
56QVariant QgsLayerMetadataResultsModel::data( const QModelIndex &index, int role ) const
57{
58 if ( index.isValid() && index.row() < mResult.metadata().count() )
59 {
60 switch ( role )
61 {
62 case Qt::ItemDataRole::DisplayRole:
63 {
64 switch ( index.column() )
65 {
66 case Sections::Identifier:
67 return mResult.metadata().at( index.row() ).identifier();
68 case Sections::Title:
69 return mResult.metadata().at( index.row() ).title();
70 case Sections::Abstract:
71 return mResult.metadata().at( index.row() ).abstract();
72 case Sections::DataProviderName:
73 {
74 const QString providerName { mResult.metadata().at( index.row() ).dataProviderName() };
75 QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( providerName ) };
76 return md ? md->description() : providerName;
77 }
78 case Sections::GeometryType:
79 {
80 const QList<QgsLayerMetadataProviderResult> metadata = mResult.metadata();
81 const QgsLayerMetadataProviderResult &md { metadata.at( index.row() ) };
83 return tr( "Raster" );
84 return md.geometryType() == Qgis::GeometryType::Unknown ? QgsWkbTypes::geometryDisplayString( Qgis::GeometryType::Null ) : QgsWkbTypes::geometryDisplayString( md.geometryType() );
85 }
86 default:
87 return QVariant();
88 }
89 break;
90 }
91 case Qt::ItemDataRole::ToolTipRole:
92 {
93 const QgsLayerMetadataFormatter formatter { mResult.metadata().at( index.row() ) };
94 return tr( R"HTML(<html><body><!-- metadata headers ---><h3>Identification</h3>%1</body></html>)HTML" )
95 .arg(
97 );
98 break;
99 }
100 case Qt::ItemDataRole::DecorationRole:
101 {
102 if ( index.column() == 0 )
103 {
104 const QList<QgsLayerMetadataProviderResult> metadata = mResult.metadata();
105 const QgsLayerMetadataProviderResult &md { metadata.at( index.row() ) };
107 return QgsApplication::getThemeIcon( u"mIconRaster.svg"_s );
109 }
110 break;
111 }
112 case static_cast<int>( CustomRole::Metadata ):
113 {
114 return QVariant::fromValue( mResult.metadata().at( index.row() ) );
115 }
116 default:
117 // Ignore
118 break;
119 }
120 }
121 return QVariant();
122}
123
124QVariant QgsLayerMetadataResultsModel::headerData( int section, Qt::Orientation orientation, int role ) const
125{
126 if ( orientation == Qt::Orientation::Horizontal && section < columnCount( createIndex( -1, -1 ) ) )
127 {
128 if ( role == Qt::ItemDataRole::DisplayRole )
129 {
130 switch ( section )
131 {
132 case Sections::Identifier:
133 return tr( "Identifier" );
134 case Sections::Title:
135 return tr( "Title" );
136 case Sections::Abstract:
137 return tr( "Abstract" );
138 case Sections::DataProviderName:
139 return tr( "Provider" );
140 case Sections::GeometryType:
141 return tr( "Layer Type" );
142 }
143 }
144 // other roles here ...
145 }
146 return QAbstractTableModel::headerData( section, orientation, role );
147}
148
149void QgsLayerMetadataResultsModel::reload()
150{
151 cancel();
152 beginResetModel();
153 // Load results from layer metadata providers
154 mResult = QgsLayerMetadataSearchResults();
155 const QList<QgsAbstractLayerMetadataProvider *> providers { QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders() };
156 for ( QgsAbstractLayerMetadataProvider *mdProvider : std::as_const( providers ) )
157 {
158 const QList<QgsLayerMetadataProviderResult> results { mdProvider->search( mSearchContext ).metadata() };
159 for ( const QgsLayerMetadataProviderResult &metadata : std::as_const( results ) )
160 {
161 mResult.addMetadata( metadata );
162 }
163 }
164 endResetModel();
165}
166
167void QgsLayerMetadataResultsModel::reloadAsync()
168{
169 cancel();
170 beginResetModel();
171 // Load results from layer metadata providers
172 mResult = QgsLayerMetadataSearchResults();
173 endResetModel();
174 mFeedback->setProgress( 0 );
175 const QList<QgsAbstractLayerMetadataProvider *> providers { QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders() };
176 for ( QgsAbstractLayerMetadataProvider *mdProvider : std::as_const( providers ) )
177 {
178 auto fetcher = std::make_unique<QgsMetadataResultsFetcher>( mdProvider, mSearchContext, mFeedback.get() );
179 auto thread = std::make_unique<QThread>();
180 fetcher->moveToThread( thread.get() );
181 // Forward signals to the model
182 connect( fetcher.get(), &QgsMetadataResultsFetcher::resultsReady, this, [this]( const QgsLayerMetadataSearchResults &results ) {
183 resultsReady( results );
184 } );
185 connect( thread.get(), &QThread::started, fetcher.get(), &QgsMetadataResultsFetcher::fetchMetadata );
186 mWorkerThreads.push_back( std::move( thread ) );
187 mWorkers.push_back( std::move( fetcher ) );
188 mWorkerThreads.back()->start();
189 }
190}
191
192void QgsLayerMetadataResultsModel::resultsReady( const QgsLayerMetadataSearchResults &results )
193{
194 mFeedback->setProgress( mFeedback->progress() + static_cast<double>( 100 ) / QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders().count() );
195 beginInsertRows( QModelIndex(), mResult.metadata().count(), mResult.metadata().count() + results.metadata().count() - 1 );
196 const QList<QgsLayerMetadataProviderResult> metadata { results.metadata() };
197 for ( const QgsLayerMetadataProviderResult &result : std::as_const( metadata ) )
198 {
199 mResult.addMetadata( result );
200 }
201 endInsertRows();
202}
203
204void QgsLayerMetadataResultsModel::cancel()
205{
206 if ( mFeedback )
207 {
208 mFeedback->cancel();
209 }
210
211 for ( const auto &workerThread : std::as_const( mWorkerThreads ) )
212 {
213 workerThread->quit();
214 workerThread->wait();
215 }
216
217 mWorkers.clear();
218 mWorkerThreads.clear();
219
220 mFeedback = std::make_unique<QgsFeedback>();
221 connect( mFeedback.get(), &QgsFeedback::progressChanged, this, &QgsLayerMetadataResultsModel::progressChanged );
222}
223
224
226
227QgsMetadataResultsFetcher::QgsMetadataResultsFetcher( const QgsAbstractLayerMetadataProvider *metadataProvider, const QgsMetadataSearchContext &searchContext, QgsFeedback *feedback )
228 : mLayerMetadataProvider( metadataProvider )
229 , mSearchContext( searchContext )
230 , mFeedback( feedback )
231{
232}
233
234void QgsMetadataResultsFetcher::fetchMetadata()
235{
236 emit resultsReady( mLayerMetadataProvider->search( mSearchContext, QString(), QgsRectangle(), mFeedback ) );
237}
238
@ Unknown
Unknown types.
Definition qgis.h:369
@ Null
No geometry.
Definition qgis.h:370
@ Raster
Raster layer.
Definition qgis.h:195
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.