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