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