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 18 #include "qgslayermetadataformatter.h" 19 #include "qgslayermetadata.h" 20 #include "qgsstringutils.h" 21 QgsLayerMetadataFormatter(const QgsLayerMetadata & metadata)22QgsLayerMetadataFormatter::QgsLayerMetadataFormatter( const QgsLayerMetadata &metadata ) 23 : mMetadata( metadata ) 24 { 25 } 26 accessSectionHtml() const27QString QgsLayerMetadataFormatter::accessSectionHtml() const 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 contactsSectionHtml() const50QString QgsLayerMetadataFormatter::contactsSectionHtml() const 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 extentSectionHtml(const bool showSpatialExtent) const110QString 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 identificationSectionHtml() const180QString QgsLayerMetadataFormatter::identificationSectionHtml() const 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 historySectionHtml() const229QString QgsLayerMetadataFormatter::historySectionHtml() const 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 linksSectionHtml() const255QString QgsLayerMetadataFormatter::linksSectionHtml() const 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 } 280