src/declarative/util/qdeclarativepropertymap.cpp
changeset 30 5dc02b23752f
child 37 758a864f9613
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/declarative/util/qdeclarativepropertymap.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $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 "qdeclarativepropertymap.h"
+
+#include <private/qmetaobjectbuilder_p.h>
+#include "private/qdeclarativeopenmetaobject_p.h"
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+//QDeclarativePropertyMapMetaObject lets us listen for changes coming from QML
+//so we can emit the changed signal.
+class QDeclarativePropertyMapMetaObject : public QDeclarativeOpenMetaObject
+{
+public:
+    QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv);
+
+protected:
+    virtual void propertyWritten(int index);
+    virtual void propertyCreated(int, QMetaPropertyBuilder &);
+
+private:
+    QDeclarativePropertyMap *map;
+    QDeclarativePropertyMapPrivate *priv;
+};
+
+class QDeclarativePropertyMapPrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QDeclarativePropertyMap)
+public:
+    QDeclarativePropertyMapMetaObject *mo;
+    QStringList keys;
+    void emitChanged(const QString &key, const QVariant &value);
+};
+
+void QDeclarativePropertyMapPrivate::emitChanged(const QString &key, const QVariant &value)
+{
+    Q_Q(QDeclarativePropertyMap);
+    emit q->valueChanged(key, value);
+}
+
+QDeclarativePropertyMapMetaObject::QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv) : QDeclarativeOpenMetaObject(obj)
+{
+    map = obj;
+    priv = objPriv;
+}
+
+void QDeclarativePropertyMapMetaObject::propertyWritten(int index)
+{
+    priv->emitChanged(QString::fromUtf8(name(index)), operator[](index));
+}
+
+void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b)
+{
+    priv->keys.append(QString::fromUtf8(b.name()));
+}
+
+/*!
+    \class QDeclarativePropertyMap
+    \since 4.7
+    \brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in QML bindings.
+
+    QDeclarativePropertyMap provides a convenient way to expose domain data to the UI layer.
+    The following example shows how you might declare data in C++ and then
+    access it in QML.
+
+    Setup in C++:
+    \code
+    //create our data
+    QDeclarativePropertyMap ownerData;
+    ownerData.insert("name", QVariant(QString("John Smith")));
+    ownerData.insert("phone", QVariant(QString("555-5555")));
+
+    //expose it to the UI layer
+    QDeclarativeContext *ctxt = view->rootContext();
+    ctxt->setProperty("owner", &data);
+    \endcode
+
+    Then, in QML:
+    \code
+    Text { text: owner.name }
+    Text { text: owner.phone }
+    \endcode
+
+    The binding is dynamic - whenever a key's value is updated, anything bound to that
+    key will be updated as well.
+
+    To detect value changes made in the UI layer you can connect to the valueChanged() signal.
+    However, note that valueChanged() is \bold NOT emitted when changes are made by calling insert()
+    or clear() - it is only emitted when a value is updated from QML.
+
+    \note It is not possible to remove keys from the map; once a key has been added, you can only
+    modify or clear its associated value.
+*/
+
+/*!
+    Constructs a bindable map with parent object \a parent.
+*/
+QDeclarativePropertyMap::QDeclarativePropertyMap(QObject *parent)
+: QObject(*(new QDeclarativePropertyMapPrivate), parent)
+{
+    Q_D(QDeclarativePropertyMap);
+    d->mo = new QDeclarativePropertyMapMetaObject(this, d);
+}
+
+/*!
+    Destroys the bindable map.
+*/
+QDeclarativePropertyMap::~QDeclarativePropertyMap()
+{
+}
+
+/*!
+    Clears the value (if any) associated with \a key.
+*/
+void QDeclarativePropertyMap::clear(const QString &key)
+{
+    Q_D(QDeclarativePropertyMap);
+    d->mo->setValue(key.toUtf8(), QVariant());
+}
+
+/*!
+    Returns the value associated with \a key.
+
+    If no value has been set for this key (or if the value has been cleared),
+    an invalid QVariant is returned.
+*/
+QVariant QDeclarativePropertyMap::value(const QString &key) const
+{
+    Q_D(const QDeclarativePropertyMap);
+    return d->mo->value(key.toUtf8());
+}
+
+/*!
+    Sets the value associated with \a key to \a value.
+
+    If the key doesn't exist, it is automatically created.
+*/
+void QDeclarativePropertyMap::insert(const QString &key, const QVariant &value)
+{
+    Q_D(QDeclarativePropertyMap);
+    d->mo->setValue(key.toUtf8(), value);
+}
+
+/*!
+    Returns the list of keys.
+
+    Keys that have been cleared will still appear in this list, even though their
+    associated values are invalid QVariants.
+*/
+QStringList QDeclarativePropertyMap::keys() const
+{
+    Q_D(const QDeclarativePropertyMap);
+    return d->keys;
+}
+
+/*!
+    \overload
+
+    Same as size().
+*/
+int QDeclarativePropertyMap::count() const
+{
+    Q_D(const QDeclarativePropertyMap);
+    return d->keys.count();
+}
+
+/*!
+    Returns the number of keys in the map.
+
+    \sa isEmpty(), count()
+*/
+int QDeclarativePropertyMap::size() const
+{
+    Q_D(const QDeclarativePropertyMap);
+    return d->keys.size();
+}
+
+/*!
+    Returns true if the map contains no keys; otherwise returns
+    false.
+
+    \sa size()
+*/
+bool QDeclarativePropertyMap::isEmpty() const
+{
+    Q_D(const QDeclarativePropertyMap);
+    return d->keys.isEmpty();
+}
+
+/*!
+    Returns true if the map contains \a key.
+
+    \sa size()
+*/
+bool QDeclarativePropertyMap::contains(const QString &key) const
+{
+    Q_D(const QDeclarativePropertyMap);
+    return d->keys.contains(key);
+}
+
+/*!
+    Returns the value associated with the key \a key as a modifiable
+    reference.
+
+    If the map contains no item with key \a key, the function inserts
+    an invalid QVariant into the map with key \a key, and
+    returns a reference to it.
+
+    \sa insert(), value()
+*/
+QVariant &QDeclarativePropertyMap::operator[](const QString &key)
+{
+    //### optimize
+    Q_D(QDeclarativePropertyMap);
+    QByteArray utf8key = key.toUtf8();
+    if (!d->keys.contains(key))
+        d->mo->setValue(utf8key, QVariant());   //force creation -- needed below
+
+    return (*(d->mo))[utf8key];
+}
+
+/*!
+    \overload
+
+    Same as value().
+*/
+QVariant QDeclarativePropertyMap::operator[](const QString &key) const
+{
+    return value(key);
+}
+
+/*!
+    \fn void QDeclarativePropertyMap::valueChanged(const QString &key, const QVariant &value)
+    This signal is emitted whenever one of the values in the map is changed. \a key
+    is the key corresponding to the \a value that was changed.
+
+    \note valueChanged() is \bold NOT emitted when changes are made by calling insert()
+    or clear() - it is only emitted when a value is updated from QML.
+*/
+
+QT_END_NAMESPACE