QGIS API Documentation
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" ).toDouble() );
427  setMaximumScale( layerElement.attribute( "maximumScale" ).toDouble() );
428 
429  // set name
430  mnl = layerElement.namedItem( "layername" );
431  mne = mnl.toElement();
432  setLayerName( mne.text() );
433 
434  //short name
435  QDomElement shortNameElem = layerElement.firstChildElement( "shortname" );
436  if ( !shortNameElem.isNull() )
437  {
438  mShortName = shortNameElem.text();
439  }
440 
441  //title
442  QDomElement titleElem = layerElement.firstChildElement( "title" );
443  if ( !titleElem.isNull() )
444  {
445  mTitle = titleElem.text();
446  }
447 
448  //abstract
449  QDomElement abstractElem = layerElement.firstChildElement( "abstract" );
450  if ( !abstractElem.isNull() )
451  {
452  mAbstract = abstractElem.text();
453  }
454 
455  //keywordList
456  QDomElement keywordListElem = layerElement.firstChildElement( "keywordList" );
457  if ( !keywordListElem.isNull() )
458  {
459  QStringList kwdList;
460  for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
461  {
462  kwdList << n.toElement().text();
463  }
464  mKeywordList = kwdList.join( ", " );
465  }
466 
467  //metadataUrl
468  QDomElement dataUrlElem = layerElement.firstChildElement( "dataUrl" );
469  if ( !dataUrlElem.isNull() )
470  {
471  mDataUrl = dataUrlElem.text();
472  mDataUrlFormat = dataUrlElem.attribute( "format", "" );
473  }
474 
475  //legendUrl
476  QDomElement legendUrlElem = layerElement.firstChildElement( "legendUrl" );
477  if ( !legendUrlElem.isNull() )
478  {
479  mLegendUrl = legendUrlElem.text();
480  mLegendUrlFormat = legendUrlElem.attribute( "format", "" );
481  }
482 
483  //attribution
484  QDomElement attribElem = layerElement.firstChildElement( "attribution" );
485  if ( !attribElem.isNull() )
486  {
487  mAttribution = attribElem.text();
488  mAttributionUrl = attribElem.attribute( "href", "" );
489  }
490 
491  //metadataUrl
492  QDomElement metaUrlElem = layerElement.firstChildElement( "metadataUrl" );
493  if ( !metaUrlElem.isNull() )
494  {
495  mMetadataUrl = metaUrlElem.text();
496  mMetadataUrlType = metaUrlElem.attribute( "type", "" );
497  mMetadataUrlFormat = metaUrlElem.attribute( "format", "" );
498  }
499 
500 #if 0
501  //read transparency level
502  QDomNode transparencyNode = layer_node.namedItem( "transparencyLevelInt" );
503  if ( ! transparencyNode.isNull() )
504  {
505  // set transparency level only if it's in project
506  // (otherwise it sets the layer transparent)
507  QDomElement myElement = transparencyNode.toElement();
508  setTransparency( myElement.text().toInt() );
509  }
510 #endif
511 
512  readCustomProperties( layerElement );
513 
514  return true;
515 } // bool QgsMapLayer::readLayerXML
516 
517 
518 bool QgsMapLayer::readXml( const QDomNode& layer_node )
519 {
520  Q_UNUSED( layer_node );
521  // NOP by default; children will over-ride with behavior specific to them
522 
523  return true;
524 } // void QgsMapLayer::readXml
525 
526 
527 
528 bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath )
529 {
530  // use scale dependent visibility flag
531  layerElement.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
532  layerElement.setAttribute( "minimumScale", QString::number( minimumScale() ) );
533  layerElement.setAttribute( "maximumScale", QString::number( maximumScale() ) );
534 
535  if ( !mExtent.isNull() )
536  {
537  layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent, document ) );
538  }
539 
540  // ID
541  QDomElement layerId = document.createElement( "id" );
542  QDomText layerIdText = document.createTextNode( id() );
543  layerId.appendChild( layerIdText );
544 
545  layerElement.appendChild( layerId );
546 
547  // data source
548  QDomElement dataSource = document.createElement( "datasource" );
549 
550  QString src = source();
551 
552  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
553  // TODO: what about postgres, mysql and others, they should not go through writePath()
554  if ( vlayer && vlayer->providerType() == "spatialite" )
555  {
556  QgsDataSourceURI uri( src );
557  QString database = QgsProject::instance()->writePath( uri.database(), relativeBasePath );
558  uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
559  src = uri.uri();
560  }
561  else if ( vlayer && vlayer->providerType() == "ogr" )
562  {
563  QStringList theURIParts = src.split( '|' );
564  theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0], relativeBasePath );
565  src = theURIParts.join( "|" );
566  }
567  else if ( vlayer && vlayer->providerType() == "gpx" )
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() == "delimitedtext" )
574  {
575  QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
576  QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->writePath( urlSource.toLocalFile(), relativeBasePath ) );
577  urlDest.setQueryItems( urlSource.queryItems() );
578  src = QString::fromAscii( urlDest.toEncoded() );
579  }
580  else if ( vlayer && vlayer->providerType() == "memory" )
581  {
582  // Refetch the source from the provider, because adding fields actually changes the source for this provider.
583  src = vlayer->dataProvider()->dataSourceUri();
584  }
585  else
586  {
587  bool handled = false;
588 
589  if ( !vlayer )
590  {
591  QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( this );
592  // Update path for subdataset
593  if ( rlayer && rlayer->providerType() == "gdal" )
594  {
595  if ( src.startsWith( "NETCDF:" ) )
596  {
597  // NETCDF:filename:variable
598  // filename can be quoted with " as it can contain colons
599  QRegExp r( "NETCDF:(.+):([^:]+)" );
600  if ( r.exactMatch( src ) )
601  {
602  QString filename = r.cap( 1 );
603  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
604  filename = filename.mid( 1, filename.length() - 2 );
605  src = "NETCDF:\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
606  handled = true;
607  }
608  }
609  else if ( src.startsWith( "HDF4_SDS:" ) )
610  {
611  // HDF4_SDS:subdataset_type:file_name:subdataset_index
612  // filename can be quoted with " as it can contain colons
613  QRegExp r( "HDF4_SDS:([^:]+):(.+):([^:]+)" );
614  if ( r.exactMatch( src ) )
615  {
616  QString filename = r.cap( 2 );
617  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
618  filename = filename.mid( 1, filename.length() - 2 );
619  src = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
620  handled = true;
621  }
622  }
623  else if ( src.startsWith( "HDF5:" ) )
624  {
625  // HDF5:file_name:subdataset
626  // filename can be quoted with " as it can contain colons
627  QRegExp r( "HDF5:(.+):([^:]+)" );
628  if ( r.exactMatch( src ) )
629  {
630  QString filename = r.cap( 1 );
631  if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
632  filename = filename.mid( 1, filename.length() - 2 );
633  src = "HDF5:\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
634  handled = true;
635  }
636  }
637  else if ( src.contains( QRegExp( "^(NITF_IM|RADARSAT_2_CALIB):" ) ) )
638  {
639  // NITF_IM:0:filename
640  // RADARSAT_2_CALIB:?:filename
641  QRegExp r( "([^:]+):([^:]+):(.+)" );
642  if ( r.exactMatch( src ) )
643  {
644  src = r.cap( 1 ) + ':' + r.cap( 2 ) + ':' + QgsProject::instance()->writePath( r.cap( 3 ), relativeBasePath );
645  handled = true;
646  }
647  }
648  }
649  }
650 
651  if ( !handled )
652  src = QgsProject::instance()->writePath( src, relativeBasePath );
653  }
654 
655  QDomText dataSourceText = document.createTextNode( src );
656  dataSource.appendChild( dataSourceText );
657 
658  layerElement.appendChild( dataSource );
659 
660 
661  // layer name
662  QDomElement layerName = document.createElement( "layername" );
663  QDomText layerNameText = document.createTextNode( originalName() );
664  layerName.appendChild( layerNameText );
665  layerElement.appendChild( layerName );
666 
667  // layer short name
668  if ( !mShortName.isEmpty() )
669  {
670  QDomElement layerShortName = document.createElement( "shortname" );
671  QDomText layerShortNameText = document.createTextNode( mShortName );
672  layerShortName.appendChild( layerShortNameText );
673  layerElement.appendChild( layerShortName );
674  }
675 
676  // layer title
677  if ( !mTitle.isEmpty() )
678  {
679  QDomElement layerTitle = document.createElement( "title" );
680  QDomText layerTitleText = document.createTextNode( mTitle );
681  layerTitle.appendChild( layerTitleText );
682  layerElement.appendChild( layerTitle );
683  }
684 
685  // layer abstract
686  if ( !mAbstract.isEmpty() )
687  {
688  QDomElement layerAbstract = document.createElement( "abstract" );
689  QDomText layerAbstractText = document.createTextNode( mAbstract );
690  layerAbstract.appendChild( layerAbstractText );
691  layerElement.appendChild( layerAbstract );
692  }
693 
694  // layer keyword list
695  QStringList keywordStringList = keywordList().split( ',' );
696  if ( !keywordStringList.isEmpty() )
697  {
698  QDomElement layerKeywordList = document.createElement( "keywordList" );
699  for ( int i = 0; i < keywordStringList.size(); ++i )
700  {
701  QDomElement layerKeywordValue = document.createElement( "value" );
702  QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
703  layerKeywordValue.appendChild( layerKeywordText );
704  layerKeywordList.appendChild( layerKeywordValue );
705  }
706  layerElement.appendChild( layerKeywordList );
707  }
708 
709  // layer metadataUrl
710  QString aDataUrl = dataUrl();
711  if ( !aDataUrl.isEmpty() )
712  {
713  QDomElement layerDataUrl = document.createElement( "dataUrl" );
714  QDomText layerDataUrlText = document.createTextNode( aDataUrl );
715  layerDataUrl.appendChild( layerDataUrlText );
716  layerDataUrl.setAttribute( "format", dataUrlFormat() );
717  layerElement.appendChild( layerDataUrl );
718  }
719 
720  // layer legendUrl
721  QString aLegendUrl = legendUrl();
722  if ( !aLegendUrl.isEmpty() )
723  {
724  QDomElement layerLegendUrl = document.createElement( "legendUrl" );
725  QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
726  layerLegendUrl.appendChild( layerLegendUrlText );
727  layerLegendUrl.setAttribute( "format", legendUrlFormat() );
728  layerElement.appendChild( layerLegendUrl );
729  }
730 
731  // layer attribution
732  QString aAttribution = attribution();
733  if ( !aAttribution.isEmpty() )
734  {
735  QDomElement layerAttribution = document.createElement( "attribution" );
736  QDomText layerAttributionText = document.createTextNode( aAttribution );
737  layerAttribution.appendChild( layerAttributionText );
738  layerAttribution.setAttribute( "href", attributionUrl() );
739  layerElement.appendChild( layerAttribution );
740  }
741 
742  // layer metadataUrl
743  QString aMetadataUrl = metadataUrl();
744  if ( !aMetadataUrl.isEmpty() )
745  {
746  QDomElement layerMetadataUrl = document.createElement( "metadataUrl" );
747  QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
748  layerMetadataUrl.appendChild( layerMetadataUrlText );
749  layerMetadataUrl.setAttribute( "type", metadataUrlType() );
750  layerMetadataUrl.setAttribute( "format", metadataUrlFormat() );
751  layerElement.appendChild( layerMetadataUrl );
752  }
753 
754  // timestamp if supported
755  if ( timestamp() > QDateTime() )
756  {
757  QDomElement stamp = document.createElement( "timestamp" );
758  QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
759  stamp.appendChild( stampText );
760  layerElement.appendChild( stamp );
761  }
762 
763  layerElement.appendChild( layerName );
764 
765  // zorder
766  // This is no longer stored in the project file. It is superfluous since the layers
767  // are written and read in the proper order.
768 
769  // spatial reference system id
770  QDomElement mySrsElement = document.createElement( "srs" );
771  mCRS->writeXML( mySrsElement, document );
772  layerElement.appendChild( mySrsElement );
773 
774 #if 0
775  // <transparencyLevelInt>
776  QDomElement transparencyLevelIntElement = document.createElement( "transparencyLevelInt" );
777  QDomText transparencyLevelIntText = document.createTextNode( QString::number( getTransparency() ) );
778  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
779  maplayer.appendChild( transparencyLevelIntElement );
780 #endif
781 
782  // now append layer node to map layer node
783 
784  writeCustomProperties( layerElement, document );
785 
786  return writeXml( layerElement, document );
787 
788 } // bool QgsMapLayer::writeXML
789 
791 {
792  QDomDocument doc( "qgis-layer-definition" );
793  QDomElement qgiselm = doc.createElement( "qlr" );
794  doc.appendChild( qgiselm );
795  QDomElement layerselm = doc.createElement( "maplayers" );
796  Q_FOREACH ( QgsMapLayer* layer, layers )
797  {
798  QDomElement layerelm = doc.createElement( "maplayer" );
799  layer->writeLayerXML( layerelm, doc, relativeBasePath );
800  layerselm.appendChild( layerelm );
801  }
802  qgiselm.appendChild( layerselm );
803  return doc;
804 }
805 
806 QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document, bool addToRegistry, bool addToLegend )
807 {
808  QList<QgsMapLayer*> layers;
809  QDomNodeList layernodes = document.elementsByTagName( "maplayer" );
810  for ( int i = 0; i < layernodes.size(); ++i )
811  {
812  QDomNode layernode = layernodes.at( i );
813  QDomElement layerElem = layernode.toElement();
814 
815  QString type = layerElem.attribute( "type" );
816  QgsDebugMsg( type );
817  QgsMapLayer *layer = nullptr;
818 
819  if ( type == "vector" )
820  {
821  layer = new QgsVectorLayer;
822  }
823  else if ( type == "raster" )
824  {
825  layer = new QgsRasterLayer;
826  }
827  else if ( type == "plugin" )
828  {
829  QString typeName = layerElem.attribute( "name" );
830  layer = QgsPluginLayerRegistry::instance()->createLayer( typeName );
831  }
832 
833  if ( !layer )
834  continue;
835 
836  bool ok = layer->readLayerXML( layerElem );
837  if ( ok )
838  {
839  layers << layer;
840  if ( addToRegistry )
841  QgsMapLayerRegistry::instance()->addMapLayer( layer, addToLegend );
842  }
843  }
844  return layers;
845 }
846 
848 {
849  QFile file( qlrfile );
850  if ( !file.open( QIODevice::ReadOnly ) )
851  {
852  QgsDebugMsg( "Can't open file" );
853  return QList<QgsMapLayer*>();
854  }
855 
856  QDomDocument doc;
857  if ( !doc.setContent( &file ) )
858  {
859  QgsDebugMsg( "Can't set content" );
860  return QList<QgsMapLayer*>();
861  }
862 
863  QFileInfo fileinfo( file );
864  QDir::setCurrent( fileinfo.absoluteDir().path() );
865  return QgsMapLayer::fromLayerDefinition( doc );
866 }
867 
868 
869 bool QgsMapLayer::writeXml( QDomNode & layer_node, QDomDocument & document )
870 {
871  Q_UNUSED( layer_node );
872  Q_UNUSED( document );
873  // NOP by default; children will over-ride with behavior specific to them
874 
875  return true;
876 } // void QgsMapLayer::writeXml
877 
878 
879 void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
880 {
881  mCustomProperties.readXml( layerNode, keyStartsWith );
882 }
883 
885 {
886  mCustomProperties.writeXml( layerNode, doc );
887 }
888 
889 void QgsMapLayer::readStyleManager( const QDomNode& layerNode )
890 {
891  QDomElement styleMgrElem = layerNode.firstChildElement( "map-layer-style-manager" );
892  if ( !styleMgrElem.isNull() )
893  mStyleManager->readXml( styleMgrElem );
894  else
895  mStyleManager->reset();
896 }
897 
899 {
900  if ( mStyleManager )
901  {
902  QDomElement styleMgrElem = doc.createElement( "map-layer-style-manager" );
903  mStyleManager->writeXml( styleMgrElem );
904  layerNode.appendChild( styleMgrElem );
905  }
906 }
907 
908 
909 
910 
912 {
913  return mValid;
914 }
915 
916 
918 {
919  QgsDebugMsg( "called" );
920  // TODO: emit a signal - it will be used to update legend
921 }
922 
923 
925 {
926  return QString();
927 }
928 
930 {
931  return QString();
932 }
933 
934 #if 0
935 void QgsMapLayer::connectNotify( const char * signal )
936 {
937  Q_UNUSED( signal );
938  QgsDebugMsgLevel( "QgsMapLayer connected to " + QString( signal ), 3 );
939 } // QgsMapLayer::connectNotify
940 #endif
941 
942 bool QgsMapLayer::isInScaleRange( double scale ) const
943 {
944  return !mScaleBasedVisibility || ( mMinScale * QGis::SCALE_PRECISION < scale && scale < mMaxScale );
945 }
946 
947 void QgsMapLayer::toggleScaleBasedVisibility( bool theVisibilityFlag )
948 {
949  setScaleBasedVisibility( theVisibilityFlag );
950 }
951 
953 {
954  return mScaleBasedVisibility;
955 }
956 
957 void QgsMapLayer::setMinimumScale( double theMinScale )
958 {
959  mMinScale = theMinScale;
960 }
961 
963 {
964  return mMinScale;
965 }
966 
967 
968 void QgsMapLayer::setMaximumScale( double theMaxScale )
969 {
970  mMaxScale = theMaxScale;
971 }
972 
973 void QgsMapLayer::setScaleBasedVisibility( const bool enabled )
974 {
975  mScaleBasedVisibility = enabled;
976 }
977 
979 {
980  return mMaxScale;
981 }
982 
984 {
985  return QStringList(); // Empty
986 }
987 
989 {
990  Q_UNUSED( layers );
991  // NOOP
992 }
993 
995 {
996  Q_UNUSED( name );
997  Q_UNUSED( vis );
998  // NOOP
999 }
1000 
1002 {
1003  return *mCRS;
1004 }
1005 
1006 void QgsMapLayer::setCrs( const QgsCoordinateReferenceSystem& srs, bool emitSignal )
1007 {
1008  *mCRS = srs;
1009 
1010  if ( !mCRS->isValid() )
1011  {
1012  mCRS->setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
1013  mCRS->validate();
1014  }
1015 
1016  if ( emitSignal )
1017  emit layerCrsChanged();
1018 }
1019 
1021 {
1022  // Capitalise the first letter of the layer name if requested
1023  QSettings settings;
1024  bool capitaliseLayerName =
1025  settings.value( "/qgis/capitaliseLayerName", QVariant( false ) ).toBool();
1026 
1027  QString layerName( name );
1028 
1029  if ( capitaliseLayerName )
1030  layerName = layerName.left( 1 ).toUpper() + layerName.mid( 1 );
1031 
1032  return layerName;
1033 }
1034 
1036 {
1037  QString myURI = publicSource();
1038 
1039  // if file is using the VSIFILE mechanism, remove the prefix
1040  if ( myURI.startsWith( "/vsigzip/", Qt::CaseInsensitive ) )
1041  {
1042  myURI.remove( 0, 9 );
1043  }
1044  else if ( myURI.startsWith( "/vsizip/", Qt::CaseInsensitive ) &&
1045  myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
1046  {
1047  // ideally we should look for .qml file inside zip file
1048  myURI.remove( 0, 8 );
1049  }
1050  else if ( myURI.startsWith( "/vsitar/", Qt::CaseInsensitive ) &&
1051  ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) ||
1052  myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) ||
1053  myURI.endsWith( ".tgz", Qt::CaseInsensitive ) ) )
1054  {
1055  // ideally we should look for .qml file inside tar file
1056  myURI.remove( 0, 8 );
1057  }
1058 
1059  QFileInfo myFileInfo( myURI );
1060  QString key;
1061 
1062  if ( myFileInfo.exists() )
1063  {
1064  // if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
1065  if ( myURI.endsWith( ".gz", Qt::CaseInsensitive ) )
1066  myURI.chop( 3 );
1067  else if ( myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
1068  myURI.chop( 4 );
1069  else if ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) )
1070  myURI.chop( 4 );
1071  else if ( myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) )
1072  myURI.chop( 7 );
1073  else if ( myURI.endsWith( ".tgz", Qt::CaseInsensitive ) )
1074  myURI.chop( 4 );
1075  myFileInfo.setFile( myURI );
1076  // get the file name for our .qml style file
1077  key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
1078  }
1079  else
1080  {
1081  key = publicSource();
1082  }
1083 
1084  return key;
1085 }
1086 
1088 {
1089  return loadNamedStyle( styleURI(), theResultFlag );
1090 }
1091 
1092 bool QgsMapLayer::loadNamedStyleFromDb( const QString &db, const QString &theURI, QString &qml )
1093 {
1094  QgsDebugMsg( QString( "db = %1 uri = %2" ).arg( db, theURI ) );
1095 
1096  bool theResultFlag = false;
1097 
1098  // read from database
1099  sqlite3 *myDatabase;
1100  sqlite3_stmt *myPreparedStatement;
1101  const char *myTail;
1102  int myResult;
1103 
1104  QgsDebugMsg( QString( "Trying to load style for \"%1\" from \"%2\"" ).arg( theURI, db ) );
1105 
1106  if ( db.isEmpty() || !QFile( db ).exists() )
1107  return false;
1108 
1109  myResult = sqlite3_open_v2( db.toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, nullptr );
1110  if ( myResult != SQLITE_OK )
1111  {
1112  return false;
1113  }
1114 
1115  QString mySql = "select qml from tbl_styles where style=?";
1116  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1117  if ( myResult == SQLITE_OK )
1118  {
1119  QByteArray param = theURI.toUtf8();
1120 
1121  if ( sqlite3_bind_text( myPreparedStatement, 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
1122  sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
1123  {
1124  qml = QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( myPreparedStatement, 0 ) ) );
1125  theResultFlag = true;
1126  }
1127 
1128  sqlite3_finalize( myPreparedStatement );
1129  }
1130 
1131  sqlite3_close( myDatabase );
1132 
1133  return theResultFlag;
1134 }
1135 
1136 
1137 QString QgsMapLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
1138 {
1139  QgsDebugMsg( QString( "uri = %1 myURI = %2" ).arg( theURI, publicSource() ) );
1140 
1141  theResultFlag = false;
1142 
1143  QDomDocument myDocument( "qgis" );
1144 
1145  // location of problem associated with errorMsg
1146  int line, column;
1147  QString myErrorMessage;
1148 
1149  QFile myFile( theURI );
1150  if ( myFile.open( QFile::ReadOnly ) )
1151  {
1152  // read file
1153  theResultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
1154  if ( !theResultFlag )
1155  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1156  myFile.close();
1157  }
1158  else
1159  {
1160  QFileInfo project( QgsProject::instance()->fileName() );
1161  QgsDebugMsg( QString( "project fileName: %1" ).arg( project.absoluteFilePath() ) );
1162 
1163  QString qml;
1164  if ( loadNamedStyleFromDb( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ), theURI, qml ) ||
1165  ( project.exists() && loadNamedStyleFromDb( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), theURI, qml ) ) ||
1166  loadNamedStyleFromDb( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( "resources/qgis.qmldb" ), theURI, qml ) )
1167  {
1168  theResultFlag = myDocument.setContent( qml, &myErrorMessage, &line, &column );
1169  if ( !theResultFlag )
1170  {
1171  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1172  }
1173  }
1174  else
1175  {
1176  myErrorMessage = tr( "Style not found in database" );
1177  }
1178  }
1179 
1180  if ( !theResultFlag )
1181  {
1182  return myErrorMessage;
1183  }
1184 
1185  theResultFlag = importNamedStyle( myDocument, myErrorMessage );
1186  if ( !theResultFlag )
1187  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( theURI, myErrorMessage );
1188 
1189  return myErrorMessage;
1190 }
1191 
1192 
1193 bool QgsMapLayer::importNamedStyle( QDomDocument& myDocument, QString& myErrorMessage )
1194 {
1195  QDomElement myRoot = myDocument.firstChildElement( "qgis" );
1196  if ( myRoot.isNull() )
1197  {
1198  myErrorMessage = tr( "Root <qgis> element could not be found" );
1199  return false;
1200  }
1201 
1202  // get style file version string, if any
1203  QgsProjectVersion fileVersion( myRoot.attribute( "version" ) );
1204  QgsProjectVersion thisVersion( QGis::QGIS_VERSION );
1205 
1206  if ( thisVersion > fileVersion )
1207  {
1208  QgsProjectFileTransform styleFile( myDocument, fileVersion );
1209  styleFile.updateRevision( thisVersion );
1210  }
1211 
1212  //Test for matching geometry type on vector layers when applying, if geometry type is given in the style
1213  if ( type() == QgsMapLayer::VectorLayer && !myRoot.firstChildElement( "layerGeometryType" ).isNull() )
1214  {
1215  QgsVectorLayer *vl = static_cast<QgsVectorLayer*>( this );
1216  int importLayerGeometryType = myRoot.firstChildElement( "layerGeometryType" ).text().toInt();
1217  if ( vl->geometryType() != importLayerGeometryType )
1218  {
1219  myErrorMessage = tr( "Cannot apply style to layer with a different geometry type" );
1220  return false;
1221  }
1222  }
1223 
1224  // use scale dependent visibility flag
1225  setScaleBasedVisibility( myRoot.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
1226  setMinimumScale( myRoot.attribute( "minimumScale" ).toDouble() );
1227  setMaximumScale( myRoot.attribute( "maximumScale" ).toDouble() );
1228 
1229  QDomNode extentNode = myRoot.namedItem( "extent" );
1230  if ( !extentNode.isNull() )
1231  {
1232  setExtent( QgsXmlUtils::readRectangle( extentNode.toElement() ) );
1233  }
1234 
1235 #if 0
1236  //read transparency level
1237  QDomNode transparencyNode = myRoot.namedItem( "transparencyLevelInt" );
1238  if ( ! transparencyNode.isNull() )
1239  {
1240  // set transparency level only if it's in project
1241  // (otherwise it sets the layer transparent)
1242  QDomElement myElement = transparencyNode.toElement();
1243  setTransparency( myElement.text().toInt() );
1244  }
1245 #endif
1246 
1247  return readSymbology( myRoot, myErrorMessage );
1248 }
1249 
1251 {
1252  QDomImplementation DomImplementation;
1253  QDomDocumentType documentType = DomImplementation.createDocumentType( "qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
1254  QDomDocument myDocument( documentType );
1255 
1256  QDomElement myRootNode = myDocument.createElement( "qgis" );
1257  myRootNode.setAttribute( "version", QString( "%1" ).arg( QGis::QGIS_VERSION ) );
1258  myDocument.appendChild( myRootNode );
1259 
1260  myRootNode.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
1261  myRootNode.setAttribute( "minimumScale", QString::number( minimumScale() ) );
1262  myRootNode.setAttribute( "maximumScale", QString::number( maximumScale() ) );
1263 
1264 #if 0
1265  // <transparencyLevelInt>
1266  QDomElement transparencyLevelIntElement = myDocument.createElement( "transparencyLevelInt" );
1267  QDomText transparencyLevelIntText = myDocument.createTextNode( QString::number( getTransparency() ) );
1268  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
1269  myRootNode.appendChild( transparencyLevelIntElement );
1270 #endif
1271 
1272  if ( !writeSymbology( myRootNode, myDocument, errorMsg ) )
1273  {
1274  errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1275  return;
1276  }
1277 
1278  /*
1279  * Check to see if the layer is vector - in which case we should also export its geometryType
1280  * to avoid eventually pasting to a layer with a different geometry
1281  */
1282  if ( type() == QgsMapLayer::VectorLayer )
1283  {
1284  //Getting the selectionLayer geometry
1285  QgsVectorLayer *vl = static_cast<QgsVectorLayer*>( this );
1286  QString geoType = QString::number( vl->geometryType() );
1287 
1288  //Adding geometryinformation
1289  QDomElement layerGeometryType = myDocument.createElement( "layerGeometryType" );
1290  QDomText type = myDocument.createTextNode( geoType );
1291 
1292  layerGeometryType.appendChild( type );
1293  myRootNode.appendChild( layerGeometryType );
1294  }
1295 
1296  doc = myDocument;
1297 }
1298 
1300 {
1301  return saveNamedStyle( styleURI(), theResultFlag );
1302 }
1303 
1304 QString QgsMapLayer::saveNamedStyle( const QString &theURI, bool &theResultFlag )
1305 {
1306  QString myErrorMessage;
1307  QDomDocument myDocument;
1308  exportNamedStyle( myDocument, myErrorMessage );
1309 
1310  // check if the uri is a file or ends with .qml,
1311  // which indicates that it should become one
1312  // everything else goes to the database
1313  QString filename;
1314 
1315  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1316  if ( vlayer && vlayer->providerType() == "ogr" )
1317  {
1318  QStringList theURIParts = theURI.split( '|' );
1319  filename = theURIParts[0];
1320  }
1321  else if ( vlayer && vlayer->providerType() == "gpx" )
1322  {
1323  QStringList theURIParts = theURI.split( '?' );
1324  filename = theURIParts[0];
1325  }
1326  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
1327  {
1328  filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1329  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1330  if ( filename.isEmpty() )
1331  filename = theURI;
1332  }
1333  else
1334  {
1335  filename = theURI;
1336  }
1337 
1338  QFileInfo myFileInfo( filename );
1339  if ( myFileInfo.exists() || filename.endsWith( ".qml", Qt::CaseInsensitive ) )
1340  {
1341  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1342  if ( !myDirInfo.isWritable() )
1343  {
1344  return tr( "The directory containing your dataset needs to be writable!" );
1345  }
1346 
1347  // now construct the file name for our .qml style file
1348  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
1349 
1350  QFile myFile( myFileName );
1351  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1352  {
1353  QTextStream myFileStream( &myFile );
1354  // save as utf-8 with 2 spaces for indents
1355  myDocument.save( myFileStream, 2 );
1356  myFile.close();
1357  theResultFlag = true;
1358  return tr( "Created default style file as %1" ).arg( myFileName );
1359  }
1360  else
1361  {
1362  theResultFlag = false;
1363  return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1364  }
1365  }
1366  else
1367  {
1368  QString qml = myDocument.toString();
1369 
1370  // read from database
1371  sqlite3 *myDatabase;
1372  sqlite3_stmt *myPreparedStatement;
1373  const char *myTail;
1374  int myResult;
1375 
1376  myResult = sqlite3_open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ).toUtf8().data(), &myDatabase );
1377  if ( myResult != SQLITE_OK )
1378  {
1379  return tr( "User database could not be opened." );
1380  }
1381 
1382  QByteArray param0 = theURI.toUtf8();
1383  QByteArray param1 = qml.toUtf8();
1384 
1385  QString mySql = "create table if not exists tbl_styles(style varchar primary key,qml varchar)";
1386  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1387  if ( myResult == SQLITE_OK )
1388  {
1389  if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
1390  {
1391  sqlite3_finalize( myPreparedStatement );
1392  sqlite3_close( myDatabase );
1393  theResultFlag = false;
1394  return tr( "The style table could not be created." );
1395  }
1396  }
1397 
1398  sqlite3_finalize( myPreparedStatement );
1399 
1400  mySql = "insert into tbl_styles(style,qml) values (?,?)";
1401  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1402  if ( myResult == SQLITE_OK )
1403  {
1404  if ( sqlite3_bind_text( myPreparedStatement, 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1405  sqlite3_bind_text( myPreparedStatement, 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1406  sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1407  {
1408  theResultFlag = true;
1409  myErrorMessage = tr( "The style %1 was saved to database" ).arg( theURI );
1410  }
1411  }
1412 
1413  sqlite3_finalize( myPreparedStatement );
1414 
1415  if ( !theResultFlag )
1416  {
1417  QString mySql = "update tbl_styles set qml=? where style=?";
1418  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1419  if ( myResult == SQLITE_OK )
1420  {
1421  if ( sqlite3_bind_text( myPreparedStatement, 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1422  sqlite3_bind_text( myPreparedStatement, 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1423  sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1424  {
1425  theResultFlag = true;
1426  myErrorMessage = tr( "The style %1 was updated in the database." ).arg( theURI );
1427  }
1428  else
1429  {
1430  theResultFlag = false;
1431  myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( theURI );
1432  }
1433  }
1434  else
1435  {
1436  theResultFlag = false;
1437  myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( theURI );
1438  }
1439 
1440  sqlite3_finalize( myPreparedStatement );
1441  }
1442 
1443  sqlite3_close( myDatabase );
1444  }
1445 
1446  return myErrorMessage;
1447 }
1448 
1450 {
1451  QDomDocument myDocument = QDomDocument();
1452 
1453  QDomNode header = myDocument.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" );
1454  myDocument.appendChild( header );
1455 
1456  // Create the root element
1457  QDomElement root = myDocument.createElementNS( "http://www.opengis.net/sld", "StyledLayerDescriptor" );
1458  root.setAttribute( "version", "1.1.0" );
1459  root.setAttribute( "units", "mm" ); // default qgsmaprenderer is Millimeters
1460  root.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" );
1461  root.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" );
1462  root.setAttribute( "xmlns:se", "http://www.opengis.net/se" );
1463  root.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
1464  root.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
1465  myDocument.appendChild( root );
1466 
1467  // Create the NamedLayer element
1468  QDomElement namedLayerNode = myDocument.createElement( "NamedLayer" );
1469  root.appendChild( namedLayerNode );
1470 
1471  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1472  if ( !vlayer )
1473  {
1474  errorMsg = tr( "Could not save symbology because:\n%1" )
1475  .arg( "Non-vector layers not supported yet" );
1476  return;
1477  }
1478 
1479  if ( !vlayer->writeSld( namedLayerNode, myDocument, errorMsg ) )
1480  {
1481  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1482  return;
1483  }
1484 
1485  doc = myDocument;
1486 }
1487 
1488 QString QgsMapLayer::saveSldStyle( const QString &theURI, bool &theResultFlag )
1489 {
1490  QString errorMsg;
1491  QDomDocument myDocument;
1492  exportSldStyle( myDocument, errorMsg );
1493  if ( !errorMsg.isNull() )
1494  {
1495  theResultFlag = false;
1496  return errorMsg;
1497  }
1498  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1499 
1500  // check if the uri is a file or ends with .sld,
1501  // which indicates that it should become one
1502  QString filename;
1503  if ( vlayer->providerType() == "ogr" )
1504  {
1505  QStringList theURIParts = theURI.split( '|' );
1506  filename = theURIParts[0];
1507  }
1508  else if ( vlayer->providerType() == "gpx" )
1509  {
1510  QStringList theURIParts = theURI.split( '?' );
1511  filename = theURIParts[0];
1512  }
1513  else if ( vlayer->providerType() == "delimitedtext" )
1514  {
1515  filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1516  // toLocalFile() returns an empty string if theURI is a plain Windows-path, e.g. "C:/style.qml"
1517  if ( filename.isEmpty() )
1518  filename = theURI;
1519  }
1520  else
1521  {
1522  filename = theURI;
1523  }
1524 
1525  QFileInfo myFileInfo( filename );
1526  if ( myFileInfo.exists() || filename.endsWith( ".sld", Qt::CaseInsensitive ) )
1527  {
1528  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1529  if ( !myDirInfo.isWritable() )
1530  {
1531  return tr( "The directory containing your dataset needs to be writable!" );
1532  }
1533 
1534  // now construct the file name for our .sld style file
1535  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".sld";
1536 
1537  QFile myFile( myFileName );
1538  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1539  {
1540  QTextStream myFileStream( &myFile );
1541  // save as utf-8 with 2 spaces for indents
1542  myDocument.save( myFileStream, 2 );
1543  myFile.close();
1544  theResultFlag = true;
1545  return tr( "Created default style file as %1" ).arg( myFileName );
1546  }
1547  }
1548 
1549  theResultFlag = false;
1550  return tr( "ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1551 }
1552 
1553 QString QgsMapLayer::loadSldStyle( const QString &theURI, bool &theResultFlag )
1554 {
1555  QgsDebugMsg( "Entered." );
1556 
1557  theResultFlag = false;
1558 
1559  QDomDocument myDocument;
1560 
1561  // location of problem associated with errorMsg
1562  int line, column;
1563  QString myErrorMessage;
1564 
1565  QFile myFile( theURI );
1566  if ( myFile.open( QFile::ReadOnly ) )
1567  {
1568  // read file
1569  theResultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
1570  if ( !theResultFlag )
1571  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1572  myFile.close();
1573  }
1574  else
1575  {
1576  myErrorMessage = tr( "Unable to open file %1" ).arg( theURI );
1577  }
1578 
1579  if ( !theResultFlag )
1580  {
1581  return myErrorMessage;
1582  }
1583 
1584  // check for root SLD element
1585  QDomElement myRoot = myDocument.firstChildElement( "StyledLayerDescriptor" );
1586  if ( myRoot.isNull() )
1587  {
1588  myErrorMessage = QString( "Error: StyledLayerDescriptor element not found in %1" ).arg( theURI );
1589  theResultFlag = false;
1590  return myErrorMessage;
1591  }
1592 
1593  // now get the style node out and pass it over to the layer
1594  // to deserialise...
1595  QDomElement namedLayerElem = myRoot.firstChildElement( "NamedLayer" );
1596  if ( namedLayerElem.isNull() )
1597  {
1598  myErrorMessage = QLatin1String( "Info: NamedLayer element not found." );
1599  theResultFlag = false;
1600  return myErrorMessage;
1601  }
1602 
1603  QString errorMsg;
1604  theResultFlag = readSld( namedLayerElem, errorMsg );
1605  if ( !theResultFlag )
1606  {
1607  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( theURI, errorMsg );
1608  return myErrorMessage;
1609  }
1610 
1611  return "";
1612 }
1613 
1614 
1616 {
1617  return &mUndoStack;
1618 }
1619 
1620 
1621 void QgsMapLayer::setCustomProperty( const QString& key, const QVariant& value )
1622 {
1623  mCustomProperties.setValue( key, value );
1624 }
1625 
1626 QVariant QgsMapLayer::customProperty( const QString& value, const QVariant& defaultValue ) const
1627 {
1628  return mCustomProperties.value( value, defaultValue );
1629 }
1630 
1632 {
1633  mCustomProperties.remove( key );
1634 }
1635 
1636 
1637 
1639 {
1640  return false;
1641 }
1642 
1643 void QgsMapLayer::setValid( bool valid )
1644 {
1645  mValid = valid;
1646 }
1647 
1649 {
1650  emit repaintRequested();
1651 }
1652 
1654 {
1655  if ( legend == mLegend )
1656  return;
1657 
1658  delete mLegend;
1659  mLegend = legend;
1660 
1661  if ( mLegend )
1662  connect( mLegend, SIGNAL( itemsChanged() ), this, SIGNAL( legendChanged() ) );
1663 
1664  emit legendChanged();
1665 }
1666 
1668 {
1669  return mLegend;
1670 }
1671 
1673 {
1674  return mStyleManager;
1675 }
1676 
1678 {
1679  emit repaintRequested();
1680 }
1681 
1683 {
1684  emit repaintRequested();
1685 }
1686 
1688 {
1689  return QString();
1690 }
1691 
1693 {
1694  mExtent = r;
1695 }
static const char * QGIS_VERSION
Definition: qgis.h:42
QString mShortName
Definition: qgsmaplayer.h:713
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.
QString toUpper() const
QDomProcessingInstruction createProcessingInstruction(const QString &target, const QString &data)
QgsMapLayer::LayerType type() const
Get the type of the layer.
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:726
static QgsAuthManager * instance()
Enforce singleton pattern.
QString mKeywordList
Definition: qgsmaplayer.h:718
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:93
QString mDataUrlFormat
Definition: qgsmaplayer.h:722
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 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:735
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:707
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:698
QString mMetadataUrl
MetadataUrl of the layer.
Definition: qgsmaplayer.h:729
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:721
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.
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:701
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:714
virtual bool readSld(const QDomNode &node, QString &errorMessage)
Definition: qgsmaplayer.h:468
double minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
QString toLocalFile() const
QString mMetadataUrlFormat
Definition: qgsmaplayer.h:731
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:725
QString mAbstract
Description of the layer.
Definition: qgsmaplayer.h:717
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:495
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:704
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()
QString legendUrl() const
Definition: qgsmaplayer.h:493
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...
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:388
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:734
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)
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:614
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:253
QString mLayerOrigName
Original name of the layer.
Definition: qgsmaplayer.h:711
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:730
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