QGIS API Documentation  3.9.0-Master (224899f119)
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() );
123  layer->setCrs( crs() );
124  layer->setCustomProperties( mCustomProperties );
125 }
126 
128 {
129  return mLayerType;
130 }
131 
132 QgsMapLayer::LayerFlags QgsMapLayer::flags() const
133 {
134  return mFlags;
135 }
136 
137 void QgsMapLayer::setFlags( QgsMapLayer::LayerFlags flags )
138 {
139  if ( flags == mFlags )
140  return;
141 
142  mFlags = flags;
143  emit flagsChanged();
144 }
145 
146 QString QgsMapLayer::id() const
147 {
148  return mID;
149 }
150 
151 void QgsMapLayer::setName( const QString &name )
152 {
153  if ( name == mLayerName )
154  return;
155 
156  mLayerName = name;
157 
158  emit nameChanged();
159 }
160 
161 QString QgsMapLayer::name() const
162 {
163  QgsDebugMsgLevel( "returning name '" + mLayerName + '\'', 4 );
164  return mLayerName;
165 }
166 
168 {
169  return nullptr;
170 }
171 
173 {
174  return nullptr;
175 }
176 
177 QString QgsMapLayer::shortName() const
178 {
179  return mShortName;
180 }
181 
183 {
184  // Redo this every time we're asked for it, as we don't know if
185  // dataSource has changed.
186  QString safeName = QgsDataSourceUri::removePassword( mDataSource );
187  return safeName;
188 }
189 
190 QString QgsMapLayer::source() const
191 {
192  return mDataSource;
193 }
194 
196 {
197  return mExtent;
198 }
199 
200 void QgsMapLayer::setBlendMode( const QPainter::CompositionMode blendMode )
201 {
202  if ( mBlendMode == blendMode )
203  return;
204 
205  mBlendMode = blendMode;
206  emit blendModeChanged( blendMode );
207  emit styleChanged();
208 }
209 
210 QPainter::CompositionMode QgsMapLayer::blendMode() const
211 {
212  return mBlendMode;
213 }
214 
215 
216 bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags )
217 {
218  bool layerError;
219  mReadFlags = flags;
220 
221  QDomNode mnl;
222  QDomElement mne;
223 
224  // read provider
225  QString provider;
226  mnl = layerElement.namedItem( QStringLiteral( "provider" ) );
227  mne = mnl.toElement();
228  provider = mne.text();
229 
230  // set data source
231  mnl = layerElement.namedItem( QStringLiteral( "datasource" ) );
232  mne = mnl.toElement();
233  mDataSource = mne.text();
234 
235  // if the layer needs authentication, ensure the master password is set
236  QRegExp rx( "authcfg=([a-z]|[A-Z]|[0-9]){7}" );
237  if ( ( rx.indexIn( mDataSource ) != -1 )
239  {
240  return false;
241  }
242 
243  mDataSource = decodedSource( mDataSource, provider, context );
244 
245  // Set the CRS from project file, asking the user if necessary.
246  // Make it the saved CRS to have WMS layer projected correctly.
247  // We will still overwrite whatever GDAL etc picks up anyway
248  // further down this function.
249  mnl = layerElement.namedItem( QStringLiteral( "layername" ) );
250  mne = mnl.toElement();
251 
253  CUSTOM_CRS_VALIDATION savedValidation;
254 
255  QDomNode srsNode = layerElement.namedItem( QStringLiteral( "srs" ) );
256  mCRS.readXml( srsNode );
257  mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( mne.text() ) );
258  if ( isSpatial() )
259  mCRS.validate();
260  savedCRS = mCRS;
261 
262  // Do not validate any projections in children, they will be overwritten anyway.
263  // No need to ask the user for a projections when it is overwritten, is there?
266 
267  QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Layer" ), mne.text() );
268 
269  // now let the children grab what they need from the Dom node.
270  layerError = !readXml( layerElement, context );
271 
272  // overwrite CRS with what we read from project file before the raster/vector
273  // file reading functions changed it. They will if projections is specified in the file.
274  // FIXME: is this necessary?
276  mCRS = savedCRS;
277 
278  // the internal name is just the data source basename
279  //QFileInfo dataSourceFileInfo( mDataSource );
280  //internalName = dataSourceFileInfo.baseName();
281 
282  // set ID
283  mnl = layerElement.namedItem( QStringLiteral( "id" ) );
284  if ( ! mnl.isNull() )
285  {
286  mne = mnl.toElement();
287  if ( ! mne.isNull() && mne.text().length() > 10 ) // should be at least 17 (yyyyMMddhhmmsszzz)
288  {
289  mID = mne.text();
290  }
291  }
292 
293  setAutoRefreshInterval( layerElement.attribute( QStringLiteral( "autoRefreshTime" ), QStringLiteral( "0" ) ).toInt() );
294  setAutoRefreshEnabled( layerElement.attribute( QStringLiteral( "autoRefreshEnabled" ), QStringLiteral( "0" ) ).toInt() );
295  setRefreshOnNofifyMessage( layerElement.attribute( QStringLiteral( "refreshOnNotifyMessage" ), QString() ) );
296  setRefreshOnNotifyEnabled( layerElement.attribute( QStringLiteral( "refreshOnNotifyEnabled" ), QStringLiteral( "0" ) ).toInt() );
297 
298 
299  // set name
300  mnl = layerElement.namedItem( QStringLiteral( "layername" ) );
301  mne = mnl.toElement();
302 
303  //name can be translated
304  setName( context.projectTranslator()->translate( QStringLiteral( "project:layers:%1" ).arg( layerElement.namedItem( QStringLiteral( "id" ) ).toElement().text() ), mne.text() ) );
305 
306  //short name
307  QDomElement shortNameElem = layerElement.firstChildElement( QStringLiteral( "shortname" ) );
308  if ( !shortNameElem.isNull() )
309  {
310  mShortName = shortNameElem.text();
311  }
312 
313  //title
314  QDomElement titleElem = layerElement.firstChildElement( QStringLiteral( "title" ) );
315  if ( !titleElem.isNull() )
316  {
317  mTitle = titleElem.text();
318  }
319 
320  //abstract
321  QDomElement abstractElem = layerElement.firstChildElement( QStringLiteral( "abstract" ) );
322  if ( !abstractElem.isNull() )
323  {
324  mAbstract = abstractElem.text();
325  }
326 
327  //keywordList
328  QDomElement keywordListElem = layerElement.firstChildElement( QStringLiteral( "keywordList" ) );
329  if ( !keywordListElem.isNull() )
330  {
331  QStringList kwdList;
332  for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
333  {
334  kwdList << n.toElement().text();
335  }
336  mKeywordList = kwdList.join( QStringLiteral( ", " ) );
337  }
338 
339  //metadataUrl
340  QDomElement dataUrlElem = layerElement.firstChildElement( QStringLiteral( "dataUrl" ) );
341  if ( !dataUrlElem.isNull() )
342  {
343  mDataUrl = dataUrlElem.text();
344  mDataUrlFormat = dataUrlElem.attribute( QStringLiteral( "format" ), QString() );
345  }
346 
347  //legendUrl
348  QDomElement legendUrlElem = layerElement.firstChildElement( QStringLiteral( "legendUrl" ) );
349  if ( !legendUrlElem.isNull() )
350  {
351  mLegendUrl = legendUrlElem.text();
352  mLegendUrlFormat = legendUrlElem.attribute( QStringLiteral( "format" ), QString() );
353  }
354 
355  //attribution
356  QDomElement attribElem = layerElement.firstChildElement( QStringLiteral( "attribution" ) );
357  if ( !attribElem.isNull() )
358  {
359  mAttribution = attribElem.text();
360  mAttributionUrl = attribElem.attribute( QStringLiteral( "href" ), QString() );
361  }
362 
363  //metadataUrl
364  QDomElement metaUrlElem = layerElement.firstChildElement( QStringLiteral( "metadataUrl" ) );
365  if ( !metaUrlElem.isNull() )
366  {
367  mMetadataUrl = metaUrlElem.text();
368  mMetadataUrlType = metaUrlElem.attribute( QStringLiteral( "type" ), QString() );
369  mMetadataUrlFormat = metaUrlElem.attribute( QStringLiteral( "format" ), QString() );
370  }
371 
372  // mMetadata.readFromLayer( this );
373  QDomElement metadataElem = layerElement.firstChildElement( QStringLiteral( "resourceMetadata" ) );
374  mMetadata.readMetadataXml( metadataElem );
375 
376  return ! layerError;
377 } // bool QgsMapLayer::readLayerXML
378 
379 
380 bool QgsMapLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
381 {
382  Q_UNUSED( layer_node )
383  Q_UNUSED( context )
384  // NOP by default; children will over-ride with behavior specific to them
385 
386  return true;
387 } // void QgsMapLayer::readXml
388 
389 
390 bool QgsMapLayer::writeLayerXml( QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context ) const
391 {
392  if ( !extent().isNull() )
393  {
394  layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent, document ) );
395  }
396 
397  layerElement.setAttribute( QStringLiteral( "autoRefreshTime" ), QString::number( mRefreshTimer->interval() ) );
398  layerElement.setAttribute( QStringLiteral( "autoRefreshEnabled" ), mRefreshTimer->isActive() ? 1 : 0 );
399  layerElement.setAttribute( QStringLiteral( "refreshOnNotifyEnabled" ), mIsRefreshOnNofifyEnabled ? 1 : 0 );
400  layerElement.setAttribute( QStringLiteral( "refreshOnNotifyMessage" ), mRefreshOnNofifyMessage );
401 
402 
403  // ID
404  QDomElement layerId = document.createElement( QStringLiteral( "id" ) );
405  QDomText layerIdText = document.createTextNode( id() );
406  layerId.appendChild( layerIdText );
407 
408  layerElement.appendChild( layerId );
409 
410  // data source
411  QDomElement dataSource = document.createElement( QStringLiteral( "datasource" ) );
412  QString src = encodedSource( source(), context );
413  QDomText dataSourceText = document.createTextNode( src );
414  dataSource.appendChild( dataSourceText );
415  layerElement.appendChild( dataSource );
416 
417  // layer name
418  QDomElement layerName = document.createElement( QStringLiteral( "layername" ) );
419  QDomText layerNameText = document.createTextNode( name() );
420  layerName.appendChild( layerNameText );
421  layerElement.appendChild( layerName );
422 
423  // layer short name
424  if ( !mShortName.isEmpty() )
425  {
426  QDomElement layerShortName = document.createElement( QStringLiteral( "shortname" ) );
427  QDomText layerShortNameText = document.createTextNode( mShortName );
428  layerShortName.appendChild( layerShortNameText );
429  layerElement.appendChild( layerShortName );
430  }
431 
432  // layer title
433  if ( !mTitle.isEmpty() )
434  {
435  QDomElement layerTitle = document.createElement( QStringLiteral( "title" ) );
436  QDomText layerTitleText = document.createTextNode( mTitle );
437  layerTitle.appendChild( layerTitleText );
438  layerElement.appendChild( layerTitle );
439  }
440 
441  // layer abstract
442  if ( !mAbstract.isEmpty() )
443  {
444  QDomElement layerAbstract = document.createElement( QStringLiteral( "abstract" ) );
445  QDomText layerAbstractText = document.createTextNode( mAbstract );
446  layerAbstract.appendChild( layerAbstractText );
447  layerElement.appendChild( layerAbstract );
448  }
449 
450  // layer keyword list
451  QStringList keywordStringList = keywordList().split( ',' );
452  if ( !keywordStringList.isEmpty() )
453  {
454  QDomElement layerKeywordList = document.createElement( QStringLiteral( "keywordList" ) );
455  for ( int i = 0; i < keywordStringList.size(); ++i )
456  {
457  QDomElement layerKeywordValue = document.createElement( QStringLiteral( "value" ) );
458  QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
459  layerKeywordValue.appendChild( layerKeywordText );
460  layerKeywordList.appendChild( layerKeywordValue );
461  }
462  layerElement.appendChild( layerKeywordList );
463  }
464 
465  // layer metadataUrl
466  QString aDataUrl = dataUrl();
467  if ( !aDataUrl.isEmpty() )
468  {
469  QDomElement layerDataUrl = document.createElement( QStringLiteral( "dataUrl" ) );
470  QDomText layerDataUrlText = document.createTextNode( aDataUrl );
471  layerDataUrl.appendChild( layerDataUrlText );
472  layerDataUrl.setAttribute( QStringLiteral( "format" ), dataUrlFormat() );
473  layerElement.appendChild( layerDataUrl );
474  }
475 
476  // layer legendUrl
477  QString aLegendUrl = legendUrl();
478  if ( !aLegendUrl.isEmpty() )
479  {
480  QDomElement layerLegendUrl = document.createElement( QStringLiteral( "legendUrl" ) );
481  QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
482  layerLegendUrl.appendChild( layerLegendUrlText );
483  layerLegendUrl.setAttribute( QStringLiteral( "format" ), legendUrlFormat() );
484  layerElement.appendChild( layerLegendUrl );
485  }
486 
487  // layer attribution
488  QString aAttribution = attribution();
489  if ( !aAttribution.isEmpty() )
490  {
491  QDomElement layerAttribution = document.createElement( QStringLiteral( "attribution" ) );
492  QDomText layerAttributionText = document.createTextNode( aAttribution );
493  layerAttribution.appendChild( layerAttributionText );
494  layerAttribution.setAttribute( QStringLiteral( "href" ), attributionUrl() );
495  layerElement.appendChild( layerAttribution );
496  }
497 
498  // layer metadataUrl
499  QString aMetadataUrl = metadataUrl();
500  if ( !aMetadataUrl.isEmpty() )
501  {
502  QDomElement layerMetadataUrl = document.createElement( QStringLiteral( "metadataUrl" ) );
503  QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
504  layerMetadataUrl.appendChild( layerMetadataUrlText );
505  layerMetadataUrl.setAttribute( QStringLiteral( "type" ), metadataUrlType() );
506  layerMetadataUrl.setAttribute( QStringLiteral( "format" ), metadataUrlFormat() );
507  layerElement.appendChild( layerMetadataUrl );
508  }
509 
510  // timestamp if supported
511  if ( timestamp() > QDateTime() )
512  {
513  QDomElement stamp = document.createElement( QStringLiteral( "timestamp" ) );
514  QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
515  stamp.appendChild( stampText );
516  layerElement.appendChild( stamp );
517  }
518 
519  layerElement.appendChild( layerName );
520 
521  // zorder
522  // This is no longer stored in the project file. It is superfluous since the layers
523  // are written and read in the proper order.
524 
525  // spatial reference system id
526  QDomElement mySrsElement = document.createElement( QStringLiteral( "srs" ) );
527  mCRS.writeXml( mySrsElement, document );
528  layerElement.appendChild( mySrsElement );
529 
530  // layer metadata
531  QDomElement myMetadataElem = document.createElement( QStringLiteral( "resourceMetadata" ) );
532  mMetadata.writeMetadataXml( myMetadataElem, document );
533  layerElement.appendChild( myMetadataElem );
534 
535  // now append layer node to map layer node
536  return writeXml( layerElement, document, context );
537 }
538 
539 void QgsMapLayer::writeCommonStyle( QDomElement &layerElement, QDomDocument &document,
540  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
541 {
542  // save categories
543  QMetaEnum metaEnum = QMetaEnum::fromType<QgsMapLayer::StyleCategories>();
544  QString categoriesKeys( metaEnum.valueToKeys( static_cast<int>( categories ) ) );
545  layerElement.setAttribute( QStringLiteral( "styleCategories" ), categoriesKeys );
546 
547  if ( categories.testFlag( Rendering ) )
548  {
549  // use scale dependent visibility flag
550  layerElement.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
551  layerElement.setAttribute( QStringLiteral( "maxScale" ), QString::number( maximumScale() ) );
552  layerElement.setAttribute( QStringLiteral( "minScale" ), QString::number( minimumScale() ) );
553  }
554 
555  if ( categories.testFlag( Symbology3D ) )
556  {
557  if ( m3DRenderer )
558  {
559  QDomElement renderer3DElem = document.createElement( QStringLiteral( "renderer-3d" ) );
560  renderer3DElem.setAttribute( QStringLiteral( "type" ), m3DRenderer->type() );
561  m3DRenderer->writeXml( renderer3DElem, context );
562  layerElement.appendChild( renderer3DElem );
563  }
564  }
565 
566  if ( categories.testFlag( LayerConfiguration ) )
567  {
568  // flags
569  // this code is saving automatically all the flags entries
570  QDomElement layerFlagsElem = document.createElement( QStringLiteral( "flags" ) );
571  auto enumMap = qgsEnumMap<QgsMapLayer::LayerFlag>();
572  for ( auto it = enumMap.constBegin(); it != enumMap.constEnd(); ++it )
573  {
574  bool flagValue = mFlags.testFlag( it.key() );
575  QDomElement flagElem = document.createElement( it.value() );
576  flagElem.appendChild( document.createTextNode( QString::number( flagValue ) ) );
577  layerFlagsElem.appendChild( flagElem );
578  }
579  layerElement.appendChild( layerFlagsElem );
580  }
581 
582  // custom properties
583  if ( categories.testFlag( CustomProperties ) )
584  {
585  writeCustomProperties( layerElement, document );
586  }
587 }
588 
589 
590 bool QgsMapLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
591 {
592  Q_UNUSED( layer_node )
593  Q_UNUSED( document )
594  Q_UNUSED( context )
595  // NOP by default; children will over-ride with behavior specific to them
596 
597  return true;
598 }
599 
600 QString QgsMapLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
601 {
602  Q_UNUSED( context )
603  return source;
604 }
605 
606 QString QgsMapLayer::decodedSource( const QString &source, const QString &dataProvider, const QgsReadWriteContext &context ) const
607 {
608  Q_UNUSED( context )
609  Q_UNUSED( dataProvider )
610  return source;
611 }
612 
614 {
615  if ( m3DRenderer )
616  m3DRenderer->resolveReferences( *project );
617 }
618 
619 
620 void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
621 {
622  mCustomProperties.readXml( layerNode, keyStartsWith );
623 }
624 
625 void QgsMapLayer::writeCustomProperties( QDomNode &layerNode, QDomDocument &doc ) const
626 {
627  mCustomProperties.writeXml( layerNode, doc );
628 }
629 
630 void QgsMapLayer::readStyleManager( const QDomNode &layerNode )
631 {
632  QDomElement styleMgrElem = layerNode.firstChildElement( QStringLiteral( "map-layer-style-manager" ) );
633  if ( !styleMgrElem.isNull() )
634  mStyleManager->readXml( styleMgrElem );
635  else
636  mStyleManager->reset();
637 }
638 
639 void QgsMapLayer::writeStyleManager( QDomNode &layerNode, QDomDocument &doc ) const
640 {
641  if ( mStyleManager )
642  {
643  QDomElement styleMgrElem = doc.createElement( QStringLiteral( "map-layer-style-manager" ) );
644  mStyleManager->writeXml( styleMgrElem );
645  layerNode.appendChild( styleMgrElem );
646  }
647 }
648 
650 {
651  return mValid;
652 }
653 
654 #if 0
655 void QgsMapLayer::connectNotify( const char *signal )
656 {
657  Q_UNUSED( signal )
658  QgsDebugMsgLevel( "QgsMapLayer connected to " + QString( signal ), 3 );
659 } // QgsMapLayer::connectNotify
660 #endif
661 
662 bool QgsMapLayer::isInScaleRange( double scale ) const
663 {
664  return !mScaleBasedVisibility ||
665  ( ( mMinScale == 0 || mMinScale * Qgis::SCALE_PRECISION < scale )
666  && ( mMaxScale == 0 || scale < mMaxScale ) );
667 }
668 
670 {
671  return mScaleBasedVisibility;
672 }
673 
675 {
676  return mRefreshTimer->isActive();
677 }
678 
680 {
681  return mRefreshTimer->interval();
682 }
683 
685 {
686  if ( interval <= 0 )
687  {
688  mRefreshTimer->stop();
689  mRefreshTimer->setInterval( 0 );
690  }
691  else
692  {
693  mRefreshTimer->setInterval( interval );
694  }
695  emit autoRefreshIntervalChanged( mRefreshTimer->isActive() ? mRefreshTimer->interval() : 0 );
696 }
697 
699 {
700  if ( !enabled )
701  mRefreshTimer->stop();
702  else if ( mRefreshTimer->interval() > 0 )
703  mRefreshTimer->start();
704 
705  emit autoRefreshIntervalChanged( mRefreshTimer->isActive() ? mRefreshTimer->interval() : 0 );
706 }
707 
709 {
710  return mMetadata;
711 }
712 
713 void QgsMapLayer::setMaximumScale( double scale )
714 {
715  mMinScale = scale;
716 }
717 
719 {
720  return mMinScale;
721 }
722 
723 
724 void QgsMapLayer::setMinimumScale( double scale )
725 {
726  mMaxScale = scale;
727 }
728 
729 void QgsMapLayer::setScaleBasedVisibility( const bool enabled )
730 {
731  mScaleBasedVisibility = enabled;
732 }
733 
735 {
736  return mMaxScale;
737 }
738 
739 QStringList QgsMapLayer::subLayers() const
740 {
741  return QStringList(); // Empty
742 }
743 
744 void QgsMapLayer::setLayerOrder( const QStringList &layers )
745 {
746  Q_UNUSED( layers )
747  // NOOP
748 }
749 
750 void QgsMapLayer::setSubLayerVisibility( const QString &name, bool vis )
751 {
752  Q_UNUSED( name )
753  Q_UNUSED( vis )
754  // NOOP
755 }
756 
758 {
759  return mCRS;
760 }
761 
762 void QgsMapLayer::setCrs( const QgsCoordinateReferenceSystem &srs, bool emitSignal )
763 {
764  mCRS = srs;
765 
766  if ( isSpatial() && !mCRS.isValid() )
767  {
768  mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
769  mCRS.validate();
770  }
771 
772  if ( emitSignal )
773  emit crsChanged();
774 }
775 
777 {
779 }
780 
781 QString QgsMapLayer::formatLayerName( const QString &name )
782 {
783  QString layerName( name );
784  layerName.replace( '_', ' ' );
786  return layerName;
787 }
788 
789 QString QgsMapLayer::baseURI( PropertyType type ) const
790 {
791  QString myURI = publicSource();
792 
793  // first get base path for delimited text, spatialite and OGR layers,
794  // as in these cases URI may contain layer name and/or additional
795  // information. This also strips prefix in case if VSIFILE mechanism
796  // is used
797  if ( providerType() == QLatin1String( "ogr" ) || providerType() == QLatin1String( "delimitedtext" ) ||
798  providerType() == QLatin1String( "spatialite" ) )
799  {
800  QVariantMap components = QgsProviderRegistry::instance()->decodeUri( providerType(), myURI );
801  myURI = components["path"].toString();
802  }
803 
804  QFileInfo myFileInfo( myURI );
805  QString key;
806 
807  if ( myFileInfo.exists() )
808  {
809  // if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
810  if ( myURI.endsWith( QLatin1String( ".gz" ), Qt::CaseInsensitive ) )
811  myURI.chop( 3 );
812  else if ( myURI.endsWith( QLatin1String( ".zip" ), Qt::CaseInsensitive ) )
813  myURI.chop( 4 );
814  else if ( myURI.endsWith( QLatin1String( ".tar" ), Qt::CaseInsensitive ) )
815  myURI.chop( 4 );
816  else if ( myURI.endsWith( QLatin1String( ".tar.gz" ), Qt::CaseInsensitive ) )
817  myURI.chop( 7 );
818  else if ( myURI.endsWith( QLatin1String( ".tgz" ), Qt::CaseInsensitive ) )
819  myURI.chop( 4 );
820  myFileInfo.setFile( myURI );
821  // get the file name for our .qml style file
822  key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + QgsMapLayer::extensionPropertyType( type );
823  }
824  else
825  {
826  key = publicSource();
827  }
828 
829  return key;
830 }
831 
833 {
834  return baseURI( PropertyType::Metadata );
835 }
836 
837 QString QgsMapLayer::saveDefaultMetadata( bool &resultFlag )
838 {
839  return saveNamedMetadata( metadataUri(), resultFlag );
840 }
841 
842 QString QgsMapLayer::loadDefaultMetadata( bool &resultFlag )
843 {
844  return loadNamedMetadata( metadataUri(), resultFlag );
845 }
846 
847 QString QgsMapLayer::styleURI() const
848 {
849  return baseURI( PropertyType::Style );
850 }
851 
852 QString QgsMapLayer::loadDefaultStyle( bool &resultFlag )
853 {
854  return loadNamedStyle( styleURI(), resultFlag );
855 }
856 
857 bool QgsMapLayer::loadNamedMetadataFromDatabase( const QString &db, const QString &uri, QString &qmd )
858 {
859  return loadNamedPropertyFromDatabase( db, uri, qmd, PropertyType::Metadata );
860 }
861 
862 bool QgsMapLayer::loadNamedStyleFromDatabase( const QString &db, const QString &uri, QString &qml )
863 {
864  return loadNamedPropertyFromDatabase( db, uri, qml, PropertyType::Style );
865 }
866 
867 bool QgsMapLayer::loadNamedPropertyFromDatabase( const QString &db, const QString &uri, QString &xml, QgsMapLayer::PropertyType type )
868 {
869  QgsDebugMsgLevel( QStringLiteral( "db = %1 uri = %2" ).arg( db, uri ), 4 );
870 
871  bool resultFlag = false;
872 
873  // read from database
876 
877  int myResult;
878 
879  QgsDebugMsgLevel( QStringLiteral( "Trying to load style or metadata for \"%1\" from \"%2\"" ).arg( uri, db ), 4 );
880 
881  if ( db.isEmpty() || !QFile( db ).exists() )
882  return false;
883 
884  myResult = database.open_v2( db, SQLITE_OPEN_READONLY, nullptr );
885  if ( myResult != SQLITE_OK )
886  {
887  return false;
888  }
889 
890  QString mySql;
891  switch ( type )
892  {
893  case Metadata:
894  mySql = QStringLiteral( "select qmd from tbl_metadata where metadata=?" );
895  break;
896 
897  case Style:
898  mySql = QStringLiteral( "select qml from tbl_styles where style=?" );
899  break;
900  }
901 
902  statement = database.prepare( mySql, myResult );
903  if ( myResult == SQLITE_OK )
904  {
905  QByteArray param = uri.toUtf8();
906 
907  if ( sqlite3_bind_text( statement.get(), 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
908  sqlite3_step( statement.get() ) == SQLITE_ROW )
909  {
910  xml = QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( statement.get(), 0 ) ) );
911  resultFlag = true;
912  }
913  }
914  return resultFlag;
915 }
916 
917 
918 QString QgsMapLayer::loadNamedStyle( const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories )
919 {
920  return loadNamedProperty( uri, PropertyType::Style, resultFlag, categories );
921 }
922 
923 QString QgsMapLayer::loadNamedProperty( const QString &uri, QgsMapLayer::PropertyType type, bool &resultFlag, StyleCategories categories )
924 {
925  QgsDebugMsgLevel( QStringLiteral( "uri = %1 myURI = %2" ).arg( uri, publicSource() ), 4 );
926 
927  resultFlag = false;
928 
929  QDomDocument myDocument( QStringLiteral( "qgis" ) );
930 
931  // location of problem associated with errorMsg
932  int line, column;
933  QString myErrorMessage;
934 
935  QFile myFile( uri );
936  if ( myFile.open( QFile::ReadOnly ) )
937  {
938  QgsDebugMsgLevel( QStringLiteral( "file found %1" ).arg( uri ), 2 );
939  // read file
940  resultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
941  if ( !resultFlag )
942  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
943  myFile.close();
944  }
945  else
946  {
947  QFileInfo project( QgsProject::instance()->fileName() );
948  QgsDebugMsgLevel( QStringLiteral( "project fileName: %1" ).arg( project.absoluteFilePath() ), 4 );
949 
950  QString xml;
951  switch ( type )
952  {
953  case QgsMapLayer::Style:
954  {
955  if ( loadNamedStyleFromDatabase( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ), uri, xml ) ||
956  ( project.exists() && loadNamedStyleFromDatabase( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), uri, xml ) ) ||
957  loadNamedStyleFromDatabase( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/qgis.qmldb" ) ), uri, xml ) )
958  {
959  resultFlag = myDocument.setContent( xml, &myErrorMessage, &line, &column );
960  if ( !resultFlag )
961  {
962  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
963  }
964  }
965  else
966  {
967  myErrorMessage = tr( "Style not found in database" );
968  resultFlag = false;
969  }
970  break;
971  }
973  {
974  if ( loadNamedMetadataFromDatabase( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ), uri, xml ) ||
975  ( project.exists() && loadNamedMetadataFromDatabase( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), uri, xml ) ) ||
976  loadNamedMetadataFromDatabase( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/qgis.qmldb" ) ), uri, xml ) )
977  {
978  resultFlag = myDocument.setContent( xml, &myErrorMessage, &line, &column );
979  if ( !resultFlag )
980  {
981  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
982  }
983  }
984  else
985  {
986  myErrorMessage = tr( "Metadata not found in database" );
987  resultFlag = false;
988  }
989  break;
990  }
991  }
992  }
993 
994  if ( !resultFlag )
995  {
996  return myErrorMessage;
997  }
998 
999  switch ( type )
1000  {
1001  case QgsMapLayer::Style:
1002  resultFlag = importNamedStyle( myDocument, myErrorMessage, categories );
1003  if ( !resultFlag )
1004  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( uri, myErrorMessage );
1005  break;
1006  case QgsMapLayer::Metadata:
1007  resultFlag = importNamedMetadata( myDocument, myErrorMessage );
1008  if ( !resultFlag )
1009  myErrorMessage = tr( "Loading metadata file %1 failed because:\n%2" ).arg( uri, myErrorMessage );
1010  break;
1011  }
1012  return myErrorMessage;
1013 }
1014 
1015 bool QgsMapLayer::importNamedMetadata( QDomDocument &document, QString &errorMessage )
1016 {
1017  QDomElement myRoot = document.firstChildElement( QStringLiteral( "qgis" ) );
1018  if ( myRoot.isNull() )
1019  {
1020  errorMessage = tr( "Root <qgis> element could not be found" );
1021  return false;
1022  }
1023 
1024  return mMetadata.readMetadataXml( myRoot );
1025 }
1026 
1027 bool QgsMapLayer::importNamedStyle( QDomDocument &myDocument, QString &myErrorMessage, QgsMapLayer::StyleCategories categories )
1028 {
1029  QDomElement myRoot = myDocument.firstChildElement( QStringLiteral( "qgis" ) );
1030  if ( myRoot.isNull() )
1031  {
1032  myErrorMessage = tr( "Root <qgis> element could not be found" );
1033  return false;
1034  }
1035 
1036  // get style file version string, if any
1037  QgsProjectVersion fileVersion( myRoot.attribute( QStringLiteral( "version" ) ) );
1038  QgsProjectVersion thisVersion( Qgis::QGIS_VERSION );
1039 
1040  if ( thisVersion > fileVersion )
1041  {
1042  QgsProjectFileTransform styleFile( myDocument, fileVersion );
1043  styleFile.updateRevision( thisVersion );
1044  }
1045 
1046  // Get source categories
1047  QgsMapLayer::StyleCategories sourceCategories = QgsXmlUtils::readFlagAttribute( myRoot, QStringLiteral( "styleCategories" ), QgsMapLayer::AllStyleCategories );
1048 
1049  //Test for matching geometry type on vector layers when applying, if geometry type is given in the style
1050  if ( ( sourceCategories.testFlag( QgsMapLayer::Symbology ) || sourceCategories.testFlag( QgsMapLayer::Symbology3D ) ) &&
1051  ( categories.testFlag( QgsMapLayer::Symbology ) || categories.testFlag( QgsMapLayer::Symbology3D ) ) )
1052  {
1053  if ( type() == QgsMapLayerType::VectorLayer && !myRoot.firstChildElement( QStringLiteral( "layerGeometryType" ) ).isNull() )
1054  {
1055  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( this );
1056  QgsWkbTypes::GeometryType importLayerGeometryType = static_cast<QgsWkbTypes::GeometryType>( myRoot.firstChildElement( QStringLiteral( "layerGeometryType" ) ).text().toInt() );
1057  if ( vl->geometryType() != importLayerGeometryType )
1058  {
1059  myErrorMessage = tr( "Cannot apply style with symbology to layer with a different geometry type" );
1060  return false;
1061  }
1062  }
1063  }
1064 
1066  return readSymbology( myRoot, myErrorMessage, context, categories ); // TODO: support relative paths in QML?
1067 }
1068 
1069 void QgsMapLayer::exportNamedMetadata( QDomDocument &doc, QString &errorMsg ) const
1070 {
1071  QDomImplementation DomImplementation;
1072  QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1073  QDomDocument myDocument( documentType );
1074 
1075  QDomElement myRootNode = myDocument.createElement( QStringLiteral( "qgis" ) );
1076  myRootNode.setAttribute( QStringLiteral( "version" ), Qgis::QGIS_VERSION );
1077  myDocument.appendChild( myRootNode );
1078 
1079  if ( !mMetadata.writeMetadataXml( myRootNode, myDocument ) )
1080  {
1081  errorMsg = QObject::tr( "Could not save metadata" );
1082  return;
1083  }
1084 
1085  doc = myDocument;
1086 }
1087 
1088 void QgsMapLayer::exportNamedStyle( QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1089 {
1090  QDomImplementation DomImplementation;
1091  QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1092  QDomDocument myDocument( documentType );
1093 
1094  QDomElement myRootNode = myDocument.createElement( QStringLiteral( "qgis" ) );
1095  myRootNode.setAttribute( QStringLiteral( "version" ), Qgis::QGIS_VERSION );
1096  myDocument.appendChild( myRootNode );
1097 
1098  if ( !writeSymbology( myRootNode, myDocument, errorMsg, context, categories ) ) // TODO: support relative paths in QML?
1099  {
1100  errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1101  return;
1102  }
1103 
1104  /*
1105  * Check to see if the layer is vector - in which case we should also export its geometryType
1106  * to avoid eventually pasting to a layer with a different geometry
1107  */
1109  {
1110  //Getting the selectionLayer geometry
1111  const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( this );
1112  QString geoType = QString::number( vl->geometryType() );
1113 
1114  //Adding geometryinformation
1115  QDomElement layerGeometryType = myDocument.createElement( QStringLiteral( "layerGeometryType" ) );
1116  QDomText type = myDocument.createTextNode( geoType );
1117 
1118  layerGeometryType.appendChild( type );
1119  myRootNode.appendChild( layerGeometryType );
1120  }
1121 
1122  doc = myDocument;
1123 }
1124 
1125 QString QgsMapLayer::saveDefaultStyle( bool &resultFlag )
1126 {
1127  return saveNamedStyle( styleURI(), resultFlag );
1128 }
1129 
1130 QString QgsMapLayer::saveNamedMetadata( const QString &uri, bool &resultFlag )
1131 {
1132  return saveNamedProperty( uri, QgsMapLayer::Metadata, resultFlag );
1133 }
1134 
1135 QString QgsMapLayer::loadNamedMetadata( const QString &uri, bool &resultFlag )
1136 {
1137  return loadNamedProperty( uri, QgsMapLayer::Metadata, resultFlag );
1138 }
1139 
1140 QString QgsMapLayer::saveNamedProperty( const QString &uri, QgsMapLayer::PropertyType type, bool &resultFlag, StyleCategories categories )
1141 {
1142  // check if the uri is a file or ends with .qml/.qmd,
1143  // which indicates that it should become one
1144  // everything else goes to the database
1145  QString filename;
1146 
1147  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1148  if ( vlayer && vlayer->providerType() == QLatin1String( "ogr" ) )
1149  {
1150  QStringList theURIParts = uri.split( '|' );
1151  filename = theURIParts[0];
1152  }
1153  else if ( vlayer && vlayer->providerType() == QLatin1String( "gpx" ) )
1154  {
1155  QStringList theURIParts = uri.split( '?' );
1156  filename = theURIParts[0];
1157  }
1158  else if ( vlayer && vlayer->providerType() == QLatin1String( "delimitedtext" ) )
1159  {
1160  filename = QUrl::fromEncoded( uri.toLatin1() ).toLocalFile();
1161  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1162  if ( filename.isEmpty() )
1163  filename = uri;
1164  }
1165  else
1166  {
1167  filename = uri;
1168  }
1169 
1170  QString myErrorMessage;
1171  QDomDocument myDocument;
1172  switch ( type )
1173  {
1174  case Metadata:
1175  exportNamedMetadata( myDocument, myErrorMessage );
1176  break;
1177 
1178  case Style:
1179  QgsReadWriteContext context;
1180  exportNamedStyle( myDocument, myErrorMessage, context, categories );
1181  break;
1182  }
1183 
1184  QFileInfo myFileInfo( filename );
1185  if ( myFileInfo.exists() || filename.endsWith( QgsMapLayer::extensionPropertyType( type ), Qt::CaseInsensitive ) )
1186  {
1187  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1188  if ( !myDirInfo.isWritable() )
1189  {
1190  return tr( "The directory containing your dataset needs to be writable!" );
1191  }
1192 
1193  // now construct the file name for our .qml or .qmd file
1194  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + QgsMapLayer::extensionPropertyType( type );
1195 
1196  QFile myFile( myFileName );
1197  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1198  {
1199  QTextStream myFileStream( &myFile );
1200  // save as utf-8 with 2 spaces for indents
1201  myDocument.save( myFileStream, 2 );
1202  myFile.close();
1203  resultFlag = true;
1204  switch ( type )
1205  {
1206  case Metadata:
1207  return tr( "Created default metadata file as %1" ).arg( myFileName );
1208 
1209  case Style:
1210  return tr( "Created default style file as %1" ).arg( myFileName );
1211  }
1212 
1213  }
1214  else
1215  {
1216  resultFlag = false;
1217  switch ( type )
1218  {
1219  case Metadata:
1220  return tr( "ERROR: Failed to created default metadata file as %1. Check file permissions and retry." ).arg( myFileName );
1221 
1222  case Style:
1223  return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1224  }
1225  }
1226  }
1227  else
1228  {
1229  QString qml = myDocument.toString();
1230 
1231  // read from database
1232  sqlite3_database_unique_ptr database;
1233  sqlite3_statement_unique_ptr statement;
1234 
1235  int myResult = database.open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ) );
1236  if ( myResult != SQLITE_OK )
1237  {
1238  return tr( "User database could not be opened." );
1239  }
1240 
1241  QByteArray param0 = uri.toUtf8();
1242  QByteArray param1 = qml.toUtf8();
1243 
1244  QString mySql;
1245  switch ( type )
1246  {
1247  case Metadata:
1248  mySql = QStringLiteral( "create table if not exists tbl_metadata(metadata varchar primary key,qmd varchar)" );
1249  break;
1250 
1251  case Style:
1252  mySql = QStringLiteral( "create table if not exists tbl_styles(style varchar primary key,qml varchar)" );
1253  break;
1254  }
1255 
1256  statement = database.prepare( mySql, myResult );
1257  if ( myResult == SQLITE_OK )
1258  {
1259  if ( sqlite3_step( statement.get() ) != SQLITE_DONE )
1260  {
1261  resultFlag = false;
1262  switch ( type )
1263  {
1264  case Metadata:
1265  return tr( "The metadata table could not be created." );
1266 
1267  case Style:
1268  return tr( "The style table could not be created." );
1269  }
1270  }
1271  }
1272 
1273  switch ( type )
1274  {
1275  case Metadata:
1276  mySql = QStringLiteral( "insert into tbl_metadata(metadata,qmd) values (?,?)" );
1277  break;
1278 
1279  case Style:
1280  mySql = QStringLiteral( "insert into tbl_styles(style,qml) values (?,?)" );
1281  break;
1282  }
1283  statement = database.prepare( mySql, myResult );
1284  if ( myResult == SQLITE_OK )
1285  {
1286  if ( sqlite3_bind_text( statement.get(), 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1287  sqlite3_bind_text( statement.get(), 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1288  sqlite3_step( statement.get() ) == SQLITE_DONE )
1289  {
1290  resultFlag = true;
1291  switch ( type )
1292  {
1293  case Metadata:
1294  myErrorMessage = tr( "The metadata %1 was saved to database" ).arg( uri );
1295  break;
1296 
1297  case Style:
1298  myErrorMessage = tr( "The style %1 was saved to database" ).arg( uri );
1299  break;
1300  }
1301  }
1302  }
1303 
1304  if ( !resultFlag )
1305  {
1306  QString mySql;
1307  switch ( type )
1308  {
1309  case Metadata:
1310  mySql = QStringLiteral( "update tbl_metadata set qmd=? where metadata=?" );
1311  break;
1312 
1313  case Style:
1314  mySql = QStringLiteral( "update tbl_styles set qml=? where style=?" );
1315  break;
1316  }
1317  statement = database.prepare( mySql, myResult );
1318  if ( myResult == SQLITE_OK )
1319  {
1320  if ( sqlite3_bind_text( statement.get(), 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1321  sqlite3_bind_text( statement.get(), 1, 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 updated in the database." ).arg( uri );
1329  break;
1330 
1331  case Style:
1332  myErrorMessage = tr( "The style %1 was updated in the database." ).arg( uri );
1333  break;
1334  }
1335  }
1336  else
1337  {
1338  resultFlag = false;
1339  switch ( type )
1340  {
1341  case Metadata:
1342  myErrorMessage = tr( "The metadata %1 could not be updated in the database." ).arg( uri );
1343  break;
1344 
1345  case Style:
1346  myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( uri );
1347  break;
1348  }
1349  }
1350  }
1351  else
1352  {
1353  resultFlag = false;
1354  switch ( type )
1355  {
1356  case Metadata:
1357  myErrorMessage = tr( "The metadata %1 could not be inserted into database." ).arg( uri );
1358  break;
1359 
1360  case Style:
1361  myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( uri );
1362  break;
1363  }
1364  }
1365  }
1366  }
1367 
1368  return myErrorMessage;
1369 }
1370 
1371 QString QgsMapLayer::saveNamedStyle( const QString &uri, bool &resultFlag, StyleCategories categories )
1372 {
1373  return saveNamedProperty( uri, QgsMapLayer::Style, resultFlag, categories );
1374 }
1375 
1376 void QgsMapLayer::exportSldStyle( QDomDocument &doc, QString &errorMsg ) const
1377 {
1378  QDomDocument myDocument = QDomDocument();
1379 
1380  QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
1381  myDocument.appendChild( header );
1382 
1383  const QgsVectorLayer *vlayer = qobject_cast<const QgsVectorLayer *>( this );
1384  const QgsRasterLayer *rlayer = qobject_cast<const QgsRasterLayer *>( this );
1385  if ( !vlayer && !rlayer )
1386  {
1387  errorMsg = tr( "Could not save symbology because:\n%1" )
1388  .arg( tr( "Only vector and raster layers are supported" ) );
1389  return;
1390  }
1391 
1392  // Create the root element
1393  QDomElement root = myDocument.createElementNS( QStringLiteral( "http://www.opengis.net/sld" ), QStringLiteral( "StyledLayerDescriptor" ) );
1394  QDomElement layerNode;
1395  if ( vlayer )
1396  {
1397  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1.0" ) );
1398  root.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" ) );
1399  root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1400  root.setAttribute( QStringLiteral( "xmlns:se" ), QStringLiteral( "http://www.opengis.net/se" ) );
1401  root.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
1402  root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
1403  myDocument.appendChild( root );
1404 
1405  // Create the NamedLayer element
1406  layerNode = myDocument.createElement( QStringLiteral( "NamedLayer" ) );
1407  root.appendChild( layerNode );
1408  }
1409 
1410  // note: Only SLD 1.0 version is generated because seems none is using SE1.1.0 at least for rasters
1411  if ( rlayer )
1412  {
1413  // Create the root element
1414  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
1415  root.setAttribute( QStringLiteral( "xmlns:gml" ), QStringLiteral( "http://www.opengis.net/gml" ) );
1416  root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1417  root.setAttribute( QStringLiteral( "xmlns:sld" ), QStringLiteral( "http://www.opengis.net/sld" ) );
1418  myDocument.appendChild( root );
1419 
1420  // Create the NamedLayer element
1421  layerNode = myDocument.createElement( QStringLiteral( "UserLayer" ) );
1422  root.appendChild( layerNode );
1423  }
1424 
1425  QgsStringMap props;
1426  if ( hasScaleBasedVisibility() )
1427  {
1428  props[ QStringLiteral( "scaleMinDenom" ) ] = QString::number( mMinScale );
1429  props[ QStringLiteral( "scaleMaxDenom" ) ] = QString::number( mMaxScale );
1430  }
1431 
1432  if ( vlayer )
1433  {
1434  if ( !vlayer->writeSld( layerNode, myDocument, errorMsg, props ) )
1435  {
1436  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1437  return;
1438  }
1439  }
1440 
1441  if ( rlayer )
1442  {
1443  if ( !rlayer->writeSld( layerNode, myDocument, errorMsg, props ) )
1444  {
1445  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1446  return;
1447  }
1448  }
1449 
1450  doc = myDocument;
1451 }
1452 
1453 QString QgsMapLayer::saveSldStyle( const QString &uri, bool &resultFlag ) const
1454 {
1455  const QgsMapLayer *mlayer = qobject_cast<const QgsMapLayer *>( this );
1456 
1457  QString errorMsg;
1458  QDomDocument myDocument;
1459  mlayer->exportSldStyle( myDocument, errorMsg );
1460  if ( !errorMsg.isNull() )
1461  {
1462  resultFlag = false;
1463  return errorMsg;
1464  }
1465  // check if the uri is a file or ends with .sld,
1466  // which indicates that it should become one
1467  QString filename;
1468  if ( mlayer->providerType() == QLatin1String( "ogr" ) )
1469  {
1470  QStringList theURIParts = uri.split( '|' );
1471  filename = theURIParts[0];
1472  }
1473  else if ( mlayer->providerType() == QLatin1String( "gpx" ) )
1474  {
1475  QStringList theURIParts = uri.split( '?' );
1476  filename = theURIParts[0];
1477  }
1478  else if ( mlayer->providerType() == QLatin1String( "delimitedtext" ) )
1479  {
1480  filename = QUrl::fromEncoded( uri.toLatin1() ).toLocalFile();
1481  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1482  if ( filename.isEmpty() )
1483  filename = uri;
1484  }
1485  else
1486  {
1487  filename = uri;
1488  }
1489 
1490  QFileInfo myFileInfo( filename );
1491  if ( myFileInfo.exists() || filename.endsWith( QLatin1String( ".sld" ), Qt::CaseInsensitive ) )
1492  {
1493  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1494  if ( !myDirInfo.isWritable() )
1495  {
1496  return tr( "The directory containing your dataset needs to be writable!" );
1497  }
1498 
1499  // now construct the file name for our .sld style file
1500  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".sld";
1501 
1502  QFile myFile( myFileName );
1503  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1504  {
1505  QTextStream myFileStream( &myFile );
1506  // save as utf-8 with 2 spaces for indents
1507  myDocument.save( myFileStream, 2 );
1508  myFile.close();
1509  resultFlag = true;
1510  return tr( "Created default style file as %1" ).arg( myFileName );
1511  }
1512  }
1513 
1514  resultFlag = false;
1515  return tr( "ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1516 }
1517 
1518 QString QgsMapLayer::loadSldStyle( const QString &uri, bool &resultFlag )
1519 {
1520  resultFlag = false;
1521 
1522  QDomDocument myDocument;
1523 
1524  // location of problem associated with errorMsg
1525  int line, column;
1526  QString myErrorMessage;
1527 
1528  QFile myFile( uri );
1529  if ( myFile.open( QFile::ReadOnly ) )
1530  {
1531  // read file
1532  resultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
1533  if ( !resultFlag )
1534  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1535  myFile.close();
1536  }
1537  else
1538  {
1539  myErrorMessage = tr( "Unable to open file %1" ).arg( uri );
1540  }
1541 
1542  if ( !resultFlag )
1543  {
1544  return myErrorMessage;
1545  }
1546 
1547  // check for root SLD element
1548  QDomElement myRoot = myDocument.firstChildElement( QStringLiteral( "StyledLayerDescriptor" ) );
1549  if ( myRoot.isNull() )
1550  {
1551  myErrorMessage = QStringLiteral( "Error: StyledLayerDescriptor element not found in %1" ).arg( uri );
1552  resultFlag = false;
1553  return myErrorMessage;
1554  }
1555 
1556  // now get the style node out and pass it over to the layer
1557  // to deserialise...
1558  QDomElement namedLayerElem = myRoot.firstChildElement( QStringLiteral( "NamedLayer" ) );
1559  if ( namedLayerElem.isNull() )
1560  {
1561  myErrorMessage = QStringLiteral( "Info: NamedLayer element not found." );
1562  resultFlag = false;
1563  return myErrorMessage;
1564  }
1565 
1566  QString errorMsg;
1567  resultFlag = readSld( namedLayerElem, errorMsg );
1568  if ( !resultFlag )
1569  {
1570  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( uri, errorMsg );
1571  return myErrorMessage;
1572  }
1573 
1574  return QString();
1575 }
1576 
1577 bool QgsMapLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1578 {
1579  Q_UNUSED( node )
1580  Q_UNUSED( errorMessage )
1581  Q_UNUSED( context )
1582  Q_UNUSED( categories )
1583  return false;
1584 }
1585 
1586 bool QgsMapLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1587  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1588 {
1589  Q_UNUSED( node )
1590  Q_UNUSED( doc )
1591  Q_UNUSED( errorMessage )
1592  Q_UNUSED( context )
1593  Q_UNUSED( categories )
1594  return false;
1595 }
1596 
1597 void QgsMapLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag )
1598 {
1599  Q_UNUSED( dataSource )
1600  Q_UNUSED( baseName )
1601  Q_UNUSED( provider )
1602  Q_UNUSED( options )
1603  Q_UNUSED( loadDefaultStyleFlag )
1604 }
1605 
1606 
1608 {
1609  return mProviderKey;
1610 }
1611 
1612 void QgsMapLayer::readCommonStyle( const QDomElement &layerElement, const QgsReadWriteContext &context,
1613  QgsMapLayer::StyleCategories categories )
1614 {
1615  if ( categories.testFlag( Symbology3D ) )
1616  {
1617  QgsAbstract3DRenderer *r3D = nullptr;
1618  QDomElement renderer3DElem = layerElement.firstChildElement( QStringLiteral( "renderer-3d" ) );
1619  if ( !renderer3DElem.isNull() )
1620  {
1621  QString type3D = renderer3DElem.attribute( QStringLiteral( "type" ) );
1623  if ( meta3D )
1624  {
1625  r3D = meta3D->createRenderer( renderer3DElem, context );
1626  }
1627  }
1628  setRenderer3D( r3D );
1629  }
1630 
1631  if ( categories.testFlag( CustomProperties ) )
1632  {
1633  // read custom properties before passing reading further to a subclass, so that
1634  // the subclass can also read custom properties
1635  readCustomProperties( layerElement );
1636  }
1637 
1638  // use scale dependent visibility flag
1639  if ( categories.testFlag( Rendering ) )
1640  {
1641  setScaleBasedVisibility( layerElement.attribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).toInt() == 1 );
1642  if ( layerElement.hasAttribute( QStringLiteral( "minimumScale" ) ) )
1643  {
1644  // older element, when scales were reversed
1645  setMaximumScale( layerElement.attribute( QStringLiteral( "minimumScale" ) ).toDouble() );
1646  setMinimumScale( layerElement.attribute( QStringLiteral( "maximumScale" ) ).toDouble() );
1647  }
1648  else
1649  {
1650  setMaximumScale( layerElement.attribute( QStringLiteral( "maxScale" ) ).toDouble() );
1651  setMinimumScale( layerElement.attribute( QStringLiteral( "minScale" ) ).toDouble() );
1652  }
1653  }
1654 
1655  if ( categories.testFlag( LayerConfiguration ) )
1656  {
1657  // flags
1658  QDomElement flagsElem = layerElement.firstChildElement( QStringLiteral( "flags" ) );
1659  LayerFlags flags = mFlags;
1660  auto enumMap = qgsEnumMap<QgsMapLayer::LayerFlag>();
1661  for ( auto it = enumMap.constBegin(); it != enumMap.constEnd(); ++it )
1662  {
1663  QDomNode flagNode = flagsElem.namedItem( it.value() );
1664  if ( flagNode.isNull() )
1665  continue;
1666  bool flagValue = flagNode.toElement().text() == "1" ? true : false;
1667  if ( flags.testFlag( it.key() ) && !flagValue )
1668  flags &= ~it.key();
1669  else if ( !flags.testFlag( it.key() ) && flagValue )
1670  flags |= it.key();
1671  }
1672  setFlags( flags );
1673  }
1674 }
1675 
1677 {
1678  return mUndoStack;
1679 }
1680 
1682 {
1683  return mUndoStackStyles;
1684 }
1685 
1687 {
1688  return mCustomProperties.keys();
1689 }
1690 
1691 void QgsMapLayer::setCustomProperty( const QString &key, const QVariant &value )
1692 {
1693  mCustomProperties.setValue( key, value );
1694 }
1695 
1697 {
1698  mCustomProperties = properties;
1699 }
1700 
1701 QVariant QgsMapLayer::customProperty( const QString &value, const QVariant &defaultValue ) const
1702 {
1703  return mCustomProperties.value( value, defaultValue );
1704 }
1705 
1706 void QgsMapLayer::removeCustomProperty( const QString &key )
1707 {
1708  mCustomProperties.remove( key );
1709 }
1710 
1712 {
1713  return mError;
1714 }
1715 
1716 
1717 
1719 {
1720  return false;
1721 }
1722 
1724 {
1725  return true;
1726 }
1727 
1728 void QgsMapLayer::setValid( bool valid )
1729 {
1730  mValid = valid;
1731 }
1732 
1734 {
1735  if ( legend == mLegend )
1736  return;
1737 
1738  delete mLegend;
1739  mLegend = legend;
1740 
1741  if ( mLegend )
1742  {
1743  mLegend->setParent( this );
1744  connect( mLegend, &QgsMapLayerLegend::itemsChanged, this, &QgsMapLayer::legendChanged );
1745  }
1746 
1747  emit legendChanged();
1748 }
1749 
1751 {
1752  return mLegend;
1753 }
1754 
1756 {
1757  return mStyleManager;
1758 }
1759 
1761 {
1762  if ( renderer == m3DRenderer )
1763  return;
1764 
1765  delete m3DRenderer;
1766  m3DRenderer = renderer;
1767  emit renderer3DChanged();
1768 }
1769 
1771 {
1772  return m3DRenderer;
1773 }
1774 
1775 void QgsMapLayer::triggerRepaint( bool deferredUpdate )
1776 {
1777  if ( mRepaintRequestedFired )
1778  return;
1779 
1780  mRepaintRequestedFired = true;
1781  emit repaintRequested( deferredUpdate );
1782  mRepaintRequestedFired = false;
1783 }
1784 
1786 {
1787  mMetadata = metadata;
1788 // mMetadata.saveToLayer( this );
1789  emit metadataChanged();
1790 }
1791 
1793 {
1794  return QString();
1795 }
1796 
1797 QDateTime QgsMapLayer::timestamp() const
1798 {
1799  return QDateTime();
1800 }
1801 
1803 {
1804  emit styleChanged();
1805 }
1806 
1808 {
1809  mExtent = r;
1810 }
1811 
1812 bool QgsMapLayer::isReadOnly() const
1813 {
1814  return true;
1815 }
1816 
1818 {
1819  return mOriginalXmlProperties;
1820 }
1821 
1823 {
1824  mOriginalXmlProperties = originalXmlProperties;
1825 }
1826 
1827 QString QgsMapLayer::generateId( const QString &layerName )
1828 {
1829  // Generate the unique ID of this layer
1830  QString uuid = QUuid::createUuid().toString();
1831  // trim { } from uuid
1832  QString id = layerName + '_' + uuid.mid( 1, uuid.length() - 2 );
1833  // Tidy the ID up to avoid characters that may cause problems
1834  // elsewhere (e.g in some parts of XML). Replaces every non-word
1835  // character (word characters are the alphabet, numbers and
1836  // underscore) with an underscore.
1837  // Note that the first backslash in the regular expression is
1838  // there for the compiler, so the pattern is actually \W
1839  id.replace( QRegExp( "[\\W]" ), QStringLiteral( "_" ) );
1840  return id;
1841 }
1842 
1844 {
1845  return true;
1846 }
1847 
1849 {
1851 }
1852 
1853 QSet<QgsMapLayerDependency> QgsMapLayer::dependencies() const
1854 {
1855  return mDependencies;
1856 }
1857 
1858 bool QgsMapLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
1859 {
1860  QSet<QgsMapLayerDependency> deps;
1861  const auto constODeps = oDeps;
1862  for ( const QgsMapLayerDependency &dep : constODeps )
1863  {
1864  if ( dep.origin() == QgsMapLayerDependency::FromUser )
1865  deps << dep;
1866  }
1867 
1868  mDependencies = deps;
1869  emit dependenciesChanged();
1870  return true;
1871 }
1872 
1874 {
1875  if ( !dataProvider() )
1876  return;
1877 
1878  if ( enabled && !isRefreshOnNotifyEnabled() )
1879  {
1880  dataProvider()->setListening( enabled );
1881  connect( dataProvider(), &QgsVectorDataProvider::notify, this, &QgsMapLayer::onNotifiedTriggerRepaint );
1882  }
1883  else if ( !enabled && isRefreshOnNotifyEnabled() )
1884  {
1885  // we don't want to disable provider listening because someone else could need it (e.g. actions)
1886  disconnect( dataProvider(), &QgsVectorDataProvider::notify, this, &QgsMapLayer::onNotifiedTriggerRepaint );
1887  }
1888  mIsRefreshOnNofifyEnabled = enabled;
1889 }
1890 
1891 void QgsMapLayer::onNotifiedTriggerRepaint( const QString &message )
1892 {
1893  if ( refreshOnNotifyMessage().isEmpty() || refreshOnNotifyMessage() == message )
1894  triggerRepaint();
1895 }
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:1480
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:51
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:1493
QString mKeywordList
Definition: qgsmaplayer.h:1485
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:1489
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.
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:1521
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:1502
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:1517
QMap< QString, QString > QgsStringMap
Definition: qgis.h:597
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:1478
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:1505
QgsRectangle mExtent
Extent of the layer.
Definition: qgsmaplayer.h:1469
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:1496
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:1508
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:1488
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.
Reads and writes project states.
Definition: qgsproject.h:90
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:1472
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:1481
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:1498
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:1492
QString mAbstract
Description of the layer.
Definition: qgsmaplayer.h:1484
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:1518
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.
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:1475
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:441
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:1501
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:1497
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:126
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:1526
~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.