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