Settings

Introduction

Settings is an extensible configuration framework for storing and accessing application settings in XML files.

Settings abstracts from the underlying representation of the configuration data, but allows, when necessary, a great amount of control over the exact serialization and deserialization mechanisms.

The C++ interface provides a natural syntax to access properties stored in a hierarchical fashion, and supports aggregates of data in the form of associative and linear containers.

Author: Paolo Capriotti <paolo DOT capriotti AT kdemail DOT net> Download: http://kboard.sourceforge.net/settings-latest.tar.gz

Quickstart

Creating a Settings object is as simple as
 Settings s(node);

where node is a QDomElement object representing the XML tree of the configuration file.

Once you have a settings object, you can set properties using the familiar indexing syntax:

 s["media-dir"] = "/media";
 s["max-instance-no"] = 10;

Reading properties is a bit less direct, because simply accessing a key does not give enough type information to infer the value type, so an explicit conversion is required with the use of the value function:

 QString media_dir = s["media-dir"].value<QString>();

Accessing keys that does not exist do not produce errors, but cause the default value to be returned for types that have a default constructor. In any case, it is possible to change the default value, and this has the added benefit to allow the type specification to be dropped:

 QString media_dir = s["media-dir"].value("/media");

There is also an alternative fancier syntax:

 QString media_dir = s["media-dir"] | "/media";

The following is a variant of the last example, useful when you want the default value to be assigned if the property happens to be undefined:

 QString media_dir = s["media-dir"] |= "/media";

If you want to test for the existence of a particular property, use the implicit boolean conversion:

 if (!s["media-dir"]) qDebug("media dir undefined!\n");

To create and access a nested property group, use the group function like this:

 Setting g = s.group["gui"];
 g["width"] = 80;
 g["height"] = 67;

Setting arrays

It is very common to have some data related to configuration which is best represented in the form of an array. In this case, a pure hierarchical representation may prove inconvenient, so Settings provides a direct support for aggregation of data in a linear container.

To access an array of properties, use the array member function like this:

 SettingArray a = s.array("languages");

You can add elements to an array using the append and insert member functions:

 Settings it = a.append();
 it["name"] = "italian";
 it["file"] = "italian.dat";

 Settings en = a.insert(0);
 en["name"] = "english";
 en["file"] = "english.dat";

Accessing and iterating can be done with the get member function.

 for (int i = 0; i < a.size(); i++) {
   std::cout << a.get(i)["name"].value<QString>() << std::endl;
 }

Alternatively, you can use the STL-like interface and any STL compatible algorithm:

 QString getName(const Settings& s) { return s["name"].value<QString>(); }
 std::transform(a.begin(), a.end(), ostream_iterator<QString>(cout, "\n"), getName);

Setting maps

A setting map is very similar to a setting array, but provides access by key instead of by index. A key is simply a subelement of each map entry. For example, the previous language configuration could be implemented as a map.

 SettingMap<QString> map = s.map("languages", "name");
 Settings it = map.insert("italian");
 it["file"] = "italian.dat";
 Settings en = map.insert("english");
 en["file]" = "english.dat";

The second argument of the map call being the name of the element that will contain the key. Map elements can be accessed using the get member function like this:

 void test_support(const QString& language) {
   if (!map.get(language)) {
     qDebug("No support for this language\n");
   }
 }

Extending Settings

Settings can be extended to support many more data types. To add a new type you only need to define a template specialization for SettingConversion with two static methods: getValue and setValue. You have full control on how object of this type will be represented in XML, and you can use attributes to keep the representation compact. See settings.h for example code.
Generated on Sun Feb 25 17:59:51 2007 for Settings by  doxygen 1.5.1