QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgslayermetadataformatter.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayermetadataformatter.cpp
3 ---------------------
4 begin : September 2017
5 copyright : (C) 2017 by Etienne Trimaille
6 email : etienne.trimaille at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
16
17#include "qgslayermetadata.h"
18#include "qgsstringutils.h"
19
20#include <QDateTime>
21#include <QString>
22#include <QStringBuilder>
23
24using namespace Qt::StringLiterals;
25
27 : mMetadata( metadata )
28{
29}
30
32{
33 QString myMetadata = u"<table class=\"list-view\">\n"_s;
34 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Fees" ) + u"</td><td>"_s + QgsStringUtils::insertLinks( mMetadata.fees() ) + u"</td></tr>\n"_s;
35 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Licenses" ) + u"</td><td>"_s + QgsStringUtils::insertLinks( mMetadata.licenses().join( "<br />"_L1 ) ) + u"</td></tr>\n"_s;
36 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Rights" ) + u"</td><td>"_s + QgsStringUtils::insertLinks( mMetadata.rights().join( "<br />"_L1 ) ) + u"</td></tr>\n"_s;
37 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Constraints" ) + u"</td><td>"_s;
38 const QList<QgsLayerMetadata::Constraint> &constraints = mMetadata.constraints();
39 bool notFirstRow = false;
40 for ( const QgsLayerMetadata::Constraint &constraint : constraints )
41 {
42 if ( notFirstRow )
43 {
44 myMetadata += "<br />"_L1;
45 }
46 myMetadata += u"<strong>"_s + constraint.type + u": </strong>"_s + QgsStringUtils::insertLinks( constraint.constraint );
47 notFirstRow = true;
48 }
49 myMetadata += "</td></tr>\n"_L1;
50 myMetadata += "</table>\n"_L1;
51 return myMetadata;
52}
53
55{
56 const QList<QgsAbstractMetadataBase::Contact> &contacts = mMetadata.contacts();
57 QString myMetadata;
58 if ( contacts.isEmpty() )
59 {
60 myMetadata += u"<p>"_s + tr( "No contact yet." ) + u"</p>"_s;
61 }
62 else
63 {
64 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
65 myMetadata += "<tr><th>"_L1 + tr( "ID" ) + "</th><th>"_L1 + tr( "Name" ) + "</th><th>"_L1 + tr( "Position" ) + "</th><th>"_L1 + tr( "Organization" ) + "</th><th>"_L1 + tr( "Role" ) + "</th><th>"_L1 + tr( "Email" ) + "</th><th>"_L1 + tr( "Voice" ) + "</th><th>"_L1 + tr( "Fax" ) + "</th><th>"_L1 + tr( "Addresses" ) + "</th></tr>\n"_L1;
66 int i = 1;
67 for ( const QgsAbstractMetadataBase::Contact &contact : contacts )
68 {
69 QString rowClass;
70 if ( i % 2 )
71 rowClass = u"class=\"odd-row\""_s;
72 myMetadata += "<tr "_L1 + rowClass + "><td>"_L1 + QString::number( i ) + "</td><td>"_L1 + contact.name + "</td><td>"_L1 + contact.position + "</td><td>"_L1 + contact.organization + "</td><td>"_L1 + contact.role + u"</td><td><a href=\"mailto:%1\">%1</a></td><td>"_s.arg( contact.email ) + contact.voice + "</td><td>"_L1 + contact.fax + "</td><td>"_L1;
73 bool notFirstRow = false;
74 for ( const QgsAbstractMetadataBase::Address &oneAddress : contact.addresses )
75 {
76 if ( notFirstRow )
77 {
78 myMetadata += "<br />\n"_L1;
79 }
80 if ( ! oneAddress.type.isEmpty() )
81 {
82 myMetadata += oneAddress.type + u"<br />"_s;
83 }
84 if ( ! oneAddress.address.isEmpty() )
85 {
86 myMetadata += oneAddress.address + u"<br />"_s;
87 }
88 if ( ! oneAddress.postalCode.isEmpty() )
89 {
90 myMetadata += oneAddress.postalCode + u"<br />"_s;
91 }
92 if ( ! oneAddress.city.isEmpty() )
93 {
94 myMetadata += oneAddress.city + u"<br />"_s;
95 }
96 if ( ! oneAddress.administrativeArea.isEmpty() )
97 {
98 myMetadata += oneAddress.administrativeArea + u"<br />"_s;
99 }
100 if ( ! oneAddress.country.isEmpty() )
101 {
102 myMetadata += oneAddress.country;
103 }
104 notFirstRow = true;
105 }
106 myMetadata += "</td></tr>\n"_L1;
107 i++;
108 }
109 myMetadata += "</table>\n"_L1;
110 }
111 return myMetadata;
112}
113
114QString QgsLayerMetadataFormatter::extentSectionHtml( const bool showSpatialExtent ) const
115{
116 const QgsLayerMetadata::Extent extent = mMetadata.extent();
117 bool notFirstRow = false;
118 QString myMetadata = u"<table class=\"list-view\">\n"_s;
119 if ( showSpatialExtent )
120 {
121 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "CRS" ) + u"</td><td>"_s;
122 if ( mMetadata.crs().isValid() )
123 {
124 myMetadata += mMetadata.crs().userFriendlyIdentifier() + u" - "_s;
125 if ( mMetadata.crs().isGeographic() )
126 myMetadata += tr( "Geographic" );
127 else
128 myMetadata += tr( "Projected" );
129 }
130 myMetadata += "</td></tr>\n"_L1;
131
132 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Spatial Extent" ) + u"</td><td>"_s;
133 const QList< QgsLayerMetadata::SpatialExtent > spatialExtents = extent.spatialExtents();
134 for ( const QgsLayerMetadata::SpatialExtent &spatialExtent : spatialExtents )
135 {
136 if ( spatialExtent.bounds.isNull() || spatialExtent.bounds.toRectangle().isNull() )
137 continue;
138
139 if ( notFirstRow )
140 {
141 myMetadata += "<br />\n"_L1;
142 }
143 myMetadata += u"<strong>"_s + tr( "CRS" ) + u": </strong>"_s + spatialExtent.extentCrs.userFriendlyIdentifier() + u" - "_s;
144 if ( spatialExtent.extentCrs.isGeographic() )
145 myMetadata += tr( "Geographic" );
146 else
147 myMetadata += tr( "Projected" );
148 myMetadata += "<br />"_L1;
149 myMetadata += u"<strong>"_s + tr( "X Minimum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.xMinimum() ) + u"<br />"_s;
150 myMetadata += u"<strong>"_s + tr( "Y Minimum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.yMinimum() ) + u"<br />"_s;
151 myMetadata += u"<strong>"_s + tr( "X Maximum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.xMaximum() ) + u"<br />"_s;
152 myMetadata += u"<strong>"_s + tr( "Y Maximum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.yMaximum() ) + u"<br />"_s;
153 if ( spatialExtent.bounds.zMinimum() || spatialExtent.bounds.zMaximum() )
154 {
155 myMetadata += u"<strong>"_s + tr( "Z Minimum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.zMinimum() ) + u"<br />"_s;
156 myMetadata += u"<strong>"_s + tr( "Z Maximum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.zMaximum() );
157 }
158 notFirstRow = true;
159 }
160 myMetadata += "</td></tr>\n"_L1;
161 }
162 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Temporal Extent" ) + u"</td><td>"_s;
163 const QList< QgsDateTimeRange > temporalExtents = extent.temporalExtents();
164 notFirstRow = false;
165 for ( const QgsDateTimeRange &temporalExtent : temporalExtents )
166 {
167 if ( notFirstRow )
168 {
169 myMetadata += "<br />\n"_L1;
170 }
171 if ( temporalExtent.isInstant() )
172 {
173 myMetadata += u"<strong>"_s + tr( "Instant:" ) + u" </strong>"_s + temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate );
174 }
175 else
176 {
177 myMetadata += u"<strong>"_s + tr( "Start:" ) + u" </strong>"_s + temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) + u"<br />\n"_s;
178 myMetadata += u"<strong>"_s + tr( "End:" ) + u" </strong>"_s + temporalExtent.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate );
179 }
180 notFirstRow = true;
181 }
182 myMetadata += "</td></tr>\n"_L1;
183 myMetadata += "</table>\n"_L1;
184 return myMetadata;
185}
186
188{
189 QString myMetadata = u"<table class=\"list-view\">\n"_s;
190
191 // Identifier
192 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Identifier" ) + u"</td><td>"_s + mMetadata.identifier() + u"</td></tr>\n"_s;
193
194 // Parent Identifier
195 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Parent Identifier" ) + u"</td><td>"_s + mMetadata.parentIdentifier() + u"</td></tr>\n"_s;
196
197 // Title
198 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Title" ) + u"</td><td>"_s + mMetadata.title() + u"</td></tr>\n"_s;
199
200 // Type
201 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Type" ) + u"</td><td>"_s + mMetadata.type() + u"</td></tr>\n"_s;
202
203 // Language
204 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Language" ) + u"</td><td>"_s + mMetadata.language() + u"</td></tr>\n"_s;
205
206 // Abstract
207 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Abstract" ) + u"</td><td>"_s + QgsStringUtils::insertLinks( mMetadata.abstract() ).replace( '\n', "<br>"_L1 ) + u"</td></tr>\n"_s;
208
209 // Categories
210 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Categories" ) + u"</td><td>"_s + mMetadata.categories().join( ", "_L1 ) + u"</td></tr>\n"_s;
211
212 // Keywords
213 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Keywords" ) + u"</td><td>\n"_s;
214 QMapIterator<QString, QStringList> i( mMetadata.keywords() );
215 if ( i.hasNext() )
216 {
217 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
218 myMetadata += "<tr><th>"_L1 + tr( "Vocabulary" ) + "</th><th>"_L1 + tr( "Items" ) + "</th></tr>\n"_L1;
219 int j = 1;
220 while ( i.hasNext() )
221 {
222 i.next();
223 QString rowClass;
224 if ( j % 2 )
225 rowClass = u"class=\"odd-row\""_s;
226 myMetadata += "<tr "_L1 + rowClass + "><td>"_L1 + i.key() + "</td><td>"_L1 + i.value().join( ", "_L1 ) + "</td></tr>\n"_L1;
227 j++;
228 }
229 myMetadata += "</table>\n"_L1; // End keywords table
230 }
231 myMetadata += "</td></tr>\n"_L1; // End of keywords row
232 myMetadata += "</table>\n"_L1; // End identification table
233 return myMetadata;
234}
235
237{
238 QString myMetadata;
239 const QStringList historyItems = mMetadata.history();
240 if ( historyItems.isEmpty() )
241 {
242 myMetadata += u"<p>"_s + tr( "No history yet." ) + u"</p>\n"_s;
243 }
244 else
245 {
246 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
247 myMetadata += "<tr><th>"_L1 + tr( "ID" ) + "</th><th>"_L1 + tr( "Action" ) + "</th></tr>\n"_L1;
248 int i = 1;
249 for ( const QString &history : historyItems )
250 {
251 QString rowClass;
252 if ( i % 2 )
253 rowClass = u"class=\"odd-row\""_s;
254 myMetadata += "<tr "_L1 + rowClass + "><td width=\"5%\">"_L1 + QString::number( i ) + "</td><td>"_L1 + QgsStringUtils::insertLinks( history ) + "</td></tr>\n"_L1;
255 i++;
256 }
257 myMetadata += "</table>\n"_L1;
258 }
259 return myMetadata;
260}
261
263{
264 QString myMetadata;
265 const QList<QgsAbstractMetadataBase::Link> &links = mMetadata.links();
266 if ( links.isEmpty() )
267 {
268 myMetadata += u"<p>"_s + tr( "No links yet." ) + u"</p>\n"_s;
269 }
270 else
271 {
272 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
273 myMetadata += "<tr><th>"_L1 + tr( "ID" ) + "</th><th>"_L1 + tr( "Name" ) + "</th><th>"_L1 + tr( "Type" ) + "</th><th>"_L1 + tr( "URL" ) + "</th><th>"_L1 + tr( "Description" ) + "</th><th>"_L1 + tr( "Format" ) + "</th><th>"_L1 + tr( "MIME Type" ) + "</th><th>"_L1 + tr( "Size" ) + "</th></tr>\n"_L1;
274 int i = 1;
275 for ( const QgsAbstractMetadataBase::Link &link : links )
276 {
277 QString rowClass;
278 if ( i % 2 )
279 rowClass = u"class=\"odd-row\""_s;
280 myMetadata += "<tr "_L1 + rowClass + "><td>"_L1 + QString::number( i ) + "</td><td>"_L1 + link.name + "</td><td>"_L1 + link.type + u"</td><td><a href=\"%1\">%1</a></td><td>"_s.arg( link.url ) + link.description + "</td><td>"_L1 + link.format + "</td><td>"_L1 + link.mimeType + "</td><td>"_L1 + link.size + "</td></tr>\n"_L1;
281 i++;
282 }
283 myMetadata += "</table>\n"_L1;
284 }
285 return myMetadata;
286}
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QgsLayerMetadataFormatter(const QgsLayerMetadata &metadata)
Constructor for QgsLayerMetadataFormatter.
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
A structured metadata store for a map layer.
static QString insertLinks(const QString &string, bool *foundLinks=nullptr)
Returns a string with any URL (e.g., http(s)/ftp) and mailto: text converted to valid HTML <a ....
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6817
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:764
QString administrativeArea
Administrative area (state, province/territory, etc.).
QString address
Free-form physical address component, e.g.
QString city
City or locality name.
QString country
Free-form country string.
QString postalCode
Postal (or ZIP) code.
Metadata constraint structure.
Metadata extent structure.
QList< QgsLayerMetadata::SpatialExtent > spatialExtents() const
Spatial extents of the resource.
QList< QgsDateTimeRange > temporalExtents() const
Temporal extents of the resource.
Metadata spatial extent structure.