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