michael@1: /*************************************************************************** michael@1: preferences.cc michael@1: ------------------- michael@1: A class to access persistant preferences for an application. Utilizes XML/DOM. michael@1: Basic format is: michael@1: michael@1: michael@1: michael@1: michael@1: michael@1: ------------------- michael@1: begin Tue Sep 12 2000 michael@1: author David Johnson, david@usermode.org michael@1: ------------------- michael@1: Copyright 2000, David Johnson michael@1: Please see the header file for copyright and license information michael@1: ***************************************************************************/ michael@1: michael@1: // version 2 michael@1: michael@1: // TODO: fix up to account for worst case scenarios: michael@1: // keys without values in file, and michael@1: // checking for a key that doesn't exist puts it into the map michael@1: // then it gets written out if dirty, possibly corrupting the file michael@1: michael@1: // TODO: Fix up error reporting michael@1: michael@3: #include michael@1: #include michael@1: #include michael@1: michael@1: #include "as_pref.h" michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // Construction // michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // Preferences() michael@1: // ------------- michael@1: // Constructor. Takes the preferences file name as an argument. michael@1: michael@1: Preferences::Preferences(const QString& filename, michael@1: const QString& format, michael@1: const QString& version) michael@1: : dirty_(false), michael@1: currentgroup_(), michael@1: file_(filename), michael@1: format_(format), michael@1: version_(version), michael@1: filestate_(false), michael@1: formatstate_(false), michael@1: groups_() michael@1: { michael@1: readData(); michael@1: dirty_ = false; michael@1: currentgroup_ = "Default"; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // ~Preferences() michael@1: // --------------- michael@1: // Destructor michael@1: michael@1: Preferences::~Preferences() michael@1: { michael@1: if (dirty_) writeData(); michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // Settings michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // getBoolean() michael@1: // ------------ michael@1: // Get a boolean value michael@1: michael@1: bool Preferences::getBool(const QString& key, bool def) michael@1: { michael@1: buffer_ = getString(key, def ? "true" : "false"); michael@1: if (buffer_.isEmpty()) return def; michael@1: if (buffer_.contains("true")) michael@1: return true; michael@1: else michael@1: return false; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // setBoolean() michael@1: // ------------ michael@1: // Set a boolean value michael@1: michael@1: void Preferences::setBool(const QString& key, bool value) michael@1: { michael@1: groups_[currentgroup_][key] = value ? "true" : "false"; michael@1: dirty_ = true; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // getNumber() michael@1: // ----------- michael@1: // Get a number value michael@1: michael@1: // TODO: this might be a place for templates michael@1: michael@1: long Preferences::getNumber(const QString& key, long def) michael@1: { michael@1: buffer_ = getString(key, QString::number(def)); michael@1: if (buffer_.isEmpty()) return def; michael@1: michael@1: bool ok; michael@1: long num = buffer_.toLong(&ok); michael@1: if (ok) return num; michael@1: else return def; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // setNumber() michael@1: // ----------- michael@1: // Set a number value michael@1: michael@1: void Preferences::setNumber(const QString& key, long value) michael@1: { michael@1: buffer_.setNum(value); michael@1: michael@1: groups_[currentgroup_][key] = buffer_; michael@1: dirty_ = true; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // getDouble() michael@1: // ----------- michael@1: // Get a double value michael@1: michael@1: double Preferences::getDouble(const QString& key, double def) michael@1: { michael@1: buffer_ = getString(key, QString::number(def)); michael@1: if (buffer_.isEmpty()) return def; michael@1: michael@1: bool ok; michael@1: double num = buffer_.toDouble(&ok); michael@1: if (ok) return num; michael@1: else return def; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // setDouble() michael@1: // ----------- michael@1: // Set a double value michael@1: michael@1: void Preferences::setDouble(const QString& key, double value) michael@1: { michael@1: buffer_.setNum(value); michael@1: michael@1: groups_[currentgroup_][key] = buffer_; michael@1: dirty_ = true; michael@1: } michael@1: michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // getString() michael@1: // ----------- michael@1: // Get a string value michael@1: michael@1: QString Preferences::getString(const QString& key, const QString& def) michael@1: { michael@1: buffer_ = ""; michael@1: if (groups_.contains(currentgroup_)) { michael@1: if (groups_[currentgroup_].contains(key)) { michael@1: buffer_ = groups_[currentgroup_][key]; michael@1: } michael@1: } michael@1: if (buffer_.isEmpty()) return def; michael@1: return buffer_; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // setString() michael@1: // ----------- michael@1: // Set a string value michael@1: michael@1: void Preferences::setString(const QString& key, const QString& value) michael@1: { michael@1: groups_[currentgroup_][key] = value; michael@1: dirty_ = true; michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // removeValue() michael@1: // ------------- michael@1: // Remove a value from the preferences michael@1: michael@1: void Preferences::removeKey(const QString& key) michael@1: { michael@1: groups_[currentgroup_].remove(key); michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // removeGroup() michael@1: // ------------- michael@1: // Remove a group from the preferences, and all its options michael@1: michael@1: void Preferences::removeGroup() michael@1: { michael@1: groups_.remove(currentgroup_); michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // flush() michael@1: // ------- michael@1: // Flush the preferences to file michael@1: michael@1: void Preferences::flush() michael@1: { michael@1: if (dirty_) { michael@1: writeData(); michael@1: dirty_ = false; michael@1: } michael@1: } michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // Serialization // michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: michael@1: ////////////////////////////////////////////////////////////////////////////// michael@1: // readData() michael@1: // ---------- michael@1: // Read data from the file michael@1: michael@1: void Preferences::readData() michael@1: { michael@1: // open file michael@1: QFile* datafile = new QFile(file_); michael@3: if (!datafile->open(QIODevice::ReadOnly)) { michael@1: // error opening file michael@1: qWarning("Error: cannot open preferences file " + file_); michael@1: datafile->close(); michael@1: delete (datafile); michael@1: filestate_ = false; michael@1: return; michael@1: } michael@1: filestate_ = true; michael@1: michael@1: // open dom document michael@1: QDomDocument doc("preferences"); michael@1: if (!doc.setContent(datafile)) { michael@1: qWarning("Error: " + file_ + " is not a proper preferences file"); michael@1: datafile->close(); michael@1: delete (datafile); michael@1: formatstate_ = false; michael@1: return; michael@1: } michael@1: datafile->close(); michael@1: delete (datafile); michael@1: michael@1: // check the doc type and stuff michael@1: if (doc.doctype().name() != "preferences") { michael@1: // wrong file type michael@1: qWarning("Error: " +file_ + " is not a valid preferences file"); michael@1: formatstate_ = false; michael@1: return; michael@1: } michael@1: QDomElement root = doc.documentElement(); michael@1: if (root.attribute("application") != format_) { michael@1: // right file type, wrong application michael@1: qWarning("Error: " + file_ + " is not a preferences file for " + format_); michael@1: formatstate_ = false; michael@1: return; michael@1: } michael@1: // We don't care about application version... michael@1: michael@1: // get list of groups michael@1: QDomNodeList nodes = root.elementsByTagName("group"); michael@1: michael@1: // iterate through the groups michael@1: QDomNodeList options; michael@1: for (unsigned n=0; n::Iterator git; michael@1: PrefMap::Iterator pit; michael@1: QDomElement group, option; michael@1: for (git = groups_.begin(); git != groups_.end(); ++git) { michael@1: // create a group element michael@1: group = doc.createElement("group"); michael@1: group.setAttribute("name", git.key()); michael@1: // add in options michael@1: for (pit = (*git).begin(); pit != (*git).end(); ++pit) { michael@1: option = doc.createElement("option"); michael@1: option.setAttribute("key", pit.key()); michael@1: option.setAttribute("value", pit.data()); michael@1: group.appendChild(option); michael@1: } michael@1: root.appendChild(group); michael@1: } michael@1: doc.appendChild(root); michael@1: michael@1: // open file michael@1: QFile* datafile = new QFile(file_); michael@3: if (!datafile->open(QIODevice::WriteOnly)) { michael@1: // error opening file michael@1: qWarning("Error: Cannot open preferences file " + file_); michael@1: datafile->close(); michael@1: delete (datafile); michael@1: filestate_ = false; michael@1: return; michael@1: } michael@1: filestate_ = true; michael@1: michael@1: // write it out michael@1: QTextStream textstream(datafile); michael@1: doc.save(textstream, 0); michael@1: datafile->close(); michael@1: delete (datafile); michael@1: formatstate_ = true; michael@1: }