~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/core/qgsprojectproperty.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 ***************************************************************************/
17
17
 
18
18
#include "qgsprojectproperty.h"
19
 
 
20
 
 
21
 
#include <qdom.h>
22
 
#include <qglobal.h>
23
 
 
24
 
// Qt4-only includes to go here
 
19
#include "qgslogger.h"
 
20
 
 
21
#include <QDomDocument>
25
22
#include <QStringList>
26
23
 
27
 
 
28
 
static const char * const ident_ = "$Id: qgsprojectproperty.cpp 5681 2006-08-10 10:51:04Z g_j_m $";
29
 
 
30
 
 
 
24
static const char * const ident_ = "$Id$";
31
25
 
32
26
 
33
27
void QgsPropertyValue::dump( size_t tabs ) const
34
28
{
35
 
    QString tabString;
36
 
    tabString.fill( '\t', tabs );
37
 
 
38
 
    if (QVariant::StringList == value_.type())
39
 
    {
40
 
        QStringList sl = value_.toStringList();
41
 
 
42
 
        for (QStringList::const_iterator i = sl.begin(); i != sl.end(); ++i)
43
 
        {
44
 
            qDebug("%s[%s] ", tabString.toLocal8Bit().data(), (const char *) (*i).toLocal8Bit().data());
45
 
        } 
46
 
    }
47
 
    else
48
 
    {
49
 
        qDebug("%s%s", tabString.toLocal8Bit().data(), (const char *) value_.toString().toLocal8Bit().data());
50
 
    }
 
29
  QString tabString;
 
30
  tabString.fill( '\t', tabs );
 
31
 
 
32
  if ( QVariant::StringList == value_.type() )
 
33
  {
 
34
    QStringList sl = value_.toStringList();
 
35
 
 
36
    for ( QStringList::const_iterator i = sl.begin(); i != sl.end(); ++i )
 
37
    {
 
38
      QgsDebugMsg( QString( "%1[%2] " ).arg( tabString ).arg( *i ) );
 
39
    }
 
40
  }
 
41
  else
 
42
  {
 
43
    QgsDebugMsg( QString( "%1%2" ).arg( tabString ).arg( value_.toString() ) );
 
44
  }
51
45
} // QgsPropertyValue::dump()
52
46
 
53
47
 
54
48
 
55
 
bool QgsPropertyValue::readXML(QDomNode & keyNode)
 
