diff options
Diffstat (limited to 'src/qml/util')
-rw-r--r-- | src/qml/util/qqmlpropertymap.cpp | 309 | ||||
-rw-r--r-- | src/qml/util/qqmlpropertymap.h | 91 | ||||
-rw-r--r-- | src/qml/util/util.pri | 5 |
3 files changed, 405 insertions, 0 deletions
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp new file mode 100644 index 0000000000..5010af17c8 --- /dev/null +++ b/src/qml/util/qqmlpropertymap.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlpropertymap.h" + +#include <private/qmetaobjectbuilder_p.h> +#include <private/qqmlopenmetaobject_p.h> + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +//QQmlPropertyMapMetaObject lets us listen for changes coming from QML +//so we can emit the changed signal. +class QQmlPropertyMapMetaObject : public QQmlOpenMetaObject +{ +public: + QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv); + +protected: + virtual void propertyWritten(int index); + virtual void propertyCreated(int, QMetaPropertyBuilder &); + virtual int createProperty(const char *, const char *); +private: + QQmlPropertyMap *map; + QQmlPropertyMapPrivate *priv; +}; + +class QQmlPropertyMapPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQmlPropertyMap) +public: + QQmlPropertyMapMetaObject *mo; + QStringList keys; + void emitChanged(const QString &key, const QVariant &value); + bool validKeyName(const QString& name); +}; + +bool QQmlPropertyMapPrivate::validKeyName(const QString& name) +{ + //The following strings shouldn't be used as property names + return name != QLatin1String("keys") + && name != QLatin1String("valueChanged") + && name != QLatin1String("QObject") + && name != QLatin1String("destroyed") + && name != QLatin1String("deleteLater"); +} + +void QQmlPropertyMapPrivate::emitChanged(const QString &key, const QVariant &value) +{ + Q_Q(QQmlPropertyMap); + emit q->valueChanged(key, value); +} + +QQmlPropertyMapMetaObject::QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv) : QQmlOpenMetaObject(obj) +{ + map = obj; + priv = objPriv; +} + +void QQmlPropertyMapMetaObject::propertyWritten(int index) +{ + priv->emitChanged(QString::fromUtf8(name(index)), operator[](index)); +} + +void QQmlPropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b) +{ + priv->keys.append(QString::fromUtf8(b.name())); +} + +int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *value) +{ + if (!priv->validKeyName(QString::fromUtf8(name))) + return -1; + return QQmlOpenMetaObject::createProperty(name, value); +} + +/*! + \class QQmlPropertyMap + \brief The QQmlPropertyMap class allows you to set key-value pairs that can be used in QML bindings. + + QQmlPropertyMap 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. + + In the C++ file: + \code + // create our data + QQmlPropertyMap ownerData; + ownerData.insert("name", QVariant(QString("John Smith"))); + ownerData.insert("phone", QVariant(QString("555-5555"))); + + // expose it to the UI layer + QQuickView view; + QQmlContext *ctxt = view.rootContext(); + ctxt->setContextProperty("owner", &ownerData); + + view.setSource(QUrl::fromLocalFile("main.qml")); + view.show(); + \endcode + + Then, in \c main.qml: + \code + Text { text: owner.name + " " + 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. +*/ +QQmlPropertyMap::QQmlPropertyMap(QObject *parent) +: QObject(*(new QQmlPropertyMapPrivate), parent) +{ + Q_D(QQmlPropertyMap); + d->mo = new QQmlPropertyMapMetaObject(this, d); +} + +/*! + Destroys the bindable map. +*/ +QQmlPropertyMap::~QQmlPropertyMap() +{ +} + +/*! + Clears the value (if any) associated with \a key. +*/ +void QQmlPropertyMap::clear(const QString &key) +{ + Q_D(QQmlPropertyMap); + 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 QQmlPropertyMap::value(const QString &key) const +{ + Q_D(const QQmlPropertyMap); + 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 QQmlPropertyMap::insert(const QString &key, const QVariant &value) +{ + Q_D(QQmlPropertyMap); + + if (d->validKeyName(key)) { + d->mo->setValue(key.toUtf8(), value); + } else { + qWarning() << "Creating property with name" + << key + << "is not permitted, conflicts with internal symbols."; + } +} + +/*! + 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 QQmlPropertyMap::keys() const +{ + Q_D(const QQmlPropertyMap); + return d->keys; +} + +/*! + \overload + + Same as size(). +*/ +int QQmlPropertyMap::count() const +{ + Q_D(const QQmlPropertyMap); + return d->keys.count(); +} + +/*! + Returns the number of keys in the map. + + \sa isEmpty(), count() +*/ +int QQmlPropertyMap::size() const +{ + Q_D(const QQmlPropertyMap); + return d->keys.size(); +} + +/*! + Returns true if the map contains no keys; otherwise returns + false. + + \sa size() +*/ +bool QQmlPropertyMap::isEmpty() const +{ + Q_D(const QQmlPropertyMap); + return d->keys.isEmpty(); +} + +/*! + Returns true if the map contains \a key. + + \sa size() +*/ +bool QQmlPropertyMap::contains(const QString &key) const +{ + Q_D(const QQmlPropertyMap); + 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 &QQmlPropertyMap::operator[](const QString &key) +{ + //### optimize + Q_D(QQmlPropertyMap); + QByteArray utf8key = key.toUtf8(); + if (!d->keys.contains(key)) + insert(key, QVariant());//force creation -- needed below + + return (*(d->mo))[utf8key]; +} + +/*! + \overload + + Same as value(). +*/ +QVariant QQmlPropertyMap::operator[](const QString &key) const +{ + return value(key); +} + +/*! + \fn void QQmlPropertyMap::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 diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h new file mode 100644 index 0000000000..53254ab672 --- /dev/null +++ b/src/qml/util/qqmlpropertymap.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROPERTYMAP_H +#define QQMLPROPERTYMAP_H + +#include <QtQml/qtqmlglobal.h> + +#include <QtCore/QObject> +#include <QtCore/QHash> +#include <QtCore/QStringList> +#include <QtCore/QVariant> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QQmlPropertyMapPrivate; +class Q_QML_EXPORT QQmlPropertyMap : public QObject +{ + Q_OBJECT +public: + QQmlPropertyMap(QObject *parent = 0); + virtual ~QQmlPropertyMap(); + + QVariant value(const QString &key) const; + void insert(const QString &key, const QVariant &value); + void clear(const QString &key); + + Q_INVOKABLE QStringList keys() const; + + int count() const; + int size() const; + bool isEmpty() const; + bool contains(const QString &key) const; + + QVariant &operator[](const QString &key); + QVariant operator[](const QString &key) const; + +Q_SIGNALS: + void valueChanged(const QString &key, const QVariant &value); + +private: + Q_DECLARE_PRIVATE(QQmlPropertyMap) + Q_DISABLE_COPY(QQmlPropertyMap) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/qml/util/util.pri b/src/qml/util/util.pri new file mode 100644 index 0000000000..3b121ba3cb --- /dev/null +++ b/src/qml/util/util.pri @@ -0,0 +1,5 @@ +SOURCES += \ + $$PWD/qqmlpropertymap.cpp + +HEADERS += \ + $$PWD/qqmlpropertymap.h |