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:
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: }