QGIS API Documentation 3.36.0-Maidenhead (09951dc0acf)
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 "qgsfeedback.h"
18#include "qgsapplication.h"
21#include "qgsiconutils.h"
22#include "qgsproviderregistry.h"
23#include "qgsprovidermetadata.h"
24#include <QIcon>
25
26QgsLayerMetadataResultsModel::QgsLayerMetadataResultsModel( const QgsMetadataSearchContext &searchContext, QObject *parent )
27 : QAbstractTableModel( parent )
28 , mSearchContext( searchContext )
29{
30 qRegisterMetaType< QgsLayerMetadataSearchResults>( "QgsLayerMetadataSearchResults" );
31 qRegisterMetaType< QgsLayerMetadataProviderResult>( "QgsLayerMetadataProviderResult" );
32}
33
34QgsLayerMetadataResultsModel::~QgsLayerMetadataResultsModel()
35{
36 cancel();
37}
38
39int QgsLayerMetadataResultsModel::rowCount( const QModelIndex &parent ) const
40{
41 return parent.isValid() ? 0 : mResult.metadata().count();
42}
43
44int QgsLayerMetadataResultsModel::columnCount( const QModelIndex &parent ) const
45{
46 return parent.isValid() ? 0 : 5;
47}
48
49QVariant QgsLayerMetadataResultsModel::data( const QModelIndex &index, int role ) const
50{
51 if ( index.isValid() && index.row() < mResult.metadata().count( ) )
52 {
53 switch ( role )
54 {
55 case Qt::ItemDataRole::DisplayRole:
56 {
57 switch ( index.column() )
58 {
59 case Sections::Identifier:
60 return mResult.metadata().at( index.row() ).identifier( );
61 case Sections::Title:
62 return mResult.metadata().at( index.row() ).title();
63 case Sections::Abstract:
64 return mResult.metadata().at( index.row() ).abstract();
65 case Sections::DataProviderName:
66 {
67 const QString providerName { mResult.metadata().at( index.row() ).dataProviderName() };
69 return md ? md->description() : providerName;
70 }
71 case Sections::GeometryType:
72 {
73 const QList<QgsLayerMetadataProviderResult> metadata = mResult.metadata();
74 const QgsLayerMetadataProviderResult &md { metadata.at( index.row() ) };
75 if ( md.layerType() == Qgis::LayerType::Raster )
76 return tr( "Raster" );
77 return md.geometryType() == Qgis::GeometryType::Unknown ? QgsWkbTypes::geometryDisplayString( Qgis::GeometryType::Null ) : QgsWkbTypes::geometryDisplayString( md.geometryType() );
78 }
79 default:
80 return QVariant();
81 }
82 break;
83 }
84 case Qt::ItemDataRole::ToolTipRole:
85 {
86 const QgsLayerMetadataFormatter formatter { mResult.metadata().at( index.row() ) };
87 return tr( R"HTML(<html><body><!-- metadata headers ---><h3>Identification</h3>%1</body></html>)HTML" )
88 .arg(
89 formatter.identificationSectionHtml() );
90 break;
91 }
92 case Qt::ItemDataRole::DecorationRole:
93 {
94 if ( index.column() == 0 )
95 {
96 const QList<QgsLayerMetadataProviderResult> metadata = mResult.metadata();
97 const QgsLayerMetadataProviderResult &md { metadata.at( index.row() ) };
98 if ( md.layerType() == Qgis::LayerType::Raster )
99 return QgsApplication::getThemeIcon( QStringLiteral( "mIconRaster.svg" ) );
100 return QgsIconUtils::iconForGeometryType( md.geometryType() == Qgis::GeometryType::Unknown ? Qgis::GeometryType::Null : md.geometryType() );
101 }
102 break;
103 }
104 case static_cast< int >( CustomRole::Metadata ):
105 {
106 return QVariant::fromValue( mResult.metadata().at( index.row() ) );
107 }
108 default:
109 // Ignore
110 break;
111
112 }
113 }
114 return QVariant();
115}
116
117QVariant QgsLayerMetadataResultsModel::headerData( int section, Qt::Orientation orientation, int role ) const
118{
119 if ( orientation == Qt::Orientation::Horizontal && section < columnCount( createIndex( -1, -1 ) ) )
120 {
121 if ( role == Qt::ItemDataRole::DisplayRole )
122 {
123 switch ( section )
124 {
125 case Sections::Identifier:
126 return tr( "Identifier" );
127 case Sections::Title:
128 return tr( "Title" );
129 case Sections::Abstract:
130 return tr( "Abstract" );
131 case Sections::DataProviderName:
132 return tr( "Provider" );
133 case Sections::GeometryType:
134 return tr( "Layer Type" );
135 }
136 }
137 // other roles here ...
138 }
139 return QAbstractTableModel::headerData( section, orientation, role );
140}
141
142void QgsLayerMetadataResultsModel::reload()
143{
144 cancel();
145 beginResetModel();
146 // Load results from layer metadata providers
148 const QList<QgsAbstractLayerMetadataProvider *> providers { QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders() };
149 for ( QgsAbstractLayerMetadataProvider *mdProvider : std::as_const( providers ) )
150 {
151 const QList<QgsLayerMetadataProviderResult> results { mdProvider->search( mSearchContext ).metadata() };
152 for ( const QgsLayerMetadataProviderResult &metadata : std::as_const( results ) )
153 {
154 mResult.addMetadata( metadata );
155 }
156 }
157 endResetModel();
158}
159
160void QgsLayerMetadataResultsModel::reloadAsync()
161{
162 cancel();
163 beginResetModel();
164 // Load results from layer metadata providers
166 endResetModel();
167 mFeedback->setProgress( 0 );
168 const QList<QgsAbstractLayerMetadataProvider *> providers { QgsApplication::instance()->layerMetadataProviderRegistry()->layerMetadataProviders() };
169 for ( QgsAbstractLayerMetadataProvider *mdProvider : std::as_const( providers ) )
170 {
171 std::unique_ptr<QgsMetadataResultsFetcher> fetcher = std::make_unique<QgsMetadataResultsFetcher>( mdProvider, mSearchContext, mFeedback.get() );
172 std::unique_ptr<QThread> thread = std::make_unique<QThread>();
173 fetcher->moveToThread( thread.get() );
174 // Forward signals to the model
175 connect( fetcher.get(), &QgsMetadataResultsFetcher::resultsReady, this, [ = ]( const QgsLayerMetadataSearchResults & results )
176 {
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() + 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.