QGIS API Documentation  2.99.0-Master (5753576)
qgsprojectfiletransform.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprojectfiletransform.cpp - description
3  -------------------
4  begin : Sun 15 dec 2007
5  copyright : (C) 2007 by Magnus Homann
6  email : magnus at homann.se
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 
20 #include "qgsprojectversion.h"
21 #include "qgslogger.h"
22 #include "qgsrasterlayer.h"
23 #include "qgsvectordataprovider.h"
24 #include "qgsvectorlayer.h"
25 #include <QTextStream>
26 #include <QDomDocument>
27 #include <QPrinter> //to find out screen resolution
28 #include <cstdlib>
29 #include "qgsproject.h"
30 #include "qgsprojectproperty.h"
31 #include "qgsrasterbandstats.h"
32 #include "qgsrasterdataprovider.h"
33 #include "qgsxmlutils.h"
34 
36 
37 
38 QgsProjectFileTransform::TransformItem QgsProjectFileTransform::sTransformers[] =
39 {
40  {PFV( 0, 8, 0 ), PFV( 0, 8, 1 ), &QgsProjectFileTransform::transformNull},
41  {PFV( 0, 8, 1 ), PFV( 0, 9, 0 ), &QgsProjectFileTransform::transform081to090},
42  {PFV( 0, 9, 0 ), PFV( 0, 9, 1 ), &QgsProjectFileTransform::transformNull},
43  {PFV( 0, 9, 1 ), PFV( 0, 10, 0 ), &QgsProjectFileTransform::transform091to0100},
44  // Following line is a hack that takes us straight from 0.9.2 to 0.11.0
45  // due to an unknown bug in migrating 0.9.2 files which we didn't pursue (TS & GS)
46  {PFV( 0, 9, 2 ), PFV( 0, 11, 0 ), &QgsProjectFileTransform::transformNull},
47  {PFV( 0, 10, 0 ), PFV( 0, 11, 0 ), &QgsProjectFileTransform::transform0100to0110},
48  {PFV( 0, 11, 0 ), PFV( 1, 0, 0 ), &QgsProjectFileTransform::transform0110to1000},
49  {PFV( 1, 0, 0 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull},
50  {PFV( 1, 0, 2 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull},
51  {PFV( 1, 1, 0 ), PFV( 1, 2, 0 ), &QgsProjectFileTransform::transform1100to1200},
52  {PFV( 1, 2, 0 ), PFV( 1, 3, 0 ), &QgsProjectFileTransform::transformNull},
53  {PFV( 1, 3, 0 ), PFV( 1, 4, 0 ), &QgsProjectFileTransform::transformNull},
54  {PFV( 1, 4, 0 ), PFV( 1, 5, 0 ), &QgsProjectFileTransform::transform1400to1500},
55  {PFV( 1, 5, 0 ), PFV( 1, 6, 0 ), &QgsProjectFileTransform::transformNull},
56  {PFV( 1, 6, 0 ), PFV( 1, 7, 0 ), &QgsProjectFileTransform::transformNull},
57  {PFV( 1, 7, 0 ), PFV( 1, 8, 0 ), &QgsProjectFileTransform::transformNull},
58  {PFV( 1, 8, 0 ), PFV( 1, 9, 0 ), &QgsProjectFileTransform::transform1800to1900},
59  {PFV( 1, 9, 0 ), PFV( 2, 0, 0 ), &QgsProjectFileTransform::transformNull},
60  {PFV( 2, 0, 0 ), PFV( 2, 1, 0 ), &QgsProjectFileTransform::transformNull},
61  {PFV( 2, 1, 0 ), PFV( 2, 2, 0 ), &QgsProjectFileTransform::transformNull},
62  {PFV( 2, 2, 0 ), PFV( 2, 3, 0 ), &QgsProjectFileTransform::transform2200to2300},
63  // A transformer with a NULL from version means that it should be run when upgrading
64  // from any version and will take care that it's not going to cause trouble if it's
65  // run several times on the same file.
66  {PFV(), PFV( 2, 99, 0 ), &QgsProjectFileTransform::transform2990},
67 };
68 
70 {
71  Q_UNUSED( newVersion );
72  bool returnValue = false;
73 
74  if ( !mDom.isNull() )
75  {
76  for ( std::size_t i = 0; i < sizeof( sTransformers ) / sizeof( TransformItem ); i++ )
77  {
78  const TransformItem& transformer = sTransformers[i];
79  if ( transformer.from == mCurrentVersion || transformer.from.isNull() )
80  {
81  // Run the transformer, and update the revision in every case
82  ( this->*( transformer.transformFunc ) )();
83  mCurrentVersion = transformer.to;
84  returnValue = true;
85  }
86  }
87  }
88  return returnValue;
89 }
90 
92 {
93  QgsDebugMsg( QString( "Current project file version is %1.%2.%3" )
94  .arg( mCurrentVersion.majorVersion() )
95  .arg( mCurrentVersion.minorVersion() )
96  .arg( mCurrentVersion.subVersion() ) );
97 #ifdef QGISDEBUG
98  // Using QgsDebugMsg() didn't print the entire mDom...
99  std::cout << mDom.toString( 2 ).toLatin1().constData(); // OK
100 #endif
101 }
102 
103 /*
104  * Transformers below!
105  */
106 
107 void QgsProjectFileTransform::transform081to090()
108 {
109  QgsDebugMsg( "Entering..." );
110  if ( ! mDom.isNull() )
111  {
112  // Start with inserting a mapcanvas element and populate it
113 
114  QDomElement mapCanvas; // A null element.
115 
116  // there should only be one <qgis>
117  QDomNode qgis = mDom.firstChildElement( QStringLiteral( "qgis" ) );
118  if ( ! qgis.isNull() )
119  {
120  QgsDebugMsg( "Populating new mapcanvas" );
121 
122  // Create a mapcanvas
123  mapCanvas = mDom.createElement( QStringLiteral( "mapcanvas" ) );
124  // Append mapcanvas to parent 'qgis'.
125  qgis.appendChild( mapCanvas );
126  // Re-parent units
127  mapCanvas.appendChild( qgis.namedItem( QStringLiteral( "units" ) ) );
128  // Re-parent extent
129  mapCanvas.appendChild( qgis.namedItem( QStringLiteral( "extent" ) ) );
130 
131  // See if we can find if projection is on.
132 
133  QDomElement properties = qgis.firstChildElement( QStringLiteral( "properties" ) );
134  QDomElement spatial = properties.firstChildElement( QStringLiteral( "SpatialRefSys" ) );
135  QDomElement hasCrsTransformEnabled = spatial.firstChildElement( QStringLiteral( "ProjectionsEnabled" ) );
136  // Type is 'int', and '1' if on.
137  // Create an element
138  QDomElement projection = mDom.createElement( QStringLiteral( "projections" ) );
139  QgsDebugMsg( QString( "Projection flag: " ) + hasCrsTransformEnabled.text() );
140  // Set flag from ProjectionsEnabled
141  projection.appendChild( mDom.createTextNode( hasCrsTransformEnabled.text() ) );
142  // Set new element as child of <mapcanvas>
143  mapCanvas.appendChild( projection );
144 
145  }
146 
147 
148  // Transforming coordinate-transforms
149  // Create a list of all map layers
150  QDomNodeList mapLayers = mDom.elementsByTagName( QStringLiteral( "maplayer" ) );
151  bool doneDestination = false;
152  for ( int i = 0; i < mapLayers.count(); i++ )
153  {
154  QDomNode mapLayer = mapLayers.item( i );
155  // Find the coordinatetransform
156  QDomNode coordinateTransform = mapLayer.namedItem( QStringLiteral( "coordinatetransform" ) );
157  // Find the sourcesrs
158  QDomNode sourceCrs = coordinateTransform.namedItem( QStringLiteral( "sourcesrs" ) );
159  // Rename to srs
160  sourceCrs.toElement().setTagName( QStringLiteral( "srs" ) );
161  // Re-parent to maplayer
162  mapLayer.appendChild( sourceCrs );
163  // Re-move coordinatetransform
164  // Take the destination CRS of the first layer and use for mapcanvas projection
165  if ( ! doneDestination )
166  {
167  // Use destination CRS from the last layer
168  QDomNode destinationCRS = coordinateTransform.namedItem( QStringLiteral( "destinationsrs" ) );
169  // Re-parent the destination CRS to the mapcanvas
170  // If mapcanvas wasn't set, nothing will happen.
171  mapCanvas.appendChild( destinationCRS );
172  // Only do this once
173  doneDestination = true;
174  }
175  mapLayer.removeChild( coordinateTransform );
176  //QDomNode id = mapLayer.namedItem("id");
177  //QgsDebugMsg(QString("Found maplayer ") + id.toElement().text());
178 
179  }
180 
181  // Set the flag 'visible' to match the status of 'checked'
182  QDomNodeList legendLayerFiles = mDom.elementsByTagName( QStringLiteral( "legendlayerfile" ) );
183  QgsDebugMsg( QString( "Legend layer file entries: " ) + QString::number( legendLayerFiles.count() ) );
184  for ( int i = 0; i < mapLayers.count(); i++ )
185  {
186  // Get one maplayer element from list
187  QDomElement mapLayer = mapLayers.item( i ).toElement();
188  // Find it's id.
189  QString id = mapLayer.firstChildElement( QStringLiteral( "id" ) ).text();
190  QgsDebugMsg( QString( "Handling layer " + id ) );
191  // Now, look it up in legend
192  for ( int j = 0; j < legendLayerFiles.count(); j++ )
193  {
194  QDomElement legendLayerFile = legendLayerFiles.item( j ).toElement();
195  if ( id == legendLayerFile.attribute( QStringLiteral( "layerid" ) ) )
196  {
197  // Found a the legend layer that matches the maplayer
198  QgsDebugMsg( "Found matching id" );
199 
200  // Set visible flag from maplayer to legendlayer
201  legendLayerFile.setAttribute( QStringLiteral( "visible" ), mapLayer.attribute( QStringLiteral( "visible" ) ) );
202 
203  // Set overview flag from maplayer to legendlayer
204  legendLayerFile.setAttribute( QStringLiteral( "isInOverview" ), mapLayer.attribute( QStringLiteral( "showInOverviewFlag" ) ) );
205  }
206  }
207  }
208  }
209  return;
210 
211 }
212 
213 void QgsProjectFileTransform::transform091to0100()
214 {
215  if ( ! mDom.isNull() )
216  {
217  // Insert transforms here!
218  QDomNodeList rasterPropertyList = mDom.elementsByTagName( QStringLiteral( "rasterproperties" ) );
219  QgsDebugMsg( QString( "Raster properties file entries: " ) + QString::number( rasterPropertyList.count() ) );
220  for ( int i = 0; i < rasterPropertyList.count(); i++ )
221  {
222  // Get one rasterproperty element from list, and rename the sub-properties.
223  QDomNode rasterProperty = rasterPropertyList.item( i );
224  // rasterProperty.namedItem("").toElement().setTagName("");
225 
226  rasterProperty.namedItem( QStringLiteral( "stdDevsToPlotDouble" ) ).toElement().setTagName( QStringLiteral( "mStandardDeviations" ) );
227 
228  rasterProperty.namedItem( QStringLiteral( "invertHistogramFlag" ) ).toElement().setTagName( QStringLiteral( "mInvertPixelsFlag" ) );
229  rasterProperty.namedItem( QStringLiteral( "showDebugOverLayFlag" ) ).toElement().setTagName( QStringLiteral( "mDebugOverLayFlag" ) );
230 
231  rasterProperty.namedItem( QStringLiteral( "redBandNameQString" ) ).toElement().setTagName( QStringLiteral( "mRedBandName" ) );
232  rasterProperty.namedItem( QStringLiteral( "blueBandNameQString" ) ).toElement().setTagName( QStringLiteral( "mBlueBandName" ) );
233  rasterProperty.namedItem( QStringLiteral( "greenBandNameQString" ) ).toElement().setTagName( QStringLiteral( "mGreenBandName" ) );
234  rasterProperty.namedItem( QStringLiteral( "grayBandNameQString" ) ).toElement().setTagName( QStringLiteral( "mGrayBandName" ) );
235  }
236 
237  // Changing symbol size for hard: symbols
238  QDomNodeList symbolPropertyList = mDom.elementsByTagName( QStringLiteral( "symbol" ) );
239  for ( int i = 0; i < symbolPropertyList.count(); i++ )
240  {
241  // Get the <poinmtsymbol> to check for 'hard:' for each <symbol>
242  QDomNode symbolProperty = symbolPropertyList.item( i );
243 
244  QDomElement pointSymbol = symbolProperty.firstChildElement( QStringLiteral( "pointsymbol" ) );
245  if ( pointSymbol.text().startsWith( QLatin1String( "hard:" ) ) )
246  {
247  // Get pointsize and line width
248  int lineWidth = symbolProperty.firstChildElement( QStringLiteral( "outlinewidth" ) ).text().toInt();
249  int pointSize = symbolProperty.firstChildElement( QStringLiteral( "pointsize" ) ).text().toInt();
250  // Just a precaution, checking for 0
251  if ( pointSize != 0 )
252  {
253  // int r = (s-2*lw)/2-1 --> 2r = (s-2*lw)-2 --> 2r+2 = s-2*lw
254  // --> 2r+2+2*lw = s
255  // where '2r' is the old size.
256  pointSize = pointSize + 2 + 2 * lineWidth;
257  QgsDebugMsg( QString( "Setting point size to %1" ).arg( pointSize ) );
258  QDomElement newPointSizeProperty = mDom.createElement( QStringLiteral( "pointsize" ) );
259  QDomText newPointSizeTxt = mDom.createTextNode( QString::number( pointSize ) );
260  newPointSizeProperty.appendChild( newPointSizeTxt );
261  symbolProperty.replaceChild( newPointSizeProperty, pointSymbol );
262  }
263  }
264  }
265 
266  }
267  return;
268 
269 }
270 
271 void QgsProjectFileTransform::transform0100to0110()
272 {
273  if ( ! mDom.isNull() )
274  {
275 #ifndef QT_NO_PRINTER
276  //Change 'outlinewidth' in QgsSymbol
277  QPrinter myPrinter( QPrinter::ScreenResolution );
278  int screenDpi = myPrinter.resolution();
279  double widthScaleFactor = 25.4 / screenDpi;
280 
281  QDomNodeList outlineWidthList = mDom.elementsByTagName( QStringLiteral( "outlinewidth" ) );
282  for ( int i = 0; i < outlineWidthList.size(); ++i )
283  {
284  //calculate new width
285  QDomElement currentOutlineElem = outlineWidthList.at( i ).toElement();
286  double outlineWidth = currentOutlineElem.text().toDouble();
287  outlineWidth *= widthScaleFactor;
288 
289  //replace old text node
290  QDomNode outlineTextNode = currentOutlineElem.firstChild();
291  QDomText newOutlineText = mDom.createTextNode( QString::number( outlineWidth ) );
292  currentOutlineElem.replaceChild( newOutlineText, outlineTextNode );
293 
294  }
295 
296  //Change 'pointsize' in QgsSymbol
297  QDomNodeList pointSizeList = mDom.elementsByTagName( QStringLiteral( "pointsize" ) );
298  for ( int i = 0; i < pointSizeList.size(); ++i )
299  {
300  //calculate new size
301  QDomElement currentPointSizeElem = pointSizeList.at( i ).toElement();
302  double pointSize = currentPointSizeElem.text().toDouble();
303  pointSize *= widthScaleFactor;
304 
305  //replace old text node
306  QDomNode pointSizeTextNode = currentPointSizeElem.firstChild();
307  QDomText newPointSizeText = mDom.createTextNode( QString::number( static_cast< int >( pointSize ) ) );
308  currentPointSizeElem.replaceChild( newPointSizeText, pointSizeTextNode );
309  }
310 #endif
311  }
312 }
313 
314 void QgsProjectFileTransform::transform0110to1000()
315 {
316  if ( ! mDom.isNull() )
317  {
318  QDomNodeList layerList = mDom.elementsByTagName( QStringLiteral( "maplayer" ) );
319  for ( int i = 0; i < layerList.size(); ++i )
320  {
321  QDomElement layerElem = layerList.at( i ).toElement();
322  QString typeString = layerElem.attribute( QStringLiteral( "type" ) );
323  if ( typeString != QLatin1String( "vector" ) )
324  {
325  continue;
326  }
327 
328  //datasource
329  QDomNode dataSourceNode = layerElem.namedItem( QStringLiteral( "datasource" ) );
330  if ( dataSourceNode.isNull() )
331  {
332  return;
333  }
334  QString dataSource = dataSourceNode.toElement().text();
335 
336  //provider key
337  QDomNode providerNode = layerElem.namedItem( QStringLiteral( "provider" ) );
338  if ( providerNode.isNull() )
339  {
340  return;
341  }
342  QString providerKey = providerNode.toElement().text();
343 
344  //create the layer to get the provider for int->fieldName conversion
345  QgsVectorLayer* theLayer = new QgsVectorLayer( dataSource, QLatin1String( "" ), providerKey, false );
346  if ( !theLayer->isValid() )
347  {
348  delete theLayer;
349  return;
350  }
351 
352  QgsVectorDataProvider* theProvider = theLayer->dataProvider();
353  if ( !theProvider )
354  {
355  return;
356  }
357  QgsFields theFields = theProvider->fields();
358 
359  //read classificationfield
360  QDomNodeList classificationFieldList = layerElem.elementsByTagName( QStringLiteral( "classificationfield" ) );
361  for ( int j = 0; j < classificationFieldList.size(); ++j )
362  {
363  QDomElement classificationFieldElem = classificationFieldList.at( j ).toElement();
364  int fieldNumber = classificationFieldElem.text().toInt();
365  if ( fieldNumber >= 0 && fieldNumber < theFields.count() )
366  {
367  QDomText fieldName = mDom.createTextNode( theFields.at( fieldNumber ).name() );
368  QDomNode nameNode = classificationFieldElem.firstChild();
369  classificationFieldElem.replaceChild( fieldName, nameNode );
370  }
371  }
372 
373  }
374  }
375 }
376 
377 void QgsProjectFileTransform::transform1100to1200()
378 {
379  QgsDebugMsg( "Entering..." );
380  if ( mDom.isNull() )
381  return;
382 
383  QDomNode qgis = mDom.firstChildElement( QStringLiteral( "qgis" ) );
384  if ( qgis.isNull() )
385  return;
386 
387  QDomElement properties = qgis.firstChildElement( QStringLiteral( "properties" ) );
388  if ( properties.isNull() )
389  return;
390 
391  QDomElement digitizing = properties.firstChildElement( QStringLiteral( "Digitizing" ) );
392  if ( digitizing.isNull() )
393  return;
394 
395  QDomElement tolList = digitizing.firstChildElement( QStringLiteral( "LayerSnappingToleranceList" ) );
396  if ( tolList.isNull() )
397  return;
398 
399  QDomElement tolUnitList = digitizing.firstChildElement( QStringLiteral( "LayerSnappingToleranceUnitList" ) );
400  if ( !tolUnitList.isNull() )
401  return;
402 
403  QStringList units;
404  for ( int i = 0; i < tolList.childNodes().count(); i++ )
405  units << QStringLiteral( "0" );
406 
407  QgsProjectPropertyValue value( units );
408  value.writeXml( QStringLiteral( "LayerSnappingToleranceUnitList" ), digitizing, mDom );
409 }
410 
411 void QgsProjectFileTransform::transform1400to1500()
412 {
413  //Adapt the XML description of the composer legend model to version 1.5
414  if ( mDom.isNull() )
415  {
416  return;
417  }
418  //Add layer id to <VectorClassificationItem>
419  QDomNodeList layerItemList = mDom.elementsByTagName( QStringLiteral( "LayerItem" ) );
420  QDomElement currentLayerItemElem;
421  QString currentLayerId;
422 
423  for ( int i = 0; i < layerItemList.size(); ++i )
424  {
425  currentLayerItemElem = layerItemList.at( i ).toElement();
426  if ( currentLayerItemElem.isNull() )
427  {
428  continue;
429  }
430  currentLayerId = currentLayerItemElem.attribute( QStringLiteral( "layerId" ) );
431 
432  QDomNodeList vectorClassificationList = currentLayerItemElem.elementsByTagName( QStringLiteral( "VectorClassificationItem" ) );
433  QDomElement currentClassificationElem;
434  for ( int j = 0; j < vectorClassificationList.size(); ++j )
435  {
436  currentClassificationElem = vectorClassificationList.at( j ).toElement();
437  if ( !currentClassificationElem.isNull() )
438  {
439  currentClassificationElem.setAttribute( QStringLiteral( "layerId" ), currentLayerId );
440  }
441  }
442 
443  //replace the text items with VectorClassification or RasterClassification items
444  QDomNodeList textItemList = currentLayerItemElem.elementsByTagName( QStringLiteral( "TextItem" ) );
445  QDomElement currentTextItem;
446 
447  for ( int j = 0; j < textItemList.size(); ++j )
448  {
449  currentTextItem = textItemList.at( j ).toElement();
450  if ( currentTextItem.isNull() )
451  {
452  continue;
453  }
454 
455  QDomElement classificationElement;
456  if ( !vectorClassificationList.isEmpty() ) //we guess it is a vector layer
457  {
458  classificationElement = mDom.createElement( QStringLiteral( "VectorClassificationItem" ) );
459  }
460  else
461  {
462  classificationElement = mDom.createElement( QStringLiteral( "RasterClassificationItem" ) );
463  }
464 
465  classificationElement.setAttribute( QStringLiteral( "layerId" ), currentLayerId );
466  classificationElement.setAttribute( QStringLiteral( "text" ), currentTextItem.attribute( QStringLiteral( "text" ) ) );
467  currentLayerItemElem.replaceChild( classificationElement, currentTextItem );
468  }
469  }
470 }
471 
472 void QgsProjectFileTransform::transform1800to1900()
473 {
474  if ( mDom.isNull() )
475  {
476  return;
477  }
478 
479  QDomNodeList layerItemList = mDom.elementsByTagName( QStringLiteral( "rasterproperties" ) );
480  for ( int i = 0; i < layerItemList.size(); ++i )
481  {
482  QDomElement rasterPropertiesElem = layerItemList.at( i ).toElement();
483  QDomNode layerNode = rasterPropertiesElem.parentNode();
484  QDomElement dataSourceElem = layerNode.firstChildElement( QStringLiteral( "datasource" ) );
485  QDomElement layerNameElem = layerNode.firstChildElement( QStringLiteral( "layername" ) );
486  QgsRasterLayer rasterLayer;
487  // TODO: We have to use more data from project file to read the layer it correctly,
488  // OTOH, we should not read it until it was converted
489  rasterLayer.readLayerXml( layerNode.toElement() );
490  convertRasterProperties( mDom, layerNode, rasterPropertiesElem, &rasterLayer );
491  }
492 
493  //composer: replace mGridAnnotationPosition with mLeftGridAnnotationPosition & co.
494  // and mGridAnnotationDirection with mLeftGridAnnotationDirection & co.
495  QDomNodeList composerMapList = mDom.elementsByTagName( QStringLiteral( "ComposerMap" ) );
496  for ( int i = 0; i < composerMapList.size(); ++i )
497  {
498  QDomNodeList gridList = composerMapList.at( i ).toElement().elementsByTagName( QStringLiteral( "Grid" ) );
499  for ( int j = 0; j < gridList.size(); ++j )
500  {
501  QDomNodeList annotationList = gridList.at( j ).toElement().elementsByTagName( QStringLiteral( "Annotation" ) );
502  for ( int k = 0; k < annotationList.size(); ++k )
503  {
504  QDomElement annotationElem = annotationList.at( k ).toElement();
505 
506  //position
507  if ( annotationElem.hasAttribute( QStringLiteral( "position" ) ) )
508  {
509  int pos = annotationElem.attribute( QStringLiteral( "position" ) ).toInt();
510  annotationElem.setAttribute( QStringLiteral( "leftPosition" ), pos );
511  annotationElem.setAttribute( QStringLiteral( "rightPosition" ), pos );
512  annotationElem.setAttribute( QStringLiteral( "topPosition" ), pos );
513  annotationElem.setAttribute( QStringLiteral( "bottomPosition" ), pos );
514  annotationElem.removeAttribute( QStringLiteral( "position" ) );
515  }
516 
517  //direction
518  if ( annotationElem.hasAttribute( QStringLiteral( "direction" ) ) )
519  {
520  int dir = annotationElem.attribute( QStringLiteral( "direction" ) ).toInt();
521  if ( dir == 2 )
522  {
523  annotationElem.setAttribute( QStringLiteral( "leftDirection" ), 0 );
524  annotationElem.setAttribute( QStringLiteral( "rightDirection" ), 0 );
525  annotationElem.setAttribute( QStringLiteral( "topDirection" ), 1 );
526  annotationElem.setAttribute( QStringLiteral( "bottomDirection" ), 1 );
527  }
528  else if ( dir == 3 )
529  {
530  annotationElem.setAttribute( QStringLiteral( "leftDirection" ), 1 );
531  annotationElem.setAttribute( QStringLiteral( "rightDirection" ), 1 );
532  annotationElem.setAttribute( QStringLiteral( "topDirection" ), 0 );
533  annotationElem.setAttribute( QStringLiteral( "bottomDirection" ), 0 );
534  }
535  else
536  {
537  annotationElem.setAttribute( QStringLiteral( "leftDirection" ), dir );
538  annotationElem.setAttribute( QStringLiteral( "rightDirection" ), dir );
539  annotationElem.setAttribute( QStringLiteral( "topDirection" ), dir );
540  annotationElem.setAttribute( QStringLiteral( "bottomDirection" ), dir );
541  }
542  annotationElem.removeAttribute( QStringLiteral( "direction" ) );
543  }
544  }
545  }
546  }
547 
548  //Composer: move all items under Composition element
549  QDomNodeList composerList = mDom.elementsByTagName( QStringLiteral( "Composer" ) );
550  for ( int i = 0; i < composerList.size(); ++i )
551  {
552  QDomElement composerElem = composerList.at( i ).toElement();
553 
554  //find <QgsComposition element
555  QDomElement compositionElem = composerElem.firstChildElement( QStringLiteral( "Composition" ) );
556  if ( compositionElem.isNull() )
557  {
558  continue;
559  }
560 
561  QDomNodeList composerChildren = composerElem.childNodes();
562 
563  if ( composerChildren.size() < 1 )
564  {
565  continue;
566  }
567 
568  for ( int j = composerChildren.size() - 1; j >= 0; --j )
569  {
570  QDomElement childElem = composerChildren.at( j ).toElement();
571  if ( childElem.tagName() == QLatin1String( "Composition" ) )
572  {
573  continue;
574  }
575 
576  composerElem.removeChild( childElem );
577  compositionElem.appendChild( childElem );
578 
579  }
580  }
581 
582  // SimpleFill symbol layer v2: avoid double transparency
583  // replacing alpha value of symbol layer's color with 255 (the
584  // transparency value is already stored as symbol transparency).
585  QDomNodeList rendererList = mDom.elementsByTagName( QStringLiteral( "renderer-v2" ) );
586  for ( int i = 0; i < rendererList.size(); ++i )
587  {
588  QDomNodeList layerList = rendererList.at( i ).toElement().elementsByTagName( QStringLiteral( "layer" ) );
589  for ( int j = 0; j < layerList.size(); ++j )
590  {
591  QDomElement layerElem = layerList.at( j ).toElement();
592  if ( layerElem.attribute( QStringLiteral( "class" ) ) == QLatin1String( "SimpleFill" ) )
593  {
594  QDomNodeList propList = layerElem.elementsByTagName( QStringLiteral( "prop" ) );
595  for ( int k = 0; k < propList.size(); ++k )
596  {
597  QDomElement propElem = propList.at( k ).toElement();
598  if ( propElem.attribute( QStringLiteral( "k" ) ) == QLatin1String( "color" ) || propElem.attribute( QStringLiteral( "k" ) ) == QLatin1String( "color_border" ) )
599  {
600  propElem.setAttribute( QStringLiteral( "v" ), propElem.attribute( QStringLiteral( "v" ) ).section( ',', 0, 2 ) + ",255" );
601  }
602  }
603  }
604  }
605  }
606 
607  QgsDebugMsg( mDom.toString() );
608 }
609 
610 void QgsProjectFileTransform::transform2200to2300()
611 {
612  //composer: set placement for all picture items to middle, to mimic <=2.2 behavior
613  QDomNodeList composerPictureList = mDom.elementsByTagName( QStringLiteral( "ComposerPicture" ) );
614  for ( int i = 0; i < composerPictureList.size(); ++i )
615  {
616  QDomElement picture = composerPictureList.at( i ).toElement();
617  picture.setAttribute( QStringLiteral( "anchorPoint" ), QString::number( 4 ) );
618  }
619 }
620 
621 void QgsProjectFileTransform::transform2990()
622 {
623  QDomNodeList mapLayers = mDom.elementsByTagName( QStringLiteral( "maplayer" ) );
624 
625  for ( int mapLayerIndex = 0; mapLayerIndex < mapLayers.count(); ++mapLayerIndex )
626  {
627  QDomElement layerElem = mapLayers.at( mapLayerIndex ).toElement();
628 
629  // The newly added fieldConfiguration element
630  QDomElement fieldConfigurationElement = mDom.createElement( QStringLiteral( "fieldConfiguration" ) );
631  layerElem.appendChild( fieldConfigurationElement );
632 
633  QDomNodeList editTypeNodes = layerElem.namedItem( QStringLiteral( "edittypes" ) ).childNodes();
634  QDomElement constraintExpressionsElem = mDom.createElement( QStringLiteral( "constraintExpressions" ) );
635  layerElem.appendChild( constraintExpressionsElem );
636 
637  for ( int i = 0; i < editTypeNodes.size(); ++i )
638  {
639  QDomNode editTypeNode = editTypeNodes.at( i );
640  QDomElement editTypeElement = editTypeNode.toElement();
641 
642  QDomElement fieldElement = mDom.createElement( QStringLiteral( "field" ) );
643  fieldConfigurationElement.appendChild( fieldElement );
644 
645  QString name = editTypeElement.attribute( QStringLiteral( "name" ) );
646  fieldElement.setAttribute( QStringLiteral( "name" ), name );
647  QDomElement constraintExpressionElem = mDom.createElement( QStringLiteral( "constraint" ) );
648  constraintExpressionElem.setAttribute( "field", name );
649  constraintExpressionsElem.appendChild( constraintExpressionElem );
650 
651  QDomElement editWidgetElement = mDom.createElement( QStringLiteral( "editWidget" ) );
652  fieldElement.appendChild( editWidgetElement );
653 
654  QString ewv2Type = editTypeElement.attribute( QStringLiteral( "widgetv2type" ) );
655  editWidgetElement.setAttribute( "type", ewv2Type );
656 
657  QDomElement ewv2CfgElem = editTypeElement.namedItem( QStringLiteral( "widgetv2config" ) ).toElement();
658 
659  if ( !ewv2CfgElem.isNull() )
660  {
661  QDomElement editWidgetConfigElement = mDom.createElement( QStringLiteral( "config" ) );
662  editWidgetElement.appendChild( editWidgetConfigElement );
663 
664  QVariantMap editWidgetConfiguration;
665 
666  QDomNamedNodeMap configAttrs = ewv2CfgElem.attributes();
667  for ( int configIndex = 0; configIndex < configAttrs.count(); ++configIndex )
668  {
669  QDomAttr configAttr = configAttrs.item( configIndex ).toAttr();
670  if ( configAttr.name() == QStringLiteral( "fieldEditable" ) )
671  {
672  editWidgetConfigElement.setAttribute( QStringLiteral( "fieldEditable" ), configAttr.value() );
673  }
674  else if ( configAttr.name() == QStringLiteral( "labelOnTop" ) )
675  {
676  editWidgetConfigElement.setAttribute( QStringLiteral( "labelOnTop" ), configAttr.value() );
677  }
678  else if ( configAttr.name() == QStringLiteral( "notNull" ) )
679  {
680  editWidgetConfigElement.setAttribute( QStringLiteral( "notNull" ), configAttr.value() );
681  }
682  else if ( configAttr.name() == QStringLiteral( "constraint" ) )
683  {
684  constraintExpressionElem.setAttribute( "exp", configAttr.value() );
685  }
686  else if ( configAttr.name() == QStringLiteral( "constraintDescription" ) )
687  {
688  constraintExpressionElem.setAttribute( "desc", configAttr.value() );
689  }
690  else
691  {
692  editWidgetConfiguration.insert( configAttr.name(), configAttr.value() );
693  }
694  }
695 
696  if ( ewv2Type == QStringLiteral( "ValueMap" ) )
697  {
698  QDomNodeList configElements = ewv2CfgElem.childNodes();
699  QVariantMap map;
700  for ( int configIndex = 0; configIndex < configElements.count(); ++configIndex )
701  {
702  QDomElement configElem = configElements.at( configIndex ).toElement();
703  map.insert( configElem.attribute( QStringLiteral( "key" ) ), configElem.attribute( QStringLiteral( "value" ) ) );
704  }
705  editWidgetConfiguration.insert( QStringLiteral( "map" ), map );
706  }
707  else if ( ewv2Type == QStringLiteral( "Photo" ) )
708  {
709  editWidgetElement.setAttribute( "type", QStringLiteral( "ExternalResource" ) );
710 
711  editWidgetConfiguration.insert( QStringLiteral( "DocumentViewer" ), 1 );
712  editWidgetConfiguration.insert( QStringLiteral( "DocumentViewerHeight" ), editWidgetConfiguration.value( QStringLiteral( "Height" ) ) );
713  editWidgetConfiguration.insert( QStringLiteral( "DocumentViewerWidth" ), editWidgetConfiguration.value( QStringLiteral( "Width" ) ) );
714  editWidgetConfiguration.insert( QStringLiteral( "RelativeStorage" ), 1 );
715  }
716  else if ( ewv2Type == QStringLiteral( "FileName" ) )
717  {
718  editWidgetElement.setAttribute( "type", QStringLiteral( "ExternalResource" ) );
719  editWidgetConfiguration.insert( QStringLiteral( "RelativeStorage" ), 1 );
720  }
721 
722  editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( editWidgetConfiguration, mDom ) );
723  }
724  }
725  }
726 }
727 
728 void QgsProjectFileTransform::convertRasterProperties( QDomDocument& doc, QDomNode& parentNode,
729  QDomElement& rasterPropertiesElem, QgsRasterLayer* rlayer )
730 {
731  //no data
732  //TODO: We would need to set no data on all bands, but we don't know number of bands here
733  QDomNode noDataNode = rasterPropertiesElem.namedItem( QStringLiteral( "mNoDataValue" ) );
734  QDomElement noDataElement = noDataNode.toElement();
735  if ( !noDataElement.text().isEmpty() )
736  {
737  QgsDebugMsg( "mNoDataValue = " + noDataElement.text() );
738  QDomElement noDataElem = doc.createElement( QStringLiteral( "noData" ) );
739 
740  QDomElement noDataRangeList = doc.createElement( QStringLiteral( "noDataRangeList" ) );
741  noDataRangeList.setAttribute( QStringLiteral( "bandNo" ), 1 );
742 
743  QDomElement noDataRange = doc.createElement( QStringLiteral( "noDataRange" ) );
744  noDataRange.setAttribute( QStringLiteral( "min" ), noDataElement.text() );
745  noDataRange.setAttribute( QStringLiteral( "max" ), noDataElement.text() );
746  noDataRangeList.appendChild( noDataRange );
747 
748  noDataElem.appendChild( noDataRangeList );
749 
750  parentNode.appendChild( noDataElem );
751  }
752 
753  QDomElement rasterRendererElem = doc.createElement( QStringLiteral( "rasterrenderer" ) );
754  //convert general properties
755 
756  //invert color
757  rasterRendererElem.setAttribute( QStringLiteral( "invertColor" ), QStringLiteral( "0" ) );
758  QDomElement invertColorElem = rasterPropertiesElem.firstChildElement( QStringLiteral( "mInvertColor" ) );
759  if ( !invertColorElem.isNull() )
760  {
761  if ( invertColorElem.text() == QLatin1String( "true" ) )
762  {
763  rasterRendererElem.setAttribute( QStringLiteral( "invertColor" ), QStringLiteral( "1" ) );
764  }
765  }
766 
767  //opacity
768  rasterRendererElem.setAttribute( QStringLiteral( "opacity" ), QStringLiteral( "1" ) );
769  QDomElement transparencyElem = parentNode.firstChildElement( QStringLiteral( "transparencyLevelInt" ) );
770  if ( !transparencyElem.isNull() )
771  {
772  double transparency = transparencyElem.text().toInt();
773  rasterRendererElem.setAttribute( QStringLiteral( "opacity" ), QString::number( transparency / 255.0 ) );
774  }
775 
776  //alphaBand was not saved until now (bug)
777  rasterRendererElem.setAttribute( QStringLiteral( "alphaBand" ), -1 );
778 
779  //gray band is used for several renderers
780  int grayBand = rasterBandNumber( rasterPropertiesElem, QStringLiteral( "mGrayBandName" ), rlayer );
781 
782  //convert renderer specific properties
783  QString drawingStyle = rasterPropertiesElem.firstChildElement( QStringLiteral( "mDrawingStyle" ) ).text();
784 
785  // While PalettedColor should normally contain only integer values, usually
786  // color palette 0-255, it may happen (Tim, issue #7023) that it contains
787  // colormap classification with double values and text labels
788  // (which should normally only appear in SingleBandPseudoColor drawingStyle)
789  // => we have to check first the values and change drawingStyle if necessary
790  if ( drawingStyle == QLatin1String( "PalettedColor" ) )
791  {
792  QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( QStringLiteral( "customColorRamp" ) );
793  QDomNodeList colorRampEntryList = customColorRampElem.elementsByTagName( QStringLiteral( "colorRampEntry" ) );
794 
795  for ( int i = 0; i < colorRampEntryList.size(); ++i )
796  {
797  QDomElement colorRampEntryElem = colorRampEntryList.at( i ).toElement();
798  QString strValue = colorRampEntryElem.attribute( QStringLiteral( "value" ) );
799  double value = strValue.toDouble();
800  if ( value < 0 || value > 10000 || !qgsDoubleNear( value, static_cast< int >( value ) ) )
801  {
802  QgsDebugMsg( QString( "forcing SingleBandPseudoColor value = %1" ).arg( value ) );
803  drawingStyle = QStringLiteral( "SingleBandPseudoColor" );
804  break;
805  }
806  }
807  }
808 
809  if ( drawingStyle == QLatin1String( "SingleBandGray" ) )
810  {
811  rasterRendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "singlebandgray" ) );
812  rasterRendererElem.setAttribute( QStringLiteral( "grayBand" ), grayBand );
813  transformContrastEnhancement( doc, rasterPropertiesElem, rasterRendererElem );
814  }
815  else if ( drawingStyle == QLatin1String( "SingleBandPseudoColor" ) )
816  {
817  rasterRendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "singlebandpseudocolor" ) );
818  rasterRendererElem.setAttribute( QStringLiteral( "band" ), grayBand );
819  QDomElement newRasterShaderElem = doc.createElement( QStringLiteral( "rastershader" ) );
820  QDomElement newColorRampShaderElem = doc.createElement( QStringLiteral( "colorrampshader" ) );
821  newRasterShaderElem.appendChild( newColorRampShaderElem );
822  rasterRendererElem.appendChild( newRasterShaderElem );
823 
824  //switch depending on mColorShadingAlgorithm
825  QString colorShadingAlgorithm = rasterPropertiesElem.firstChildElement( QStringLiteral( "mColorShadingAlgorithm" ) ).text();
826  if ( colorShadingAlgorithm == QLatin1String( "PseudoColorShader" ) || colorShadingAlgorithm == QLatin1String( "FreakOutShader" ) )
827  {
828  newColorRampShaderElem.setAttribute( QStringLiteral( "colorRampType" ), QStringLiteral( "INTERPOLATED" ) );
829 
830  //get minmax from rasterlayer
831  QgsRasterBandStats rasterBandStats = rlayer->dataProvider()->bandStatistics( grayBand );
832  double minValue = rasterBandStats.minimumValue;
833  double maxValue = rasterBandStats.maximumValue;
834  double breakSize = ( maxValue - minValue ) / 3;
835 
836  QStringList colorList;
837  if ( colorShadingAlgorithm == QLatin1String( "FreakOutShader" ) )
838  {
839  colorList << QStringLiteral( "#ff00ff" ) << QStringLiteral( "#00ffff" ) << QStringLiteral( "#ff0000" ) << QStringLiteral( "#00ff00" );
840  }
841  else //pseudocolor
842  {
843  colorList << QStringLiteral( "#0000ff" ) << QStringLiteral( "#00ffff" ) << QStringLiteral( "#ffff00" ) << QStringLiteral( "#ff0000" );
844  }
845  QStringList::const_iterator colorIt = colorList.constBegin();
846  double boundValue = minValue;
847  for ( ; colorIt != colorList.constEnd(); ++colorIt )
848  {
849  QDomElement newItemElem = doc.createElement( QStringLiteral( "item" ) );
850  newItemElem.setAttribute( QStringLiteral( "value" ), QString::number( boundValue ) );
851  newItemElem.setAttribute( QStringLiteral( "label" ), QString::number( boundValue ) );
852  newItemElem.setAttribute( QStringLiteral( "color" ), *colorIt );
853  newColorRampShaderElem.appendChild( newItemElem );
854  boundValue += breakSize;
855  }
856  }
857  else if ( colorShadingAlgorithm == QLatin1String( "ColorRampShader" ) )
858  {
859  QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( QStringLiteral( "customColorRamp" ) );
860  QString type = customColorRampElem.firstChildElement( QStringLiteral( "colorRampType" ) ).text();
861  newColorRampShaderElem.setAttribute( QStringLiteral( "colorRampType" ), type );
862  QDomNodeList colorNodeList = customColorRampElem.elementsByTagName( QStringLiteral( "colorRampEntry" ) );
863 
864  QString value, label;
865  QColor newColor;
866  int red, green, blue;
867  QDomElement currentItemElem;
868  for ( int i = 0; i < colorNodeList.size(); ++i )
869  {
870  currentItemElem = colorNodeList.at( i ).toElement();
871  value = currentItemElem.attribute( QStringLiteral( "value" ) );
872  label = currentItemElem.attribute( QStringLiteral( "label" ) );
873  red = currentItemElem.attribute( QStringLiteral( "red" ) ).toInt();
874  green = currentItemElem.attribute( QStringLiteral( "green" ) ).toInt();
875  blue = currentItemElem.attribute( QStringLiteral( "blue" ) ).toInt();
876  newColor = QColor( red, green, blue );
877  QDomElement newItemElem = doc.createElement( QStringLiteral( "item" ) );
878  newItemElem.setAttribute( QStringLiteral( "value" ), value );
879  newItemElem.setAttribute( QStringLiteral( "label" ), label );
880  newItemElem.setAttribute( QStringLiteral( "color" ), newColor.name() );
881  newColorRampShaderElem.appendChild( newItemElem );
882  }
883  }
884  }
885  else if ( drawingStyle == QLatin1String( "PalettedColor" ) )
886  {
887  rasterRendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "paletted" ) );
888  rasterRendererElem.setAttribute( QStringLiteral( "band" ), grayBand );
889  QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( QStringLiteral( "customColorRamp" ) );
890  QDomNodeList colorRampEntryList = customColorRampElem.elementsByTagName( QStringLiteral( "colorRampEntry" ) );
891  QDomElement newColorPaletteElem = doc.createElement( QStringLiteral( "colorPalette" ) );
892 
893  int red = 0;
894  int green = 0;
895  int blue = 0;
896  int value = 0;
897  QDomElement colorRampEntryElem;
898  for ( int i = 0; i < colorRampEntryList.size(); ++i )
899  {
900  colorRampEntryElem = colorRampEntryList.at( i ).toElement();
901  QDomElement newPaletteElem = doc.createElement( QStringLiteral( "paletteEntry" ) );
902  value = static_cast< int >( colorRampEntryElem.attribute( QStringLiteral( "value" ) ).toDouble() );
903  newPaletteElem.setAttribute( QStringLiteral( "value" ), value );
904  red = colorRampEntryElem.attribute( QStringLiteral( "red" ) ).toInt();
905  green = colorRampEntryElem.attribute( QStringLiteral( "green" ) ).toInt();
906  blue = colorRampEntryElem.attribute( QStringLiteral( "blue" ) ).toInt();
907  newPaletteElem.setAttribute( QStringLiteral( "color" ), QColor( red, green, blue ).name() );
908  QString label = colorRampEntryElem.attribute( QStringLiteral( "label" ) );
909  if ( !label.isEmpty() )
910  {
911  newPaletteElem.setAttribute( QStringLiteral( "label" ), label );
912  }
913  newColorPaletteElem.appendChild( newPaletteElem );
914  }
915  rasterRendererElem.appendChild( newColorPaletteElem );
916  }
917  else if ( drawingStyle == QLatin1String( "MultiBandColor" ) )
918  {
919  rasterRendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "multibandcolor" ) );
920 
921  //red band, green band, blue band
922  int redBand = rasterBandNumber( rasterPropertiesElem, QStringLiteral( "mRedBandName" ), rlayer );
923  int greenBand = rasterBandNumber( rasterPropertiesElem, QStringLiteral( "mGreenBandName" ), rlayer );
924  int blueBand = rasterBandNumber( rasterPropertiesElem, QStringLiteral( "mBlueBandName" ), rlayer );
925  rasterRendererElem.setAttribute( QStringLiteral( "redBand" ), redBand );
926  rasterRendererElem.setAttribute( QStringLiteral( "greenBand" ), greenBand );
927  rasterRendererElem.setAttribute( QStringLiteral( "blueBand" ), blueBand );
928 
929  transformContrastEnhancement( doc, rasterPropertiesElem, rasterRendererElem );
930  }
931  else
932  {
933  return;
934  }
935 
936  //replace rasterproperties element with rasterrenderer element
937  if ( !parentNode.isNull() )
938  {
939  parentNode.replaceChild( rasterRendererElem, rasterPropertiesElem );
940  }
941 }
942 
943 int QgsProjectFileTransform::rasterBandNumber( const QDomElement &rasterPropertiesElem, const QString &bandName,
944  QgsRasterLayer *rlayer )
945 {
946  if ( !rlayer )
947  {
948  return -1;
949  }
950 
951  int band = -1;
952  QDomElement rasterBandElem = rasterPropertiesElem.firstChildElement( bandName );
953  if ( !rasterBandElem.isNull() )
954  {
955  QRegExp re( "(\\d+)" );
956 
957  if ( re.indexIn( rasterBandElem.text() ) >= 0 )
958  {
959  return re.cap( 1 ).toInt();
960  }
961  }
962  return band;
963 }
964 
965 void QgsProjectFileTransform::transformContrastEnhancement( QDomDocument& doc, const QDomElement& rasterproperties, QDomElement& rendererElem )
966 {
967  if ( rasterproperties.isNull() || rendererElem.isNull() )
968  {
969  return;
970  }
971 
972  double minimumValue = 0;
973  double maximumValue = 0;
974  QDomElement contrastMinMaxElem = rasterproperties.firstChildElement( QStringLiteral( "contrastEnhancementMinMaxValues" ) );
975  if ( contrastMinMaxElem.isNull() )
976  {
977  return;
978  }
979 
980  QDomElement contrastEnhancementAlgorithmElem = rasterproperties.firstChildElement( QStringLiteral( "mContrastEnhancementAlgorithm" ) );
981  if ( contrastEnhancementAlgorithmElem.isNull() )
982  {
983  return;
984  }
985 
986  //convert enhancement name to enumeration
987  int algorithmEnum = 0;
988  QString algorithmString = contrastEnhancementAlgorithmElem.text();
989  if ( algorithmString == QLatin1String( "StretchToMinimumMaximum" ) )
990  {
991  algorithmEnum = 1;
992  }
993  else if ( algorithmString == QLatin1String( "StretchAndClipToMinimumMaximum" ) )
994  {
995  algorithmEnum = 2;
996  }
997  else if ( algorithmString == QLatin1String( "ClipToMinimumMaximum" ) )
998  {
999  algorithmEnum = 3;
1000  }
1001  else if ( algorithmString == QLatin1String( "UserDefinedEnhancement" ) )
1002  {
1003  algorithmEnum = 4;
1004  }
1005 
1006  QDomNodeList minMaxEntryList = contrastMinMaxElem.elementsByTagName( QStringLiteral( "minMaxEntry" ) );
1007  QStringList enhancementNameList;
1008  if ( minMaxEntryList.size() == 1 )
1009  {
1010  enhancementNameList << QStringLiteral( "contrastEnhancement" );
1011  }
1012  if ( minMaxEntryList.size() == 3 )
1013  {
1014  enhancementNameList << QStringLiteral( "redContrastEnhancement" ) << QStringLiteral( "greenContrastEnhancement" ) << QStringLiteral( "blueContrastEnhancement" );
1015  }
1016  if ( minMaxEntryList.size() > enhancementNameList.size() )
1017  {
1018  return;
1019  }
1020 
1021  QDomElement minMaxEntryElem;
1022  for ( int i = 0; i < minMaxEntryList.size(); ++i )
1023  {
1024  minMaxEntryElem = minMaxEntryList.at( i ).toElement();
1025  QDomElement minElem = minMaxEntryElem.firstChildElement( QStringLiteral( "min" ) );
1026  if ( minElem.isNull() )
1027  {
1028  return;
1029  }
1030  minimumValue = minElem.text().toDouble();
1031 
1032  QDomElement maxElem = minMaxEntryElem.firstChildElement( QStringLiteral( "max" ) );
1033  if ( maxElem.isNull() )
1034  {
1035  return;
1036  }
1037  maximumValue = maxElem.text().toDouble();
1038 
1039  QDomElement newContrastEnhancementElem = doc.createElement( enhancementNameList.at( i ) );
1040  QDomElement newMinValElem = doc.createElement( QStringLiteral( "minValue" ) );
1041  QDomText minText = doc.createTextNode( QString::number( minimumValue ) );
1042  newMinValElem.appendChild( minText );
1043  newContrastEnhancementElem.appendChild( newMinValElem );
1044  QDomElement newMaxValElem = doc.createElement( QStringLiteral( "maxValue" ) );
1045  QDomText maxText = doc.createTextNode( QString::number( maximumValue ) );
1046  newMaxValElem.appendChild( maxText );
1047  newContrastEnhancementElem.appendChild( newMaxValElem );
1048 
1049  QDomElement newAlgorithmElem = doc.createElement( QStringLiteral( "algorithm" ) );
1050  QDomText newAlgorithmText = doc.createTextNode( QString::number( algorithmEnum ) );
1051  newAlgorithmElem.appendChild( newAlgorithmText );
1052  newContrastEnhancementElem.appendChild( newAlgorithmElem );
1053 
1054  rendererElem.appendChild( newContrastEnhancementElem );
1055  }
1056 }
1057 
1058 void QgsProjectFileTransform::transformRasterTransparency( QDomDocument& doc, const QDomElement& orig, QDomElement& rendererElem )
1059 {
1060  //soon...
1061  Q_UNUSED( doc );
1062  Q_UNUSED( orig );
1063  Q_UNUSED( rendererElem );
1064 }
1065 
static void convertRasterProperties(QDomDocument &doc, QDomNode &parentNode, QDomElement &rasterPropertiesElem, QgsRasterLayer *rlayer)
QgsProjectVersion PFV
void dump()
Prints the contents via QgsDebugMsg()
QString name
Definition: qgsfield.h:53
bool readLayerXml(const QDomElement &layerElement)
Sets state from Dom document.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
bool updateRevision(const QgsProjectVersion &version)
double maximumValue
The maximum cell value in the raster band.
Container of fields for a vector layer.
Definition: qgsfields.h:39
bool isValid() const
Return the status of the layer.
bool isNull() const
Returns true if this is a NULL project version.
int count() const
Return number of items.
Definition: qgsfields.cpp:115
Project property value node, contains a QgsProjectPropertyKey&#39;s value.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:193
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:135
virtual QgsRasterBandStats bandStatistics(int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Get band statistics.
The RasterBandStats struct is a container for statistics about a single raster band.
A class to describe the version of a project.
virtual QgsFields fields() const =0
Returns the fields associated with this data provider.
bool writeXml(const QString &nodeName, QDomElement &element, QDomDocument &document) override
Writes the property hierarchy to a specified DOM element.
double minimumValue
The minimum cell value in the raster band.
QgsRasterDataProvider * dataProvider()
Returns the data provider.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
This is the base class for vector data providers.
Represents a vector layer which manages a vector based data sets.
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.