Plasma
configloader.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2007 Aaron Seigo <aseigo@kde.org> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU Library General Public License as 00006 * published by the Free Software Foundation; either version 2, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details 00013 * 00014 * You should have received a copy of the GNU Library General Public 00015 * License along with this program; if not, write to the 00016 * Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "configloader.h" 00021 #include "private/configloader_p.h" 00022 00023 #include <QColor> 00024 #include <QFont> 00025 #include <QHash> 00026 #include <QXmlContentHandler> 00027 #include <QXmlInputSource> 00028 #include <QXmlSimpleReader> 00029 00030 #include <kdebug.h> 00031 #include <kurl.h> 00032 00033 namespace Plasma 00034 { 00035 class ConfigLoaderHandler : public QXmlDefaultHandler 00036 { 00037 public: 00038 ConfigLoaderHandler(ConfigLoader *config, ConfigLoaderPrivate *d); 00039 bool startElement(const QString &namespaceURI, const QString &localName, 00040 const QString &qName, const QXmlAttributes &atts); 00041 bool endElement(const QString &namespaceURI, const QString &localName, 00042 const QString &qName); 00043 bool characters(const QString &ch); 00044 00045 private: 00046 void addItem(); 00047 void resetState(); 00048 00049 ConfigLoader *m_config; 00050 ConfigLoaderPrivate *d; 00051 int m_min; 00052 int m_max; 00053 QString m_name; 00054 QString m_key; 00055 QString m_type; 00056 QString m_label; 00057 QString m_default; 00058 QString m_cdata; 00059 QString m_whatsThis; 00060 KConfigSkeleton::ItemEnum::Choice m_choice; 00061 QList<KConfigSkeleton::ItemEnum::Choice> m_enumChoices; 00062 bool m_haveMin; 00063 bool m_haveMax; 00064 bool m_inChoice; 00065 }; 00066 00067 void ConfigLoaderPrivate::parse(ConfigLoader *loader, QIODevice *xml) 00068 { 00069 QXmlInputSource source(xml); 00070 QXmlSimpleReader reader; 00071 ConfigLoaderHandler handler(loader, this); 00072 reader.setContentHandler(&handler); 00073 reader.parse(&source, false); 00074 } 00075 00076 ConfigLoaderHandler::ConfigLoaderHandler(ConfigLoader *config, ConfigLoaderPrivate *d) 00077 : QXmlDefaultHandler(), 00078 m_config(config), 00079 d(d) 00080 { 00081 resetState(); 00082 } 00083 00084 bool ConfigLoaderHandler::startElement(const QString &namespaceURI, const QString &localName, 00085 const QString &qName, const QXmlAttributes &attrs) 00086 { 00087 Q_UNUSED(namespaceURI) 00088 Q_UNUSED(qName) 00089 00090 // kDebug() << "ConfigLoaderHandler::startElement(" << localName << qName; 00091 int numAttrs = attrs.count(); 00092 QString tag = localName.toLower(); 00093 if (tag == "group") { 00094 QString group; 00095 for (int i = 0; i < numAttrs; ++i) { 00096 QString name = attrs.localName(i).toLower(); 00097 if (name == "name") { 00098 //kDebug() << "set group to" << attrs.value(i); 00099 group = attrs.value(i); 00100 } 00101 } 00102 if (group.isEmpty()) { 00103 group = d->baseGroup; 00104 } else { 00105 d->groups.append(group); 00106 if (!d->baseGroup.isEmpty()) { 00107 group = d->baseGroup + '\x1d' + group; 00108 } 00109 } 00110 m_config->setCurrentGroup(group); 00111 } else if (tag == "entry") { 00112 for (int i = 0; i < numAttrs; ++i) { 00113 QString name = attrs.localName(i).toLower(); 00114 if (name == "name") { 00115 m_name = attrs.value(i).trimmed(); 00116 } else if (name == "type") { 00117 m_type = attrs.value(i).toLower(); 00118 } else if (name == "key") { 00119 m_key = attrs.value(i).trimmed(); 00120 } 00121 } 00122 } else if (tag == "choice") { 00123 m_choice.name.clear(); 00124 m_choice.label.clear(); 00125 m_choice.whatsThis.clear(); 00126 for (int i = 0; i < numAttrs; ++i) { 00127 QString name = attrs.localName(i).toLower(); 00128 if (name == "name") { 00129 m_choice.name = attrs.value(i); 00130 } 00131 } 00132 m_inChoice = true; 00133 } 00134 00135 return true; 00136 } 00137 00138 bool ConfigLoaderHandler::characters(const QString &ch) 00139 { 00140 m_cdata.append(ch); 00141 return true; 00142 } 00143 00144 bool ConfigLoaderHandler::endElement(const QString &namespaceURI, 00145 const QString &localName, const QString &qName) 00146 { 00147 Q_UNUSED(namespaceURI) 00148 Q_UNUSED(qName) 00149 00150 // kDebug() << "ConfigLoaderHandler::endElement(" << localName << qName; 00151 const QString tag = localName.toLower(); 00152 if (tag == "entry") { 00153 addItem(); 00154 resetState(); 00155 } else if (tag == "label") { 00156 if (m_inChoice) { 00157 m_choice.label = m_cdata.trimmed(); 00158 } else { 00159 m_label = m_cdata.trimmed(); 00160 } 00161 } else if (tag == "whatsthis") { 00162 if (m_inChoice) { 00163 m_choice.whatsThis = m_cdata.trimmed(); 00164 } else { 00165 m_whatsThis = m_cdata.trimmed(); 00166 } 00167 } else if (tag == "default") { 00168 m_default = m_cdata.trimmed(); 00169 } else if (tag == "min") { 00170 m_min = m_cdata.toInt(&m_haveMin); 00171 } else if (tag == "max") { 00172 m_max = m_cdata.toInt(&m_haveMax); 00173 } else if (tag == "choice") { 00174 m_enumChoices.append(m_choice); 00175 m_inChoice = false; 00176 } 00177 00178 m_cdata.clear(); 00179 return true; 00180 } 00181 00182 void ConfigLoaderHandler::addItem() 00183 { 00184 if (m_name.isEmpty()) { 00185 if (m_key.isEmpty()) { 00186 return; 00187 } 00188 00189 m_name = m_key; 00190 } 00191 00192 m_name.remove(' '); 00193 00194 KConfigSkeletonItem *item = 0; 00195 00196 if (m_type == "bool") { 00197 bool defaultValue = m_default.toLower() == "true"; 00198 item = m_config->addItemBool(m_name, *d->newBool(), defaultValue, m_key); 00199 } else if (m_type == "color") { 00200 item = m_config->addItemColor(m_name, *d->newColor(), QColor(m_default), m_key); 00201 } else if (m_type == "datetime") { 00202 item = m_config->addItemDateTime(m_name, *d->newDateTime(), 00203 QDateTime::fromString(m_default), m_key); 00204 } else if (m_type == "enum") { 00205 m_key = (m_key.isEmpty()) ? m_name : m_key; 00206 KConfigSkeleton::ItemEnum *enumItem = 00207 new KConfigSkeleton::ItemEnum(m_config->currentGroup(), 00208 m_key, *d->newInt(), 00209 m_enumChoices, 00210 m_default.toUInt()); 00211 m_config->addItem(enumItem, m_name); 00212 item = enumItem; 00213 } else if (m_type == "font") { 00214 item = m_config->addItemFont(m_name, *d->newFont(), QFont(m_default), m_key); 00215 } else if (m_type == "int") { 00216 KConfigSkeleton::ItemInt *intItem = m_config->addItemInt(m_name, *d->newInt(), 00217 m_default.toInt(), m_key); 00218 00219 if (m_haveMin) { 00220 intItem->setMinValue(m_min); 00221 } 00222 00223 if (m_haveMax) { 00224 intItem->setMaxValue(m_max); 00225 } 00226 00227 item = intItem; 00228 } else if (m_type == "password") { 00229 item = m_config->addItemPassword(m_name, *d->newString(), m_default, m_key); 00230 } else if (m_type == "path") { 00231 item = m_config->addItemPath(m_name, *d->newString(), m_default, m_key); 00232 } else if (m_type == "string") { 00233 item = m_config->addItemString(m_name, *d->newString(), m_default, m_key); 00234 } else if (m_type == "stringlist") { 00235 //FIXME: the split() is naive and will break on lists with ,'s in them 00236 item = m_config->addItemStringList(m_name, *d->newStringList(), 00237 m_default.split(','), m_key); 00238 } else if (m_type == "uint") { 00239 KConfigSkeleton::ItemUInt *uintItem = 00240 m_config->addItemUInt(m_name, *d->newUint(), m_default.toUInt(), m_key); 00241 if (m_haveMin) { 00242 uintItem->setMinValue(m_min); 00243 } 00244 if (m_haveMax) { 00245 uintItem->setMaxValue(m_max); 00246 } 00247 item = uintItem; 00248 } else if (m_type == "url") { 00249 m_key = (m_key.isEmpty()) ? m_name : m_key; 00250 KConfigSkeleton::ItemUrl *urlItem = 00251 new KConfigSkeleton::ItemUrl(m_config->currentGroup(), 00252 m_key, *d->newUrl(), 00253 m_default); 00254 m_config->addItem(urlItem, m_name); 00255 item = urlItem; 00256 } else if (m_type == "double") { 00257 KConfigSkeleton::ItemDouble *doubleItem = m_config->addItemDouble(m_name, 00258 *d->newDouble(), m_default.toDouble(), m_key); 00259 if (m_haveMin) { 00260 doubleItem->setMinValue(m_min); 00261 } 00262 if (m_haveMax) { 00263 doubleItem->setMaxValue(m_max); 00264 } 00265 item = doubleItem; 00266 } else if (m_type == "intlist") { 00267 QStringList tmpList = m_default.split(','); 00268 QList<int> defaultList; 00269 foreach (const QString &tmp, tmpList) { 00270 defaultList.append(tmp.toInt()); 00271 } 00272 item = m_config->addItemIntList(m_name, *d->newIntList(), defaultList, m_key); 00273 } else if (m_type == "longlong") { 00274 KConfigSkeleton::ItemLongLong *longlongItem = m_config->addItemLongLong(m_name, 00275 *d->newLongLong(), m_default.toLongLong(), m_key); 00276 if (m_haveMin) { 00277 longlongItem->setMinValue(m_min); 00278 } 00279 if (m_haveMax) { 00280 longlongItem->setMaxValue(m_max); 00281 } 00282 item = longlongItem; 00283 /* No addItemPathList in KConfigSkeleton ? 00284 } else if (m_type == "PathList") { 00285 //FIXME: the split() is naive and will break on lists with ,'s in them 00286 item = m_config->addItemPathList(m_name, *d->newStringList(), m_default.split(","), m_key); 00287 */ 00288 } else if (m_type == "point") { 00289 QPoint defaultPoint; 00290 QStringList tmpList = m_default.split(','); 00291 if (tmpList.size() >= 2) { 00292 defaultPoint.setX(tmpList[0].toInt()); 00293 defaultPoint.setY(tmpList[1].toInt()); 00294 } 00295 item = m_config->addItemPoint(m_name, *d->newPoint(), defaultPoint, m_key); 00296 } else if (m_type == "rect") { 00297 QRect defaultRect; 00298 QStringList tmpList = m_default.split(','); 00299 if (tmpList.size() >= 4) { 00300 defaultRect.setCoords(tmpList[0].toInt(), tmpList[1].toInt(), 00301 tmpList[2].toInt(), tmpList[3].toInt()); 00302 } 00303 item = m_config->addItemRect(m_name, *d->newRect(), defaultRect, m_key); 00304 } else if (m_type == "size") { 00305 QSize defaultSize; 00306 QStringList tmpList = m_default.split(','); 00307 if (tmpList.size() >= 2) { 00308 defaultSize.setWidth(tmpList[0].toInt()); 00309 defaultSize.setHeight(tmpList[1].toInt()); 00310 } 00311 item = m_config->addItemSize(m_name, *d->newSize(), defaultSize, m_key); 00312 } else if (m_type == "ulonglong") { 00313 KConfigSkeleton::ItemULongLong *ulonglongItem = 00314 m_config->addItemULongLong(m_name, *d->newULongLong(), m_default.toULongLong(), m_key); 00315 if (m_haveMin) { 00316 ulonglongItem->setMinValue(m_min); 00317 } 00318 if (m_haveMax) { 00319 ulonglongItem->setMaxValue(m_max); 00320 } 00321 item = ulonglongItem; 00322 /* No addItemUrlList in KConfigSkeleton ? 00323 } else if (m_type == "urllist") { 00324 //FIXME: the split() is naive and will break on lists with ,'s in them 00325 QStringList tmpList = m_default.split(","); 00326 KUrl::List defaultList; 00327 foreach (const QString& tmp, tmpList) { 00328 defaultList.append(KUrl(tmp)); 00329 } 00330 item = m_config->addItemUrlList(m_name, *d->newUrlList(), defaultList, m_key);*/ 00331 } 00332 00333 if (item) { 00334 item->setLabel(m_label); 00335 item->setWhatsThis(m_whatsThis); 00336 d->keysToNames.insert(item->group() + item->key(), item->name()); 00337 } 00338 } 00339 00340 void ConfigLoaderHandler::resetState() 00341 { 00342 m_haveMin = false; 00343 m_min = 0; 00344 m_haveMax = false; 00345 m_max = 0; 00346 m_name.clear(); 00347 m_type.clear(); 00348 m_label.clear(); 00349 m_default.clear(); 00350 m_key.clear(); 00351 m_whatsThis.clear(); 00352 m_enumChoices.clear(); 00353 m_inChoice = false; 00354 } 00355 00356 ConfigLoader::ConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent) 00357 : KConfigSkeleton(configFile, parent), 00358 d(new ConfigLoaderPrivate) 00359 { 00360 d->parse(this, xml); 00361 } 00362 00363 ConfigLoader::ConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent) 00364 : KConfigSkeleton(config, parent), 00365 d(new ConfigLoaderPrivate) 00366 { 00367 d->parse(this, xml); 00368 } 00369 00370 //FIXME: obviously this is broken and should be using the group as the root, 00371 // but KConfigSkeleton does not currently support this. it will eventually though, 00372 // at which point this can be addressed properly 00373 ConfigLoader::ConfigLoader(const KConfigGroup *config, QIODevice *xml, QObject *parent) 00374 : KConfigSkeleton(KSharedConfig::openConfig(config->config()->name()), parent), 00375 d(new ConfigLoaderPrivate) 00376 { 00377 KConfigGroup group = config->parent(); 00378 d->baseGroup = config->name(); 00379 while (group.isValid() && group.name() != "<default>") { 00380 d->baseGroup = group.name() + '\x1d' + d->baseGroup; 00381 group = group.parent(); 00382 } 00383 d->parse(this, xml); 00384 } 00385 00386 ConfigLoader::~ConfigLoader() 00387 { 00388 delete d; 00389 } 00390 00391 KConfigSkeletonItem *ConfigLoader::findItem(const QString &group, const QString &key) 00392 { 00393 return KConfigSkeleton::findItem(d->keysToNames[group + key]); 00394 } 00395 00396 KConfigSkeletonItem *ConfigLoader::findItemByName(const QString &name) 00397 { 00398 return KConfigSkeleton::findItem(name); 00399 } 00400 00401 QVariant ConfigLoader::property(const QString &name) 00402 { 00403 KConfigSkeletonItem *item = KConfigSkeleton::findItem(name); 00404 00405 if (item) { 00406 return item->property(); 00407 } 00408 00409 return QVariant(); 00410 } 00411 00412 bool ConfigLoader::hasGroup(const QString &group) const 00413 { 00414 return d->groups.contains(group); 00415 } 00416 00417 QStringList ConfigLoader::groupList() const 00418 { 00419 return d->groups; 00420 } 00421 00422 void ConfigLoader::usrWriteConfig() 00423 { 00424 if (d->saveDefaults) { 00425 KConfigSkeletonItem::List itemList = items(); 00426 for(int i = 0; i < itemList.size(); i++) { 00427 KConfigGroup cg(config(), itemList.at(i)->group()); 00428 cg.writeEntry(itemList.at(i)->key(), ""); 00429 } 00430 } 00431 } 00432 00433 } // Plasma namespace
KDE 4.6 API Reference