QGIS API Documentation  3.17.0-Master (a035f434f4)
qgsmaplayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaplayer.cpp - description
3  -------------------
4  begin : Fri Jun 28 2002
5  copyright : (C) 2002 by Gary E.Sherman
6  email : sherman at mrcc.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 
19 #include <QDir>
20 #include <QDomDocument>
21 #include <QDomElement>
22 #include <QDomImplementation>
23 #include <QDomNode>
24 #include <QFile>
25 #include <QFileInfo>
26 #include <QTextStream>
27 #include <QUrl>
28 
29 #include <sqlite3.h>
30 
31 #include "qgssqliteutils.h"
32 
33 #include "qgssqliteutils.h"
34 #include "qgs3drendererregistry.h"
35 #include "qgsabstract3drenderer.h"
36 #include "qgsapplication.h"
38 #include "qgsdatasourceuri.h"
39 #include "qgslogger.h"
40 #include "qgsauthmanager.h"
41 #include "qgsmaplayer.h"
42 #include "qgsmaplayerlegend.h"
44 #include "qgsmeshlayer.h"
45 #include "qgspathresolver.h"
47 #include "qgsproject.h"
48 #include "qgsproviderregistry.h"
49 #include "qgsrasterlayer.h"
50 #include "qgsreadwritecontext.h"
51 #include "qgsrectangle.h"
52 #include "qgsvectorlayer.h"
53 #include "qgsvectordataprovider.h"
54 #include "qgsxmlutils.h"
55 #include "qgsstringutils.h"
57 
59 {
60  switch ( type )
61  {
62  case Metadata:
63  return QStringLiteral( ".qmd" );
64 
65  case Style:
66  return QStringLiteral( ".qml" );
67  }
68  return QString();
69 }
70 
72  const QString &lyrname,
73  const QString &source )
74  : mDataSource( source )
75  , mLayerName( lyrname )
76  , mLayerType( type )
77  , mUndoStack( new QUndoStack( this ) )
78  , mUndoStackStyles( new QUndoStack( this ) )
79  , mStyleManager( new QgsMapLayerStyleManager( this ) )
80  , mRefreshTimer( new QTimer( this ) )
81 {
82  mID = generateId( lyrname );
83  connect( this, &QgsMapLayer::crsChanged, this, &QgsMapLayer::configChanged );
84  connect( this, &QgsMapLayer::nameChanged, this, &QgsMapLayer::configChanged );
85  connect( mRefreshTimer, &QTimer::timeout, this, [ = ] { triggerRepaint( true ); } );
86 }
87 
89 {
90  delete m3DRenderer;
91  delete mLegend;
92  delete mStyleManager;
93 }
94 
95 void QgsMapLayer::clone( QgsMapLayer *layer ) const
96 {
97  layer->setBlendMode( blendMode() );
98 
99  const auto constStyles = styleManager()->styles();
100  for ( const QString &s : constStyles )
101  {
102  layer->styleManager()->addStyle( s, styleManager()->style( s ) );
103  }
104 
105  layer->setName( name() );
106  layer->setShortName( shortName() );
107  layer->setExtent( extent() );
108  layer->setMaximumScale( maximumScale() );
109  layer->setMinimumScale( minimumScale() );
111  layer->setTitle( title() );
112  layer->setAbstract( abstract() );
113  layer->setKeywordList( keywordList() );
114  layer->setDataUrl( dataUrl() );
115  layer->setDataUrlFormat( dataUrlFormat() );
116  layer->setAttribution( attribution() );
117  layer->setAttributionUrl( attributionUrl() );
118  layer->setMetadataUrl( metadataUrl() );
121  layer->setLegendUrl( legendUrl() );
123  layer->setDependencies( dependencies() );
125  layer->setCrs( crs() );
126  layer->setCustomProperties( mCustomProperties );
127  layer->setOpacity( mLayerOpacity );
128 }
129 
131 {
132  return mLayerType;
133 }
134 
135 QgsMapLayer::LayerFlags QgsMapLayer::flags() const
136 {
137  return mFlags;
138 }
139 
140 void QgsMapLayer::setFlags( QgsMapLayer::LayerFlags flags )
141 {
142  if ( flags == mFlags )
143  return;
144 
145  mFlags = flags;
146  emit flagsChanged();
147 }
148 
149 QString QgsMapLayer::id() const
150 {
151  return mID;
152 }
153 
154 void QgsMapLayer::setName( const QString &name )
155 {
156  if ( name == mLayerName )
157  return;
158 
159  mLayerName = name;
160 
161  emit nameChanged();
162 }
163 
164 QString QgsMapLayer::name() const
165 {
166  QgsDebugMsgLevel( "returning name '" + mLayerName + '\'', 4 );
167  return mLayerName;
168 }
169 
171 {
172  return nullptr;
173 }
174 
176 {
177  return nullptr;
178 }
179 
180 QString QgsMapLayer::shortName() const
181 {
182  return mShortName;
183 }
184 
186 {
187  // Redo this every time we're asked for it, as we don't know if
188  // dataSource has changed.
189  QString safeName = QgsDataSourceUri::removePassword( mDataSource );
190  return safeName;
191 }
192 
193 QString QgsMapLayer::source() const
194 {
195  return mDataSource;
196 }
197 
199 {
200  return mExtent;
201 }
202 
203 void QgsMapLayer::setBlendMode( const QPainter::CompositionMode blendMode )
204 {
205  if ( mBlendMode == blendMode )
206  return;
207 
208  mBlendMode = blendMode;
209  emit blendModeChanged( blendMode );
210  emit styleChanged();
211 }
212 
213 QPainter::CompositionMode QgsMapLayer::blendMode() const
214 {
215  return mBlendMode;
216 }
217 
219 {
220  if ( qgsDoubleNear( mLayerOpacity, opacity ) )
221  return;
223  emit opacityChanged( opacity );
224  emit styleChanged();
225 }
226 
227 double QgsMapLayer::opacity() const
228 {
229  return mLayerOpacity;
230 }
231 
232 bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags )
233 {
234  bool layerError;
235  mReadFlags = flags;
236 
237  QDomNode mnl;
238  QDomElement mne;
239 
240  // read provider
241  QString provider;
242  mnl = layerElement.namedItem( QStringLiteral( "provider" ) );
243  mne = mnl.toElement();
244  provider = mne.text();
245 
246  // set data source
247  mnl = layerElement.namedItem( QStringLiteral( "datasource" ) );
248  mne = mnl.toElement();
249  mDataSource = mne.text();
250 
251  // if the layer needs authentication, ensure the master password is set
252  QRegExp rx( "authcfg=([a-z]|[A-Z]|[0-9]){7}" );
253  if ( ( rx.indexIn( mDataSource ) != -1 )
255  {
256  return false;
257  }
258 
259  mDataSource = decodedSource( mDataSource, provider, context );
260 
261  // Set the CRS from project file, asking the user if necessary.
262  // Make it the saved CRS to have WMS layer projected correctly.
263  // We will still overwrite whatever GDAL etc picks up anyway
264  // further down this function.
265  mnl = layerElement.namedItem( QStringLiteral( "layername" ) );
266  mne = mnl.toElement();
267 
269  CUSTOM_CRS_VALIDATION savedValidation;
270 
271  QDomNode srsNode = layerElement.namedItem( QStringLiteral( "srs" ) );
272  mCRS.readXml( srsNode );
273  mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( mne.text() ) );
275  mCRS.validate();
276  savedCRS = mCRS;
277 
278  // Do not validate any projections in children, they will be overwritten anyway.
279  // No need to ask the user for a projections when it is overwritten, is there?
282 
283  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Layer" ), mne.text() );
284 
285  // the internal name is just the data source basename
286  //QFileInfo dataSourceFileInfo( mDataSource );
287  //internalName = dataSourceFileInfo.baseName();
288 
289  // set ID
290  mnl = layerElement.namedItem( QStringLiteral( "id" ) );
291  if ( ! mnl.isNull() )
292  {
293  mne = mnl.toElement();
294  if ( ! mne.isNull() && mne.text().length() > 10 ) // should be at least 17 (yyyyMMddhhmmsszzz)
295  {
296  mID = mne.text();
297  }
298  }
299 
300  setAutoRefreshInterval( layerElement.attribute( QStringLiteral( "autoRefreshTime" ), QStringLiteral( "0" ) ).toInt() );
301  setAutoRefreshEnabled( layerElement.attribute( QStringLiteral( "autoRefreshEnabled" ), QStringLiteral( "0" ) ).toInt() );
302  setRefreshOnNofifyMessage( layerElement.attribute( QStringLiteral( "refreshOnNotifyMessage" ), QString() ) );
303  setRefreshOnNotifyEnabled( layerElement.attribute( QStringLiteral( "refreshOnNotifyEnabled" ), QStringLiteral( "0" ) ).toInt() );
304 
305  // set name
306  mnl = layerElement.namedItem( QStringLiteral( "layername" ) );
307  mne = mnl.toElement();
308 
309  //name can be translated
310  setName( context.projectTranslator()->translate( QStringLiteral( "project:layers:%1" ).arg( layerElement.namedItem( QStringLiteral( "id" ) ).toElement().text() ), mne.text() ) );
311 
312  // now let the children grab what they need from the Dom node.
313  layerError = !readXml( layerElement, context );
314 
315  // overwrite CRS with what we read from project file before the raster/vector
316  // file reading functions changed it. They will if projections is specified in the file.
317  // FIXME: is this necessary? Yes, it is (autumn 2019)
319  mCRS = savedCRS;
320 
321  //short name
322  QDomElement shortNameElem = layerElement.firstChildElement( QStringLiteral( "shortname" ) );
323  if ( !shortNameElem.isNull() )
324  {
325  mShortName = shortNameElem.text();
326  }
327 
328  //title
329  QDomElement titleElem = layerElement.firstChildElement( QStringLiteral( "title" ) );
330  if ( !titleElem.isNull() )
331  {
332  mTitle = titleElem.text();
333  }
334 
335  //abstract
336  QDomElement abstractElem = layerElement.firstChildElement( QStringLiteral( "abstract" ) );
337  if ( !abstractElem.isNull() )
338  {
339  mAbstract = abstractElem.text();
340  }
341 
342  //keywordList
343  QDomElement keywordListElem = layerElement.firstChildElement( QStringLiteral( "keywordList" ) );
344  if ( !keywordListElem.isNull() )
345  {
346  QStringList kwdList;
347  for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
348  {
349  kwdList << n.toElement().text();
350  }
351  mKeywordList = kwdList.join( QLatin1String( ", " ) );
352  }
353 
354  //metadataUrl
355  QDomElement dataUrlElem = layerElement.firstChildElement( QStringLiteral( "dataUrl" ) );
356  if ( !dataUrlElem.isNull() )
357  {
358  mDataUrl = dataUrlElem.text();
359  mDataUrlFormat = dataUrlElem.attribute( QStringLiteral( "format" ), QString() );
360  }
361 
362  //legendUrl
363  QDomElement legendUrlElem = layerElement.firstChildElement( QStringLiteral( "legendUrl" ) );
364  if ( !legendUrlElem.isNull() )
365  {
366  mLegendUrl = legendUrlElem.text();
367  mLegendUrlFormat = legendUrlElem.attribute( QStringLiteral( "format" ), QString() );
368  }
369 
370  //attribution
371  QDomElement attribElem = layerElement.firstChildElement( QStringLiteral( "attribution" ) );
372  if ( !attribElem.isNull() )
373  {
374  mAttribution = attribElem.text();
375  mAttributionUrl = attribElem.attribute( QStringLiteral( "href" ), QString() );
376  }
377 
378  //metadataUrl
379  QDomElement metaUrlElem = layerElement.firstChildElement( QStringLiteral( "metadataUrl" ) );
380  if ( !metaUrlElem.isNull() )
381  {
382  mMetadataUrl = metaUrlElem.text();
383  mMetadataUrlType = metaUrlElem.attribute( QStringLiteral( "type" ), QString() );
384  mMetadataUrlFormat = metaUrlElem.attribute( QStringLiteral( "format" ), QString() );
385  }
386 
387  // mMetadata.readFromLayer( this );
388  QDomElement metadataElem = layerElement.firstChildElement( QStringLiteral( "resourceMetadata" ) );
389  mMetadata.readMetadataXml( metadataElem );
390 
391  return ! layerError;
392 } // bool QgsMapLayer::readLayerXML
393 
394 
395 bool QgsMapLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
396 {
397  Q_UNUSED( layer_node )
398  Q_UNUSED( context )
399  // NOP by default; children will over-ride with behavior specific to them
400 
401  return true;
402 } // void QgsMapLayer::readXml
403 
404 
405 bool QgsMapLayer::writeLayerXml( QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context ) const
406 {
407  if ( !extent().isNull() )
408  {
409  layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent, document ) );
410  }
411 
412  layerElement.setAttribute( QStringLiteral( "autoRefreshTime" ), QString::number( mRefreshTimer->interval() ) );
413  layerElement.setAttribute( QStringLiteral( "autoRefreshEnabled" ), mRefreshTimer->isActive() ? 1 : 0 );
414  layerElement.setAttribute( QStringLiteral( "refreshOnNotifyEnabled" ), mIsRefreshOnNofifyEnabled ? 1 : 0 );
415  layerElement.setAttribute( QStringLiteral( "refreshOnNotifyMessage" ), mRefreshOnNofifyMessage );
416 
417 
418  // ID
419  QDomElement layerId = document.createElement( QStringLiteral( "id" ) );
420  QDomText layerIdText = document.createTextNode( id() );
421  layerId.appendChild( layerIdText );
422 
423  layerElement.appendChild( layerId );
424 
425  // data source
426  QDomElement dataSource = document.createElement( QStringLiteral( "datasource" ) );
427  QString src = encodedSource( source(), context );
428  QDomText dataSourceText = document.createTextNode( src );
429  dataSource.appendChild( dataSourceText );
430  layerElement.appendChild( dataSource );
431 
432  // layer name
433  QDomElement layerName = document.createElement( QStringLiteral( "layername" ) );
434  QDomText layerNameText = document.createTextNode( name() );
435  layerName.appendChild( layerNameText );
436  layerElement.appendChild( layerName );
437 
438  // layer short name
439  if ( !mShortName.isEmpty() )
440  {
441  QDomElement layerShortName = document.createElement( QStringLiteral( "shortname" ) );
442  QDomText layerShortNameText = document.createTextNode( mShortName );
443  layerShortName.appendChild( layerShortNameText );
444  layerElement.appendChild( layerShortName );
445  }
446 
447  // layer title
448  if ( !mTitle.isEmpty() )
449  {
450  QDomElement layerTitle = document.createElement( QStringLiteral( "title" ) );
451  QDomText layerTitleText = document.createTextNode( mTitle );
452  layerTitle.appendChild( layerTitleText );
453  layerElement.appendChild( layerTitle );
454  }
455 
456  // layer abstract
457  if ( !mAbstract.isEmpty() )
458  {
459  QDomElement layerAbstract = document.createElement( QStringLiteral( "abstract" ) );
460  QDomText layerAbstractText = document.createTextNode( mAbstract );
461  layerAbstract.appendChild( layerAbstractText );
462  layerElement.appendChild( layerAbstract );
463  }
464 
465  // layer keyword list
466  QStringList keywordStringList = keywordList().split( ',' );
467  if ( !keywordStringList.isEmpty() )
468  {
469  QDomElement layerKeywordList = document.createElement( QStringLiteral( "keywordList" ) );
470  for ( int i = 0; i < keywordStringList.size(); ++i )
471  {
472  QDomElement layerKeywordValue = document.createElement( QStringLiteral( "value" ) );
473  QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
474  layerKeywordValue.appendChild( layerKeywordText );
475  layerKeywordList.appendChild( layerKeywordValue );
476  }
477  layerElement.appendChild( layerKeywordList );
478  }
479 
480  // layer metadataUrl
481  QString aDataUrl = dataUrl();
482  if ( !aDataUrl.isEmpty() )
483  {
484  QDomElement layerDataUrl = document.createElement( QStringLiteral( "dataUrl" ) );
485  QDomText layerDataUrlText = document.createTextNode( aDataUrl );
486  layerDataUrl.appendChild( layerDataUrlText );
487  layerDataUrl.setAttribute( QStringLiteral( "format" ), dataUrlFormat() );
488  layerElement.appendChild( layerDataUrl );
489  }
490 
491  // layer legendUrl
492  QString aLegendUrl = legendUrl();
493  if ( !aLegendUrl.isEmpty() )
494  {
495  QDomElement layerLegendUrl = document.createElement( QStringLiteral( "legendUrl" ) );
496  QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
497  layerLegendUrl.appendChild( layerLegendUrlText );
498  layerLegendUrl.setAttribute( QStringLiteral( "format" ), legendUrlFormat() );
499  layerElement.appendChild( layerLegendUrl );
500  }
501 
502  // layer attribution
503  QString aAttribution = attribution();
504  if ( !aAttribution.isEmpty() )
505  {
506  QDomElement layerAttribution = document.createElement( QStringLiteral( "attribution" ) );
507  QDomText layerAttributionText = document.createTextNode( aAttribution );
508  layerAttribution.appendChild( layerAttributionText );
509  layerAttribution.setAttribute( QStringLiteral( "href" ), attributionUrl() );
510  layerElement.appendChild( layerAttribution );
511  }
512 
513  // layer metadataUrl
514  QString aMetadataUrl = metadataUrl();
515  if ( !aMetadataUrl.isEmpty() )
516  {
517  QDomElement layerMetadataUrl = document.createElement( QStringLiteral( "metadataUrl" ) );
518  QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
519  layerMetadataUrl.appendChild( layerMetadataUrlText );
520  layerMetadataUrl.setAttribute( QStringLiteral( "type" ), metadataUrlType() );
521  layerMetadataUrl.setAttribute( QStringLiteral( "format" ), metadataUrlFormat() );
522  layerElement.appendChild( layerMetadataUrl );
523  }
524 
525  // timestamp if supported
526  if ( timestamp() > QDateTime() )
527  {
528  QDomElement stamp = document.createElement( QStringLiteral( "timestamp" ) );
529  QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
530  stamp.appendChild( stampText );
531  layerElement.appendChild( stamp );
532  }
533 
534  layerElement.appendChild( layerName );
535 
536  // zorder
537  // This is no longer stored in the project file. It is superfluous since the layers
538  // are written and read in the proper order.
539 
540  // spatial reference system id
541  QDomElement mySrsElement = document.createElement( QStringLiteral( "srs" ) );
542  mCRS.writeXml( mySrsElement, document );
543  layerElement.appendChild( mySrsElement );
544 
545  // layer metadata
546  QDomElement myMetadataElem = document.createElement( QStringLiteral( "resourceMetadata" ) );
547  mMetadata.writeMetadataXml( myMetadataElem, document );
548  layerElement.appendChild( myMetadataElem );
549 
550  // now append layer node to map layer node
551  return writeXml( layerElement, document, context );
552 }
553 
554 void QgsMapLayer::writeCommonStyle( QDomElement &layerElement, QDomDocument &document,
555  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
556 {
557  // save categories
558  QMetaEnum metaEnum = QMetaEnum::fromType<QgsMapLayer::StyleCategories>();
559  QString categoriesKeys( metaEnum.valueToKeys( static_cast<int>( categories ) ) );
560  layerElement.setAttribute( QStringLiteral( "styleCategories" ), categoriesKeys );
561 
562  if ( categories.testFlag( Rendering ) )
563  {
564  // use scale dependent visibility flag
565  layerElement.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
566  layerElement.setAttribute( QStringLiteral( "maxScale" ), QString::number( maximumScale() ) );
567  layerElement.setAttribute( QStringLiteral( "minScale" ), QString::number( minimumScale() ) );
568  }
569 
570  if ( categories.testFlag( Symbology3D ) )
571  {
572  if ( m3DRenderer )
573  {
574  QDomElement renderer3DElem = document.createElement( QStringLiteral( "renderer-3d" ) );
575  renderer3DElem.setAttribute( QStringLiteral( "type" ), m3DRenderer->type() );
576  m3DRenderer->writeXml( renderer3DElem, context );
577  layerElement.appendChild( renderer3DElem );
578  }
579  }
580 
581  if ( categories.testFlag( LayerConfiguration ) )
582  {
583  // flags
584  // this code is saving automatically all the flags entries
585  QDomElement layerFlagsElem = document.createElement( QStringLiteral( "flags" ) );
586  auto enumMap = qgsEnumMap<QgsMapLayer::LayerFlag>();
587  for ( auto it = enumMap.constBegin(); it != enumMap.constEnd(); ++it )
588  {
589  bool flagValue = mFlags.testFlag( it.key() );
590  QDomElement flagElem = document.createElement( it.value() );
591  flagElem.appendChild( document.createTextNode( QString::number( flagValue ) ) );
592  layerFlagsElem.appendChild( flagElem );
593  }
594  layerElement.appendChild( layerFlagsElem );
595  }
596 
597  if ( categories.testFlag( Temporal ) )
598  {
599  QgsMapLayerTemporalProperties *lTemporalProperties = const_cast< QgsMapLayer * >( this )->temporalProperties();
600  if ( lTemporalProperties )
601  lTemporalProperties->writeXml( layerElement, document, context );
602  }
603 
604  // custom properties
605  if ( categories.testFlag( CustomProperties ) )
606  {
607  writeCustomProperties( layerElement, document );
608  }
609 }
610 
611 
612 bool QgsMapLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
613 {
614  Q_UNUSED( layer_node )
615  Q_UNUSED( document )
616  Q_UNUSED( context )
617  // NOP by default; children will over-ride with behavior specific to them
618 
619  return true;
620 }
621 
622 QString QgsMapLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
623 {
624  Q_UNUSED( context )
625  return source;
626 }
627 
628 QString QgsMapLayer::decodedSource( const QString &source, const QString &dataProvider, const QgsReadWriteContext &context ) const
629 {
630  Q_UNUSED( context )
631  Q_UNUSED( dataProvider )
632  return source;
633 }
634 
636 {
637  emit beforeResolveReferences( project );
638  if ( m3DRenderer )
639  m3DRenderer->resolveReferences( *project );
640 }
641 
642 
643 void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
644 {
645  mCustomProperties.readXml( layerNode, keyStartsWith );
646 }
647 
648 void QgsMapLayer::writeCustomProperties( QDomNode &layerNode, QDomDocument &doc ) const
649 {
650  mCustomProperties.writeXml( layerNode, doc );
651 }
652 
653 void QgsMapLayer::readStyleManager( const QDomNode &layerNode )
654 {
655  QDomElement styleMgrElem = layerNode.firstChildElement( QStringLiteral( "map-layer-style-manager" ) );
656  if ( !styleMgrElem.isNull() )
657  mStyleManager->readXml( styleMgrElem );
658  else
659  mStyleManager->reset();
660 }
661 
662 void QgsMapLayer::writeStyleManager( QDomNode &layerNode, QDomDocument &doc ) const
663 {
664  if ( mStyleManager )
665  {
666  QDomElement styleMgrElem = doc.createElement( QStringLiteral( "map-layer-style-manager" ) );
667  mStyleManager->writeXml( styleMgrElem );
668  layerNode.appendChild( styleMgrElem );
669  }
670 }
671 
672 bool QgsMapLayer::isValid() const
673 {
674  return mValid;
675 }
676 
677 #if 0
678 void QgsMapLayer::connectNotify( const char *signal )
679 {
680  Q_UNUSED( signal )
681  QgsDebugMsgLevel( "QgsMapLayer connected to " + QString( signal ), 3 );
682 } // QgsMapLayer::connectNotify
683 #endif
684 
685 bool QgsMapLayer::isInScaleRange( double scale ) const
686 {
687  return !mScaleBasedVisibility ||
688  ( ( mMinScale == 0 || mMinScale * Qgis::SCALE_PRECISION < scale )
689  && ( mMaxScale == 0 || scale < mMaxScale ) );
690 }
691 
693 {
694  return mScaleBasedVisibility;
695 }
696 
698 {
699  return mRefreshTimer->isActive();
700 }
701 
703 {
704  return mRefreshTimer->interval();
705 }
706 
708 {
709  if ( interval <= 0 )
710  {
711  mRefreshTimer->stop();
712  mRefreshTimer->setInterval( 0 );
713  }
714  else
715  {
716  mRefreshTimer->setInterval( interval );
717  }
718  emit autoRefreshIntervalChanged( mRefreshTimer->isActive() ? mRefreshTimer->interval() : 0 );
719 }
720 
722 {
723  if ( !enabled )
724  mRefreshTimer->stop();
725  else if ( mRefreshTimer->interval() > 0 )
726  mRefreshTimer->start();
727 
728  emit autoRefreshIntervalChanged( mRefreshTimer->isActive() ? mRefreshTimer->interval() : 0 );
729 }
730 
732 {
733  return mMetadata;
734 }
735 
736 void QgsMapLayer::setMaximumScale( double scale )
737 {
738  mMinScale = scale;
739 }
740 
742 {
743  return mMinScale;
744 }
745 
746 
747 void QgsMapLayer::setMinimumScale( double scale )
748 {
749  mMaxScale = scale;
750 }
751 
752 void QgsMapLayer::setScaleBasedVisibility( const bool enabled )
753 {
754  mScaleBasedVisibility = enabled;
755 }
756 
758 {
759  return mMaxScale;
760 }
761 
762 QStringList QgsMapLayer::subLayers() const
763 {
764  return QStringList(); // Empty
765 }
766 
767 void QgsMapLayer::setLayerOrder( const QStringList &layers )
768 {
769  Q_UNUSED( layers )
770  // NOOP
771 }
772 
773 void QgsMapLayer::setSubLayerVisibility( const QString &name, bool vis )
774 {
775  Q_UNUSED( name )
776  Q_UNUSED( vis )
777  // NOOP
778 }
779 
781 {
782  return mCRS;
783 }
784 
785 void QgsMapLayer::setCrs( const QgsCoordinateReferenceSystem &srs, bool emitSignal )
786 {
787  mCRS = srs;
788 
790  {
791  mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
792  mCRS.validate();
793  }
794 
795  if ( emitSignal )
796  emit crsChanged();
797 }
798 
800 {
801  const QgsDataProvider *lDataProvider = dataProvider();
802  return lDataProvider ? lDataProvider->transformContext() : QgsCoordinateTransformContext();
803 }
804 
805 QString QgsMapLayer::formatLayerName( const QString &name )
806 {
807  QString layerName( name );
808  layerName.replace( '_', ' ' );
810  return layerName;
811 }
812 
813 QString QgsMapLayer::baseURI( PropertyType type ) const
814 {
815  QString myURI = publicSource();
816 
817  // first get base path for delimited text, spatialite and OGR layers,
818  // as in these cases URI may contain layer name and/or additional
819  // information. This also strips prefix in case if VSIFILE mechanism
820  // is used
821  if ( providerType() == QLatin1String( "ogr" ) || providerType() == QLatin1String( "delimitedtext" ) ||
822  providerType() == QLatin1String( "spatialite" ) )
823  {
824  QVariantMap components = QgsProviderRegistry::instance()->decodeUri( providerType(), myURI );
825  myURI = components["path"].toString();
826  }
827 
828  QFileInfo myFileInfo( myURI );
829  QString key;
830 
831  if ( myFileInfo.exists() )
832  {
833  // if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
834  if ( myURI.endsWith( QLatin1String( ".gz" ), Qt::CaseInsensitive ) )
835  myURI.chop( 3 );
836  else if ( myURI.endsWith( QLatin1String( ".zip" ), Qt::CaseInsensitive ) )
837  myURI.chop( 4 );
838  else if ( myURI.endsWith( QLatin1String( ".tar" ), Qt::CaseInsensitive ) )
839  myURI.chop( 4 );
840  else if ( myURI.endsWith( QLatin1String( ".tar.gz" ), Qt::CaseInsensitive ) )
841  myURI.chop( 7 );
842  else if ( myURI.endsWith( QLatin1String( ".tgz" ), Qt::CaseInsensitive ) )
843  myURI.chop( 4 );
844  myFileInfo.setFile( myURI );
845  // get the file name for our .qml style file
846  key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + QgsMapLayer::extensionPropertyType( type );
847  }
848  else
849  {
850  key = publicSource();
851  }
852 
853  return key;
854 }
855 
857 {
858  return baseURI( PropertyType::Metadata );
859 }
860 
861 QString QgsMapLayer::saveDefaultMetadata( bool &resultFlag )
862 {
863  return saveNamedMetadata( metadataUri(), resultFlag );
864 }
865 
866 QString QgsMapLayer::loadDefaultMetadata( bool &resultFlag )
867 {
868  return loadNamedMetadata( metadataUri(), resultFlag );
869 }
870 
871 QString QgsMapLayer::styleURI() const
872 {
873  return baseURI( PropertyType::Style );
874 }
875 
876 QString QgsMapLayer::loadDefaultStyle( bool &resultFlag )
877 {
878  return loadNamedStyle( styleURI(), resultFlag );
879 }
880 
881 bool QgsMapLayer::loadNamedMetadataFromDatabase( const QString &db, const QString &uri, QString &qmd )
882 {
883  return loadNamedPropertyFromDatabase( db, uri, qmd, PropertyType::Metadata );
884 }
885 
886 bool QgsMapLayer::loadNamedStyleFromDatabase( const QString &db, const QString &uri, QString &qml )
887 {
888  return loadNamedPropertyFromDatabase( db, uri, qml, PropertyType::Style );
889 }
890 
891 bool QgsMapLayer::loadNamedPropertyFromDatabase( const QString &db, const QString &uri, QString &xml, QgsMapLayer::PropertyType type )
892 {
893  QgsDebugMsgLevel( QStringLiteral( "db = %1 uri = %2" ).arg( db, uri ), 4 );
894 
895  bool resultFlag = false;
896 
897  // read from database
900 
901  int myResult;
902 
903  QgsDebugMsgLevel( QStringLiteral( "Trying to load style or metadata for \"%1\" from \"%2\"" ).arg( uri, db ), 4 );
904 
905  if ( db.isEmpty() || !QFile( db ).exists() )
906  return false;
907 
908  myResult = database.open_v2( db, SQLITE_OPEN_READONLY, nullptr );
909  if ( myResult != SQLITE_OK )
910  {
911  return false;
912  }
913 
914  QString mySql;
915  switch ( type )
916  {
917  case Metadata:
918  mySql = QStringLiteral( "select qmd from tbl_metadata where metadata=?" );
919  break;
920 
921  case Style:
922  mySql = QStringLiteral( "select qml from tbl_styles where style=?" );
923  break;
924  }
925 
926  statement = database.prepare( mySql, myResult );
927  if ( myResult == SQLITE_OK )
928  {
929  QByteArray param = uri.toUtf8();
930 
931  if ( sqlite3_bind_text( statement.get(), 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
932  sqlite3_step( statement.get() ) == SQLITE_ROW )
933  {
934  xml = QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( statement.get(), 0 ) ) );
935  resultFlag = true;
936  }
937  }
938  return resultFlag;
939 }
940 
941 
942 QString QgsMapLayer::loadNamedStyle( const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories )
943 {
944  return loadNamedProperty( uri, PropertyType::Style, resultFlag, categories );
945 }
946 
947 QString QgsMapLayer::loadNamedProperty( const QString &uri, QgsMapLayer::PropertyType type, bool &resultFlag, StyleCategories categories )
948 {
949  QgsDebugMsgLevel( QStringLiteral( "uri = %1 myURI = %2" ).arg( uri, publicSource() ), 4 );
950 
951  resultFlag = false;
952 
953  QDomDocument myDocument( QStringLiteral( "qgis" ) );
954 
955  // location of problem associated with errorMsg
956  int line, column;
957  QString myErrorMessage;
958 
959  QFile myFile( uri );
960  if ( myFile.open( QFile::ReadOnly ) )
961  {
962  QgsDebugMsgLevel( QStringLiteral( "file found %1" ).arg( uri ), 2 );
963  // read file
964  resultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
965  if ( !resultFlag )
966  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
967  myFile.close();
968  }
969  else
970  {
971  QFileInfo project( QgsProject::instance()->fileName() );
972  QgsDebugMsgLevel( QStringLiteral( "project fileName: %1" ).arg( project.absoluteFilePath() ), 4 );
973 
974  QString xml;
975  switch ( type )
976  {
977  case QgsMapLayer::Style:
978  {
979  if ( loadNamedStyleFromDatabase( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ), uri, xml ) ||
980  ( project.exists() && loadNamedStyleFromDatabase( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), uri, xml ) ) ||
981  loadNamedStyleFromDatabase( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/qgis.qmldb" ) ), uri, xml ) )
982  {
983  resultFlag = myDocument.setContent( xml, &myErrorMessage, &line, &column );
984  if ( !resultFlag )
985  {
986  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
987  }
988  }
989  else
990  {
991  myErrorMessage = tr( "Style not found in database" );
992  resultFlag = false;
993  }
994  break;
995  }
997  {
998  if ( loadNamedMetadataFromDatabase( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ), uri, xml ) ||
999  ( project.exists() && loadNamedMetadataFromDatabase( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), uri, xml ) ) ||
1000  loadNamedMetadataFromDatabase( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/qgis.qmldb" ) ), uri, xml ) )
1001  {
1002  resultFlag = myDocument.setContent( xml, &myErrorMessage, &line, &column );
1003  if ( !resultFlag )
1004  {
1005  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1006  }
1007  }
1008  else
1009  {
1010  myErrorMessage = tr( "Metadata not found in database" );
1011  resultFlag = false;
1012  }
1013  break;
1014  }
1015  }
1016  }
1017 
1018  if ( !resultFlag )
1019  {
1020  return myErrorMessage;
1021  }
1022 
1023  switch ( type )
1024  {
1025  case QgsMapLayer::Style:
1026  resultFlag = importNamedStyle( myDocument, myErrorMessage, categories );
1027  if ( !resultFlag )
1028  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( uri, myErrorMessage );
1029  break;
1030  case QgsMapLayer::Metadata:
1031  resultFlag = importNamedMetadata( myDocument, myErrorMessage );
1032  if ( !resultFlag )
1033  myErrorMessage = tr( "Loading metadata file %1 failed because:\n%2" ).arg( uri, myErrorMessage );
1034  break;
1035  }
1036  return myErrorMessage;
1037 }
1038 
1039 bool QgsMapLayer::importNamedMetadata( QDomDocument &document, QString &errorMessage )
1040 {
1041  QDomElement myRoot = document.firstChildElement( QStringLiteral( "qgis" ) );
1042  if ( myRoot.isNull() )
1043  {
1044  errorMessage = tr( "Root <qgis> element could not be found" );
1045  return false;
1046  }
1047 
1048  return mMetadata.readMetadataXml( myRoot );
1049 }
1050 
1051 bool QgsMapLayer::importNamedStyle( QDomDocument &myDocument, QString &myErrorMessage, QgsMapLayer::StyleCategories categories )
1052 {
1053  QDomElement myRoot = myDocument.firstChildElement( QStringLiteral( "qgis" ) );
1054  if ( myRoot.isNull() )
1055  {
1056  myErrorMessage = tr( "Root <qgis> element could not be found" );
1057  return false;
1058  }
1059 
1060  // get style file version string, if any
1061  QgsProjectVersion fileVersion( myRoot.attribute( QStringLiteral( "version" ) ) );
1062  QgsProjectVersion thisVersion( Qgis::version() );
1063 
1064  if ( thisVersion > fileVersion )
1065  {
1066  QgsProjectFileTransform styleFile( myDocument, fileVersion );
1067  styleFile.updateRevision( thisVersion );
1068  }
1069 
1070  // Get source categories
1071  QgsMapLayer::StyleCategories sourceCategories = QgsXmlUtils::readFlagAttribute( myRoot, QStringLiteral( "styleCategories" ), QgsMapLayer::AllStyleCategories );
1072 
1073  //Test for matching geometry type on vector layers when applying, if geometry type is given in the style
1074  if ( ( sourceCategories.testFlag( QgsMapLayer::Symbology ) || sourceCategories.testFlag( QgsMapLayer::Symbology3D ) ) &&
1075  ( categories.testFlag( QgsMapLayer::Symbology ) || categories.testFlag( QgsMapLayer::Symbology3D ) ) )
1076  {
1077  if ( type() == QgsMapLayerType::VectorLayer && !myRoot.firstChildElement( QStringLiteral( "layerGeometryType" ) ).isNull() )
1078  {
1079  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( this );
1080  QgsWkbTypes::GeometryType importLayerGeometryType = static_cast<QgsWkbTypes::GeometryType>( myRoot.firstChildElement( QStringLiteral( "layerGeometryType" ) ).text().toInt() );
1081  if ( importLayerGeometryType != QgsWkbTypes::GeometryType::UnknownGeometry && vl->geometryType() != importLayerGeometryType )
1082  {
1083  myErrorMessage = tr( "Cannot apply style with symbology to layer with a different geometry type" );
1084  return false;
1085  }
1086  }
1087  }
1088 
1090  return readSymbology( myRoot, myErrorMessage, context, categories ); // TODO: support relative paths in QML?
1091 }
1092 
1093 void QgsMapLayer::exportNamedMetadata( QDomDocument &doc, QString &errorMsg ) const
1094 {
1095  QDomImplementation DomImplementation;
1096  QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1097  QDomDocument myDocument( documentType );
1098 
1099  QDomElement myRootNode = myDocument.createElement( QStringLiteral( "qgis" ) );
1100  myRootNode.setAttribute( QStringLiteral( "version" ), Qgis::version() );
1101  myDocument.appendChild( myRootNode );
1102 
1103  if ( !mMetadata.writeMetadataXml( myRootNode, myDocument ) )
1104  {
1105  errorMsg = QObject::tr( "Could not save metadata" );
1106  return;
1107  }
1108 
1109  doc = myDocument;
1110 }
1111 
1112 void QgsMapLayer::exportNamedStyle( QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1113 {
1114  QDomImplementation DomImplementation;
1115  QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1116  QDomDocument myDocument( documentType );
1117 
1118  QDomElement myRootNode = myDocument.createElement( QStringLiteral( "qgis" ) );
1119  myRootNode.setAttribute( QStringLiteral( "version" ), Qgis::version() );
1120  myDocument.appendChild( myRootNode );
1121 
1122  if ( !writeSymbology( myRootNode, myDocument, errorMsg, context, categories ) ) // TODO: support relative paths in QML?
1123  {
1124  errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1125  return;
1126  }
1127 
1128  /*
1129  * Check to see if the layer is vector - in which case we should also export its geometryType
1130  * to avoid eventually pasting to a layer with a different geometry
1131  */
1133  {
1134  //Getting the selectionLayer geometry
1135  const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( this );
1136  QString geoType = QString::number( vl->geometryType() );
1137 
1138  //Adding geometryinformation
1139  QDomElement layerGeometryType = myDocument.createElement( QStringLiteral( "layerGeometryType" ) );
1140  QDomText type = myDocument.createTextNode( geoType );
1141 
1142  layerGeometryType.appendChild( type );
1143  myRootNode.appendChild( layerGeometryType );
1144  }
1145 
1146  doc = myDocument;
1147 }
1148 
1149 QString QgsMapLayer::saveDefaultStyle( bool &resultFlag )
1150 {
1151  return saveNamedStyle( styleURI(), resultFlag );
1152 }
1153 
1154 QString QgsMapLayer::saveNamedMetadata( const QString &uri, bool &resultFlag )
1155 {
1156  return saveNamedProperty( uri, QgsMapLayer::Metadata, resultFlag );
1157 }
1158 
1159 QString QgsMapLayer::loadNamedMetadata( const QString &uri, bool &resultFlag )
1160 {
1161  return loadNamedProperty( uri, QgsMapLayer::Metadata, resultFlag );
1162 }
1163 
1164 QString QgsMapLayer::saveNamedProperty( const QString &uri, QgsMapLayer::PropertyType type, bool &resultFlag, StyleCategories categories )
1165 {
1166  // check if the uri is a file or ends with .qml/.qmd,
1167  // which indicates that it should become one
1168  // everything else goes to the database
1169  QString filename;
1170 
1171  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1172  if ( vlayer && vlayer->providerType() == QLatin1String( "ogr" ) )
1173  {
1174  QStringList theURIParts = uri.split( '|' );
1175  filename = theURIParts[0];
1176  }
1177  else if ( vlayer && vlayer->providerType() == QLatin1String( "gpx" ) )
1178  {
1179  QStringList theURIParts = uri.split( '?' );
1180  filename = theURIParts[0];
1181  }
1182  else if ( vlayer && vlayer->providerType() == QLatin1String( "delimitedtext" ) )
1183  {
1184  filename = QUrl::fromEncoded( uri.toLatin1() ).toLocalFile();
1185  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1186  if ( filename.isEmpty() )
1187  filename = uri;
1188  }
1189  else
1190  {
1191  filename = uri;
1192  }
1193 
1194  QString myErrorMessage;
1195  QDomDocument myDocument;
1196  switch ( type )
1197  {
1198  case Metadata:
1199  exportNamedMetadata( myDocument, myErrorMessage );
1200  break;
1201 
1202  case Style:
1203  QgsReadWriteContext context;
1204  exportNamedStyle( myDocument, myErrorMessage, context, categories );
1205  break;
1206  }
1207 
1208  QFileInfo myFileInfo( filename );
1209  if ( myFileInfo.exists() || filename.endsWith( QgsMapLayer::extensionPropertyType( type ), Qt::CaseInsensitive ) )
1210  {
1211  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1212  if ( !myDirInfo.isWritable() )
1213  {
1214  return tr( "The directory containing your dataset needs to be writable!" );
1215  }
1216 
1217  // now construct the file name for our .qml or .qmd file
1218  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + QgsMapLayer::extensionPropertyType( type );
1219 
1220  QFile myFile( myFileName );
1221  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1222  {
1223  QTextStream myFileStream( &myFile );
1224  // save as utf-8 with 2 spaces for indents
1225  myDocument.save( myFileStream, 2 );
1226  myFile.close();
1227  resultFlag = true;
1228  switch ( type )
1229  {
1230  case Metadata:
1231  return tr( "Created default metadata file as %1" ).arg( myFileName );
1232 
1233  case Style:
1234  return tr( "Created default style file as %1" ).arg( myFileName );
1235  }
1236 
1237  }
1238  else
1239  {
1240  resultFlag = false;
1241  switch ( type )
1242  {
1243  case Metadata:
1244  return tr( "ERROR: Failed to created default metadata file as %1. Check file permissions and retry." ).arg( myFileName );
1245 
1246  case Style:
1247  return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1248  }
1249  }
1250  }
1251  else
1252  {
1253  QString qml = myDocument.toString();
1254 
1255  // read from database
1256  sqlite3_database_unique_ptr database;
1257  sqlite3_statement_unique_ptr statement;
1258 
1259  int myResult = database.open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ) );
1260  if ( myResult != SQLITE_OK )
1261  {
1262  return tr( "User database could not be opened." );
1263  }
1264 
1265  QByteArray param0 = uri.toUtf8();
1266  QByteArray param1 = qml.toUtf8();
1267 
1268  QString mySql;
1269  switch ( type )
1270  {
1271  case Metadata:
1272  mySql = QStringLiteral( "create table if not exists tbl_metadata(metadata varchar primary key,qmd varchar)" );
1273  break;
1274 
1275  case Style:
1276  mySql = QStringLiteral( "create table if not exists tbl_styles(style varchar primary key,qml varchar)" );
1277  break;
1278  }
1279 
1280  statement = database.prepare( mySql, myResult );
1281  if ( myResult == SQLITE_OK )
1282  {
1283  if ( sqlite3_step( statement.get() ) != SQLITE_DONE )
1284  {
1285  resultFlag = false;
1286  switch ( type )
1287  {
1288  case Metadata:
1289  return tr( "The metadata table could not be created." );
1290 
1291  case Style:
1292  return tr( "The style table could not be created." );
1293  }
1294  }
1295  }
1296 
1297  switch ( type )
1298  {
1299  case Metadata:
1300  mySql = QStringLiteral( "insert into tbl_metadata(metadata,qmd) values (?,?)" );
1301  break;
1302 
1303  case Style:
1304  mySql = QStringLiteral( "insert into tbl_styles(style,qml) values (?,?)" );
1305  break;
1306  }
1307  statement = database.prepare( mySql, myResult );
1308  if ( myResult == SQLITE_OK )
1309  {
1310  if ( sqlite3_bind_text( statement.get(), 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1311  sqlite3_bind_text( statement.get(), 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1312  sqlite3_step( statement.get() ) == SQLITE_DONE )
1313  {
1314  resultFlag = true;
1315  switch ( type )
1316  {
1317  case Metadata:
1318  myErrorMessage = tr( "The metadata %1 was saved to database" ).arg( uri );
1319  break;
1320 
1321  case Style:
1322  myErrorMessage = tr( "The style %1 was saved to database" ).arg( uri );
1323  break;
1324  }
1325  }
1326  }
1327 
1328  if ( !resultFlag )
1329  {
1330  QString mySql;
1331  switch ( type )
1332  {
1333  case Metadata:
1334  mySql = QStringLiteral( "update tbl_metadata set qmd=? where metadata=?" );
1335  break;
1336 
1337  case Style:
1338  mySql = QStringLiteral( "update tbl_styles set qml=? where style=?" );
1339  break;
1340  }
1341  statement = database.prepare( mySql, myResult );
1342  if ( myResult == SQLITE_OK )
1343  {
1344  if ( sqlite3_bind_text( statement.get(), 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1345  sqlite3_bind_text( statement.get(), 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1346  sqlite3_step( statement.get() ) == SQLITE_DONE )
1347  {
1348  resultFlag = true;
1349  switch ( type )
1350  {
1351  case Metadata:
1352  myErrorMessage = tr( "The metadata %1 was updated in the database." ).arg( uri );
1353  break;
1354 
1355  case Style:
1356  myErrorMessage = tr( "The style %1 was updated in the database." ).arg( uri );
1357  break;
1358  }
1359  }
1360  else
1361  {
1362  resultFlag = false;
1363  switch ( type )
1364  {
1365  case Metadata:
1366  myErrorMessage = tr( "The metadata %1 could not be updated in the database." ).arg( uri );
1367  break;
1368 
1369  case Style:
1370  myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( uri );
1371  break;
1372  }
1373  }
1374  }
1375  else
1376  {
1377  resultFlag = false;
1378  switch ( type )
1379  {
1380  case Metadata:
1381  myErrorMessage = tr( "The metadata %1 could not be inserted into database." ).arg( uri );
1382  break;
1383 
1384  case Style:
1385  myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( uri );
1386  break;
1387  }
1388  }
1389  }
1390  }
1391 
1392  return myErrorMessage;
1393 }
1394 
1395 QString QgsMapLayer::saveNamedStyle( const QString &uri, bool &resultFlag, StyleCategories categories )
1396 {
1397  return saveNamedProperty( uri, QgsMapLayer::Style, resultFlag, categories );
1398 }
1399 
1400 void QgsMapLayer::exportSldStyle( QDomDocument &doc, QString &errorMsg ) const
1401 {
1402  QDomDocument myDocument = QDomDocument();
1403 
1404  QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
1405  myDocument.appendChild( header );
1406 
1407  const QgsVectorLayer *vlayer = qobject_cast<const QgsVectorLayer *>( this );
1408  const QgsRasterLayer *rlayer = qobject_cast<const QgsRasterLayer *>( this );
1409  if ( !vlayer && !rlayer )
1410  {
1411  errorMsg = tr( "Could not save symbology because:\n%1" )
1412  .arg( tr( "Only vector and raster layers are supported" ) );
1413  return;
1414  }
1415 
1416  // Create the root element
1417  QDomElement root = myDocument.createElementNS( QStringLiteral( "http://www.opengis.net/sld" ), QStringLiteral( "StyledLayerDescriptor" ) );
1418  QDomElement layerNode;
1419  if ( vlayer )
1420  {
1421  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1.0" ) );
1422  root.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" ) );
1423  root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1424  root.setAttribute( QStringLiteral( "xmlns:se" ), QStringLiteral( "http://www.opengis.net/se" ) );
1425  root.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
1426  root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
1427  myDocument.appendChild( root );
1428 
1429  // Create the NamedLayer element
1430  layerNode = myDocument.createElement( QStringLiteral( "NamedLayer" ) );
1431  root.appendChild( layerNode );
1432  }
1433 
1434  // note: Only SLD 1.0 version is generated because seems none is using SE1.1.0 at least for rasters
1435  if ( rlayer )
1436  {
1437  // Create the root element
1438  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
1439  root.setAttribute( QStringLiteral( "xmlns:gml" ), QStringLiteral( "http://www.opengis.net/gml" ) );
1440  root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1441  root.setAttribute( QStringLiteral( "xmlns:sld" ), QStringLiteral( "http://www.opengis.net/sld" ) );
1442  myDocument.appendChild( root );
1443 
1444  // Create the NamedLayer element
1445  layerNode = myDocument.createElement( QStringLiteral( "UserLayer" ) );
1446  root.appendChild( layerNode );
1447  }
1448 
1449  QgsStringMap props;
1450  if ( hasScaleBasedVisibility() )
1451  {
1452  props[ QStringLiteral( "scaleMinDenom" ) ] = QString::number( mMinScale );
1453  props[ QStringLiteral( "scaleMaxDenom" ) ] = QString::number( mMaxScale );
1454  }
1455 
1456  if ( vlayer )
1457  {
1458  if ( !vlayer->writeSld( layerNode, myDocument, errorMsg, props ) )
1459  {
1460  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1461  return;
1462  }
1463  }
1464 
1465  if ( rlayer )
1466  {
1467  if ( !rlayer->writeSld( layerNode, myDocument, errorMsg, props ) )
1468  {
1469  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1470  return;
1471  }
1472  }
1473 
1474  doc = myDocument;
1475 }
1476 
1477 QString QgsMapLayer::saveSldStyle( const QString &uri, bool &resultFlag ) const
1478 {
1479  const QgsMapLayer *mlayer = qobject_cast<const QgsMapLayer *>( this );
1480 
1481  QString errorMsg;
1482  QDomDocument myDocument;
1483  mlayer->exportSldStyle( myDocument, errorMsg );
1484  if ( !errorMsg.isNull() )
1485  {
1486  resultFlag = false;
1487  return errorMsg;
1488  }
1489  // check if the uri is a file or ends with .sld,
1490  // which indicates that it should become one
1491  QString filename;
1492  if ( mlayer->providerType() == QLatin1String( "ogr" ) )
1493  {
1494  QStringList theURIParts = uri.split( '|' );
1495  filename = theURIParts[0];
1496  }
1497  else if ( mlayer->providerType() == QLatin1String( "gpx" ) )
1498  {
1499  QStringList theURIParts = uri.split( '?' );
1500  filename = theURIParts[0];
1501  }
1502  else if ( mlayer->providerType() == QLatin1String( "delimitedtext" ) )
1503  {
1504  filename = QUrl::fromEncoded( uri.toLatin1() ).toLocalFile();
1505  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1506  if ( filename.isEmpty() )
1507  filename = uri;
1508  }
1509  else
1510  {
1511  filename = uri;
1512  }
1513 
1514  QFileInfo myFileInfo( filename );
1515  if ( myFileInfo.exists() || filename.endsWith( QLatin1String( ".sld" ), Qt::CaseInsensitive ) )
1516  {
1517  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1518  if ( !myDirInfo.isWritable() )
1519  {
1520  return tr( "The directory containing your dataset needs to be writable!" );
1521  }
1522 
1523  // now construct the file name for our .sld style file
1524  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".sld";
1525 
1526  QFile myFile( myFileName );
1527  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1528  {
1529  QTextStream myFileStream( &myFile );
1530  // save as utf-8 with 2 spaces for indents
1531  myDocument.save( myFileStream, 2 );
1532  myFile.close();
1533  resultFlag = true;
1534  return tr( "Created default style file as %1" ).arg( myFileName );
1535  }
1536  }
1537 
1538  resultFlag = false;
1539  return tr( "ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1540 }
1541 
1542 QString QgsMapLayer::loadSldStyle( const QString &uri, bool &resultFlag )
1543 {
1544  resultFlag = false;
1545 
1546  QDomDocument myDocument;
1547 
1548  // location of problem associated with errorMsg
1549  int line, column;
1550  QString myErrorMessage;
1551 
1552  QFile myFile( uri );
1553  if ( myFile.open( QFile::ReadOnly ) )
1554  {
1555  // read file
1556  resultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
1557  if ( !resultFlag )
1558  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1559  myFile.close();
1560  }
1561  else
1562  {
1563  myErrorMessage = tr( "Unable to open file %1" ).arg( uri );
1564  }
1565 
1566  if ( !resultFlag )
1567  {
1568  return myErrorMessage;
1569  }
1570 
1571  // check for root SLD element
1572  QDomElement myRoot = myDocument.firstChildElement( QStringLiteral( "StyledLayerDescriptor" ) );
1573  if ( myRoot.isNull() )
1574  {
1575  myErrorMessage = QStringLiteral( "Error: StyledLayerDescriptor element not found in %1" ).arg( uri );
1576  resultFlag = false;
1577  return myErrorMessage;
1578  }
1579 
1580  // now get the style node out and pass it over to the layer
1581  // to deserialise...
1582  QDomElement namedLayerElem = myRoot.firstChildElement( QStringLiteral( "NamedLayer" ) );
1583  if ( namedLayerElem.isNull() )
1584  {
1585  myErrorMessage = QStringLiteral( "Info: NamedLayer element not found." );
1586  resultFlag = false;
1587  return myErrorMessage;
1588  }
1589 
1590  QString errorMsg;
1591  resultFlag = readSld( namedLayerElem, errorMsg );
1592  if ( !resultFlag )
1593  {
1594  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( uri, errorMsg );
1595  return myErrorMessage;
1596  }
1597 
1598  return QString();
1599 }
1600 
1601 bool QgsMapLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1602 {
1603  Q_UNUSED( node )
1604  Q_UNUSED( errorMessage )
1605  Q_UNUSED( context )
1606  Q_UNUSED( categories )
1607  return false;
1608 }
1609 
1610 bool QgsMapLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1611  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1612 {
1613  Q_UNUSED( node )
1614  Q_UNUSED( doc )
1615  Q_UNUSED( errorMessage )
1616  Q_UNUSED( context )
1617  Q_UNUSED( categories )
1618  return false;
1619 }
1620 
1621 void QgsMapLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag )
1622 {
1623  Q_UNUSED( dataSource )
1624  Q_UNUSED( baseName )
1625  Q_UNUSED( provider )
1626  Q_UNUSED( options )
1627  Q_UNUSED( loadDefaultStyleFlag )
1628 }
1629 
1630 
1632 {
1633  return mProviderKey;
1634 }
1635 
1636 void QgsMapLayer::readCommonStyle( const QDomElement &layerElement, const QgsReadWriteContext &context,
1637  QgsMapLayer::StyleCategories categories )
1638 {
1639  if ( categories.testFlag( Symbology3D ) )
1640  {
1641  QgsAbstract3DRenderer *r3D = nullptr;
1642  QDomElement renderer3DElem = layerElement.firstChildElement( QStringLiteral( "renderer-3d" ) );
1643  if ( !renderer3DElem.isNull() )
1644  {
1645  QString type3D = renderer3DElem.attribute( QStringLiteral( "type" ) );
1647  if ( meta3D )
1648  {
1649  r3D = meta3D->createRenderer( renderer3DElem, context );
1650  }
1651  }
1652  setRenderer3D( r3D );
1653  }
1654 
1655  if ( categories.testFlag( CustomProperties ) )
1656  {
1657  // read custom properties before passing reading further to a subclass, so that
1658  // the subclass can also read custom properties
1659  readCustomProperties( layerElement );
1660  }
1661 
1662  // use scale dependent visibility flag
1663  if ( categories.testFlag( Rendering ) )
1664  {
1665  setScaleBasedVisibility( layerElement.attribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).toInt() == 1 );
1666  if ( layerElement.hasAttribute( QStringLiteral( "minimumScale" ) ) )
1667  {
1668  // older element, when scales were reversed
1669  setMaximumScale( layerElement.attribute( QStringLiteral( "minimumScale" ) ).toDouble() );
1670  setMinimumScale( layerElement.attribute( QStringLiteral( "maximumScale" ) ).toDouble() );
1671  }
1672  else
1673  {
1674  setMaximumScale( layerElement.attribute( QStringLiteral( "maxScale" ) ).toDouble() );
1675  setMinimumScale( layerElement.attribute( QStringLiteral( "minScale" ) ).toDouble() );
1676  }
1677  }
1678 
1679  if ( categories.testFlag( LayerConfiguration ) )
1680  {
1681  // flags
1682  QDomElement flagsElem = layerElement.firstChildElement( QStringLiteral( "flags" ) );
1683  LayerFlags flags = mFlags;
1684  auto enumMap = qgsEnumMap<QgsMapLayer::LayerFlag>();
1685  for ( auto it = enumMap.constBegin(); it != enumMap.constEnd(); ++it )
1686  {
1687  QDomNode flagNode = flagsElem.namedItem( it.value() );
1688  if ( flagNode.isNull() )
1689  continue;
1690  bool flagValue = flagNode.toElement().text() == "1" ? true : false;
1691  if ( flags.testFlag( it.key() ) && !flagValue )
1692  flags &= ~it.key();
1693  else if ( !flags.testFlag( it.key() ) && flagValue )
1694  flags |= it.key();
1695  }
1696  setFlags( flags );
1697  }
1698 
1699  if ( categories.testFlag( Temporal ) )
1700  {
1701  QgsMapLayerTemporalProperties *lTemporalProperties = temporalProperties();
1702  if ( lTemporalProperties )
1703  lTemporalProperties->readXml( layerElement.toElement(), context );
1704  }
1705 }
1706 
1708 {
1709  return mUndoStack;
1710 }
1711 
1713 {
1714  return mUndoStackStyles;
1715 }
1716 
1718 {
1719  return mCustomProperties.keys();
1720 }
1721 
1722 void QgsMapLayer::setCustomProperty( const QString &key, const QVariant &value )
1723 {
1724  if ( !mCustomProperties.contains( key ) || mCustomProperties.value( key ) != value )
1725  {
1726  mCustomProperties.setValue( key, value );
1727  emit customPropertyChanged( key );
1728  }
1729 }
1730 
1732 {
1733  mCustomProperties = properties;
1734 }
1735 
1737 {
1738  return mCustomProperties;
1739 }
1740 
1741 QVariant QgsMapLayer::customProperty( const QString &value, const QVariant &defaultValue ) const
1742 {
1743  return mCustomProperties.value( value, defaultValue );
1744 }
1745 
1746 void QgsMapLayer::removeCustomProperty( const QString &key )
1747 {
1748 
1749  if ( mCustomProperties.contains( key ) )
1750  {
1751  mCustomProperties.remove( key );
1752  emit customPropertyChanged( key );
1753  }
1754 }
1755 
1757 {
1758  return mError;
1759 }
1760 
1761 
1762 
1764 {
1765  return false;
1766 }
1767 
1769 {
1770  return true;
1771 }
1772 
1774 {
1775  // invalid layers are temporary? -- who knows?!
1776  if ( !isValid() )
1777  return false;
1778 
1779  if ( mProviderKey == QLatin1String( "memory" ) )
1780  return true;
1781 
1782  const QVariantMap sourceParts = QgsProviderRegistry::instance()->decodeUri( mProviderKey, mDataSource );
1783  const QString path = sourceParts.value( QStringLiteral( "path" ) ).toString();
1784  if ( path.isEmpty() )
1785  return false;
1786 
1787  // check if layer path is inside one of the standard temporary file locations for this platform
1788  const QStringList tempPaths = QStandardPaths::standardLocations( QStandardPaths::TempLocation );
1789  for ( const QString &tempPath : tempPaths )
1790  {
1791  if ( path.startsWith( tempPath ) )
1792  return true;
1793  }
1794 
1795  return false;
1796 }
1797 
1798 void QgsMapLayer::setValid( bool valid )
1799 {
1800  if ( mValid == valid )
1801  return;
1802 
1803  mValid = valid;
1804  emit isValidChanged();
1805 }
1806 
1808 {
1809  if ( legend == mLegend )
1810  return;
1811 
1812  delete mLegend;
1813  mLegend = legend;
1814 
1815  if ( mLegend )
1816  {
1817  mLegend->setParent( this );
1818  connect( mLegend, &QgsMapLayerLegend::itemsChanged, this, &QgsMapLayer::legendChanged );
1819  }
1820 
1821  emit legendChanged();
1822 }
1823 
1825 {
1826  return mLegend;
1827 }
1828 
1830 {
1831  return mStyleManager;
1832 }
1833 
1835 {
1836  if ( renderer == m3DRenderer )
1837  return;
1838 
1839  delete m3DRenderer;
1840  m3DRenderer = renderer;
1841  emit renderer3DChanged();
1842 }
1843 
1845 {
1846  return m3DRenderer;
1847 }
1848 
1849 void QgsMapLayer::triggerRepaint( bool deferredUpdate )
1850 {
1851  if ( mRepaintRequestedFired )
1852  return;
1853 
1854  mRepaintRequestedFired = true;
1855  emit repaintRequested( deferredUpdate );
1856  mRepaintRequestedFired = false;
1857 }
1858 
1860 {
1861  mMetadata = metadata;
1862 // mMetadata.saveToLayer( this );
1863  emit metadataChanged();
1864 }
1865 
1867 {
1868  return QString();
1869 }
1870 
1871 QDateTime QgsMapLayer::timestamp() const
1872 {
1873  return QDateTime();
1874 }
1875 
1877 {
1878  emit styleChanged();
1879 }
1880 
1882 {
1883  mExtent = r;
1884 }
1885 
1886 bool QgsMapLayer::isReadOnly() const
1887 {
1888  return true;
1889 }
1890 
1892 {
1893  return mOriginalXmlProperties;
1894 }
1895 
1897 {
1898  mOriginalXmlProperties = originalXmlProperties;
1899 }
1900 
1901 QString QgsMapLayer::generateId( const QString &layerName )
1902 {
1903  // Generate the unique ID of this layer
1904  QString uuid = QUuid::createUuid().toString();
1905  // trim { } from uuid
1906  QString id = layerName + '_' + uuid.mid( 1, uuid.length() - 2 );
1907  // Tidy the ID up to avoid characters that may cause problems
1908  // elsewhere (e.g in some parts of XML). Replaces every non-word
1909  // character (word characters are the alphabet, numbers and
1910  // underscore) with an underscore.
1911  // Note that the first backslash in the regular expression is
1912  // there for the compiler, so the pattern is actually \W
1913  id.replace( QRegExp( "[\\W]" ), QStringLiteral( "_" ) );
1914  return id;
1915 }
1916 
1918 {
1919  return true;
1920 }
1921 
1923 {
1925 }
1926 
1927 QSet<QgsMapLayerDependency> QgsMapLayer::dependencies() const
1928 {
1929  return mDependencies;
1930 }
1931 
1932 bool QgsMapLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
1933 {
1934  QSet<QgsMapLayerDependency> deps;
1935  const auto constODeps = oDeps;
1936  for ( const QgsMapLayerDependency &dep : constODeps )
1937  {
1938  if ( dep.origin() == QgsMapLayerDependency::FromUser )
1939  deps << dep;
1940  }
1941 
1942  mDependencies = deps;
1943  emit dependenciesChanged();
1944  return true;
1945 }
1946 
1948 {
1949  QgsDataProvider *lDataProvider = dataProvider();
1950  if ( !lDataProvider )
1951  return;
1952 
1953  if ( enabled && !isRefreshOnNotifyEnabled() )
1954  {
1955  lDataProvider->setListening( enabled );
1956  connect( lDataProvider, &QgsVectorDataProvider::notify, this, &QgsMapLayer::onNotifiedTriggerRepaint );
1957  }
1958  else if ( !enabled && isRefreshOnNotifyEnabled() )
1959  {
1960  // we don't want to disable provider listening because someone else could need it (e.g. actions)
1961  disconnect( lDataProvider, &QgsVectorDataProvider::notify, this, &QgsMapLayer::onNotifiedTriggerRepaint );
1962  }
1963  mIsRefreshOnNofifyEnabled = enabled;
1964 }
1965 
1966 void QgsMapLayer::onNotifiedTriggerRepaint( const QString &message )
1967 {
1968  if ( refreshOnNotifyMessage().isEmpty() || refreshOnNotifyMessage() == message )
1969  triggerRepaint();
1970 }
virtual bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write just the symbology information for the layer into the document.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:407
QString mShortName
Definition: qgsmaplayer.h:1585
virtual QStringList subLayers() const
Returns the sublayers of this layer.
void setMetadataUrl(const QString &metaUrl)
Sets the metadata URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:418
The class is used as a container of context for various read/write operations on other objects...
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:369
static QString generateId(const QString &layerName)
Generates an unique identifier for this layer, the generate ID is prefixed by layerName.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:83
static QString formatLayerName(const QString &name)
A convenience function to capitalize and format a layer name.
static Qgs3DRendererRegistry * renderer3DRegistry()
Returns registry of available 3D renderers.
QStringList styles() const
Returns list of all defined style names.
void setShortName(const QString &shortName)
Sets the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:277
virtual void resolveReferences(const QgsProject &project)
Resolves references to other objects - second phase of loading - after readXml()
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as SLD style in a QDomDocument.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void dependenciesChanged()
Emitted when dependencies are changed.
virtual QString loadSldStyle(const QString &uri, bool &resultFlag)
Attempts to style the layer using the formatting from an SLD type file.
Base class for all renderers that may to participate in 3D view.
QgsMapLayerType type() const
Returns the type of the layer.
QString mAttributionUrl
Definition: qgsmaplayer.h:1598
QString mKeywordList
Definition: qgsmaplayer.h:1590
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user&#39;s home dir.
virtual QString saveNamedStyle(const QString &uri, bool &resultFlag, StyleCategories categories=AllStyleCategories)
Save the properties of this layer as a named style (either as a .qml file on disk or as a record in t...
virtual QSet< QgsMapLayerDependency > dependencies() const
Gets the list of dependencies.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
virtual QgsDataProvider * dataProvider()
Returns the layer&#39;s data provider, it may be nullptr.
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from an XML node.
void reset()
Reset the style manager to a basic state - with one default style which is set as current...
Q_INVOKABLE QStringList customPropertyKeys() const
Returns list of all keys within custom properties.
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString())
Push a category to the stack.
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
QgsMapLayerLegend * legend() const
Can be nullptr.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
void setCustomProperties(const QgsObjectCustomProperties &properties)
Set custom properties for layer.
void metadataChanged()
Emitted when the layer&#39;s metadata is changed.
QString mDataUrlFormat
Definition: qgsmaplayer.h:1594
virtual QgsError error() const
Gets current status error.
Represents a raster layer.
void validate()
Perform some validation on this CRS.
bool mShouldValidateCrs
true if the layer&#39;s CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1638
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:351
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:1626
bool updateRevision(const QgsProjectVersion &version)
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:316
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
QString providerType() const
Returns the provider type (provider key) for this layer.
PropertyType
Maplayer has a style and a metadata property.
Definition: qgsmaplayer.h:140
QString mLegendUrlFormat
Definition: qgsmaplayer.h:1607
void setRefreshOnNotifyEnabled(bool enabled)
Set whether provider notification is connected to triggerRepaint.
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
static void setCustomCrsValidation(CUSTOM_CRS_VALIDATION f)
Sets custom function to force valid CRS.
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
Temporal properties.
Definition: qgsmaplayer.h:182
virtual QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context)=0
Writes the properties to a DOM element, to be used later with readXml().
virtual bool loadNamedStyleFromDatabase(const QString &db, const QString &uri, QString &qml)
Retrieve a named style for this layer from a sqlite database.
virtual void resolveReferences(QgsProject *project)
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects...
virtual bool writeXml(QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context) const
Called by writeLayerXML(), used by children to write state specific to them to project files...
virtual QString saveSldStyle(const QString &uri, bool &resultFlag) const
Saves the properties of this layer to an SLD format file.
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc)
Definition: qgsxmlutils.cpp:81
void crsChanged()
Emit a signal that layer&#39;s CRS has been reset.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
virtual const QgsLayerMetadata & metadata() const
Returns a reference to the layer&#39;s metadata store.
void configChanged()
Emitted whenever the configuration is changed.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the layer...
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for the given key.
void setMetadataUrlType(const QString &metaUrlType)
Set the metadata type of the layer used by QGIS Server in GetCapabilities request MetadataUrlType ind...
Definition: qgsmaplayer.h:436
Allows entering a context category and takes care of leaving this category on deletion of the class...
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
Abstract base class for spatial data provider implementations.
virtual QString encodedSource(const QString &source, const QgsReadWriteContext &context) const
Called by writeLayerXML(), used by derived classes to encode provider&#39;s specific data source to proje...
virtual QString styleURI() const
Retrieve the style URI for this layer (either as a .qml file on disk or as a record in the users styl...
void writeXml(QDomNode &parentNode, QDomDocument &doc) const
Writes the store contents to an XML node.
double mLayerOpacity
Layer opacity.
Definition: qgsmaplayer.h:1645
QString saveNamedMetadata(const QString &uri, bool &resultFlag)
Save the current metadata of this layer as a named metadata (either as a .qmd file on disk or as a re...
bool isValid() const
Returns the status of the layer.
virtual double opacity() const
Returns the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1...
An interface for classes which can visit style entity (e.g.
void notify(const QString &msg)
Emitted when the datasource issues a notification.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
bool mIsRefreshOnNofifyEnabled
Definition: qgsmaplayer.h:1622
QMap< QString, QString > QgsStringMap
Definition: qgis.h:759
void remove(const QString &key)
Removes a key (entry) from the store.
void exportNamedMetadata(QDomDocument &doc, QString &errorMsg) const
Export the current metadata of this layer as named metadata in a QDomDocument.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1583
bool isRefreshOnNotifyEnabled() const
Returns true if the refresh on provider nofification is enabled.
Definition: qgsmaplayer.h:1186
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
bool loadNamedMetadataFromDatabase(const QString &db, const QString &uri, QString &qmd)
Retrieve a named metadata for this layer from a sqlite database.
virtual QString htmlMetadata() const
Obtain a formatted HTML string containing assorted metadata for this layer.
virtual QgsRectangle extent() const
Returns the extent of the layer.
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer&#39;s style manager.
QgsError mError
Error.
Definition: qgsmaplayer.h:1610
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer&#39;s temporal properties.
Definition: qgsmaplayer.h:1229
QgsRectangle mExtent
Extent of the layer.
Definition: qgsmaplayer.h:1574
virtual void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const =0
Writes renderer&#39;s properties to given XML element.
static T readFlagAttribute(const QDomElement &element, const QString &attributeName, T defaultValue)
Read a flag value from an attribute of the element.
Definition: qgsxmlutils.h:92
QString mMetadataUrl
MetadataUrl of the layer.
Definition: qgsmaplayer.h:1601
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:1019
QString metadataUrlFormat() const
Returns the metadata format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:463
virtual bool readXml(const QDomElement &element, const QgsReadWriteContext &context)=0
Reads temporal properties from a DOM element previously written by writeXml().
void setValidationHint(const QString &html)
Set user hint for validation.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
void setKeywordList(const QString &keywords)
Sets the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:323
void setValue(const QString &key, const QVariant &value)
Add an entry to the store with the specified key.
static QString version()
Version string.
Definition: qgis.cpp:276
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
bool readMetadataXml(const QDomElement &metadataElement) override
Sets state from DOM document.
static QString capitalize(const QString &string, Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:291
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any). To be called by subclasses.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted...
int autoRefreshInterval() const
Returns the auto refresh interval (in milliseconds).
virtual void setSubLayerVisibility(const QString &name, bool visible)
Set the visibility of the given sublayer name.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass)
virtual QString decodedSource(const QString &source, const QString &dataProvider, const QgsReadWriteContext &context) const
Called by readLayerXML(), used by derived classes to decode provider&#39;s specific data source from proj...
void setOriginalXmlProperties(const QString &originalXmlProperties)
Sets the original XML properties for the layer to originalXmlProperties.
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:178
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer&#39;s metadata store.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
QSet< QgsMapLayerDependency > mDependencies
List of layers that may modify this layer on modification.
Definition: qgsmaplayer.h:1613
virtual void setListening(bool isListening)
Set whether the provider will listen to datasource notifications If set, the provider will issue noti...
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1...
void nameChanged()
Emitted when the name has been changed.
A class to describe the version of a project.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
void readXml(const QDomElement &mgrElement)
Read configuration (for project loading)
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:331
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsStringMap &props=QgsStringMap()) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
QString mDataUrl
DataUrl of the layer.
Definition: qgsmaplayer.h:1593
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
virtual bool isEditable() const
Returns true if the layer can be edited.
virtual QString saveDefaultMetadata(bool &resultFlag)
Save the current metadata of this layer as the default metadata (either as a .qmd file on disk or as ...
QString legendUrl() const
Returns the URL for the layer&#39;s legend.
Definition: qgsmaplayer.h:1014
QgsCoordinateReferenceSystem crs() const
Returns the layer&#39;s spatial reference system.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:94
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
const QgsObjectCustomProperties & customProperties() const
Read all custom properties from layer.
bool contains(const QString &key) const
Returns true if the properties contains a key with the specified name.
void setRenderer3D(QgsAbstract3DRenderer *renderer)
Sets 3D renderer for the layer.
void isValidChanged()
Emitted when the validity of this layer changed.
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
static QString extensionPropertyType(PropertyType type)
Returns the extension of a Property.
Definition: qgsmaplayer.cpp:58
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
double minimumScale() const
Returns the minimum map scale (i.e.
Contains information about the context in which a coordinate transform is executed.
double maximumScale() const
Returns the maximum map scale (i.e.
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1577
void setName(const QString &name)
Set the display name of the layer.
void setDataUrlFormat(const QString &dataUrlFormat)
Sets the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:360
int open(const QString &path)
Opens the database at the specified file path.
QStringList keys() const
Returns a list of all stored keys.
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
QString mTitle
Definition: qgsmaplayer.h:1586
virtual bool readSld(const QDomNode &node, QString &errorMessage)
Definition: qgsmaplayer.h:917
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:1024
Convert just the first letter of each word to uppercase, leave the rest untouched.
QString mMetadataUrlFormat
Definition: qgsmaplayer.h:1603
void setLegendUrl(const QString &legendUrl)
Sets the URL for the layer&#39;s legend.
Definition: qgsmaplayer.h:1009
void setMetadataUrlFormat(const QString &metaUrlFormat)
Sets the metadata format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:454
virtual bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context)
Called by readLayerXML(), used by children to read state specific to them from project files...
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:299
static QString pkgDataPath()
Returns the common root path of all application data directories.
static CUSTOM_CRS_VALIDATION customCrsValidation()
Gets custom function.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
The derived translate() translates with QTranslator and qm file the sourceText.
QString mAttribution
Attribution of the layer.
Definition: qgsmaplayer.h:1597
QString mAbstract
Description of the layer.
Definition: qgsmaplayer.h:1589
General configuration: identifiable, removable, searchable, display expression, read-only.
Definition: qgsmaplayer.h:168
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists). To be called by subclasses.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
QString originalXmlProperties() const
Returns the XML properties of the original layer as they were when the layer was first read from the ...
void blendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when the blend mode is changed, through QgsMapLayer::setBlendMode() ...
virtual bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const =0
Write the style for the layer into the docment provided.
void opacityChanged(double opacity)
Emitted when the layer&#39;s opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
bool writeMetadataXml(QDomElement &metadataElement, QDomDocument &document) const override
Stores state in a DOM node.
A structured metadata store for a map layer.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:140
QString mRefreshOnNofifyMessage
Definition: qgsmaplayer.h:1623
static QgsAuthManager * authManager()
Returns the application&#39;s authentication manager instance.
virtual bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read the style for the current layer from the DOM node supplied.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
void beforeResolveReferences(QgsProject *project)
Emitted when all layers are loaded and references can be resolved, just before the references of this...
Base class for storage of map layer temporal properties.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
virtual QString saveDefaultStyle(bool &resultFlag)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
Custom properties (by plugins for instance)
Definition: qgsmaplayer.h:179
void itemsChanged()
Emitted when existing items/nodes got invalid and should be replaced by new ones. ...
Setting options for creating vector data providers.
QString name() const
Returns the display name of the layer.
QgsMapLayer(QgsMapLayerType type=QgsMapLayerType::VectorLayer, const QString &name=QString(), const QString &source=QString())
Constructor for QgsMapLayer.
Definition: qgsmaplayer.cpp:71
virtual bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)=0
Read the symbology for the current layer from the DOM node supplied.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1580
QString source() const
Returns the source for the layer.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
QgsError is container for error messages (report).
Definition: qgserror.h:80
bool setMasterPassword(bool verify=false)
Main call to initially set or continually check master password is set.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:469
Qgs3DRendererAbstractMetadata * rendererMetadata(const QString &type) const
Returns metadata for a 3D renderer type (may be used to create a new instance of the type) ...
void customPropertyChanged(const QString &key)
Emitted when a custom property of the layer has been changed or removed.
QString mLegendUrl
WMS legend.
Definition: qgsmaplayer.h:1606
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
This class represents a coordinate reference system (CRS).
void legendChanged()
Signal emitted when legend of the layer has changed.
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags=QgsMapLayer::ReadFlags())
Sets state from DOM document.
Simple key-value store (keys = strings, values = variants) that supports loading/saving to/from XML i...
void setAutoRefreshInterval(int interval)
Sets the auto refresh interval (in milliseconds) for the layer.
virtual bool isTemporary() const
Returns true if the layer is considered a temporary layer.
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
void setAttributionUrl(const QString &attribUrl)
Sets the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:398
virtual QString loadDefaultMetadata(bool &resultFlag)
Retrieve the default metadata for this layer if one exists (either as a .qmd file on disk or as a rec...
QString metadataUrl() const
Returns the metadata URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:427
virtual void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
void setAutoRefreshEnabled(bool enabled)
Sets whether auto refresh is enabled for the layer.
QUndoStack * undoStackStyles()
Returns pointer to layer&#39;s style undo stack.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:67
bool addStyle(const QString &name, const QgsMapLayerStyle &style)
Add a style with given name and data.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QUndoStack * undoStack()
Returns pointer to layer&#39;s undo stack.
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:380
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
void setRefreshOnNofifyMessage(const QString &message)
Set the notification message that triggers repaint If refresh on notification is enabled, the notification will triggerRepaint only if the notification message is equal to.
Definition: qgsmaplayer.h:1304
virtual QString loadNamedMetadata(const QString &uri, bool &resultFlag)
Retrieve a named metadata for this layer if one exists (either as a .qmd file on disk or as a record ...
bool hasAutoRefreshEnabled() const
Returns true if auto refresh is enabled for the layer.
Base metadata class for 3D renderers.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
void autoRefreshIntervalChanged(int interval)
Emitted when the auto refresh interval changes.
This class models dependencies with or between map layers.
Management of styles for use with one map layer.
QString refreshOnNotifyMessage() const
Returns the message that should be notified by the provider to triggerRepaint.
Definition: qgsmaplayer.h:1179
Represents a vector layer which manages a vector based data sets.
virtual QDateTime timestamp() const
Time stamp of data source in the moment when data/metadata were loaded by provider.
virtual void setLayerOrder(const QStringList &layers)
Reorders the previously selected sublayers of this layer from bottom to top.
void writeXml(QDomElement &mgrElement) const
Write configuration (for project saving)
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in DOM node.
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:342
void setValid(bool valid)
Sets whether layer is valid or not.
QString mMetadataUrlType
Definition: qgsmaplayer.h:1602
virtual QgsAbstract3DRenderer * createRenderer(QDomElement &elem, const QgsReadWriteContext &context)=0
Returns new instance of the renderer given the DOM element.
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:307
static const double SCALE_PRECISION
Fudge factor used to compare two scales.
Definition: qgis.h:169
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:389
void setFlags(QgsMapLayer::LayerFlags flags)
Returns the flags for this layer.
void flagsChanged()
Emitted when layer&#39;s flags have been modified.
QString metadataUrlType() const
Returns the metadata type of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:445
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void renderer3DChanged()
Signal emitted when 3D renderer associated with the layer has changed.
static QString removePassword(const QString &aUri)
Removes the password element from a URI.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It&#39;s up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1631
~QgsMapLayer() override
Definition: qgsmaplayer.cpp:88
bool importNamedMetadata(QDomDocument &document, QString &errorMessage)
Import the metadata of this layer from a QDomDocument.
virtual QString metadataUri() const
Retrieve the metadata URI for this layer (either as a .qmd file on disk or as a record in the users s...
virtual bool setDependencies(const QSet< QgsMapLayerDependency > &layers)
Sets the list of dependencies.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.