Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / libs / plasma / configxml.cpp
blob576c18aa1efb58337ac502bbc3c40bbc407fac28
1 /*
2 * Copyright 2007 Aaron Seigo <aseigo@kde.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "configxml.h"
22 #include <QColor>
23 #include <QFont>
24 #include <QXmlContentHandler>
25 #include <QXmlInputSource>
26 #include <QXmlSimpleReader>
28 #include <KDebug>
29 #include <KUrl>
31 namespace Plasma
34 class ConfigXml::Private
36 public:
37 ~Private()
39 qDeleteAll(bools);
40 qDeleteAll(strings);
41 qDeleteAll(stringlists);
42 qDeleteAll(colors);
43 qDeleteAll(fonts);
44 qDeleteAll(ints);
45 qDeleteAll(uints);
46 qDeleteAll(urls);
47 qDeleteAll(dateTimes);
48 qDeleteAll(doubles);
49 qDeleteAll(intlists);
50 qDeleteAll(longlongs);
51 qDeleteAll(points);
52 qDeleteAll(rects);
53 qDeleteAll(sizes);
54 qDeleteAll(ulonglongs);
55 qDeleteAll(urllists);
58 bool* newBool()
60 bool* v = new bool;
61 bools.append(v);
62 return v;
65 QString* newString()
67 QString* v = new QString;
68 strings.append(v);
69 return v;
72 QStringList* newStringList()
74 QStringList* v = new QStringList;
75 stringlists.append(v);
76 return v;
79 QColor* newColor()
81 QColor* v = new QColor;
82 colors.append(v);
83 return v;
86 QFont* newFont()
88 QFont* v = new QFont;
89 fonts.append(v);
90 return v;
93 qint32* newInt()
95 qint32* v = new qint32;
96 ints.append(v);
97 return v;
100 quint32* newUint()
102 quint32* v = new quint32;
103 uints.append(v);
104 return v;
107 KUrl* newUrl()
109 KUrl* v = new KUrl;
110 urls.append(v);
111 return v;
114 QDateTime* newDateTime()
116 QDateTime* v = new QDateTime;
117 dateTimes.append(v);
118 return v;
121 double* newDouble()
123 double* v = new double;
124 doubles.append(v);
125 return v;
128 QList<qint32>* newIntList()
130 QList<qint32>* v = new QList<qint32>;
131 intlists.append(v);
132 return v;
135 qint64* newLongLong()
137 qint64* v = new qint64;
138 longlongs.append(v);
139 return v;
142 QPoint* newPoint()
144 QPoint* v = new QPoint;
145 points.append(v);
146 return v;
149 QRect* newRect()
151 QRect* v = new QRect;
152 rects.append(v);
153 return v;
156 QSize* newSize()
158 QSize* v = new QSize;
159 sizes.append(v);
160 return v;
163 quint64* newULongLong()
165 quint64* v = new quint64;
166 ulonglongs.append(v);
167 return v;
170 KUrl::List* newUrlList()
172 KUrl::List* v = new KUrl::List;
173 urllists.append(v);
174 return v;
177 void parse(ConfigXml *configXml, QIODevice *xml);
179 QList<bool*> bools;
180 QList<QString*> strings;
181 QList<QStringList*> stringlists;
182 QList<QColor*> colors;
183 QList<QFont*> fonts;
184 QList<qint32*> ints;
185 QList<quint32*> uints;
186 QList<KUrl*> urls;
187 QList<QDateTime*> dateTimes;
188 QList<double*> doubles;
189 QList<QList<qint32>*> intlists;
190 QList<qint64*> longlongs;
191 QList<QPoint*> points;
192 QList<QRect*> rects;
193 QList<QSize*> sizes;
194 QList<quint64*> ulonglongs;
195 QList<KUrl::List*> urllists;
198 class ConfigXmlHandler : public QXmlDefaultHandler
200 public:
201 ConfigXmlHandler(ConfigXml* config, ConfigXml::Private* d);
202 bool startElement(const QString &namespaceURI, const QString & localName, const QString &qName, const QXmlAttributes &atts);
203 bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
204 bool characters(const QString &ch);
206 private:
207 void addItem();
208 void resetState();
210 ConfigXml* m_config;
211 ConfigXml::Private* d;
212 int m_min;
213 int m_max;
214 QString m_name;
215 QString m_key;
216 QString m_type;
217 QString m_label;
218 QString m_default;
219 QString m_cdata;
220 QString m_whatsThis;
221 KConfigSkeleton::ItemEnum::Choice m_choice;
222 QList<KConfigSkeleton::ItemEnum::Choice> m_enumChoices;
223 bool m_haveMin;
224 bool m_haveMax;
225 bool m_inChoice;
228 void ConfigXml::Private::parse(ConfigXml *configXml, QIODevice *xml)
230 QXmlInputSource source(xml);
231 QXmlSimpleReader reader;
232 ConfigXmlHandler handler(configXml, this);
233 reader.setContentHandler(&handler);
234 reader.parse(&source, false);
237 ConfigXmlHandler::ConfigXmlHandler(ConfigXml* config, ConfigXml::Private* d)
238 : QXmlDefaultHandler(),
239 m_config(config),
240 d(d)
242 resetState();
245 bool ConfigXmlHandler::startElement(const QString &namespaceURI, const QString &localName,
246 const QString &qName, const QXmlAttributes &attrs)
248 Q_UNUSED(namespaceURI)
249 Q_UNUSED(qName)
251 // kDebug() << "ConfigXmlHandler::startElement(" << localName << qName;
252 int numAttrs = attrs.count();
253 QString tag = localName.toLower();
254 if (tag == "group") {
255 for (int i = 0; i < numAttrs; ++i) {
256 QString name = attrs.localName(i).toLower();
257 if (name == "name") {
258 kDebug() << "set group to " << attrs.value(i);
259 m_config->setCurrentGroup(attrs.value(i));
262 } else if (tag == "entry") {
263 for (int i = 0; i < numAttrs; ++i) {
264 QString name = attrs.localName(i).toLower();
265 if (name == "name") {
266 m_name = attrs.value(i);
267 } else if (name == "type") {
268 m_type = attrs.value(i).toLower();
269 } else if (name == "key") {
270 m_key = attrs.value(i);
273 } else if (tag == "choice") {
274 m_choice.name.clear();
275 m_choice.label.clear();
276 m_choice.whatsThis.clear();
277 for (int i = 0; i < numAttrs; ++i) {
278 QString name = attrs.localName(i).toLower();
279 if (name == "name") {
280 m_choice.name = attrs.value(i);
283 m_inChoice = true;
286 return true;
289 bool ConfigXmlHandler::characters(const QString &ch)
291 m_cdata.append(ch);
292 return true;
295 bool ConfigXmlHandler::endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
297 Q_UNUSED(namespaceURI)
298 Q_UNUSED(qName)
300 // kDebug() << "ConfigXmlHandler::endElement(" << localName << qName;
301 QString tag = localName.toLower();
302 if (tag == "entry") {
303 addItem();
304 resetState();
305 } else if (tag == "label") {
306 if (m_inChoice) {
307 m_choice.label = m_cdata;
308 } else {
309 m_label = m_cdata;
311 } else if (tag == "whatsthis") {
312 if (m_inChoice) {
313 m_choice.whatsThis = m_cdata;
314 } else {
315 m_whatsThis = m_cdata;
317 } else if (tag == "default") {
318 m_default = m_cdata;
319 } else if (tag == "min") {
320 m_min = m_cdata.toInt(&m_haveMin);
321 } else if (tag == "max") {
322 m_max = m_cdata.toInt(&m_haveMax);
323 } else if (tag == "choice") {
324 m_enumChoices.append(m_choice);
325 m_inChoice = false;
328 m_cdata.clear();
329 return true;
332 void ConfigXmlHandler::addItem()
334 if (m_name.isEmpty()) {
335 return;
338 KConfigSkeletonItem* item = 0;
340 if (m_type == "bool") {
341 bool defaultValue = m_default.toLower() == "true";
342 item = m_config->addItemBool(m_name, *d->newBool(), defaultValue, m_key);
343 } else if (m_type == "color") {
344 item = m_config->addItemColor(m_name, *d->newColor(), QColor(m_default), m_key);
345 } else if (m_type == "datetime") {
346 item = m_config->addItemDateTime(m_name, *d->newDateTime(),
347 QDateTime::fromString(m_default), m_key);
348 } else if (m_type == "enum") {
349 KConfigSkeleton::ItemEnum* enumItem =
350 new KConfigSkeleton::ItemEnum(m_config->currentGroup(),
351 m_key, *d->newInt(),
352 m_enumChoices,
353 m_default.toUInt());
354 enumItem->setName(m_name);
355 m_config->addItem(enumItem, m_name);
356 item = enumItem;
357 } else if (m_type == "font") {
358 item = m_config->addItemFont(m_name, *d->newFont(), QFont(m_default), m_key);
359 } else if (m_type == "int") {
360 KConfigSkeleton::ItemInt* intItem = m_config->addItemInt(m_name,
361 *d->newInt(),
362 m_default.toInt(),
363 m_key);
364 if (m_haveMin) {
365 intItem->setMinValue(m_min);
367 if (m_haveMax) {
368 intItem->setMaxValue(m_max);
370 item = intItem;
371 } else if (m_type == "password") {
372 item = m_config->addItemPassword(m_name, *d->newString(), m_default, m_key);
373 } else if (m_type == "path") {
374 item = m_config->addItemPath(m_name, *d->newString(), m_default, m_key);
375 } else if (m_type == "string") {
376 item = m_config->addItemString(m_name, *d->newString(), m_default, m_key);
377 } else if (m_type == "stringlist") {
378 //FIXME: the split() is naive and will break on lists with ,'s in them
379 item = m_config->addItemStringList(m_name, *d->newStringList(), m_default.split(","), m_key);
380 } else if (m_type == "uint") {
381 KConfigSkeleton::ItemUInt* uintItem = m_config->addItemUInt(m_name,
382 *d->newUint(),
383 m_default.toUInt(),
384 m_key);
385 if (m_haveMin) {
386 uintItem->setMinValue(m_min);
388 if (m_haveMax) {
389 uintItem->setMaxValue(m_max);
391 item = uintItem;
392 } else if (m_type == "url") {
393 KConfigSkeleton::ItemUrl* urlItem =
394 new KConfigSkeleton::ItemUrl(m_config->currentGroup(),
395 m_key, *d->newUrl(),
396 m_default);
397 urlItem->setName(m_name);
398 m_config->addItem(urlItem, m_name);
399 item = urlItem;
400 } else if (m_type == "double") {
401 KConfigSkeleton::ItemDouble* doubleItem = m_config->addItemDouble(m_name,
402 *d->newDouble(), m_default.toDouble(), m_key);
403 if (m_haveMin) {
404 doubleItem->setMinValue(m_min);
406 if (m_haveMax) {
407 doubleItem->setMaxValue(m_max);
409 item = doubleItem;
410 } else if (m_type == "intlist") {
411 QStringList tmpList = m_default.split(",");
412 QList<qint32> defaultList;
413 foreach (QString tmp, tmpList) {
414 defaultList.append(tmp.toInt());
416 item = m_config->addItemIntList(m_name, *d->newIntList(), defaultList, m_key);
417 } else if (m_type == "longlong") {
418 KConfigSkeleton::ItemLongLong* longlongItem = m_config->addItemLongLong(m_name,
419 *d->newLongLong(), m_default.toLongLong(), m_key);
420 if (m_haveMin) {
421 longlongItem->setMinValue(m_min);
423 if (m_haveMax) {
424 longlongItem->setMaxValue(m_max);
426 item = longlongItem;
427 /* No addItemPathList in KConfigSkeleton ?
428 } else if (m_type == "PathList") {
429 //FIXME: the split() is naive and will break on lists with ,'s in them
430 item = m_config->addItemPathList(m_name, *d->newStringList(), m_default.split(","), m_key); */
431 } else if (m_type == "point") {
432 QPoint defaultPoint;
433 QStringList tmpList = m_default.split(",");
434 while (tmpList.size() >= 2) {
435 defaultPoint.setX(tmpList[0].toInt());
436 defaultPoint.setY(tmpList[1].toInt());
438 item = m_config->addItemPoint(m_name, *d->newPoint(), defaultPoint, m_key);
439 } else if (m_type == "rect") {
440 QRect defaultRect;
441 QStringList tmpList = m_default.split(",");
442 while (tmpList.size() >= 4) {
443 defaultRect.setCoords(tmpList[0].toInt(), tmpList[1].toInt(),
444 tmpList[2].toInt(), tmpList[3].toInt());
446 item = m_config->addItemRect(m_name, *d->newRect(), defaultRect, m_key);
447 } else if (m_type == "size") {
448 QSize defaultSize;
449 QStringList tmpList = m_default.split(",");
450 while (tmpList.size() >= 2) {
451 defaultSize.setWidth(tmpList[0].toInt());
452 defaultSize.setHeight(tmpList[1].toInt());
454 item = m_config->addItemSize(m_name, *d->newSize(), defaultSize, m_key);
455 } else if (m_type == "ulonglong") {
456 KConfigSkeleton::ItemULongLong* ulonglongItem = m_config->addItemULongLong(m_name,
457 *d->newULongLong(), m_default.toULongLong(), m_key);
458 if (m_haveMin) {
459 ulonglongItem->setMinValue(m_min);
461 if (m_haveMax) {
462 ulonglongItem->setMaxValue(m_max);
464 item = ulonglongItem;
465 /* No addItemUrlList in KConfigSkeleton ?
466 } else if (m_type == "urllist") {
467 //FIXME: the split() is naive and will break on lists with ,'s in them
468 QStringList tmpList = m_default.split(",");
469 KUrl::List defaultList;
470 foreach (QString tmp, tmpList) {
471 defaultList.append(KUrl(tmp));
473 item = m_config->addItemUrlList(m_name, *d->newUrlList(), defaultList, m_key);*/
476 if (item) {
477 item->setLabel(m_label);
478 item->setWhatsThis(m_whatsThis);
482 void ConfigXmlHandler::resetState()
484 m_haveMin = false;
485 m_min = 0;
486 m_haveMax = false;
487 m_max = 0;
488 m_name.clear();
489 m_type.clear();
490 m_label.clear();
491 m_default.clear();
492 m_key.clear();
493 m_whatsThis.clear();
494 m_enumChoices.clear();
495 m_inChoice = false;
498 ConfigXml::ConfigXml(const QString &configFile, QIODevice *xml, QObject *parent)
499 : KConfigSkeleton(configFile, parent),
500 d(new Private)
502 QXmlInputSource source(xml);
503 QXmlSimpleReader reader;
504 ConfigXmlHandler handler(this, d);
505 reader.setContentHandler(&handler);
506 reader.parse(&source, false);
509 ConfigXml::ConfigXml(KSharedConfigPtr config, QIODevice *xml, QObject *parent)
510 : KConfigSkeleton(config, parent),
511 d(new Private)
513 d->parse(this, xml);
516 //FIXME: obviously this is broken and should be using the group as the root,
517 // but KConfigSkeleton does not currently support this. it will eventually though,
518 // at which point this can be addressed properly
519 ConfigXml::ConfigXml(const KConfigGroup *config, QIODevice *xml, QObject *parent)
520 : KConfigSkeleton(KSharedConfig::openConfig(config->config()->name()), parent),
521 d(new Private)
523 d->parse(this, xml);
526 ConfigXml::~ConfigXml()
528 delete d;
531 } // Plasma namespace