Quantum GIS API Documentation
1.7.4
|
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