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