|
QGIS API Documentation
master-3f58142
|
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 00018 00019 #include "qgsprojectfiletransform.h" 00020 #include "qgsprojectversion.h" 00021 #include "qgslogger.h" 00022 #include "qgsrasterlayer.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 "qgsproject.h" 00030 #include "qgsprojectproperty.h" 00031 00032 typedef QgsProjectVersion PFV; 00033 00034 00035 QgsProjectFileTransform::transform QgsProjectFileTransform::transformers[] = 00036 { 00037 {PFV( 0, 8, 0 ), PFV( 0, 8, 1 ), &QgsProjectFileTransform::transformNull}, 00038 {PFV( 0, 8, 1 ), PFV( 0, 9, 0 ), &QgsProjectFileTransform::transform081to090}, 00039 {PFV( 0, 9, 0 ), PFV( 0, 9, 1 ), &QgsProjectFileTransform::transformNull}, 00040 {PFV( 0, 9, 1 ), PFV( 0, 10, 0 ), &QgsProjectFileTransform::transform091to0100}, 00041 // Following line is a hack that takes us straight from 0.9.2 to 0.11.0 00042 // due to an unknown bug in migrating 0.9.2 files which we didnt pursue (TS & GS) 00043 {PFV( 0, 9, 2 ), PFV( 0, 11, 0 ), &QgsProjectFileTransform::transformNull}, 00044 {PFV( 0, 10, 0 ), PFV( 0, 11, 0 ), &QgsProjectFileTransform::transform0100to0110}, 00045 {PFV( 0, 11, 0 ), PFV( 1, 0, 0 ), &QgsProjectFileTransform::transform0110to1000}, 00046 {PFV( 1, 0, 0 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull}, 00047 {PFV( 1, 0, 2 ), PFV( 1, 1, 0 ), &QgsProjectFileTransform::transformNull}, 00048 {PFV( 1, 1, 0 ), PFV( 1, 2, 0 ), &QgsProjectFileTransform::transform1100to1200}, 00049 {PFV( 1, 2, 0 ), PFV( 1, 3, 0 ), &QgsProjectFileTransform::transformNull}, 00050 {PFV( 1, 3, 0 ), PFV( 1, 4, 0 ), &QgsProjectFileTransform::transformNull}, 00051 {PFV( 1, 4, 0 ), PFV( 1, 5, 0 ), &QgsProjectFileTransform::transform1400to1500}, 00052 {PFV( 1, 5, 0 ), PFV( 1, 6, 0 ), &QgsProjectFileTransform::transformNull}, 00053 {PFV( 1, 6, 0 ), PFV( 1, 7, 0 ), &QgsProjectFileTransform::transformNull}, 00054 {PFV( 1, 7, 0 ), PFV( 1, 8, 0 ), &QgsProjectFileTransform::transformNull}, 00055 {PFV( 1, 8, 0 ), PFV( 1, 9, 0 ), &QgsProjectFileTransform::transform1800to1900} 00056 }; 00057 00058 bool QgsProjectFileTransform::updateRevision( QgsProjectVersion newVersion ) 00059 { 00060 Q_UNUSED( newVersion ); 00061 bool returnValue = false; 00062 00063 if ( ! mDom.isNull() ) 00064 { 00065 for ( std::size_t i = 0; i < sizeof( transformers ) / sizeof( transform ); i++ ) 00066 { 00067 if ( transformers[i].from == mCurrentVersion ) 00068 { 00069 // Run the transformer, and update the revision in every case 00070 ( this->*( transformers[i].transformFunc ) )(); 00071 mCurrentVersion = transformers[i].to; 00072 returnValue = true; 00073 } 00074 } 00075 } 00076 return returnValue; 00077 } 00078 00079 void QgsProjectFileTransform::dump() 00080 { 00081 QgsDebugMsg( QString( "Current project file version is %1.%2.%3" ) 00082 .arg( mCurrentVersion.majorVersion() ) 00083 .arg( mCurrentVersion.minorVersion() ) 00084 .arg( mCurrentVersion.subVersion() ) ); 00085 #ifdef QGISDEBUG 00086 // Using QgsDebugMsg() didn't print the entire mDom... 00087 std::cout << mDom.toString( 2 ).toLatin1().constData(); // OK 00088 #endif 00089 } 00090 00091 /* 00092 * Transformers below! 00093 */ 00094 00095 void QgsProjectFileTransform::transform081to090() 00096 { 00097 QgsDebugMsg( "Entering..." ); 00098 if ( ! mDom.isNull() ) 00099 { 00100 // Start with inserting a mapcanvas element and populate it 00101 00102 QDomElement mapCanvas; // A null element. 00103 00104 // there should only be one <qgis> 00105 QDomNode qgis = mDom.firstChildElement( "qgis" ); 00106 if ( ! qgis.isNull() ) 00107 { 00108 QgsDebugMsg( "Populating new mapcanvas" ); 00109 00110 // Create a mapcanvas 00111 mapCanvas = mDom.createElement( "mapcanvas" ); 00112 // Append mapcanvas to parent 'qgis'. 00113 qgis.appendChild( mapCanvas ); 00114 // Re-parent units 00115 mapCanvas.appendChild( qgis.namedItem( "units" ) ); 00116 // Re-parent extent 00117 mapCanvas.appendChild( qgis.namedItem( "extent" ) ); 00118 00119 // See if we can find if projection is on. 00120 00121 QDomElement properties = qgis.firstChildElement( "properties" ); 00122 QDomElement spatial = properties.firstChildElement( "SpatialRefSys" ); 00123 QDomElement hasCrsTransformEnabled = spatial.firstChildElement( "ProjectionsEnabled" ); 00124 // Type is 'int', and '1' if on. 00125 // Create an element 00126 QDomElement projection = mDom.createElement( "projections" ); 00127 QgsDebugMsg( QString( "Projection flag: " ) + hasCrsTransformEnabled.text() ); 00128 // Set flag from ProjectionsEnabled 00129 projection.appendChild( mDom.createTextNode( hasCrsTransformEnabled.text() ) ); 00130 // Set new element as child of <mapcanvas> 00131 mapCanvas.appendChild( projection ); 00132 00133 } 00134 00135 00136 // Transforming coordinate-transforms 00137 // Create a list of all map layers 00138 QDomNodeList mapLayers = mDom.elementsByTagName( "maplayer" ); 00139 bool doneDestination = false; 00140 for ( int i = 0; i < mapLayers.count(); i++ ) 00141 { 00142 QDomNode mapLayer = mapLayers.item( i ); 00143 // Find the coordinatetransform 00144 QDomNode coordinateTransform = mapLayer.namedItem( "coordinatetransform" ); 00145 // Find the sourcesrs 00146 QDomNode sourceCrs = coordinateTransform.namedItem( "sourcesrs" ); 00147 // Rename to srs 00148 sourceCrs.toElement().setTagName( "srs" ); 00149 // Re-parent to maplayer 00150 mapLayer.appendChild( sourceCrs ); 00151 // Re-move coordinatetransform 00152 // Take the destination CRS of the first layer and use for mapcanvas projection 00153 if ( ! doneDestination ) 00154 { 00155 // Use destination CRS from the last layer 00156 QDomNode destinationCRS = coordinateTransform.namedItem( "destinationsrs" ); 00157 // Re-parent the destination CRS to the mapcanvas 00158 // If mapcanvas wasn't set, nothing will happen. 00159 mapCanvas.appendChild( destinationCRS ); 00160 // Only do this once 00161 doneDestination = true; 00162 } 00163 mapLayer.removeChild( coordinateTransform ); 00164 //QDomNode id = mapLayer.namedItem("id"); 00165 //QgsDebugMsg(QString("Found maplayer ") + id.toElement().text()); 00166 00167 } 00168 00169 // Set the flag 'visible' to match the status of 'checked' 00170 QDomNodeList legendLayerFiles = mDom.elementsByTagName( "legendlayerfile" ); 00171 QgsDebugMsg( QString( "Legend layer file entries: " ) + QString::number( legendLayerFiles.count() ) ); 00172 for ( int i = 0; i < mapLayers.count(); i++ ) 00173 { 00174 // Get one maplayer element from list 00175 QDomElement mapLayer = mapLayers.item( i ).toElement(); 00176 // Find it's id. 00177 QString id = mapLayer.firstChildElement( "id" ).text(); 00178 QgsDebugMsg( QString( "Handling layer " + id ) ); 00179 // Now, look it up in legend 00180 for ( int j = 0; j < legendLayerFiles.count(); j++ ) 00181 { 00182 QDomElement legendLayerFile = legendLayerFiles.item( j ).toElement(); 00183 if ( id == legendLayerFile.attribute( "layerid" ) ) 00184 { 00185 // Found a the legend layer that matches the maplayer 00186 QgsDebugMsg( "Found matching id" ); 00187 00188 // Set visible flag from maplayer to legendlayer 00189 legendLayerFile.setAttribute( "visible", mapLayer.attribute( "visible" ) ); 00190 00191 // Set overview flag from maplayer to legendlayer 00192 legendLayerFile.setAttribute( "isInOverview", mapLayer.attribute( "showInOverviewFlag" ) ); 00193 } 00194 } 00195 } 00196 } 00197 return; 00198 00199 } 00200 00201 void QgsProjectFileTransform::transform091to0100() 00202 { 00203 QgsDebugMsg( "entering" ); 00204 if ( ! mDom.isNull() ) 00205 { 00206 // Insert transforms here! 00207 QDomNodeList rasterPropertyList = mDom.elementsByTagName( "rasterproperties" ); 00208 QgsDebugMsg( QString( "Raster properties file entries: " ) + QString::number( rasterPropertyList.count() ) ); 00209 for ( int i = 0; i < rasterPropertyList.count(); i++ ) 00210 { 00211 // Get one rasterproperty element from list, and rename the sub-properties. 00212 QDomNode rasterProperty = rasterPropertyList.item( i ); 00213 // rasterProperty.namedItem("").toElement().setTagName(""); 00214 00215 rasterProperty.namedItem( "stdDevsToPlotDouble" ).toElement().setTagName( "mStandardDeviations" ); 00216 00217 rasterProperty.namedItem( "invertHistogramFlag" ).toElement().setTagName( "mInvertPixelsFlag" ); 00218 rasterProperty.namedItem( "showDebugOverLayFlag" ).toElement().setTagName( "mDebugOverLayFlag" ); 00219 00220 rasterProperty.namedItem( "redBandNameQString" ).toElement().setTagName( "mRedBandName" ); 00221 rasterProperty.namedItem( "blueBandNameQString" ).toElement().setTagName( "mBlueBandName" ); 00222 rasterProperty.namedItem( "greenBandNameQString" ).toElement().setTagName( "mGreenBandName" ); 00223 rasterProperty.namedItem( "grayBandNameQString" ).toElement().setTagName( "mGrayBandName" ); 00224 } 00225 00226 // Changing symbol size for hard: symbols 00227 QDomNodeList symbolPropertyList = mDom.elementsByTagName( "symbol" ); 00228 for ( int i = 0; i < symbolPropertyList.count(); i++ ) 00229 { 00230 // Get the <poinmtsymbol> to check for 'hard:' for each <symbol> 00231 QDomNode symbolProperty = symbolPropertyList.item( i ); 00232 00233 QDomElement pointSymbol = symbolProperty.firstChildElement( "pointsymbol" ); 00234 if ( pointSymbol.text().startsWith( "hard:" ) ) 00235 { 00236 // Get pointsize and line width 00237 int lineWidth = symbolProperty.firstChildElement( "outlinewidth" ).text().toInt(); 00238 int pointSize = symbolProperty.firstChildElement( "pointsize" ).text().toInt(); 00239 // Just a precaution, checking for 0 00240 if ( pointSize != 0 ) 00241 { 00242 // int r = (s-2*lw)/2-1 --> 2r = (s-2*lw)-2 --> 2r+2 = s-2*lw 00243 // --> 2r+2+2*lw = s 00244 // where '2r' is the old size. 00245 pointSize = pointSize + 2 + 2 * lineWidth; 00246 QgsDebugMsg( QString( "Setting point size to %1" ).arg( pointSize ) ); 00247 QDomElement newPointSizeProperty = mDom.createElement( "pointsize" ); 00248 QDomText newPointSizeTxt = mDom.createTextNode( QString::number( pointSize ) ); 00249 newPointSizeProperty.appendChild( newPointSizeTxt ); 00250 symbolProperty.replaceChild( newPointSizeProperty, pointSymbol ); 00251 } 00252 } 00253 } 00254 00255 } 00256 return; 00257 00258 } 00259 00260 void QgsProjectFileTransform::transform0100to0110() 00261 { 00262 if ( ! mDom.isNull() ) 00263 { 00264 //Change 'outlinewidth' in QgsSymbol 00265 QPrinter myPrinter( QPrinter::ScreenResolution ); 00266 int screenDpi = myPrinter.resolution(); 00267 double widthScaleFactor = 25.4 / screenDpi; 00268 00269 QDomNodeList outlineWidthList = mDom.elementsByTagName( "outlinewidth" ); 00270 for ( int i = 0; i < outlineWidthList.size(); ++i ) 00271 { 00272 //calculate new width 00273 QDomElement currentOutlineElem = outlineWidthList.at( i ).toElement(); 00274 double outlineWidth = currentOutlineElem.text().toDouble(); 00275 outlineWidth *= widthScaleFactor; 00276 00277 //replace old text node 00278 QDomNode outlineTextNode = currentOutlineElem.firstChild(); 00279 QDomText newOutlineText = mDom.createTextNode( QString::number( outlineWidth ) ); 00280 currentOutlineElem.replaceChild( newOutlineText, outlineTextNode ); 00281 00282 } 00283 00284 //Change 'pointsize' in QgsSymbol 00285 QDomNodeList pointSizeList = mDom.elementsByTagName( "pointsize" ); 00286 for ( int i = 0; i < pointSizeList.size(); ++i ) 00287 { 00288 //calculate new size 00289 QDomElement currentPointSizeElem = pointSizeList.at( i ).toElement(); 00290 double pointSize = currentPointSizeElem.text().toDouble(); 00291 pointSize *= widthScaleFactor; 00292 00293 //replace old text node 00294 QDomNode pointSizeTextNode = currentPointSizeElem.firstChild(); 00295 QDomText newPointSizeText = mDom.createTextNode( QString::number(( int )pointSize ) ); 00296 currentPointSizeElem.replaceChild( newPointSizeText, pointSizeTextNode ); 00297 } 00298 } 00299 } 00300 00301 void QgsProjectFileTransform::transform0110to1000() 00302 { 00303 if ( ! mDom.isNull() ) 00304 { 00305 QDomNodeList layerList = mDom.elementsByTagName( "maplayer" ); 00306 for ( int i = 0; i < layerList.size(); ++i ) 00307 { 00308 QDomElement layerElem = layerList.at( i ).toElement(); 00309 QString typeString = layerElem.attribute( "type" ); 00310 if ( typeString != "vector" ) 00311 { 00312 continue; 00313 } 00314 00315 //datasource 00316 QDomNode dataSourceNode = layerElem.namedItem( "datasource" ); 00317 if ( dataSourceNode.isNull() ) 00318 { 00319 return; 00320 } 00321 QString dataSource = dataSourceNode.toElement().text(); 00322 00323 //provider key 00324 QDomNode providerNode = layerElem.namedItem( "provider" ); 00325 if ( providerNode.isNull() ) 00326 { 00327 return; 00328 } 00329 QString providerKey = providerNode.toElement().text(); 00330 00331 //create the layer to get the provider for int->fieldName conversion 00332 QgsVectorLayer* theLayer = new QgsVectorLayer( dataSource, "", providerKey, false ); 00333 if ( !theLayer->isValid() ) 00334 { 00335 delete theLayer; 00336 return; 00337 } 00338 00339 QgsVectorDataProvider* theProvider = theLayer->dataProvider(); 00340 if ( !theProvider ) 00341 { 00342 return; 00343 } 00344 QgsFields theFields = theProvider->fields(); 00345 00346 //read classificationfield 00347 QDomNodeList classificationFieldList = layerElem.elementsByTagName( "classificationfield" ); 00348 for ( int j = 0; j < classificationFieldList.size(); ++j ) 00349 { 00350 QDomElement classificationFieldElem = classificationFieldList.at( j ).toElement(); 00351 int fieldNumber = classificationFieldElem.text().toInt(); 00352 if ( fieldNumber >= 0 && fieldNumber < theFields.count() ) 00353 { 00354 QDomText fieldName = mDom.createTextNode( theFields[fieldNumber].name() ); 00355 QDomNode nameNode = classificationFieldElem.firstChild(); 00356 classificationFieldElem.replaceChild( fieldName, nameNode ); 00357 } 00358 } 00359 00360 } 00361 } 00362 } 00363 00364 void QgsProjectFileTransform::transform1100to1200() 00365 { 00366 QgsDebugMsg( "Entering..." ); 00367 if ( mDom.isNull() ) 00368 return; 00369 00370 QDomNode qgis = mDom.firstChildElement( "qgis" ); 00371 if ( qgis.isNull() ) 00372 return; 00373 00374 QDomElement properties = qgis.firstChildElement( "properties" ); 00375 if ( properties.isNull() ) 00376 return; 00377 00378 QDomElement digitizing = properties.firstChildElement( "Digitizing" ); 00379 if ( digitizing.isNull() ) 00380 return; 00381 00382 QDomElement tolList = digitizing.firstChildElement( "LayerSnappingToleranceList" ); 00383 if ( tolList.isNull() ) 00384 return; 00385 00386 QDomElement tolUnitList = digitizing.firstChildElement( "LayerSnappingToleranceUnitList" ); 00387 if ( !tolUnitList.isNull() ) 00388 return; 00389 00390 QStringList units; 00391 for ( int i = 0; i < tolList.childNodes().count(); i++ ) 00392 units << "0"; 00393 00394 QgsPropertyValue value( units ); 00395 value.writeXML( "LayerSnappingToleranceUnitList", digitizing, mDom ); 00396 } 00397 00398 void QgsProjectFileTransform::transform1400to1500() 00399 { 00400 //Adapt the XML description of the composer legend model to version 1.5 00401 if ( mDom.isNull() ) 00402 { 00403 return; 00404 } 00405 //Add layer id to <VectorClassificationItem> 00406 QDomNodeList layerItemList = mDom.elementsByTagName( "LayerItem" ); 00407 QDomElement currentLayerItemElem; 00408 QString currentLayerId; 00409 00410 for ( int i = 0; i < layerItemList.size(); ++i ) 00411 { 00412 currentLayerItemElem = layerItemList.at( i ).toElement(); 00413 if ( currentLayerItemElem.isNull() ) 00414 { 00415 continue; 00416 } 00417 currentLayerId = currentLayerItemElem.attribute( "layerId" ); 00418 00419 QDomNodeList vectorClassificationList = currentLayerItemElem.elementsByTagName( "VectorClassificationItem" ); 00420 QDomElement currentClassificationElem; 00421 for ( int j = 0; j < vectorClassificationList.size(); ++j ) 00422 { 00423 currentClassificationElem = vectorClassificationList.at( j ).toElement(); 00424 if ( !currentClassificationElem.isNull() ) 00425 { 00426 currentClassificationElem.setAttribute( "layerId", currentLayerId ); 00427 } 00428 } 00429 00430 //replace the text items with VectorClassification or RasterClassification items 00431 QDomNodeList textItemList = currentLayerItemElem.elementsByTagName( "TextItem" ); 00432 QDomElement currentTextItem; 00433 00434 for ( int j = 0; j < textItemList.size(); ++j ) 00435 { 00436 currentTextItem = textItemList.at( j ).toElement(); 00437 if ( currentTextItem.isNull() ) 00438 { 00439 continue; 00440 } 00441 00442 QDomElement classificationElement; 00443 if ( vectorClassificationList.size() > 0 ) //we guess it is a vector layer 00444 { 00445 classificationElement = mDom.createElement( "VectorClassificationItem" ); 00446 } 00447 else 00448 { 00449 classificationElement = mDom.createElement( "RasterClassificationItem" ); 00450 } 00451 00452 classificationElement.setAttribute( "layerId", currentLayerId ); 00453 classificationElement.setAttribute( "text", currentTextItem.attribute( "text" ) ); 00454 currentLayerItemElem.replaceChild( classificationElement, currentTextItem ); 00455 } 00456 } 00457 } 00458 00459 void QgsProjectFileTransform::transform1800to1900() 00460 { 00461 if ( mDom.isNull() ) 00462 { 00463 return; 00464 } 00465 00466 QDomNodeList layerItemList = mDom.elementsByTagName( "rasterproperties" ); 00467 for ( int i = 0; i < layerItemList.size(); ++i ) 00468 { 00469 QDomElement rasterPropertiesElem = layerItemList.at( i ).toElement(); 00470 QDomNode layerNode = rasterPropertiesElem.parentNode(); 00471 QDomElement dataSourceElem = layerNode.firstChildElement( "datasource" ); 00472 QDomElement layerNameElem = layerNode.firstChildElement( "layername" ); 00473 QgsRasterLayer rasterLayer; 00474 // TODO: We have to use more data from project file to read the layer it correctly, 00475 // OTOH, we should not read it until it was converted 00476 rasterLayer.readLayerXML( layerNode.toElement() ); 00477 convertRasterProperties( mDom, layerNode, rasterPropertiesElem, &rasterLayer ); 00478 } 00479 00480 //composer: replace mGridAnnotationPosition with mLeftGridAnnotationPosition & co. 00481 // and mGridAnnotationDirection with mLeftGridAnnotationDirection & co. 00482 QDomNodeList composerMapList = mDom.elementsByTagName( "ComposerMap" ); 00483 for ( int i = 0; i < composerMapList.size(); ++i ) 00484 { 00485 QDomNodeList gridList = composerMapList.at( i ).toElement().elementsByTagName( "Grid" ); 00486 for ( int j = 0; j < gridList.size(); ++j ) 00487 { 00488 QDomNodeList annotationList = gridList.at( j ).toElement().elementsByTagName( "Annotation" ); 00489 for ( int k = 0; k < annotationList.size(); ++k ) 00490 { 00491 QDomElement annotationElem = annotationList.at( k ).toElement(); 00492 00493 //position 00494 if ( annotationElem.hasAttribute( "position" ) ) 00495 { 00496 int pos = annotationElem.attribute( "position" ).toInt(); 00497 annotationElem.setAttribute( "leftPosition", pos ); 00498 annotationElem.setAttribute( "rightPosition", pos ); 00499 annotationElem.setAttribute( "topPosition", pos ); 00500 annotationElem.setAttribute( "bottomPosition", pos ); 00501 annotationElem.removeAttribute( "position" ); 00502 } 00503 00504 //direction 00505 if ( annotationElem.hasAttribute( "direction" ) ) 00506 { 00507 int dir = annotationElem.attribute( "direction" ).toInt(); 00508 if ( dir == 2 ) 00509 { 00510 annotationElem.setAttribute( "leftDirection", 0 ); 00511 annotationElem.setAttribute( "rightDirection", 0 ); 00512 annotationElem.setAttribute( "topDirection", 1 ); 00513 annotationElem.setAttribute( "bottomDirection", 1 ); 00514 } 00515 else if ( dir == 3 ) 00516 { 00517 annotationElem.setAttribute( "leftDirection", 1 ); 00518 annotationElem.setAttribute( "rightDirection", 1 ); 00519 annotationElem.setAttribute( "topDirection", 0 ); 00520 annotationElem.setAttribute( "bottomDirection", 0 ); 00521 } 00522 else 00523 { 00524 annotationElem.setAttribute( "leftDirection", dir ); 00525 annotationElem.setAttribute( "rightDirection", dir ); 00526 annotationElem.setAttribute( "topDirection", dir ); 00527 annotationElem.setAttribute( "bottomDirection", dir ); 00528 } 00529 annotationElem.removeAttribute( "direction" ); 00530 } 00531 } 00532 } 00533 } 00534 00535 //Composer: move all items under Composition element 00536 QDomNodeList composerList = mDom.elementsByTagName( "Composer" ); 00537 for ( int i = 0; i < composerList.size(); ++i ) 00538 { 00539 QDomElement composerElem = composerList.at( i ).toElement(); 00540 00541 //find <QgsComposition element 00542 QDomElement compositionElem = composerElem.firstChildElement( "Composition" ); 00543 if ( compositionElem.isNull() ) 00544 { 00545 continue; 00546 } 00547 00548 QDomNodeList composerChildren = composerElem.childNodes(); 00549 00550 if ( composerChildren.size() < 1 ) 00551 { 00552 continue; 00553 } 00554 00555 for ( int j = composerChildren.size() - 1; j >= 0; --j ) 00556 { 00557 QDomElement childElem = composerChildren.at( j ).toElement(); 00558 if ( childElem.tagName() == "Composition" ) 00559 { 00560 continue; 00561 } 00562 00563 composerElem.removeChild( childElem ); 00564 compositionElem.appendChild( childElem ); 00565 00566 } 00567 } 00568 00569 // SimpleFill symbol layer v2: avoid double transparency 00570 // replacing alpha value of symbol layer's color with 255 (the 00571 // transparency value is already stored as symbol transparency). 00572 QDomNodeList rendererList = mDom.elementsByTagName( "renderer-v2" ); 00573 for ( int i = 0; i < rendererList.size(); ++i ) 00574 { 00575 QDomNodeList layerList = rendererList.at( i ).toElement().elementsByTagName( "layer" ); 00576 for ( int j = 0; j < layerList.size(); ++j ) 00577 { 00578 QDomElement layerElem = layerList.at( j ).toElement(); 00579 if ( layerElem.attribute( "class" ) == "SimpleFill" ) 00580 { 00581 QDomNodeList propList = layerElem.elementsByTagName( "prop" ); 00582 for ( int k = 0; k < propList.size(); ++k ) 00583 { 00584 QDomElement propElem = propList.at( k ).toElement(); 00585 if ( propElem.attribute( "k" ) == "color" || propElem.attribute( "k" ) == "color_border" ) 00586 { 00587 propElem.setAttribute( "v", propElem.attribute( "v" ).section( ",", 0, 2 ) + ",255" ); 00588 } 00589 } 00590 } 00591 } 00592 } 00593 00594 QgsDebugMsg( mDom.toString() ); 00595 } 00596 00597 void QgsProjectFileTransform::convertRasterProperties( QDomDocument& doc, QDomNode& parentNode, 00598 QDomElement& rasterPropertiesElem, QgsRasterLayer* rlayer ) 00599 { 00600 //no data 00601 //TODO: We would need to set no data on all bands, but we don't know number of bands here 00602 QDomNode noDataNode = rasterPropertiesElem.namedItem( "mNoDataValue" ); 00603 QDomElement noDataElement = noDataNode.toElement(); 00604 if ( !noDataElement.text().isEmpty() ) 00605 { 00606 QgsDebugMsg( "mNoDataValue = " + noDataElement.text() ); 00607 QDomElement noDataElem = doc.createElement( "noData" ); 00608 00609 QDomElement noDataRangeList = doc.createElement( "noDataRangeList" ); 00610 noDataRangeList.setAttribute( "bandNo", 1 ); 00611 00612 QDomElement noDataRange = doc.createElement( "noDataRange" ); 00613 noDataRange.setAttribute( "min", noDataElement.text() ); 00614 noDataRange.setAttribute( "max", noDataElement.text() ); 00615 noDataRangeList.appendChild( noDataRange ); 00616 00617 noDataElem.appendChild( noDataRangeList ); 00618 00619 parentNode.appendChild( noDataElem ); 00620 } 00621 00622 QDomElement rasterRendererElem = doc.createElement( "rasterrenderer" ); 00623 //convert general properties 00624 00625 //invert color 00626 rasterRendererElem.setAttribute( "invertColor", "0" ); 00627 QDomElement invertColorElem = rasterPropertiesElem.firstChildElement( "mInvertColor" ); 00628 if ( !invertColorElem.isNull() ) 00629 { 00630 if ( invertColorElem.text() == "true" ) 00631 { 00632 rasterRendererElem.setAttribute( "invertColor", "1" ); 00633 } 00634 } 00635 00636 //opacity 00637 rasterRendererElem.setAttribute( "opacity", "1" ); 00638 QDomElement transparencyElem = parentNode.firstChildElement( "transparencyLevelInt" ); 00639 if ( !transparencyElem.isNull() ) 00640 { 00641 double transparency = transparencyElem.text().toInt(); 00642 rasterRendererElem.setAttribute( "opacity", QString::number( transparency / 255.0 ) ); 00643 } 00644 00645 //alphaBand was not saved until now (bug) 00646 rasterRendererElem.setAttribute( "alphaBand", -1 ); 00647 00648 //gray band is used for several renderers 00649 int grayBand = rasterBandNumber( rasterPropertiesElem, "mGrayBandName", rlayer ); 00650 00651 //convert renderer specific properties 00652 QString drawingStyle = rasterPropertiesElem.firstChildElement( "mDrawingStyle" ).text(); 00653 00654 // While PalettedColor should normaly contain only integer values, usually 00655 // color palette 0-255, it may happen (Tim, issue #7023) that it contains 00656 // colormap classification with double values and text labels 00657 // (which should normaly only appear in SingleBandPseudoColor drawingStyle) 00658 // => we have to check first the values and change drawingStyle if necessary 00659 if ( drawingStyle == "PalettedColor" ) 00660 { 00661 QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( "customColorRamp" ); 00662 QDomNodeList colorRampEntryList = customColorRampElem.elementsByTagName( "colorRampEntry" ); 00663 00664 for ( int i = 0; i < colorRampEntryList.size(); ++i ) 00665 { 00666 QDomElement colorRampEntryElem = colorRampEntryList.at( i ).toElement(); 00667 QString strValue = colorRampEntryElem.attribute( "value" ); 00668 double value = strValue.toDouble(); 00669 if ( value < 0 || value > 10000 || value != ( int )value ) 00670 { 00671 QgsDebugMsg( QString( "forcing SingleBandPseudoColor value = %1" ).arg( value ) ); 00672 drawingStyle = "SingleBandPseudoColor"; 00673 break; 00674 } 00675 } 00676 } 00677 00678 if ( drawingStyle == "SingleBandGray" ) 00679 { 00680 rasterRendererElem.setAttribute( "type", "singlebandgray" ); 00681 rasterRendererElem.setAttribute( "grayBand", grayBand ); 00682 transformContrastEnhancement( doc, rasterPropertiesElem, rasterRendererElem ); 00683 } 00684 else if ( drawingStyle == "SingleBandPseudoColor" ) 00685 { 00686 rasterRendererElem.setAttribute( "type", "singlebandpseudocolor" ); 00687 rasterRendererElem.setAttribute( "band", grayBand ); 00688 QDomElement newRasterShaderElem = doc.createElement( "rastershader" ); 00689 QDomElement newColorRampShaderElem = doc.createElement( "colorrampshader" ); 00690 newRasterShaderElem.appendChild( newColorRampShaderElem ); 00691 rasterRendererElem.appendChild( newRasterShaderElem ); 00692 00693 //switch depending on mColorShadingAlgorithm 00694 QString colorShadingAlgorithm = rasterPropertiesElem.firstChildElement( "mColorShadingAlgorithm" ).text(); 00695 if ( colorShadingAlgorithm == "PseudoColorShader" || colorShadingAlgorithm == "FreakOutShader" ) 00696 { 00697 newColorRampShaderElem.setAttribute( "colorRampType", "INTERPOLATED" ); 00698 00699 //get minmax from rasterlayer 00700 QgsRasterBandStats rasterBandStats = rlayer->dataProvider()->bandStatistics( grayBand ); 00701 double minValue = rasterBandStats.minimumValue; 00702 double maxValue = rasterBandStats.maximumValue; 00703 double breakSize = ( maxValue - minValue ) / 3; 00704 00705 QStringList colorList; 00706 if ( colorShadingAlgorithm == "FreakOutShader" ) 00707 { 00708 colorList << "#ff00ff" << "#00ffff" << "#ff0000" << "#00ff00"; 00709 } 00710 else //pseudocolor 00711 { 00712 colorList << "#0000ff" << "#00ffff" << "#ffff00" << "#ff0000"; 00713 } 00714 QStringList::const_iterator colorIt = colorList.constBegin(); 00715 double boundValue = minValue; 00716 for ( ; colorIt != colorList.constEnd(); ++colorIt ) 00717 { 00718 QDomElement newItemElem = doc.createElement( "item" ); 00719 newItemElem.setAttribute( "value", QString::number( boundValue ) ); 00720 newItemElem.setAttribute( "label", QString::number( boundValue ) ); 00721 newItemElem.setAttribute( "color", *colorIt ); 00722 newColorRampShaderElem.appendChild( newItemElem ); 00723 boundValue += breakSize; 00724 } 00725 } 00726 else if ( colorShadingAlgorithm == "ColorRampShader" ) 00727 { 00728 QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( "customColorRamp" ); 00729 QString type = customColorRampElem.firstChildElement( "colorRampType" ).text(); 00730 newColorRampShaderElem.setAttribute( "colorRampType", type ); 00731 QDomNodeList colorNodeList = customColorRampElem.elementsByTagName( "colorRampEntry" ); 00732 00733 QString value, label; 00734 QColor newColor; 00735 int red, green, blue; 00736 QDomElement currentItemElem; 00737 for ( int i = 0; i < colorNodeList.size(); ++i ) 00738 { 00739 currentItemElem = colorNodeList.at( i ).toElement(); 00740 value = currentItemElem.attribute( "value" ); 00741 label = currentItemElem.attribute( "label" ); 00742 red = currentItemElem.attribute( "red" ).toInt(); 00743 green = currentItemElem.attribute( "green" ).toInt(); 00744 blue = currentItemElem.attribute( "blue" ).toInt(); 00745 newColor = QColor( red, green, blue ); 00746 QDomElement newItemElem = doc.createElement( "item" ); 00747 newItemElem.setAttribute( "value", value ); 00748 newItemElem.setAttribute( "label", label ); 00749 newItemElem.setAttribute( "color", newColor.name() ); 00750 newColorRampShaderElem.appendChild( newItemElem ); 00751 } 00752 } 00753 } 00754 else if ( drawingStyle == "PalettedColor" ) 00755 { 00756 rasterRendererElem.setAttribute( "type", "paletted" ); 00757 rasterRendererElem.setAttribute( "band", grayBand ); 00758 QDomElement customColorRampElem = rasterPropertiesElem.firstChildElement( "customColorRamp" ); 00759 QDomNodeList colorRampEntryList = customColorRampElem.elementsByTagName( "colorRampEntry" ); 00760 QDomElement newColorPaletteElem = doc.createElement( "colorPalette" ); 00761 00762 int red = 0; 00763 int green = 0; 00764 int blue = 0; 00765 int value = 0; 00766 QDomElement colorRampEntryElem; 00767 for ( int i = 0; i < colorRampEntryList.size(); ++i ) 00768 { 00769 colorRampEntryElem = colorRampEntryList.at( i ).toElement(); 00770 QDomElement newPaletteElem = doc.createElement( "paletteEntry" ); 00771 value = ( int )( colorRampEntryElem.attribute( "value" ).toDouble() ); 00772 newPaletteElem.setAttribute( "value", value ); 00773 red = colorRampEntryElem.attribute( "red" ).toInt(); 00774 green = colorRampEntryElem.attribute( "green" ).toInt(); 00775 blue = colorRampEntryElem.attribute( "blue" ).toInt(); 00776 newPaletteElem.setAttribute( "color", QColor( red, green, blue ).name() ); 00777 newColorPaletteElem.appendChild( newPaletteElem ); 00778 } 00779 rasterRendererElem.appendChild( newColorPaletteElem ); 00780 } 00781 else if ( drawingStyle == "MultiBandColor" ) 00782 { 00783 rasterRendererElem.setAttribute( "type", "multibandcolor" ); 00784 00785 //red band, green band, blue band 00786 int redBand = rasterBandNumber( rasterPropertiesElem, "mRedBandName", rlayer ); 00787 int greenBand = rasterBandNumber( rasterPropertiesElem, "mGreenBandName", rlayer ); 00788 int blueBand = rasterBandNumber( rasterPropertiesElem, "mBlueBandName", rlayer ); 00789 rasterRendererElem.setAttribute( "redBand", redBand ); 00790 rasterRendererElem.setAttribute( "greenBand", greenBand ); 00791 rasterRendererElem.setAttribute( "blueBand", blueBand ); 00792 00793 transformContrastEnhancement( doc, rasterPropertiesElem, rasterRendererElem ); 00794 } 00795 else 00796 { 00797 return; 00798 } 00799 00800 //replace rasterproperties element with rasterrenderer element 00801 if ( !parentNode.isNull() ) 00802 { 00803 parentNode.replaceChild( rasterRendererElem, rasterPropertiesElem ); 00804 } 00805 } 00806 00807 int QgsProjectFileTransform::rasterBandNumber( const QDomElement& rasterPropertiesElem, const QString bandName, 00808 QgsRasterLayer* rlayer ) 00809 { 00810 if ( !rlayer ) 00811 { 00812 return -1; 00813 } 00814 00815 int band = -1; 00816 QDomElement rasterBandElem = rasterPropertiesElem.firstChildElement( bandName ); 00817 if ( !rasterBandElem.isNull() ) 00818 { 00819 for ( int i = 1; i <= rlayer->bandCount(); i++ ) 00820 { 00821 if ( rlayer->bandName( i ) == rasterBandElem.text() ) 00822 { 00823 band = i; 00824 break; 00825 } 00826 } 00827 } 00828 return band; 00829 } 00830 00831 void QgsProjectFileTransform::transformContrastEnhancement( QDomDocument& doc, const QDomElement& rasterproperties, QDomElement& rendererElem ) 00832 { 00833 if ( rasterproperties.isNull() || rendererElem.isNull() ) 00834 { 00835 return; 00836 } 00837 00838 double minimumValue = 0; 00839 double maximumValue = 0; 00840 QDomElement contrastMinMaxElem = rasterproperties.firstChildElement( "contrastEnhancementMinMaxValues" ); 00841 if ( contrastMinMaxElem.isNull() ) 00842 { 00843 return; 00844 } 00845 00846 QDomElement contrastEnhancementAlgorithmElem = rasterproperties.firstChildElement( "mContrastEnhancementAlgorithm" ); 00847 if ( contrastEnhancementAlgorithmElem.isNull() ) 00848 { 00849 return; 00850 } 00851 00852 //convert enhancement name to enumeration 00853 int algorithmEnum = 0; 00854 QString algorithmString = contrastEnhancementAlgorithmElem.text(); 00855 if ( algorithmString == "StretchToMinimumMaximum" ) 00856 { 00857 algorithmEnum = 1; 00858 } 00859 else if ( algorithmString == "StretchAndClipToMinimumMaximum" ) 00860 { 00861 algorithmEnum = 2; 00862 } 00863 else if ( algorithmString == "ClipToMinimumMaximum" ) 00864 { 00865 algorithmEnum = 3; 00866 } 00867 else if ( algorithmString == "UserDefinedEnhancement" ) 00868 { 00869 algorithmEnum = 4; 00870 } 00871 00872 QDomNodeList minMaxEntryList = contrastMinMaxElem.elementsByTagName( "minMaxEntry" ); 00873 QStringList enhancementNameList; 00874 if ( minMaxEntryList.size() == 1 ) 00875 { 00876 enhancementNameList << "contrastEnhancement"; 00877 } 00878 if ( minMaxEntryList.size() == 3 ) 00879 { 00880 enhancementNameList << "redContrastEnhancement" << "greenContrastEnhancement" << "blueContrastEnhancement"; 00881 } 00882 if ( minMaxEntryList.size() > enhancementNameList.size() ) 00883 { 00884 return; 00885 } 00886 00887 QDomElement minMaxEntryElem; 00888 for ( int i = 0; i < minMaxEntryList.size(); ++i ) 00889 { 00890 minMaxEntryElem = minMaxEntryList.at( i ).toElement(); 00891 QDomElement minElem = minMaxEntryElem.firstChildElement( "min" ); 00892 if ( minElem.isNull() ) 00893 { 00894 return; 00895 } 00896 minimumValue = minElem.text().toDouble(); 00897 00898 QDomElement maxElem = minMaxEntryElem.firstChildElement( "max" ); 00899 if ( maxElem.isNull() ) 00900 { 00901 return; 00902 } 00903 maximumValue = maxElem.text().toDouble(); 00904 00905 QDomElement newContrastEnhancementElem = doc.createElement( enhancementNameList.at( i ) ); 00906 QDomElement newMinValElem = doc.createElement( "minValue" ); 00907 QDomText minText = doc.createTextNode( QString::number( minimumValue ) ); 00908 newMinValElem.appendChild( minText ); 00909 newContrastEnhancementElem.appendChild( newMinValElem ); 00910 QDomElement newMaxValElem = doc.createElement( "maxValue" ); 00911 QDomText maxText = doc.createTextNode( QString::number( maximumValue ) ); 00912 newMaxValElem.appendChild( maxText ); 00913 newContrastEnhancementElem.appendChild( newMaxValElem ); 00914 00915 QDomElement newAlgorithmElem = doc.createElement( "algorithm" ); 00916 QDomText newAlgorithmText = doc.createTextNode( QString::number( algorithmEnum ) ); 00917 newAlgorithmElem.appendChild( newAlgorithmText ); 00918 newContrastEnhancementElem.appendChild( newAlgorithmElem ); 00919 00920 rendererElem.appendChild( newContrastEnhancementElem ); 00921 } 00922 } 00923 00924 void QgsProjectFileTransform::transformRasterTransparency( QDomDocument& doc, const QDomElement& orig, QDomElement& rendererElem ) 00925 { 00926 //soon... 00927 Q_UNUSED( doc ); 00928 Q_UNUSED( orig ); 00929 Q_UNUSED( rendererElem ); 00930 } 00931