Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslayermetadata.cpp 3 : : -------------------- 4 : : begin : April 2017 5 : : copyright : (C) 2017 by Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #include "qgslayermetadata.h" 19 : : #include "qgsmaplayer.h" 20 : : 21 : 0 : QgsLayerMetadata *QgsLayerMetadata::clone() const 22 : : { 23 : 0 : return new QgsLayerMetadata( *this ); 24 : 0 : } 25 : : 26 : 0 : QString QgsLayerMetadata::fees() const 27 : : { 28 : 0 : return mFees; 29 : : } 30 : : 31 : 0 : void QgsLayerMetadata::setFees( const QString &fees ) 32 : : { 33 : 0 : mFees = fees; 34 : 0 : } 35 : : 36 : 0 : void QgsLayerMetadata::addConstraint( const QgsLayerMetadata::Constraint &constraint ) 37 : : { 38 : 0 : mConstraints << constraint; 39 : 0 : } 40 : : 41 : 0 : QList<QgsLayerMetadata::Constraint> QgsLayerMetadata::constraints() const 42 : : { 43 : 0 : return mConstraints; 44 : : } 45 : : 46 : 0 : void QgsLayerMetadata::setConstraints( const QList<Constraint> &constraints ) 47 : : { 48 : 0 : mConstraints = constraints; 49 : 0 : } 50 : : 51 : 0 : QStringList QgsLayerMetadata::rights() const 52 : : { 53 : 0 : return mRights; 54 : : } 55 : : 56 : 0 : void QgsLayerMetadata::setRights( const QStringList &rights ) 57 : : { 58 : 0 : mRights = rights; 59 : 0 : } 60 : : 61 : 0 : QStringList QgsLayerMetadata::licenses() const 62 : : { 63 : 0 : return mLicenses; 64 : : } 65 : : 66 : 0 : void QgsLayerMetadata::setLicenses( const QStringList &licenses ) 67 : : { 68 : 0 : mLicenses = licenses; 69 : 0 : } 70 : : 71 : 0 : QString QgsLayerMetadata::encoding() const 72 : : { 73 : 0 : return mEncoding; 74 : : } 75 : : 76 : 0 : void QgsLayerMetadata::setEncoding( const QString &encoding ) 77 : : { 78 : 0 : mEncoding = encoding; 79 : 0 : } 80 : : 81 : 0 : QgsCoordinateReferenceSystem QgsLayerMetadata::crs() const 82 : : { 83 : 0 : return mCrs; 84 : : } 85 : : 86 : 0 : void QgsLayerMetadata::setCrs( const QgsCoordinateReferenceSystem &crs ) 87 : : { 88 : 0 : mCrs = crs; 89 : 0 : } 90 : : 91 : 0 : void QgsLayerMetadata::saveToLayer( QgsMapLayer *layer ) const 92 : : { 93 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/identifier" ), mIdentifier ); 94 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/parentIdentifier" ), mParentIdentifier ); 95 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/language" ), mLanguage ); 96 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/type" ), mType ); 97 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/title" ), mTitle ); 98 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/extent" ), QVariant::fromValue( mExtent ) ); 99 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/abstract" ), mAbstract ); 100 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/fees" ), mFees ); 101 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/rights" ), mRights ); 102 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/licenses" ), mLicenses ); 103 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/history" ), mHistory ); 104 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/encoding" ), mEncoding ); 105 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/crs" ), mCrs.authid() ); 106 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/constraints" ), QVariant::fromValue( mConstraints ) ); 107 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/keywords" ), QVariant::fromValue( mKeywords ) ); 108 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/contacts" ), QVariant::fromValue( mContacts ) ); 109 : 0 : layer->setCustomProperty( QStringLiteral( "metadata/links" ), QVariant::fromValue( mLinks ) ); 110 : 0 : } 111 : : 112 : 0 : void QgsLayerMetadata::readFromLayer( const QgsMapLayer *layer ) 113 : : { 114 : 0 : mIdentifier = layer->customProperty( QStringLiteral( "metadata/identifier" ) ).toString(); 115 : 0 : mParentIdentifier = layer->customProperty( QStringLiteral( "metadata/parentIdentifier" ) ).toString(); 116 : 0 : mLanguage = layer->customProperty( QStringLiteral( "metadata/language" ) ).toString(); 117 : 0 : mType = layer->customProperty( QStringLiteral( "metadata/type" ) ).toString(); 118 : 0 : mTitle = layer->customProperty( QStringLiteral( "metadata/title" ) ).toString(); 119 : 0 : mAbstract = layer->customProperty( QStringLiteral( "metadata/abstract" ) ).toString(); 120 : 0 : mFees = layer->customProperty( QStringLiteral( "metadata/fees" ) ).toString(); 121 : 0 : mRights = layer->customProperty( QStringLiteral( "metadata/rights" ) ).toStringList(); 122 : 0 : mLicenses = layer->customProperty( QStringLiteral( "metadata/licenses" ) ).toStringList(); 123 : 0 : mHistory = layer->customProperty( QStringLiteral( "metadata/history" ) ).toStringList(); 124 : 0 : mEncoding = layer->customProperty( QStringLiteral( "metadata/encoding" ) ).toString(); 125 : 0 : QString crsAuthId = layer->customProperty( QStringLiteral( "metadata/crs" ) ).toString(); 126 : 0 : mCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crsAuthId ); 127 : 0 : mExtent = layer->customProperty( QStringLiteral( "metadata/extent" ) ).value<Extent>(); 128 : 0 : mConstraints = layer->customProperty( QStringLiteral( "metadata/constraints" ) ).value<ConstraintList>(); 129 : 0 : mKeywords = layer->customProperty( QStringLiteral( "metadata/keywords" ) ).value<QgsAbstractMetadataBase::KeywordMap>(); 130 : 0 : mContacts = layer->customProperty( QStringLiteral( "metadata/contacts" ) ).value<QgsAbstractMetadataBase::ContactList>(); 131 : 0 : mLinks = layer->customProperty( QStringLiteral( "metadata/links" ) ).value<QgsAbstractMetadataBase::LinkList>(); 132 : 0 : } 133 : : 134 : 0 : bool QgsLayerMetadata::readMetadataXml( const QDomElement &metadataElement ) 135 : : { 136 : 0 : QgsAbstractMetadataBase::readMetadataXml( metadataElement ); 137 : : 138 : 0 : QDomNode mnl; 139 : 0 : QDomElement mne; 140 : : 141 : : // set fees 142 : 0 : mnl = metadataElement.namedItem( QStringLiteral( "fees" ) ); 143 : 0 : mFees = mnl.toElement().text(); 144 : : 145 : : // constraints 146 : 0 : QDomNodeList constraintsList = metadataElement.elementsByTagName( QStringLiteral( "constraints" ) ); 147 : 0 : mConstraints.clear(); 148 : 0 : for ( int i = 0; i < constraintsList.size(); i++ ) 149 : : { 150 : 0 : mnl = constraintsList.at( i ); 151 : 0 : mne = mnl.toElement(); 152 : 0 : addConstraint( QgsLayerMetadata::Constraint( mne.text(), mne.attribute( QStringLiteral( "type" ) ) ) ); 153 : 0 : } 154 : : 155 : : // rights 156 : 0 : QDomNodeList rightsNodeList = metadataElement.elementsByTagName( QStringLiteral( "rights" ) ); 157 : 0 : QStringList rightsList; 158 : 0 : for ( int i = 0; i < rightsNodeList.size(); i++ ) 159 : : { 160 : 0 : mnl = rightsNodeList.at( i ); 161 : 0 : mne = mnl.toElement(); 162 : 0 : rightsList.append( mne.text() ); 163 : 0 : } 164 : 0 : setRights( rightsList ); 165 : : 166 : : // licenses 167 : 0 : QDomNodeList licensesNodeList = metadataElement.elementsByTagName( QStringLiteral( "license" ) ); 168 : 0 : QStringList licensesList; 169 : 0 : for ( int i = 0; i < licensesNodeList.size(); i++ ) 170 : : { 171 : 0 : mnl = licensesNodeList.at( i ); 172 : 0 : mne = mnl.toElement(); 173 : 0 : licensesList.append( mne.text() ); 174 : 0 : } 175 : 0 : setLicenses( licensesList ); 176 : : 177 : : // encoding 178 : 0 : mnl = metadataElement.namedItem( QStringLiteral( "encoding" ) ); 179 : 0 : mEncoding = mnl.toElement().text(); 180 : : 181 : : // crs 182 : 0 : mnl = metadataElement.namedItem( QStringLiteral( "crs" ) ); 183 : 0 : if ( !mCrs.readXml( mnl ) ) 184 : 0 : mCrs = QgsCoordinateReferenceSystem(); 185 : : 186 : : // extent 187 : 0 : mnl = metadataElement.namedItem( QStringLiteral( "extent" ) ); 188 : 0 : QgsLayerMetadata::Extent metadataExtent; 189 : : 190 : : // spatial extent 191 : 0 : QDomNodeList spatialList = mnl.toElement().elementsByTagName( QStringLiteral( "spatial" ) ); 192 : 0 : QList< QgsLayerMetadata::SpatialExtent > metadataSpatialExtents; 193 : 0 : for ( int i = 0; i < spatialList.size(); i++ ) 194 : : { 195 : 0 : mnl = spatialList.at( i ); 196 : 0 : mne = mnl.toElement(); 197 : 0 : QgsLayerMetadata::SpatialExtent se = QgsLayerMetadata::SpatialExtent(); 198 : 0 : se.extentCrs = QgsCoordinateReferenceSystem( mne.attribute( QStringLiteral( "crs" ) ) ); 199 : 0 : se.bounds = QgsBox3d(); 200 : 0 : se.bounds.setXMinimum( mne.attribute( QStringLiteral( "minx" ) ).toDouble() ); 201 : 0 : se.bounds.setYMinimum( mne.attribute( QStringLiteral( "miny" ) ).toDouble() ); 202 : 0 : se.bounds.setZMinimum( mne.attribute( QStringLiteral( "minz" ) ).toDouble() ); 203 : 0 : se.bounds.setXMaximum( mne.attribute( QStringLiteral( "maxx" ) ).toDouble() ); 204 : 0 : se.bounds.setYMaximum( mne.attribute( QStringLiteral( "maxy" ) ).toDouble() ); 205 : 0 : se.bounds.setZMaximum( mne.attribute( QStringLiteral( "maxz" ) ).toDouble() ); 206 : 0 : metadataSpatialExtents.append( se ); 207 : 0 : } 208 : 0 : metadataExtent.setSpatialExtents( metadataSpatialExtents ); 209 : : 210 : : // temporal extent 211 : 0 : mnl = metadataElement.namedItem( QStringLiteral( "extent" ) ); 212 : 0 : QDomNodeList temporalList = mnl.toElement().elementsByTagName( QStringLiteral( "temporal" ) ); 213 : 0 : QList<QgsDateTimeRange> metadataDates; 214 : 0 : for ( int j = 0; j < temporalList.size(); j++ ) 215 : : { 216 : 0 : mnl = temporalList.at( j ); 217 : 0 : QDomNodeList instantList = mnl.toElement().elementsByTagName( QStringLiteral( "instant" ) ); 218 : 0 : for ( int i = 0; i < instantList.size(); i++ ) 219 : : { 220 : 0 : mnl = instantList.at( i ); 221 : 0 : QDateTime d = QDateTime().fromString( mnl.toElement().text(), Qt::ISODate ); 222 : 0 : QgsDateTimeRange date = QgsDateTimeRange( d, d ); 223 : 0 : metadataDates << date; 224 : 0 : } 225 : 0 : QDomNodeList periodList = mnl.toElement().elementsByTagName( QStringLiteral( "period" ) ); 226 : 0 : for ( int i = 0; i < periodList.size(); i++ ) 227 : : { 228 : 0 : QDomNode begin = periodList.at( i ).namedItem( QStringLiteral( "start" ) ); 229 : 0 : QDomNode end = periodList.at( i ).namedItem( QStringLiteral( "end" ) ); 230 : 0 : QDateTime beginDate = QDateTime().fromString( begin.toElement().text(), Qt::ISODate ); 231 : 0 : QDateTime endDate = QDateTime().fromString( end.toElement().text(), Qt::ISODate ); 232 : 0 : QgsDateTimeRange date = QgsDateTimeRange( beginDate, endDate ); 233 : 0 : metadataDates << date; 234 : 0 : } 235 : 0 : } 236 : 0 : metadataExtent.setTemporalExtents( metadataDates ); 237 : 0 : setExtent( metadataExtent ); 238 : : 239 : : return true; 240 : 0 : } 241 : : 242 : 0 : bool QgsLayerMetadata::writeMetadataXml( QDomElement &metadataElement, QDomDocument &document ) const 243 : : { 244 : 0 : QgsAbstractMetadataBase::writeMetadataXml( metadataElement, document ); 245 : : 246 : : // fees 247 : 0 : QDomElement fees = document.createElement( QStringLiteral( "fees" ) ); 248 : 0 : QDomText feesText = document.createTextNode( mFees ); 249 : 0 : fees.appendChild( feesText ); 250 : 0 : metadataElement.appendChild( fees ); 251 : : 252 : : // constraints 253 : 0 : for ( const QgsLayerMetadata::Constraint &constraint : mConstraints ) 254 : : { 255 : 0 : QDomElement constraintElement = document.createElement( QStringLiteral( "constraints" ) ); 256 : 0 : constraintElement.setAttribute( QStringLiteral( "type" ), constraint.type ); 257 : 0 : QDomText constraintText = document.createTextNode( constraint.constraint ); 258 : 0 : constraintElement.appendChild( constraintText ); 259 : 0 : metadataElement.appendChild( constraintElement ); 260 : 0 : } 261 : : 262 : : // rights 263 : 0 : for ( const QString &right : mRights ) 264 : : { 265 : 0 : QDomElement rightElement = document.createElement( QStringLiteral( "rights" ) ); 266 : 0 : QDomText rightText = document.createTextNode( right ); 267 : 0 : rightElement.appendChild( rightText ); 268 : 0 : metadataElement.appendChild( rightElement ); 269 : 0 : } 270 : : 271 : : // license 272 : 0 : for ( const QString &license : mLicenses ) 273 : : { 274 : 0 : QDomElement licenseElement = document.createElement( QStringLiteral( "license" ) ); 275 : 0 : QDomText licenseText = document.createTextNode( license ); 276 : 0 : licenseElement.appendChild( licenseText ); 277 : 0 : metadataElement.appendChild( licenseElement ); 278 : 0 : } 279 : : 280 : : // encoding 281 : 0 : QDomElement encoding = document.createElement( QStringLiteral( "encoding" ) ); 282 : 0 : QDomText encodingText = document.createTextNode( mEncoding ); 283 : 0 : encoding.appendChild( encodingText ); 284 : 0 : metadataElement.appendChild( encoding ); 285 : : 286 : : // crs 287 : 0 : QDomElement crsElement = document.createElement( QStringLiteral( "crs" ) ); 288 : 0 : mCrs.writeXml( crsElement, document ); 289 : 0 : metadataElement.appendChild( crsElement ); 290 : : 291 : : // extent 292 : 0 : QDomElement extentElement = document.createElement( QStringLiteral( "extent" ) ); 293 : : 294 : : // spatial extents 295 : 0 : const QList< QgsLayerMetadata::SpatialExtent > sExtents = extent().spatialExtents(); 296 : 0 : for ( const QgsLayerMetadata::SpatialExtent &spatialExtent : sExtents ) 297 : : { 298 : 0 : QDomElement spatialElement = document.createElement( QStringLiteral( "spatial" ) ); 299 : : // Dimensions fixed in the XSD 300 : 0 : spatialElement.setAttribute( QStringLiteral( "dimensions" ), QStringLiteral( "2" ) ); 301 : 0 : spatialElement.setAttribute( QStringLiteral( "crs" ), spatialExtent.extentCrs.authid() ); 302 : 0 : spatialElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( spatialExtent.bounds.xMinimum() ) ); 303 : 0 : spatialElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( spatialExtent.bounds.yMinimum() ) ); 304 : 0 : spatialElement.setAttribute( QStringLiteral( "minz" ), qgsDoubleToString( spatialExtent.bounds.zMinimum() ) ); 305 : 0 : spatialElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( spatialExtent.bounds.xMaximum() ) ); 306 : 0 : spatialElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( spatialExtent.bounds.yMaximum() ) ); 307 : 0 : spatialElement.setAttribute( QStringLiteral( "maxz" ), qgsDoubleToString( spatialExtent.bounds.zMaximum() ) ); 308 : 0 : extentElement.appendChild( spatialElement ); 309 : 0 : } 310 : : 311 : : // temporal extents 312 : 0 : const QList< QgsDateTimeRange > tExtents = extent().temporalExtents(); 313 : 0 : for ( const QgsDateTimeRange &temporalExtent : tExtents ) 314 : : { 315 : 0 : QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) ); 316 : 0 : if ( temporalExtent.isInstant() ) 317 : : { 318 : 0 : QDomElement instantElement = document.createElement( QStringLiteral( "instant" ) ); 319 : 0 : QDomText instantText = document.createTextNode( temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) ); 320 : 0 : instantElement.appendChild( instantText ); 321 : 0 : temporalElement.appendChild( instantElement ); 322 : 0 : } 323 : : else 324 : : { 325 : 0 : QDomElement periodElement = document.createElement( QStringLiteral( "period" ) ); 326 : 0 : QDomElement startElement = document.createElement( QStringLiteral( "start" ) ); 327 : 0 : QDomElement endElement = document.createElement( QStringLiteral( "end" ) ); 328 : 0 : QDomText startText = document.createTextNode( temporalExtent.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) ); 329 : 0 : QDomText endText = document.createTextNode( temporalExtent.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) ); 330 : 0 : startElement.appendChild( startText ); 331 : 0 : endElement.appendChild( endText ); 332 : 0 : periodElement.appendChild( startElement ); 333 : 0 : periodElement.appendChild( endElement ); 334 : 0 : temporalElement.appendChild( periodElement ); 335 : 0 : } 336 : 0 : extentElement.appendChild( temporalElement ); 337 : 0 : } 338 : : 339 : 0 : metadataElement.appendChild( extentElement ); 340 : : 341 : : return true; 342 : 0 : } 343 : : 344 : 0 : const QgsLayerMetadata::Extent &QgsLayerMetadata::extent() const 345 : : { 346 : 0 : return mExtent; 347 : : } 348 : : 349 : 0 : QgsLayerMetadata::Extent &QgsLayerMetadata::extent() 350 : : { 351 : 0 : return mExtent; 352 : : } 353 : : 354 : 0 : void QgsLayerMetadata::setExtent( const Extent &extent ) 355 : : { 356 : 0 : mExtent = extent; 357 : 0 : } 358 : : 359 : 0 : QList<QgsLayerMetadata::SpatialExtent> QgsLayerMetadata::Extent::spatialExtents() const 360 : : { 361 : 0 : return mSpatialExtents; 362 : : } 363 : : 364 : 0 : void QgsLayerMetadata::Extent::setSpatialExtents( const QList<QgsLayerMetadata::SpatialExtent> &spatialExtents ) 365 : : { 366 : 0 : mSpatialExtents = spatialExtents; 367 : 0 : } 368 : : 369 : 0 : QList<QgsDateTimeRange> QgsLayerMetadata::Extent::temporalExtents() const 370 : : { 371 : 0 : return mTemporalExtents; 372 : : } 373 : : 374 : 0 : void QgsLayerMetadata::Extent::setTemporalExtents( const QList<QgsDateTimeRange> &temporalExtents ) 375 : : { 376 : 0 : mTemporalExtents = temporalExtents; 377 : 0 : } 378 : : 379 : 0 : bool QgsLayerMetadata::Extent::operator==( const QgsLayerMetadata::Extent &other ) const 380 : : { 381 : 0 : return mSpatialExtents == other.mSpatialExtents && mTemporalExtents == other.mTemporalExtents; 382 : : } 383 : : 384 : 0 : bool QgsLayerMetadata::operator==( const QgsLayerMetadata &other ) const 385 : : { 386 : 0 : return equals( other ) && 387 : 0 : mFees == other.mFees && 388 : 0 : mConstraints == other.mConstraints && 389 : 0 : mRights == other.mRights && 390 : 0 : mLicenses == other.mLicenses && 391 : 0 : mEncoding == other.mEncoding && 392 : 0 : mCrs == other.mCrs && 393 : 0 : mExtent == other.mExtent; 394 : : } 395 : : 396 : 0 : bool QgsLayerMetadata::SpatialExtent::operator==( const QgsLayerMetadata::SpatialExtent &other ) const 397 : : { 398 : 0 : return extentCrs == other.extentCrs && 399 : 0 : bounds == other.bounds; 400 : : } 401 : : 402 : 0 : bool QgsLayerMetadata::Constraint::operator==( const QgsLayerMetadata::Constraint &other ) const 403 : : { 404 : 0 : return type == other.type && constraint == other.constraint; 405 : : }