1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/as_pref.cpp Fri Nov 28 11:21:08 2008 +0100 1.3 @@ -0,0 +1,354 @@ 1.4 +/*************************************************************************** 1.5 + preferences.cc 1.6 + ------------------- 1.7 + A class to access persistant preferences for an application. Utilizes XML/DOM. 1.8 + Basic format is: 1.9 + <!DOCTYPE preferences> 1.10 + <preferences version="0.1" application="MyApp" > 1.11 + <group name="Default" > 1.12 + <option key="alpha" value="true" /> 1.13 + <option key="beta" value="99" /> 1.14 + <option key="gamma" value="test" /> 1.15 + </group> 1.16 + </preferences> 1.17 + ------------------- 1.18 + begin Tue Sep 12 2000 1.19 + author David Johnson, david@usermode.org 1.20 + ------------------- 1.21 + Copyright 2000, David Johnson 1.22 + Please see the header file for copyright and license information 1.23 +***************************************************************************/ 1.24 + 1.25 +// version 2 1.26 + 1.27 +// TODO: fix up to account for worst case scenarios: 1.28 +// keys without values in file, and 1.29 +// checking for a key that doesn't exist puts it into the map 1.30 +// then it gets written out if dirty, possibly corrupting the file 1.31 + 1.32 +// TODO: Fix up error reporting 1.33 + 1.34 +#include <qdom.h> 1.35 +#include <qfile.h> 1.36 +#include <qtextstream.h> 1.37 + 1.38 +#include "as_pref.h" 1.39 + 1.40 +////////////////////////////////////////////////////////////////////////////// 1.41 +// Construction // 1.42 +////////////////////////////////////////////////////////////////////////////// 1.43 + 1.44 +////////////////////////////////////////////////////////////////////////////// 1.45 +// Preferences() 1.46 +// ------------- 1.47 +// Constructor. Takes the preferences file name as an argument. 1.48 + 1.49 +Preferences::Preferences(const QString& filename, 1.50 + const QString& format, 1.51 + const QString& version) 1.52 + : dirty_(false), 1.53 + currentgroup_(), 1.54 + file_(filename), 1.55 + format_(format), 1.56 + version_(version), 1.57 + filestate_(false), 1.58 + formatstate_(false), 1.59 + groups_() 1.60 +{ 1.61 + readData(); 1.62 + dirty_ = false; 1.63 + currentgroup_ = "Default"; 1.64 +} 1.65 + 1.66 +////////////////////////////////////////////////////////////////////////////// 1.67 +// ~Preferences() 1.68 +// --------------- 1.69 +// Destructor 1.70 + 1.71 +Preferences::~Preferences() 1.72 +{ 1.73 + if (dirty_) writeData(); 1.74 +} 1.75 + 1.76 +////////////////////////////////////////////////////////////////////////////// 1.77 +// Settings 1.78 +////////////////////////////////////////////////////////////////////////////// 1.79 + 1.80 +////////////////////////////////////////////////////////////////////////////// 1.81 +// getBoolean() 1.82 +// ------------ 1.83 +// Get a boolean value 1.84 + 1.85 +bool Preferences::getBool(const QString& key, bool def) 1.86 +{ 1.87 + buffer_ = getString(key, def ? "true" : "false"); 1.88 + if (buffer_.isEmpty()) return def; 1.89 + if (buffer_.contains("true")) 1.90 + return true; 1.91 + else 1.92 + return false; 1.93 +} 1.94 + 1.95 +////////////////////////////////////////////////////////////////////////////// 1.96 +// setBoolean() 1.97 +// ------------ 1.98 +// Set a boolean value 1.99 + 1.100 +void Preferences::setBool(const QString& key, bool value) 1.101 +{ 1.102 + groups_[currentgroup_][key] = value ? "true" : "false"; 1.103 + dirty_ = true; 1.104 +} 1.105 + 1.106 +////////////////////////////////////////////////////////////////////////////// 1.107 +// getNumber() 1.108 +// ----------- 1.109 +// Get a number value 1.110 + 1.111 +// TODO: this might be a place for templates 1.112 + 1.113 +long Preferences::getNumber(const QString& key, long def) 1.114 +{ 1.115 + buffer_ = getString(key, QString::number(def)); 1.116 + if (buffer_.isEmpty()) return def; 1.117 + 1.118 + bool ok; 1.119 + long num = buffer_.toLong(&ok); 1.120 + if (ok) return num; 1.121 + else return def; 1.122 +} 1.123 + 1.124 +////////////////////////////////////////////////////////////////////////////// 1.125 +// setNumber() 1.126 +// ----------- 1.127 +// Set a number value 1.128 + 1.129 +void Preferences::setNumber(const QString& key, long value) 1.130 +{ 1.131 + buffer_.setNum(value); 1.132 + 1.133 + groups_[currentgroup_][key] = buffer_; 1.134 + dirty_ = true; 1.135 +} 1.136 + 1.137 +////////////////////////////////////////////////////////////////////////////// 1.138 +// getDouble() 1.139 +// ----------- 1.140 +// Get a double value 1.141 + 1.142 +double Preferences::getDouble(const QString& key, double def) 1.143 +{ 1.144 + buffer_ = getString(key, QString::number(def)); 1.145 + if (buffer_.isEmpty()) return def; 1.146 + 1.147 + bool ok; 1.148 + double num = buffer_.toDouble(&ok); 1.149 + if (ok) return num; 1.150 + else return def; 1.151 +} 1.152 + 1.153 +////////////////////////////////////////////////////////////////////////////// 1.154 +// setDouble() 1.155 +// ----------- 1.156 +// Set a double value 1.157 + 1.158 +void Preferences::setDouble(const QString& key, double value) 1.159 +{ 1.160 + buffer_.setNum(value); 1.161 + 1.162 + groups_[currentgroup_][key] = buffer_; 1.163 + dirty_ = true; 1.164 +} 1.165 + 1.166 + 1.167 +////////////////////////////////////////////////////////////////////////////// 1.168 +// getString() 1.169 +// ----------- 1.170 +// Get a string value 1.171 + 1.172 +QString Preferences::getString(const QString& key, const QString& def) 1.173 +{ 1.174 + buffer_ = ""; 1.175 + if (groups_.contains(currentgroup_)) { 1.176 + if (groups_[currentgroup_].contains(key)) { 1.177 + buffer_ = groups_[currentgroup_][key]; 1.178 + } 1.179 + } 1.180 + if (buffer_.isEmpty()) return def; 1.181 + return buffer_; 1.182 +} 1.183 + 1.184 +////////////////////////////////////////////////////////////////////////////// 1.185 +// setString() 1.186 +// ----------- 1.187 +// Set a string value 1.188 + 1.189 +void Preferences::setString(const QString& key, const QString& value) 1.190 +{ 1.191 + groups_[currentgroup_][key] = value; 1.192 + dirty_ = true; 1.193 +} 1.194 + 1.195 +////////////////////////////////////////////////////////////////////////////// 1.196 +// removeValue() 1.197 +// ------------- 1.198 +// Remove a value from the preferences 1.199 + 1.200 +void Preferences::removeKey(const QString& key) 1.201 +{ 1.202 + groups_[currentgroup_].remove(key); 1.203 +} 1.204 + 1.205 +////////////////////////////////////////////////////////////////////////////// 1.206 +// removeGroup() 1.207 +// ------------- 1.208 +// Remove a group from the preferences, and all its options 1.209 + 1.210 +void Preferences::removeGroup() 1.211 +{ 1.212 + groups_.remove(currentgroup_); 1.213 +} 1.214 + 1.215 +////////////////////////////////////////////////////////////////////////////// 1.216 +// flush() 1.217 +// ------- 1.218 +// Flush the preferences to file 1.219 + 1.220 +void Preferences::flush() 1.221 +{ 1.222 + if (dirty_) { 1.223 + writeData(); 1.224 + dirty_ = false; 1.225 + } 1.226 +} 1.227 + 1.228 +////////////////////////////////////////////////////////////////////////////// 1.229 +// Serialization // 1.230 +////////////////////////////////////////////////////////////////////////////// 1.231 + 1.232 +////////////////////////////////////////////////////////////////////////////// 1.233 +// readData() 1.234 +// ---------- 1.235 +// Read data from the file 1.236 + 1.237 +void Preferences::readData() 1.238 +{ 1.239 + // open file 1.240 + QFile* datafile = new QFile(file_); 1.241 + if (!datafile->open(IO_ReadOnly)) { 1.242 + // error opening file 1.243 + qWarning("Error: cannot open preferences file " + file_); 1.244 + datafile->close(); 1.245 + delete (datafile); 1.246 + filestate_ = false; 1.247 + return; 1.248 + } 1.249 + filestate_ = true; 1.250 + 1.251 + // open dom document 1.252 + QDomDocument doc("preferences"); 1.253 + if (!doc.setContent(datafile)) { 1.254 + qWarning("Error: " + file_ + " is not a proper preferences file"); 1.255 + datafile->close(); 1.256 + delete (datafile); 1.257 + formatstate_ = false; 1.258 + return; 1.259 + } 1.260 + datafile->close(); 1.261 + delete (datafile); 1.262 + 1.263 + // check the doc type and stuff 1.264 + if (doc.doctype().name() != "preferences") { 1.265 + // wrong file type 1.266 + qWarning("Error: " +file_ + " is not a valid preferences file"); 1.267 + formatstate_ = false; 1.268 + return; 1.269 + } 1.270 + QDomElement root = doc.documentElement(); 1.271 + if (root.attribute("application") != format_) { 1.272 + // right file type, wrong application 1.273 + qWarning("Error: " + file_ + " is not a preferences file for " + format_); 1.274 + formatstate_ = false; 1.275 + return; 1.276 + } 1.277 + // We don't care about application version... 1.278 + 1.279 + // get list of groups 1.280 + QDomNodeList nodes = root.elementsByTagName("group"); 1.281 + 1.282 + // iterate through the groups 1.283 + QDomNodeList options; 1.284 + for (unsigned n=0; n<nodes.count(); ++n) { 1.285 + if (nodes.item(n).isElement()) { 1.286 + processGroup(nodes.item(n).toElement()); 1.287 + } 1.288 + } 1.289 + formatstate_ = true; 1.290 +} 1.291 + 1.292 +void Preferences::processGroup(QDomElement group) 1.293 +{ 1.294 + QDomElement elem; 1.295 + QDomNodeList options; 1.296 + currentgroup_ = group.attribute("name", "Default"); 1.297 + options = group.elementsByTagName("option"); 1.298 + for (unsigned n=0; n<options.count(); ++n) { 1.299 + if (options.item(n).isElement()) { 1.300 + elem = options.item(n).toElement(); 1.301 + setString(elem.attribute("key"), elem.attribute("value")); 1.302 + } 1.303 + } 1.304 +} 1.305 + 1.306 +////////////////////////////////////////////////////////////////////////////// 1.307 +// writeData() 1.308 +// ----------- 1.309 +// Write data out to the file 1.310 + 1.311 +void Preferences::writeData() 1.312 +{ 1.313 + QDomDocument doc("preferences"); 1.314 + 1.315 + // create the root element 1.316 + QDomElement root = doc.createElement(doc.doctype().name()); 1.317 + root.setAttribute("version", version_); 1.318 + root.setAttribute("application", format_); 1.319 + 1.320 + // now do our options group by group 1.321 + QMap<QString, PrefMap>::Iterator git; 1.322 + PrefMap::Iterator pit; 1.323 + QDomElement group, option; 1.324 + for (git = groups_.begin(); git != groups_.end(); ++git) { 1.325 + // create a group element 1.326 + group = doc.createElement("group"); 1.327 + group.setAttribute("name", git.key()); 1.328 + // add in options 1.329 + for (pit = (*git).begin(); pit != (*git).end(); ++pit) { 1.330 + option = doc.createElement("option"); 1.331 + option.setAttribute("key", pit.key()); 1.332 + option.setAttribute("value", pit.data()); 1.333 + group.appendChild(option); 1.334 + } 1.335 + root.appendChild(group); 1.336 + } 1.337 + doc.appendChild(root); 1.338 + 1.339 + // open file 1.340 + QFile* datafile = new QFile(file_); 1.341 + if (!datafile->open(IO_WriteOnly)) { 1.342 + // error opening file 1.343 + qWarning("Error: Cannot open preferences file " + file_); 1.344 + datafile->close(); 1.345 + delete (datafile); 1.346 + filestate_ = false; 1.347 + return; 1.348 + } 1.349 + filestate_ = true; 1.350 + 1.351 + // write it out 1.352 + QTextStream textstream(datafile); 1.353 + doc.save(textstream, 0); 1.354 + datafile->close(); 1.355 + delete (datafile); 1.356 + formatstate_ = true; 1.357 +}