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