QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 <QDomNode>
21 #include <QFileInfo>
22 #include <QSettings> // TODO: get rid of it [MD]
23 #include <QDir>
24 #include <QFile>
25 #include <QDomDocument>
26 #include <QDomElement>
27 #include <QDomImplementation>
28 #include <QTextStream>
29 #include <QUrl>
30 
31 #include <sqlite3.h>
32 
33 #include "qgslogger.h"
34 #include "qgsrectangle.h"
35 #include "qgsmaplayer.h"
37 #include "qgsapplication.h"
38 #include "qgsmaplayerlegend.h"
39 #include "qgsproject.h"
40 #include "qgspluginlayerregistry.h"
42 #include "qgsdatasourceuri.h"
43 #include "qgsvectorlayer.h"
44 #include "qgsrasterlayer.h"
45 #include "qgspluginlayer.h"
46 #include "qgsproviderregistry.h"
47 
49  QString lyrname,
50  QString source ) :
51  mValid( false ), // assume the layer is invalid
52  mDataSource( source ),
53  mLayerOrigName( lyrname ), // store the original name
54  mID( "" ),
55  mLayerType( type ),
56  mBlendMode( QPainter::CompositionMode_SourceOver ) // Default to normal blending
57  , mLegend( 0 )
58 {
60 
61  // Set the display name = internal name
62  QgsDebugMsg( "original name: '" + mLayerOrigName + "'" );
64  QgsDebugMsg( "display name: '" + mLayerName + "'" );
65 
66  // Generate the unique ID of this layer
67  QDateTime dt = QDateTime::currentDateTime();
68  mID = lyrname + dt.toString( "yyyyMMddhhmmsszzz" );
69  // Tidy the ID up to avoid characters that may cause problems
70  // elsewhere (e.g in some parts of XML). Replaces every non-word
71  // character (word characters are the alphabet, numbers and
72  // underscore) with an underscore.
73  // Note that the first backslashe in the regular expression is
74  // there for the compiler, so the pattern is actually \W
75  mID.replace( QRegExp( "[\\W]" ), "_" );
76 
77  //set some generous defaults for scale based visibility
78  mMinScale = 0;
79  mMaxScale = 100000000;
80  mScaleBasedVisibility = false;
81 }
82 
84 {
85  delete mCRS;
86  delete mLegend;
87 }
88 
90 {
91  return mLayerType;
92 }
93 
95 QString QgsMapLayer::id() const
96 {
97  return mID;
98 }
99 
101 void QgsMapLayer::setLayerName( const QString & name )
102 {
103  QgsDebugMsg( "new original name: '" + name + "'" );
104  QString newName = capitaliseLayerName( name );
105  QgsDebugMsg( "new display name: '" + name + "'" );
106  if ( name == mLayerOrigName && newName == mLayerName ) return;
107  mLayerOrigName = name; // store the new original name
108  mLayerName = newName;
109  emit layerNameChanged();
110 }
111 
113 QString const & QgsMapLayer::name() const
114 {
115  QgsDebugMsgLevel( "returning name '" + mLayerName + "'", 4 );
116  return mLayerName;
117 }
118 
120 {
121  // Redo this every time we're asked for it, as we don't know if
122  // dataSource has changed.
123  QString safeName = QgsDataSourceURI::removePassword( mDataSource );
124  return safeName;
125 }
126 
127 QString const & QgsMapLayer::source() const
128 {
129  return mDataSource;
130 }
131 
133 {
134  return mExtent;
135 }
136 
138 void QgsMapLayer::setBlendMode( const QPainter::CompositionMode &blendMode )
139 {
141  emit blendModeChanged( blendMode );
142 }
143 
145 QPainter::CompositionMode QgsMapLayer::blendMode() const
146 {
147  return mBlendMode;
148 }
149 
150 bool QgsMapLayer::draw( QgsRenderContext& rendererContext )
151 {
152  Q_UNUSED( rendererContext );
153  return false;
154 }
155 
157 {
158  Q_UNUSED( rendererContext );
159 }
160 
161 bool QgsMapLayer::readLayerXML( const QDomElement& layerElement )
162 {
164  CUSTOM_CRS_VALIDATION savedValidation;
165  bool layerError;
166 
167  QDomNode mnl;
168  QDomElement mne;
169 
170  // read provider
171  QString provider;
172  mnl = layerElement.namedItem( "provider" );
173  mne = mnl.toElement();
174  provider = mne.text();
175 
176  // set data source
177  mnl = layerElement.namedItem( "datasource" );
178  mne = mnl.toElement();
179  mDataSource = mne.text();
180 
181  // TODO: this should go to providers
182  if ( provider == "spatialite" )
183  {
185  uri.setDatabase( QgsProject::instance()->readPath( uri.database() ) );
186  mDataSource = uri.uri();
187  }
188  else if ( provider == "ogr" )
189  {
190  QStringList theURIParts = mDataSource.split( "|" );
191  theURIParts[0] = QgsProject::instance()->readPath( theURIParts[0] );
192  mDataSource = theURIParts.join( "|" );
193  }
194  else if ( provider == "delimitedtext" )
195  {
196  QUrl urlSource = QUrl::fromEncoded( mDataSource.toAscii() );
197 
198  if ( !mDataSource.startsWith( "file:" ) )
199  {
200  QUrl file = QUrl::fromLocalFile( mDataSource.left( mDataSource.indexOf( "?" ) ) );
201  urlSource.setScheme( "file" );
202  urlSource.setPath( file.path() );
203  }
204 
205  QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->readPath( urlSource.toLocalFile() ) );
206  urlDest.setQueryItems( urlSource.queryItems() );
207  mDataSource = QString::fromAscii( urlDest.toEncoded() );
208  }
209  else if ( provider == "wms" )
210  {
211  // >>> BACKWARD COMPATIBILITY < 1.9
212  // For project file backward compatibility we must support old format:
213  // 1. mode: <url>
214  // example: http://example.org/wms?
215  // 2. mode: tiled=<width>;<height>;<resolution>;<resolution>...,ignoreUrl=GetMap;GetFeatureInfo,featureCount=<count>,username=<name>,password=<password>,url=<url>
216  // example: tiled=256;256;0.703;0.351,url=http://example.org/tilecache?
217  // example: featureCount=10,http://example.org/wms?
218  // example: ignoreUrl=GetMap;GetFeatureInfo,username=cimrman,password=jara,url=http://example.org/wms?
219  // This is modified version of old QgsWmsProvider::parseUri
220  // The new format has always params crs,format,layers,styles and that params
221  // should not appear in old format url -> use them to identify version
222  if ( !mDataSource.contains( "crs=" ) && !mDataSource.contains( "format=" ) )
223  {
224  QgsDebugMsg( "Old WMS URI format detected -> converting to new format" );
225  QgsDataSourceURI uri;
226  if ( !mDataSource.startsWith( "http:" ) )
227  {
228  QStringList parts = mDataSource.split( "," );
229  QStringListIterator iter( parts );
230  while ( iter.hasNext() )
231  {
232  QString item = iter.next();
233  if ( item.startsWith( "username=" ) )
234  {
235  uri.setParam( "username", item.mid( 9 ) );
236  }
237  else if ( item.startsWith( "password=" ) )
238  {
239  uri.setParam( "password", item.mid( 9 ) );
240  }
241  else if ( item.startsWith( "tiled=" ) )
242  {
243  // in < 1.9 tiled= may apper in to variants:
244  // tiled=width;height - non tiled mode, specifies max width and max height
245  // tiled=width;height;resolutions-1;resolution2;... - tile mode
246 
247  QStringList params = item.mid( 6 ).split( ";" );
248 
249  if ( params.size() == 2 ) // non tiled mode
250  {
251  uri.setParam( "maxWidth", params.takeFirst() );
252  uri.setParam( "maxHeight", params.takeFirst() );
253  }
254  else if ( params.size() > 2 ) // tiled mode
255  {
256  // resolutions are no more needed and size limit is not used for tiles
257  // we have to tell to the provider however that it is tiled
258  uri.setParam( "tileMatrixSet", "" );
259  }
260  }
261  else if ( item.startsWith( "featureCount=" ) )
262  {
263  uri.setParam( "featureCount", item.mid( 13 ) );
264  }
265  else if ( item.startsWith( "url=" ) )
266  {
267  uri.setParam( "url", item.mid( 4 ) );
268  }
269  else if ( item.startsWith( "ignoreUrl=" ) )
270  {
271  uri.setParam( "ignoreUrl", item.mid( 10 ).split( ";" ) );
272  }
273  }
274  }
275  else
276  {
277  uri.setParam( "url", mDataSource );
278  }
279  mDataSource = uri.encodedUri();
280  // At this point, the URI is obviously incomplete, we add additional params
281  // in QgsRasterLayer::readXml
282  }
283  // <<< BACKWARD COMPATIBILITY < 1.9
284  }
285  else
286  {
288  }
289 
290  // Set the CRS from project file, asking the user if necessary.
291  // Make it the saved CRS to have WMS layer projected correctly.
292  // We will still overwrite whatever GDAL etc picks up anyway
293  // further down this function.
294  mnl = layerElement.namedItem( "layername" );
295  mne = mnl.toElement();
296 
297  QDomNode srsNode = layerElement.namedItem( "srs" );
298  mCRS->readXML( srsNode );
299  mCRS->setValidationHint( tr( "Specify CRS for layer %1" ).arg( mne.text() ) );
300  mCRS->validate();
301  savedCRS = *mCRS;
302 
303  // Do not validate any projections in children, they will be overwritten anyway.
304  // No need to ask the user for a projections when it is overwritten, is there?
307 
308  // now let the children grab what they need from the Dom node.
309  layerError = !readXml( layerElement );
310 
311  // overwrite CRS with what we read from project file before the raster/vector
312  // file readnig functions changed it. They will if projections is specfied in the file.
313  // FIXME: is this necessary?
315  *mCRS = savedCRS;
316 
317  // Abort if any error in layer, such as not found.
318  if ( layerError )
319  {
320  return false;
321  }
322 
323  // the internal name is just the data source basename
324  //QFileInfo dataSourceFileInfo( mDataSource );
325  //internalName = dataSourceFileInfo.baseName();
326 
327  // set ID
328  mnl = layerElement.namedItem( "id" );
329  if ( ! mnl.isNull() )
330  {
331  mne = mnl.toElement();
332  if ( ! mne.isNull() && mne.text().length() > 10 ) // should be at least 17 (yyyyMMddhhmmsszzz)
333  {
334  mID = mne.text();
335  }
336  }
337 
338  // use scale dependent visibility flag
339  toggleScaleBasedVisibility( layerElement.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
340  setMinimumScale( layerElement.attribute( "minimumScale" ).toFloat() );
341  setMaximumScale( layerElement.attribute( "maximumScale" ).toFloat() );
342 
343  // set name
344  mnl = layerElement.namedItem( "layername" );
345  mne = mnl.toElement();
346  setLayerName( mne.text() );
347 
348  //title
349  QDomElement titleElem = layerElement.firstChildElement( "title" );
350  if ( !titleElem.isNull() )
351  {
352  mTitle = titleElem.text();
353  }
354 
355  //abstract
356  QDomElement abstractElem = layerElement.firstChildElement( "abstract" );
357  if ( !abstractElem.isNull() )
358  {
359  mAbstract = abstractElem.text();
360  }
361 
362  //keywordList
363  QDomElement keywordListElem = layerElement.firstChildElement( "keywordList" );
364  if ( !keywordListElem.isNull() )
365  {
366  QStringList kwdList;
367  for ( QDomNode n = keywordListElem.firstChild(); !n.isNull(); n = n.nextSibling() )
368  {
369  kwdList << n.toElement().text();
370  }
371  mKeywordList = kwdList.join( ", " );
372  }
373 
374  //metadataUrl
375  QDomElement dataUrlElem = layerElement.firstChildElement( "dataUrl" );
376  if ( !dataUrlElem.isNull() )
377  {
378  mDataUrl = dataUrlElem.text();
379  mDataUrlFormat = dataUrlElem.attribute( "format", "" );
380  }
381 
382  //legendUrl
383  QDomElement legendUrlElem = layerElement.firstChildElement( "legendUrl" );
384  if ( !legendUrlElem.isNull() )
385  {
386  mLegendUrl = legendUrlElem.text();
387  mLegendUrlFormat = legendUrlElem.attribute( "format", "" );
388  }
389 
390  //attribution
391  QDomElement attribElem = layerElement.firstChildElement( "attribution" );
392  if ( !attribElem.isNull() )
393  {
394  mAttribution = attribElem.text();
395  mAttributionUrl = attribElem.attribute( "href", "" );
396  }
397 
398  //metadataUrl
399  QDomElement metaUrlElem = layerElement.firstChildElement( "metadataUrl" );
400  if ( !metaUrlElem.isNull() )
401  {
402  mMetadataUrl = metaUrlElem.text();
403  mMetadataUrlType = metaUrlElem.attribute( "type", "" );
404  mMetadataUrlFormat = metaUrlElem.attribute( "format", "" );
405  }
406 
407 #if 0
408  //read transparency level
409  QDomNode transparencyNode = layer_node.namedItem( "transparencyLevelInt" );
410  if ( ! transparencyNode.isNull() )
411  {
412  // set transparency level only if it's in project
413  // (otherwise it sets the layer transparent)
414  QDomElement myElement = transparencyNode.toElement();
415  setTransparency( myElement.text().toInt() );
416  }
417 #endif
418 
419  readCustomProperties( layerElement );
420 
421  return true;
422 } // bool QgsMapLayer::readLayerXML
423 
424 
425 bool QgsMapLayer::readXml( const QDomNode& layer_node )
426 {
427  Q_UNUSED( layer_node );
428  // NOP by default; children will over-ride with behavior specific to them
429 
430  return true;
431 } // void QgsMapLayer::readXml
432 
433 
434 
435 bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& document )
436 {
437  // use scale dependent visibility flag
438  layerElement.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
439  layerElement.setAttribute( "minimumScale", QString::number( minimumScale() ) );
440  layerElement.setAttribute( "maximumScale", QString::number( maximumScale() ) );
441 
442  // ID
443  QDomElement layerId = document.createElement( "id" );
444  QDomText layerIdText = document.createTextNode( id() );
445  layerId.appendChild( layerIdText );
446 
447  layerElement.appendChild( layerId );
448 
449  // data source
450  QDomElement dataSource = document.createElement( "datasource" );
451 
452  QString src = source();
453 
454  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
455  // TODO: what about postgres, mysql and others, they should not go through writePath()
456  if ( vlayer && vlayer->providerType() == "spatialite" )
457  {
458  QgsDataSourceURI uri( src );
459  QString database = QgsProject::instance()->writePath( uri.database() );
460  uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
461  src = uri.uri();
462  }
463  else if ( vlayer && vlayer->providerType() == "ogr" )
464  {
465  QStringList theURIParts = src.split( "|" );
466  theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0] );
467  src = theURIParts.join( "|" );
468  }
469  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
470  {
471  QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
472  QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->writePath( urlSource.toLocalFile() ) );
473  urlDest.setQueryItems( urlSource.queryItems() );
474  src = QString::fromAscii( urlDest.toEncoded() );
475  }
476  else
477  {
478  src = QgsProject::instance()->writePath( src );
479  }
480 
481  QDomText dataSourceText = document.createTextNode( src );
482  dataSource.appendChild( dataSourceText );
483 
484  layerElement.appendChild( dataSource );
485 
486 
487  // layer name
488  QDomElement layerName = document.createElement( "layername" );
489  QDomText layerNameText = document.createTextNode( originalName() );
490  layerName.appendChild( layerNameText );
491 
492  // layer title
493  QDomElement layerTitle = document.createElement( "title" ) ;
494  QDomText layerTitleText = document.createTextNode( title() );
495  layerTitle.appendChild( layerTitleText );
496 
497  // layer abstract
498  QDomElement layerAbstract = document.createElement( "abstract" );
499  QDomText layerAbstractText = document.createTextNode( abstract() );
500  layerAbstract.appendChild( layerAbstractText );
501 
502  layerElement.appendChild( layerName );
503  layerElement.appendChild( layerTitle );
504  layerElement.appendChild( layerAbstract );
505 
506  // layer keyword list
507  QStringList keywordStringList = keywordList().split( "," );
508  if ( keywordStringList.size() > 0 )
509  {
510  QDomElement layerKeywordList = document.createElement( "keywordList" );
511  for ( int i = 0; i < keywordStringList.size(); ++i )
512  {
513  QDomElement layerKeywordValue = document.createElement( "value" );
514  QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
515  layerKeywordValue.appendChild( layerKeywordText );
516  layerKeywordList.appendChild( layerKeywordValue );
517  }
518  layerElement.appendChild( layerKeywordList );
519  }
520 
521  // layer metadataUrl
522  QString aDataUrl = dataUrl();
523  if ( !aDataUrl.isEmpty() )
524  {
525  QDomElement layerDataUrl = document.createElement( "dataUrl" ) ;
526  QDomText layerDataUrlText = document.createTextNode( aDataUrl );
527  layerDataUrl.appendChild( layerDataUrlText );
528  layerDataUrl.setAttribute( "format", dataUrlFormat() );
529  layerElement.appendChild( layerDataUrl );
530  }
531 
532  // layer legendUrl
533  QString aLegendUrl = legendUrl();
534  if ( !aLegendUrl.isEmpty() )
535  {
536  QDomElement layerLegendUrl = document.createElement( "legendUrl" ) ;
537  QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
538  layerLegendUrl.appendChild( layerLegendUrlText );
539  layerLegendUrl.setAttribute( "format", legendUrlFormat() );
540  layerElement.appendChild( layerLegendUrl );
541  }
542 
543  // layer attribution
544  QString aAttribution = attribution();
545  if ( !aAttribution.isEmpty() )
546  {
547  QDomElement layerAttribution = document.createElement( "attribution" ) ;
548  QDomText layerAttributionText = document.createTextNode( aAttribution );
549  layerAttribution.appendChild( layerAttributionText );
550  layerAttribution.setAttribute( "href", attributionUrl() );
551  layerElement.appendChild( layerAttribution );
552  }
553 
554  // layer metadataUrl
555  QString aMetadataUrl = metadataUrl();
556  if ( !aMetadataUrl.isEmpty() )
557  {
558  QDomElement layerMetadataUrl = document.createElement( "metadataUrl" ) ;
559  QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
560  layerMetadataUrl.appendChild( layerMetadataUrlText );
561  layerMetadataUrl.setAttribute( "type", metadataUrlType() );
562  layerMetadataUrl.setAttribute( "format", metadataUrlFormat() );
563  layerElement.appendChild( layerMetadataUrl );
564  }
565 
566  // timestamp if supported
567  if ( timestamp() > QDateTime() )
568  {
569  QDomElement stamp = document.createElement( "timestamp" );
570  QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
571  stamp.appendChild( stampText );
572  layerElement.appendChild( stamp );
573  }
574 
575  layerElement.appendChild( layerName );
576 
577  // zorder
578  // This is no longer stored in the project file. It is superfluous since the layers
579  // are written and read in the proper order.
580 
581  // spatial reference system id
582  QDomElement mySrsElement = document.createElement( "srs" );
583  mCRS->writeXML( mySrsElement, document );
584  layerElement.appendChild( mySrsElement );
585 
586 #if 0
587  // <transparencyLevelInt>
588  QDomElement transparencyLevelIntElement = document.createElement( "transparencyLevelInt" );
589  QDomText transparencyLevelIntText = document.createTextNode( QString::number( getTransparency() ) );
590  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
591  maplayer.appendChild( transparencyLevelIntElement );
592 #endif
593 
594  // now append layer node to map layer node
595 
596  writeCustomProperties( layerElement, document );
597 
598  return writeXml( layerElement, document );
599 
600 } // bool QgsMapLayer::writeXML
601 
602 QDomDocument QgsMapLayer::asLayerDefinition( QList<QgsMapLayer *> layers )
603 {
604  QDomDocument doc( "qgis-layer-definition" );
605  QDomElement layerselm = doc.createElement( "maplayers" );
606  foreach ( QgsMapLayer* layer, layers )
607  {
608  QDomElement layerelm = doc.createElement( "maplayer" );
609  layer->writeLayerXML( layerelm, doc );
610  layerelm.removeChild( layerelm.firstChildElement( "id" ) );
611  layerselm.appendChild( layerelm );
612  }
613  doc.appendChild( layerselm );
614  return doc;
615 }
616 
617 QList<QgsMapLayer*> QgsMapLayer::fromLayerDefinition( QDomDocument& document )
618 {
619  QList<QgsMapLayer*> layers;
620  QDomNodeList layernodes = document.elementsByTagName( "maplayer" );
621  for ( int i = 0; i < layernodes.size(); ++i )
622  {
623  QDomNode layernode = layernodes.at( i );
624  QDomElement layerElem = layernode.toElement();
625 
626  QString type = layerElem.attribute( "type" );
627  QgsDebugMsg( type );
628  QgsMapLayer *layer = NULL;
629 
630  if ( type == "vector" )
631  {
632  layer = new QgsVectorLayer;
633  }
634  else if ( type == "raster" )
635  {
636  layer = new QgsRasterLayer;
637  }
638  else if ( type == "plugin" )
639  {
640  QString typeName = layerElem.attribute( "name" );
641  layer = QgsPluginLayerRegistry::instance()->createLayer( typeName );
642  }
643 
644  bool ok = layer->readLayerXML( layerElem );
645  if ( ok )
646  layers << layer;
647  }
648  return layers;
649 }
650 
651 QList<QgsMapLayer *> QgsMapLayer::fromLayerDefinitionFile( const QString qlrfile )
652 {
653  QFile file( qlrfile );
654  if ( !file.open( QIODevice::ReadOnly ) )
655  {
656  QgsDebugMsg( "Can't open file" );
657  return QList<QgsMapLayer*>();
658  }
659 
660  QDomDocument doc;
661  if ( !doc.setContent( &file ) )
662  {
663  QgsDebugMsg( "Can't set content" );
664  return QList<QgsMapLayer*>();
665  }
666 
667  return QgsMapLayer::fromLayerDefinition( doc );
668 }
669 
670 
671 bool QgsMapLayer::writeXml( QDomNode & layer_node, QDomDocument & document )
672 {
673  Q_UNUSED( layer_node );
674  Q_UNUSED( document );
675  // NOP by default; children will over-ride with behavior specific to them
676 
677  return true;
678 } // void QgsMapLayer::writeXml
679 
680 
681 void QgsMapLayer::readCustomProperties( const QDomNode &layerNode, const QString &keyStartsWith )
682 {
683  mCustomProperties.readXml( layerNode, keyStartsWith );
684 }
685 
686 void QgsMapLayer::writeCustomProperties( QDomNode &layerNode, QDomDocument &doc ) const
687 {
688  mCustomProperties.writeXml( layerNode, doc );
689 }
690 
691 
692 
693 
695 {
696  return mValid;
697 }
698 
699 
701 {
702  QgsDebugMsg( "called" );
703  // TODO: emit a signal - it will be used to update legend
704 }
705 
706 
708 {
709  return QString();
710 }
711 
713 {
714  return QString();
715 }
716 
717 void QgsMapLayer::connectNotify( const char * signal )
718 {
719  Q_UNUSED( signal );
720  QgsDebugMsgLevel( "QgsMapLayer connected to " + QString( signal ), 3 );
721 } // QgsMapLayer::connectNotify
722 
723 
724 
725 void QgsMapLayer::toggleScaleBasedVisibility( bool theVisibilityFlag )
726 {
727  mScaleBasedVisibility = theVisibilityFlag;
728 }
729 
731 {
732  return mScaleBasedVisibility;
733 }
734 
735 void QgsMapLayer::setMinimumScale( float theMinScale )
736 {
737  mMinScale = theMinScale;
738 }
739 
741 {
742  return mMinScale;
743 }
744 
745 
746 void QgsMapLayer::setMaximumScale( float theMaxScale )
747 {
748  mMaxScale = theMaxScale;
749 }
750 
752 {
753  return mMaxScale;
754 }
755 
756 
757 QStringList QgsMapLayer::subLayers() const
758 {
759  return QStringList(); // Empty
760 }
761 
762 void QgsMapLayer::setLayerOrder( const QStringList &layers )
763 {
764  Q_UNUSED( layers );
765  // NOOP
766 }
767 
768 void QgsMapLayer::setSubLayerVisibility( QString name, bool vis )
769 {
770  Q_UNUSED( name );
771  Q_UNUSED( vis );
772  // NOOP
773 }
774 
776 {
777  return *mCRS;
778 }
779 
780 void QgsMapLayer::setCrs( const QgsCoordinateReferenceSystem& srs, bool emitSignal )
781 {
782  *mCRS = srs;
783 
784  if ( !mCRS->isValid() )
785  {
786  mCRS->setValidationHint( tr( "Specify CRS for layer %1" ).arg( name() ) );
787  mCRS->validate();
788  }
789 
790  if ( emitSignal )
791  emit layerCrsChanged();
792 }
793 
794 QString QgsMapLayer::capitaliseLayerName( const QString& name )
795 {
796  // Capitalise the first letter of the layer name if requested
797  QSettings settings;
798  bool capitaliseLayerName =
799  settings.value( "/qgis/capitaliseLayerName", QVariant( false ) ).toBool();
800 
801  QString layerName( name );
802 
803  if ( capitaliseLayerName )
804  layerName = layerName.left( 1 ).toUpper() + layerName.mid( 1 );
805 
806  return layerName;
807 }
808 
810 {
811  QString myURI = publicSource();
812 
813  // if file is using the VSIFILE mechanism, remove the prefix
814  if ( myURI.startsWith( "/vsigzip/", Qt::CaseInsensitive ) )
815  {
816  myURI.remove( 0, 9 );
817  }
818  else if ( myURI.startsWith( "/vsizip/", Qt::CaseInsensitive ) &&
819  myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
820  {
821  // ideally we should look for .qml file inside zip file
822  myURI.remove( 0, 8 );
823  }
824  else if ( myURI.startsWith( "/vsitar/", Qt::CaseInsensitive ) &&
825  ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) ||
826  myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) ||
827  myURI.endsWith( ".tgz", Qt::CaseInsensitive ) ) )
828  {
829  // ideally we should look for .qml file inside tar file
830  myURI.remove( 0, 8 );
831  }
832 
833  QFileInfo myFileInfo( myURI );
834  QString key;
835 
836  if ( myFileInfo.exists() )
837  {
838  // if file is using the /vsizip/ or /vsigzip/ mechanism, cleanup the name
839  if ( myURI.endsWith( ".gz", Qt::CaseInsensitive ) )
840  myURI.chop( 3 );
841  else if ( myURI.endsWith( ".zip", Qt::CaseInsensitive ) )
842  myURI.chop( 4 );
843  else if ( myURI.endsWith( ".tar", Qt::CaseInsensitive ) )
844  myURI.chop( 4 );
845  else if ( myURI.endsWith( ".tar.gz", Qt::CaseInsensitive ) )
846  myURI.chop( 7 );
847  else if ( myURI.endsWith( ".tgz", Qt::CaseInsensitive ) )
848  myURI.chop( 4 );
849  else if ( myURI.endsWith( ".gz", Qt::CaseInsensitive ) )
850  myURI.chop( 3 );
851  myFileInfo.setFile( myURI );
852  // get the file name for our .qml style file
853  key = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
854  }
855  else
856  {
857  key = publicSource();
858  }
859 
860  return key;
861 }
862 
863 QString QgsMapLayer::loadDefaultStyle( bool & theResultFlag )
864 {
865  return loadNamedStyle( styleURI(), theResultFlag );
866 }
867 
868 bool QgsMapLayer::loadNamedStyleFromDb( const QString &db, const QString &theURI, QString &qml )
869 {
870  QgsDebugMsg( QString( "db = %1 uri = %2" ).arg( db ).arg( theURI ) );
871 
872  bool theResultFlag = false;
873 
874  // read from database
875  sqlite3 *myDatabase;
876  sqlite3_stmt *myPreparedStatement;
877  const char *myTail;
878  int myResult;
879 
880  QgsDebugMsg( QString( "Trying to load style for \"%1\" from \"%2\"" ).arg( theURI ).arg( db ) );
881 
882  if ( !QFile( db ).exists() )
883  return false;
884 
885  myResult = sqlite3_open_v2( db.toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, NULL );
886  if ( myResult != SQLITE_OK )
887  {
888  return false;
889  }
890 
891  QString mySql = "select qml from tbl_styles where style=?";
892  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
893  if ( myResult == SQLITE_OK )
894  {
895  QByteArray param = theURI.toUtf8();
896 
897  if ( sqlite3_bind_text( myPreparedStatement, 1, param.data(), param.length(), SQLITE_STATIC ) == SQLITE_OK &&
898  sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
899  {
900  qml = QString::fromUtf8(( char * )sqlite3_column_text( myPreparedStatement, 0 ) );
901  theResultFlag = true;
902  }
903 
904  sqlite3_finalize( myPreparedStatement );
905  }
906 
907  sqlite3_close( myDatabase );
908 
909  return theResultFlag;
910 }
911 
912 QString QgsMapLayer::loadNamedStyle( const QString &theURI, bool &theResultFlag )
913 {
914  QgsDebugMsg( QString( "uri = %1 myURI = %2" ).arg( theURI ).arg( publicSource() ) );
915 
916  theResultFlag = false;
917 
918  QDomDocument myDocument( "qgis" );
919 
920  // location of problem associated with errorMsg
921  int line, column;
922  QString myErrorMessage;
923 
924  QFile myFile( theURI );
925  if ( myFile.open( QFile::ReadOnly ) )
926  {
927  // read file
928  theResultFlag = myDocument.setContent( &myFile, &myErrorMessage, &line, &column );
929  if ( !theResultFlag )
930  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
931  myFile.close();
932  }
933  else
934  {
935  QFileInfo project( QgsProject::instance()->fileName() );
936  QgsDebugMsg( QString( "project fileName: %1" ).arg( project.absoluteFilePath() ) );
937 
938  QString qml;
939  if ( loadNamedStyleFromDb( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ), theURI, qml ) ||
940  ( project.exists() && loadNamedStyleFromDb( project.absoluteDir().absoluteFilePath( project.baseName() + ".qmldb" ), theURI, qml ) ) ||
941  loadNamedStyleFromDb( QDir( QgsApplication::pkgDataPath() ).absoluteFilePath( "resources/qgis.qmldb" ), theURI, qml ) )
942  {
943  theResultFlag = myDocument.setContent( qml, &myErrorMessage, &line, &column );
944  if ( !theResultFlag )
945  {
946  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
947  }
948  }
949  else
950  {
951  myErrorMessage = tr( "Style not found in database" );
952  }
953  }
954 
955  if ( !theResultFlag )
956  {
957  return myErrorMessage;
958  }
959 
960  // get style file version string, if any
961  QgsProjectVersion fileVersion( myDocument.firstChildElement( "qgis" ).attribute( "version" ) );
962  QgsProjectVersion thisVersion( QGis::QGIS_VERSION );
963 
964  if ( thisVersion > fileVersion )
965  {
966  QgsLogger::warning( "Loading a style file that was saved with an older "
967  "version of qgis (saved in " + fileVersion.text() +
968  ", loaded in " + QGis::QGIS_VERSION +
969  "). Problems may occur." );
970 
971  QgsProjectFileTransform styleFile( myDocument, fileVersion );
972  // styleFile.dump();
973  styleFile.updateRevision( thisVersion );
974  // styleFile.dump();
975  }
976 
977  // now get the layer node out and pass it over to the layer
978  // to deserialise...
979  QDomElement myRoot = myDocument.firstChildElement( "qgis" );
980  if ( myRoot.isNull() )
981  {
982  myErrorMessage = tr( "Error: qgis element could not be found in %1" ).arg( theURI );
983  theResultFlag = false;
984  return myErrorMessage;
985  }
986 
987  // use scale dependent visibility flag
988  toggleScaleBasedVisibility( myRoot.attribute( "hasScaleBasedVisibilityFlag" ).toInt() == 1 );
989  setMinimumScale( myRoot.attribute( "minimumScale" ).toFloat() );
990  setMaximumScale( myRoot.attribute( "maximumScale" ).toFloat() );
991 
992 #if 0
993  //read transparency level
994  QDomNode transparencyNode = myRoot.namedItem( "transparencyLevelInt" );
995  if ( ! transparencyNode.isNull() )
996  {
997  // set transparency level only if it's in project
998  // (otherwise it sets the layer transparent)
999  QDomElement myElement = transparencyNode.toElement();
1000  setTransparency( myElement.text().toInt() );
1001  }
1002 #endif
1003 
1004  QString errorMsg;
1005  theResultFlag = readSymbology( myRoot, errorMsg );
1006  if ( !theResultFlag )
1007  {
1008  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( theURI ).arg( errorMsg );
1009  return myErrorMessage;
1010  }
1011 
1012  return "";
1013 }
1014 
1015 void QgsMapLayer::exportNamedStyle( QDomDocument &doc, QString &errorMsg )
1016 {
1017  QDomImplementation DomImplementation;
1018  QDomDocumentType documentType = DomImplementation.createDocumentType( "qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
1019  QDomDocument myDocument( documentType );
1020 
1021  QDomElement myRootNode = myDocument.createElement( "qgis" );
1022  myRootNode.setAttribute( "version", QString( "%1" ).arg( QGis::QGIS_VERSION ) );
1023  myDocument.appendChild( myRootNode );
1024 
1025  myRootNode.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
1026  myRootNode.setAttribute( "minimumScale", QString::number( minimumScale() ) );
1027  myRootNode.setAttribute( "maximumScale", QString::number( maximumScale() ) );
1028 
1029 #if 0
1030  // <transparencyLevelInt>
1031  QDomElement transparencyLevelIntElement = myDocument.createElement( "transparencyLevelInt" );
1032  QDomText transparencyLevelIntText = myDocument.createTextNode( QString::number( getTransparency() ) );
1033  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
1034  myRootNode.appendChild( transparencyLevelIntElement );
1035 #endif
1036 
1037  if ( !writeSymbology( myRootNode, myDocument, errorMsg ) )
1038  {
1039  errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1040  return;
1041  }
1042  doc = myDocument;
1043 }
1044 
1045 QString QgsMapLayer::saveDefaultStyle( bool & theResultFlag )
1046 {
1047  return saveNamedStyle( styleURI(), theResultFlag );
1048 }
1049 
1050 QString QgsMapLayer::saveNamedStyle( const QString &theURI, bool &theResultFlag )
1051 {
1052  QString myErrorMessage;
1053  QDomDocument myDocument;
1054  exportNamedStyle( myDocument, myErrorMessage );
1055 
1056  // check if the uri is a file or ends with .qml,
1057  // which indicates that it should become one
1058  // everything else goes to the database
1059  QString filename;
1060 
1061  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1062  if ( vlayer && vlayer->providerType() == "ogr" )
1063  {
1064  QStringList theURIParts = theURI.split( "|" );
1065  filename = theURIParts[0];
1066  }
1067  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
1068  {
1069  filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1070  }
1071  else
1072  {
1073  filename = theURI;
1074  }
1075 
1076  QFileInfo myFileInfo( filename );
1077  if ( myFileInfo.exists() || filename.endsWith( ".qml", Qt::CaseInsensitive ) )
1078  {
1079  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1080  if ( !myDirInfo.isWritable() )
1081  {
1082  return tr( "The directory containing your dataset needs to be writable!" );
1083  }
1084 
1085  // now construct the file name for our .qml style file
1086  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";
1087 
1088  QFile myFile( myFileName );
1089  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1090  {
1091  QTextStream myFileStream( &myFile );
1092  // save as utf-8 with 2 spaces for indents
1093  myDocument.save( myFileStream, 2 );
1094  myFile.close();
1095  theResultFlag = true;
1096  return tr( "Created default style file as %1" ).arg( myFileName );
1097  }
1098  else
1099  {
1100  theResultFlag = false;
1101  return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
1102  }
1103  }
1104  else
1105  {
1106  QString qml = myDocument.toString();
1107 
1108  // read from database
1109  sqlite3 *myDatabase;
1110  sqlite3_stmt *myPreparedStatement;
1111  const char *myTail;
1112  int myResult;
1113 
1114  myResult = sqlite3_open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ).toUtf8().data(), &myDatabase );
1115  if ( myResult != SQLITE_OK )
1116  {
1117  return tr( "User database could not be opened." );
1118  }
1119 
1120  QByteArray param0 = theURI.toUtf8();
1121  QByteArray param1 = qml.toUtf8();
1122 
1123  QString mySql = "create table if not exists tbl_styles(style varchar primary key,qml varchar)";
1124  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1125  if ( myResult == SQLITE_OK )
1126  {
1127  if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
1128  {
1129  sqlite3_finalize( myPreparedStatement );
1130  sqlite3_close( myDatabase );
1131  theResultFlag = false;
1132  return tr( "The style table could not be created." );
1133  }
1134  }
1135 
1136  sqlite3_finalize( myPreparedStatement );
1137 
1138  mySql = "insert into tbl_styles(style,qml) values (?,?)";
1139  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1140  if ( myResult == SQLITE_OK )
1141  {
1142  if ( sqlite3_bind_text( myPreparedStatement, 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1143  sqlite3_bind_text( myPreparedStatement, 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1144  sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1145  {
1146  theResultFlag = true;
1147  myErrorMessage = tr( "The style %1 was saved to database" ).arg( theURI );
1148  }
1149  }
1150 
1151  sqlite3_finalize( myPreparedStatement );
1152 
1153  if ( !theResultFlag )
1154  {
1155  QString mySql = "update tbl_styles set qml=? where style=?";
1156  myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
1157  if ( myResult == SQLITE_OK )
1158  {
1159  if ( sqlite3_bind_text( myPreparedStatement, 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
1160  sqlite3_bind_text( myPreparedStatement, 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
1161  sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
1162  {
1163  theResultFlag = true;
1164  myErrorMessage = tr( "The style %1 was updated in the database." ).arg( theURI );
1165  }
1166  else
1167  {
1168  theResultFlag = false;
1169  myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( theURI );
1170  }
1171  }
1172  else
1173  {
1174  theResultFlag = false;
1175  myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( theURI );
1176  }
1177 
1178  sqlite3_finalize( myPreparedStatement );
1179  }
1180 
1181  sqlite3_close( myDatabase );
1182  }
1183 
1184  return myErrorMessage;
1185 }
1186 
1187 void QgsMapLayer::exportSldStyle( QDomDocument &doc, QString &errorMsg )
1188 {
1189  QDomDocument myDocument = QDomDocument();
1190 
1191  QDomNode header = myDocument.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" );
1192  myDocument.appendChild( header );
1193 
1194  // Create the root element
1195  QDomElement root = myDocument.createElementNS( "http://www.opengis.net/sld", "StyledLayerDescriptor" );
1196  root.setAttribute( "version", "1.1.0" );
1197  root.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" );
1198  root.setAttribute( "xmlns:ogc", "http://www.opengis.net/ogc" );
1199  root.setAttribute( "xmlns:se", "http://www.opengis.net/se" );
1200  root.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
1201  root.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
1202  myDocument.appendChild( root );
1203 
1204  // Create the NamedLayer element
1205  QDomElement namedLayerNode = myDocument.createElement( "NamedLayer" );
1206  root.appendChild( namedLayerNode );
1207 
1208  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1209  if ( !vlayer )
1210  {
1211  errorMsg = tr( "Could not save symbology because:\n%1" )
1212  .arg( "Non-vector layers not supported yet" );
1213  return;
1214  }
1215 
1216  if ( !vlayer->writeSld( namedLayerNode, myDocument, errorMsg ) )
1217  {
1218  errorMsg = tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
1219  return;
1220  }
1221 
1222  doc = myDocument;
1223 }
1224 
1225 QString QgsMapLayer::saveSldStyle( const QString &theURI, bool &theResultFlag )
1226 {
1227  QString errorMsg;
1228  QDomDocument myDocument;
1229  exportSldStyle( myDocument, errorMsg );
1230  if ( !errorMsg.isNull() )
1231  {
1232  theResultFlag = false;
1233  return errorMsg;
1234  }
1235  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
1236 
1237  // check if the uri is a file or ends with .sld,
1238  // which indicates that it should become one
1239  QString filename;
1240  if ( vlayer->providerType() == "ogr" )
1241  {
1242  QStringList theURIParts = theURI.split( "|" );
1243  filename = theURIParts[0];
1244  }
1245  else if ( vlayer->providerType() == "delimitedtext" )
1246  {
1247  filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
1248  }
1249  else
1250  {
1251  filename = theURI;
1252  }
1253 
1254  QFileInfo myFileInfo( filename );
1255  if ( myFileInfo.exists() || filename.endsWith( ".sld", Qt::CaseInsensitive ) )
1256  {
1257  QFileInfo myDirInfo( myFileInfo.path() ); //excludes file name
1258  if ( !myDirInfo.isWritable() )
1259  {
1260  return tr( "The directory containing your dataset needs to be writable!" );
1261  }
1262 
1263  // now construct the file name for our .sld style file
1264  QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".sld";
1265 
1266  QFile myFile( myFileName );
1267  if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
1268  {
1269  QTextStream myFileStream( &myFile );
1270  // save as utf-8 with 2 spaces for indents
1271  myDocument.save( myFileStream, 2 );
1272  myFile.close();
1273  theResultFlag = true;
1274  return tr( "Created default style file as %1" ).arg( myFileName );
1275  }
1276  }
1277 
1278  theResultFlag = false;
1279  return tr( "ERROR: Failed to created SLD style file as %1. Check file permissions and retry." ).arg( filename );
1280 }
1281 
1282 QString QgsMapLayer::loadSldStyle( const QString &theURI, bool &theResultFlag )
1283 {
1284  QgsDebugMsg( "Entered." );
1285 
1286  theResultFlag = false;
1287 
1288  QDomDocument myDocument;
1289 
1290  // location of problem associated with errorMsg
1291  int line, column;
1292  QString myErrorMessage;
1293 
1294  QFile myFile( theURI );
1295  if ( myFile.open( QFile::ReadOnly ) )
1296  {
1297  // read file
1298  theResultFlag = myDocument.setContent( &myFile, true, &myErrorMessage, &line, &column );
1299  if ( !theResultFlag )
1300  myErrorMessage = tr( "%1 at line %2 column %3" ).arg( myErrorMessage ).arg( line ).arg( column );
1301  myFile.close();
1302  }
1303  else
1304  {
1305  myErrorMessage = tr( "Unable to open file %1" ).arg( theURI );
1306  }
1307 
1308  if ( !theResultFlag )
1309  {
1310  return myErrorMessage;
1311  }
1312 
1313  // check for root SLD element
1314  QDomElement myRoot = myDocument.firstChildElement( "StyledLayerDescriptor" );
1315  if ( myRoot.isNull() )
1316  {
1317  myErrorMessage = QString( "Error: StyledLayerDescriptor element not found in %1" ).arg( theURI );
1318  theResultFlag = false;
1319  return myErrorMessage;
1320  }
1321 
1322  // now get the style node out and pass it over to the layer
1323  // to deserialise...
1324  QDomElement namedLayerElem = myRoot.firstChildElement( "NamedLayer" );
1325  if ( namedLayerElem.isNull() )
1326  {
1327  myErrorMessage = QString( "Info: NamedLayer element not found." );
1328  theResultFlag = false;
1329  return myErrorMessage;
1330  }
1331 
1332  QString errorMsg;
1333  theResultFlag = readSld( namedLayerElem, errorMsg );
1334  if ( !theResultFlag )
1335  {
1336  myErrorMessage = tr( "Loading style file %1 failed because:\n%2" ).arg( theURI ).arg( errorMsg );
1337  return myErrorMessage;
1338  }
1339 
1340  return "";
1341 }
1342 
1343 
1345 {
1346  return &mUndoStack;
1347 }
1348 
1349 
1350 void QgsMapLayer::setCustomProperty( const QString& key, const QVariant& value )
1351 {
1352  mCustomProperties.setValue( key, value );
1353 }
1354 
1355 QVariant QgsMapLayer::customProperty( const QString& value, const QVariant& defaultValue ) const
1356 {
1357  return mCustomProperties.value( value, defaultValue );
1358 }
1359 
1360 void QgsMapLayer::removeCustomProperty( const QString& key )
1361 {
1362  mCustomProperties.remove( key );
1363 }
1364 
1365 
1366 
1368 {
1369  return false;
1370 }
1371 
1372 void QgsMapLayer::setValid( bool valid )
1373 {
1374  mValid = valid;
1375 }
1376 
1378 {
1379  emit repaintRequested();
1380 }
1381 
1383 {
1384  if ( legend == mLegend )
1385  return;
1386 
1387  delete mLegend;
1388  mLegend = legend;
1389 
1390  if ( mLegend )
1391  connect( mLegend, SIGNAL( itemsChanged() ), this, SIGNAL( legendChanged() ) );
1392 
1393  emit legendChanged();
1394 }
1395 
1397 {
1398  return mLegend;
1399 }
1400 
1402 {
1403  emit repaintRequested();
1404 }
1405 
1407 {
1408  return QString();
1409 }
1410 
1412 {
1413  mExtent = r;
1414 }
static const char * QGIS_VERSION
Definition: qgis.h:40
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.
static const QString pkgDataPath()
Returns the common root path of all application data directories.
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
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:48
QString mID
Unique ID of this layer - used to refer to this layer in map layer registry.
Definition: qgsmaplayer.h:557
QgsPluginLayer * createLayer(QString typeName)
return new layer if corresponding plugin has been found, else return NULL
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:89
virtual QString metadata()
Obtain Metadata for this layer.
virtual void drawLabels(QgsRenderContext &rendererContext)
Draw labels.
virtual QString loadSldStyle(const QString &theURI, bool &theResultFlag)
QString mAttributionUrl
Definition: qgsmaplayer.h:531
QString mKeywordList
Definition: qgsmaplayer.h:523
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith="")
Read custom properties from project file.
QString publicSource() const
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from XML.
virtual ~QgsMapLayer()
Destructor.
Definition: qgsmaplayer.cpp:83
QString mDataUrlFormat
Definition: qgsmaplayer.h:527
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
static QString removePassword(const QString &aUri)
Removes password element from uris.
virtual Q_DECL_DEPRECATED QString lastError()
const QString & originalName() const
Get the original name of the layer.
Definition: qgsmaplayer.h:94
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:162
QString password() const
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:540
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
bool mScaleBasedVisibility
A flag that tells us whether to use the above vars to restrict layer visibility.
Definition: qgsmaplayer.h:573
float minimumScale() const
void blendModeChanged(const QPainter::CompositionMode &blendMode)
Signal emitted when the blend mode is changed, through QgsMapLayer::setBlendMode() ...
const QString & attribution() const
Definition: qgsmaplayer.h:113
static CUSTOM_CRS_VALIDATION customSrsValidation()
Gets custom function.
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 ...
QUndoStack mUndoStack
Collection of undoable operations for this layer.
Definition: qgsmaplayer.h:576
static const QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
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.
void setBlendMode(const QPainter::CompositionMode &blendMode)
Write blend mode for layer.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:512
void setMaximumScale(float theMaxScale)
Accessor and mutator for the maximum scale denominator member.
virtual bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage) const =0
Write the symbology for the layer into the docment provided.
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.
const QString & legendUrl() const
Definition: qgsmaplayer.h:375
static QString capitaliseLayerName(const QString &name)
A convenience function to (un)capitalise the layer name.
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SSLmode sslmode=SSLprefer)
Set all connection related members at once.
const QString & name() const
Get the display name of the layer.
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.
QgsRectangle mExtent
Extent of the layer.
Definition: qgsmaplayer.h:503
QPainter::CompositionMode mBlendMode
Blend mode for the layer.
Definition: qgsmaplayer.h:563
QString mMetadataUrl
MetadataUrl of the layer.
Definition: qgsmaplayer.h:534
QPainter::CompositionMode blendMode() const
Read blend mode for layer.
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
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage) const
void layerCrsChanged()
Emit a signal that layer's CRS has been reset added in 1.4.
const QString & dataUrl() const
Definition: qgsmaplayer.h:107
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...
QString uri() const
return complete uri
bool writeLayerXML(QDomElement &layerElement, QDomDocument &document)
stores state in Dom node
const QString & metadataUrlType() const
Definition: qgsmaplayer.h:121
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
Q_DECL_DEPRECATED void setCacheImage(QImage *)
const QString & source() const
Returns the source for the layer.
LayerType
Layers enum defining the types of layers that can be added to a map.
Definition: qgsmaplayer.h:54
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
A class to describe the version of a project.
float maximumScale() const
virtual void setExtent(const QgsRectangle &rect)
Set the extent.
QgsObjectCustomProperties mCustomProperties
Layer's persistent storage of additional properties (may be used by plugins)
Definition: qgsmaplayer.h:579
QString mDataUrl
DataUrl of the layer.
Definition: qgsmaplayer.h:526
const QString & metadataUrl() const
Definition: qgsmaplayer.h:119
The QgsMapLayerLegend class is abstract interface for implementations of legends for one map layer...
QString writePath(QString filename) const
prepare a filename to save it to the project file
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:95
virtual void setSubLayerVisibility(QString name, bool vis)
Set the visibility of the given sublayer name.
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
virtual Q_DECL_DEPRECATED QString lastErrorTitle()
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
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()
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:506
QString host() const
QString mTitle
Definition: qgsmaplayer.h:519
virtual bool readSld(const QDomNode &node, QString &errorMessage)
Definition: qgsmaplayer.h:351
QString mMetadataUrlFormat
Definition: qgsmaplayer.h:536
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
struct sqlite3 sqlite3
QString mAttribution
Attribution of the layer.
Definition: qgsmaplayer.h:530
QString mAbstract
Description of the layer.
Definition: qgsmaplayer.h:522
QgsMapLayerLegend * legend() const
QString file
Definition: qgssvgcache.cpp:76
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as named style in a QDomDocument.
QString providerType() const
Return the provider type for this layer.
static QList< QgsMapLayer * > fromLayerDefinitionFile(const QString qlrfile)
void connectNotify(const char *signal)
debugging member - invoked when a connect() is made to this object
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
Contains information about the context of a rendering operation.
Q_DECL_DEPRECATED void clearCacheImage()
Clear cached image.
QString mDataSource
data source description string, varies by layer type
Definition: qgsmaplayer.h:509
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.
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:362
virtual bool readXml(const QDomNode &layer_node)
called by readLayerXML(), used by children to read state specific to them from project files...
float mMaxScale
Maximum scale denominator at which this layer should be displayed.
Definition: qgsmaplayer.h:571
QString mLegendUrl
WMS legend.
Definition: qgsmaplayer.h:539
Class for storing a coordinate reference system (CRS)
void legendChanged()
Signal emitted when legend of the layer has changed.
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's spatial reference system.
static QDomDocument asLayerDefinition(QList< QgsMapLayer * > layers)
Returns the given layer as a layer definition document Layer definitions store the data source as wel...
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)
QgsMapLayer::LayerType mLayerType
Type of the layer (eg.
Definition: qgsmaplayer.h:560
QgsCoordinateReferenceSystem * mCRS
layer's spatial reference system.
Definition: qgsmaplayer.h:548
static QList< QgsMapLayer * > fromLayerDefinition(QDomDocument &document)
Creates a new layer from a layer defininition document.
static QgsPluginLayerRegistry * instance()
means of accessing canonical single instance
QUndoStack * undoStack()
Return pointer to layer'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:422
const QString & attributionUrl() const
Definition: qgsmaplayer.h:115
void(* CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem &)
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
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...
const QString & metadataUrlFormat() const
Definition: qgsmaplayer.h:123
const QString & legendUrlFormat() const
Definition: qgsmaplayer.h:377
virtual QgsRectangle extent()
Return the extent of the layer.
Represents a vector layer which manages a vector based data sets.
QgsMapLayerLegend * mLegend
Controller of legend items of this layer.
Definition: qgsmaplayer.h:582
virtual void setLayerOrder(const QStringList &layers)
Reorders the previously selected sublayers of this layer from bottom to top (Useful for providers tha...
const QString & title() const
Definition: qgsmaplayer.h:97
QString mLayerOrigName
Original name of the layer.
Definition: qgsmaplayer.h:517
void setValid(bool valid)
set whether layer is valid or not - should be used in constructor.
QString username() const
QString mMetadataUrlType
Definition: qgsmaplayer.h:535
const QString & keywordList() const
Definition: qgsmaplayer.h:103
float mMinScale
Minimum scale denominator at which this layer should be displayed.
Definition: qgsmaplayer.h:569
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg)
Export the properties of this layer as SLD style in a QDomDocument.
QString port() const
const QString & dataUrlFormat() const
Definition: qgsmaplayer.h:109
void toggleScaleBasedVisibility(bool theVisibilityFlag)
Accessor and mutator for the scale based visilibility flag.
QgsMapLayer(QgsMapLayer::LayerType type=VectorLayer, QString lyrname=QString::null, QString source=QString::null)
Constructor.
Definition: qgsmaplayer.cpp:48
void setMinimumScale(float theMinScale)
Accessor and mutator for the minimum scale denominator member.
#define tr(sourceText)