Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 /* $Id$ */
18 
19 
21 #include "qgsprojectversion.h"
22 #include "qgslogger.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 "qgsprojectproperty.h"
30 
32 
33 
35 {
36  {PFV( 0, 8, 0 ), PFV( 0, 8, 1 ), &QgsProjectFileTransform::transformNull},
37  {PFV( 0, 8, 1 ), PFV( 0, 9, 0 ), &QgsProjectFileTransform::transform081to090},
38  {PFV( 0, 9, 0 ), PFV( 0, 9, 1 ), &QgsProjectFileTransform::transformNull},
39  {PFV( 0, 9, 1 ), PFV( 0, 10, 0 ), &QgsProjectFileTransform::transform091to0100},
40  {PFV( 0, 9, 2 ), PFV( 0, 10, 0 ), &QgsProjectFileTransform::transformNull},
41  {PFV( 0, 10, 0 ), PFV( 0, 11, 0 ), &QgsProjectFileTransform::transform0100to0110},
42  {PFV( 0, 11, 0 ), PFV( 1, 0, 0 ), &QgsProjectFileTransform::transform0110to1000},
43  {PFV( 1, 0, 0 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull},
44  {PFV( 1, 0, 2 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull},
45  {PFV( 1, 1, 0 ), PFV( 1, 2, 0 ), &QgsProjectFileTransform::transform1100to1200},
46  {PFV( 1, 2, 0 ), PFV( 1, 3, 0 ), &QgsProjectFileTransform::transformNull},
47  {PFV( 1, 3, 0 ), PFV( 1, 4, 0 ), &QgsProjectFileTransform::transformNull},
48  {PFV( 1, 4, 0 ), PFV( 1, 5, 0 ), &QgsProjectFileTransform::transform1400to1500},
49  {PFV( 1, 5, 0 ), PFV( 1, 6, 0 ), &QgsProjectFileTransform::transformNull},
50  {PFV( 1, 6, 0 ), PFV( 1, 7, 0 ), &QgsProjectFileTransform::transformNull},
51 };
52 
54 {
55  bool returnValue = false;
56 
57  if ( ! mDom.isNull() )
58  {
59  for ( std::size_t i = 0; i < sizeof( transformers ) / sizeof( transform ); i++ )
60  {
61  if ( transformers[i].from == mCurrentVersion )
62  {
63  // Run the transformer, and update the revision in every case
64  ( this->*( transformers[i].transformFunc ) )();
66  returnValue = true;
67  }
68  }
69  }
70  return returnValue;
71 }
72 
74 {
75  QgsDebugMsg( QString( "Current project file version is %1.%2.%3" )
78  .arg( mCurrentVersion.subVersion() ) );
79 #ifdef QGISDEBUG
80  // Using QgsDebugMsg() didn't print the entire mDom...
81  std::cout << mDom.toString( 2 ).toLatin1().constData(); // OK
82 #endif
83 }
84 
85 /*
86  * Transformers below!
87  */
88 
90 {
91  QgsDebugMsg( "Entering..." );
92  if ( ! mDom.isNull() )
93  {
94  // Start with inserting a mapcanvas element and populate it
95 
96  QDomElement mapCanvas; // A null element.
97 
98  // there should only be one <qgis>
99  QDomNode qgis = mDom.firstChildElement( "qgis" );
100  if ( ! qgis.isNull() )
101  {
102  QgsDebugMsg( "Populating new mapcanvas" );
103 
104  // Create a mapcanvas
105  mapCanvas = mDom.createElement( "mapcanvas" );
106  // Append mapcanvas to parent 'qgis'.
107  qgis.appendChild( mapCanvas );
108  // Re-parent units
109  mapCanvas.appendChild( qgis.namedItem( "units" ) );
110  // Re-parent extent
111  mapCanvas.appendChild( qgis.namedItem( "extent" ) );
112 
113  // See if we can find if projection is on.
114 
115  QDomElement properties = qgis.firstChildElement( "properties" );
116  QDomElement spatial = properties.firstChildElement( "SpatialRefSys" );
117  QDomElement hasCrsTransformEnabled = spatial.firstChildElement( "ProjectionsEnabled" );
118  // Type is 'int', and '1' if on.
119  // Create an element
120  QDomElement projection = mDom.createElement( "projections" );
121  QgsDebugMsg( QString( "Projection flag: " ) + hasCrsTransformEnabled.text() );
122  // Set flag from ProjectionsEnabled
123  projection.appendChild( mDom.createTextNode( hasCrsTransformEnabled.text() ) );
124  // Set new element as child of <mapcanvas>
125  mapCanvas.appendChild( projection );
126 
127  }
128 
129 
130  // Transforming coordinate-transforms
131  // Create a list of all map layers
132  QDomNodeList mapLayers = mDom.elementsByTagName( "maplayer" );
133  bool doneDestination = false;
134  for ( int i = 0; i < mapLayers.count(); i++ )
135  {
136  QDomNode mapLayer = mapLayers.item( i );
137  // Find the coordinatetransform
138  QDomNode coordinateTransform = mapLayer.namedItem( "coordinatetransform" );
139  // Find the sourcesrs
140  QDomNode sourceCrs = coordinateTransform.namedItem( "sourcesrs" );
141  // Rename to srs
142  sourceCrs.toElement().setTagName( "srs" );
143  // Re-parent to maplayer
144  mapLayer.appendChild( sourceCrs );
145  // Re-move coordinatetransform
146  // Take the destination CRS of the first layer and use for mapcanvas projection
147  if ( ! doneDestination )
148  {
149  // Use destination CRS from the last layer
150  QDomNode destinationCRS = coordinateTransform.namedItem( "destinationsrs" );
151  // Re-parent the destination CRS to the mapcanvas
152  // If mapcanvas wasn't set, nothing will happen.
153  mapCanvas.appendChild( destinationCRS );
154  // Only do this once
155  doneDestination = true;
156  }
157  mapLayer.removeChild( coordinateTransform );
158  //QDomNode id = mapLayer.namedItem("id");
159  //QgsDebugMsg(QString("Found maplayer ") + id.toElement().text());
160 
161  }
162 
163  // Set the flag 'visible' to match the status of 'checked'
164  QDomNodeList legendLayerFiles = mDom.elementsByTagName( "legendlayerfile" );
165  QgsDebugMsg( QString( "Legend layer file entries: " ) + QString::number( legendLayerFiles.count() ) );
166  for ( int i = 0; i < mapLayers.count(); i++ )
167  {
168  // Get one maplayer element from list
169  QDomElement mapLayer = mapLayers.item( i ).toElement();
170  // Find it's id.
171  QString id = mapLayer.firstChildElement( "id" ).text();
172  QgsDebugMsg( QString( "Handling layer " + id ) );
173  // Now, look it up in legend
174  for ( int j = 0; j < legendLayerFiles.count(); j++ )
175  {
176  QDomElement legendLayerFile = legendLayerFiles.item( j ).toElement();
177  if ( id == legendLayerFile.attribute( "layerid" ) )
178  {
179  // Found a the legend layer that matches the maplayer
180  QgsDebugMsg( "Found matching id" );
181 
182  // Set visible flag from maplayer to legendlayer
183  legendLayerFile.setAttribute( "visible", mapLayer.attribute( "visible" ) );
184 
185  // Set overview flag from maplayer to legendlayer
186  legendLayerFile.setAttribute( "isInOverview", mapLayer.attribute( "showInOverviewFlag" ) );
187  }
188  }
189  }
190  }
191  return;
192 
193 }
194 
196 {
197  QgsDebugMsg( "entering" );
198  if ( ! mDom.isNull() )
199  {
200  // Insert transforms here!
201  QDomNodeList rasterPropertyList = mDom.elementsByTagName( "rasterproperties" );
202  QgsDebugMsg( QString( "Raster properties file entries: " ) + QString::number( rasterPropertyList.count() ) );
203  for ( int i = 0; i < rasterPropertyList.count(); i++ )
204  {
205  // Get one rasterproperty element from list, and rename the sub-properties.
206  QDomNode rasterProperty = rasterPropertyList.item( i );
207  // rasterProperty.namedItem("").toElement().setTagName("");
208 
209  rasterProperty.namedItem( "stdDevsToPlotDouble" ).toElement().setTagName( "mStandardDeviations" );
210 
211  rasterProperty.namedItem( "invertHistogramFlag" ).toElement().setTagName( "mInvertPixelsFlag" );
212  rasterProperty.namedItem( "showDebugOverLayFlag" ).toElement().setTagName( "mDebugOverLayFlag" );
213 
214  rasterProperty.namedItem( "redBandNameQString" ).toElement().setTagName( "mRedBandName" );
215  rasterProperty.namedItem( "blueBandNameQString" ).toElement().setTagName( "mBlueBandName" );
216  rasterProperty.namedItem( "greenBandNameQString" ).toElement().setTagName( "mGreenBandName" );
217  rasterProperty.namedItem( "grayBandNameQString" ).toElement().setTagName( "mGrayBandName" );
218  }
219 
220  // Changing symbol size for hard: symbols
221  QDomNodeList symbolPropertyList = mDom.elementsByTagName( "symbol" );
222  for ( int i = 0; i < symbolPropertyList.count(); i++ )
223  {
224  // Get the <poinmtsymbol> to check for 'hard:' for each <symbol>
225  QDomNode symbolProperty = symbolPropertyList.item( i );
226 
227  QDomElement pointSymbol = symbolProperty.firstChildElement( "pointsymbol" );
228  if ( pointSymbol.text().startsWith( "hard:" ) )
229  {
230  // Get pointsize and line width
231  int lineWidth = symbolProperty.firstChildElement( "outlinewidth" ).text().toInt();
232  int pointSize = symbolProperty.firstChildElement( "pointsize" ).text().toInt();
233  // Just a precaution, checking for 0
234  if ( pointSize != 0 )
235  {
236  // int r = (s-2*lw)/2-1 --> 2r = (s-2*lw)-2 --> 2r+2 = s-2*lw
237  // --> 2r+2+2*lw = s
238  // where '2r' is the old size.
239  pointSize = pointSize + 2 + 2 * lineWidth;
240  QgsDebugMsg( QString( "Setting point size to %1" ).arg( pointSize ) );
241  QDomElement newPointSizeProperty = mDom.createElement( "pointsize" );
242  QDomText newPointSizeTxt = mDom.createTextNode( QString::number( pointSize ) );
243  newPointSizeProperty.appendChild( newPointSizeTxt );
244  symbolProperty.replaceChild( newPointSizeProperty, pointSymbol );
245  }
246  }
247  }
248 
249  }
250  return;
251 
252 }
253 
255 {
256  if ( ! mDom.isNull() )
257  {
258  //Change 'outlinewidth' in QgsSymbol
259  QPrinter myPrinter( QPrinter::ScreenResolution );
260  int screenDpi = myPrinter.resolution();
261  double widthScaleFactor = 25.4 / screenDpi;
262 
263  QDomNodeList outlineWidthList = mDom.elementsByTagName( "outlinewidth" );
264  for ( int i = 0; i < outlineWidthList.size(); ++i )
265  {
266  //calculate new width
267  QDomElement currentOutlineElem = outlineWidthList.at( i ).toElement();
268  double outlineWidth = currentOutlineElem.text().toDouble();
269  outlineWidth *= widthScaleFactor;
270 
271  //replace old text node
272  QDomNode outlineTextNode = currentOutlineElem.firstChild();
273  QDomText newOutlineText = mDom.createTextNode( QString::number( outlineWidth ) );
274  currentOutlineElem.replaceChild( newOutlineText, outlineTextNode );
275 
276  }
277 
278  //Change 'pointsize' in QgsSymbol
279  QDomNodeList pointSizeList = mDom.elementsByTagName( "pointsize" );
280  for ( int i = 0; i < pointSizeList.size(); ++i )
281  {
282  //calculate new size
283  QDomElement currentPointSizeElem = pointSizeList.at( i ).toElement();
284  double pointSize = currentPointSizeElem.text().toDouble();
285  pointSize *= widthScaleFactor;
286 
287  //replace old text node
288  QDomNode pointSizeTextNode = currentPointSizeElem.firstChild();
289  QDomText newPointSizeText = mDom.createTextNode( QString::number(( int )pointSize ) );
290  currentPointSizeElem.replaceChild( newPointSizeText, pointSizeTextNode );
291  }
292  }
293 }
294 
296 {
297  if ( ! mDom.isNull() )
298  {
299  QDomNodeList layerList = mDom.elementsByTagName( "maplayer" );
300  for ( int i = 0; i < layerList.size(); ++i )
301  {
302  QDomElement layerElem = layerList.at( i ).toElement();
303  QString typeString = layerElem.attribute( "type" );
304  if ( typeString != "vector" )
305  {
306  continue;
307  }
308 
309  //datasource
310  QDomNode dataSourceNode = layerElem.namedItem( "datasource" );
311  if ( dataSourceNode.isNull() )
312  {
313  return;
314  }
315  QString dataSource = dataSourceNode.toElement().text();
316 
317  //provider key
318  QDomNode providerNode = layerElem.namedItem( "provider" );
319  if ( providerNode.isNull() )
320  {
321  return;
322  }
323  QString providerKey = providerNode.toElement().text();
324 
325  //create the layer to get the provider for int->fieldName conversion
326  QgsVectorLayer* theLayer = new QgsVectorLayer( dataSource, "", providerKey, false );
327  if ( !theLayer->isValid() )
328  {
329  delete theLayer;
330  return;
331  }
332 
333  QgsVectorDataProvider* theProvider = theLayer->dataProvider();
334  if ( !theProvider )
335  {
336  return;
337  }
338  QgsFieldMap theFieldMap = theProvider->fields();
339 
340  //read classificationfield
341  QDomNodeList classificationFieldList = layerElem.elementsByTagName( "classificationfield" );
342  for ( int j = 0; j < classificationFieldList.size(); ++j )
343  {
344  QDomElement classificationFieldElem = classificationFieldList.at( j ).toElement();
345  int fieldNumber = classificationFieldElem.text().toInt();
346  QgsFieldMap::const_iterator field_it = theFieldMap.find( fieldNumber );
347  if ( field_it != theFieldMap.constEnd() )
348  {
349  QDomText fieldName = mDom.createTextNode( field_it.value().name() );
350  QDomNode nameNode = classificationFieldElem.firstChild();
351  classificationFieldElem.replaceChild( fieldName, nameNode );
352  }
353  }
354 
355  }
356  }
357 }
358 
360 {
361  QgsDebugMsg( "Entering..." );
362  if ( mDom.isNull() )
363  return;
364 
365  QDomNode qgis = mDom.firstChildElement( "qgis" );
366  if ( qgis.isNull() )
367  return;
368 
369  QDomElement properties = qgis.firstChildElement( "properties" );
370  if ( properties.isNull() )
371  return;
372 
373  QDomElement digitizing = properties.firstChildElement( "Digitizing" );
374  if ( digitizing.isNull() )
375  return;
376 
377  QDomElement tolList = digitizing.firstChildElement( "LayerSnappingToleranceList" );
378  if ( tolList.isNull() )
379  return;
380 
381  QDomElement tolUnitList = digitizing.firstChildElement( "LayerSnappingToleranceUnitList" );
382  if ( !tolUnitList.isNull() )
383  return;
384 
385  QStringList units;
386  for ( int i = 0; i < tolList.childNodes().count(); i++ )
387  units << "0";
388 
389  QgsPropertyValue value( units );
390  value.writeXML( "LayerSnappingToleranceUnitList", digitizing, mDom );
391 }
392 
394 {
395  //Adapt the XML description of the composer legend model to version 1.5
396  if ( mDom.isNull() )
397  {
398  return;
399  }
400  //Add layer id to <VectorClassificationItem>
401  QDomNodeList layerItemList = mDom.elementsByTagName( "LayerItem" );
402  QDomElement currentLayerItemElem;
403  QString currentLayerId;
404 
405  for ( int i = 0; i < layerItemList.size(); ++i )
406  {
407  currentLayerItemElem = layerItemList.at( i ).toElement();
408  if ( currentLayerItemElem.isNull() )
409  {
410  continue;
411  }
412  currentLayerId = currentLayerItemElem.attribute( "layerId" );
413 
414  QDomNodeList vectorClassificationList = currentLayerItemElem.elementsByTagName( "VectorClassificationItem" );
415  QDomElement currentClassificationElem;
416  for ( int j = 0; j < vectorClassificationList.size(); ++j )
417  {
418  currentClassificationElem = vectorClassificationList.at( j ).toElement();
419  if ( !currentClassificationElem.isNull() )
420  {
421  currentClassificationElem.setAttribute( "layerId", currentLayerId );
422  }
423  }
424 
425  //replace the text items with VectorClassification or RasterClassification items
426  QDomNodeList textItemList = currentLayerItemElem.elementsByTagName( "TextItem" );
427  QDomElement currentTextItem;
428 
429  for ( int j = 0; j < textItemList.size(); ++j )
430  {
431  currentTextItem = textItemList.at( j ).toElement();
432  if ( currentTextItem.isNull() )
433  {
434  continue;
435  }
436 
437  QDomElement classificationElement;
438  if ( vectorClassificationList.size() > 0 ) //we guess it is a vector layer
439  {
440  classificationElement = mDom.createElement( "VectorClassificationItem" );
441  }
442  else
443  {
444  classificationElement = mDom.createElement( "RasterClassificationItem" );
445  }
446 
447  classificationElement.setAttribute( "layerId", currentLayerId );
448  classificationElement.setAttribute( "text", currentTextItem.attribute( "text" ) );
449  currentLayerItemElem.replaceChild( classificationElement, currentTextItem );
450  }
451  }
452 }
453