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