QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
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 "qgssqliteutils.h"
22#include "qgsapplication.h"
24#include "qgsdatasourceuri.h"
25#include "qgsfileutils.h"
26#include "qgslogger.h"
27#include "qgsauthmanager.h"
28#include "qgsmaplayer.h"
29#include "qgsmaplayerlegend.h"
31#include "qgspathresolver.h"
33#include "qgsproject.h"
34#include "qgsproviderregistry.h"
35#include "qgsrasterlayer.h"
36#include "qgsreadwritecontext.h"
37#include "qgsrectangle.h"
38#include "qgssldexportcontext.h"
39#include "qgsvectorlayer.h"
40#include "qgsxmlutils.h"
41#include "qgsstringutils.h"
42#include "qgsmessagelog.h"
45#include "qgsprovidermetadata.h"
46#include "qgslayernotesutils.h"
47#include "qgsdatums.h"
48#include "qgsprojoperation.h"
49#include "qgsthreadingutils.h"
50#include "qgsunittypes.h"
51
52#include <QDir>
53#include <QDomDocument>
54#include <QDomElement>
55#include <QDomImplementation>
56#include <QDomNode>
57#include <QFile>
58#include <QFileInfo>
59#include <QLocale>
60#include <QTextStream>
61#include <QUrl>
62#include <QTimer>
63#include <QStandardPaths>
64#include <QUuid>
65#include <QRegularExpression>
66
67#include <sqlite3.h>
68
70{
71 switch ( type )
72 {
73 case Metadata:
74 return QStringLiteral( ".qmd" );
75
76 case Style:
77 return QStringLiteral( ".qml" );
78 }
79 return QString();
80}
81
83 const QString &lyrname,
84 const QString &source )
85 : mDataSource( source )
86 , mLayerName( lyrname )
87 , mLayerType( type )
88 , mServerProperties( std::make_unique<QgsMapLayerServerProperties>( this ) )
89 , mUndoStack( new QUndoStack( this ) )
90 , mUndoStackStyles( new QUndoStack( this ) )
91 , mStyleManager( new QgsMapLayerStyleManager( this ) )
92 , mRefreshTimer( new QTimer( this ) )
93{
94 mID = generateId( lyrname );
97 connect( mRefreshTimer, &QTimer::timeout, this, [ = ] { triggerRepaint( true ); } );
98}
99
101{
102 if ( project() && project()->pathResolver().writePath( mDataSource ).startsWith( "attachment:" ) )
103 {
105 }
106
107 delete m3DRenderer;
108 delete mLegend;
109 delete mStyleManager;
110}
111
112void QgsMapLayer::clone( QgsMapLayer *layer ) const
113{
115
116 layer->setBlendMode( blendMode() );
117
118 const auto constStyles = styleManager()->styles();
119 for ( const QString &s : constStyles )
120 {
121 layer->styleManager()->addStyle( s, styleManager()->style( s ) );
122 }
123
124 layer->setName( name() );
125 layer->setShortName( shortName() );
126 layer->setExtent( extent() );
127 layer->setMaximumScale( maximumScale() );
128 layer->setMinimumScale( minimumScale() );
130 layer->setTitle( title() );
131 layer->setAbstract( abstract() );
132 layer->setKeywordList( keywordList() );
133 layer->setDataUrl( dataUrl() );
135 layer->setAttribution( attribution() );
137 layer->setLegendUrl( legendUrl() );
139 layer->setDependencies( dependencies() );
141 layer->setCrs( crs() );
142 layer->setCustomProperties( mCustomProperties );
143 layer->setOpacity( mLayerOpacity );
144 layer->setMetadata( mMetadata );
145 layer->serverProperties()->copyTo( mServerProperties.get() );
146}
147
149{
150 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
152
153 return mLayerType;
154}
155
156QgsMapLayer::LayerFlags QgsMapLayer::flags() const
157{
159
160 return mFlags;
161}
162
163void QgsMapLayer::setFlags( QgsMapLayer::LayerFlags flags )
164{
166
167 if ( flags == mFlags )
168 return;
169
170 mFlags = flags;
171 emit flagsChanged();
172}
173
174Qgis::MapLayerProperties QgsMapLayer::properties() const
175{
177
178 return Qgis::MapLayerProperties();
179}
180
181QString QgsMapLayer::id() const
182{
183 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
185
186 return mID;
187}
188
189void QgsMapLayer::setName( const QString &name )
190{
192
193 if ( name == mLayerName )
194 return;
195
197
198 emit nameChanged();
199}
200
201QString QgsMapLayer::name() const
202{
203 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
205
206 QgsDebugMsgLevel( "returning name '" + mLayerName + '\'', 4 );
207 return mLayerName;
208}
209
211{
213
214 return nullptr;
215}
216
218{
220
221 return nullptr;
222}
223
225{
227
228 return mShortName;
229}
230
231void QgsMapLayer::setMetadataUrl( const QString &metaUrl )
232{
234
235 QList<QgsMapLayerServerProperties::MetadataUrl> urls = serverProperties()->metadataUrls();
236 if ( urls.isEmpty() )
237 {
238 const QgsMapLayerServerProperties::MetadataUrl newItem = QgsMapLayerServerProperties::MetadataUrl( metaUrl, QLatin1String(), QLatin1String() );
239 urls.prepend( newItem );
240 }
241 else
242 {
243 const QgsMapLayerServerProperties::MetadataUrl old = urls.takeFirst();
244 const QgsMapLayerServerProperties::MetadataUrl newItem( metaUrl, old.type, old.format );
245 urls.prepend( newItem );
246 }
248}
249
251{
253
254 if ( mServerProperties->metadataUrls().isEmpty() )
255 {
256 return QLatin1String();
257 }
258 else
259 {
260 return mServerProperties->metadataUrls().first().url;
261 }
262}
263
264void QgsMapLayer::setMetadataUrlType( const QString &metaUrlType )
265{
267
268 QList<QgsMapLayerServerProperties::MetadataUrl> urls = mServerProperties->metadataUrls();
269 if ( urls.isEmpty() )
270 {
271 const QgsMapLayerServerProperties::MetadataUrl newItem( QLatin1String(), metaUrlType, QLatin1String() );
272 urls.prepend( newItem );
273 }
274 else
275 {
276 const QgsMapLayerServerProperties::MetadataUrl old = urls.takeFirst();
277 const QgsMapLayerServerProperties::MetadataUrl newItem( old.url, metaUrlType, old.format );
278 urls.prepend( newItem );
279 }
280 mServerProperties->setMetadataUrls( urls );
281}
282
284{
286
287 if ( mServerProperties->metadataUrls().isEmpty() )
288 {
289 return QLatin1String();
290 }
291 else
292 {
293 return mServerProperties->metadataUrls().first().type;
294 }
295}
296
297void QgsMapLayer::setMetadataUrlFormat( const QString &metaUrlFormat )
298{
300
301 QList<QgsMapLayerServerProperties::MetadataUrl> urls = mServerProperties->metadataUrls();
302 if ( urls.isEmpty() )
303 {
304 const QgsMapLayerServerProperties::MetadataUrl newItem( QLatin1String(), QLatin1String(), metaUrlFormat );
305 urls.prepend( newItem );
306 }
307 else
308 {
309 const QgsMapLayerServerProperties::MetadataUrl old = urls.takeFirst( );
310 const QgsMapLayerServerProperties::MetadataUrl newItem( old.url, old.type, metaUrlFormat );
311 urls.prepend( newItem );
312 }
313 mServerProperties->setMetadataUrls( urls );
314}
315
317{
319
320 if ( mServerProperties->metadataUrls().isEmpty() )
321 {
322 return QString();
323 }
324 else
325 {
326 return mServerProperties->metadataUrls().first().format;
327 }
328}
329
331{
333
334 // Redo this every time we're asked for it, as we don't know if
335 // dataSource has changed.
336 QString safeName = QgsDataSourceUri::removePassword( mDataSource );
337 return safeName;
338}
339
340QString QgsMapLayer::source() const
341{
343
344 return mDataSource;
345}
346
348{
350
351 return mExtent;
352}
353
354void QgsMapLayer::setBlendMode( const QPainter::CompositionMode blendMode )
355{
357
358 if ( mBlendMode == blendMode )
359 return;
360
361 mBlendMode = blendMode;
364}
365
366QPainter::CompositionMode QgsMapLayer::blendMode() const
367{
368 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
370
371 return mBlendMode;
372}
373
374void QgsMapLayer::setOpacity( double opacity )
375{
377
379 return;
381 emit opacityChanged( opacity );
383}
384
386{
387 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
389
390 return mLayerOpacity;
391}
392
393bool QgsMapLayer::readLayerXml( const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags )
394{
396
397 bool layerError;
399
400 QDomNode mnl;
401 QDomElement mne;
402
403 // read provider
404 QString provider;
405 mnl = layerElement.namedItem( QStringLiteral( "provider" ) );
406 mne = mnl.toElement();
407 provider = mne.text();
408
409 // set data source
410 mnl = layerElement.namedItem( QStringLiteral( "datasource" ) );
411 mne = mnl.toElement();
412 mDataSource = context.pathResolver().readPath( mne.text() );
413
414 // if the layer needs authentication, ensure the master password is set
415 const thread_local QRegularExpression rx( "authcfg=([a-z]|[A-Z]|[0-9]){7}" );
416 if ( rx.match( mDataSource ).hasMatch()
418 {
419 return false;
420 }
421
422 mDataSource = decodedSource( mDataSource, provider, context );
423
424 // Set the CRS from project file, asking the user if necessary.
425 // Make it the saved CRS to have WMS layer projected correctly.
426 // We will still overwrite whatever GDAL etc picks up anyway
427 // further down this function.
428 mnl = layerElement.namedItem( QStringLiteral( "layername" ) );
429 mne = mnl.toElement();
430
432 CUSTOM_CRS_VALIDATION savedValidation;
433
434 const QDomNode srsNode = layerElement.namedItem( QStringLiteral( "srs" ) );
435 mCRS.readXml( srsNode );
436 mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( mne.text() ) );
437 if ( isSpatial() && type() != Qgis::LayerType::Annotation )
438 mCRS.validate();
439 savedCRS = mCRS;
440
441 // Do not validate any projections in children, they will be overwritten anyway.
442 // No need to ask the user for a projections when it is overwritten, is there?
445
446 const QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Layer" ), mne.text() );
447
448 // the internal name is just the data source basename
449 //QFileInfo dataSourceFileInfo( mDataSource );
450 //internalName = dataSourceFileInfo.baseName();
451
452 // set ID
453 mnl = layerElement.namedItem( QStringLiteral( "id" ) );
454 if ( ! mnl.isNull() )
455 {
456 mne = mnl.toElement();
457 if ( ! mne.isNull() && mne.text().length() > 10 ) // should be at least 17 (yyyyMMddhhmmsszzz)
458 {
459 mID = mne.text();
460 }
461 }
462
463 // set name
464 mnl = layerElement.namedItem( QStringLiteral( "layername" ) );
465 mne = mnl.toElement();
466
467 //name can be translated
468 setName( context.projectTranslator()->translate( QStringLiteral( "project:layers:%1" ).arg( layerElement.namedItem( QStringLiteral( "id" ) ).toElement().text() ), mne.text() ) );
469
470 // now let the children grab what they need from the Dom node.
471 layerError = !readXml( layerElement, context );
472
473 // overwrite CRS with what we read from project file before the raster/vector
474 // file reading functions changed it. They will if projections is specified in the file.
475 // FIXME: is this necessary? Yes, it is (autumn 2019)
477 mCRS = savedCRS;
478
479 //short name
480 const QDomElement shortNameElem = layerElement.firstChildElement( QStringLiteral( "shortname" ) );
481 if ( !shortNameElem.isNull() )
482 {
483 mShortName = shortNameElem.text();
484 }
485
486 //title
487 const QDomElement titleElem = layerElement.firstChildElement( QStringLiteral( "title" ) );
488 if ( !titleElem.isNull() )
489 {
490 mTitle = titleElem.text();
491 }
492
493 //abstract
494 const QDomElement abstractElem = layerElement.firstChildElement( QStringLiteral( "abstract" ) );
495 if ( !abstractElem.isNull() )
496 {
497 mAbstract = abstractElem.text();
498 }
499
500 //keywordList
501 const QDomElement keywordListElem = layerElement.firstChildElement( QStringLiteral( "keywordList" ) );
502 if ( !keywordListElem.isNull() )
503 {
504 QStringList kwdList;
505 for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
506 {
507 kwdList << n.toElement().text();
508 }
509 mKeywordList = kwdList.join( QLatin1String( ", " ) );
510 }
511
512 //dataUrl
513 const QDomElement dataUrlElem = layerElement.firstChildElement( QStringLiteral( "dataUrl" ) );
514 if ( !dataUrlElem.isNull() )
515 {
516 mDataUrl = dataUrlElem.text();
517 mDataUrlFormat = dataUrlElem.attribute( QStringLiteral( "format" ), QString() );
518 }
519
520 //legendUrl
521 const QDomElement legendUrlElem = layerElement.firstChildElement( QStringLiteral( "legendUrl" ) );
522 if ( !legendUrlElem.isNull() )
523 {
524 mLegendUrl = legendUrlElem.text();
525 mLegendUrlFormat = legendUrlElem.attribute( QStringLiteral( "format" ), QString() );
526 }
527
528 //attribution
529 const QDomElement attribElem = layerElement.firstChildElement( QStringLiteral( "attribution" ) );
530 if ( !attribElem.isNull() )
531 {
532 mAttribution = attribElem.text();
533 mAttributionUrl = attribElem.attribute( QStringLiteral( "href" ), QString() );
534 }
535
536 serverProperties()->readXml( layerElement );
537
538 if ( serverProperties()->metadataUrls().isEmpty() )
539 {
540 // metadataUrl is still empty, maybe it's a QGIS Project < 3.22
541 // keep for legacy
542 const QDomElement metaUrlElem = layerElement.firstChildElement( QStringLiteral( "metadataUrl" ) );
543 if ( !metaUrlElem.isNull() )
544 {
545 const QString url = metaUrlElem.text();
546 const QString type = metaUrlElem.attribute( QStringLiteral( "type" ), QString() );
547 const QString format = metaUrlElem.attribute( QStringLiteral( "format" ), QString() );
548 const QgsMapLayerServerProperties::MetadataUrl newItem( url, type, format );
549 mServerProperties->setMetadataUrls( QList<QgsMapLayerServerProperties::MetadataUrl>() << newItem );
550 }
551 }
552
553 // mMetadata.readFromLayer( this );
554 const QDomElement metadataElem = layerElement.firstChildElement( QStringLiteral( "resourceMetadata" ) );
555 mMetadata.readMetadataXml( metadataElem );
556
557 setAutoRefreshInterval( layerElement.attribute( QStringLiteral( "autoRefreshTime" ), QStringLiteral( "0" ) ).toInt() );
558 setAutoRefreshEnabled( layerElement.attribute( QStringLiteral( "autoRefreshEnabled" ), QStringLiteral( "0" ) ).toInt() );
559 setRefreshOnNofifyMessage( layerElement.attribute( QStringLiteral( "refreshOnNotifyMessage" ), QString() ) );
560 setRefreshOnNotifyEnabled( layerElement.attribute( QStringLiteral( "refreshOnNotifyEnabled" ), QStringLiteral( "0" ) ).toInt() );
561
562 // geographic extent is read only if necessary
563 if ( mReadFlags & QgsMapLayer::ReadFlag::FlagTrustLayerMetadata )
564 {
565 const QDomNode wgs84ExtentNode = layerElement.namedItem( QStringLiteral( "wgs84extent" ) );
566 if ( !wgs84ExtentNode.isNull() )
567 mWgs84Extent = QgsXmlUtils::readRectangle( wgs84ExtentNode.toElement() );
568 }
569
570 mLegendPlaceholderImage = layerElement.attribute( QStringLiteral( "legendPlaceholderImage" ) );
571
572 return ! layerError;
573} // bool QgsMapLayer::readLayerXML
574
575
576bool QgsMapLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
577{
579
580 Q_UNUSED( layer_node )
581 Q_UNUSED( context )
582 // NOP by default; children will over-ride with behavior specific to them
583
584 // read Extent
586 {
587 const QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
588 if ( !extentNode.isNull() )
589 {
590 mExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
591 }
592 }
593
594 return true;
595} // void QgsMapLayer::readXml
596
597
598bool QgsMapLayer::writeLayerXml( QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context ) const
599{
601
602 if ( !extent().isNull() )
603 {
604 layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent, document ) );
605 layerElement.appendChild( QgsXmlUtils::writeRectangle( wgs84Extent( true ), document, QStringLiteral( "wgs84extent" ) ) );
606 }
607
608 layerElement.setAttribute( QStringLiteral( "autoRefreshTime" ), QString::number( mRefreshTimer->interval() ) );
609 layerElement.setAttribute( QStringLiteral( "autoRefreshEnabled" ), mRefreshTimer->isActive() ? 1 : 0 );
610 layerElement.setAttribute( QStringLiteral( "refreshOnNotifyEnabled" ), mIsRefreshOnNofifyEnabled ? 1 : 0 );
611 layerElement.setAttribute( QStringLiteral( "refreshOnNotifyMessage" ), mRefreshOnNofifyMessage );
612
613 // ID
614 QDomElement layerId = document.createElement( QStringLiteral( "id" ) );
615 const QDomText layerIdText = document.createTextNode( id() );
616 layerId.appendChild( layerIdText );
617
618 layerElement.appendChild( layerId );
619
620 // data source
621 QDomElement dataSource = document.createElement( QStringLiteral( "datasource" ) );
622 const QString src = context.pathResolver().writePath( encodedSource( source(), context ) );
623 const QDomText dataSourceText = document.createTextNode( src );
624 dataSource.appendChild( dataSourceText );
625 layerElement.appendChild( dataSource );
626
627 // layer name
628 QDomElement layerName = document.createElement( QStringLiteral( "layername" ) );
629 const QDomText layerNameText = document.createTextNode( name() );
630 layerName.appendChild( layerNameText );
631 layerElement.appendChild( layerName );
632
633 // layer short name
634 if ( !mShortName.isEmpty() )
635 {
636 QDomElement layerShortName = document.createElement( QStringLiteral( "shortname" ) );
637 const QDomText layerShortNameText = document.createTextNode( mShortName );
638 layerShortName.appendChild( layerShortNameText );
639 layerElement.appendChild( layerShortName );
640 }
641
642 // layer title
643 if ( !mTitle.isEmpty() )
644 {
645 QDomElement layerTitle = document.createElement( QStringLiteral( "title" ) );
646 const QDomText layerTitleText = document.createTextNode( mTitle );
647 layerTitle.appendChild( layerTitleText );
648 layerElement.appendChild( layerTitle );
649 }
650
651 // layer abstract
652 if ( !mAbstract.isEmpty() )
653 {
654 QDomElement layerAbstract = document.createElement( QStringLiteral( "abstract" ) );
655 const QDomText layerAbstractText = document.createTextNode( mAbstract );
656 layerAbstract.appendChild( layerAbstractText );
657 layerElement.appendChild( layerAbstract );
658 }
659
660 // layer keyword list
661 const QStringList keywordStringList = keywordList().split( ',' );
662 if ( !keywordStringList.isEmpty() )
663 {
664 QDomElement layerKeywordList = document.createElement( QStringLiteral( "keywordList" ) );
665 for ( int i = 0; i < keywordStringList.size(); ++i )
666 {
667 QDomElement layerKeywordValue = document.createElement( QStringLiteral( "value" ) );
668 const QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
669 layerKeywordValue.appendChild( layerKeywordText );
670 layerKeywordList.appendChild( layerKeywordValue );
671 }
672 layerElement.appendChild( layerKeywordList );
673 }
674
675 // layer dataUrl
676 const QString aDataUrl = dataUrl();
677 if ( !aDataUrl.isEmpty() )
678 {
679 QDomElement layerDataUrl = document.createElement( QStringLiteral( "dataUrl" ) );
680 const QDomText layerDataUrlText = document.createTextNode( aDataUrl );
681 layerDataUrl.appendChild( layerDataUrlText );
682 layerDataUrl.setAttribute( QStringLiteral( "format" ), dataUrlFormat() );
683 layerElement.appendChild( layerDataUrl );
684 }
685
686 // layer legendUrl
687 const QString aLegendUrl = legendUrl();
688 if ( !aLegendUrl.isEmpty() )
689 {
690 QDomElement layerLegendUrl = document.createElement( QStringLiteral( "legendUrl" ) );
691 const QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
692 layerLegendUrl.appendChild( layerLegendUrlText );
693 layerLegendUrl.setAttribute( QStringLiteral( "format" ), legendUrlFormat() );
694 layerElement.appendChild( layerLegendUrl );
695 }
696
697 // layer attribution
698 const QString aAttribution = attribution();
699 if ( !aAttribution.isEmpty() )
700 {
701 QDomElement layerAttribution = document.createElement( QStringLiteral( "attribution" ) );
702 const QDomText layerAttributionText = document.createTextNode( aAttribution );
703 layerAttribution.appendChild( layerAttributionText );
704 layerAttribution.setAttribute( QStringLiteral( "href" ), attributionUrl() );
705 layerElement.appendChild( layerAttribution );
706 }
707
708 // timestamp if supported
709 if ( timestamp() > QDateTime() )
710 {
711 QDomElement stamp = document.createElement( QStringLiteral( "timestamp" ) );
712 const QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
713 stamp.appendChild( stampText );
714 layerElement.appendChild( stamp );
715 }
716
717 layerElement.appendChild( layerName );
718
719 // zorder
720 // This is no longer stored in the project file. It is superfluous since the layers
721 // are written and read in the proper order.
722
723 // spatial reference system id
724 QDomElement mySrsElement = document.createElement( QStringLiteral( "srs" ) );
725 mCRS.writeXml( mySrsElement, document );
726 layerElement.appendChild( mySrsElement );
727
728 // layer metadata
729 QDomElement myMetadataElem = document.createElement( QStringLiteral( "resourceMetadata" ) );
730 mMetadata.writeMetadataXml( myMetadataElem, document );
731 layerElement.appendChild( myMetadataElem );
732
733 layerElement.setAttribute( QStringLiteral( "legendPlaceholderImage" ), mLegendPlaceholderImage );
734
735 // now append layer node to map layer node
736 return writeXml( layerElement, document, context );
737}
738
739void QgsMapLayer::writeCommonStyle( QDomElement &layerElement, QDomDocument &document,
740 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
741{
743
744 // save categories
745 const QMetaEnum metaEnum = QMetaEnum::fromType<QgsMapLayer::StyleCategories>();
746 const QString categoriesKeys( metaEnum.valueToKeys( static_cast<int>( categories ) ) );
747 layerElement.setAttribute( QStringLiteral( "styleCategories" ), categoriesKeys );
748
749 if ( categories.testFlag( Rendering ) )
750 {
751 // use scale dependent visibility flag
752 layerElement.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
753 layerElement.setAttribute( QStringLiteral( "maxScale" ), QString::number( maximumScale() ) );
754 layerElement.setAttribute( QStringLiteral( "minScale" ), QString::number( minimumScale() ) );
755 }
756
757 if ( categories.testFlag( Symbology3D ) )
758 {
759 if ( m3DRenderer )
760 {
761 QDomElement renderer3DElem = document.createElement( QStringLiteral( "renderer-3d" ) );
762 renderer3DElem.setAttribute( QStringLiteral( "type" ), m3DRenderer->type() );
763 m3DRenderer->writeXml( renderer3DElem, context );
764 layerElement.appendChild( renderer3DElem );
765 }
766 }
767
768 if ( categories.testFlag( LayerConfiguration ) )
769 {
770 // flags
771 // this code is saving automatically all the flags entries
772 QDomElement layerFlagsElem = document.createElement( QStringLiteral( "flags" ) );
773 const auto enumMap = qgsEnumMap<QgsMapLayer::LayerFlag>();
774 for ( auto it = enumMap.constBegin(); it != enumMap.constEnd(); ++it )
775 {
776 const bool flagValue = mFlags.testFlag( it.key() );
777 QDomElement flagElem = document.createElement( it.value() );
778 flagElem.appendChild( document.createTextNode( QString::number( flagValue ) ) );
779 layerFlagsElem.appendChild( flagElem );
780 }
781 layerElement.appendChild( layerFlagsElem );
782 }
783
784 if ( categories.testFlag( Temporal ) )
785 {
787 properties->writeXml( layerElement, document, context );
788 }
789
790 if ( categories.testFlag( Elevation ) )
791 {
793 properties->writeXml( layerElement, document, context );
794 }
795
796 if ( categories.testFlag( Notes ) && QgsLayerNotesUtils::layerHasNotes( this ) )
797 {
798 QDomElement notesElem = document.createElement( QStringLiteral( "userNotes" ) );
799 notesElem.setAttribute( QStringLiteral( "value" ), QgsLayerNotesUtils::layerNotes( this ) );
800 layerElement.appendChild( notesElem );
801 }
802
803 // custom properties
804 if ( categories.testFlag( CustomProperties ) )
805 {
806 writeCustomProperties( layerElement, document );
807 }
808}
809
810
811bool QgsMapLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
812{
814
815 Q_UNUSED( layer_node )
816 Q_UNUSED( document )
817 Q_UNUSED( context )
818 // NOP by default; children will over-ride with behavior specific to them
819
820 return true;
821}
822
823QString QgsMapLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
824{
826
827 Q_UNUSED( context )
828 return source;
829}
830
831QString QgsMapLayer::decodedSource( const QString &source, const QString &dataProvider, const QgsReadWriteContext &context ) const
832{
834
835 Q_UNUSED( context )
836 Q_UNUSED( dataProvider )
837 return source;
838}
839
841{
843
845 if ( m3DRenderer )
846 m3DRenderer->resolveReferences( *project );
847}
848
849
850void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
851{
853
854 const QgsObjectCustomProperties oldKeys = mCustomProperties;
855
856 mCustomProperties.readXml( layerNode, keyStartsWith );
857
858 for ( const QString &key : mCustomProperties.keys() )
859 {
860 if ( !oldKeys.contains( key ) || mCustomProperties.value( key ) != oldKeys.value( key ) )
861 {
862 emit customPropertyChanged( key );
863 }
864 }
865}
866
867void QgsMapLayer::writeCustomProperties( QDomNode &layerNode, QDomDocument &doc ) const
868{
870
871 mCustomProperties.writeXml( layerNode, doc );
872}
873
874void QgsMapLayer::readStyleManager( const QDomNode &layerNode )
875{
877
878 const QDomElement styleMgrElem = layerNode.firstChildElement( QStringLiteral( "map-layer-style-manager" ) );
879 if ( !styleMgrElem.isNull() )
880 mStyleManager->readXml( styleMgrElem );
881 else
882 mStyleManager->reset();
883}
884
885void QgsMapLayer::writeStyleManager( QDomNode &layerNode, QDomDocument &doc ) const
886{
888
889 if ( mStyleManager )
890 {
891 QDomElement styleMgrElem = doc.createElement( QStringLiteral( "map-layer-style-manager" ) );
892 mStyleManager->writeXml( styleMgrElem );
893 layerNode.appendChild( styleMgrElem );
894 }
895}
896
898{
900
901 return mMapTipTemplate;
902}
903
904void QgsMapLayer::setMapTipTemplate( const QString &mapTip )
905{
907
908 if ( mMapTipTemplate == mapTip )
909 return;
910
911 mMapTipTemplate = mapTip;
913}
914
916{
917 // because QgsVirtualLayerProvider is not anywhere NEAR thread safe:
919
920 return mValid;
921}
922
923#if 0
924void QgsMapLayer::connectNotify( const char *signal )
925{
926 Q_UNUSED( signal )
927 QgsDebugMsgLevel( "QgsMapLayer connected to " + QString( signal ), 3 );
928} // QgsMapLayer::connectNotify
929#endif
930
931bool QgsMapLayer::isInScaleRange( double scale ) const
932{
933 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
935
936 return !mScaleBasedVisibility ||
937 ( ( mMinScale == 0 || mMinScale * Qgis::SCALE_PRECISION < scale )
938 && ( mMaxScale == 0 || scale < mMaxScale ) );
939}
940
942{
943 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
945
946 return mScaleBasedVisibility;
947}
948
950{
952
953 return mRefreshTimer->isActive();
954}
955
957{
959
960 return mRefreshTimer->interval();
961}
962
964{
966
967 if ( interval <= 0 )
968 {
969 mRefreshTimer->stop();
970 mRefreshTimer->setInterval( 0 );
971 }
972 else
973 {
974 mRefreshTimer->setInterval( interval );
975 }
976 emit autoRefreshIntervalChanged( mRefreshTimer->isActive() ? mRefreshTimer->interval() : 0 );
977}
978
980{
982
983 if ( !enabled )
984 mRefreshTimer->stop();
985 else if ( mRefreshTimer->interval() > 0 )
986 mRefreshTimer->start();
987
988 emit autoRefreshIntervalChanged( mRefreshTimer->isActive() ? mRefreshTimer->interval() : 0 );
989}
990
992{
994
995 return mMetadata;
996}
997
999{
1001
1002 mMinScale = scale;
1003}
1004
1006{
1008
1009 return mMinScale;
1010}
1011
1013{
1015
1016 mMaxScale = scale;
1017}
1018
1020{
1022
1023 mScaleBasedVisibility = enabled;
1024}
1025
1027{
1029
1030 return mMaxScale;
1031}
1032
1033QStringList QgsMapLayer::subLayers() const
1034{
1036
1037 return QStringList();
1038}
1039
1040void QgsMapLayer::setLayerOrder( const QStringList &layers )
1041{
1043
1044 Q_UNUSED( layers )
1045}
1046
1047void QgsMapLayer::setSubLayerVisibility( const QString &name, bool vis )
1048{
1050
1051 Q_UNUSED( name )
1052 Q_UNUSED( vis )
1053}
1054
1056{
1058
1059 return false;
1060}
1061
1063{
1064 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
1066
1067 return mCRS;
1068}
1069
1070void QgsMapLayer::setCrs( const QgsCoordinateReferenceSystem &srs, bool emitSignal )
1071{
1073
1074 mCRS = srs;
1075
1076 if ( mShouldValidateCrs && isSpatial() && !mCRS.isValid() && type() != Qgis::LayerType::Annotation )
1077 {
1078 mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
1079 mCRS.validate();
1080 }
1081
1082 if ( emitSignal )
1083 emit crsChanged();
1084}
1085
1087{
1089
1090 const QgsDataProvider *lDataProvider = dataProvider();
1091 return lDataProvider ? lDataProvider->transformContext() : QgsCoordinateTransformContext();
1092}
1093
1094QString QgsMapLayer::formatLayerName( const QString &name )
1095{
1096 QString layerName( name );
1097 layerName.replace( '_', ' ' );
1099 return layerName;
1100}
1101
1102QString QgsMapLayer::baseURI( PropertyType type ) const
1103{
1105
1106 QString myURI = publicSource();
1107
1108 // first get base path for delimited text, spatialite and OGR layers,
1109 // as in these cases URI may contain layer name and/or additional
1110 // information. This also strips prefix in case if VSIFILE mechanism
1111 // is used
1112 if ( providerType() == QLatin1String( "ogr" ) || providerType() == QLatin1String( "delimitedtext" )
1113 || providerType() == QLatin1String( "gdal" ) || providerType() == QLatin1String( "spatialite" ) )
1114 {
1115 QVariantMap components = QgsProviderRegistry::instance()->decodeUri( providerType(), myURI );
1116 myURI = components["path"].toString();
1117 }
1118
1119 QFileInfo myFileInfo( myURI );
1120 QString key;
1121
1122 if ( myFileInfo.exists() )
1123 {
1124 // if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
1125 if ( myURI.endsWith( QLatin1String( ".gz" ), Qt::CaseInsensitive ) )
1126 myURI.chop( 3 );
1127 else if ( myURI.endsWith( QLatin1String( ".zip" ), Qt::CaseInsensitive ) )
1128 myURI.chop( 4 );
1129 else if ( myURI.endsWith( QLatin1String( ".tar" ), Qt::CaseInsensitive ) )
1130 myURI.chop( 4 );
1131 else if ( myURI.endsWith( QLatin1String( ".tar.gz" ), Qt::CaseInsensitive ) )
1132 myURI.chop( 7 );
1133 else if ( myURI.endsWith( QLatin1String( ".tgz" ), Qt::CaseInsensitive ) )
1134 myURI.chop( 4 );
1135 myFileInfo.setFile( myURI );
1136 // get the file name for our .qml style file
1137 key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + QgsMapLayer::extensionPropertyType( type );
1138 }
1139 else
1140 {
1141 key = publicSource();
1142 }
1143
1144 return key;
1145}
1146
1148{
1150
1151 return baseURI( PropertyType::Metadata );
1152}
1153
1154QString QgsMapLayer::saveDefaultMetadata( bool &resultFlag )
1155{
1157
1158 if ( const QgsProviderMetadata *metadata = QgsProviderRegistry::instance()->providerMetadata( providerType() ) )
1159 {
1160 if ( metadata->providerCapabilities() & QgsProviderMetadata::SaveLayerMetadata )
1161 {
1162 try
1163 {
1164 QString errorMessage;
1165 resultFlag = QgsProviderRegistry::instance()->saveLayerMetadata( providerType(), mDataSource, mMetadata, errorMessage );
1166 if ( resultFlag )
1167 return tr( "Successfully saved default layer metadata" );
1168 else
1169 return errorMessage;
1170 }
1171 catch ( QgsNotSupportedException &e )
1172 {
1173 resultFlag = false;
1174 return e.what();
1175 }
1176 }
1177 }
1178
1179 // fallback default metadata saving method, for providers which don't support (or implement) saveLayerMetadata
1180 return saveNamedMetadata( metadataUri(), resultFlag );
1181}
1182
1183QString QgsMapLayer::loadDefaultMetadata( bool &resultFlag )
1184{
1186
1187 return loadNamedMetadata( metadataUri(), resultFlag );
1188}
1189
1191{
1193
1194 return baseURI( PropertyType::Style );
1195}
1196
1197QString QgsMapLayer::loadDefaultStyle( bool &resultFlag )
1198{
1200
1201 return loadNamedStyle( styleURI(), resultFlag );
1202}
1203
1204bool QgsMapLayer::loadNamedMetadataFromDatabase( const QString &db, const QString &uri, QString &qmd )
1205{
1207
1208 return loadNamedPropertyFromDatabase( db, uri, qmd, PropertyType::Metadata );
1209}
1210
1211bool QgsMapLayer::loadNamedStyleFromDatabase( const QString &db, const QString &uri, QString &qml )
1212{
1214
1215 return loadNamedPropertyFromDatabase( db, uri, qml, PropertyType::Style );
1216}
1217
1218bool QgsMapLayer::loadNamedPropertyFromDatabase( const QString &db, const QString &uri, QString &xml, QgsMapLayer::PropertyType type )
1219{
1221
1222 QgsDebugMsgLevel( QStringLiteral( "db = %1 uri = %2" ).arg( db, uri ), 4 );
1223
1224 bool resultFlag = false;
1225
1226 // read from database
1229
1230 int myResult;
1231
1232 QgsDebugMsgLevel( QStringLiteral( "Trying to load style or metadata for \"%1\" from \"%2\"" ).arg( uri, db ), 4 );
1233
1234 if ( db.isEmpty() || !QFile( db ).exists() )
1235 return false;
1236
1237 myResult = database.open_v2( db, SQLITE_OPEN_READONLY, nullptr );
1238 if ( myResult != SQLITE_OK )
1239 {
1240 return false;
1241 }
1242
1243 QString mySql;
1244 switch ( type )
1245 {
1246 case Metadata:
1247 mySql = QStringLiteral( "select qmd from tbl_metadata where metadata=?" );
1248 break;
1249
1250 case Style:
1251 mySql = QStringLiteral( "select qml from tbl_styles where style=?" );
1252 break;
1253 }
1254
1255 statement = database.prepare( mySql, myResult );
1256 if ( myResult == SQLITE_OK )
1257 {
1258 QByteArray param = uri.toUtf8();
1259
1260 if ( sqlite3_bind_text( statement.get(), 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
1261 sqlite3_step( statement.get() ) == SQLITE_ROW )
1262 {
1263 xml = QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( statement.get(), 0 ) ) );
1264 resultFlag = true;
1265 }
1266 }
1267 return resultFlag;
1268}
1269
1270
1271QString QgsMapLayer::loadNamedStyle( const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories )
1272{
1274
1275 return loadNamedProperty( uri, PropertyType::Style, resultFlag, categories );
1276}
1277
1278QString QgsMapLayer::loadNamedProperty( const QString &uri, QgsMapLayer::PropertyType type, bool &resultFlag, StyleCategories categories )
1279{
1281
1282 QgsDebugMsgLevel( QStringLiteral( "uri = %1 myURI = %2" ).arg( uri, publicSource() ), 4 );
1283
1284 resultFlag = false;
1285 if ( uri.isEmpty() )
1286 return QString();
1287
1288 QDomDocument myDocument( QStringLiteral( "qgis" ) );
1289
1290 // location of problem associated with errorMsg
1291 int line, column;
1292 QString myErrorMessage;
1293
1294 QFile myFile( uri );
1295 if ( myFile.open( QFile::ReadOnly ) )
1296 {
1297 QgsDebugMsgLevel( QStringLiteral( "file found %1" ).arg( uri ), 2 );
1298 // read file
1299 resultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
1300 if ( !resultFlag )
1301 myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1302 myFile.close();
1303 }
1304 else
1305 {
1306 const QFileInfo project( QgsProject::instance()->fileName() );
1307 QgsDebugMsgLevel( QStringLiteral( "project fileName: %1" ).arg( project.absoluteFilePath() ), 4 );
1308
1309 QString xml;
1310 switch ( type )
1311 {
1312 case QgsMapLayer::Style:
1313 {
1314 if ( loadNamedStyleFromDatabase( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ), uri, xml ) ||
1315 ( project.exists() && loadNamedStyleFromDatabase( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), uri, xml ) ) ||
1316 loadNamedStyleFromDatabase( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/qgis.qmldb" ) ), uri, xml ) )
1317 {
1318 resultFlag = myDocument.setContent( xml, &myErrorMessage, &line, &column );
1319 if ( !resultFlag )
1320 {
1321 myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1322 }
1323 }
1324 else
1325 {
1326 myErrorMessage = tr( "Style not found in database" );
1327 resultFlag = false;
1328 }
1329 break;
1330 }
1332 {
1333 if ( loadNamedMetadataFromDatabase( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ), uri, xml ) ||
1334 ( project.exists() && loadNamedMetadataFromDatabase( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), uri, xml ) ) ||
1335 loadNamedMetadataFromDatabase( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( QStringLiteral( "resources/qgis.qmldb" ) ), uri, xml ) )
1336 {
1337 resultFlag = myDocument.setContent( xml, &myErrorMessage, &line, &column );
1338 if ( !resultFlag )
1339 {
1340 myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1341 }
1342 }
1343 else
1344 {
1345 myErrorMessage = tr( "Metadata not found in database" );
1346 resultFlag = false;
1347 }
1348 break;
1349 }
1350 }
1351 }
1352
1353 if ( !resultFlag )
1354 {
1355 return myErrorMessage;
1356 }
1357
1358 switch ( type )
1359 {
1360 case QgsMapLayer::Style:
1361 resultFlag = importNamedStyle( myDocument, myErrorMessage, categories );
1362 if ( !resultFlag )
1363 myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( uri, myErrorMessage );
1364 break;
1366 resultFlag = importNamedMetadata( myDocument, myErrorMessage );
1367 if ( !resultFlag )
1368 myErrorMessage = tr( "Loading metadata file %1 failed because:\n%2" ).arg( uri, myErrorMessage );
1369 break;
1370 }
1371 return myErrorMessage;
1372}
1373
1374bool QgsMapLayer::importNamedMetadata( QDomDocument &document, QString &errorMessage )
1375{
1377
1378 const QDomElement myRoot = document.firstChildElement( QStringLiteral( "qgis" ) );
1379 if ( myRoot.isNull() )
1380 {
1381 errorMessage = tr( "Root <qgis> element could not be found" );
1382 return false;
1383 }
1384
1385 return mMetadata.readMetadataXml( myRoot );
1386}
1387
1388bool QgsMapLayer::importNamedStyle( QDomDocument &myDocument, QString &myErrorMessage, QgsMapLayer::StyleCategories categories )
1389{
1391
1392 const QDomElement myRoot = myDocument.firstChildElement( QStringLiteral( "qgis" ) );
1393 if ( myRoot.isNull() )
1394 {
1395 myErrorMessage = tr( "Root <qgis> element could not be found" );
1396 return false;
1397 }
1398
1399 // get style file version string, if any
1400 const QgsProjectVersion fileVersion( myRoot.attribute( QStringLiteral( "version" ) ) );
1401 const QgsProjectVersion thisVersion( Qgis::version() );
1402
1403 if ( thisVersion > fileVersion )
1404 {
1405 QgsProjectFileTransform styleFile( myDocument, fileVersion );
1406 styleFile.updateRevision( thisVersion );
1407 }
1408
1409 // Get source categories
1410 const QgsMapLayer::StyleCategories sourceCategories = QgsXmlUtils::readFlagAttribute( myRoot, QStringLiteral( "styleCategories" ), QgsMapLayer::AllStyleCategories );
1411
1412 //Test for matching geometry type on vector layers when applying, if geometry type is given in the style
1413 if ( ( sourceCategories.testFlag( QgsMapLayer::Symbology ) || sourceCategories.testFlag( QgsMapLayer::Symbology3D ) ) &&
1414 ( categories.testFlag( QgsMapLayer::Symbology ) || categories.testFlag( QgsMapLayer::Symbology3D ) ) )
1415 {
1416 if ( type() == Qgis::LayerType::Vector && !myRoot.firstChildElement( QStringLiteral( "layerGeometryType" ) ).isNull() )
1417 {
1418 QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( this );
1419 const Qgis::GeometryType importLayerGeometryType = static_cast<Qgis::GeometryType>( myRoot.firstChildElement( QStringLiteral( "layerGeometryType" ) ).text().toInt() );
1420 if ( importLayerGeometryType != Qgis::GeometryType::Unknown && vl->geometryType() != importLayerGeometryType )
1421 {
1422 myErrorMessage = tr( "Cannot apply style with symbology to layer with a different geometry type" );
1423 return false;
1424 }
1425 }
1426 }
1427
1429 return readSymbology( myRoot, myErrorMessage, context, categories ); // TODO: support relative paths in QML?
1430}
1431
1432void QgsMapLayer::exportNamedMetadata( QDomDocument &doc, QString &errorMsg ) const
1433{
1435
1436 QDomImplementation DomImplementation;
1437 const QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1438 QDomDocument myDocument( documentType );
1439
1440 QDomElement myRootNode = myDocument.createElement( QStringLiteral( "qgis" ) );
1441 myRootNode.setAttribute( QStringLiteral( "version" ), Qgis::version() );
1442 myDocument.appendChild( myRootNode );
1443
1444 if ( !mMetadata.writeMetadataXml( myRootNode, myDocument ) )
1445 {
1446 errorMsg = QObject::tr( "Could not save metadata" );
1447 return;
1448 }
1449
1450 doc = myDocument;
1451}
1452
1453void QgsMapLayer::exportNamedStyle( QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1454{
1456
1457 QDomImplementation DomImplementation;
1458 const QDomDocumentType documentType = DomImplementation.createDocumentType( QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
1459 QDomDocument myDocument( documentType );
1460
1461 QDomElement myRootNode = myDocument.createElement( QStringLiteral( "qgis" ) );
1462 myRootNode.setAttribute( QStringLiteral( "version" ), Qgis::version() );
1463 myDocument.appendChild( myRootNode );
1464
1465 if ( !writeSymbology( myRootNode, myDocument, errorMsg, context, categories ) ) // TODO: support relative paths in QML?
1466 {
1467 errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1468 return;
1469 }
1470
1471 /*
1472 * Check to see if the layer is vector - in which case we should also export its geometryType
1473 * to avoid eventually pasting to a layer with a different geometry
1474 */
1475 if ( type() == Qgis::LayerType::Vector )
1476 {
1477 //Getting the selectionLayer geometry
1478 const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( this );
1479 const QString geoType = QString::number( static_cast<int>( vl->geometryType() ) );
1480
1481 //Adding geometryinformation
1482 QDomElement layerGeometryType = myDocument.createElement( QStringLiteral( "layerGeometryType" ) );
1483 const QDomText type = myDocument.createTextNode( geoType );
1484
1485 layerGeometryType.appendChild( type );
1486 myRootNode.appendChild( layerGeometryType );
1487 }
1488
1489 doc = myDocument;
1490}
1491
1492QString QgsMapLayer::saveDefaultStyle( bool &resultFlag )
1493{
1495
1496 return saveDefaultStyle( resultFlag, AllStyleCategories );
1497}
1498
1499QString QgsMapLayer::saveDefaultStyle( bool &resultFlag, StyleCategories categories )
1500{
1502
1503 return saveNamedStyle( styleURI(), resultFlag, categories );
1504}
1505
1506QString QgsMapLayer::saveNamedMetadata( const QString &uri, bool &resultFlag )
1507{
1509
1510 return saveNamedProperty( uri, QgsMapLayer::Metadata, resultFlag );
1511}
1512
1513QString QgsMapLayer::loadNamedMetadata( const QString &uri, bool &resultFlag )
1514{
1516
1517 return loadNamedProperty( uri, QgsMapLayer::Metadata, resultFlag );
1518}
1519
1520QString QgsMapLayer::saveNamedProperty( const QString &uri, QgsMapLayer::PropertyType type, bool &resultFlag, StyleCategories categories )
1521{
1523
1524 // check if the uri is a file or ends with .qml/.qmd,
1525 // which indicates that it should become one
1526 // everything else goes to the database
1527 QString filename;
1528
1529 QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1530 if ( vlayer && vlayer->providerType() == QLatin1String( "ogr" ) )
1531 {
1532 QStringList theURIParts = uri.split( '|' );
1533 filename = theURIParts[0];
1534 }
1535 else if ( vlayer && vlayer->providerType() == QLatin1String( "gpx" ) )
1536 {
1537 QStringList theURIParts = uri.split( '?' );
1538 filename = theURIParts[0];
1539 }
1540 else if ( vlayer && vlayer->providerType() == QLatin1String( "delimitedtext" ) )
1541 {
1542 filename = QUrl::fromEncoded( uri.toLatin1() ).toLocalFile();
1543 // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1544 if ( filename.isEmpty() )
1545 filename = uri;
1546 }
1547 else
1548 {
1549 filename = uri;
1550 }
1551
1552 QString myErrorMessage;
1553 QDomDocument myDocument;
1554 switch ( type )
1555 {
1556 case Metadata:
1557 exportNamedMetadata( myDocument, myErrorMessage );
1558 break;
1559
1560 case Style:
1561 const QgsReadWriteContext context;
1562 exportNamedStyle( myDocument, myErrorMessage, context, categories );
1563 break;
1564 }
1565
1566 const QFileInfo myFileInfo( filename );
1567 if ( myFileInfo.exists() || filename.endsWith( QgsMapLayer::extensionPropertyType( type ), Qt::CaseInsensitive ) )
1568 {
1569 const QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1570 if ( !myDirInfo.isWritable() )
1571 {
1572 return tr( "The directory containing your dataset needs to be writable!" );
1573 }
1574
1575 // now construct the file name for our .qml or .qmd file
1576 const QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + QgsMapLayer::extensionPropertyType( type );
1577
1578 QFile myFile( myFileName );
1579 if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1580 {
1581 QTextStream myFileStream( &myFile );
1582 // save as utf-8 with 2 spaces for indents
1583 myDocument.save( myFileStream, 2 );
1584 myFile.close();
1585 resultFlag = true;
1586 switch ( type )
1587 {
1588 case Metadata:
1589 return tr( "Created default metadata file as %1" ).arg( myFileName );
1590
1591 case Style:
1592 return tr( "Created default style file as %1" ).arg( myFileName );
1593 }
1594
1595 }
1596 else
1597 {
1598 resultFlag = false;
1599 switch ( type )
1600 {
1601 case Metadata:
1602 return tr( "ERROR: Failed to created default metadata file as %1. Check file permissions and retry." ).arg( myFileName );
1603
1604 case Style:
1605 return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1606 }
1607 }
1608 }
1609 else
1610 {
1611 const QString qml = myDocument.toString();
1612
1613 // read from database
1616
1617 int myResult = database.open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( QStringLiteral( "qgis.qmldb" ) ) );
1618 if ( myResult != SQLITE_OK )
1619 {
1620 return tr( "User database could not be opened." );
1621 }
1622
1623 QByteArray param0 = uri.toUtf8();
1624 QByteArray param1 = qml.toUtf8();
1625
1626 QString mySql;
1627 switch ( type )
1628 {
1629 case Metadata:
1630 mySql = QStringLiteral( "create table if not exists tbl_metadata(metadata varchar primary key,qmd varchar)" );
1631 break;
1632
1633 case Style:
1634 mySql = QStringLiteral( "create table if not exists tbl_styles(style varchar primary key,qml varchar)" );
1635 break;
1636 }
1637
1638 statement = database.prepare( mySql, myResult );
1639 if ( myResult == SQLITE_OK )
1640 {
1641 if ( sqlite3_step( statement.get() ) != SQLITE_DONE )
1642 {
1643 resultFlag = false;
1644 switch ( type )
1645 {
1646 case Metadata:
1647 return tr( "The metadata table could not be created." );
1648
1649 case Style:
1650 return tr( "The style table could not be created." );
1651 }
1652 }
1653 }
1654
1655 switch ( type )
1656 {
1657 case Metadata:
1658 mySql = QStringLiteral( "insert into tbl_metadata(metadata,qmd) values (?,?)" );
1659 break;
1660
1661 case Style:
1662 mySql = QStringLiteral( "insert into tbl_styles(style,qml) values (?,?)" );
1663 break;
1664 }
1665 statement = database.prepare( mySql, myResult );
1666 if ( myResult == SQLITE_OK )
1667 {
1668 if ( sqlite3_bind_text( statement.get(), 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1669 sqlite3_bind_text( statement.get(), 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1670 sqlite3_step( statement.get() ) == SQLITE_DONE )
1671 {
1672 resultFlag = true;
1673 switch ( type )
1674 {
1675 case Metadata:
1676 myErrorMessage = tr( "The metadata %1 was saved to database" ).arg( uri );
1677 break;
1678
1679 case Style:
1680 myErrorMessage = tr( "The style %1 was saved to database" ).arg( uri );
1681 break;
1682 }
1683 }
1684 }
1685
1686 if ( !resultFlag )
1687 {
1688 QString mySql;
1689 switch ( type )
1690 {
1691 case Metadata:
1692 mySql = QStringLiteral( "update tbl_metadata set qmd=? where metadata=?" );
1693 break;
1694
1695 case Style:
1696 mySql = QStringLiteral( "update tbl_styles set qml=? where style=?" );
1697 break;
1698 }
1699 statement = database.prepare( mySql, myResult );
1700 if ( myResult == SQLITE_OK )
1701 {
1702 if ( sqlite3_bind_text( statement.get(), 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1703 sqlite3_bind_text( statement.get(), 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1704 sqlite3_step( statement.get() ) == SQLITE_DONE )
1705 {
1706 resultFlag = true;
1707 switch ( type )
1708 {
1709 case Metadata:
1710 myErrorMessage = tr( "The metadata %1 was updated in the database." ).arg( uri );
1711 break;
1712
1713 case Style:
1714 myErrorMessage = tr( "The style %1 was updated in the database." ).arg( uri );
1715 break;
1716 }
1717 }
1718 else
1719 {
1720 resultFlag = false;
1721 switch ( type )
1722 {
1723 case Metadata:
1724 myErrorMessage = tr( "The metadata %1 could not be updated in the database." ).arg( uri );
1725 break;
1726
1727 case Style:
1728 myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( uri );
1729 break;
1730 }
1731 }
1732 }
1733 else
1734 {
1735 resultFlag = false;
1736 switch ( type )
1737 {
1738 case Metadata:
1739 myErrorMessage = tr( "The metadata %1 could not be inserted into database." ).arg( uri );
1740 break;
1741
1742 case Style:
1743 myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( uri );
1744 break;
1745 }
1746 }
1747 }
1748 }
1749
1750 return myErrorMessage;
1751}
1752
1753QString QgsMapLayer::saveNamedStyle( const QString &uri, bool &resultFlag, StyleCategories categories )
1754{
1756
1757 return saveNamedProperty( uri, QgsMapLayer::Style, resultFlag, categories );
1758}
1759
1760void QgsMapLayer::exportSldStyle( QDomDocument &doc, QString &errorMsg ) const
1761{
1762
1763 return exportSldStyleV2( doc, errorMsg, QgsSldExportContext() );
1764}
1765
1766void QgsMapLayer::exportSldStyleV2( QDomDocument &doc, QString &errorMsg, const QgsSldExportContext &exportContext ) const
1767{
1769
1770 QDomDocument myDocument = QDomDocument();
1771
1772 const QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
1773 myDocument.appendChild( header );
1774
1775 const QgsVectorLayer *vlayer = qobject_cast<const QgsVectorLayer *>( this );
1776 const QgsRasterLayer *rlayer = qobject_cast<const QgsRasterLayer *>( this );
1777 if ( !vlayer && !rlayer )
1778 {
1779 errorMsg = tr( "Could not save symbology because:\n%1" )
1780 .arg( tr( "Only vector and raster layers are supported" ) );
1781 return;
1782 }
1783
1784 // Create the root element
1785 QDomElement root = myDocument.createElementNS( QStringLiteral( "http://www.opengis.net/sld" ), QStringLiteral( "StyledLayerDescriptor" ) );
1786 QDomElement layerNode;
1787 if ( vlayer )
1788 {
1789 root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1.0" ) );
1790 root.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" ) );
1791 root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1792 root.setAttribute( QStringLiteral( "xmlns:se" ), QStringLiteral( "http://www.opengis.net/se" ) );
1793 root.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
1794 root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
1795 myDocument.appendChild( root );
1796
1797 // Create the NamedLayer element
1798 layerNode = myDocument.createElement( QStringLiteral( "NamedLayer" ) );
1799 root.appendChild( layerNode );
1800 }
1801
1802 // note: Only SLD 1.0 version is generated because seems none is using SE1.1.0 at least for rasters
1803 if ( rlayer )
1804 {
1805 // Create the root element
1806 root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
1807 root.setAttribute( QStringLiteral( "xmlns:gml" ), QStringLiteral( "http://www.opengis.net/gml" ) );
1808 root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
1809 root.setAttribute( QStringLiteral( "xmlns:sld" ), QStringLiteral( "http://www.opengis.net/sld" ) );
1810 myDocument.appendChild( root );
1811
1812 // Create the NamedLayer element
1813 layerNode = myDocument.createElement( QStringLiteral( "UserLayer" ) );
1814 root.appendChild( layerNode );
1815 }
1816
1817 QVariantMap props;
1818
1819 QVariant context;
1820 context.setValue( exportContext );
1821
1822 props[ QStringLiteral( "SldExportContext" ) ] = context;
1823
1825 {
1826 props[ QStringLiteral( "scaleMinDenom" ) ] = QString::number( mMinScale );
1827 props[ QStringLiteral( "scaleMaxDenom" ) ] = QString::number( mMaxScale );
1828 }
1829
1830 if ( vlayer )
1831 {
1832 if ( !vlayer->writeSld( layerNode, myDocument, errorMsg, props ) )
1833 {
1834 errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1835 return;
1836 }
1837 }
1838
1839 if ( rlayer )
1840 {
1841 if ( !rlayer->writeSld( layerNode, myDocument, errorMsg, props ) )
1842 {
1843 errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1844 return;
1845 }
1846 }
1847
1848 doc = myDocument;
1849}
1850
1851QString QgsMapLayer::saveSldStyle( const QString &uri, bool &resultFlag ) const
1852{
1853 QgsSldExportContext context;
1854 context.setExportFilePath( uri );
1855 return saveSldStyleV2( resultFlag, context );
1856}
1857
1858QString QgsMapLayer::saveSldStyleV2( bool &resultFlag, const QgsSldExportContext &exportContext ) const
1859{
1861
1862 const QgsMapLayer *mlayer = qobject_cast<const QgsMapLayer *>( this );
1863
1864 const QString uri { exportContext.exportFilePath() };
1865
1866 // check if the uri is a file or ends with .sld,
1867 // which indicates that it should become one
1868 QString filename;
1869 if ( mlayer->providerType() == QLatin1String( "ogr" ) )
1870 {
1871 QStringList theURIParts = uri.split( '|' );
1872 filename = theURIParts[0];
1873 }
1874 else if ( mlayer->providerType() == QLatin1String( "gpx" ) )
1875 {
1876 QStringList theURIParts = uri.split( '?' );
1877 filename = theURIParts[0];
1878 }
1879 else if ( mlayer->providerType() == QLatin1String( "delimitedtext" ) )
1880 {
1881 filename = QUrl::fromEncoded( uri.toLatin1() ).toLocalFile();
1882 // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1883 if ( filename.isEmpty() )
1884 filename = uri;
1885 }
1886 else
1887 {
1888 filename = uri;
1889 }
1890
1891 const QFileInfo myFileInfo( filename );
1892 if ( myFileInfo.exists() || filename.endsWith( QLatin1String( ".sld" ), Qt::CaseInsensitive ) )
1893 {
1894 const QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1895 if ( !myDirInfo.isWritable() )
1896 {
1897 return tr( "The directory containing your dataset needs to be writable!" );
1898 }
1899
1900 // now construct the file name for our .sld style file
1901 const QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".sld";
1902
1903 QString errorMsg;
1904 QDomDocument myDocument;
1905
1906 QgsSldExportContext context { exportContext };
1907 context.setExportFilePath( myFileName );
1908
1909 mlayer->exportSldStyleV2( myDocument, errorMsg, context );
1910
1911 if ( !errorMsg.isNull() )
1912 {
1913 resultFlag = false;
1914 return errorMsg;
1915 }
1916
1917 QFile myFile( myFileName );
1918 if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1919 {
1920 QTextStream myFileStream( &myFile );
1921 // save as utf-8 with 2 spaces for indents
1922 myDocument.save( myFileStream, 2 );
1923 myFile.close();
1924 resultFlag = true;
1925 return tr( "Created default style file as %1" ).arg( myFileName );
1926 }
1927 }
1928
1929 resultFlag = false;
1930 return tr( "ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1931
1932}
1933
1934QString QgsMapLayer::loadSldStyle( const QString &uri, bool &resultFlag )
1935{
1937
1938 resultFlag = false;
1939
1940 QDomDocument myDocument;
1941
1942 // location of problem associated with errorMsg
1943 int line, column;
1944 QString myErrorMessage;
1945
1946 QFile myFile( uri );
1947 if ( myFile.open( QFile::ReadOnly ) )
1948 {
1949 // read file
1950 resultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
1951 if ( !resultFlag )
1952 myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1953 myFile.close();
1954 }
1955 else
1956 {
1957 myErrorMessage = tr( "Unable to open file %1" ).arg( uri );
1958 }
1959
1960 if ( !resultFlag )
1961 {
1962 return myErrorMessage;
1963 }
1964
1965 // check for root SLD element
1966 const QDomElement myRoot = myDocument.firstChildElement( QStringLiteral( "StyledLayerDescriptor" ) );
1967 if ( myRoot.isNull() )
1968 {
1969 myErrorMessage = QStringLiteral( "Error: StyledLayerDescriptor element not found in %1" ).arg( uri );
1970 resultFlag = false;
1971 return myErrorMessage;
1972 }
1973
1974 // now get the style node out and pass it over to the layer
1975 // to deserialise...
1976 const QDomElement namedLayerElem = myRoot.firstChildElement( QStringLiteral( "NamedLayer" ) );
1977 if ( namedLayerElem.isNull() )
1978 {
1979 myErrorMessage = QStringLiteral( "Info: NamedLayer element not found." );
1980 resultFlag = false;
1981 return myErrorMessage;
1982 }
1983
1984 QString errorMsg;
1985 resultFlag = readSld( namedLayerElem, errorMsg );
1986 if ( !resultFlag )
1987 {
1988 myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( uri, errorMsg );
1989 return myErrorMessage;
1990 }
1991
1992 return QString();
1993}
1994
1995bool QgsMapLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1996{
1998
1999 Q_UNUSED( node )
2000 Q_UNUSED( errorMessage )
2001 Q_UNUSED( context )
2002 Q_UNUSED( categories )
2003 return false;
2004}
2005
2006bool QgsMapLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2007 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2008{
2010
2011 Q_UNUSED( node )
2012 Q_UNUSED( doc )
2013 Q_UNUSED( errorMessage )
2014 Q_UNUSED( context )
2015 Q_UNUSED( categories )
2016 return false;
2017}
2018
2019
2020void QgsMapLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider,
2021 bool loadDefaultStyleFlag )
2022{
2024
2026
2027 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
2028 if ( loadDefaultStyleFlag )
2029 {
2031 }
2032
2034 {
2036 }
2037 setDataSource( dataSource, baseName, provider, options, flags );
2038}
2039
2040void QgsMapLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider,
2041 const QgsDataProvider::ProviderOptions &options, bool loadDefaultStyleFlag )
2042{
2044
2045 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
2046 if ( loadDefaultStyleFlag )
2047 {
2049 }
2050
2052 {
2054 }
2055 setDataSource( dataSource, baseName, provider, options, flags );
2056}
2057
2058void QgsMapLayer::setDataSource( const QString &dataSource, const QString &baseName, const QString &provider,
2059 const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
2060{
2062
2065 {
2067 }
2068 setDataSourcePrivate( dataSource, baseName, provider, options, flags );
2069 emit dataSourceChanged();
2070 emit dataChanged();
2072}
2073
2074
2075void QgsMapLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider,
2076 const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
2077{
2079
2080 Q_UNUSED( dataSource )
2081 Q_UNUSED( baseName )
2082 Q_UNUSED( provider )
2083 Q_UNUSED( options )
2084 Q_UNUSED( flags )
2085}
2086
2087
2089{
2091
2092 return mProviderKey;
2093}
2094
2095void QgsMapLayer::readCommonStyle( const QDomElement &layerElement, const QgsReadWriteContext &context,
2096 QgsMapLayer::StyleCategories categories )
2097{
2099
2100 if ( categories.testFlag( Symbology3D ) )
2101 {
2102 const QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "3D Symbology" ) );
2103
2104 QgsAbstract3DRenderer *r3D = nullptr;
2105 QDomElement renderer3DElem = layerElement.firstChildElement( QStringLiteral( "renderer-3d" ) );
2106 if ( !renderer3DElem.isNull() )
2107 {
2108 const QString type3D = renderer3DElem.attribute( QStringLiteral( "type" ) );
2110 if ( meta3D )
2111 {
2112 r3D = meta3D->createRenderer( renderer3DElem, context );
2113 }
2114 }
2115 setRenderer3D( r3D );
2116 }
2117
2118 if ( categories.testFlag( CustomProperties ) )
2119 {
2120 // read custom properties before passing reading further to a subclass, so that
2121 // the subclass can also read custom properties
2122 readCustomProperties( layerElement );
2123 }
2124
2125 // use scale dependent visibility flag
2126 if ( categories.testFlag( Rendering ) )
2127 {
2128 setScaleBasedVisibility( layerElement.attribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).toInt() == 1 );
2129 if ( layerElement.hasAttribute( QStringLiteral( "minimumScale" ) ) )
2130 {
2131 // older element, when scales were reversed
2132 setMaximumScale( layerElement.attribute( QStringLiteral( "minimumScale" ) ).toDouble() );
2133 setMinimumScale( layerElement.attribute( QStringLiteral( "maximumScale" ) ).toDouble() );
2134 }
2135 else
2136 {
2137 setMaximumScale( layerElement.attribute( QStringLiteral( "maxScale" ) ).toDouble() );
2138 setMinimumScale( layerElement.attribute( QStringLiteral( "minScale" ) ).toDouble() );
2139 }
2140 }
2141
2142 if ( categories.testFlag( LayerConfiguration ) )
2143 {
2144 // flags
2145 const QDomElement flagsElem = layerElement.firstChildElement( QStringLiteral( "flags" ) );
2146 LayerFlags flags = mFlags;
2147 const auto enumMap = qgsEnumMap<QgsMapLayer::LayerFlag>();
2148 for ( auto it = enumMap.constBegin(); it != enumMap.constEnd(); ++it )
2149 {
2150 const QDomNode flagNode = flagsElem.namedItem( it.value() );
2151 if ( flagNode.isNull() )
2152 continue;
2153 const bool flagValue = flagNode.toElement().text() == "1" ? true : false;
2154 if ( flags.testFlag( it.key() ) && !flagValue )
2155 flags &= ~it.key();
2156 else if ( !flags.testFlag( it.key() ) && flagValue )
2157 flags |= it.key();
2158 }
2159 setFlags( flags );
2160 }
2161
2162 if ( categories.testFlag( Temporal ) )
2163 {
2164 const QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Temporal" ) );
2165
2167 properties->readXml( layerElement.toElement(), context );
2168 }
2169
2170 if ( categories.testFlag( Elevation ) )
2171 {
2172 const QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Elevation" ) );
2173
2175 properties->readXml( layerElement.toElement(), context );
2176 }
2177
2178 if ( categories.testFlag( Notes ) )
2179 {
2180 const QDomElement notesElem = layerElement.firstChildElement( QStringLiteral( "userNotes" ) );
2181 if ( !notesElem.isNull() )
2182 {
2183 const QString notes = notesElem.attribute( QStringLiteral( "value" ) );
2184 QgsLayerNotesUtils::setLayerNotes( this, notes );
2185 }
2186 }
2187}
2188
2190{
2192
2193 return mUndoStack;
2194}
2195
2197{
2199
2200 return mUndoStackStyles;
2201}
2202
2204{
2206
2207 return mCustomProperties.keys();
2208}
2209
2210void QgsMapLayer::setCustomProperty( const QString &key, const QVariant &value )
2211{
2213
2214 if ( !mCustomProperties.contains( key ) || mCustomProperties.value( key ) != value )
2215 {
2216 mCustomProperties.setValue( key, value );
2217 emit customPropertyChanged( key );
2218 }
2219}
2220
2222{
2224
2225 mCustomProperties = properties;
2226 for ( const QString &key : mCustomProperties.keys() )
2227 {
2228 emit customPropertyChanged( key );
2229 }
2230}
2231
2233{
2235
2236 return mCustomProperties;
2237}
2238
2239QVariant QgsMapLayer::customProperty( const QString &value, const QVariant &defaultValue ) const
2240{
2241 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
2243
2244 return mCustomProperties.value( value, defaultValue );
2245}
2246
2247void QgsMapLayer::removeCustomProperty( const QString &key )
2248{
2250
2251 if ( mCustomProperties.contains( key ) )
2252 {
2253 mCustomProperties.remove( key );
2254 emit customPropertyChanged( key );
2255 }
2256}
2257
2259{
2261
2262 return mError;
2263}
2264
2266{
2268
2269 return false;
2270}
2271
2273{
2275
2276 return false;
2277}
2278
2280{
2282
2283 return true;
2284}
2285
2287{
2289
2290 // invalid layers are temporary? -- who knows?!
2291 if ( !isValid() )
2292 return false;
2293
2294 if ( mProviderKey == QLatin1String( "memory" ) )
2295 return true;
2296
2297 const QVariantMap sourceParts = QgsProviderRegistry::instance()->decodeUri( mProviderKey, mDataSource );
2298 const QString path = sourceParts.value( QStringLiteral( "path" ) ).toString();
2299 if ( path.isEmpty() )
2300 return false;
2301
2302 // check if layer path is inside one of the standard temporary file locations for this platform
2303 const QStringList tempPaths = QStandardPaths::standardLocations( QStandardPaths::TempLocation );
2304 for ( const QString &tempPath : tempPaths )
2305 {
2306 if ( path.startsWith( tempPath ) )
2307 return true;
2308 }
2309
2310 return false;
2311}
2312
2313void QgsMapLayer::setValid( bool valid )
2314{
2316
2317 if ( mValid == valid )
2318 return;
2319
2320 mValid = valid;
2321 emit isValidChanged();
2322}
2323
2325{
2327
2328 if ( legend == mLegend )
2329 return;
2330
2331 delete mLegend;
2332 mLegend = legend;
2333
2334 if ( mLegend )
2335 {
2336 mLegend->setParent( this );
2337 connect( mLegend, &QgsMapLayerLegend::itemsChanged, this, &QgsMapLayer::legendChanged, Qt::UniqueConnection );
2338 }
2339
2340 emit legendChanged();
2341}
2342
2344{
2346
2347 return mLegend;
2348}
2349
2351{
2353
2354 return mStyleManager;
2355}
2356
2358{
2360
2361 if ( renderer == m3DRenderer )
2362 return;
2363
2364 delete m3DRenderer;
2365 m3DRenderer = renderer;
2366 emit renderer3DChanged();
2367 emit repaintRequested();
2369}
2370
2372{
2374
2375 return m3DRenderer;
2376}
2377
2378void QgsMapLayer::triggerRepaint( bool deferredUpdate )
2379{
2381
2382 if ( mRepaintRequestedFired )
2383 return;
2384 mRepaintRequestedFired = true;
2385 emit repaintRequested( deferredUpdate );
2386 mRepaintRequestedFired = false;
2387}
2388
2390{
2392
2393 emit request3DUpdate();
2394}
2395
2397{
2399
2400 mMetadata = metadata;
2401// mMetadata.saveToLayer( this );
2402 emit metadataChanged();
2403}
2404
2406{
2408
2409 return QString();
2410}
2411
2412QDateTime QgsMapLayer::timestamp() const
2413{
2415
2416 return QDateTime();
2417}
2418
2420{
2422
2424 emit styleChanged();
2425}
2426
2428{
2430
2431 updateExtent( extent );
2432}
2433
2434bool QgsMapLayer::isReadOnly() const
2435{
2437
2438 return true;
2439}
2440
2442{
2444
2445 return mOriginalXmlProperties;
2446}
2447
2448void QgsMapLayer::setOriginalXmlProperties( const QString &originalXmlProperties )
2449{
2451
2452 mOriginalXmlProperties = originalXmlProperties;
2453}
2454
2455QString QgsMapLayer::generateId( const QString &layerName )
2456{
2457 // Generate the unique ID of this layer
2458 const QString uuid = QUuid::createUuid().toString();
2459 // trim { } from uuid
2460 QString id = layerName + '_' + uuid.mid( 1, uuid.length() - 2 );
2461 // Tidy the ID up to avoid characters that may cause problems
2462 // elsewhere (e.g in some parts of XML). Replaces every non-word
2463 // character (word characters are the alphabet, numbers and
2464 // underscore) with an underscore.
2465 // Note that the first backslash in the regular expression is
2466 // there for the compiler, so the pattern is actually \W
2467 id.replace( QRegularExpression( "[\\W]" ), QStringLiteral( "_" ) );
2468 return id;
2469}
2470
2472{
2474
2475 return true;
2476}
2477
2479{
2481
2482 return !mMapTipTemplate.isEmpty();
2483}
2484
2485void QgsMapLayer::setProviderType( const QString &providerType )
2486{
2488
2490}
2491
2492QSet<QgsMapLayerDependency> QgsMapLayer::dependencies() const
2493{
2495
2496 return mDependencies;
2497}
2498
2499bool QgsMapLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
2500{
2502
2503 QSet<QgsMapLayerDependency> deps;
2504 const auto constODeps = oDeps;
2505 for ( const QgsMapLayerDependency &dep : constODeps )
2506 {
2507 if ( dep.origin() == QgsMapLayerDependency::FromUser )
2508 deps << dep;
2509 }
2510
2511 mDependencies = deps;
2512 emit dependenciesChanged();
2513 return true;
2514}
2515
2517{
2519
2520 QgsDataProvider *lDataProvider = dataProvider();
2521
2522 if ( !lDataProvider )
2523 return;
2524
2525 if ( enabled && !isRefreshOnNotifyEnabled() )
2526 {
2527 lDataProvider->setListening( enabled );
2528 connect( lDataProvider, &QgsDataProvider::notify, this, &QgsMapLayer::onNotified );
2529 }
2530 else if ( !enabled && isRefreshOnNotifyEnabled() )
2531 {
2532 // we don't want to disable provider listening because someone else could need it (e.g. actions)
2533 disconnect( lDataProvider, &QgsDataProvider::notify, this, &QgsMapLayer::onNotified );
2534 }
2535 mIsRefreshOnNofifyEnabled = enabled;
2536}
2537
2539{
2541
2542 if ( QgsMapLayerStore *store = qobject_cast<QgsMapLayerStore *>( parent() ) )
2543 {
2544 return qobject_cast<QgsProject *>( store->parent() );
2545 }
2546 return nullptr;
2547}
2548
2549void QgsMapLayer::onNotified( const QString &message )
2550{
2552
2553 if ( refreshOnNotifyMessage().isEmpty() || refreshOnNotifyMessage() == message )
2554 {
2556 emit dataChanged();
2557 }
2558}
2559
2560QgsRectangle QgsMapLayer::wgs84Extent( bool forceRecalculate ) const
2561{
2563
2565
2566 if ( ! forceRecalculate && ! mWgs84Extent.isNull() )
2567 {
2568 wgs84Extent = mWgs84Extent;
2569 }
2570 else if ( ! mExtent.isNull() )
2571 {
2573 transformer.setBallparkTransformsAreAppropriate( true );
2574 try
2575 {
2576 wgs84Extent = transformer.transformBoundingBox( mExtent );
2577 }
2578 catch ( const QgsCsException &cse )
2579 {
2580 QgsMessageLog::logMessage( tr( "Error transforming extent: %1" ).arg( cse.what() ) );
2582 }
2583 }
2584 return wgs84Extent;
2585}
2586
2587void QgsMapLayer::updateExtent( const QgsRectangle &extent ) const
2588{
2590
2591 if ( extent == mExtent )
2592 return;
2593
2594 mExtent = extent;
2595
2596 // do not update the wgs84 extent if we trust layer metadata
2597 if ( mReadFlags & QgsMapLayer::ReadFlag::FlagTrustLayerMetadata )
2598 return;
2599
2600 mWgs84Extent = wgs84Extent( true );
2601}
2602
2604{
2606
2607 // do not update the wgs84 extent if we trust layer metadata
2608 if ( mReadFlags & QgsMapLayer::ReadFlag::FlagTrustLayerMetadata )
2609 return;
2610
2611 mWgs84Extent = QgsRectangle();
2612}
2613
2615{
2617
2618 QString metadata = QStringLiteral( "<h1>" ) + tr( "General" ) + QStringLiteral( "</h1>\n<hr>\n" ) + QStringLiteral( "<table class=\"list-view\">\n" );
2619
2620 // name
2621 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
2622
2623 QString path;
2624 bool isLocalPath = false;
2625 if ( dataProvider() )
2626 {
2627 // local path
2628 QVariantMap uriComponents = QgsProviderRegistry::instance()->decodeUri( dataProvider()->name(), publicSource() );
2629 if ( uriComponents.contains( QStringLiteral( "path" ) ) )
2630 {
2631 path = uriComponents[QStringLiteral( "path" )].toString();
2632 QFileInfo fi( path );
2633 if ( fi.exists() )
2634 {
2635 isLocalPath = true;
2636 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Path" ) + QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( path ).toString(), QDir::toNativeSeparators( path ) ) ) + QStringLiteral( "</td></tr>\n" );
2637
2638 QDateTime lastModified = fi.lastModified();
2639 QString lastModifiedFileName;
2640 QSet<QString> sidecarFiles = QgsFileUtils::sidecarFilesForPath( path );
2641 if ( fi.isFile() )
2642 {
2643 qint64 fileSize = fi.size();
2644 if ( !sidecarFiles.isEmpty() )
2645 {
2646 lastModifiedFileName = fi.fileName();
2647 QStringList sidecarFileNames;
2648 for ( const QString &sidecarFile : sidecarFiles )
2649 {
2650 QFileInfo sidecarFi( sidecarFile );
2651 fileSize += sidecarFi.size();
2652 if ( sidecarFi.lastModified() > lastModified )
2653 {
2654 lastModified = sidecarFi.lastModified();
2655 lastModifiedFileName = sidecarFi.fileName();
2656 }
2657 sidecarFileNames << sidecarFi.fileName();
2658 }
2659 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + ( sidecarFiles.size() > 1 ? tr( "Sidecar files" ) : tr( "Sidecar file" ) ) + QStringLiteral( "</td><td>%1" ).arg( sidecarFileNames.join( QLatin1String( ", " ) ) ) + QStringLiteral( "</td></tr>\n" );
2660 }
2661 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + ( !sidecarFiles.isEmpty() ? tr( "Total size" ) : tr( "Size" ) ) + QStringLiteral( "</td><td>%1" ).arg( QgsFileUtils::representFileSize( fileSize ) ) + QStringLiteral( "</td></tr>\n" );
2662 }
2663 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Last modified" ) + QStringLiteral( "</td><td>%1" ).arg( QLocale().toString( fi.lastModified() ) ) + ( !lastModifiedFileName.isEmpty() ? QStringLiteral( " (%1)" ).arg( lastModifiedFileName ) : QString() ) + QStringLiteral( "</td></tr>\n" );
2664 }
2665 }
2666 if ( uriComponents.contains( QStringLiteral( "url" ) ) )
2667 {
2668 const QString url = uriComponents[QStringLiteral( "url" )].toString();
2669 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "URL" ) + QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl( url ).toString(), url ) ) + QStringLiteral( "</td></tr>\n" );
2670 }
2671 }
2672
2673 // data source
2674 if ( publicSource() != path || !isLocalPath )
2675 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>%1" ).arg( publicSource() != path ? publicSource() : path ) + QStringLiteral( "</td></tr>\n" );
2676
2677 // provider
2678 if ( dataProvider() )
2679 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Provider" ) + QStringLiteral( "</td><td>%1" ).arg( dataProvider()->name() ) + QStringLiteral( "</td></tr>\n" );
2680
2681 metadata += QLatin1String( "</table>\n<br><br>" );
2682 return metadata;
2683}
2684
2686{
2688
2689 QString metadata = QStringLiteral( "<h1>" ) + tr( "Coordinate Reference System (CRS)" ) + QStringLiteral( "</h1>\n<hr>\n" );
2690 metadata += QLatin1String( "<table class=\"list-view\">\n" );
2691
2692 // Identifier
2694 if ( !c.isValid() )
2695 metadata += QStringLiteral( "<tr><td colspan=\"2\" class=\"highlight\">" ) + tr( "Unknown" ) + QStringLiteral( "</td></tr>\n" );
2696 else
2697 {
2698 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + c.userFriendlyIdentifier( QgsCoordinateReferenceSystem::FullString ) + QStringLiteral( "</td></tr>\n" );
2699
2700 // map units
2701 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Units" ) + QStringLiteral( "</td><td>" )
2702 + ( c.isGeographic() ? tr( "Geographic (uses latitude and longitude for coordinates)" ) : QgsUnitTypes::toString( c.mapUnits() ) )
2703 + QStringLiteral( "</td></tr>\n" );
2704
2705
2706 // operation
2707 const QgsProjOperation operation = c.operation();
2708 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Method" ) + QStringLiteral( "</td><td>" ) + operation.description() + QStringLiteral( "</td></tr>\n" );
2709
2710 // celestial body
2711 try
2712 {
2713 const QString celestialBody = c.celestialBodyName();
2714 if ( !celestialBody.isEmpty() )
2715 {
2716 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Celestial body" ) + QStringLiteral( "</td><td>" ) + celestialBody + QStringLiteral( "</td></tr>\n" );
2717 }
2718 }
2719 catch ( QgsNotSupportedException & )
2720 {
2721
2722 }
2723
2724 QString accuracyString;
2725 // dynamic crs with no epoch?
2726 if ( c.isDynamic() && std::isnan( c.coordinateEpoch() ) )
2727 {
2728 accuracyString = tr( "Based on a dynamic CRS, but no coordinate epoch is set. Coordinates are ambiguous and of limited accuracy." );
2729 }
2730
2731 // based on datum ensemble?
2732 try
2733 {
2734 const QgsDatumEnsemble ensemble = c.datumEnsemble();
2735 if ( ensemble.isValid() )
2736 {
2737 QString id;
2738 if ( !ensemble.code().isEmpty() )
2739 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
2740 else
2741 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
2742
2743 if ( ensemble.accuracy() > 0 )
2744 {
2745 accuracyString = tr( "Based on %1, which has a limited accuracy of <b>at best %2 meters</b>." ).arg( id ).arg( ensemble.accuracy() );
2746 }
2747 else
2748 {
2749 accuracyString = tr( "Based on %1, which has a limited accuracy." ).arg( id );
2750 }
2751 }
2752 }
2753 catch ( QgsNotSupportedException & )
2754 {
2755
2756 }
2757
2758 if ( !accuracyString.isEmpty() )
2759 {
2760 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Accuracy" ) + QStringLiteral( "</td><td>" ) + accuracyString + QStringLiteral( "</td></tr>\n" );
2761 }
2762
2763 // static/dynamic
2764 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Reference" ) + QStringLiteral( "</td><td>%1</td></tr>\n" ).arg( c.isDynamic() ? tr( "Dynamic (relies on a datum which is not plate-fixed)" ) : tr( "Static (relies on a datum which is plate-fixed)" ) );
2765
2766 // coordinate epoch
2767 if ( !std::isnan( c.coordinateEpoch() ) )
2768 {
2769 metadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Coordinate epoch" ) + QStringLiteral( "</td><td>%1</td></tr>\n" ).arg( c.coordinateEpoch() );
2770 }
2771 }
2772
2773 metadata += QLatin1String( "</table>\n<br><br>\n" );
2774 return metadata;
2775}
static QString version()
Version string.
Definition: qgis.cpp:277
static const double SCALE_PRECISION
Fudge factor used to compare two scales.
Definition: qgis.h:3257
@ ForceFirstLetterToCapital
Convert just the first letter of each word to uppercase, leave the rest untouched.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition: qgis.h:228
LayerType
Types of layers that can be added to a map.
Definition: qgis.h:115
Base metadata class for 3D renderers.
virtual QgsAbstract3DRenderer * createRenderer(QDomElement &elem, const QgsReadWriteContext &context)=0
Returns new instance of the renderer given the DOM element.
Qgs3DRendererAbstractMetadata * rendererMetadata(const QString &type) const
Returns metadata for a 3D renderer type (may be used to create a new instance of the type)
Base class for all renderers that may to participate in 3D view.
virtual QString type() const =0
Returns unique identifier of the renderer class (used to identify subclass)
virtual void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const =0
Writes renderer's properties to given XML element.
virtual void resolveReferences(const QgsProject &project)
Resolves references to other objects - second phase of loading - after readXml()
static QString pkgDataPath()
Returns the common root path of all application data directories.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static Qgs3DRendererRegistry * renderer3DRegistry()
Returns registry of available 3D renderers.
bool setMasterPassword(bool verify=false)
Main call to initially set or continually check master password is set.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
void validate()
Perform some validation on this CRS.
static CUSTOM_CRS_VALIDATION customCrsValidation()
Gets custom function.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
static void setCustomCrsValidation(CUSTOM_CRS_VALIDATION f)
Sets custom function to force valid CRS.
void setValidationHint(const QString &html)
Set user hint for validation.
@ FullString
Full definition – possibly a very lengthy string, e.g. with no truncation of custom WKT definitions.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
Abstract base class for spatial data provider implementations.
@ FlagLoadDefaultStyle
Reset the layer's style to the default for the datasource.
@ FlagTrustDataSource
Trust datasource config (primary key unicity, geometry type and srid, etc). Improves provider load ti...
void notify(const QString &msg)
Emitted when the datasource issues a notification.
static QString removePassword(const QString &aUri)
Removes the password element from a URI.
Contains information about a datum ensemble.
Definition: qgsdatums.h:95
QString code() const
Identification code, e.g.
Definition: qgsdatums.h:122
QString authority() const
Authority name, e.g.
Definition: qgsdatums.h:117
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
Definition: qgsdatums.h:102
QString name() const
Display name of datum ensemble.
Definition: qgsdatums.h:107
double accuracy() const
Positional accuracy (in meters).
Definition: qgsdatums.h:112
QgsError is container for error messages (report).
Definition: qgserror.h:81
QString what() const
Definition: qgsexception.h:48
static QSet< QString > sidecarFilesForPath(const QString &path)
Returns a list of the sidecar files which exist for the dataset a the specified path.
static QString representFileSize(qint64 bytes)
Returns the human size from bytes.
A structured metadata store for a map layer.
bool readMetadataXml(const QDomElement &metadataElement) override
Sets state from DOM document.
bool writeMetadataXml(QDomElement &metadataElement, QDomDocument &document) const override
Stores state in a DOM node.
static void setLayerNotes(QgsMapLayer *layer, const QString &notes)
Sets the notes for the specified layer, where notes is a HTML formatted string.
static bool layerHasNotes(const QgsMapLayer *layer)
Returns true if the specified layer has notes available.
static QString layerNotes(const QgsMapLayer *layer)
Returns the notes for the specified layer.
This class models dependencies with or between map layers.
Base class for storage of map layer elevation properties.
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer.
void itemsChanged()
Emitted when existing items/nodes got invalid and should be replaced by new ones.
Manages QGIS Server properties for a map layer.
void readXml(const QDomNode &layer_node)
Reads server properties from project file.
void copyTo(QgsMapLayerServerProperties *properties) const
Copy properties to another instance.
A storage object for map layers, in which the layers are owned by the store and have their lifetime b...
Management of styles for use with one map layer.
bool addStyle(const QString &name, const QgsMapLayerStyle &style)
Add a style with given name and data.
QStringList styles() const
Returns list of all defined style names.
void writeXml(QDomElement &mgrElement) const
Write configuration (for project saving)
void reset()
Reset the style manager to a basic state - with one default style which is set as current.
void readXml(const QDomElement &mgrElement)
Read configuration (for project loading)
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString mKeywordList
Definition: qgsmaplayer.h:2008
void setShortName(const QString &shortName)
Sets the short name of the layer used by QGIS Server to identify the layer.
Definition: qgsmaplayer.h:288
bool importNamedMetadata(QDomDocument &document, QString &errorMessage)
Import the metadata of this layer from a QDomDocument.
QString name
Definition: qgsmaplayer.h:76
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
virtual bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const =0
Write the style for the layer into the document provided.
QString legendUrlFormat() const
Returns the format for a URL based layer legend.
Definition: qgsmaplayer.h:1318
QgsRectangle wgs84Extent(bool forceRecalculate=false) const
Returns the WGS84 extent (EPSG:4326) of the layer according to ReadFlag::FlagTrustLayerMetadata.
void setRefreshOnNotifyEnabled(bool enabled)
Set whether provider notification is connected to triggerRepaint.
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
QgsAbstract3DRenderer * renderer3D() const
Returns 3D renderer associated with the layer.
virtual bool isTemporary() const
Returns true if the layer is considered a temporary layer.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the layer.
void dependenciesChanged()
Emitted when dependencies are changed.
virtual bool hasMapTips() const
Returns true if the layer contains map tips.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
void legendChanged()
Signal emitted when legend of the layer has changed.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QgsMapLayerLegend * legend() const
Can be nullptr.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
void setAbstract(const QString &abstract)
Sets the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:317
void metadataChanged()
Emitted when the layer's metadata is changed.
virtual QgsRectangle extent() const
Returns the extent of the layer.
virtual QString saveSldStyle(const QString &uri, bool &resultFlag) const
Saves the properties of this layer to an SLD format file.
QString source() const
Returns the source for the layer.
void setLegendUrl(const QString &legendUrl)
Sets the URL for the layer's legend.
Definition: qgsmaplayer.h:1303
virtual bool setDependencies(const QSet< QgsMapLayerDependency > &layers)
Sets the list of dependencies.
void request3DUpdate()
Signal emitted when a layer requires an update in any 3D maps.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QgsError mError
Error.
Definition: qgsmaplayer.h:2023
int mBlockStyleChangedSignal
If non-zero, the styleChanged signal should not be emitted.
Definition: qgsmaplayer.h:2065
QString providerType() const
Returns the provider type (provider key) for this layer.
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
void configChanged()
Emitted whenever the configuration is changed.
void trigger3DUpdate()
Will advise any 3D maps that this layer requires to be updated in the scene.
void autoRefreshIntervalChanged(int interval)
Emitted when the auto refresh interval changes.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
virtual QSet< QgsMapLayerDependency > dependencies() const
Gets the list of dependencies.
void setCustomProperties(const QgsObjectCustomProperties &properties)
Set custom properties for layer.
virtual QString encodedSource(const QString &source, const QgsReadWriteContext &context) const
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
virtual void setSubLayerVisibility(const QString &name, bool visible)
Set the visibility of the given sublayer name.
void isValidChanged()
Emitted when the validity of this layer changed.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
bool loadNamedMetadataFromDatabase(const QString &db, const QString &uri, QString &qmd)
Retrieve a named metadata for this layer from a sqlite database.
virtual bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context)
Called by readLayerXML(), used by children to read state specific to them from project files.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
Definition: qgsmaplayer.h:420
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:395
void setOriginalXmlProperties(const QString &originalXmlProperties)
Sets the original XML properties for the layer to originalXmlProperties.
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
QString mRefreshOnNofifyMessage
Definition: qgsmaplayer.h:2036
QString mLegendUrl
WMS legend.
Definition: qgsmaplayer.h:2019
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:2001
virtual QString loadNamedMetadata(const QString &uri, bool &resultFlag)
Retrieve a named metadata for this layer if one exists (either as a .qmd file on disk or as a record ...
virtual bool writeXml(QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context) const
Called by writeLayerXML(), used by children to write state specific to them to project files.
bool hasAutoRefreshEnabled() const
Returns true if auto refresh is enabled for the layer.
void mapTipTemplateChanged()
Emitted when the map tip template changes.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
void setAttributionUrl(const QString &attribUrl)
Sets the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:403
void setAutoRefreshEnabled(bool enabled)
Sets whether auto refresh is enabled for the layer.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
static QString formatLayerName(const QString &name)
A convenience function to capitalize and format a layer name.
void renderer3DChanged()
Signal emitted when 3D renderer associated with the layer has changed.
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:325
QgsMapLayer(Qgis::LayerType type=Qgis::LayerType::Vector, const QString &name=QString(), const QString &source=QString())
Constructor for QgsMapLayer.
Definition: qgsmaplayer.cpp:82
QString originalXmlProperties() const
Returns the XML properties of the original layer as they were when the layer was first read from the ...
Qgis::LayerType type
Definition: qgsmaplayer.h:80
QString dataUrlFormat() const
Returns the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:376
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
QString mTitle
Definition: qgsmaplayer.h:2004
void setDataUrl(const QString &dataUrl)
Sets the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:350
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
void setKeywordList(const QString &keywords)
Sets the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:332
void setAttribution(const QString &attrib)
Sets the attribution of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:386
void setFlags(QgsMapLayer::LayerFlags flags)
Returns the flags for this layer.
bool isRefreshOnNotifyEnabled() const
Returns true if the refresh on provider nofification is enabled.
Definition: qgsmaplayer.h:1480
QString shortName() const
Returns the short name of the layer used by QGIS Server to identify the layer.
QSet< QgsMapLayerDependency > mDependencies
List of layers that may modify this layer on modification.
Definition: qgsmaplayer.h:2026
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
virtual Qgis::MapLayerProperties properties() const
Returns the map layer properties of this layer.
virtual QString loadSldStyle(const QString &uri, bool &resultFlag)
Attempts to style the layer using the formatting from an SLD type file.
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
virtual bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read the style for the current layer from the DOM node supplied.
virtual QString saveDefaultMetadata(bool &resultFlag)
Save the current metadata of this layer as the default metadata (either as a .qmd file on disk or as ...
virtual bool supportsEditing() const
Returns whether the layer supports editing or not.
void setDataUrlFormat(const QString &dataUrlFormat)
Sets the DataUrl format of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:367
QString mLegendUrlFormat
Definition: qgsmaplayer.h:2020
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:2039
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
void styleChanged()
Signal emitted whenever a change affects the layer's style.
virtual bool isEditable() const
Returns true if the layer can be edited.
QUndoStack * undoStack()
Returns pointer to layer's undo stack.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:310
void crsChanged()
Emit a signal that layer's CRS has been reset.
virtual QgsError error() const
Gets current status error.
bool writeLayerXml(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores state in DOM node.
virtual QString styleURI() const
Retrieve the style URI for this layer (either as a .qml file on disk or as a record in the users styl...
QString mAttributionUrl
Definition: qgsmaplayer.h:2016
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:359
bool readLayerXml(const QDomElement &layerElement, QgsReadWriteContext &context, QgsMapLayer::ReadFlags flags=QgsMapLayer::ReadFlags())
Sets state from DOM document.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
Q_DECL_DEPRECATED QString metadataUrlFormat() const
Returns the metadata format of the layer used by QGIS Server in GetCapabilities request.
void setRefreshOnNofifyMessage(const QString &message)
Set the notification message that triggers repaint If refresh on notification is enabled,...
Definition: qgsmaplayer.h:1655
static QString generateId(const QString &layerName)
Generates an unique identifier for this layer, the generate ID is prefixed by layerName.
void opacityChanged(double opacity)
Emitted when the layer's opacity is changed, where opacity is a value between 0 (transparent) and 1 (...
virtual bool isModified() const
Returns true if the layer has been modified since last commit/save.
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
Definition: qgsmaplayer.h:1523
QString mShortName
Definition: qgsmaplayer.h:2003
QUndoStack * undoStackStyles()
Returns pointer to layer's style undo stack.
void dataChanged()
Data of layer changed.
virtual QStringList subLayers() const
Returns the sublayers of this layer.
virtual QString htmlMetadata() const
Obtain a formatted HTML string containing assorted metadata for this layer.
Q_DECL_DEPRECATED void setMetadataUrlFormat(const QString &metaUrlFormat)
Sets the metadata format of the layer used by QGIS Server in GetCapabilities request.
virtual bool loadNamedStyleFromDatabase(const QString &db, const QString &uri, QString &qml)
Retrieve a named style for this layer from a sqlite database.
static QString extensionPropertyType(PropertyType type)
Returns the extension of a Property.
Definition: qgsmaplayer.cpp:69
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void blendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when the blend mode is changed, through QgsMapLayer::setBlendMode()
virtual QString saveSldStyleV2(bool &resultFlag, const QgsSldExportContext &exportContext) const
Saves the properties of this layer to an SLD format file.
void setName(const QString &name)
Set the display name of the layer.
void setAutoRefreshInterval(int interval)
Sets the auto refresh interval (in milliseconds) for the layer.
virtual bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)=0
Read the symbology for the current layer from the DOM node supplied.
Q_DECL_DEPRECATED QString metadataUrl() const
Returns the metadata URL of the layer used by QGIS Server in GetCapabilities request.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
virtual void resolveReferences(QgsProject *project)
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
QString saveNamedMetadata(const QString &uri, bool &resultFlag)
Save the current metadata of this layer as a named metadata (either as a .qmd file on disk or as a re...
bool isValid
Definition: qgsmaplayer.h:81
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1998
QString refreshOnNotifyMessage() const
Returns the message that should be notified by the provider to triggerRepaint.
Definition: qgsmaplayer.h:1473
virtual bool readSld(const QDomNode &node, QString &errorMessage)
Definition: qgsmaplayer.h:1181
virtual QString loadDefaultMetadata(bool &resultFlag)
Retrieve the default metadata for this layer if one exists (either as a .qmd file on disk or as a rec...
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
Definition: qgsmaplayer.h:635
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:634
void setValid(bool valid)
Sets whether layer is valid or not.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:412
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QString mAbstract
Description of the layer.
Definition: qgsmaplayer.h:2007
void customPropertyChanged(const QString &key)
Emitted when a custom property of the layer has been changed or removed.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:2044
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
double minimumScale() const
Returns the minimum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
QString legendUrl() const
Returns the URL for the layer's legend.
Definition: qgsmaplayer.h:1308
QString mDataUrlFormat
Definition: qgsmaplayer.h:2012
void flagsChanged()
Emitted when layer's flags have been modified.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
void setLegendUrlFormat(const QString &legendUrlFormat)
Sets the format for a URL based layer legend.
Definition: qgsmaplayer.h:1313
void exportNamedMetadata(QDomDocument &doc, QString &errorMsg) const
Export the current metadata of this layer as named metadata in a QDomDocument.
virtual QString saveNamedStyle(const QString &uri, bool &resultFlag, StyleCategories categories=AllStyleCategories)
Save the properties of this layer as a named style (either as a .qml file on disk or as a record in t...
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as SLD style in a QDomDocument.
void beforeResolveReferences(QgsProject *project)
Emitted when all layers are loaded and references can be resolved, just before the references of this...
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
Q_DECL_DEPRECATED void setMetadataUrl(const QString &metaUrl)
Sets the metadata URL of the layer used by QGIS Server in GetCapabilities request.
virtual QgsMapLayerElevationProperties * elevationProperties()
Returns the layer's elevation properties.
Definition: qgsmaplayer.h:1530
Q_INVOKABLE QStringList customPropertyKeys() const
Returns list of all keys within custom properties.
QgsProject * project() const
Returns the parent project if this map layer is added to a project.
Q_DECL_DEPRECATED void setMetadataUrlType(const QString &metaUrlType)
Set the metadata type of the layer used by QGIS Server in GetCapabilities request MetadataUrlType ind...
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:82
virtual QString decodedSource(const QString &source, const QString &dataProvider, const QgsReadWriteContext &context) const
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
void nameChanged()
Emitted when the name has been changed.
virtual QString metadataUri() const
Retrieve the metadata URI for this layer (either as a .qmd file on disk or as a record in the users s...
int autoRefreshInterval
Definition: qgsmaplayer.h:77
virtual bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write just the symbology information for the layer into the document.
bool mIsRefreshOnNofifyEnabled
Definition: qgsmaplayer.h:2035
QString mDataUrl
DataUrl of the layer.
Definition: qgsmaplayer.h:2011
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
double mLayerOpacity
Layer opacity.
Definition: qgsmaplayer.h:2058
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1995
@ AllStyleCategories
Definition: qgsmaplayer.h:179
@ LayerConfiguration
General configuration: identifiable, removable, searchable, display expression, read-only.
Definition: qgsmaplayer.h:161
@ Symbology
Symbology.
Definition: qgsmaplayer.h:162
@ Notes
Layer user notes (since QGIS 3.20)
Definition: qgsmaplayer.h:178
@ Temporal
Temporal properties (since QGIS 3.14)
Definition: qgsmaplayer.h:175
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:171
@ Elevation
Elevation settings (since QGIS 3.18)
Definition: qgsmaplayer.h:177
@ Symbology3D
3D symbology
Definition: qgsmaplayer.h:163
@ CustomProperties
Custom properties (by plugins for instance)
Definition: qgsmaplayer.h:172
virtual QDateTime timestamp() const
Time stamp of data source in the moment when data/metadata were loaded by provider.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
virtual QString saveDefaultStyle(bool &resultFlag, StyleCategories categories)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
void setRenderer3D(QgsAbstract3DRenderer *renderer)
Sets 3D renderer for the layer.
QString mAttribution
Attribution of the layer.
Definition: qgsmaplayer.h:2015
~QgsMapLayer() override
const QgsObjectCustomProperties & customProperties() const
Read all custom properties from layer.
virtual void exportSldStyleV2(QDomDocument &doc, QString &errorMsg, const QgsSldExportContext &exportContext) const
Export the properties of this layer as SLD style in a QDomDocument.
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
Q_DECL_DEPRECATED QString metadataUrlType() const
Returns the metadata type of the layer used by QGIS Server in GetCapabilities request.
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
double maximumScale() const
Returns the maximum map scale (i.e.
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:340
virtual void setLayerOrder(const QStringList &layers)
Reorders the previously selected sublayers of this layer from bottom to top.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
QString mapTipTemplate
Definition: qgsmaplayer.h:83
void setTitle(const QString &title)
Sets the title of the layer used by QGIS Server in GetCapabilities request.
Definition: qgsmaplayer.h:302
PropertyType
Maplayer has a style and a metadata property.
Definition: qgsmaplayer.h:134
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:2051
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
Definition: qgsexception.h:118
Simple key-value store (keys = strings, values = variants) that supports loading/saving to/from XML i...
void setValue(const QString &key, const QVariant &value)
Add an entry to the store with the specified key.
QStringList keys() const
Returns a list of all stored keys.
void writeXml(QDomNode &parentNode, QDomDocument &doc) const
Writes the store contents to an XML node.
void remove(const QString &key)
Removes a key (entry) from the store.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for the given key.
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from an XML node.
bool contains(const QString &key) const
Returns true if the properties contains a key with the specified name.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
Contains information about a PROJ operation.
QString description() const
Description.
Class to convert from older project file versions to newer.
bool updateRevision(const QgsProjectVersion &version)
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
The derived translate() translates with QTranslator and qm file the sourceText.
A class to describe the version of a project.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:105
bool removeAttachedFile(const QString &path)
Removes the attached file.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
QString baseName() const
Returns the base name of the project file without the path and without extension - derived from fileN...
Definition: qgsproject.cpp:893
QString absoluteFilePath() const
Returns full absolute path to the project file if the project is stored in a file system - derived fr...
Definition: qgsproject.cpp:879
Holds data provider key, description, and associated shared library file or function pointer informat...
@ SaveLayerMetadata
Indicates that the provider supports saving native layer metadata (since QGIS 3.20)
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage) SIP_THROW(QgsNotSupportedException)
Saves metadata to the layer corresponding to the specified uri.
Represents a raster layer.
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props=QVariantMap()) const
Writes the symbology of the layer into the document provided in SLD 1.0.0 format.
Allows entering a context category and takes care of leaving this category on deletion of the class.
The class is used as a container of context for various read/write operations on other objects.
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString()) const
Push a category to the stack.
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
void setMetadataUrls(const QList< QgsServerMetadataUrlProperties::MetadataUrl > &metaUrls)
Sets a the list of metadata URL for the layer.
QList< QgsServerMetadataUrlProperties::MetadataUrl > metadataUrls() const
Returns a list of metadataUrl resources associated for the layer.
The QgsSldExportContext class holds SLD export options and other information related to SLD export of...
QString exportFilePath() const
Returns the export file path for the SLD.
void setExportFilePath(const QString &exportFilePath)
Sets the export file path for the SLD to exportFilePath.
static QString capitalize(const QString &string, Qgis::Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
An interface for classes which can visit style entity (e.g.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
Represents a vector layer which manages a vector based data sets.
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props=QVariantMap()) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
static T readFlagAttribute(const QDomElement &element, const QString &attributeName, T defaultValue)
Read a flag value from an attribute of the element.
Definition: qgsxmlutils.h:99
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc, const QString &elementName=QStringLiteral("extent"))
Encodes a rectangle to a DOM element.
Definition: qgsxmlutils.cpp:81
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:39
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
int open(const QString &path)
Opens the database at the specified file path.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:3509
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition: qgis.h:4005
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS_NON_FATAL
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.
QString format
Format specification of online resource.