QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 <QDateTime>
20 #include <QDir>
21 #include <QDomDocument>
22 #include <QDomElement>
23 #include <QDomImplementation>
24 #include <QDomNode>
25 #include <QFile>
26 #include <QFileInfo>
27 #include <QSettings> // TODO: get rid of it [MD]
28 #include <QTextStream>
29 #include <QUrl>
30 
31 #include <sqlite3.h>
32 
33 #include "qgsapplication.h"
35 #include "qgsdatasourceuri.h"
36 #include "qgslogger.h"
37 #include "qgsauthmanager.h"
38 #include "qgsmaplayer.h"
39 #include "qgsmaplayerlegend.h"
41 #include "qgspluginlayer.h"
42 #include "qgspluginlayerregistry.h"
44 #include "qgsproject.h"
45 #include "qgsproviderregistry.h"
46 #include "qgsrasterlayer.h"
47 #include "qgsrectangle.h"
48 #include "qgsvectorlayer.h"
49 #include "qgsvectordataprovider.h"
50 #include "qgsmaplayerregistry.h"
51 #include "qgsxmlutils.h"
52 
53 
55  const QString& lyrname,
56  const QString& source )
57  : mValid( false ) // assume the layer is invalid
58  , mDataSource( source )
59  , mLayerOrigName( lyrname ) // store the original name
60  , mID( "" )
61  , mLayerType( type )
62  , mBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal blending
63  , mLegend( nullptr )
64  , mStyleManager( new QgsMapLayerStyleManager( this ) )
65 {
66  // Set the display name = internal name
68 
69  mShortName = "";
70  //mShortName.replace( QRegExp( "[\\W]" ), "_" );
71 
72  // Generate the unique ID of this layer
74  mID = lyrname + dt.toString( "yyyyMMddhhmmsszzz" );
75  // Tidy the ID up to avoid characters that may cause problems
76  // elsewhere (e.g in some parts of XML). Replaces every non-word
77  // character (word characters are the alphabet, numbers and
78  // underscore) with an underscore.
79  // Note that the first backslashe in the regular expression is
80  // there for the compiler, so the pattern is actually \W
81  mID.replace( QRegExp( "[\\W]" ), "_" );
82 
83  //set some generous defaults for scale based visibility
84  mMinScale = 0;
85  mMaxScale = 100000000;
86  mScaleBasedVisibility = false;
87 
88  connect( this, SIGNAL( nameChanged() ), this, SIGNAL( layerNameChanged() ) );
89 
90  connect( mStyleManager, SIGNAL( currentStyleChanged( QString ) ), this, SIGNAL( styleChanged() ) );
91 }
92 
94 {
95  delete mLegend;
96  delete mStyleManager;
97 }
98 
100 {
101  return mLayerType;
102 }
103 
106 {
107  return mID;
108 }
109 
111 {
112  setName( name );
113 }
114 
116 {
117  QString newName = capitaliseLayerName( name );
118  if ( name == mLayerOrigName && newName == mLayerName )
119  return;
120 
121  mLayerOrigName = name; // store the new original name
122  mLayerName = newName;
123 
124  emit nameChanged();
125 }
126 
129 {
130  QgsDebugMsgLevel( "returning name '" + mLayerName + '\'', 4 );
131  return mLayerName;
132 }
133 
135 {
136  // Redo this every time we're asked for it, as we don't know if
137  // dataSource has changed.
139  return safeName;
140 }
141 
143 {
144  return mDataSource;
145 }
146 
148 {
149  return mExtent;
150 }
151 
153 void QgsMapLayer::setBlendMode( QPainter::CompositionMode blendMode )
154 {
155  mBlendMode = blendMode;
156  emit blendModeChanged( blendMode );
157  emit styleChanged();
158 }
159 
161 QPainter::CompositionMode QgsMapLayer::blendMode() const
162 {
163  return mBlendMode;
164 }
165 
166 bool QgsMapLayer::draw( QgsRenderContext& rendererContext )
167 {
168  Q_UNUSED( rendererContext );
169  return false;
170 }
171 
173 {
174  Q_UNUSED( rendererContext );
175 }
176 
177 bool QgsMapLayer::readLayerXML( const QDomElement& layerElement, const QString& relativeBasePath )
178 {
179  bool layerError;
180 
181  QDomNode mnl;
182  QDomElement mne;
183 
184  // read provider
185  QString provider;
186  mnl = layerElement.namedItem( "provider" );
187  mne = mnl.toElement();
188  provider = mne.text();
189 
190  // set data source
191  mnl = layerElement.namedItem( "datasource" );
192  mne = mnl.toElement();
193  mDataSource = mne.text();
194 
195  // if the layer needs authentication, ensure the master password is set
196  QRegExp rx( "authcfg=([a-z]|[A-Z]|[0-9]){7}" );
197  if (( rx.indexIn( mDataSource ) != -1 )
199  {
200  return false;
201  }
202 
203  // TODO: this should go to providers
204  // see also QgsProject::createEmbeddedLayer
205  if ( provider == "spatialite" )
206  {
208  uri.setDatabase( QgsProject::instance()->readPath( uri.database(), relativeBasePath ) );
209  mDataSource = uri.uri();
210  }
211  else if ( provider == "ogr" )
212  {
213  QStringList theURIParts = mDataSource.split( '|' );
214  theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
215  mDataSource = theURIParts.join( "|" );
216  }
217  else if ( provider == "gpx" )
218  {
219  QStringList theURIParts = mDataSource.split( '?' );
220  theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0], relativeBasePath );
221  mDataSource = theURIParts.join( "?" );
222  }
223  else if ( provider == "delimitedtext" )
224  {
225  QUrl urlSource = QUrl::fromEncoded( mDataSource.toAscii() );
226 
227  if ( !mDataSource.startsWith( "file:" ) )
228  {
230  urlSource.setScheme( "file" );
231  urlSource.setPath( file.path() );
232  }
233 
234  QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile(), relativeBasePath ) );
235  urlDest.setQueryItems( urlSource.queryItems() );
237  }
238  else if ( provider == "wms" )
239  {
240  // >>> BACKWARD COMPATIBILITY < 1.9
241  // For project file backward compatibility we must support old format:
242  // 1. mode: <url>
243  // example: http://example.org/wms?
244  // 2. mode: tiled=<width>;<height>;<resolution>;<resolution>...,ignoreUrl=GetMap;GetFeatureInfo,featureCount=<count>,username=<name>,password=<password>,url=<url>
245  // example: tiled=256;256;0.703;0.351,url=http://example.org/tilecache?
246  // example: featureCount=10,http://example.org/wms?
247  // example: ignoreUrl=GetMap;GetFeatureInfo,username=cimrman,password=jara,url=http://example.org/wms?
248  // This is modified version of old QgsWmsProvider::parseUri
249  // The new format has always params crs,format,layers,styles and that params
250  // should not appear in old format url -> use them to identify version
251  // XYZ tile layers do not need to contain crs,format params, but they have type=xyz
252  if ( !mDataSource.contains( "type=" ) &&
253  !mDataSource.contains( "crs=" ) && !mDataSource.contains( "format=" ) )
254  {
255  QgsDebugMsg( "Old WMS URI format detected -> converting to new format" );
256  QgsDataSourceURI uri;
257  if ( !mDataSource.startsWith( "http:" ) )
258  {
259  QStringList parts = mDataSource.split( ',' );
260  QStringListIterator iter( parts );
261  while ( iter.hasNext() )
262  {
263  QString item = iter.next();
264  if ( item.startsWith( "username=" ) )
265  {
266  uri.setParam( "username", item.mid( 9 ) );
267  }
268  else if ( item.startsWith( "password=" ) )
269  {
270  uri.setParam( "password", item.mid( 9 ) );
271  }
272  else if ( item.startsWith( "tiled=" ) )
273  {
274  // in < 1.9 tiled= may apper in to variants:
275  // tiled=width;height - non tiled mode, specifies max width and max height
276  // tiled=width;height;resolutions-1;resolution2;... - tile mode
277 
278  QStringList params = item.mid( 6 ).split( ';' );
279 
280  if ( params.size() == 2 ) // non tiled mode
281  {
282  uri.setParam( "maxWidth", params.takeFirst() );
283  uri.setParam( "maxHeight", params.takeFirst() );
284  }
285  else if ( params.size() > 2 ) // tiled mode
286  {
287  // resolutions are no more needed and size limit is not used for tiles
288  // we have to tell to the provider however that it is tiled
289  uri.setParam( "tileMatrixSet", "" );
290  }
291  }
292  else if ( item.startsWith( "featureCount=" ) )
293  {
294  uri.setParam( "featureCount", item.mid( 13 ) );
295  }
296  else if ( item.startsWith( "url=" ) )
297  {
298  uri.setParam( "url", item.mid( 4 ) );
299  }
300  else if ( item.startsWith( "ignoreUrl=" ) )
301  {
302  uri.setParam( "ignoreUrl", item.mid( 10 ).split( ';' ) );
303  }
304  }
305  }
306  else
307  {
308  uri.setParam( "url", mDataSource );
309  }
310  mDataSource = uri.encodedUri();
311  // At this point, the URI is obviously incomplete, we add additional params
312  // in QgsRasterLayer::readXml
313  }
314  // <<< BACKWARD COMPATIBILITY < 1.9
315  }
316  else
317  {
318  bool handled = false;
319 
320  if ( provider == "gdal" )
321  {
322  if ( mDataSource.startsWith( "NETCDF:" ) )
323  {
324  // NETCDF:filename:variable
325  // filename can be quoted with " as it can contain colons
326  QRegExp r( "NETCDF:(.+):([^:]+)" );
327  if ( r.exactMatch( mDataSource ) )
328  {
329  QString filename = r.cap( 1 );
330  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
331  filename = filename.mid( 1, filename.length() - 2 );
332  mDataSource = "NETCDF:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
333  handled = true;
334  }
335  }
336  else if ( mDataSource.startsWith( "HDF4_SDS:" ) )
337  {
338  // HDF4_SDS:subdataset_type:file_name:subdataset_index
339  // filename can be quoted with " as it can contain colons
340  QRegExp r( "HDF4_SDS:([^:]+):(.+):([^:]+)" );
341  if ( r.exactMatch( mDataSource ) )
342  {
343  QString filename = r.cap( 2 );
344  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
345  filename = filename.mid( 1, filename.length() - 2 );
346  mDataSource = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
347  handled = true;
348  }
349  }
350  else if ( mDataSource.startsWith( "HDF5:" ) )
351  {
352  // HDF5:file_name:subdataset
353  // filename can be quoted with " as it can contain colons
354  QRegExp r( "HDF5:(.+):([^:]+)" );
355  if ( r.exactMatch( mDataSource ) )
356  {
357  QString filename = r.cap( 1 );
358  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
359  filename = filename.mid( 1, filename.length() - 2 );
360  mDataSource = "HDF5:\"" + QgsProject::instance()->readPath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
361  handled = true;
362  }
363  }
364  else if ( mDataSource.contains( QRegExp( "^(NITF_IM|RADARSAT_2_CALIB):" ) ) )
365  {
366  // NITF_IM:0:filename
367  // RADARSAT_2_CALIB:?:filename
368  QRegExp r( "([^:]+):([^:]+):(.+)" );
369  if ( r.exactMatch( mDataSource ) )
370  {
371  mDataSource = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->readPath( r.cap( 3 ), relativeBasePath );
372  handled = true;
373  }
374  }
375  }
376 
377  if ( !handled )
378  mDataSource = QgsProject::instance()->readPath( mDataSource, relativeBasePath );
379  }
380 
381  // Set the CRS from project file, asking the user if necessary.
382  // Make it the saved CRS to have WMS layer projected correctly.
383  // We will still overwrite whatever GDAL etc picks up anyway
384  // further down this function.
385  mnl = layerElement.namedItem( "layername" );
386  mne = mnl.toElement();
387 
389  CUSTOM_CRS_VALIDATION savedValidation;
390 
391  QDomNode srsNode = layerElement.namedItem( "srs" );
392  mCRS.readXML( srsNode );
393  mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( mne.text() ) );
394  mCRS.validate();
395  savedCRS = mCRS;
396 
397  // Do not validate any projections in children, they will be overwritten anyway.
398  // No need to ask the user for a projections when it is overwritten, is there?
401 
402  // now let the children grab what they need from the Dom node.
403  layerError = !readXml( layerElement );
404 
405  // overwrite CRS with what we read from project file before the raster/vector
406  // file readnig functions changed it. They will if projections is specfied in the file.
407  // FIXME: is this necessary?
409  mCRS = savedCRS;
410 
411  // Abort if any error in layer, such as not found.
412  if ( layerError )
413  {
414  return false;
415  }
416 
417  // the internal name is just the data source basename
418  //QFileInfo dataSourceFileInfo( mDataSource );
419  //internalName = dataSourceFileInfo.baseName();
420 
421  // set ID
422  mnl = layerElement.namedItem( "id" );
423  if ( ! mnl.isNull() )
424  {
425  mne = mnl.toElement();
426  if ( ! mne.isNull() && mne.text().length() > 10 ) // should be at least 17 (yyyyMMddhhmmsszzz)
427  {
428  mID = mne.text();
429  }
430  }
431 
432  // use scale dependent visibility flag
433  setScaleBasedVisibility( layerElement.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
434  setMinimumScale( layerElement.attribute( "minimumScale" ).toDouble() );
435  setMaximumScale( layerElement.attribute( "maximumScale" ).toDouble() );
436 
437  QDomNode extentNode = layerElement.namedItem( "extent" );
438  if ( !extentNode.isNull() )
439  {
440  setExtent( QgsXmlUtils::readRectangle( extentNode.toElement() ) );
441  }
442 
443  // set name
444  mnl = layerElement.namedItem( "layername" );
445  mne = mnl.toElement();
446  setName( mne.text() );
447 
448  //short name
449  QDomElement shortNameElem = layerElement.firstChildElement( "shortname" );
450  if ( !shortNameElem.isNull() )
451  {
452  mShortName = shortNameElem.text();
453  }
454 
455  //title
456  QDomElement titleElem = layerElement.firstChildElement( "title" );
457  if ( !titleElem.isNull() )
458  {
459  mTitle = titleElem.text();
460  }
461 
462  //abstract
463  QDomElement abstractElem = layerElement.firstChildElement( "abstract" );
464  if ( !abstractElem.isNull() )
465  {
466  mAbstract = abstractElem.text();
467  }
468 
469  //keywordList
470  QDomElement keywordListElem = layerElement.firstChildElement( "keywordList" );
471  if ( !keywordListElem.isNull() )
472  {
473  QStringList kwdList;
474  for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
475  {
476  kwdList << n.toElement().text();
477  }
478  mKeywordList = kwdList.join( ", " );
479  }
480 
481  //metadataUrl
482  QDomElement dataUrlElem = layerElement.firstChildElement( "dataUrl" );
483  if ( !dataUrlElem.isNull() )
484  {
485  mDataUrl = dataUrlElem.text();
486  mDataUrlFormat = dataUrlElem.attribute( "format", "" );
487  }
488 
489  //legendUrl
490  QDomElement legendUrlElem = layerElement.firstChildElement( "legendUrl" );
491  if ( !legendUrlElem.isNull() )
492  {
493  mLegendUrl = legendUrlElem.text();
494  mLegendUrlFormat = legendUrlElem.attribute( "format", "" );
495  }
496 
497  //attribution
498  QDomElement attribElem = layerElement.firstChildElement( "attribution" );
499  if ( !attribElem.isNull() )
500  {
501  mAttribution = attribElem.text();
502  mAttributionUrl = attribElem.attribute( "href", "" );
503  }
504 
505  //metadataUrl
506  QDomElement metaUrlElem = layerElement.firstChildElement( "metadataUrl" );
507  if ( !metaUrlElem.isNull() )
508  {
509  mMetadataUrl = metaUrlElem.text();
510  mMetadataUrlType = metaUrlElem.attribute( "type", "" );
511  mMetadataUrlFormat = metaUrlElem.attribute( "format", "" );
512  }
513 
514 #if 0
515  //read transparency level
516  QDomNode transparencyNode = layer_node.namedItem( "transparencyLevelInt" );
517  if ( ! transparencyNode.isNull() )
518  {
519  // set transparency level only if it's in project
520  // (otherwise it sets the layer transparent)
521  QDomElement myElement = transparencyNode.toElement();
522  setTransparency( myElement.text().toInt() );
523  }
524 #endif
525 
526  readCustomProperties( layerElement );
527 
528  return true;
529 } // bool QgsMapLayer::readLayerXML
530 
531 
532 bool QgsMapLayer::readXml( const QDomNode& layer_node )
533 {
534  Q_UNUSED( layer_node );
535  // NOP by default; children will over-ride with behavior specific to them
536 
537  return true;
538 } // void QgsMapLayer::readXml
539 
540 
541 
542 bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath )
543 {
544  // use scale dependent visibility flag
545  layerElement.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
546  layerElement.setAttribute( "minimumScale", QString::number( minimumScale() ) );
547  layerElement.setAttribute( "maximumScale", QString::number( maximumScale() ) );
548 
549  if ( !mExtent.isNull() )
550  {
551  layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent, document ) );
552  }
553 
554  // ID
555  QDomElement layerId = document.createElement( "id" );
556  QDomText layerIdText = document.createTextNode( id() );
557  layerId.appendChild( layerIdText );
558 
559  layerElement.appendChild( layerId );
560 
561  // data source
562  QDomElement dataSource = document.createElement( "datasource" );
563 
564  QString src = source();
565 
566  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
567  // TODO: what about postgres, mysql and others, they should not go through writePath()
568  if ( vlayer && vlayer->providerType() == "spatialite" )
569  {
570  QgsDataSourceURI uri( src );
571  QString database = QgsProject::instance()->writePath( uri.database(), relativeBasePath );
572  uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
573  src = uri.uri();
574  }
575  else if ( vlayer && vlayer->providerType() == "ogr" )
576  {
577  QStringList theURIParts = src.split( '|' );
578  theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0], relativeBasePath );
579  src = theURIParts.join( "|" );
580  }
581  else if ( vlayer && vlayer->providerType() == "gpx" )
582  {
583  QStringList theURIParts = src.split( '?' );
584  theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0], relativeBasePath );
585  src = theURIParts.join( "?" );
586  }
587  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
588  {
589  QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
590  QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->writePath( urlSource.toLocalFile(), relativeBasePath ) );
591  urlDest.setQueryItems( urlSource.queryItems() );
592  src = QString::fromAscii( urlDest.toEncoded() );
593  }
594  else if ( vlayer && vlayer->providerType() == "memory" )
595  {
596  // Refetch the source from the provider, because adding fields actually changes the source for this provider.
597  src = vlayer->dataProvider()->dataSourceUri();
598  }
599  else
600  {
601  bool handled = false;
602 
603  if ( !vlayer )
604  {
605  QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( this );
606  // Update path for subdataset
607  if ( rlayer && rlayer->providerType() == "gdal" )
608  {
609  if ( src.startsWith( "NETCDF:" ) )
610  {
611  // NETCDF:filename:variable
612  // filename can be quoted with " as it can contain colons
613  QRegExp r( "NETCDF:(.+):([^:]+)" );
614  if ( r.exactMatch( src ) )
615  {
616  QString filename = r.cap( 1 );
617  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
618  filename = filename.mid( 1, filename.length() - 2 );
619  src = "NETCDF:\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
620  handled = true;
621  }
622  }
623  else if ( src.startsWith( "HDF4_SDS:" ) )
624  {
625  // HDF4_SDS:subdataset_type:file_name:subdataset_index
626  // filename can be quoted with " as it can contain colons
627  QRegExp r( "HDF4_SDS:([^:]+):(.+):([^:]+)" );
628  if ( r.exactMatch( src ) )
629  {
630  QString filename = r.cap( 2 );
631  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
632  filename = filename.mid( 1, filename.length() - 2 );
633  src = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
634  handled = true;
635  }
636  }
637  else if ( src.startsWith( "HDF5:" ) )
638  {
639  // HDF5:file_name:subdataset
640  // filename can be quoted with " as it can contain colons
641  QRegExp r( "HDF5:(.+):([^:]+)" );
642  if ( r.exactMatch( src ) )
643  {
644  QString filename = r.cap( 1 );
645  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
646  filename = filename.mid( 1, filename.length() - 2 );
647  src = "HDF5:\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
648  handled = true;
649  }
650  }
651  else if ( src.contains( QRegExp( "^(NITF_IM|RADARSAT_2_CALIB):" ) ) )
652  {
653  // NITF_IM:0:filename
654  // RADARSAT_2_CALIB:?:filename
655  QRegExp r( "([^:]+):([^:]+):(.+)" );
656  if ( r.exactMatch( src ) )
657  {
658  src = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->writePath( r.cap( 3 ), relativeBasePath );
659  handled = true;
660  }
661  }
662  }
663  }
664 
665  if ( !handled )
666  src = QgsProject::instance()->writePath( src, relativeBasePath );
667  }
668 
669  QDomText dataSourceText = document.createTextNode( src );
670  dataSource.appendChild( dataSourceText );
671 
672  layerElement.appendChild( dataSource );
673 
674 
675  // layer name
676  QDomElement layerName = document.createElement( "layername" );
677  QDomText layerNameText = document.createTextNode( originalName() );
678  layerName.appendChild( layerNameText );
679  layerElement.appendChild( layerName );
680 
681  // layer short name
682  if ( !mShortName.isEmpty() )
683  {
684  QDomElement layerShortName = document.createElement( "shortname" );
685  QDomText layerShortNameText = document.createTextNode( mShortName );
686  layerShortName.appendChild( layerShortNameText );
687  layerElement.appendChild( layerShortName );
688  }
689 
690  // layer title
691  if ( !mTitle.isEmpty() )
692  {
693  QDomElement layerTitle = document.createElement( "title" );
694  QDomText layerTitleText = document.createTextNode( mTitle );
695  layerTitle.appendChild( layerTitleText );
696  layerElement.appendChild( layerTitle );
697  }
698 
699  // layer abstract
700  if ( !mAbstract.isEmpty() )
701  {
702  QDomElement layerAbstract = document.createElement( "abstract" );
703  QDomText layerAbstractText = document.createTextNode( mAbstract );
704  layerAbstract.appendChild( layerAbstractText );
705  layerElement.appendChild( layerAbstract );
706  }
707 
708  // layer keyword list
709  QStringList keywordStringList = keywordList().split( ',' );
710  if ( !keywordStringList.isEmpty() )
711  {
712  QDomElement layerKeywordList = document.createElement( "keywordList" );
713  for ( int i = 0; i < keywordStringList.size(); ++i )
714  {
715  QDomElement layerKeywordValue = document.createElement( "value" );
716  QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
717  layerKeywordValue.appendChild( layerKeywordText );
718  layerKeywordList.appendChild( layerKeywordValue );
719  }
720  layerElement.appendChild( layerKeywordList );
721  }
722 
723  // layer metadataUrl
724  QString aDataUrl = dataUrl();
725  if ( !aDataUrl.isEmpty() )
726  {
727  QDomElement layerDataUrl = document.createElement( "dataUrl" );
728  QDomText layerDataUrlText = document.createTextNode( aDataUrl );
729  layerDataUrl.appendChild( layerDataUrlText );
730  layerDataUrl.setAttribute( "format", dataUrlFormat() );
731  layerElement.appendChild( layerDataUrl );
732  }
733 
734  // layer legendUrl
735  QString aLegendUrl = legendUrl();
736  if ( !aLegendUrl.isEmpty() )
737  {
738  QDomElement layerLegendUrl = document.createElement( "legendUrl" );
739  QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
740  layerLegendUrl.appendChild( layerLegendUrlText );
741  layerLegendUrl.setAttribute( "format", legendUrlFormat() );
742  layerElement.appendChild( layerLegendUrl );
743  }
744 
745  // layer attribution
746  QString aAttribution = attribution();
747  if ( !aAttribution.isEmpty() )
748  {
749  QDomElement layerAttribution = document.createElement( "attribution" );
750  QDomText layerAttributionText = document.createTextNode( aAttribution );
751  layerAttribution.appendChild( layerAttributionText );
752  layerAttribution.setAttribute( "href", attributionUrl() );
753  layerElement.appendChild( layerAttribution );
754  }
755 
756  // layer metadataUrl
757  QString aMetadataUrl = metadataUrl();
758  if ( !aMetadataUrl.isEmpty() )
759  {
760  QDomElement layerMetadataUrl = document.createElement( "metadataUrl" );
761  QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
762  layerMetadataUrl.appendChild( layerMetadataUrlText );
763  layerMetadataUrl.setAttribute( "type", metadataUrlType() );
764  layerMetadataUrl.setAttribute( "format", metadataUrlFormat() );
765  layerElement.appendChild( layerMetadataUrl );
766  }
767 
768  // timestamp if supported
769  if ( timestamp() > QDateTime() )
770  {
771  QDomElement stamp = document.createElement( "timestamp" );
772  QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
773  stamp.appendChild( stampText );
774  layerElement.appendChild( stamp );
775  }
776 
777  layerElement.appendChild( layerName );
778 
779  // zorder
780  // This is no longer stored in the project file. It is superfluous since the layers
781  // are written and read in the proper order.
782 
783  // spatial reference system id
784  QDomElement mySrsElement = document.createElement( "srs" );
785  mCRS.writeXML( mySrsElement, document );
786  layerElement.appendChild( mySrsElement );
787 
788 #if 0
789  // <transparencyLevelInt>
790  QDomElement transparencyLevelIntElement = document.createElement( "transparencyLevelInt" );
791  QDomText transparencyLevelIntText = document.createTextNode( QString::number( getTransparency() ) );
792  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
793  maplayer.appendChild( transparencyLevelIntElement );
794 #endif
795 
796  // now append layer node to map layer node
797 
798  writeCustomProperties( layerElement, document );
799 
800  return writeXml( layerElement, document );
801 
802 } // bool QgsMapLayer::writeXML
803 
805 {
806  QDomDocument doc( "qgis-layer-definition" );
807  QDomElement qgiselm = doc.createElement( "qlr" );
808  doc.appendChild( qgiselm );
809  QDomElement layerselm = doc.createElement( "maplayers" );
810  Q_FOREACH ( QgsMapLayer* layer, layers )
811  {
812  QDomElement layerelm = doc.createElement( "maplayer" );
813  layer->writeLayerXML( layerelm, doc, relativeBasePath );
814  layerselm.appendChild( layerelm );
815  }
816  qgiselm.appendChild( layerselm );
817  return doc;
818 }
819 
820 QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend, const QString& relativeBasePath )
821 {
822  QList<QgsMapLayer*> layers;
823  QDomNodeList layernodes = document.elementsByTagName( "maplayer" );
824  for ( int i = 0; i < layernodes.size(); ++i )
825  {
826  QDomNode layernode = layernodes.at( i );
827  QDomElement layerElem = layernode.toElement();
828 
829  QString type = layerElem.attribute( "type" );
830  QgsDebugMsg( type );
831  QgsMapLayer *layer = nullptr;
832 
833  if ( type == "vector" )
834  {
835  layer = new QgsVectorLayer;
836  }
837  else if ( type == "raster" )
838  {
839  layer = new QgsRasterLayer;
840  }
841  else if ( type == "plugin" )
842  {
843  QString typeName = layerElem.attribute( "name" );
844  layer = QgsPluginLayerRegistry::instance()->createLayer( typeName );
845  }
846 
847  if ( !layer )
848  continue;
849 
850  bool ok = layer->readLayerXML( layerElem, relativeBasePath );
851  if ( ok )
852  {
853  layers << layer;
854  if ( addToRegistry )
855  QgsMapLayerRegistry::instance()->addMapLayer( layer, addToLegend );
856  }
857  }
858  return layers;
859 }
860 
862 {
863  QFile file( qlrfile );
864  if ( !file.open( QIODevice::ReadOnly ) )
865  {
866  QgsDebugMsg( "Can't open file" );
867  return QList<QgsMapLayer*>();
868  }
869 
870  QDomDocument doc;
871  if ( !doc.setContent( &file ) )
872  {
873  QgsDebugMsg( "Can't set content" );
874  return QList<QgsMapLayer*>();
875  }
876 
877  QFileInfo fileinfo( file );
878  QDir::setCurrent( fileinfo.absoluteDir().path() );
879  return QgsMapLayer::fromLayerDefinition( doc );
880 }
881 
882 
883 bool QgsMapLayer::writeXml( QDomNode & layer_node, QDomDocument & document )
884 {
885  Q_UNUSED( layer_node );
886  Q_UNUSED( document );
887  // NOP by default; children will over-ride with behavior specific to them
888 
889  return true;
890 } // void QgsMapLayer::writeXml
891 
892 
893 void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
894 {
895  mCustomProperties.readXml( layerNode, keyStartsWith );
896 }
897 
899 {
900  mCustomProperties.writeXml( layerNode, doc );
901 }
902 
903 void QgsMapLayer::readStyleManager( const QDomNode& layerNode )
904 {
905  QDomElement styleMgrElem = layerNode.firstChildElement( "map-layer-style-manager" );
906  if ( !styleMgrElem.isNull() )
907  mStyleManager->readXml( styleMgrElem );
908  else
909  mStyleManager->reset();
910 }
911 
913 {
914  if ( mStyleManager )
915  {
916  QDomElement styleMgrElem = doc.createElement( "map-layer-style-manager" );
917  mStyleManager->writeXml( styleMgrElem );
918  layerNode.appendChild( styleMgrElem );
919  }
920 }
921 
922 
923 
924 
926 {
927  return mValid;
928 }
929 
930 
932 {
933  QgsDebugMsg( "called" );
934  // TODO: emit a signal - it will be used to update legend
935 }
936 
937 
939 {
940  return QString();
941 }
942 
944 {
945  return QString();
946 }
947 
948 #if 0
949 void QgsMapLayer::connectNotify( const char * signal )
950 {
951  Q_UNUSED( signal );
952  QgsDebugMsgLevel( "QgsMapLayer connected to " + QString( signal ), 3 );
953 } // QgsMapLayer::connectNotify
954 #endif
955 
956 bool QgsMapLayer::isInScaleRange( double scale ) const
957 {
958  return !mScaleBasedVisibility || ( mMinScale * QGis::SCALE_PRECISION < scale && scale < mMaxScale );
959 }
960 
961 void QgsMapLayer::toggleScaleBasedVisibility( bool theVisibilityFlag )
962 {
963  setScaleBasedVisibility( theVisibilityFlag );
964 }
965 
967 {
968  return mScaleBasedVisibility;
969 }
970 
971 void QgsMapLayer::setMinimumScale( double theMinScale )
972 {
973  mMinScale = theMinScale;
974 }
975 
977 {
978  return mMinScale;
979 }
980 
981 
982 void QgsMapLayer::setMaximumScale( double theMaxScale )
983 {
984  mMaxScale = theMaxScale;
985 }
986 
987 void QgsMapLayer::setScaleBasedVisibility( const bool enabled )
988 {
989  mScaleBasedVisibility = enabled;
990 }
991 
993 {
994  return mMaxScale;
995 }
996 
998 {
999  return QStringList(); // Empty
1000 }
1001 
1003 {
1004  Q_UNUSED( layers );
1005  // NOOP
1006 }
1007 
1009 {
1010  Q_UNUSED( name );
1011  Q_UNUSED( vis );
1012  // NOOP
1013 }
1014 
1016 {
1017  return mCRS;
1018 }
1019 
1020 void QgsMapLayer::setCrs( const QgsCoordinateReferenceSystem& srs, bool emitSignal )
1021 {
1022  mCRS = srs;
1023 
1024  if ( !mCRS.isValid() )
1025  {
1026  mCRS.setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
1027  mCRS.validate();
1028  }
1029 
1030  if ( emitSignal )
1031  emit layerCrsChanged();
1032 }
1033 
1035 {
1036  // Capitalise the first letter of the layer name if requested
1037  QSettings settings;
1038  bool capitaliseLayerName =
1039  settings.value( "/qgis/capitaliseLayerName", QVariant( false ) ).toBool();
1040 
1041  QString layerName( name );
1042 
1043  if ( capitaliseLayerName && !layerName.isEmpty() )
1044  layerName = layerName.at( 0 ).toUpper() + layerName.mid( 1 );
1045 
1046  return layerName;
1047 }
1048 
1050 {
1051  QString myURI = publicSource();
1052 
1053  // if file is using the VSIFILE mechanism, remove the prefix
1054  if ( myURI.startsWith( "/vsigzip/", Qt::CaseInsensitive ) )
1055  {
1056  myURI.remove( 0, 9 );
1057  }
1058  else if ( myURI.startsWith( "/vsizip/", Qt::CaseInsensitive ) &&
1059  myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
1060  {
1061  // ideally we should look for .qml file inside zip file
1062  myURI.remove( 0, 8 );
1063  }
1064  else if ( myURI.startsWith( "/vsitar/", Qt::CaseInsensitive ) &&
1065  ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) ||
1066  myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) ||
1067  myURI.endsWith( ".tgz", Qt::CaseInsensitive ) ) )
1068  {
1069  // ideally we should look for .qml file inside tar file
1070  myURI.remove( 0, 8 );
1071  }
1072 
1073  QFileInfo myFileInfo( myURI );
1074  QString key;
1075 
1076  if ( myFileInfo.exists() )
1077  {
1078  // if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
1079  if ( myURI.endsWith( ".gz", Qt::CaseInsensitive ) )
1080  myURI.chop( 3 );
1081  else if ( myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
1082  myURI.chop( 4 );
1083  else if ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) )
1084  myURI.chop( 4 );
1085  else if ( myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) )
1086  myURI.chop( 7 );
1087  else if ( myURI.endsWith( ".tgz", Qt::CaseInsensitive ) )
1088  myURI.chop( 4 );
1089  myFileInfo.setFile( myURI );
1090  // get the file name for our .qml style file
1091  key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
1092  }
1093  else
1094  {
1095  key = publicSource();
1096  }
1097 
1098  return key;
1099 }
1100 
1102 {
1103  return loadNamedStyle( styleURI(), theResultFlag );
1104 }
1105 
1106 bool QgsMapLayer::loadNamedStyleFromDb( const QString &db, const QString &theURI, QString &qml )
1107 {
1108  QgsDebugMsg( QString( "db = %1 uri = %2" ).arg( db, theURI ) );
1109 
1110  bool theResultFlag = false;
1111 
1112  // read from database
1113  sqlite3 *myDatabase;
1114  sqlite3_stmt *myPreparedStatement;
1115  const char *myTail;
1116  int myResult;
1117 
1118  QgsDebugMsg( QString( "Trying to load style for \"%1\" from \"%2\"" ).arg( theURI, db ) );
1119 
1120  if ( db.isEmpty() || !QFile( db ).exists() )
1121  return false;
1122 
1123  myResult = sqlite3_open_v2( db.toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, nullptr );
1124  if ( myResult != SQLITE_OK )
1125  {
1126  return false;
1127  }
1128 
1129  QString mySql = "select qml from tbl_styles where style=?";
1130  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1131  if ( myResult == SQLITE_OK )
1132  {
1133  QByteArray param = theURI.toUtf8();
1134 
1135  if ( sqlite3_bind_text( myPreparedStatement, 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
1136  sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1137  {
1138  qml = QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( myPreparedStatement, 0 ) ) );
1139  theResultFlag = true;
1140  }
1141 
1142  sqlite3_finalize( myPreparedStatement );
1143  }
1144 
1145  sqlite3_close( myDatabase );
1146 
1147  return theResultFlag;
1148 }
1149 
1150 
1151 QString QgsMapLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
1152 {
1153  QgsDebugMsg( QString( "uri = %1 myURI = %2" ).arg( theURI, publicSource() ) );
1154 
1155  theResultFlag = false;
1156 
1157  QDomDocument myDocument( "qgis" );
1158 
1159  // location of problem associated with errorMsg
1160  int line, column;
1161  QString myErrorMessage;
1162 
1163  QFile myFile( theURI );
1164  if ( myFile.open( QFile::ReadOnly ) )
1165  {
1166  // read file
1167  theResultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
1168  if ( !theResultFlag )
1169  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1170  myFile.close();
1171  }
1172  else
1173  {
1174  QFileInfo project( QgsProject::instance()->fileName() );
1175  QgsDebugMsg( QString( "project fileName: %1" ).arg( project.absoluteFilePath() ) );
1176 
1177  QString qml;
1178  if ( loadNamedStyleFromDb( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ), theURI, qml ) ||
1179  ( project.exists() && loadNamedStyleFromDb( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), theURI, qml ) ) ||
1180  loadNamedStyleFromDb( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( "resources/qgis.qmldb" ), theURI, qml ) )
1181  {
1182  theResultFlag = myDocument.setContent( qml, &myErrorMessage, &line, &column );
1183  if ( !theResultFlag )
1184  {
1185  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1186  }
1187  }
1188  else
1189  {
1190  myErrorMessage = tr( "Style not found in database" );
1191  }
1192  }
1193 
1194  if ( !theResultFlag )
1195  {
1196  return myErrorMessage;
1197  }
1198 
1199  theResultFlag = importNamedStyle( myDocument, myErrorMessage );
1200  if ( !theResultFlag )
1201  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( theURI, myErrorMessage );
1202 
1203  return myErrorMessage;
1204 }
1205 
1206 
1207 bool QgsMapLayer::importNamedStyle( QDomDocument& myDocument, QString& myErrorMessage )
1208 {
1209  QDomElement myRoot = myDocument.firstChildElement( "qgis" );
1210  if ( myRoot.isNull() )
1211  {
1212  myErrorMessage = tr( "Root <qgis> element could not be found" );
1213  return false;
1214  }
1215 
1216  // get style file version string, if any
1217  QgsProjectVersion fileVersion( myRoot.attribute( "version" ) );
1218  QgsProjectVersion thisVersion( QGis::QGIS_VERSION );
1219 
1220  if ( thisVersion > fileVersion )
1221  {
1222  QgsProjectFileTransform styleFile( myDocument, fileVersion );
1223  styleFile.updateRevision( thisVersion );
1224  }
1225 
1226  //Test for matching geometry type on vector layers when applying, if geometry type is given in the style
1227  if ( type() == QgsMapLayer::VectorLayer && !myRoot.firstChildElement( "layerGeometryType" ).isNull() )
1228  {
1229  QgsVectorLayer *vl = static_cast<QgsVectorLayer*>( this );
1230  int importLayerGeometryType = myRoot.firstChildElement( "layerGeometryType" ).text().toInt();
1231  if ( vl->geometryType() != importLayerGeometryType )
1232  {
1233  myErrorMessage = tr( "Cannot apply style to layer with a different geometry type" );
1234  return false;
1235  }
1236  }
1237 
1238  // use scale dependent visibility flag
1239  setScaleBasedVisibility( myRoot.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
1240  setMinimumScale( myRoot.attribute( "minimumScale" ).toDouble() );
1241  setMaximumScale( myRoot.attribute( "maximumScale" ).toDouble() );
1242 
1243 #if 0
1244  //read transparency level
1245  QDomNode transparencyNode = myRoot.namedItem( "transparencyLevelInt" );
1246  if ( ! transparencyNode.isNull() )
1247  {
1248  // set transparency level only if it's in project
1249  // (otherwise it sets the layer transparent)
1250  QDomElement myElement = transparencyNode.toElement();
1251  setTransparency( myElement.text().toInt() );
1252  }
1253 #endif
1254 
1255  return readSymbology( myRoot, myErrorMessage );
1256 }
1257 
1259 {
1260  QDomImplementation DomImplementation;
1261  QDomDocumentType documentType = DomImplementation.createDocumentType( "qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
1262  QDomDocument myDocument( documentType );
1263 
1264  QDomElement myRootNode = myDocument.createElement( "qgis" );
1265  myRootNode.setAttribute( "version", QGis::QGIS_VERSION );
1266  myDocument.appendChild( myRootNode );
1267 
1268  myRootNode.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
1269  myRootNode.setAttribute( "minimumScale", QString::number( minimumScale() ) );
1270  myRootNode.setAttribute( "maximumScale", QString::number( maximumScale() ) );
1271 
1272 #if 0
1273  // <transparencyLevelInt>
1274  QDomElement transparencyLevelIntElement = myDocument.createElement( "transparencyLevelInt" );
1275  QDomText transparencyLevelIntText = myDocument.createTextNode( QString::number( getTransparency() ) );
1276  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
1277  myRootNode.appendChild( transparencyLevelIntElement );
1278 #endif
1279 
1280  if ( !writeSymbology( myRootNode, myDocument, errorMsg ) )
1281  {
1282  errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1283  return;
1284  }
1285 
1286  /*
1287  * Check to see if the layer is vector - in which case we should also export its geometryType
1288  * to avoid eventually pasting to a layer with a different geometry
1289  */
1290  if ( type() == QgsMapLayer::VectorLayer )
1291  {
1292  //Getting the selectionLayer geometry
1293  QgsVectorLayer *vl = static_cast<QgsVectorLayer*>( this );
1294  QString geoType = QString::number( vl->geometryType() );
1295 
1296  //Adding geometryinformation
1297  QDomElement layerGeometryType = myDocument.createElement( "layerGeometryType" );
1298  QDomText type = myDocument.createTextNode( geoType );
1299 
1300  layerGeometryType.appendChild( type );
1301  myRootNode.appendChild( layerGeometryType );
1302  }
1303 
1304  doc = myDocument;
1305 }
1306 
1308 {
1309  return saveNamedStyle( styleURI(), theResultFlag );
1310 }
1311 
1312 QString QgsMapLayer::saveNamedStyle( const QString &theURI, bool &theResultFlag )
1313 {
1314  QString myErrorMessage;
1315  QDomDocument myDocument;
1316  exportNamedStyle( myDocument, myErrorMessage );
1317 
1318  // check if the uri is a file or ends with .qml,
1319  // which indicates that it should become one
1320  // everything else goes to the database
1321  QString filename;
1322 
1323  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1324  if ( vlayer && vlayer->providerType() == "ogr" )
1325  {
1326  QStringList theURIParts = theURI.split( '|' );
1327  filename = theURIParts[0];
1328  }
1329  else if ( vlayer && vlayer->providerType() == "gpx" )
1330  {
1331  QStringList theURIParts = theURI.split( '?' );
1332  filename = theURIParts[0];
1333  }
1334  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
1335  {
1336  filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1337  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1338  if ( filename.isEmpty() )
1339  filename = theURI;
1340  }
1341  else
1342  {
1343  filename = theURI;
1344  }
1345 
1346  QFileInfo myFileInfo( filename );
1347  if ( myFileInfo.exists() || filename.endsWith( ".qml", Qt::CaseInsensitive ) )
1348  {
1349  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1350  if ( !myDirInfo.isWritable() )
1351  {
1352  return tr( "The directory containing your dataset needs to be writable!" );
1353  }
1354 
1355  // now construct the file name for our .qml style file
1356  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
1357 
1358  QFile myFile( myFileName );
1359  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1360  {
1361  QTextStream myFileStream( &myFile );
1362  // save as utf-8 with 2 spaces for indents
1363  myDocument.save( myFileStream, 2 );
1364  myFile.close();
1365  theResultFlag = true;
1366  return tr( "Created default style file as %1" ).arg( myFileName );
1367  }
1368  else
1369  {
1370  theResultFlag = false;
1371  return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1372  }
1373  }
1374  else
1375  {
1376  QString qml = myDocument.toString();
1377 
1378  // read from database
1379  sqlite3 *myDatabase;
1380  sqlite3_stmt *myPreparedStatement;
1381  const char *myTail;
1382  int myResult;
1383 
1384  myResult = sqlite3_open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ).toUtf8().data(), &myDatabase );
1385  if ( myResult != SQLITE_OK )
1386  {
1387  return tr( "User database could not be opened." );
1388  }
1389 
1390  QByteArray param0 = theURI.toUtf8();
1391  QByteArray param1 = qml.toUtf8();
1392 
1393  QString mySql = "create table if not exists tbl_styles(style varchar primary key,qml varchar)";
1394  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1395  if ( myResult == SQLITE_OK )
1396  {
1397  if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
1398  {
1399  sqlite3_finalize( myPreparedStatement );
1400  sqlite3_close( myDatabase );
1401  theResultFlag = false;
1402  return tr( "The style table could not be created." );
1403  }
1404  }
1405 
1406  sqlite3_finalize( myPreparedStatement );
1407 
1408  mySql = "insert into tbl_styles(style,qml) values (?,?)";
1409  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1410  if ( myResult == SQLITE_OK )
1411  {
1412  if ( sqlite3_bind_text( myPreparedStatement, 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1413  sqlite3_bind_text( myPreparedStatement, 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1414  sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1415  {
1416  theResultFlag = true;
1417  myErrorMessage = tr( "The style %1 was saved to database" ).arg( theURI );
1418  }
1419  }
1420 
1421  sqlite3_finalize( myPreparedStatement );
1422 
1423  if ( !theResultFlag )
1424  {
1425  QString mySql = "update tbl_styles set qml=? where style=?";
1426  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1427  if ( myResult == SQLITE_OK )
1428  {
1429  if ( sqlite3_bind_text( myPreparedStatement, 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1430  sqlite3_bind_text( myPreparedStatement, 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1431  sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1432  {
1433  theResultFlag = true;
1434  myErrorMessage = tr( "The style %1 was updated in the database." ).arg( theURI );
1435  }
1436  else
1437  {
1438  theResultFlag = false;
1439  myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( theURI );
1440  }
1441  }
1442  else
1443  {
1444  theResultFlag = false;
1445  myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( theURI );
1446  }
1447 
1448  sqlite3_finalize( myPreparedStatement );
1449  }
1450 
1451  sqlite3_close( myDatabase );
1452  }
1453 
1454  return myErrorMessage;
1455 }
1456 
1458 {
1459  QDomDocument myDocument = QDomDocument();
1460 
1461  QDomNode header = myDocument.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" );
1462  myDocument.appendChild( header );
1463 
1464  // Create the root element
1465  QDomElement root = myDocument.createElementNS( "http://www.opengis.net/sld", "StyledLayerDescriptor" );
1466  root.setAttribute( "version", "1.1.0" );
1467  root.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" );
1468  root.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" );
1469  root.setAttribute( "xmlns:se", "http://www.opengis.net/se" );
1470  root.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
1471  root.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
1472  myDocument.appendChild( root );
1473 
1474  // Create the NamedLayer element
1475  QDomElement namedLayerNode = myDocument.createElement( "NamedLayer" );
1476  root.appendChild( namedLayerNode );
1477 
1478  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1479  if ( !vlayer )
1480  {
1481  errorMsg = tr( "Could not save symbology because:\n%1" )
1482  .arg( "Non-vector layers not supported yet" );
1483  return;
1484  }
1485 
1486  QgsStringMap props;
1487  if ( hasScaleBasedVisibility() )
1488  {
1489  props[ "scaleMinDenom" ] = QString::number( mMinScale );
1490  props[ "scaleMaxDenom" ] = QString::number( mMaxScale );
1491  }
1492  if ( !vlayer->writeSld( namedLayerNode, myDocument, errorMsg, props ) )
1493  {
1494  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1495  return;
1496  }
1497 
1498  doc = myDocument;
1499 }
1500 
1501 QString QgsMapLayer::saveSldStyle( const QString &theURI, bool &theResultFlag )
1502 {
1503  QString errorMsg;
1504  QDomDocument myDocument;
1505  exportSldStyle( myDocument, errorMsg );
1506  if ( !errorMsg.isNull() )
1507  {
1508  theResultFlag = false;
1509  return errorMsg;
1510  }
1511  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1512 
1513  // check if the uri is a file or ends with .sld,
1514  // which indicates that it should become one
1515  QString filename;
1516  if ( vlayer->providerType() == "ogr" )
1517  {
1518  QStringList theURIParts = theURI.split( '|' );
1519  filename = theURIParts[0];
1520  }
1521  else if ( vlayer->providerType() == "gpx" )
1522  {
1523  QStringList theURIParts = theURI.split( '?' );
1524  filename = theURIParts[0];
1525  }
1526  else if ( vlayer->providerType() == "delimitedtext" )
1527  {
1528  filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1529  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1530  if ( filename.isEmpty() )
1531  filename = theURI;
1532  }
1533  else
1534  {
1535  filename = theURI;
1536  }
1537 
1538  QFileInfo myFileInfo( filename );
1539  if ( myFileInfo.exists() || filename.endsWith( ".sld", Qt::CaseInsensitive ) )
1540  {
1541  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1542  if ( !myDirInfo.isWritable() )
1543  {
1544  return tr( "The directory containing your dataset needs to be writable!" );
1545  }
1546 
1547  // now construct the file name for our .sld style file
1548  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".sld";
1549 
1550  QFile myFile( myFileName );
1551  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1552  {
1553  QTextStream myFileStream( &myFile );
1554  // save as utf-8 with 2 spaces for indents
1555  myDocument.save( myFileStream, 2 );
1556  myFile.close();
1557  theResultFlag = true;
1558  return tr( "Created default style file as %1" ).arg( myFileName );
1559  }
1560  }
1561 
1562  theResultFlag = false;
1563  return tr( "ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1564 }
1565 
1566 QString QgsMapLayer::loadSldStyle( const QString &theURI, bool &theResultFlag )
1567 {
1568  QgsDebugMsg( "Entered." );
1569 
1570  theResultFlag = false;
1571 
1572  QDomDocument myDocument;
1573 
1574  // location of problem associated with errorMsg
1575  int line, column;
1576  QString myErrorMessage;
1577 
1578  QFile myFile( theURI );
1579  if ( myFile.open( QFile::ReadOnly ) )
1580  {
1581  // read file
1582  theResultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
1583  if ( !theResultFlag )
1584  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1585  myFile.close();
1586  }
1587  else
1588  {
1589  myErrorMessage = tr( "Unable to open file %1" ).arg( theURI );
1590  }
1591 
1592  if ( !theResultFlag )
1593  {
1594  return myErrorMessage;
1595  }
1596 
1597  // check for root SLD element
1598  QDomElement myRoot = myDocument.firstChildElement( "StyledLayerDescriptor" );
1599  if ( myRoot.isNull() )
1600  {
1601  myErrorMessage = QString( "Error: StyledLayerDescriptor element not found in %1" ).arg( theURI );
1602  theResultFlag = false;
1603  return myErrorMessage;
1604  }
1605 
1606  // now get the style node out and pass it over to the layer
1607  // to deserialise...
1608  QDomElement namedLayerElem = myRoot.firstChildElement( "NamedLayer" );
1609  if ( namedLayerElem.isNull() )
1610  {
1611  myErrorMessage = QLatin1String( "Info: NamedLayer element not found." );
1612  theResultFlag = false;
1613  return myErrorMessage;
1614  }
1615 
1616  QString errorMsg;
1617  theResultFlag = readSld( namedLayerElem, errorMsg );
1618  if ( !theResultFlag )
1619  {
1620  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( theURI, errorMsg );
1621  return myErrorMessage;
1622  }
1623 
1624  return "";
1625 }
1626 
1627 bool QgsMapLayer::readStyle( const QDomNode& node, QString& errorMessage )
1628 {
1629  Q_UNUSED( node );
1630  Q_UNUSED( errorMessage );
1631  return false;
1632 }
1633 
1634 bool QgsMapLayer::writeStyle( QDomNode& node, QDomDocument& doc, QString& errorMessage ) const
1635 {
1636  Q_UNUSED( node );
1637  Q_UNUSED( doc );
1638  Q_UNUSED( errorMessage );
1639  return false;
1640 }
1641 
1642 
1644 {
1645  return &mUndoStack;
1646 }
1647 
1649 {
1650  return &mUndoStackStyles;
1651 }
1652 
1653 
1654 void QgsMapLayer::setCustomProperty( const QString& key, const QVariant& value )
1655 {
1656  mCustomProperties.setValue( key, value );
1657 }
1658 
1659 QVariant QgsMapLayer::customProperty( const QString& value, const QVariant& defaultValue ) const
1660 {
1661  return mCustomProperties.value( value, defaultValue );
1662 }
1663 
1665 {
1666  mCustomProperties.remove( key );
1667 }
1668 
1669 
1670 
1672 {
1673  return false;
1674 }
1675 
1676 void QgsMapLayer::setValid( bool valid )
1677 {
1678  mValid = valid;
1679 }
1680 
1682 {
1683  emit repaintRequested();
1684 }
1685 
1687 {
1688  if ( legend == mLegend )
1689  return;
1690 
1691  delete mLegend;
1692  mLegend = legend;
1693 
1694  if ( mLegend )
1695  connect( mLegend, SIGNAL( itemsChanged() ), this, SIGNAL( legendChanged() ) );
1696 
1697  emit legendChanged();
1698 }
1699 
1701 {
1702  return mLegend;
1703 }
1704 
1706 {
1707  return mStyleManager;
1708 }
1709 
1711 {
1712  emit repaintRequested();
1713 }
1714 
1716 {
1717  emit repaintRequested();
1718 }
1719 
1721 {
1722  return QString();
1723 }
1724 
1726 {
1727  emit styleChanged();
1728 }
1729 
1731 {
1732  mExtent = r;
1733 }
QString attributionUrl() const
Get the attribution URL of the layer used by QGIS Server in GetCapabilities request Attribution indic...
Definition: qgsmaplayer.h:200
QString mShortName
Definition: qgsmaplayer.h:780
virtual QStringList subLayers() const
Returns the sublayers of this layer (Useful for providers that manage their own layers, such as WMS)
QString fromAscii(const char *str, int size)
QString toString(Qt::DateFormat format) const
virtual QString saveNamedStyle(const QString &theURI, bool &theResultFlag)
Save the properties of this layer as a named style (either as a .qml file on disk or as a record in t...
QString dataUrlFormat() const
Get the DataUrl format of the layer used by QGIS Server in GetCapabilities request DataUrl is a a lin...
Definition: qgsmaplayer.h:174
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
QString cap(int nth) const
QDomProcessingInstruction createProcessingInstruction(const QString &target, const QString &data)
QString path() const
virtual QString metadata()
Obtain Metadata for this layer.
virtual void drawLabels(QgsRenderContext &rendererContext)
Draw labels.
virtual QString loadSldStyle(const QString &theURI, bool &theResultFlag)
QString mAttributionUrl
Definition: qgsmaplayer.h:793
static QgsAuthManager * instance()
Enforce singleton pattern.
QString mKeywordList
Definition: qgsmaplayer.h:785
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith="")
Read custom properties from project file.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user&#39;s home dir.
Q_DECL_DEPRECATED void layerNameChanged()
Emit a signal that the layer name has been changed.
QDomNode appendChild(const QDomNode &newChild)
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from XML.
void reset()
Reset the style manager to a basic state - with one default style which is set as current...
QgsMapLayerLegend * legend() const
Can be null.
virtual ~QgsMapLayer()
Destructor.
Definition: qgsmaplayer.cpp:93
QString mDataUrlFormat
Definition: qgsmaplayer.h:789
QString attribute(const QString &name, const QString &defValue) const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void validate()
Perform some validation on this CRS.
QString toString(int indent) const
QString dataUrl() const
Get the DataUrl of the layer used by QGIS Server in GetCapabilities request DataUrl is a a link to th...
Definition: qgsmaplayer.h:162
static QString removePassword(const QString &aUri)
Removes password element from uris.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
virtual Q_DECL_DEPRECATED QString lastError()
QList< QPair< QString, QString > > queryItems() const
void setFile(const QString &file)
bool updateRevision(const QgsProjectVersion &version)
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
virtual bool readSymbology(const QDomNode &node, QString &errorMessage)=0
Read the symbology for the current layer from the Dom node supplied.
void setDatabase(const QString &database)
Set database.
QString mLegendUrlFormat
Definition: qgsmaplayer.h:802
const T & at(int i) const
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
static QList< QgsMapLayer * > fromLayerDefinition(QDomDocument &document, bool addToRegistry=false, bool addToLegend=false, const QString &relativeBasePath=QString())
Creates a new layer from a layer defininition document.
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc)
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Return value for the given key. If the key is not stored, default value will be used.
void writeXml(QDomNode &parentNode, QDomDocument &doc) const
Write store contents to XML.
QString join(const QString &separator) const
int length() const
bool exists() const
QString & remove(int position, int n)
static CUSTOM_CRS_VALIDATION customSrsValidation()
Gets custom function.
virtual QDateTime timestamp() const
Time stamp of data source in the moment when data/metadata were loaded by provider.
Definition: qgsmaplayer.h:651
QDomElement createElementNS(const QString &nsURI, const QString &qName)
virtual QString saveDefaultStyle(bool &theResultFlag)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
bool readLayerXML(const QDomElement &layerElement, const QString &relativeBasePath=QString())
Sets state from Dom document.
void chop(int n)
double toDouble(bool *ok) const
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayer(QgsMapLayer::LayerType type=VectorLayer, const QString &lyrname=QString::null, const QString &source=QString::null)
Constructor.
Definition: qgsmaplayer.cpp:54
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:99
QChar separator()
QString tr(const char *sourceText, const char *disambiguation, int n)
void remove(const QString &key)
Remove a key (entry) from the store.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:774
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
virtual bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage) const =0
Write the symbology for the layer into the docment provided.
int size() const
bool isNull() const
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
static void setCustomSrsValidation(CUSTOM_CRS_VALIDATION f)
Sets custom function to force valid CRS QGIS uses implementation in QgisGui::customSrsValidation.
virtual bool draw(QgsRenderContext &rendererContext)
This is the method that does the actual work of drawing the layer onto a paint device.
QgsMapLayerStyleManager * styleManager() const
Get access to the layer&#39;s style manager.
QString port() const
Returns the port.
static QString capitaliseLayerName(const QString &name)
A convenience function to (un)capitalise the layer name.
QDomElement toElement() const
void setPath(const QString &path)
int indexIn(const QString &str, int offset, CaretMode caretMode) const
QgsRectangle mExtent
Extent of the layer.
Definition: qgsmaplayer.h:765
static QDomDocument asLayerDefinition(const QList< QgsMapLayer *> &layers, const QString &relativeBasePath=QString())
Returns the given layer as a layer definition document Layer definitions store the data source as wel...
QString mMetadataUrl
MetadataUrl of the layer.
Definition: qgsmaplayer.h:796
QString password() const
Returns the password.
QString metadataUrlFormat() const
Get the metadata format of the layer used by QGIS Server in GetCapabilities request MetadataUrlType i...
Definition: qgsmaplayer.h:238
void setValidationHint(const QString &html)
Set user hint for validation.
QString number(int n, int base)
QString fromUtf8(const char *str, int size)
void setValue(const QString &key, const QVariant &value)
Add an entry to the store. If the entry with the keys exists already, it will be overwritten.
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
void layerCrsChanged()
Emit a signal that layer&#39;s CRS has been reset.
void readStyleManager(const QDomNode &layerNode)
Read style manager&#39;s configuration (if any).
QString text() const
virtual bool loadNamedStyleFromDb(const QString &db, const QString &theURI, QString &qml)
virtual bool writeXml(QDomNode &layer_node, QDomDocument &document)
Called by writeLayerXML(), used by children to write state specific to them to project files...
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
QString originalName() const
Get the original name of the layer.
Definition: qgsmaplayer.h:104
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
Q_DECL_DEPRECATED void setCacheImage(QImage *)
LayerType
Layers enum defining the types of layers that can be added to a map.
Definition: qgsmaplayer.h:57
QString database() const
Returns the database.
bool readXML(const QDomNode &theNode)
Restores state from the given Dom node.
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer&#39;s spatial reference system.
void setAttribute(const QString &name, const QString &value)
void nameChanged()
Emitted when the name has been changed.
A class to describe the version of a project.
QString providerType() const
[ data provider interface ] Which provider is being used for this Raster Layer?
int toInt(bool *ok, int base) const
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
void readXml(const QDomElement &mgrElement)
Read configuration (for project loading)
bool isEmpty() const
QDomNodeList elementsByTagName(const QString &tagname) const
QString keywordList() const
Get the keyword list of the layer used by QGIS Server in GetCapabilities request. ...
Definition: qgsmaplayer.h:148
QString absoluteFilePath() const
bool isEmpty() const
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Get the data source specification.
QString mDataUrl
DataUrl of the layer.
Definition: qgsmaplayer.h:788
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
void setScheme(const QString &scheme)
void triggerRepaint()
Will advice the map canvas (and any other interested party) that this layer requires to be repainted...
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
virtual bool isEditable() const
True if the layer can be edited.
QString path() const
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SSLmode sslmode=SSLprefer, const QString &authConfigId=QString())
Set all connection related members at once.
QDir absoluteDir() const
QString legendUrl() const
Definition: qgsmaplayer.h:530
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
bool setCurrent(const QString &path)
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example...
virtual Q_DECL_DEPRECATED QString lastErrorTitle()
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QString uri(bool expandAuthConfig=true) const
return complete uri
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg)
Import the properties of this layer from a QDomDocument.
virtual bool readStyle(const QDomNode &node, QString &errorMessage)
Read the style for the current layer from the Dom node supplied.
virtual QString saveSldStyle(const QString &theURI, bool &theResultFlag)
double minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
bool isValid()
Return the status of the layer.
double maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:768
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
static QList< QgsMapLayer * > fromLayerDefinitionFile(const QString &qlrfile)
void setName(const QString &name)
Set the display name of the layer.
static QString QGIS_VERSION
Definition: qgis.h:46
QString mTitle
Definition: qgsmaplayer.h:781
virtual bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
Write just the style information for the layer into the document.
virtual bool readSld(const QDomNode &node, QString &errorMessage)
Definition: qgsmaplayer.h:481
QString legendUrlFormat() const
Definition: qgsmaplayer.h:532
QString toLocalFile() const
QString mMetadataUrlFormat
Definition: qgsmaplayer.h:798
QDomText createTextNode(const QString &value)
void setMinimumScale(double theMinScale)
Sets the minimum scale denominator at which the layer will be visible.
virtual void connectNotify(const char *signal)
virtual void setSubLayerVisibility(const QString &name, bool vis)
Set the visibility of the given sublayer name.
bool exists() const
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
static QString pkgDataPath()
Returns the common root path of all application data directories.
QDomNode namedItem(const QString &name) const
struct sqlite3 sqlite3
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QString username() const
Returns the username.
QByteArray encodedUri() const
return complete encoded uri (generic mode)
QString mAttribution
Attribution of the layer.
Definition: qgsmaplayer.h:792
QString mAbstract
Description of the layer.
Definition: qgsmaplayer.h:784
virtual void close()
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager&#39;s configuration (if exists).
void blendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when the blend mode is changed, through QgsMapLayer::setBlendMode() ...
bool isNull() const
void setMaximumScale(double theMaxScale)
Sets the maximum scale denominator at which the layer will be visible.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as named style in a QDomDocument.
QString & replace(int position, int n, QChar after)
bool writeLayerXML(QDomElement &layerElement, QDomDocument &document, const QString &relativeBasePath=QString())
Stores state in Dom node.
QVariant value(const QString &key, const QVariant &defaultValue) const
Contains information about the context of a rendering operation.
QString name() const
Get the display name of the layer.
QDateTime currentDateTime()
void save(QTextStream &str, int indent) const
QDomNode firstChild() const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QString mid(int position, int n) const
Q_DECL_DEPRECATED void clearCacheImage()
Clear cached image.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:771
virtual QString loadDefaultStyle(bool &theResultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString source() const
Returns the source for the layer.
T takeFirst()
QChar toUpper() const
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
bool setMasterPassword(bool verify=false)
Main call to initially set or continually check master password is set.
virtual void invalidTransformInput()
Event handler for when a coordinate transform fails due to bad vertex error.
QString host() const
Returns the host.
QString readPath(QString filename, const QString &relativeBasePath=QString()) const
Turn filename read from the project file to an absolute path.
void repaintRequested()
By emitting this signal the layer tells that either appearance or content have been changed and any v...
const QChar at(int position) const
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
QDomElement firstChildElement(const QString &tagName) const
virtual bool readXml(const QDomNode &layer_node)
Called by readLayerXML(), used by children to read state specific to them from project files...
QString mLegendUrl
WMS legend.
Definition: qgsmaplayer.h:801
Class for storing a coordinate reference system (CRS)
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
QString absoluteFilePath(const QString &fileName) const
void legendChanged()
Signal emitted when legend of the layer has changed.
int length() const
bool toBool() const
char * data()
QString left(int n) const
void setQueryItems(const QList< QPair< QString, QString > > &query)
QString completeBaseName() const
Q_DECL_DEPRECATED void setLayerName(const QString &name)
Set the display name of the layer.
QString metadataUrl() const
Get the metadata URL of the layer used by QGIS Server in GetCapabilities request MetadataUrl is a a l...
Definition: qgsmaplayer.h:214
virtual QString loadNamedStyle(const QString &theURI, bool &theResultFlag)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
QUndoStack * undoStackStyles()
Return pointer to layer&#39;s style undo stack.
static QgsPluginLayerRegistry * instance()
Means of accessing canonical single instance.
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
QUndoStack * undoStack()
Return pointer to layer&#39;s undo stack.
int size() const
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
QgsVectorDataProvider * dataProvider()
Returns the data provider.
QString providerType() const
Return the provider type for this layer.
QgsMapLayer * addMapLayer(QgsMapLayer *theMapLayer, bool addToLegend=true, bool takeOwnership=true)
Add a layer to the map of loaded layers.
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
Stores state to the given Dom node in the given document.
QDomElement createElement(const QString &tagName)
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual QString styleURI()
Retrieve the style URI for this layer (either as a .qml file on disk or as a record in the users styl...
Management of styles for use with one map layer.
QDomDocumentType createDocumentType(const QString &qName, const QString &publicId, const QString &systemId)
virtual QgsRectangle extent()
Return the extent of the layer.
Represents a vector layer which manages a vector based data sets.
virtual void setLayerOrder(const QStringList &layers)
Reorders the previously selected sublayers of this layer from bottom to top (Useful for providers tha...
bool exactMatch(const QString &str) const
void writeXml(QDomElement &mgrElement) const
Write configuration (for project saving)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
static double SCALE_PRECISION
Fudge factor used to compare two scales.
Definition: qgis.h:257
QString mLayerOrigName
Original name of the layer.
Definition: qgsmaplayer.h:778
void setValid(bool valid)
Set whether layer is valid or not - should be used in constructor.
QString baseName() const
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:52
QString mMetadataUrlType
Definition: qgsmaplayer.h:797
QgsPluginLayer * createLayer(const QString &typeName, const QString &uri=QString())
Return new layer if corresponding plugin has been found, else return NULL.
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as SLD style in a QDomDocument.
QUrl fromEncoded(const QByteArray &input)
QByteArray toEncoded(QFlags< QUrl::FormattingOption > options) const
QByteArray toAscii() const
QString attribution() const
Get the attribution of the layer used by QGIS Server in GetCapabilities request Attribution indicates...
Definition: qgsmaplayer.h:188
QUrl fromLocalFile(const QString &localFile)
QString metadataUrlType() const
Get the metadata type of the layer used by QGIS Server in GetCapabilities request MetadataUrlType ind...
Definition: qgsmaplayer.h:226
void setScaleBasedVisibility(const bool enabled)
Sets whether scale based visibility is enabled for the layer.
Q_DECL_DEPRECATED void toggleScaleBasedVisibility(bool theVisibilityFlag)
Accessor for the scale based visilibility flag.
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QDomNode at(int index) const
QString writePath(const QString &filename, const QString &relativeBasePath=QString()) const
Prepare a filename to save it to the project file.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QByteArray toUtf8() const