Quantum GIS API Documentation
1.7.4
|
00001 /*************************************************************************** 00002 qgsproject.cpp - description 00003 ------------------- 00004 begin : February 24, 2005 00005 copyright : (C) 2005 by Mark Coletti 00006 email : mcoletti at gmail.com 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 #include "qgsprojectproperty.h" 00019 #include "qgslogger.h" 00020 00021 #include <QDomDocument> 00022 #include <QStringList> 00023 00024 static const char * const ident_ = "$Id$"; 00025 00026 00027 void QgsPropertyValue::dump( size_t tabs ) const 00028 { 00029 QString tabString; 00030 tabString.fill( '\t', tabs ); 00031 00032 if ( QVariant::StringList == value_.type() ) 00033 { 00034 QStringList sl = value_.toStringList(); 00035 00036 for ( QStringList::const_iterator i = sl.begin(); i != sl.end(); ++i ) 00037 { 00038 QgsDebugMsg( QString( "%1[%2] " ).arg( tabString ).arg( *i ) ); 00039 } 00040 } 00041 else 00042 { 00043 QgsDebugMsg( QString( "%1%2" ).arg( tabString ).arg( value_.toString() ) ); 00044 } 00045 } // QgsPropertyValue::dump() 00046 00047 00048 00049 bool QgsPropertyValue::readXML( QDomNode & keyNode ) 00050 { 00051 // this *should* be a Dom element node 00052 QDomElement subkeyElement = keyNode.toElement(); 00053 00054 // get the type so that we can properly parse the key value 00055 QString typeString = subkeyElement.attribute( "type" ); 00056 00057 if ( QString::null == typeString ) 00058 { 00059 QgsDebugMsg( QString( "null ``type'' attribute for %1" ).arg( keyNode.nodeName() ) ); 00060 00061 return false; 00062 } 00063 00064 // the values come in as strings; we need to restore them to their 00065 // original values *and* types 00066 value_.clear(); 00067 00068 // get the type associated with the value first 00069 QVariant::Type type = QVariant::nameToType( typeString.toLocal8Bit().constData() ); 00070 00071 // This huge switch is left-over from an earlier incarnation of 00072 // QgsProject where there was a fine level of granularity for value 00073 // types. The current interface, borrowed from QSettings, supports a 00074 // very small sub-set of these types. However, I've left all the 00075 // other types just in case the interface is expanded to include these 00076 // other types. 00077 00078 switch ( type ) 00079 { 00080 case QVariant::Invalid: 00081 QgsDebugMsg( QString( "invalid value type %1 .. " ).arg( typeString ) ); 00082 return false; 00083 00084 case QVariant::Map: 00085 QgsDebugMsg( "no support for QVariant::Map" ); 00086 return false; 00087 00088 case QVariant::List: 00089 QgsDebugMsg( "no support for QVariant::List" ); 00090 return false; 00091 00092 case QVariant::String: 00093 value_ = subkeyElement.text(); // no translating necessary 00094 break; 00095 00096 case QVariant::StringList: 00097 { 00098 int i = 0; 00099 QDomNodeList values = keyNode.childNodes(); 00100 00101 // all the QStringList values will be inside <value> elements 00102 QStringList valueStringList; 00103 00104 while ( i < values.count() ) 00105 { 00106 if ( "value" == values.item( i ).nodeName() ) 00107 { // <value>s have only one element, which contains actual string value 00108 valueStringList.append( values.item( i ).firstChild().nodeValue() ); 00109 } 00110 else 00111 { 00112 QgsDebugMsg( QString( "non <value> element ``%1'' in string list" ).arg( values.item( i ).nodeName() ) ); 00113 } 00114 00115 ++i; 00116 } 00117 00118 value_ = valueStringList; 00119 break; 00120 } 00121 00122 case QVariant::Font: 00123 QgsDebugMsg( "no support for QVariant::Font" ); 00124 return false; 00125 00126 case QVariant::Pixmap: 00127 QgsDebugMsg( "no support for QVariant::Pixmap" ); 00128 return false; 00129 00130 case QVariant::Brush: 00131 QgsDebugMsg( "no support for QVariant::Brush" ); 00132 return false; 00133 00134 case QVariant::Rect: 00135 QgsDebugMsg( "no support for QVariant::Rect" ); 00136 return false; 00137 00138 case QVariant::Size: 00139 QgsDebugMsg( "no support for QVariant::Size" ); 00140 return false; 00141 00142 case QVariant::Color: 00143 QgsDebugMsg( "no support for QVariant::Color" ); 00144 return false; 00145 00146 case QVariant::Palette: 00147 QgsDebugMsg( "no support for QVariant::Palette" ); 00148 return false; 00149 00150 case QVariant::Point: 00151 QgsDebugMsg( "no support for QVariant::Point" ); 00152 return false; 00153 00154 case QVariant::Image: 00155 QgsDebugMsg( "no support for QVariant::Image" ); 00156 return false; 00157 00158 case QVariant::Int: 00159 value_ = QVariant( subkeyElement.text() ).toInt(); 00160 break; 00161 00162 case QVariant::UInt: 00163 value_ = QVariant( subkeyElement.text() ).toUInt(); 00164 break; 00165 00166 case QVariant::Bool: 00167 value_ = QVariant( subkeyElement.text() ).toBool(); 00168 break; 00169 00170 case QVariant::Double: 00171 value_ = QVariant( subkeyElement.text() ).toDouble(); 00172 break; 00173 00174 case QVariant::ByteArray: 00175 value_ = QVariant( subkeyElement.text() ).toByteArray(); 00176 break; 00177 00178 case QVariant::Polygon: 00179 QgsDebugMsg( "no support for QVariant::Polygon" ); 00180 return false; 00181 00182 case QVariant::Region: 00183 QgsDebugMsg( "no support for QVariant::Region" ); 00184 return false; 00185 00186 case QVariant::Bitmap: 00187 QgsDebugMsg( "no support for QVariant::Bitmap" ); 00188 return false; 00189 00190 case QVariant::Cursor: 00191 QgsDebugMsg( "no support for QVariant::Cursor" ); 00192 return false; 00193 00194 case QVariant::BitArray : 00195 QgsDebugMsg( "no support for QVariant::BitArray" ); 00196 return false; 00197 00198 case QVariant::KeySequence : 00199 QgsDebugMsg( "no support for QVariant::KeySequence" ); 00200 return false; 00201 00202 case QVariant::Pen : 00203 QgsDebugMsg( "no support for QVariant::Pen" ); 00204 return false; 00205 00206 // 00207 // QGIS DIES NOT SUPPORT THESE VARIANT TYPES IN VERSION 3.1 DISABLING FOR NOW 00208 // 00209 /* 00210 case QVariant::LongLong : 00211 value_ = QVariant(subkeyElement.text()).toLongLong(); 00212 break; 00213 00214 case QVariant::ULongLong : 00215 value_ = QVariant(subkeyElement.text()).toULongLong(); 00216 break; 00217 */ 00218 default : 00219 QgsDebugMsg( QString( "unsupported value type %1 .. not propertly translated to QVariant" ).arg( typeString ) ); 00220 } 00221 00222 return true; 00223 00224 } // QgsPropertyValue::readXML 00225 00226 00230 bool QgsPropertyValue::writeXML( QString const & nodeName, 00231 QDomElement & keyElement, 00232 QDomDocument & document ) 00233 { 00234 QDomElement valueElement = document.createElement( nodeName ); 00235 00236 // remember the type so that we can rebuild it when the project is read in 00237 valueElement.setAttribute( "type", value_.typeName() ); 00238 00239 00240 // we handle string lists differently from other types in that we 00241 // create a sequence of repeated elements to cover all the string list 00242 // members; each value will be in a <value></value> tag. 00243 // XXX Not the most elegant way to handle string lists? 00244 if ( QVariant::StringList == value_.type() ) 00245 { 00246 QStringList sl = value_.toStringList(); 00247 00248 for ( QStringList::iterator i = sl.begin(); 00249 i != sl.end(); 00250 ++i ) 00251 { 00252 QDomElement stringListElement = document.createElement( "value" ); 00253 QDomText valueText = document.createTextNode( *i ); 00254 stringListElement.appendChild( valueText ); 00255 00256 valueElement.appendChild( stringListElement ); 00257 } 00258 } 00259 else // we just plop the value in as plain ole text 00260 { 00261 QDomText valueText = document.createTextNode( value_.toString() ); 00262 valueElement.appendChild( valueText ); 00263 } 00264 00265 keyElement.appendChild( valueElement ); 00266 00267 return true; 00268 } // QgsPropertyValue::writeXML 00269 00270 00271 00272 00273 QgsPropertyKey::QgsPropertyKey( QString const name ) 00274 : mName( name ) 00275 {} 00276 00277 QgsPropertyKey::~QgsPropertyKey() 00278 { 00279 clearKeys(); 00280 } 00281 00282 QVariant QgsPropertyKey::value() const 00283 { 00284 QgsProperty *foundQgsProperty = mProperties.value( name() ); 00285 00286 if ( !foundQgsProperty ) 00287 { 00288 QgsDebugMsg( "key has null child" ); 00289 return QVariant(); // just return an QVariant::Invalid 00290 } 00291 00292 return foundQgsProperty->value(); 00293 } // QVariant QgsPropertyKey::value() 00294 00295 00296 void QgsPropertyKey::dump( size_t tabs ) const 00297 { 00298 QString tabString; 00299 00300 tabString.fill( '\t', tabs ); 00301 00302 QgsDebugMsg( QString( "%1name: %2" ).arg( tabString ).arg( name() ) ); 00303 00304 tabs++; 00305 tabString.fill( '\t', tabs ); 00306 00307 if ( ! mProperties.isEmpty() ) 00308 { 00309 QHashIterator < QString, QgsProperty* > i( mProperties ); 00310 while ( i.hasNext() ) 00311 { 00312 if ( i.next().value()->isValue() ) 00313 { 00314 QgsPropertyValue * propertyValue = 00315 dynamic_cast<QgsPropertyValue*>( i.value() ); 00316 00317 if ( QVariant::StringList == propertyValue->value().type() ) 00318 { 00319 QgsDebugMsg( QString( "%1key: <%2> value:" ).arg( tabString ).arg( i.key() ) ); 00320 propertyValue->dump( tabs + 1 ); 00321 } 00322 else 00323 { 00324 QgsDebugMsg( QString( "%1key: <%2> value: %3" ).arg( tabString ).arg( i.key() ).arg( propertyValue->value().toString() ) ); 00325 } 00326 } 00327 else 00328 { 00329 QgsDebugMsg( QString( "%1key: <%2> subkey: <%3>" ) 00330 .arg( tabString ) 00331 .arg( i.key() ) 00332 .arg( dynamic_cast<QgsPropertyKey*>( i.value() )->name() ) ); 00333 i.value()->dump( tabs + 1 ); 00334 } 00335 00336 // qDebug("<%s>", name().toUtf8().constData()); 00337 // if ( i.value()->isValue() ) 00338 // { 00339 // qDebug(" <%s>", i.key().toUtf8().constData() ); 00340 // } 00341 // i.value()->dump(); 00342 // if ( i.value()->isValue() ) 00343 // { 00344 // qDebug(" </%s>", i.key().toUtf8().constData() ); 00345 // } 00346 // qDebug("</%s>", name().toUtf8().constData()); 00347 } 00348 } 00349 00350 } // QgsPropertyKey::dump 00351 00352 00353 00354 bool QgsPropertyKey::readXML( QDomNode & keyNode ) 00355 { 00356 int i = 0; 00357 QDomNodeList subkeys = keyNode.childNodes(); 00358 00359 while ( i < subkeys.count() ) 00360 { 00361 // if the current node is an element that has a "type" attribute, 00362 // then we know it's a leaf node; i.e., a subkey _value_, and not 00363 // a subkey 00364 if ( subkeys.item( i ).hasAttributes() && // if we have attributes 00365 subkeys.item( i ).isElement() && // and we're an element 00366 subkeys.item( i ).toElement().hasAttribute( "type" ) ) // and we have a "type" attribute 00367 { // then we're a key value 00368 delete mProperties.take( subkeys.item( i ).nodeName() ); 00369 mProperties.insert( subkeys.item( i ).nodeName(), new QgsPropertyValue ); 00370 00371 QDomNode subkey = subkeys.item( i ); 00372 00373 if ( !mProperties[subkeys.item( i ).nodeName()]->readXML( subkey ) ) 00374 { 00375 QgsDebugMsg( QString( "unable to parse key value %1" ).arg( subkeys.item( i ).nodeName() ) ); 00376 } 00377 } 00378 else // otherwise it's a subkey, so just 00379 // recurse on down the remaining keys 00380 { 00381 addKey( subkeys.item( i ).nodeName() ); 00382 00383 QDomNode subkey = subkeys.item( i ); 00384 00385 if ( !mProperties[subkeys.item( i ).nodeName()]->readXML( subkey ) ) 00386 { 00387 QgsDebugMsg( QString( "unable to parse subkey %1" ).arg( subkeys.item( i ).nodeName() ) ); 00388 } 00389 } 00390 00391 ++i; 00392 } 00393 00394 return true; 00395 } // QgsPropertyKey::readXML(QDomNode & keyNode) 00396 00397 00402 bool QgsPropertyKey::writeXML( QString const &nodeName, QDomElement & element, QDomDocument & document ) 00403 { 00404 // If it's an _empty_ node (i.e., one with no properties) we need to emit 00405 // an empty place holder; else create new Dom elements as necessary. 00406 00407 QDomElement keyElement = document.createElement( nodeName ); // Dom element for this property key 00408 00409 if ( ! mProperties.isEmpty() ) 00410 { 00411 QHashIterator < QString, QgsProperty* > i( mProperties ); 00412 while ( i.hasNext() ) 00413 { 00414 i.next(); 00415 if ( !i.value()->writeXML( i.key(), keyElement, document ) ) 00416 { 00417 return false; 00418 } 00419 } 00420 } 00421 00422 element.appendChild( keyElement ); 00423 00424 return true; 00425 } // QgsPropertyKey::writeXML 00426 00427 00428 00431 void QgsPropertyKey::entryList( QStringList & entries ) const 00432 { 00433 // now add any leaf nodes to the entries list 00434 QHashIterator < QString, QgsProperty* > i( mProperties ); 00435 while ( i.hasNext() ) 00436 { 00437 // add any of the nodes that have just a single value 00438 if ( i.next().value()->isLeaf() ) 00439 { 00440 entries.append( i.key() ); 00441 } 00442 } 00443 } // QgsPropertyKey::entryList 00444 00445 00446 00447 void QgsPropertyKey::subkeyList( QStringList & entries ) const 00448 { 00449 // now add any leaf nodes to the entries list 00450 QHashIterator < QString, QgsProperty* > i( mProperties ); 00451 while ( i.hasNext() ) 00452 { 00453 // add any of the nodes that have just a single value 00454 if ( !i.next().value()->isLeaf() ) 00455 { 00456 entries.append( i.key() ); 00457 } 00458 } 00459 } // QgsPropertyKey::subkeyList 00460 00461 00462 bool QgsPropertyKey::isLeaf() const 00463 { 00464 if ( 0 == count() ) 00465 { 00466 return true; 00467 } 00468 else if ( 1 == count() ) 00469 { 00470 QHashIterator < QString, QgsProperty* > i( mProperties ); 00471 00472 if ( i.hasNext() && i.next().value()->isValue() ) 00473 { 00474 return true; 00475 } 00476 } 00477 00478 return false; 00479 } // QgsPropertyKey::isLeaf