qtmobility/src/publishsubscribe/contextkitlayer.cpp
changeset 1 2b40d63a9c3d
child 11 06b8e2af4411
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qtmobility/src/publishsubscribe/contextkitlayer.cpp	Fri Apr 16 15:51:22 2010 +0300
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvaluespace.h"
+#include "qvaluespace_p.h"
+
+#include <QSet>
+#include <QDebug>
+#include <contextproperty.h>
+#include <contextregistryinfo.h>
+
+QTM_BEGIN_NAMESPACE
+
+using namespace QValueSpace;
+
+/* ContextKit layer
+
+   This layer makes ContextKit properties visible in the QValueSpace.
+
+   You can not publish values of ContextKit properties using the
+   QValueSpace.  This might be fixed later.
+
+   ContextKit properties have names with dots in them, which allows
+   these properties to be arranged in a tree.  The context commander
+   does this in its UI, for example.
+
+   However, the ContextKit itself does not pay attention to the dots
+   at all: properties just have names and there are no such things as
+   parent / child / sibling relations between properties.  For
+   example, there is a property called "Battery.ChargeLevel", but the
+   ContextKit doesn't know anything about "Battery".  Subscribing to
+   "Battery" is exactly the same as subscribing to any other
+   non-declared property.  When "Battery.ChargeLevel" changes,
+   "Battery" does _not_ receive a change notification.
+
+   The QValueSpace, on the other hand, has a explicit tree-structure:
+   the key "/foo" represents all its children, like "/foo/bar".  When
+   "/foo/bar" changes, "/foo" _does_ receive a change notification.
+
+   There are two ways to map ContextKit properties into the
+   QValueSpace: simply as a long list of siblings (a one-level tree),
+   or as the multi-level tree that is implied by their names.
+
+   We do the latter since that is more natural.  For example, the
+   ContextKit property "Battery.ChargeLevel" is mapped to
+   "/Battery/ChargeLevel", and the key "/Battery" gets a change
+   notifications for all its children.
+*/
+
+/* ContextKitHandle - contains a ContextKit property and all its
+                      direct and indirect children.
+
+   ContextKitHandles do not form a hierarchy between each other; think
+   of them as individual little trees that are created in direct
+   response to requests to the ContextKitLayer.  The properties in
+   these trees can overlap; a single ContextKit property can be
+   accessed via many ContextKitHandles.
+ */
+
+class ContextKitHandle : public QObject {
+    
+    Q_OBJECT
+
+public:
+    ContextKitHandle (ContextKitHandle *parent, const QString &root);
+    ~ContextKitHandle ();
+
+    bool value (const QString &path, QVariant *data);
+    void subscribe ();
+    void unsubscribe ();
+    QSet<QString> children ();
+
+signals:
+    void valueChanged();
+
+private:
+    QString prefix;
+    QHash<QString, ContextProperty *> props;
+
+    void insert (const QString &path, const QString &key);
+};
+
+void ContextKitHandle::insert (const QString &path, const QString &key)
+{
+    ContextProperty *prop = new ContextProperty (key);
+    connect (prop, SIGNAL (valueChanged()),
+             this, SIGNAL (valueChanged()));
+    props.insert (path, prop);
+}
+
+ContextKitHandle::ContextKitHandle (ContextKitHandle *parent, const QString &path)
+{
+    QString key = path;
+    if (key.startsWith("/"))
+        key = key.mid(1);
+    key = key.replace('/', '.');
+    if (parent)
+        key = parent->prefix + key;
+
+    prefix = (key == "")? "" : key + ".";
+    foreach (const QString &k, ContextRegistryInfo::instance()->listKeys())
+    {
+        if (k == key)
+            insert ("", k);
+        else if (k.startsWith (prefix))
+            insert (k.mid(prefix.length()).replace ('.', '/'), k);
+    }
+}
+
+ContextKitHandle::~ContextKitHandle ()
+{
+    foreach (ContextProperty *prop, props.values())
+        delete prop;
+}
+
+bool
+ContextKitHandle::value (const QString &path, QVariant *data)
+{
+    // path always starts with a "/".
+    ContextProperty *p = props.value (path.mid(1));
+    if (p)
+    {
+        *data = p->value();
+        return true;
+    }
+    else
+        return false;
+}
+
+void
+ContextKitHandle::subscribe ()
+{
+    foreach (ContextProperty *p, props.values())
+        p->subscribe ();
+}
+
+void
+ContextKitHandle::unsubscribe ()
+{
+    foreach (ContextProperty *p, props.values())
+        p->unsubscribe ();
+}
+
+QSet<QString>
+ContextKitHandle::children ()
+{
+    QSet<QString> kids;
+
+    foreach (const QString &path, props.keys())
+    {
+        int pos = path.indexOf("/");
+        if (pos >= 0)
+            kids.insert (path.left(pos));
+        else
+            kids.insert (path);
+    }
+    return kids;
+}
+
+/* ContextKitLayer - implements QAbstractValueSpaceLayer interface to
+                     hook ContextKit into QValueSpace.
+   
+   It mainly creates ContextKitHandles and dispatches to them.
+*/
+
+class ContextKitLayer : public QAbstractValueSpaceLayer
+{
+    Q_OBJECT
+
+public:
+    ContextKitLayer();
+    virtual ~ContextKitLayer();
+
+    /* ValueSpaceLayer interface - Common functions */
+    QString name();
+    bool startup(Type);
+    QUuid id();
+    unsigned int order();
+    LayerOptions layerOptions() const;
+
+    Handle item(Handle parent, const QString &);
+    void removeHandle(Handle);
+    void setProperty(Handle handle, Properties);
+
+    bool value(Handle, QVariant *);
+    bool value(Handle, const QString &, QVariant *);
+    QSet<QString> children(Handle);
+
+    /* ValueSpaceLayer interface - QValueSpaceSubscriber functions */
+    bool supportsInterestNotification() const { return true; }
+    bool notifyInterest(Handle handle, bool interested);
+
+    /* ValueSpaceLayer interface - QValueSpacePublisher functions */
+    bool setValue(QValueSpacePublisher *, Handle, const QString &, const QVariant &) { return false; }
+    bool removeValue(QValueSpacePublisher *, Handle, const QString &) { return false; }
+    bool removeSubTree(QValueSpacePublisher *, Handle) { return false; }
+    void addWatch(QValueSpacePublisher *, Handle) { return; }
+    void removeWatches(QValueSpacePublisher *, Handle) { return; }
+    void sync() { return; }
+
+    static ContextKitLayer *instance();
+
+private slots:
+    void contextHandleChanged();
+};
+
+QVALUESPACE_AUTO_INSTALL_LAYER(ContextKitLayer);
+
+ContextKitLayer::ContextKitLayer ()
+{
+}
+
+ContextKitLayer::~ContextKitLayer ()
+{
+}
+
+Q_GLOBAL_STATIC(ContextKitLayer, contextKitLayer);
+ContextKitLayer *ContextKitLayer::instance ()
+{
+    return contextKitLayer ();
+}
+
+QString ContextKitLayer::name()
+{
+    return "ContextKit Layer";
+}
+
+bool ContextKitLayer::startup(Type)
+{
+    return true;
+}
+
+QUuid ContextKitLayer::id()
+{
+    return QVALUESPACE_CONTEXTKIT_LAYER;
+}
+
+unsigned int ContextKitLayer::order()
+{
+    return 0;
+}
+
+LayerOptions ContextKitLayer::layerOptions () const
+{
+    return TransientLayer | ReadOnlyLayer;
+}
+
+QAbstractValueSpaceLayer::Handle ContextKitLayer::item (Handle parent, const QString &subPath)
+{
+    return (Handle) new ContextKitHandle ((parent == InvalidHandle)
+                                          ? NULL
+                                          : (ContextKitHandle *) parent,
+                                          subPath);
+}
+
+void ContextKitLayer::removeHandle (Handle handle)
+{
+    ContextKitHandle *h = (ContextKitHandle *)handle;
+    delete h;
+}
+
+void ContextKitLayer::setProperty (Handle handle, Properties properties)
+{
+    ContextKitHandle *h = (ContextKitHandle *)handle;
+
+    if (properties & Publish)
+        connect (h, SIGNAL(valueChanged()),
+                 this, SLOT(contextHandleChanged()));
+    else
+        disconnect (h, SIGNAL(valueChanged()),
+                    this, SLOT(contextHandleChanged()));
+}
+
+void ContextKitLayer::contextHandleChanged()
+{
+    ContextKitHandle *h = (ContextKitHandle *)sender();
+    emit handleChanged ((Handle) h);
+}
+
+bool ContextKitLayer::value (Handle handle, QVariant *data)
+{
+    ContextKitHandle *h = (ContextKitHandle *)handle;
+    return h->value ("", data);
+}
+
+bool ContextKitLayer::value (Handle handle, const QString &subPath, QVariant *data)
+{
+    ContextKitHandle *h = (ContextKitHandle *)handle;
+    return h->value (subPath, data);
+}
+
+bool ContextKitLayer::notifyInterest(Handle handle, bool interested)
+{
+    ContextKitHandle *h = (ContextKitHandle *)handle;
+
+    if (interested)
+        h->subscribe();
+    else
+        h->unsubscribe();
+    return true;
+}
+
+QSet<QString> ContextKitLayer::children (Handle handle)
+{
+    ContextKitHandle *h = (ContextKitHandle *)handle;
+    return h->children ();
+}
+
+#include "contextkitlayer.moc"
+QTM_END_NAMESPACE
+