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