49
bool QgsPropertyValue::readXML( QDomNode & keyNode )
56
50
{
57
 
    // this *should* be a DOM element node
58
 
    QDomElement subkeyElement = keyNode.toElement();
59
 
 
60
 
    // get the type so that we can properly parse the key value
61
 
    QString typeString = subkeyElement.attribute("type");
62
 
 
63
 
    if (QString::null == typeString)
64
 
    {
65
 
        qDebug("%s:%d null ``type'' attribute for %s", __FILE__, __LINE__,
66
 
               (const char *) keyNode.nodeName().utf8());
67
 
 
68
 
        return false;
69
 
    }
70
 
 
71
 
    // the values come in as strings; we need to restore them to their
72
 
    // original values *and* types
73
 
    value_.clear();
74
 
 
75
 
    // get the type associated with the value first
76
 
    QVariant::Type type = QVariant::nameToType(typeString.toLocal8Bit().data());
77
 
 
78
 
    // This huge switch is left-over from an earlier incarnation of
79
 
    // QgsProject where there was a fine level of granularity for value
80
 
    // types.  The current interface, borrowed from QSettings, supports a
81
 
    // very small sub-set of these types.  However, I've left all the
82
 
    // other types just in case the interface is expanded to include these
83
 
    // other types.
84
 
 
85
 
    switch (type)
86
 
    {
87
 
        case QVariant::Invalid:
88
 
            qDebug("%s:%d invalid value type %s .. ", __FILE__, __LINE__,
89
 
                   (const char *) typeString.utf8());
90
 
 
91
 
            return false;
92
 
 
93
 
            break;
94
 
 
95
 
        case QVariant::Map:
96
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Map", __LINE__);
97
 
 
98
 
            return false;
99
 
 
100
 
            break;
101
 
 
102
 
        case QVariant::List:
103
 
            qDebug("qgsproject.cpp:%d add support for QVariant::List", __LINE__);
104
 
 
105
 
            return false;
106
 
 
107
 
            break;
108
 
 
109
 
        case QVariant::String:
110
 
            value_ = subkeyElement.text();  // no translating necessary
111
 
            break;
112
 
 
113
 
        case QVariant::StringList:
 
51
  // this *should* be a Dom element node
 
52
  QDomElement subkeyElement = keyNode.toElement();
 
53
 
 
54
  // get the type so that we can properly parse the key value
 
55
  QString typeString = subkeyElement.attribute( "type" );
 
56
 
 
57
  if ( QString::null == typeString )
 
58
  {
 
59
    QgsDebugMsg( QString( "null ``type'' attribute for %1" ).arg( keyNode.nodeName() ) );
 
60
 
 
61
    return false;
 
62
  }
 
63
 
 
64
  // the values come in as strings; we need to restore them to their
 
65
  // original values *and* types
 
66
  value_.clear();
 
67
 
 
68
  // get the type associated with the value first
 
69
  QVariant::Type type = QVariant::nameToType( typeString.toLocal8Bit().constData() );
 
70
 
 
71
  // This huge switch is left-over from an earlier incarnation of
 
72
  // QgsProject where there was a fine level of granularity for value
 
73
  // types.  The current interface, borrowed from QSettings, supports a
 
74
  // very small sub-set of these types.  However, I've left all the
 
75
  // other types just in case the interface is expanded to include these
 
76
  // other types.
 
77
 
 
78
  switch ( type )
 
79
  {
 
80
    case QVariant::Invalid:
 
81
      QgsDebugMsg( QString( "invalid value type %1 .. " ).arg( typeString ) );
 
82
      return false;
 
83
 
 
84
    case QVariant::Map:
 
85
      QgsDebugMsg( "no support for QVariant::Map" );
 
86
      return false;
 
87
 
 
88
    case QVariant::List:
 
89
      QgsDebugMsg( "no support for QVariant::List" );
 
90
      return false;
 
91
 
 
92
    case QVariant::String:
 
93
      value_ = subkeyElement.text();  // no translating necessary
 
94
      break;
 
95
 
 
96
    case QVariant::StringList:
 
97
    {
 
98
      int i = 0;
 
99
      QDomNodeList values = keyNode.childNodes();
 
100
 
 
101
      // all the QStringList values will be inside <value> elements
 
102
      QStringList valueStringList;
 
103
 
 
104
      while ( i < values.count() )
 
105
      {
 
106
        if ( "value" == values.item( i ).nodeName() )
 
107
        {                     // <value>s have only one element, which contains actual string value
 
108
          valueStringList.append( values.item( i ).firstChild().nodeValue() );
 
109
        }
 
110
        else
114
111
        {
115
 
            int i = 0;
116
 
            QDomNodeList values = keyNode.childNodes();
117
 
 
118
 
            // all the QStringList values will be inside <value> elements
119
 
            QStringList valueStringList;
120
 
 
121
 
            while (i < values.count())
122
 
            {
123
 
                if ("value" == values.item(i).nodeName())
124
 
                {                     // <value>s have only one element, which contains actual string value
125
 
                    valueStringList.append(values.item(i).firstChild().nodeValue());
126
 
                } else
127
 
                {
128
 
                    qDebug
129
 
                        ("qgsproject.cpp:%d non <value> element ``%s'' in string list",
130
 
                         __LINE__, (const char *) values.item(i).nodeName().utf8());
131
 
                }
132
 
 
133
 
                ++i;
134
 
            }
135
 
 
136
 
            value_ = valueStringList;
137
 
 
138
 
            break;
 
112
          QgsDebugMsg( QString( "non <value> element ``%1'' in string list" ).arg( values.item( i ).nodeName() ) );
139
113
        }
140
 
        case QVariant::Font:
141
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Font", __LINE__);
142
 
 
143
 
            return false;
144
 
 
145
 
            break;
146
 
 
147
 
        case QVariant::Pixmap:
148
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Pixmap", __LINE__);
149
 
 
150
 
            return false;
151
 
 
152
 
            break;
153
 
 
154
 
        case QVariant::Brush:
155
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Brush", __LINE__);
156
 
 
157
 
            return false;
158
 
 
159
 
            break;
160
 
 
161
 
        case QVariant::Rect:
162
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Rect", __LINE__);
163
 
 
164
 
            return false;
165
 
 
166
 
            break;
167
 
 
168
 
        case QVariant::Size:
169
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Size", __LINE__);
170
 
 
171
 
            return false;
172
 
 
173
 
            break;
174
 
 
175
 
        case QVariant::Color:
176
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Color", __LINE__);
177
 
 
178
 
            return false;
179
 
 
180
 
            break;
181
 
 
182
 
        case QVariant::Palette:
183
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Palette", __LINE__);
184
 
 
185
 
            return false;
186
 
 
187
 
            break;
188
 
 
189
 
        case QVariant::ColorGroup:
190
 
            qDebug("qgsproject.cpp:%d add support for QVariant::ColorGroup",
191
 
                   __LINE__);
192
 
 
193
 
            return false;
194
 
 
195
 
            break;
196
 
 
197
 
        case QVariant::Point:
198
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Point", __LINE__);
199
 
 
200
 
            return false;
201
 
 
202
 
            break;
203
 
 
204
 
        case QVariant::Image:
205
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Image", __LINE__);
206
 
 
207
 
            return false;
208
 
 
209
 
            break;
210
 
 
211
 
        case QVariant::Int:
212
 
            value_ = QVariant(subkeyElement.text()).asInt();
213
 
 
214
 
            break;
215
 
 
216
 
        case QVariant::UInt:
217
 
            value_ = QVariant(subkeyElement.text()).asUInt();
218
 
 
219
 
            break;
220
 
 
221
 
        case QVariant::Bool:
222
 
            value_ = QVariant(subkeyElement.text()).asBool();
223
 
 
224
 
            break;
225
 
 
226
 
        case QVariant::Double:
227
 
            value_ = QVariant(subkeyElement.text()).asDouble();
228
 
 
229
 
            break;
230
 
 
231
 
        // in Qt4 this is equivalent to case QVariant::ByteArray
232
 
        case QVariant::CString:
233
 
            value_ = QVariant(subkeyElement.text()).asCString();
234
 
 
235
 
            break;
236
 
 
237
 
        case QVariant::PointArray:
238
 
            qDebug("qgsproject.cpp:%d add support for QVariant::PointArray",
239
 
                   __LINE__);
240
 
 
241
 
            return false;
242
 
 
243
 
            break;
244
 
 
245
 
        case QVariant::Region:
246
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Region", __LINE__);
247
 
 
248
 
            return false;
249
 
 
250
 
            break;
251
 
 
252
 
        case QVariant::Bitmap:
253
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Bitmap", __LINE__);
254
 
 
255
 
            return false;
256
 
 
257
 
            break;
258
 
 
259
 
 
260
 
        case QVariant::Cursor:
261
 
            qDebug("qgsproject.cpp:%d add support for QVariant::Cursor", __LINE__);
262
 
            return false;
263
 
 
264
 
            break;
265
 
 
266
 
        case QVariant::BitArray :
267
 
            qDebug( "qgsproject.cpp:%d add support for QVariant::BitArray", __LINE__ );
268
 
 
269
 
            return false;
270
 
 
271
 
            break;
272
 
 
273
 
        case QVariant::KeySequence :
274
 
            qDebug( "qgsproject.cpp:%d add support for QVariant::KeySequence", __LINE__ );
275
 
 
276
 
            return false;
277
 
 
278
 
            break;
279
 
 
280
 
        case QVariant::Pen :
281
 
            qDebug( "qgsproject.cpp:%d add support for QVariant::Pen", __LINE__ );
282
 
 
283
 
            return false;
284
 
 
285
 
            break;
286
 
            //
287
 
            // QGIS DIES NOT SUPPORT THESE VARIANT TYPES IN VERSION 3.1 DISABLING FOR NOW
288
 
            //
289
 
            /*
290
 
              case QVariant::LongLong :
291
 
              value_ = QVariant(subkeyElement.text()).asLongLong();
292
 
              break;
293
 
 
294
 
              case QVariant::ULongLong :
295
 
              value_ = QVariant(subkeyElement.text()).asULongLong();
296
 
              break;
297
 
            */
298
 
        default :
299
 
            qDebug( "%s:%d unsupported value type %s .. not propertly translated to QVariant in qgsproject.cpp:",
300
 
                    __FILE__, __LINE__, (const char*)typeString.utf8() );
 
114
 
 
115
        ++i;
 
116
      }
 
117
 
 
118
      value_ = valueStringList;
 
119
      break;
301
120
    }
302
121
 
303
 
    return true;
 
122
    case QVariant::Font:
 
123
      QgsDebugMsg( "no support for QVariant::Font" );
 
124
      return false;
 
125
 
 
126
    case QVariant::Pixmap:
 
127
      QgsDebugMsg( "no support for QVariant::Pixmap" );
 
128
      return false;
 
129
 
 
130
    case QVariant::Brush:
 
131
      QgsDebugMsg( "no support for QVariant::Brush" );
 
132
      return false;
 
133
 
 
134
    case QVariant::Rect:
 
135
      QgsDebugMsg( "no support for QVariant::Rect" );
 
136
      return false;
 
137
 
 
138
    case QVariant::Size:
 
139
      QgsDebugMsg( "no support for QVariant::Size" );
 
140
      return false;
 
141
 
 
142
    case QVariant::Color:
 
143
      QgsDebugMsg( "no support for QVariant::Color" );
 
144
      return false;
 
145
 
 
146
    case QVariant::Palette:
 
147
      QgsDebugMsg( "no support for QVariant::Palette" );
 
148
      return false;
 
149
 
 
150
    case QVariant::Point:
 
151
      QgsDebugMsg( "no support for QVariant::Point" );
 
152
      return false;
 
153
 
 
154
    case QVariant::Image:
 
155
      QgsDebugMsg( "no support for QVariant::Image" );
 
156
      return false;
 
157
 
 
158
    case QVariant::Int:
 
159
      value_ = QVariant( subkeyElement.text() ).toInt();
 
160
      break;
 
161
 
 
162
    case QVariant::UInt:
 
163
      value_ = QVariant( subkeyElement.text() ).toUInt();
 
164
      break;
 
165
 
 
166
    case QVariant::Bool:
 
167
      value_ = QVariant( subkeyElement.text() ).toBool();
 
168
      break;
 
169
 
 
170
    case QVariant::Double:
 
171
      value_ = QVariant( subkeyElement.text() ).toDouble();
 
172
      break;
 
173
 
 
174
    case QVariant::ByteArray:
 
175
      value_ = QVariant( subkeyElement.text() ).toByteArray();
 
176
      break;
 
177
 
 
178
    case QVariant::Polygon:
 
179
      QgsDebugMsg( "no support for QVariant::Polygon" );
 
180
      return false;
 
181
 
 
182
    case QVariant::Region:
 
183
      QgsDebugMsg( "no support for QVariant::Region" );
 
184
      return false;
 
185
 
 
186
    case QVariant::Bitmap:
 
187
      QgsDebugMsg( "no support for QVariant::Bitmap" );
 
188
      return false;
 
189
 
 
190
    case QVariant::Cursor:
 
191
      QgsDebugMsg( "no support for QVariant::Cursor" );
 
192
      return false;
 
193
 
 
194
    case QVariant::BitArray :
 
195
      QgsDebugMsg( "no support for QVariant::BitArray" );
 
196
      return false;
 
197
 
 
198
    case QVariant::KeySequence :
 
199
      QgsDebugMsg( "no support for QVariant::KeySequence" );
 
200
      return false;
 
201
 
 
202
    case QVariant::Pen :
 
203
      QgsDebugMsg( "no support for QVariant::Pen" );
 
204
      return false;
 
205
 
 
206
      //
 
207
      // QGIS DIES NOT SUPPORT THESE VARIANT TYPES IN VERSION 3.1 DISABLING FOR NOW
 
208
      //
 
209
      /*
 
210
        case QVariant::LongLong :
 
211
        value_ = QVariant(subkeyElement.text()).toLongLong();
 
212
        break;
 
213
 
 
214
        case QVariant::ULongLong :
 
215
        value_ = QVariant(subkeyElement.text()).toULongLong();
 
216
        break;
 
217
      */
 
218
    default :
 
219
      QgsDebugMsg( QString( "unsupported value type %1 .. not propertly translated to QVariant" ).arg( typeString ) );
 
220
  }
 
221
 
 
222
  return true;
304
223
 
305
224
} // QgsPropertyValue::readXML
306
225
 
308
227
/**
309
228
   @param element created by parent QgsPropertyKey
310
229
*/
311
 
bool QgsPropertyValue::writeXML( QString const & nodeName, 
312
 
                                 QDomElement   & keyElement, 
 
230
bool QgsPropertyValue::writeXML( QString const & nodeName,
 
231
                                 QDomElement   & keyElement,
313
232
                                 QDomDocument  & document )
314
233
{
315
 
    QDomElement valueElement = document.createElement( nodeName );
316
 
 
317
 
    // remember the type so that we can rebuild it when the project is read in
318
 
    valueElement.setAttribute( "type", value_.typeName() );
319
 
 
320
 
 
321
 
    // we handle string lists differently from other types in that we
322
 
    // create a sequence of repeated elements to cover all the string list
323
 
    // members; each value will be in a <value></value> tag.
324
 
    // XXX Not the most elegant way to handle string lists?
325
 
    if ( QVariant::StringList == value_.type() )
326
 
    {
327
 
        QStringList sl = value_.asStringList();
328
 
 
329
 
        for ( QStringList::iterator i = sl.begin();
330
 
              i != sl.end();
331
 
              ++i )
332
 
        {
333
 
            QDomElement stringListElement = document.createElement( "value" );
334
 
            QDomText valueText = document.createTextNode( *i );
335
 
            stringListElement.appendChild( valueText );
336
 
 
337
 
            valueElement.appendChild( stringListElement );
338
 
        }
339
 
    }
340
 
    else                    // we just plop the value in as plain ole text
341
 
    {
342
 
        QDomText valueText = document.createTextNode( value_.toString() );
343
 
        valueElement.appendChild( valueText );
344
 
    }
345
 
 
346
 
    keyElement.appendChild( valueElement );
347
 
 
348
 
    return true;
 
234
  QDomElement valueElement = document.createElement( nodeName );
 
235
 
 
236
  // remember the type so that we can rebuild it when the project is read in
 
237
  valueElement.setAttribute( "type", value_.typeName() );
 
238
 
 
239
 
 
240
  // we handle string lists differently from other types in that we
 
241
  // create a sequence of repeated elements to cover all the string list
 
242
  // members; each value will be in a <value></value> tag.
 
243
  // XXX Not the most elegant way to handle string lists?
 
244
  if ( QVariant::StringList == value_.type() )
 
245
  {
 
246
    QStringList sl = value_.toStringList();
 
247
 
 
248
    for ( QStringList::iterator i = sl.begin();
 
249
          i != sl.end();
 
250
          ++i )
 
251
    {
 
252
      QDomElement stringListElement = document.createElement( "value" );
 
253
      QDomText valueText = document.createTextNode( *i );
 
254
      stringListElement.appendChild( valueText );
 
255
 
 
256
      valueElement.appendChild( stringListElement );
 
257
    }
 
258
  }
 
259
  else                    // we just plop the value in as plain ole text
 
260
  {
 
261
    QDomText valueText = document.createTextNode( value_.toString() );
 
262
    valueElement.appendChild( valueText );
 
263
  }
 
264
 
 
265
  keyElement.appendChild( valueElement );
 
266
 
 
267
  return true;
349
268
} // QgsPropertyValue::writeXML
350
269
 
351
270
 
352
271
 
353
272
 
354
273
QgsPropertyKey::QgsPropertyKey( QString const name )
355
 
    : name_( name )
 
274
    : mName( name )
 
275
{}
 
276
 
 
277
QgsPropertyKey::~QgsPropertyKey()
356
278
{
357
 
    // since we own our properties, we are responsible for deleting the
358
 
    // contents
359
 
    properties_.setAutoDelete(true);
 
279
  clearKeys();
360
280
}
361
281
 
362
282
QVariant QgsPropertyKey::value() const
363
283
{
364
 
    QgsProperty * foundQgsProperty;
365
 
 
366
 
    if ( 0 == ( foundQgsProperty = properties_.find( name()) ) )
367
 
    {                        // recurse down to next key
368
 
        return foundQgsProperty->value();
369
 
    } else
370
 
    {
371
 
        qDebug("%s:%d QgsPropertyKey has null child", __FILE__, __LINE__);
372
 
 
373
 
        return QVariant();     // just return an QVariant::Invalid
374
 
    }
375
 
} // QVariant QgsPropertyKey::value() 
 
284
  QgsProperty * foundQgsProperty;
 
285
 
 
286
  if ( 0 == ( foundQgsProperty = mProperties.value( name() ) ) )
 
287
  {                        // recurse down to next key
 
288
    return foundQgsProperty->value();
 
289
  }
 
290
  else
 
291
  {
 
292
    QgsDebugMsg( "key has null child" );
 
293
 
 
294
    return QVariant();     // just return an QVariant::Invalid
 
295
  }
 
296
} // QVariant QgsPropertyKey::value()
376
297
 
377
298
 
378
299
void QgsPropertyKey::dump( size_t tabs ) const
379
300
{
380
 
    QString tabString;
381
 
 
382
 
    tabString.fill( '\t', tabs );
383
 
 
384
 
    qDebug( "%sname: %s", tabString.toLocal8Bit().data(), name().toLocal8Bit().data() );
385
 
         
386
 
    tabs++;
387
 
    tabString.fill( '\t', tabs );
388
 
 
389
 
    if ( ! properties_.isEmpty() )
 
301
  QString tabString;
 
302
 
 
303
  tabString.fill( '\t', tabs );
 
304
 
 
305
  QgsDebugMsg( QString( "%1name: %2" ).arg( tabString ).arg( name() ) );
 
306
 
 
307
  tabs++;
 
308
  tabString.fill( '\t', tabs );
 
309
 
 
310
  if ( ! mProperties.isEmpty() )
 
311
  {
 
312
    QHashIterator < QString, QgsProperty* > i( mProperties );
 
313
    while ( i.hasNext() )
390
314
    {
391
 
        for (Q3DictIterator < QgsProperty > i(properties_); i.current(); ++i)
392
 
        {
393
 
            if ( i.current()->isValue() )
394
 
            {
395
 
                QgsPropertyValue * propertyValue = 
396
 
                    dynamic_cast<QgsPropertyValue*>( i.current() );
397
 
 
398
 
                if ( QVariant::StringList == propertyValue->value().type() )
399
 
                {
400
 
                    qDebug("%skey: <%s>  value:", 
401
 
                           tabString.toLocal8Bit().data(), 
402
 
                           i.currentKey().toLocal8Bit().data() );
403
 
 
404
 
                    propertyValue->dump( tabs + 1 );
405
 
                }
406
 
                else
407
 
                {
408
 
                    qDebug("%skey: <%s>  value: %s", 
409
 
                           tabString.toLocal8Bit().data(), 
410
 
                           i.currentKey().toLocal8Bit().data(), 
411
 
                           propertyValue->value().toString().toLocal8Bit().data() );
412
 
                }
413
 
            }
414
 
            else
415
 
            {
416
 
                qDebug("%skey: <%s>  subkey: <%s>", 
417
 
                       tabString.toLocal8Bit().data(), 
418
 
                       i.currentKey().toLocal8Bit().data(),
419
 
                       dynamic_cast<QgsPropertyKey*>(i.current())->name().toLocal8Bit().data() );
420
 
 
421
 
                i.current()->dump( tabs + 1 );
422
 
            }
423
 
 
424
 
//              qDebug("<%s>", (const char *) name().utf8());
425
 
//              if ( i.current()->isValue() )
426
 
//              {
427
 
//                  qDebug("   <%s>", (const char*) i.currentKey().utf8() );
428
 
//              }
429
 
//              i.current()->dump();
430
 
//              if ( i.current()->isValue() )
431
 
//              {
432
 
//                  qDebug("   </%s>", (const char*) i.currentKey().utf8() );
433
 
//              }
434
 
//              qDebug("</%s>", (const char *) name().utf8());
435
 
        }
 
315
      if ( i.next().value()->isValue() )
 
316
      {
 
317
        QgsPropertyValue * propertyValue =
 
318
          dynamic_cast<QgsPropertyValue*>( i.value() );
 
319
 
 
320
        if ( QVariant::StringList == propertyValue->value().type() )
 
321
        {
 
322
          QgsDebugMsg( QString( "%1key: <%2>  value:" ).arg( tabString ).arg( i.key() ) );
 
323
          propertyValue->dump( tabs + 1 );
 
324
        }
 
325
        else
 
326
        {
 
327
          QgsDebugMsg( QString( "%1key: <%2>  value: %3" ).arg( tabString ).arg( i.key() ).arg( propertyValue->value().toString() ) );
 
328
        }
 
329
      }
 
330
      else
 
331
      {
 
332
        QgsDebugMsg( QString( "%1key: <%2>  subkey: <%3>" )
 
333
                     .arg( tabString )
 
334
                     .arg( i.key() )
 
335
                     .arg( dynamic_cast<QgsPropertyKey*>( i.value() )->name() ) );
 
336
        i.value()->dump( tabs + 1 );
 
337
      }
 
338
 
 
339
//              qDebug("<%s>", name().toUtf8().constData());
 
340
//              if ( i.value()->isValue() )
 
341
//              {
 
342
//                  qDebug("   <%s>", i.key().toUtf8().constData() );
 
343
//              }
 
344
//              i.value()->dump();
 
345
//              if ( i.value()->isValue() )
 
346
//              {
 
347
//                  qDebug("   </%s>", i.key().toUtf8().constData() );
 
348
//              }
 
349
//              qDebug("</%s>", name().toUtf8().constData());
436
350
    }
 
351
  }
437
352
 
438
353
} // QgsPropertyKey::dump
439
354
 
440
355
 
441
356
 
442
 
bool QgsPropertyKey::readXML(QDomNode & keyNode)
 
357
bool QgsPropertyKey::readXML( QDomNode & keyNode )
443
358
{
444
 
    int i = 0;
445
 
    QDomNodeList subkeys = keyNode.childNodes();
446
 
 
447
 
    while (i < subkeys.count())
 
359
  int i = 0;
 
360
  QDomNodeList subkeys = keyNode.childNodes();
 
361
 
 
362
  while ( i < subkeys.count() )
 
363
  {
 
364
    // if the current node is an element that has a "type" attribute,
 
365
    // then we know it's a leaf node; i.e., a subkey _value_, and not
 
366
    // a subkey
 
367
    if ( subkeys.item( i ).hasAttributes() && // if we have attributes
 
368
         subkeys.item( i ).isElement() && // and we're an element
 
369
         subkeys.item( i ).toElement().hasAttribute( "type" ) ) // and we have a "type" attribute
 
370
    {                   // then we're a key value
 
371
      delete mProperties.take( subkeys.item( i ).nodeName() );
 
372
      mProperties.insert( subkeys.item( i ).nodeName(), new QgsPropertyValue );
 
373
 
 
374
      QDomNode subkey = subkeys.item( i );
 
375
 
 
376
      if ( !mProperties[subkeys.item( i ).nodeName()]->readXML( subkey ) )
 
377
      {
 
378
        QgsDebugMsg( QString( "unable to parse key value %1" ).arg( subkeys.item( i ).nodeName() ) );
 
379
      }
 
380
    }
 
381
    else             // otherwise it's a subkey, so just
 
382
      // recurse on down the remaining keys
448
383
    {
449
 
        // if the current node is an element that has a "type" attribute,
450
 
        // then we know it's a leaf node; i.e., a subkey _value_, and not
451
 
        // a subkey
452
 
        if (subkeys.item(i).hasAttributes() && // if we have attributes
453
 
            subkeys.item(i).isElement() && // and we're an element
454
 
            subkeys.item(i).toElement().hasAttribute("type")) // and we have a "type" attribute
455
 
        {                   // then we're a key value
456
 
            properties_.replace(subkeys.item(i).nodeName(), new QgsPropertyValue);
457
 
 
458
 
            QDomNode subkey = subkeys.item(i);
459
 
 
460
 
            if (!properties_[subkeys.item(i).nodeName()]->readXML(subkey))
461
 
            {
462
 
                qDebug("%s:%d unable to parse key value %s", __FILE__, __LINE__,
463
 
                       (const char *) subkeys.item(i).nodeName().utf8());
464
 
            }
465
 
        } else             // otherwise it's a subkey, so just
466
 
            // recurse on down the remaining keys
467
 
        {
468
 
            addKey( subkeys.item(i).nodeName() );
469
 
 
470
 
            QDomNode subkey = subkeys.item(i);
471
 
 
472
 
            if (!properties_[subkeys.item(i).nodeName()]->readXML(subkey))
473
 
            {
474
 
                qDebug("%s:%d unable to parse subkey %s", __FILE__, __LINE__,
475
 
                       (const char *) subkeys.item(i).nodeName().utf8());
476
 
            }
477
 
        }
478
 
 
479
 
        ++i;
 
384
      addKey( subkeys.item( i ).nodeName() );
 
385
 
 
386
      QDomNode subkey = subkeys.item( i );
 
387
 
 
388
      if ( !mProperties[subkeys.item( i ).nodeName()]->readXML( subkey ) )
 
389
      {
 
390
        QgsDebugMsg( QString( "unable to parse subkey %1" ).arg( subkeys.item( i ).nodeName() ) );
 
391
      }
480
392
    }
481
393
 
482
 
    return true;
 
394
    ++i;
 
395
  }
 
396
 
 
397
  return true;
483
398
} // QgsPropertyKey::readXML(QDomNode & keyNode)
484
399
 
485
400
 
486
401
/**
487
 
  Property keys will always create a DOM element for itself and then
 
402
  Property keys will always create a Dom element for itself and then
488
403
  recursively call writeXML for any constituent properties.
489
404
*/
490
 
bool QgsPropertyKey::writeXML(QString const &nodeName, QDomElement & element, QDomDocument & document)
 
405
bool QgsPropertyKey::writeXML( QString const &nodeName, QDomElement & element, QDomDocument & document )
491
406
{
492
 
    // If it's an _empty_ node (i.e., one with no properties) we need to emit
493
 
    // an empty place holder; else create new DOM elements as necessary.
494
 
 
495
 
    QDomElement keyElement = document.createElement(nodeName); // DOM element for this property key
496
 
 
497
 
    if ( ! properties_.isEmpty() )
 
407
  // If it's an _empty_ node (i.e., one with no properties) we need to emit
 
408
  // an empty place holder; else create new Dom elements as necessary.
 
409
 
 
410
  QDomElement keyElement = document.createElement( nodeName ); // Dom element for this property key
 
411
 
 
412
  if ( ! mProperties.isEmpty() )
 
413
  {
 
414
    QHashIterator < QString, QgsProperty* > i( mProperties );
 
415
    while ( i.hasNext() )
498
416
    {
499
 
        for (Q3DictIterator < QgsProperty > i(properties_); i.current(); ++i)
500
 
        {
501
 
            if (!i.current()->writeXML(i.currentKey(), keyElement, document))
502
 
            {
503
 
                return false;
504
 
            }
505
 
        }
 
417
      i.next();
 
418
      if ( !i.value()->writeXML( i.key(), keyElement, document ) )
 
419
      {
 
420
        return false;
 
421
      }
506
422
    }
507
 
 
508
 
    element.appendChild(keyElement);
509
 
 
510
 
    return true;
 
423
  }
 
424
 
 
425
  element.appendChild( keyElement );
 
426
 
 
427
  return true;
511
428
} // QgsPropertyKey::writeXML
512
429
 
513
430
 
514
431
 
515
432
/** return keys that do not contain other keys
516
 
 */ 
 
433
 */
517
434
void QgsPropertyKey::entryList( QStringList & entries ) const
518
435
{
519
 
    // now add any leaf nodes to the entries list
520
 
    for (Q3DictIterator<QgsProperty> i(properties_); i.current(); ++i)
 
436
  // now add any leaf nodes to the entries list
 
437
  QHashIterator < QString, QgsProperty* > i( mProperties );
 
438
  while ( i.hasNext() )
 
439
  {
 
440
    // add any of the nodes that have just a single value
 
441
    if ( i.next().value()->isLeaf() )
521
442
    {
522
 
        // add any of the nodes that have just a single value
523
 
        if (i.current()->isLeaf())
524
 
        {
525
 
            entries.append(i.currentKey());
526
 
        }
 
443
      entries.append( i.key() );
527
444
    }
 
445
  }
528
446
} // QgsPropertyKey::entryList
529
447
 
530
448
 
531
449
 
532
 
void QgsPropertyKey::subkeyList(QStringList & entries) const
 
450
void QgsPropertyKey::subkeyList( QStringList & entries ) const
533
451
{
534
 
    // now add any leaf nodes to the entries list
535
 
    for (Q3DictIterator < QgsProperty > i(properties_); i.current(); ++i)
 
452
  // now add any leaf nodes to the entries list
 
453
  QHashIterator < QString, QgsProperty* > i( mProperties );
 
454
  while ( i.hasNext() )
 
455
  {
 
456
    // add any of the nodes that have just a single value
 
457
    if ( !i.next().value()->isLeaf() )
536
458
    {
537
 
        // add any of the nodes that have just a single value
538
 
        if (!i.current()->isLeaf())
539
 
        {
540
 
            entries.append(i.currentKey());
541
 
        }
 
459
      entries.append( i.key() );
542
460
    }
 
461
  }
543
462
} // QgsPropertyKey::subkeyList
544
463
 
545
464
 
546
465
bool QgsPropertyKey::isLeaf() const
547
466
{
548
 
    if (0 == count())
549
 
    {
550
 
        return true;
551
 
    }
552
 
    else if (1 == count())
553
 
    {
554
 
        Q3DictIterator < QgsProperty > i(properties_);
555
 
 
556
 
        if (i.current() && i.current()->isValue())
557
 
        {
558
 
            return true;
559
 
        }
560
 
    }
561
 
 
562
 
    return false;
 
467
  if ( 0 == count() )
 
468
  {
 
469
    return true;
 
470
  }
 
471
  else if ( 1 == count() )
 
472
  {
 
473
    QHashIterator < QString, QgsProperty* > i( mProperties );
 
474
 
 
475
    if ( i.hasNext() && i.next().value()->isValue() )
 
476
    {
 
477
      return true;
 
478
    }
 
479
  }
 
480
 
 
481
  return false;
563
482
} // QgsPropertyKey::isLeaf
564
 
 
565
 
 
566