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