LCOV - code coverage report
Current view: top level - core/project - qgsprojectproperty.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 13 193 6.7 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                           qgsproject.cpp -  description
       3                 :            :                              -------------------
       4                 :            :   begin                : February 24, 2005
       5                 :            :   copyright            : (C) 2005 by Mark Coletti
       6                 :            :   email                : mcoletti at gmail.com
       7                 :            : ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #include "qgsprojectproperty.h"
      19                 :            : #include "qgslogger.h"
      20                 :            : #include "qgis.h"
      21                 :            : #include "qgsmessagelog.h"
      22                 :            : 
      23                 :            : #include <QDomDocument>
      24                 :            : #include <QStringList>
      25                 :            : 
      26                 :         71 : QgsProjectProperty::QgsProjectProperty() //NOLINT
      27                 :         71 : {
      28                 :         71 : }
      29                 :            : 
      30                 :          0 : void QgsProjectPropertyValue::dump( int tabs ) const
      31                 :            : {
      32                 :            :   Q_UNUSED( tabs )
      33                 :            : #ifdef QGISDEBUG
      34                 :            : 
      35                 :            :   QString tabString;
      36                 :            :   tabString.fill( '\t', tabs );
      37                 :            : 
      38                 :            :   if ( QVariant::StringList == mValue.type() )
      39                 :            :   {
      40                 :            :     const QStringList sl = mValue.toStringList();
      41                 :            : 
      42                 :            :     for ( const auto &string : sl )
      43                 :            :     {
      44                 :            :       QgsDebugMsgLevel( QStringLiteral( "%1[%2] " ).arg( tabString, string ), 4 );
      45                 :            :     }
      46                 :            :   }
      47                 :            :   else
      48                 :            :   {
      49                 :            :     QgsDebugMsgLevel( QStringLiteral( "%1%2" ).arg( tabString, mValue.toString() ), 4 );
      50                 :            :   }
      51                 :            : #endif
      52                 :          0 : }
      53                 :            : 
      54                 :          0 : bool QgsProjectPropertyValue::readXml( const QDomNode &keyNode )
      55                 :            : {
      56                 :            :   // this *should* be a Dom element node
      57                 :          0 :   QDomElement subkeyElement = keyNode.toElement();
      58                 :            : 
      59                 :            :   // get the type so that we can properly parse the key value
      60                 :          0 :   QString typeString = subkeyElement.attribute( QStringLiteral( "type" ) );
      61                 :            : 
      62                 :          0 :   if ( typeString.isNull() )
      63                 :            :   {
      64                 :          0 :     QgsDebugMsg( QStringLiteral( "null ``type'' attribute for %1" ).arg( keyNode.nodeName() ) );
      65                 :            : 
      66                 :          0 :     return false;
      67                 :            :   }
      68                 :            : 
      69                 :            :   // the values come in as strings; we need to restore them to their
      70                 :            :   // original values *and* types
      71                 :          0 :   mValue.clear();
      72                 :            : 
      73                 :            :   // get the type associated with the value first
      74                 :          0 :   QVariant::Type type = QVariant::nameToType( typeString.toLocal8Bit().constData() );
      75                 :            : 
      76                 :            :   // This huge switch is left-over from an earlier incarnation of
      77                 :            :   // QgsProject where there was a fine level of granularity for value
      78                 :            :   // types.  The current interface, borrowed from QgsSettings, supports a
      79                 :            :   // very small sub-set of these types.  However, I've left all the
      80                 :            :   // other types just in case the interface is expanded to include these
      81                 :            :   // other types.
      82                 :            : 
      83                 :          0 :   switch ( type )
      84                 :            :   {
      85                 :            :     case QVariant::Invalid:
      86                 :          0 :       QgsDebugMsg( QStringLiteral( "invalid value type %1 .. " ).arg( typeString ) );
      87                 :          0 :       return false;
      88                 :            : 
      89                 :            :     case QVariant::Map:
      90                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Map" ) );
      91                 :          0 :       return false;
      92                 :            : 
      93                 :            :     case QVariant::List:
      94                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::List" ) );
      95                 :          0 :       return false;
      96                 :            : 
      97                 :            :     case QVariant::String:
      98                 :          0 :       mValue = subkeyElement.text();  // no translating necessary
      99                 :          0 :       break;
     100                 :            : 
     101                 :            :     case QVariant::StringList:
     102                 :            :     {
     103                 :          0 :       int i = 0;
     104                 :          0 :       QDomNodeList values = keyNode.childNodes();
     105                 :            : 
     106                 :            :       // all the QStringList values will be inside <value> elements
     107                 :          0 :       QStringList valueStringList;
     108                 :            : 
     109                 :          0 :       while ( i < values.count() )
     110                 :            :       {
     111                 :          0 :         if ( "value" == values.item( i ).nodeName() )
     112                 :            :         {
     113                 :            :           // <value>s have only one element, which contains actual string value
     114                 :          0 :           valueStringList.append( values.item( i ).firstChild().nodeValue() );
     115                 :          0 :         }
     116                 :            :         else
     117                 :            :         {
     118                 :          0 :           QgsDebugMsg( QStringLiteral( "non <value> element ``%1'' in string list" ).arg( values.item( i ).nodeName() ) );
     119                 :            :         }
     120                 :            : 
     121                 :          0 :         ++i;
     122                 :            :       }
     123                 :            : 
     124                 :          0 :       mValue = valueStringList;
     125                 :            :       break;
     126                 :          0 :     }
     127                 :            : 
     128                 :            :     case QVariant::Font:
     129                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Font" ) );
     130                 :          0 :       return false;
     131                 :            : 
     132                 :            :     case QVariant::Pixmap:
     133                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Pixmap" ) );
     134                 :          0 :       return false;
     135                 :            : 
     136                 :            :     case QVariant::Brush:
     137                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Brush" ) );
     138                 :          0 :       return false;
     139                 :            : 
     140                 :            :     case QVariant::Rect:
     141                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Rect" ) );
     142                 :          0 :       return false;
     143                 :            : 
     144                 :            :     case QVariant::Size:
     145                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Size" ) );
     146                 :          0 :       return false;
     147                 :            : 
     148                 :            :     case QVariant::Color:
     149                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Color" ) );
     150                 :          0 :       return false;
     151                 :            : 
     152                 :            :     case QVariant::Palette:
     153                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Palette" ) );
     154                 :          0 :       return false;
     155                 :            : 
     156                 :            :     case QVariant::Point:
     157                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Point" ) );
     158                 :          0 :       return false;
     159                 :            : 
     160                 :            :     case QVariant::Image:
     161                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Image" ) );
     162                 :          0 :       return false;
     163                 :            : 
     164                 :            :     case QVariant::Int:
     165                 :          0 :       mValue = QVariant( subkeyElement.text() ).toInt();
     166                 :          0 :       break;
     167                 :            : 
     168                 :            :     case QVariant::UInt:
     169                 :          0 :       mValue = QVariant( subkeyElement.text() ).toUInt();
     170                 :          0 :       break;
     171                 :            : 
     172                 :            :     case QVariant::Bool:
     173                 :          0 :       mValue = QVariant( subkeyElement.text() ).toBool();
     174                 :          0 :       break;
     175                 :            : 
     176                 :            :     case QVariant::Double:
     177                 :          0 :       mValue = QVariant( subkeyElement.text() ).toDouble();
     178                 :          0 :       break;
     179                 :            : 
     180                 :            :     case QVariant::ByteArray:
     181                 :          0 :       mValue = QVariant( subkeyElement.text() ).toByteArray();
     182                 :          0 :       break;
     183                 :            : 
     184                 :            :     case QVariant::Polygon:
     185                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Polygon" ) );
     186                 :          0 :       return false;
     187                 :            : 
     188                 :            :     case QVariant::Region:
     189                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Region" ) );
     190                 :          0 :       return false;
     191                 :            : 
     192                 :            :     case QVariant::Bitmap:
     193                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Bitmap" ) );
     194                 :          0 :       return false;
     195                 :            : 
     196                 :            :     case QVariant::Cursor:
     197                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Cursor" ) );
     198                 :          0 :       return false;
     199                 :            : 
     200                 :            :     case QVariant::BitArray :
     201                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::BitArray" ) );
     202                 :          0 :       return false;
     203                 :            : 
     204                 :            :     case QVariant::KeySequence :
     205                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::KeySequence" ) );
     206                 :          0 :       return false;
     207                 :            : 
     208                 :            :     case QVariant::Pen :
     209                 :          0 :       QgsDebugMsg( QStringLiteral( "no support for QVariant::Pen" ) );
     210                 :          0 :       return false;
     211                 :            : 
     212                 :            : #if 0 // Currently unsupported variant types
     213                 :            :     case QVariant::LongLong :
     214                 :            :       value_ = QVariant( subkeyElement.text() ).toLongLong();
     215                 :            :       break;
     216                 :            : 
     217                 :            :     case QVariant::ULongLong :
     218                 :            :       value_ = QVariant( subkeyElement.text() ).toULongLong();
     219                 :            :       break;
     220                 :            : #endif
     221                 :            :     default :
     222                 :          0 :       QgsDebugMsg( QStringLiteral( "unsupported value type %1 .. not properly translated to QVariant" ).arg( typeString ) );
     223                 :          0 :   }
     224                 :            : 
     225                 :          0 :   return true;
     226                 :            : 
     227                 :          0 : }
     228                 :            : 
     229                 :            : 
     230                 :            : // keyElement is created by parent QgsProjectPropertyKey
     231                 :          0 : bool QgsProjectPropertyValue::writeXml( QString const &nodeName,
     232                 :            :                                         QDomElement    &keyElement,
     233                 :            :                                         QDomDocument   &document )
     234                 :            : {
     235                 :          0 :   QDomElement valueElement = document.createElement( nodeName );
     236                 :            : 
     237                 :            :   // remember the type so that we can rebuild it when the project is read in
     238                 :          0 :   valueElement.setAttribute( QStringLiteral( "type" ), mValue.typeName() );
     239                 :            : 
     240                 :            : 
     241                 :            :   // we handle string lists differently from other types in that we
     242                 :            :   // create a sequence of repeated elements to cover all the string list
     243                 :            :   // members; each value will be in a <value></value> tag.
     244                 :            :   // XXX Not the most elegant way to handle string lists?
     245                 :          0 :   if ( QVariant::StringList == mValue.type() )
     246                 :            :   {
     247                 :          0 :     QStringList sl = mValue.toStringList();
     248                 :            : 
     249                 :          0 :     for ( QStringList::iterator i = sl.begin();
     250                 :          0 :           i != sl.end();
     251                 :          0 :           ++i )
     252                 :            :     {
     253                 :          0 :       QDomElement stringListElement = document.createElement( QStringLiteral( "value" ) );
     254                 :          0 :       QDomText valueText = document.createTextNode( *i );
     255                 :          0 :       stringListElement.appendChild( valueText );
     256                 :            : 
     257                 :          0 :       valueElement.appendChild( stringListElement );
     258                 :          0 :     }
     259                 :          0 :   }
     260                 :            :   else                    // we just plop the value in as plain ole text
     261                 :            :   {
     262                 :          0 :     QDomText valueText = document.createTextNode( mValue.toString() );
     263                 :          0 :     valueElement.appendChild( valueText );
     264                 :          0 :   }
     265                 :            : 
     266                 :          0 :   keyElement.appendChild( valueElement );
     267                 :            : 
     268                 :            :   return true;
     269                 :          0 : }
     270                 :            : 
     271                 :            : 
     272                 :         30 : QgsProjectPropertyKey::QgsProjectPropertyKey( const QString &name )
     273                 :         30 :   : mName( name )
     274                 :         90 : {}
     275                 :            : 
     276                 :         41 : QgsProjectPropertyKey::~QgsProjectPropertyKey()
     277                 :         41 : {
     278                 :         22 :   clearKeys();
     279                 :         41 : }
     280                 :            : 
     281                 :          0 : QVariant QgsProjectPropertyKey::value() const
     282                 :            : {
     283                 :          0 :   QgsProjectProperty *foundQgsProperty = mProperties.value( name() );
     284                 :            : 
     285                 :          0 :   if ( !foundQgsProperty )
     286                 :            :   {
     287                 :          0 :     QgsDebugMsg( QStringLiteral( "key has null child" ) );
     288                 :          0 :     return QVariant();     // just return an QVariant::Invalid
     289                 :            :   }
     290                 :            : 
     291                 :          0 :   return foundQgsProperty->value();
     292                 :          0 : }
     293                 :            : 
     294                 :            : 
     295                 :          0 : void QgsProjectPropertyKey::dump( int tabs ) const
     296                 :            : {
     297                 :          0 :   QString tabString;
     298                 :            : 
     299                 :          0 :   tabString.fill( '\t', tabs );
     300                 :            : 
     301                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "%1name: %2" ).arg( tabString, name() ), 4 );
     302                 :            : 
     303                 :          0 :   tabs++;
     304                 :          0 :   tabString.fill( '\t', tabs );
     305                 :            : 
     306                 :          0 :   if ( ! mProperties.isEmpty() )
     307                 :            :   {
     308                 :          0 :     QHashIterator < QString, QgsProjectProperty * > i( mProperties );
     309                 :          0 :     while ( i.hasNext() )
     310                 :            :     {
     311                 :          0 :       if ( i.next().value()->isValue() )
     312                 :            :       {
     313                 :          0 :         QgsProjectPropertyValue *propertyValue = static_cast<QgsProjectPropertyValue *>( i.value() );
     314                 :            : 
     315                 :          0 :         if ( QVariant::StringList == propertyValue->value().type() )
     316                 :            :         {
     317                 :          0 :           QgsDebugMsgLevel( QStringLiteral( "%1key: <%2>  value:" ).arg( tabString, i.key() ), 4 );
     318                 :          0 :           propertyValue->dump( tabs + 1 );
     319                 :          0 :         }
     320                 :            :         else
     321                 :            :         {
     322                 :          0 :           QgsDebugMsgLevel( QStringLiteral( "%1key: <%2>  value: %3" ).arg( tabString, i.key(), propertyValue->value().toString() ), 4 );
     323                 :            :         }
     324                 :          0 :       }
     325                 :            :       else
     326                 :            :       {
     327                 :          0 :         QgsDebugMsgLevel( QStringLiteral( "%1key: <%2>  subkey: <%3>" )
     328                 :            :                           .arg( tabString,
     329                 :            :                                 i.key(),
     330                 :            :                                 static_cast<QgsProjectPropertyKey *>( i.value() )->name() ), 4 );
     331                 :          0 :         i.value()->dump( tabs + 1 );
     332                 :            :       }
     333                 :            : 
     334                 :            : #if 0
     335                 :            :       qDebug( "<%s>", name().toUtf8().constData() );
     336                 :            :       if ( i.value()->isValue() )
     337                 :            :       {
     338                 :            :         qDebug( "   <%s>", i.key().toUtf8().constData() );
     339                 :            :       }
     340                 :            :       i.value()->dump();
     341                 :            :       if ( i.value()->isValue() )
     342                 :            :       {
     343                 :            :         qDebug( "   </%s>", i.key().toUtf8().constData() );
     344                 :            :       }
     345                 :            :       qDebug( "</%s>", name().toUtf8().constData() );
     346                 :            : #endif
     347                 :            :     }
     348                 :          0 :   }
     349                 :            : 
     350                 :          0 : }
     351                 :            : 
     352                 :            : 
     353                 :            : 
     354                 :          0 : bool QgsProjectPropertyKey::readXml( const QDomNode &keyNode )
     355                 :            : {
     356                 :          0 :   int i = 0;
     357                 :          0 :   QDomNodeList subkeys = keyNode.childNodes();
     358                 :            : 
     359                 :          0 :   while ( i < subkeys.count() )
     360                 :            :   {
     361                 :            :     // if the current node is an element that has a "type" attribute,
     362                 :            :     // then we know it's a leaf node; i.e., a subkey _value_, and not
     363                 :            :     // a subkey
     364                 :          0 :     if ( subkeys.item( i ).hasAttributes() && // if we have attributes
     365                 :          0 :          subkeys.item( i ).isElement() && // and we're an element
     366                 :          0 :          subkeys.item( i ).toElement().hasAttribute( QStringLiteral( "type" ) ) ) // and we have a "type" attribute
     367                 :            :     {
     368                 :            :       // then we're a key value
     369                 :          0 :       delete mProperties.take( subkeys.item( i ).nodeName() );
     370                 :          0 :       mProperties.insert( subkeys.item( i ).nodeName(), new QgsProjectPropertyValue );
     371                 :            : 
     372                 :          0 :       QDomNode subkey = subkeys.item( i );
     373                 :            : 
     374                 :          0 :       if ( !mProperties[subkeys.item( i ).nodeName()]->readXml( subkey ) )
     375                 :            :       {
     376                 :          0 :         QgsDebugMsg( QStringLiteral( "unable to parse key value %1" ).arg( subkeys.item( i ).nodeName() ) );
     377                 :          0 :       }
     378                 :          0 :     }
     379                 :            :     else // otherwise it's a subkey, so just recurse on down the remaining keys
     380                 :            :     {
     381                 :          0 :       addKey( subkeys.item( i ).nodeName() );
     382                 :            : 
     383                 :          0 :       QDomNode subkey = subkeys.item( i );
     384                 :            : 
     385                 :          0 :       if ( !mProperties[subkeys.item( i ).nodeName()]->readXml( subkey ) )
     386                 :            :       {
     387                 :          0 :         QgsDebugMsg( QStringLiteral( "unable to parse subkey %1" ).arg( subkeys.item( i ).nodeName() ) );
     388                 :          0 :       }
     389                 :          0 :     }
     390                 :            : 
     391                 :          0 :     ++i;
     392                 :            :   }
     393                 :            : 
     394                 :            :   return true;
     395                 :          0 : }
     396                 :            : 
     397                 :            : 
     398                 :            : /*
     399                 :            :   Property keys will always create a Dom element for itself and then
     400                 :            :   recursively call writeXml for any constituent properties.
     401                 :            : */
     402                 :          0 : bool QgsProjectPropertyKey::writeXml( QString const &nodeName, QDomElement &element, QDomDocument &document )
     403                 :            : {
     404                 :            :   // If it's an _empty_ node (i.e., one with no properties) we need to emit
     405                 :            :   // an empty place holder; else create new Dom elements as necessary.
     406                 :            : 
     407                 :          0 :   QDomElement keyElement = document.createElement( nodeName ); // Dom element for this property key
     408                 :            : 
     409                 :          0 :   if ( ! mProperties.isEmpty() )
     410                 :            :   {
     411                 :          0 :     auto keys = mProperties.keys();
     412                 :          0 :     std::sort( keys.begin(), keys.end() );
     413                 :            : 
     414                 :          0 :     for ( const auto &key : std::as_const( keys ) )
     415                 :            :     {
     416                 :          0 :       if ( !mProperties.value( key )->writeXml( key, keyElement, document ) )
     417                 :          0 :         QgsMessageLog::logMessage( tr( "Failed to save project property %1" ).arg( key ) );
     418                 :            :     }
     419                 :          0 :   }
     420                 :            : 
     421                 :          0 :   element.appendChild( keyElement );
     422                 :            : 
     423                 :            :   return true;
     424                 :          0 : }
     425                 :            : 
     426                 :          0 : void QgsProjectPropertyKey::entryList( QStringList &entries ) const
     427                 :            : {
     428                 :            :   // now add any leaf nodes to the entries list
     429                 :          0 :   QHashIterator < QString, QgsProjectProperty * > i( mProperties );
     430                 :          0 :   while ( i.hasNext() )
     431                 :            :   {
     432                 :            :     // add any of the nodes that have just a single value
     433                 :          0 :     if ( i.next().value()->isLeaf() )
     434                 :            :     {
     435                 :          0 :       entries.append( i.key() );
     436                 :          0 :     }
     437                 :            :   }
     438                 :          0 : }
     439                 :            : 
     440                 :          0 : void QgsProjectPropertyKey::subkeyList( QStringList &entries ) const
     441                 :            : {
     442                 :            :   // now add any leaf nodes to the entries list
     443                 :          0 :   QHashIterator < QString, QgsProjectProperty * > i( mProperties );
     444                 :          0 :   while ( i.hasNext() )
     445                 :            :   {
     446                 :            :     // add any of the nodes that have just a single value
     447                 :          0 :     if ( !i.next().value()->isLeaf() )
     448                 :            :     {
     449                 :          0 :       entries.append( i.key() );
     450                 :          0 :     }
     451                 :            :   }
     452                 :          0 : }
     453                 :            : 
     454                 :            : 
     455                 :          0 : bool QgsProjectPropertyKey::isLeaf() const
     456                 :            : {
     457                 :          0 :   if ( 0 == count() )
     458                 :            :   {
     459                 :          0 :     return true;
     460                 :            :   }
     461                 :          0 :   else if ( 1 == count() )
     462                 :            :   {
     463                 :          0 :     QHashIterator < QString, QgsProjectProperty * > i( mProperties );
     464                 :            : 
     465                 :          0 :     if ( i.hasNext() && i.next().value()->isValue() )
     466                 :            :     {
     467                 :          0 :       return true;
     468                 :            :     }
     469                 :          0 :   }
     470                 :            : 
     471                 :          0 :   return false;
     472                 :          0 : }
     473                 :            : 
     474                 :          5 : void QgsProjectPropertyKey::setName( const QString &name )
     475                 :            : {
     476                 :          5 :   mName = name;
     477                 :          5 : }

Generated by: LCOV version 1.14