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