QGIS API Documentation  3.23.0-Master (c716e02dd3)
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  ***************************************************************************/
15 #include <QStringBuilder>
16 #include <QDateTime>
17 
19 #include "qgslayermetadata.h"
20 #include "qgsstringutils.h"
21 
23  : mMetadata( metadata )
24 {
25 }
26 
28 {
29  QString myMetadata = QStringLiteral( "<table class=\"list-view\">\n" );
30  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Fees" ) + QStringLiteral( "</td><td>" ) + QgsStringUtils::insertLinks( mMetadata.fees() ) + QStringLiteral( "</td></tr>\n" );
31  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Licenses" ) + QStringLiteral( "</td><td>" ) + QgsStringUtils::insertLinks( mMetadata.licenses().join( QLatin1String( "<br />" ) ) ) + QStringLiteral( "</td></tr>\n" );
32  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Rights" ) + QStringLiteral( "</td><td>" ) + QgsStringUtils::insertLinks( mMetadata.rights().join( QLatin1String( "<br />" ) ) ) + QStringLiteral( "</td></tr>\n" );
33  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Constraints" ) + QStringLiteral( "</td><td>" );
34  const QList<QgsLayerMetadata::Constraint> &constraints = mMetadata.constraints();
35  bool notFirstRow = false;
36  for ( const QgsLayerMetadata::Constraint &constraint : constraints )
37  {
38  if ( notFirstRow )
39  {
40  myMetadata += QLatin1String( "<br />" );
41  }
42  myMetadata += QStringLiteral( "<strong>" ) + constraint.type + QStringLiteral( ": </strong>" ) + QgsStringUtils::insertLinks( constraint.constraint );
43  notFirstRow = true;
44  }
45  myMetadata += QLatin1String( "</td></tr>\n" );
46  myMetadata += QLatin1String( "</table>\n" );
47  return myMetadata;
48 }
49 
51 {
52  const QList<QgsAbstractMetadataBase::Contact> &contacts = mMetadata.contacts();
53  QString myMetadata;
54  if ( contacts.isEmpty() )
55  {
56  myMetadata += QStringLiteral( "<p>" ) + tr( "No contact yet." ) + QStringLiteral( "</p>" );
57  }
58  else
59  {
60  myMetadata += QLatin1String( "<table width=\"100%\" class=\"tabular-view\">\n" );
61  myMetadata += QLatin1String( "<tr><th>" ) + tr( "ID" ) + QLatin1String( "</th><th>" ) + tr( "Name" ) + QLatin1String( "</th><th>" ) + tr( "Position" ) + QLatin1String( "</th><th>" ) + tr( "Organization" ) + QLatin1String( "</th><th>" ) + tr( "Role" ) + QLatin1String( "</th><th>" ) + tr( "Email" ) + QLatin1String( "</th><th>" ) + tr( "Voice" ) + QLatin1String( "</th><th>" ) + tr( "Fax" ) + QLatin1String( "</th><th>" ) + tr( "Addresses" ) + QLatin1String( "</th></tr>\n" );
62  int i = 1;
63  for ( const QgsAbstractMetadataBase::Contact &contact : contacts )
64  {
65  QString rowClass;
66  if ( i % 2 )
67  rowClass = QStringLiteral( "class=\"odd-row\"" );
68  myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td>" ) + QString::number( i ) + QLatin1String( "</td><td>" ) + contact.name + QLatin1String( "</td><td>" ) + contact.position + QLatin1String( "</td><td>" ) + contact.organization + QLatin1String( "</td><td>" ) + contact.role + QStringLiteral( "</td><td><a href=\"mailto:%1\">%1</a></td><td>" ).arg( contact.email ) + contact.voice + QLatin1String( "</td><td>" ) + contact.fax + QLatin1String( "</td><td>" );
69  bool notFirstRow = false;
70  for ( const QgsAbstractMetadataBase::Address &oneAddress : contact.addresses )
71  {
72  if ( notFirstRow )
73  {
74  myMetadata += QLatin1String( "<br />\n" );
75  }
76  if ( ! oneAddress.type.isEmpty() )
77  {
78  myMetadata += oneAddress.type + QStringLiteral( "<br />" );
79  }
80  if ( ! oneAddress.address.isEmpty() )
81  {
82  myMetadata += oneAddress.address + QStringLiteral( "<br />" );
83  }
84  if ( ! oneAddress.postalCode.isEmpty() )
85  {
86  myMetadata += oneAddress.postalCode + QStringLiteral( "<br />" );
87  }
88  if ( ! oneAddress.city.isEmpty() )
89  {
90  myMetadata += oneAddress.city + QStringLiteral( "<br />" );
91  }
92  if ( ! oneAddress.administrativeArea.isEmpty() )
93  {
94  myMetadata += oneAddress.administrativeArea + QStringLiteral( "<br />" );
95  }
96  if ( ! oneAddress.country.isEmpty() )
97  {
98  myMetadata += oneAddress.country;
99  }
100  notFirstRow = true;
101  }
102  myMetadata += QLatin1String( "</td></tr>\n" );
103  i++;
104  }
105  myMetadata += QLatin1String( "</table>\n" );
106  }
107  return myMetadata;
108 }
109 
110 QString QgsLayerMetadataFormatter::extentSectionHtml( const bool showSpatialExtent ) const
111 {
112  const QgsLayerMetadata::Extent extent = mMetadata.extent();
113  bool notFirstRow = false;
114  QString myMetadata = QStringLiteral( "<table class=\"list-view\">\n" );
115  if ( showSpatialExtent )
116  {
117  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "CRS" ) + QStringLiteral( "</td><td>" );
118  if ( mMetadata.crs().isValid() )
119  {
120  myMetadata += mMetadata.crs().userFriendlyIdentifier() + QStringLiteral( " - " );
121  if ( mMetadata.crs().isGeographic() )
122  myMetadata += tr( "Geographic" );
123  else
124  myMetadata += tr( "Projected" );
125  }
126  myMetadata += QLatin1String( "</td></tr>\n" );
127 
128  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Spatial Extent" ) + QStringLiteral( "</td><td>" );
129  const QList< QgsLayerMetadata::SpatialExtent > spatialExtents = extent.spatialExtents();
130  for ( const QgsLayerMetadata::SpatialExtent &spatialExtent : spatialExtents )
131  {
132  if ( notFirstRow )
133  {
134  myMetadata += QLatin1String( "<br />\n" );
135  }
136  myMetadata += QStringLiteral( "<strong>" ) + tr( "CRS" ) + QStringLiteral( ": </strong>" ) + spatialExtent.extentCrs.userFriendlyIdentifier() + QStringLiteral( " - " );
137  if ( spatialExtent.extentCrs.isGeographic() )
138  myMetadata += tr( "Geographic" );
139  else
140  myMetadata += tr( "Projected" );
141  myMetadata += QLatin1String( "<br />" );
142  myMetadata += QStringLiteral( "<strong>" ) + tr( "X Minimum:" ) + QStringLiteral( " </strong>" ) + qgsDoubleToString( spatialExtent.bounds.xMinimum() ) + QStringLiteral( "<br />" );
143  myMetadata += QStringLiteral( "<strong>" ) + tr( "Y Minimum:" ) + QStringLiteral( " </strong>" ) + qgsDoubleToString( spatialExtent.bounds.yMinimum() ) + QStringLiteral( "<br />" );
144  myMetadata += QStringLiteral( "<strong>" ) + tr( "X Maximum:" ) + QStringLiteral( " </strong>" ) + qgsDoubleToString( spatialExtent.bounds.xMaximum() ) + QStringLiteral( "<br />" );
145  myMetadata += QStringLiteral( "<strong>" ) + tr( "Y Maximum:" ) + QStringLiteral( " </strong>" ) + qgsDoubleToString( spatialExtent.bounds.yMaximum() ) + QStringLiteral( "<br />" );
146  if ( spatialExtent.bounds.zMinimum() || spatialExtent.bounds.zMaximum() )
147  {
148  myMetadata += QStringLiteral( "<strong>" ) + tr( "Z Minimum:" ) + QStringLiteral( " </strong>" ) + qgsDoubleToString( spatialExtent.bounds.zMinimum() ) + QStringLiteral( "<br />" );
149  myMetadata += QStringLiteral( "<strong>" ) + tr( "Z Maximum:" ) + QStringLiteral( " </strong>" ) + qgsDoubleToString( spatialExtent.bounds.zMaximum() );
150  }
151  notFirstRow = true;
152  }
153  myMetadata += QLatin1String( "</td></tr>\n" );
154  }
155  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Temporal Extent" ) + QStringLiteral( "</td><td>" );
156  const QList< QgsDateTimeRange > temporalExtents = extent.temporalExtents();
157  notFirstRow = false;
158  for ( const QgsDateTimeRange &temporalExtent : temporalExtents )
159  {
160  if ( notFirstRow )
161  {
162  myMetadata += QLatin1String( "<br />\n" );
163  }
164  if ( temporalExtent.isInstant() )
165  {
166  myMetadata += QStringLiteral( "<strong>" ) + tr( "Instant:" ) + QStringLiteral( " </strong>" ) + temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate );
167  }
168  else
169  {
170  myMetadata += QStringLiteral( "<strong>" ) + tr( "Start:" ) + QStringLiteral( " </strong>" ) + temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) + QStringLiteral( "<br />\n" );
171  myMetadata += QStringLiteral( "<strong>" ) + tr( "End:" ) + QStringLiteral( " </strong>" ) + temporalExtent.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate );
172  }
173  notFirstRow = true;
174  }
175  myMetadata += QLatin1String( "</td></tr>\n" );
176  myMetadata += QLatin1String( "</table>\n" );
177  return myMetadata;
178 }
179 
181 {
182  QString myMetadata = QStringLiteral( "<table class=\"list-view\">\n" );
183 
184  // Identifier
185  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Identifier" ) + QStringLiteral( "</td><td>" ) + mMetadata.identifier() + QStringLiteral( "</td></tr>\n" );
186 
187  // Parent Identifier
188  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Parent Identifier" ) + QStringLiteral( "</td><td>" ) + mMetadata.parentIdentifier() + QStringLiteral( "</td></tr>\n" );
189 
190  // Title
191  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Title" ) + QStringLiteral( "</td><td>" ) + mMetadata.title() + QStringLiteral( "</td></tr>\n" );
192 
193  // Type
194  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Type" ) + QStringLiteral( "</td><td>" ) + mMetadata.type() + QStringLiteral( "</td></tr>\n" );
195 
196  // Language
197  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Language" ) + QStringLiteral( "</td><td>" ) + mMetadata.language() + QStringLiteral( "</td></tr>\n" );
198 
199  // Abstract
200  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Abstract" ) + QStringLiteral( "</td><td>" ) + QgsStringUtils::insertLinks( mMetadata.abstract() ).replace( '\n', QLatin1String( "<br>" ) ) + QStringLiteral( "</td></tr>\n" );
201 
202  // Categories
203  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Categories" ) + QStringLiteral( "</td><td>" ) + mMetadata.categories().join( QLatin1String( ", " ) ) + QStringLiteral( "</td></tr>\n" );
204 
205  // Keywords
206  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Keywords" ) + QStringLiteral( "</td><td>\n" );
207  QMapIterator<QString, QStringList> i( mMetadata.keywords() );
208  if ( i.hasNext() )
209  {
210  myMetadata += QLatin1String( "<table width=\"100%\" class=\"tabular-view\">\n" );
211  myMetadata += QLatin1String( "<tr><th>" ) + tr( "Vocabulary" ) + QLatin1String( "</th><th>" ) + tr( "Items" ) + QLatin1String( "</th></tr>\n" );
212  int j = 1;
213  while ( i.hasNext() )
214  {
215  i.next();
216  QString rowClass;
217  if ( j % 2 )
218  rowClass = QStringLiteral( "class=\"odd-row\"" );
219  myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td>" ) + i.key() + QLatin1String( "</td><td>" ) + i.value().join( QLatin1String( ", " ) ) + QLatin1String( "</td></tr>\n" );
220  j++;
221  }
222  myMetadata += QLatin1String( "</table>\n" ); // End keywords table
223  }
224  myMetadata += QLatin1String( "</td></tr>\n" ); // End of keywords row
225  myMetadata += QLatin1String( "</table>\n" ); // End identification table
226  return myMetadata;
227 }
228 
230 {
231  QString myMetadata;
232  const QStringList historyItems = mMetadata.history();
233  if ( historyItems.isEmpty() )
234  {
235  myMetadata += QStringLiteral( "<p>" ) + tr( "No history yet." ) + QStringLiteral( "</p>\n" );
236  }
237  else
238  {
239  myMetadata += QLatin1String( "<table width=\"100%\" class=\"tabular-view\">\n" );
240  myMetadata += QLatin1String( "<tr><th>" ) + tr( "ID" ) + QLatin1String( "</th><th>" ) + tr( "Action" ) + QLatin1String( "</th></tr>\n" );
241  int i = 1;
242  for ( const QString &history : historyItems )
243  {
244  QString rowClass;
245  if ( i % 2 )
246  rowClass = QStringLiteral( "class=\"odd-row\"" );
247  myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td width=\"5%\">" ) + QString::number( i ) + QLatin1String( "</td><td>" ) + QgsStringUtils::insertLinks( history ) + QLatin1String( "</td></tr>\n" );
248  i++;
249  }
250  myMetadata += QLatin1String( "</table>\n" );
251  }
252  return myMetadata;
253 }
254 
256 {
257  QString myMetadata;
258  const QList<QgsAbstractMetadataBase::Link> &links = mMetadata.links();
259  if ( links.isEmpty() )
260  {
261  myMetadata += QStringLiteral( "<p>" ) + tr( "No links yet." ) + QStringLiteral( "</p>\n" );
262  }
263  else
264  {
265  myMetadata += QLatin1String( "<table width=\"100%\" class=\"tabular-view\">\n" );
266  myMetadata += QLatin1String( "<tr><th>" ) + tr( "ID" ) + QLatin1String( "</th><th>" ) + tr( "Name" ) + QLatin1String( "</th><th>" ) + tr( "Type" ) + QLatin1String( "</th><th>" ) + tr( "URL" ) + QLatin1String( "</th><th>" ) + tr( "Description" ) + QLatin1String( "</th><th>" ) + tr( "Format" ) + QLatin1String( "</th><th>" ) + tr( "MIME Type" ) + QLatin1String( "</th><th>" ) + tr( "Size" ) + QLatin1String( "</th></tr>\n" );
267  int i = 1;
268  for ( const QgsAbstractMetadataBase::Link &link : links )
269  {
270  QString rowClass;
271  if ( i % 2 )
272  rowClass = QStringLiteral( "class=\"odd-row\"" );
273  myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td>" ) + QString::number( i ) + QLatin1String( "</td><td>" ) + link.name + QLatin1String( "</td><td>" ) + link.type + QStringLiteral( "</td><td><a href=\"%1\">%1</a></td><td>" ).arg( link.url ) + link.description + QLatin1String( "</td><td>" ) + link.format + QLatin1String( "</td><td>" ) + link.mimeType + QLatin1String( "</td><td>" ) + link.size + QLatin1String( "</td></tr>\n" );
274  i++;
275  }
276  myMetadata += QLatin1String( "</table>\n" );
277  }
278  return myMetadata;
279 }
QgsAbstractMetadataBase::ContactList contacts() const
Returns a list of contact persons or entities associated with the resource.
QStringList categories() const
Returns categories of the resource.
QString abstract() const
Returns a free-form description of the resource.
QString title() const
Returns the human readable name of the resource, typically displayed in search results.
QStringList history() const
Returns a freeform description of the history or lineage of the resource.
QgsAbstractMetadataBase::KeywordMap keywords() const
Returns the keywords map, which is a set of descriptive keywords associated with the resource.
QgsAbstractMetadataBase::LinkList links() const
Returns a list of online resources associated with the resource.
QString parentIdentifier() const
A reference, URI, URL or some other mechanism to identify the parent resource that this resource is a...
QString language() const
Returns the human language associated with the resource.
QString type() const
Returns the nature of the resource.
QString identifier() const
A reference, URI, URL or some other mechanism to identify the resource.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString userFriendlyIdentifier(IdentifierType type=MediumString) const
Returns a user friendly identifier for the CRS.
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.
const QgsLayerMetadata::Extent & extent() const
Returns the spatial and temporal extents associated with the resource.
QgsLayerMetadata::ConstraintList constraints() const
Returns a list of constraints associated with using the resource.
QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system described by the layer's metadata.
QStringList licenses() const
Returns a list of licenses associated with the resource (examples: http://opendefinition....
QStringList rights() const
Returns a list of attribution or copyright strings associated with the resource.
QString fees() const
Returns any fees associated with using the resource.
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:1498
QString administrativeArea
Administrative area (state, province/territory, etc.).
QString address
Free-form physical address component, e.g.
QString city
City or locality name.
QString type
Type of address, e.g.
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.