Quantum GIS API Documentation  1.7.4
src/core/qgsprojectfiletransform.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           qgsprojectfiletransform.cpp  -  description
00003                              -------------------
00004     begin                : Sun 15 dec 2007
00005     copyright            : (C) 2007 by Magnus Homann
00006     email                : magnus at homann.se
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 /* $Id$ */
00018 
00019 
00020 #include "qgsprojectfiletransform.h"
00021 #include "qgsprojectversion.h"
00022 #include "qgslogger.h"
00023 #include "qgsvectordataprovider.h"
00024 #include "qgsvectorlayer.h"
00025 #include <QTextStream>
00026 #include <QDomDocument>
00027 #include <QPrinter> //to find out screen resolution
00028 #include <cstdlib>
00029 #include "qgsprojectproperty.h"
00030 
00031 typedef QgsProjectVersion PFV;
00032 
00033 
00034 QgsProjectFileTransform::transform QgsProjectFileTransform::transformers[] =
00035 {
00036   {PFV( 0, 8, 0 ), PFV( 0, 8, 1 ), &QgsProjectFileTransform::transformNull},
00037   {PFV( 0, 8, 1 ), PFV( 0, 9, 0 ), &QgsProjectFileTransform::transform081to090},
00038   {PFV( 0, 9, 0 ), PFV( 0, 9, 1 ), &QgsProjectFileTransform::transformNull},
00039   {PFV( 0, 9, 1 ), PFV( 0, 10, 0 ), &QgsProjectFileTransform::transform091to0100},
00040   {PFV( 0, 9, 2 ), PFV( 0, 10, 0 ), &QgsProjectFileTransform::transformNull},
00041   {PFV( 0, 10, 0 ), PFV( 0, 11, 0 ), &QgsProjectFileTransform::transform0100to0110},
00042   {PFV( 0, 11, 0 ), PFV( 1, 0, 0 ), &QgsProjectFileTransform::transform0110to1000},
00043   {PFV( 1, 0, 0 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull},
00044   {PFV( 1, 0, 2 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull},
00045   {PFV( 1, 1, 0 ), PFV( 1, 2, 0 ), &QgsProjectFileTransform::transform1100to1200},
00046   {PFV( 1, 2, 0 ), PFV( 1, 3, 0 ), &QgsProjectFileTransform::transformNull},
00047   {PFV( 1, 3, 0 ), PFV( 1, 4, 0 ), &QgsProjectFileTransform::transformNull},
00048   {PFV( 1, 4, 0 ), PFV( 1, 5, 0 ), &QgsProjectFileTransform::transform1400to1500},
00049   {PFV( 1, 5, 0 ), PFV( 1, 6, 0 ), &QgsProjectFileTransform::transformNull},
00050   {PFV( 1, 6, 0 ), PFV( 1, 7, 0 ), &QgsProjectFileTransform::transformNull},
00051 };
00052 
00053 bool QgsProjectFileTransform::updateRevision( QgsProjectVersion newVersion )
00054 {
00055   bool returnValue = false;
00056 
00057   if ( ! mDom.isNull() )
00058   {
00059     for ( std::size_t i = 0; i < sizeof( transformers ) / sizeof( transform ); i++ )
00060     {
00061       if ( transformers[i].from == mCurrentVersion )
00062       {
00063         // Run the transformer, and update the revision in every case
00064         ( this->*( transformers[i].transformFunc ) )();
00065         mCurrentVersion = transformers[i].to;
00066         returnValue = true;
00067       }
00068     }
00069   }
00070   return returnValue;
00071 }
00072 
00073 void QgsProjectFileTransform::dump()
00074 {
00075   QgsDebugMsg( QString( "Current project file version is %1.%2.%3" )
00076                .arg( mCurrentVersion.majorVersion() )
00077                .arg( mCurrentVersion.minorVersion() )
00078                .arg( mCurrentVersion.subVersion() ) );
00079 #ifdef QGISDEBUG
00080   // Using QgsDebugMsg() didn't print the entire mDom...
00081   std::cout << mDom.toString( 2 ).toLatin1().constData(); // OK
00082 #endif
00083 }
00084 
00085 /*
00086  *  Transformers below!
00087  */
00088 
00089 void QgsProjectFileTransform::transform081to090()
00090 {
00091   QgsDebugMsg( "Entering..." );
00092   if ( ! mDom.isNull() )
00093   {
00094     // Start with inserting a mapcanvas element and populate it
00095 
00096     QDomElement mapCanvas; // A null element.
00097 
00098     // there should only be one <qgis>
00099     QDomNode qgis = mDom.firstChildElement( "qgis" );
00100     if ( ! qgis.isNull() )
00101     {
00102       QgsDebugMsg( "Populating new mapcanvas" );
00103 
00104       // Create a mapcanvas
00105       mapCanvas = mDom.createElement( "mapcanvas" );
00106       // Append mapcanvas to parent 'qgis'.
00107       qgis.appendChild( mapCanvas );
00108       // Re-parent units
00109       mapCanvas.appendChild( qgis.namedItem( "units" ) );
00110       // Re-parent extent
00111       mapCanvas.appendChild( qgis.namedItem( "extent" ) );
00112 
00113       // See if we can find if projection is on.
00114 
00115       QDomElement properties = qgis.firstChildElement( "properties" );
00116       QDomElement spatial = properties.firstChildElement( "SpatialRefSys" );
00117       QDomElement hasCrsTransformEnabled = spatial.firstChildElement( "ProjectionsEnabled" );
00118       // Type is 'int', and '1' if on.
00119       // Create an element
00120       QDomElement projection = mDom.createElement( "projections" );
00121       QgsDebugMsg( QString( "Projection flag: " ) + hasCrsTransformEnabled.text() );
00122       // Set flag from ProjectionsEnabled
00123       projection.appendChild( mDom.createTextNode( hasCrsTransformEnabled.text() ) );
00124       // Set new element as child of <mapcanvas>
00125       mapCanvas.appendChild( projection );
00126 
00127     }
00128 
00129 
00130     // Transforming coordinate-transforms
00131     // Create a list of all map layers
00132     QDomNodeList mapLayers = mDom.elementsByTagName( "maplayer" );
00133     bool doneDestination = false;
00134     for ( int i = 0; i < mapLayers.count(); i++ )
00135     {
00136       QDomNode mapLayer = mapLayers.item( i );
00137       // Find the coordinatetransform
00138       QDomNode coordinateTransform = mapLayer.namedItem( "coordinatetransform" );
00139       // Find the sourcesrs
00140       QDomNode sourceCrs = coordinateTransform.namedItem( "sourcesrs" );
00141       // Rename to srs
00142       sourceCrs.toElement().setTagName( "srs" );
00143       // Re-parent to maplayer
00144       mapLayer.appendChild( sourceCrs );
00145       // Re-move coordinatetransform
00146       // Take the destination CRS of the first layer and use for mapcanvas projection
00147       if ( ! doneDestination )
00148       {
00149         // Use destination CRS from the last layer
00150         QDomNode destinationCRS = coordinateTransform.namedItem( "destinationsrs" );
00151         // Re-parent the destination CRS to the mapcanvas
00152         // If mapcanvas wasn't set, nothing will happen.
00153         mapCanvas.appendChild( destinationCRS );
00154         // Only do this once
00155         doneDestination = true;
00156       }
00157       mapLayer.removeChild( coordinateTransform );
00158       //QDomNode id = mapLayer.namedItem("id");
00159       //QgsDebugMsg(QString("Found maplayer ") + id.toElement().text());
00160 
00161     }
00162 
00163     // Set the flag 'visible' to match the status of 'checked'
00164     QDomNodeList legendLayerFiles = mDom.elementsByTagName( "legendlayerfile" );
00165     QgsDebugMsg( QString( "Legend layer file entries: " ) + QString::number( legendLayerFiles.count() ) );
00166     for ( int i = 0; i < mapLayers.count(); i++ )
00167     {
00168       // Get one maplayer element from list
00169       QDomElement mapLayer = mapLayers.item( i ).toElement();
00170       // Find it's id.
00171       QString id = mapLayer.firstChildElement( "id" ).text();
00172       QgsDebugMsg( QString( "Handling layer " + id ) );
00173       // Now, look it up in legend
00174       for ( int j = 0; j < legendLayerFiles.count(); j++ )
00175       {
00176         QDomElement legendLayerFile = legendLayerFiles.item( j ).toElement();
00177         if ( id == legendLayerFile.attribute( "layerid" ) )
00178         {
00179           // Found a the legend layer that matches the maplayer
00180           QgsDebugMsg( "Found matching id" );
00181 
00182           // Set visible flag from maplayer to legendlayer
00183           legendLayerFile.setAttribute( "visible", mapLayer.attribute( "visible" ) );
00184 
00185           // Set overview flag from maplayer to legendlayer
00186           legendLayerFile.setAttribute( "isInOverview", mapLayer.attribute( "showInOverviewFlag" ) );
00187         }
00188       }
00189     }
00190   }
00191   return;
00192 
00193 }
00194 
00195 void QgsProjectFileTransform::transform091to0100()
00196 {
00197   QgsDebugMsg( "entering" );
00198   if ( ! mDom.isNull() )
00199   {
00200     // Insert transforms here!
00201     QDomNodeList rasterPropertyList = mDom.elementsByTagName( "rasterproperties" );
00202     QgsDebugMsg( QString( "Raster properties file entries: " ) + QString::number( rasterPropertyList.count() ) );
00203     for ( int i = 0; i < rasterPropertyList.count(); i++ )
00204     {
00205       // Get one rasterproperty element from list, and rename the sub-properties.
00206       QDomNode rasterProperty = rasterPropertyList.item( i );
00207       // rasterProperty.namedItem("").toElement().setTagName("");
00208 
00209       rasterProperty.namedItem( "stdDevsToPlotDouble" ).toElement().setTagName( "mStandardDeviations" );
00210 
00211       rasterProperty.namedItem( "invertHistogramFlag" ).toElement().setTagName( "mInvertPixelsFlag" );
00212       rasterProperty.namedItem( "showDebugOverLayFlag" ).toElement().setTagName( "mDebugOverLayFlag" );
00213 
00214       rasterProperty.namedItem( "redBandNameQString" ).toElement().setTagName( "mRedBandName" );
00215       rasterProperty.namedItem( "blueBandNameQString" ).toElement().setTagName( "mBlueBandName" );
00216       rasterProperty.namedItem( "greenBandNameQString" ).toElement().setTagName( "mGreenBandName" );
00217       rasterProperty.namedItem( "grayBandNameQString" ).toElement().setTagName( "mGrayBandName" );
00218     }
00219 
00220     // Changing symbol size for hard: symbols
00221     QDomNodeList symbolPropertyList = mDom.elementsByTagName( "symbol" );
00222     for ( int i = 0; i < symbolPropertyList.count(); i++ )
00223     {
00224       // Get the <poinmtsymbol> to check for 'hard:' for each <symbol>
00225       QDomNode symbolProperty = symbolPropertyList.item( i );
00226 
00227       QDomElement pointSymbol = symbolProperty.firstChildElement( "pointsymbol" );
00228       if ( pointSymbol.text().startsWith( "hard:" ) )
00229       {
00230         // Get pointsize and line width
00231         int lineWidth = symbolProperty.firstChildElement( "outlinewidth" ).text().toInt();
00232         int pointSize = symbolProperty.firstChildElement( "pointsize" ).text().toInt();
00233         // Just a precaution, checking for 0
00234         if ( pointSize != 0 )
00235         {
00236           // int r = (s-2*lw)/2-1 --> 2r = (s-2*lw)-2 --> 2r+2 = s-2*lw
00237           // --> 2r+2+2*lw = s
00238           // where '2r' is the old size.
00239           pointSize = pointSize + 2 + 2 * lineWidth;
00240           QgsDebugMsg( QString( "Setting point size to %1" ).arg( pointSize ) );
00241           QDomElement newPointSizeProperty = mDom.createElement( "pointsize" );
00242           QDomText newPointSizeTxt = mDom.createTextNode( QString::number( pointSize ) );
00243           newPointSizeProperty.appendChild( newPointSizeTxt );
00244           symbolProperty.replaceChild( newPointSizeProperty, pointSymbol );
00245         }
00246       }
00247     }
00248 
00249   }
00250   return;
00251 
00252 }
00253 
00254 void QgsProjectFileTransform::transform0100to0110()
00255 {
00256   if ( ! mDom.isNull() )
00257   {
00258     //Change 'outlinewidth' in QgsSymbol
00259     QPrinter myPrinter( QPrinter::ScreenResolution );
00260     int screenDpi = myPrinter.resolution();
00261     double widthScaleFactor = 25.4 / screenDpi;
00262 
00263     QDomNodeList outlineWidthList = mDom.elementsByTagName( "outlinewidth" );
00264     for ( int i = 0; i < outlineWidthList.size(); ++i )
00265     {
00266       //calculate new width
00267       QDomElement currentOutlineElem = outlineWidthList.at( i ).toElement();
00268       double outlineWidth = currentOutlineElem.text().toDouble();
00269       outlineWidth *= widthScaleFactor;
00270 
00271       //replace old text node
00272       QDomNode outlineTextNode = currentOutlineElem.firstChild();
00273       QDomText newOutlineText = mDom.createTextNode( QString::number( outlineWidth ) );
00274       currentOutlineElem.replaceChild( newOutlineText, outlineTextNode );
00275 
00276     }
00277 
00278     //Change 'pointsize' in QgsSymbol
00279     QDomNodeList pointSizeList = mDom.elementsByTagName( "pointsize" );
00280     for ( int i = 0; i < pointSizeList.size(); ++i )
00281     {
00282       //calculate new size
00283       QDomElement currentPointSizeElem = pointSizeList.at( i ).toElement();
00284       double pointSize = currentPointSizeElem.text().toDouble();
00285       pointSize *= widthScaleFactor;
00286 
00287       //replace old text node
00288       QDomNode pointSizeTextNode = currentPointSizeElem.firstChild();
00289       QDomText newPointSizeText = mDom.createTextNode( QString::number(( int )pointSize ) );
00290       currentPointSizeElem.replaceChild( newPointSizeText, pointSizeTextNode );
00291     }
00292   }
00293 }
00294 
00295 void QgsProjectFileTransform::transform0110to1000()
00296 {
00297   if ( ! mDom.isNull() )
00298   {
00299     QDomNodeList layerList = mDom.elementsByTagName( "maplayer" );
00300     for ( int i = 0; i < layerList.size(); ++i )
00301     {
00302       QDomElement layerElem = layerList.at( i ).toElement();
00303       QString typeString = layerElem.attribute( "type" );
00304       if ( typeString != "vector" )
00305       {
00306         continue;
00307       }
00308 
00309       //datasource
00310       QDomNode dataSourceNode = layerElem.namedItem( "datasource" );
00311       if ( dataSourceNode.isNull() )
00312       {
00313         return;
00314       }
00315       QString dataSource = dataSourceNode.toElement().text();
00316 
00317       //provider key
00318       QDomNode providerNode = layerElem.namedItem( "provider" );
00319       if ( providerNode.isNull() )
00320       {
00321         return;
00322       }
00323       QString providerKey = providerNode.toElement().text();
00324 
00325       //create the layer to get the provider for int->fieldName conversion
00326       QgsVectorLayer* theLayer = new QgsVectorLayer( dataSource, "", providerKey, false );
00327       if ( !theLayer->isValid() )
00328       {
00329         delete theLayer;
00330         return;
00331       }
00332 
00333       QgsVectorDataProvider* theProvider = theLayer->dataProvider();
00334       if ( !theProvider )
00335       {
00336         return;
00337       }
00338       QgsFieldMap theFieldMap = theProvider->fields();
00339 
00340       //read classificationfield
00341       QDomNodeList classificationFieldList = layerElem.elementsByTagName( "classificationfield" );
00342       for ( int j = 0; j < classificationFieldList.size(); ++j )
00343       {
00344         QDomElement classificationFieldElem = classificationFieldList.at( j ).toElement();
00345         int fieldNumber = classificationFieldElem.text().toInt();
00346         QgsFieldMap::const_iterator field_it = theFieldMap.find( fieldNumber );
00347         if ( field_it != theFieldMap.constEnd() )
00348         {
00349           QDomText fieldName = mDom.createTextNode( field_it.value().name() );
00350           QDomNode nameNode = classificationFieldElem.firstChild();
00351           classificationFieldElem.replaceChild( fieldName, nameNode );
00352         }
00353       }
00354 
00355     }
00356   }
00357 }
00358 
00359 void QgsProjectFileTransform::transform1100to1200()
00360 {
00361   QgsDebugMsg( "Entering..." );
00362   if ( mDom.isNull() )
00363     return;
00364 
00365   QDomNode qgis = mDom.firstChildElement( "qgis" );
00366   if ( qgis.isNull() )
00367     return;
00368 
00369   QDomElement properties = qgis.firstChildElement( "properties" );
00370   if ( properties.isNull() )
00371     return;
00372 
00373   QDomElement digitizing = properties.firstChildElement( "Digitizing" );
00374   if ( digitizing.isNull() )
00375     return;
00376 
00377   QDomElement tolList = digitizing.firstChildElement( "LayerSnappingToleranceList" );
00378   if ( tolList.isNull() )
00379     return;
00380 
00381   QDomElement tolUnitList = digitizing.firstChildElement( "LayerSnappingToleranceUnitList" );
00382   if ( !tolUnitList.isNull() )
00383     return;
00384 
00385   QStringList units;
00386   for ( int i = 0; i < tolList.childNodes().count(); i++ )
00387     units << "0";
00388 
00389   QgsPropertyValue value( units );
00390   value.writeXML( "LayerSnappingToleranceUnitList", digitizing, mDom );
00391 }
00392 
00393 void QgsProjectFileTransform::transform1400to1500()
00394 {
00395   //Adapt the XML description of the composer legend model to version 1.5
00396   if ( mDom.isNull() )
00397   {
00398     return;
00399   }
00400   //Add layer id to <VectorClassificationItem>
00401   QDomNodeList layerItemList = mDom.elementsByTagName( "LayerItem" );
00402   QDomElement currentLayerItemElem;
00403   QString currentLayerId;
00404 
00405   for ( int i = 0; i < layerItemList.size(); ++i )
00406   {
00407     currentLayerItemElem = layerItemList.at( i ).toElement();
00408     if ( currentLayerItemElem.isNull() )
00409     {
00410       continue;
00411     }
00412     currentLayerId = currentLayerItemElem.attribute( "layerId" );
00413 
00414     QDomNodeList vectorClassificationList = currentLayerItemElem.elementsByTagName( "VectorClassificationItem" );
00415     QDomElement currentClassificationElem;
00416     for ( int j = 0; j < vectorClassificationList.size(); ++j )
00417     {
00418       currentClassificationElem = vectorClassificationList.at( j ).toElement();
00419       if ( !currentClassificationElem.isNull() )
00420       {
00421         currentClassificationElem.setAttribute( "layerId", currentLayerId );
00422       }
00423     }
00424 
00425     //replace the text items with VectorClassification or RasterClassification items
00426     QDomNodeList textItemList = currentLayerItemElem.elementsByTagName( "TextItem" );
00427     QDomElement currentTextItem;
00428 
00429     for ( int j = 0; j < textItemList.size(); ++j )
00430     {
00431       currentTextItem = textItemList.at( j ).toElement();
00432       if ( currentTextItem.isNull() )
00433       {
00434         continue;
00435       }
00436 
00437       QDomElement classificationElement;
00438       if ( vectorClassificationList.size() > 0 ) //we guess it is a vector layer
00439       {
00440         classificationElement = mDom.createElement( "VectorClassificationItem" );
00441       }
00442       else
00443       {
00444         classificationElement = mDom.createElement( "RasterClassificationItem" );
00445       }
00446 
00447       classificationElement.setAttribute( "layerId", currentLayerId );
00448       classificationElement.setAttribute( "text", currentTextItem.attribute( "text" ) );
00449       currentLayerItemElem.replaceChild( classificationElement, currentTextItem );
00450     }
00451   }
00452 }
00453 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines