Home · All Namespaces · All Classes · Grouped Classes · Modules · Functions codeless banner

Qt Extended Value Space

Overview

The Qt Extended Value Space unifies various sources of hierarchical data into a single consistent model. Conceptually the Value Space is a hierarchical tree of which each node or leaf can optionally contain a QVariant value. A serialized version of a simple example Value Space might look like this.

    /Device/Buttons = 3
    /Device/Buttons/1/Name = Context
    /Device/Buttons/1/Usable = true
    /Device/Buttons/2/Name = Select
    /Device/Buttons/2/Usable = false
    /Device/Buttons/3/Name = Back
    /Device/Buttons/3/Usable = true

Programmers access the Value Space through the QValueSpaceItem class. This class allows applications to read item values, navigate through and subscribe to change notifications for items within the space.

Nodes in the Value Space can be thought of as representing schema objects. Obviously this is a conceptual differentiation and not a physical one, as internally the Value Space is treated as one large tree. By applying structured schema to the space "explorability" is increased. For example, the /Device/Buttons schema can be defined as containing a value representing the number of mappable buttons on a device, and a sub-item for each adhering to the MappableButton schema. The MappableButton schema itself may be defined as containing two attributes Name and Usable. Change notification is modeled in this fashion also. Where the /Device/Buttons/1/Name item is to change, the /Device/Buttons/1 item would be marked as changed, and so on up the tree. This allows, for example, subscription to just /Device/Buttons to be notified when anything "button" related changes.

Internally, the Value Space consists of an arbitrary number of data source trees, or layers, which are stacked on top of each other to form the final unified view. If a "higher" layer contains an item, it shadows the value of items in the layers below it. The two most important Value Space layers are:

The Application Object layer

The Application Object layer allows applications to add and remove "transient" data from the Value Space. Applications access the Application Object layer through the QValueSpaceObject class.

The INI layer

The INI layer maps regular INI files into the Value Space. This mapping allows values stored in configuration files to be used interchangably with other values in the Value Space. The INI layer is described in the architecture section below.

Consider the Value Space item /Device/Buttons. If both the Application Object layer and the INI layer contained this item, the value in the Application Object layer would shadow that from the INI layer. However, if only the INI layer contained this item, it would be visible through the QValueSpaceItem class, even if the Application Object layer contained sub-items such as /Device/Buttons/1. That is, layer shadowing occurs by value not by path.

Architecture

Layers in the Qt Extended Value Space are provided by objects implementing the IValueSpaceLayer interface. The two internal layers, the Application Object layer and the INI layer, are implemented in this fashion. The Value Space supports adding new, 3rd party layers through calls to the QValueSpace::installLayer() method. All layers must be installed prior to the first Value Space usage. Although it is legal to have a different set of layers installed in each process (a process local layer, for example) this asymmetric model is discouraged as it might cause confusion if these two processes communicate.

The Qt Extended Value Space system is divided into two parts: a single server and zero or more clients. Internally the Value Space system draws no distinction between the two - the server is also a client, for example - but certain layers, in particular the Application Object layer, do. The Value Space server must be initialized via a call to QValueSpace::initValuespaceManager() prior to any use of the Value Space. Value Space clients will automatically initialize the first time Value Space functionionality is used.

Application Object layer

The external use of the Application Object layer is described in QValueSpaceObject. The Application Object layer stores all values in a 10MB block of shared memory which is reserved when the Value Space initializes. As the layer creates this region at startup, it is assumed that the operating system lazily commits memory. If this assumption is invalid, the Application Object layer will unnecessarily consume 10MB of memory.

Value Space clients read from the Application Object layer's shared memory region directly. A kernel lock is acquired for each read to prevent corruption. While the layer supports concurrent readers, it is possible that a faulty or malicious application could acquire and refuse to release this lock causing any layer updates to be delayed indefinately.

Only the Value Space server ever writes to the shared memory region. When clients attempt to add items to the layer, their changes are transmitted via the /tmp/qtopia-N/valuespace_applayer Unix domain socket to the server where the update is performed. Updates are batched in-process and sent when the process re-enters the Qt event loop. Transmission and synchronization of changes can be forced manually by the QValueSpaceObject::sync() call, although as this requires a round trip between the client and server, doing so frequently may significantly degrade performance.

Change notifications are transmitted to clients in the form of "something has changed" messages. Nodes within the shared memory region are versioned, which allows clients to quickly determine exactly what has changed without the need for a bulkier change notification protocol.

INI layer

The INI layer maps INI files from disk into the Value Space. The INI layer supports arbitrary mappings, fallback paths and partial change notification.

As the unified path structure of the Value Space doesn't allow the INI layer to transparently determine which INI file to access off disk, a INI layer configuration file (an INI file itself) is used to dictate how INI files are located. The INI file identified by Trolltech/IniValueSpace using the QSettings resolution rules is used for this purpose.

The general form of the INI layer configuration file is:

    [General]
    Translations=<Directory to INI translations>
    LanguageItem=<Value Space Item for current language>
    Mappings=<Number of mappings that follow>

    [Mapping<x>]
    ValueSpacePath=(Required)
    FileSystemPath=(One of FileSystemPath or FileSystemPaths required)
    FileSystemPaths=(One of FileSystemPath or FileSystemPaths required)
    FileSystemPath<x>=(Required if FileSystemPaths specified)
    FileSystemExtension=(Optional.  Required if DirectoryDepth is specified)
    DirectoryDepth=(Optional.  Only allowed if FileSystemExtension specified)

