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