Quantum GIS API Documentation  1.7.4
src/core/qgsprojectproperty.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines