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