The General/Mappings key simply specifies the number of mappings that follow, which are grouped as Mapping0 - Mapping<n>. Each mapping consists of a single required field, ValueSpacePath, and a number of optional and interdependant keys.

The {ValueSpacePath} key specifies the point of mapping in the value space. This is called a "terminal" point. There may be only a single mapping for each distinct terminal point. Two /Device mappings are not allowed, but a /Device and a /Device/Buttons mapping is fine. Each terminal mapping is either a "depth mapping" or a "file mapping".

File mappings are identified by the lack of the FileSystemExtension and DirectoryDepth keys. File mappings map a single INI file to a single Value Space node. For example, in following mapping

    [Mapping0]
    ValueSpacePath=/Device/Buttons
    FileSystemPath=/opt/Qtopia/etc/defaultbuttons.conf

if the /opt/Qtopia/etc/defaultbuttons.conf file contained a Mode/Type key, the corresponding Value Space item /Device/Buttons/Mode/Type would exist.

Using the FileSystemPaths list, fallback file mappings may be created. For example

    [Mapping0]
    ValueSpacePath=/Device/Buttons
    FileSystemPaths=2
    FileSystemPath0=/tmp/qtembedded-0/defaultbuttons.conf
    FileSystemPath1=/opt/Qtopia/etc/defaultbuttons.conf

will first attempt to map /tmp/qtembedded-0/defaultbuttons.conf and then, if this doesn't exist, /opt/Qtopia/etc/defaultbuttons.conf. Fallback mappings completely obscure each other. That is, the two files /tmp/qtembedded-0/defaultbuttons.conf and /opt/Qtopia/etc/defaultbuttons.conf are not unified, but whichever exists is used and the other ignored. Fallbacks are monitored for change, so if the /tmp/qtembedded-0/defaultbuttons.conf file is created sometime later the INI layer will update accordingly.

Depth mappings allow groups of ini files to be mapped into the Value Space dynamically. Depth mappings are identified by the presence of the FileExtension key. In the case of depth mappings, the ValueSpacePath point specifies the beginning of the mapping. The next DirectoryDepth sub-paths are treated as directory specifiers, and the subsequent sub-path a file name with the FileSystemExtension extension. For example

    [Mapping0]
    ValueSpacePath=/Applications
    FileSystemPath=/opt/Qtopia/apps
    FileSystemExtension=desktop
    DirectoryDepth=1

    [Mapping1]
    ValueSpacePath=/GamesApplications
    FileSystemPath=/opt/Qtopia/apps/Games
    FileSystemExtension=desktop
    DirectoryDepth=0

creates two mappings. In the above both the Value Space items /Applications/Games/parashoot and /GamesApplications/parashoot map to the /opt/Qtopia/apps/Games/parashoot.desktop INI file. Thus if this file contained Desktop Entry/Name, the corresponding Value Space paths /Applications/Games/parashoot/Desktop Entry/Name and /GamesApplications/parashoot/Desktop Entry/Name would also exist.

As with file mappings, depth mapping support fallback paths. For example

    [Mapping0]
    ValueSpacePath=/Settings
    FileSystemPaths=2
    FileSystemPath0=/home/username/.config
    FileSystemPath1=/etc/
    FileSystemExtension=conf
    DirectoryDepth=1

will map /Settings/Trolltech/qpe first to /home/username/.config/Trolltech/qpe.conf and then to /etc/Trolltech/qpe.conf. Like file mappings, the fallback paths are monitored in case the file is later created.

Keys within an INI file can be marked as translatable by appending the "[]" token to them. For example, the following file contains one translatable key, /Example/Translatable and one non-translatable key, /Example/NonTranslatable.

    [Translation]
    File=ExampleTranslation
    Context=ExampleContext

    [Example]
    Translatable[]=Translatable Value
    NonTranslatable=Non-Translatable Value

In both cases the "[]" token is omitted from the key name when accessed through the QValueSpaceItem class.

INI translation files must be stored under a directory structure rooted at the General/Translations directory provided in the INI layer's configuration file. If this configuration entry is omitted, translation is disabled. To provide accurate translations, the INI layer also needs to know the current system language. This information is accesses through the Value Space itself, from the item path specified by General/LanguageItem. Together the translations directory, and the current system language are combined to form the root under which the INI layer looks for translations files.

INI files that include translatable keys, must also include the special Translation INI group that dictates how the INI layer locates translations for the key's value. The Translation/File key specifies the file to open under the translations root directory discussed above, and the Translation/Context key the Qt translation context to use within that file. The INI layer supports change notifications on language change.

Currently the INI layer only supports partial change notification. Change notifications will occur for keys that exist within mapped INI files, but these notifications will not be propagated up the Value Space tree. For example with the previous mapping, should the qpe.conf file change,

    // Will emit QValueSpaceItem::contentsChanged()
    QValueSpaceItem item("/Settings/Trolltech/qpe/Desktop Entry/Name");

    // Will emit QValueSpaceItem::contentsChanged()
    QValueSpaceItem item2("/Settings/Trolltech/qpe");

    // Will NOT emit QValueSpaceItem::contentsChanged()
    QValueSpaceItem item3("/Settings/Trolltech");

.

This limitation may be removed in future versions.


Copyright © 2009 Trolltech Trademarks
Qt Extended 4.4.3