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