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