QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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" ).arg( formatter.identificationSectionHtml() );
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( u"mIconRaster.svg"_s );
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 ) { resultsReady( results ); } );
180 connect( thread.get(), &QThread::started, fetcher.get(), &QgsMetadataResultsFetcher::fetchMetadata );
181 mWorkerThreads.push_back( std::move( thread ) );
182 mWorkers.push_back( std::move( fetcher ) );
183 mWorkerThreads.back()->start();
184 }
185}
186
187void QgsLayerMetadataResultsModel::resultsReady( const QgsLayerMetadataSearchResults &results )
188{
189 mFeedback->setProgress( mFeedback->progress() + static_cast<double>( 100 ) / QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders().count() );
190 beginInsertRows( QModelIndex(), mResult.metadata().count(), mResult.metadata().count() + results.metadata().count() - 1 );
191 const QList<QgsLayerMetadataProviderResult> metadata { results.metadata() };
192 for ( const QgsLayerMetadataProviderResult &result : std::as_const( metadata ) )
193 {
194 mResult.addMetadata( result );
195 }
196 endInsertRows();
197}
198
199void QgsLayerMetadataResultsModel::cancel()
200{
201 if ( mFeedback )
202 {
203 mFeedback->cancel();
204 }
205
206 for ( const auto &workerThread : std::as_const( mWorkerThreads ) )
207 {
208 workerThread->quit();
209 workerThread->wait();
210 }
211
212 mWorkers.clear();
213 mWorkerThreads.clear();
214
215 mFeedback = std::make_unique<QgsFeedback>();
216 connect( mFeedback.get(), &QgsFeedback::progressChanged, this, &QgsLayerMetadataResultsModel::progressChanged );
217}
218
219
221
222QgsMetadataResultsFetcher::QgsMetadataResultsFetcher( const QgsAbstractLayerMetadataProvider *metadataProvider, const QgsMetadataSearchContext &searchContext, QgsFeedback *feedback )
223 : mLayerMetadataProvider( metadataProvider )
224 , mSearchContext( searchContext )
225 , mFeedback( feedback )
226{}
227
228void QgsMetadataResultsFetcher::fetchMetadata()
229{
230 emit resultsReady( mLayerMetadataProvider->search( mSearchContext, QString(), QgsRectangle(), mFeedback ) );
231}
232
@ Unknown
Unknown types.
Definition qgis.h:383
@ Null
No geometry.
Definition qgis.h:384
@ Raster
Raster layer.
Definition qgis.h:208
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.