QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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
31{
32 QString myMetadata = u"<table class=\"list-view\">\n"_s;
33 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Fees" ) + u"</td><td>"_s + QgsStringUtils::insertLinks( mMetadata.fees() ) + u"</td></tr>\n"_s;
34 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;
35 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;
36 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Constraints" ) + u"</td><td>"_s;
37 const QList<QgsLayerMetadata::Constraint> &constraints = mMetadata.constraints();
38 bool notFirstRow = false;
39 for ( const QgsLayerMetadata::Constraint &constraint : constraints )
40 {
41 if ( notFirstRow )
42 {
43 myMetadata += "<br />"_L1;
44 }
45 myMetadata += u"<strong>"_s + constraint.type + u": </strong>"_s + QgsStringUtils::insertLinks( constraint.constraint );
46 notFirstRow = true;
47 }
48 myMetadata += "</td></tr>\n"_L1;
49 myMetadata += "</table>\n"_L1;
50 return myMetadata;
51}
52
54{
55 const QList<QgsAbstractMetadataBase::Contact> &contacts = mMetadata.contacts();
56 QString myMetadata;
57 if ( contacts.isEmpty() )
58 {
59 myMetadata += u"<p>"_s + tr( "No contact yet." ) + u"</p>"_s;
60 }
61 else
62 {
63 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
64 myMetadata += "<tr><th>"_L1
65 + tr( "ID" )
66 + "</th><th>"_L1
67 + tr( "Name" )
68 + "</th><th>"_L1
69 + tr( "Position" )
70 + "</th><th>"_L1
71 + tr( "Organization" )
72 + "</th><th>"_L1
73 + tr( "Role" )
74 + "</th><th>"_L1
75 + tr( "Email" )
76 + "</th><th>"_L1
77 + tr( "Voice" )
78 + "</th><th>"_L1
79 + tr( "Fax" )
80 + "</th><th>"_L1
81 + tr( "Addresses" )
82 + "</th></tr>\n"_L1;
83 int i = 1;
84 for ( const QgsAbstractMetadataBase::Contact &contact : contacts )
85 {
86 QString rowClass;
87 if ( i % 2 )
88 rowClass = u"class=\"odd-row\""_s;
89 myMetadata += "<tr "_L1
90 + rowClass
91 + "><td>"_L1
92 + QString::number( i )
93 + "</td><td>"_L1
94 + contact.name
95 + "</td><td>"_L1
96 + contact.position
97 + "</td><td>"_L1
98 + contact.organization
99 + "</td><td>"_L1
100 + contact.role
101 + u"</td><td><a href=\"mailto:%1\">%1</a></td><td>"_s.arg( contact.email )
102 + contact.voice
103 + "</td><td>"_L1
104 + contact.fax
105 + "</td><td>"_L1;
106 bool notFirstRow = false;
107 for ( const QgsAbstractMetadataBase::Address &oneAddress : contact.addresses )
108 {
109 if ( notFirstRow )
110 {
111 myMetadata += "<br />\n"_L1;
112 }
113 if ( !oneAddress.type.isEmpty() )
114 {
115 myMetadata += oneAddress.type + u"<br />"_s;
116 }
117 if ( !oneAddress.address.isEmpty() )
118 {
119 myMetadata += oneAddress.address + u"<br />"_s;
120 }
121 if ( !oneAddress.postalCode.isEmpty() )
122 {
123 myMetadata += oneAddress.postalCode + u"<br />"_s;
124 }
125 if ( !oneAddress.city.isEmpty() )
126 {
127 myMetadata += oneAddress.city + u"<br />"_s;
128 }
129 if ( !oneAddress.administrativeArea.isEmpty() )
130 {
131 myMetadata += oneAddress.administrativeArea + u"<br />"_s;
132 }
133 if ( !oneAddress.country.isEmpty() )
134 {
135 myMetadata += oneAddress.country;
136 }
137 notFirstRow = true;
138 }
139 myMetadata += "</td></tr>\n"_L1;
140 i++;
141 }
142 myMetadata += "</table>\n"_L1;
143 }
144 return myMetadata;
145}
146
147QString QgsLayerMetadataFormatter::extentSectionHtml( const bool showSpatialExtent ) const
148{
149 const QgsLayerMetadata::Extent extent = mMetadata.extent();
150 bool notFirstRow = false;
151 QString myMetadata = u"<table class=\"list-view\">\n"_s;
152 if ( showSpatialExtent )
153 {
154 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "CRS" ) + u"</td><td>"_s;
155 if ( mMetadata.crs().isValid() )
156 {
157 myMetadata += mMetadata.crs().userFriendlyIdentifier() + u" - "_s;
158 if ( mMetadata.crs().isGeographic() )
159 myMetadata += tr( "Geographic" );
160 else
161 myMetadata += tr( "Projected" );
162 }
163 myMetadata += "</td></tr>\n"_L1;
164
165 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Spatial Extent" ) + u"</td><td>"_s;
166 const QList< QgsLayerMetadata::SpatialExtent > spatialExtents = extent.spatialExtents();
167 for ( const QgsLayerMetadata::SpatialExtent &spatialExtent : spatialExtents )
168 {
169 if ( spatialExtent.bounds.isNull() || spatialExtent.bounds.toRectangle().isNull() )
170 continue;
171
172 if ( notFirstRow )
173 {
174 myMetadata += "<br />\n"_L1;
175 }
176 myMetadata += u"<strong>"_s + tr( "CRS" ) + u": </strong>"_s + spatialExtent.extentCrs.userFriendlyIdentifier() + u" - "_s;
177 if ( spatialExtent.extentCrs.isGeographic() )
178 myMetadata += tr( "Geographic" );
179 else
180 myMetadata += tr( "Projected" );
181 myMetadata += "<br />"_L1;
182 myMetadata += u"<strong>"_s + tr( "X Minimum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.xMinimum() ) + u"<br />"_s;
183 myMetadata += u"<strong>"_s + tr( "Y Minimum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.yMinimum() ) + u"<br />"_s;
184 myMetadata += u"<strong>"_s + tr( "X Maximum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.xMaximum() ) + u"<br />"_s;
185 myMetadata += u"<strong>"_s + tr( "Y Maximum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.yMaximum() ) + u"<br />"_s;
186 if ( spatialExtent.bounds.zMinimum() || spatialExtent.bounds.zMaximum() )
187 {
188 myMetadata += u"<strong>"_s + tr( "Z Minimum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.zMinimum() ) + u"<br />"_s;
189 myMetadata += u"<strong>"_s + tr( "Z Maximum:" ) + u" </strong>"_s + qgsDoubleToString( spatialExtent.bounds.zMaximum() );
190 }
191 notFirstRow = true;
192 }
193 myMetadata += "</td></tr>\n"_L1;
194 }
195 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Temporal Extent" ) + u"</td><td>"_s;
196 const QList< QgsDateTimeRange > temporalExtents = extent.temporalExtents();
197 notFirstRow = false;
198 for ( const QgsDateTimeRange &temporalExtent : temporalExtents )
199 {
200 if ( notFirstRow )
201 {
202 myMetadata += "<br />\n"_L1;
203 }
204 if ( temporalExtent.isInstant() )
205 {
206 myMetadata += u"<strong>"_s + tr( "Instant:" ) + u" </strong>"_s + temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate );
207 }
208 else
209 {
210 myMetadata += u"<strong>"_s + tr( "Start:" ) + u" </strong>"_s + temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) + u"<br />\n"_s;
211 myMetadata += u"<strong>"_s + tr( "End:" ) + u" </strong>"_s + temporalExtent.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate );
212 }
213 notFirstRow = true;
214 }
215 myMetadata += "</td></tr>\n"_L1;
216 myMetadata += "</table>\n"_L1;
217 return myMetadata;
218}
219
221{
222 QString myMetadata = u"<table class=\"list-view\">\n"_s;
223
224 // Identifier
225 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Identifier" ) + u"</td><td>"_s + mMetadata.identifier() + u"</td></tr>\n"_s;
226
227 // Parent Identifier
228 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Parent Identifier" ) + u"</td><td>"_s + mMetadata.parentIdentifier() + u"</td></tr>\n"_s;
229
230 // Title
231 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Title" ) + u"</td><td>"_s + mMetadata.title() + u"</td></tr>\n"_s;
232
233 // Type
234 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Type" ) + u"</td><td>"_s + mMetadata.type() + u"</td></tr>\n"_s;
235
236 // Language
237 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Language" ) + u"</td><td>"_s + mMetadata.language() + u"</td></tr>\n"_s;
238
239 // Abstract
240 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;
241
242 // Categories
243 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Categories" ) + u"</td><td>"_s + mMetadata.categories().join( ", "_L1 ) + u"</td></tr>\n"_s;
244
245 // Keywords
246 myMetadata += u"<tr><td class=\"highlight\">"_s + tr( "Keywords" ) + u"</td><td>\n"_s;
247 QMapIterator<QString, QStringList> i( mMetadata.keywords() );
248 if ( i.hasNext() )
249 {
250 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
251 myMetadata += "<tr><th>"_L1 + tr( "Vocabulary" ) + "</th><th>"_L1 + tr( "Items" ) + "</th></tr>\n"_L1;
252 int j = 1;
253 while ( i.hasNext() )
254 {
255 i.next();
256 QString rowClass;
257 if ( j % 2 )
258 rowClass = u"class=\"odd-row\""_s;
259 myMetadata += "<tr "_L1 + rowClass + "><td>"_L1 + i.key() + "</td><td>"_L1 + i.value().join( ", "_L1 ) + "</td></tr>\n"_L1;
260 j++;
261 }
262 myMetadata += "</table>\n"_L1; // End keywords table
263 }
264 myMetadata += "</td></tr>\n"_L1; // End of keywords row
265 myMetadata += "</table>\n"_L1; // End identification table
266 return myMetadata;
267}
268
270{
271 QString myMetadata;
272 const QStringList historyItems = mMetadata.history();
273 if ( historyItems.isEmpty() )
274 {
275 myMetadata += u"<p>"_s + tr( "No history yet." ) + u"</p>\n"_s;
276 }
277 else
278 {
279 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
280 myMetadata += "<tr><th>"_L1 + tr( "ID" ) + "</th><th>"_L1 + tr( "Action" ) + "</th></tr>\n"_L1;
281 int i = 1;
282 for ( const QString &history : historyItems )
283 {
284 QString rowClass;
285 if ( i % 2 )
286 rowClass = u"class=\"odd-row\""_s;
287 myMetadata += "<tr "_L1 + rowClass + "><td width=\"5%\">"_L1 + QString::number( i ) + "</td><td>"_L1 + QgsStringUtils::insertLinks( history ) + "</td></tr>\n"_L1;
288 i++;
289 }
290 myMetadata += "</table>\n"_L1;
291 }
292 return myMetadata;
293}
294
296{
297 QString myMetadata;
298 const QList<QgsAbstractMetadataBase::Link> &links = mMetadata.links();
299 if ( links.isEmpty() )
300 {
301 myMetadata += u"<p>"_s + tr( "No links yet." ) + u"</p>\n"_s;
302 }
303 else
304 {
305 myMetadata += "<table width=\"100%\" class=\"tabular-view\">\n"_L1;
306 myMetadata += "<tr><th>"_L1
307 + tr( "ID" )
308 + "</th><th>"_L1
309 + tr( "Name" )
310 + "</th><th>"_L1
311 + tr( "Type" )
312 + "</th><th>"_L1
313 + tr( "URL" )
314 + "</th><th>"_L1
315 + tr( "Description" )
316 + "</th><th>"_L1
317 + tr( "Format" )
318 + "</th><th>"_L1
319 + tr( "MIME Type" )
320 + "</th><th>"_L1
321 + tr( "Size" )
322 + "</th></tr>\n"_L1;
323 int i = 1;
324 for ( const QgsAbstractMetadataBase::Link &link : links )
325 {
326 QString rowClass;
327 if ( i % 2 )
328 rowClass = u"class=\"odd-row\""_s;
329 myMetadata += "<tr "_L1
330 + rowClass
331 + "><td>"_L1
332 + QString::number( i )
333 + "</td><td>"_L1
334 + link.name
335 + "</td><td>"_L1
336 + link.type
337 + u"</td><td><a href=\"%1\">%1</a></td><td>"_s.arg( link.url )
338 + link.description
339 + "</td><td>"_L1
340 + link.format
341 + "</td><td>"_L1
342 + link.mimeType
343 + "</td><td>"_L1
344 + link.size
345 + "</td></tr>\n"_L1;
346 i++;
347 }
348 myMetadata += "</table>\n"_L1;
349 }
350 return myMetadata;
351}
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:6893
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:705
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.