src/declarative/util/qdeclarativepropertymap.cpp
changeset 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdeclarativepropertymap.h"
       
    43 
       
    44 #include <private/qmetaobjectbuilder_p.h>
       
    45 #include "private/qdeclarativeopenmetaobject_p.h"
       
    46 
       
    47 #include <QDebug>
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 //QDeclarativePropertyMapMetaObject lets us listen for changes coming from QML
       
    52 //so we can emit the changed signal.
       
    53 class QDeclarativePropertyMapMetaObject : public QDeclarativeOpenMetaObject
       
    54 {
       
    55 public:
       
    56     QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv);
       
    57 
       
    58 protected:
       
    59     virtual void propertyWritten(int index);
       
    60     virtual void propertyCreated(int, QMetaPropertyBuilder &);
       
    61 
       
    62 private:
       
    63     QDeclarativePropertyMap *map;
       
    64     QDeclarativePropertyMapPrivate *priv;
       
    65 };
       
    66 
       
    67 class QDeclarativePropertyMapPrivate : public QObjectPrivate
       
    68 {
       
    69     Q_DECLARE_PUBLIC(QDeclarativePropertyMap)
       
    70 public:
       
    71     QDeclarativePropertyMapMetaObject *mo;
       
    72     QStringList keys;
       
    73     void emitChanged(const QString &key, const QVariant &value);
       
    74 };
       
    75 
       
    76 void QDeclarativePropertyMapPrivate::emitChanged(const QString &key, const QVariant &value)
       
    77 {
       
    78     Q_Q(QDeclarativePropertyMap);
       
    79     emit q->valueChanged(key, value);
       
    80 }
       
    81 
       
    82 QDeclarativePropertyMapMetaObject::QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv) : QDeclarativeOpenMetaObject(obj)
       
    83 {
       
    84     map = obj;
       
    85     priv = objPriv;
       
    86 }
       
    87 
       
    88 void QDeclarativePropertyMapMetaObject::propertyWritten(int index)
       
    89 {
       
    90     priv->emitChanged(QString::fromUtf8(name(index)), operator[](index));
       
    91 }
       
    92 
       
    93 void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b)
       
    94 {
       
    95     priv->keys.append(QString::fromUtf8(b.name()));
       
    96 }
       
    97 
       
    98 /*!
       
    99     \class QDeclarativePropertyMap
       
   100     \since 4.7
       
   101     \brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in QML bindings.
       
   102 
       
   103     QDeclarativePropertyMap provides a convenient way to expose domain data to the UI layer.
       
   104     The following example shows how you might declare data in C++ and then
       
   105     access it in QML.
       
   106 
       
   107     Setup in C++:
       
   108     \code
       
   109     //create our data
       
   110     QDeclarativePropertyMap ownerData;
       
   111     ownerData.insert("name", QVariant(QString("John Smith")));
       
   112     ownerData.insert("phone", QVariant(QString("555-5555")));
       
   113 
       
   114     //expose it to the UI layer
       
   115     QDeclarativeContext *ctxt = view->rootContext();
       
   116     ctxt->setProperty("owner", &data);
       
   117     \endcode
       
   118 
       
   119     Then, in QML:
       
   120     \code
       
   121     Text { text: owner.name }
       
   122     Text { text: owner.phone }
       
   123     \endcode
       
   124 
       
   125     The binding is dynamic - whenever a key's value is updated, anything bound to that
       
   126     key will be updated as well.
       
   127 
       
   128     To detect value changes made in the UI layer you can connect to the valueChanged() signal.
       
   129     However, note that valueChanged() is \bold NOT emitted when changes are made by calling insert()
       
   130     or clear() - it is only emitted when a value is updated from QML.
       
   131 
       
   132     \note It is not possible to remove keys from the map; once a key has been added, you can only
       
   133     modify or clear its associated value.
       
   134 */
       
   135 
       
   136 /*!
       
   137     Constructs a bindable map with parent object \a parent.
       
   138 */
       
   139 QDeclarativePropertyMap::QDeclarativePropertyMap(QObject *parent)
       
   140 : QObject(*(new QDeclarativePropertyMapPrivate), parent)
       
   141 {
       
   142     Q_D(QDeclarativePropertyMap);
       
   143     d->mo = new QDeclarativePropertyMapMetaObject(this, d);
       
   144 }
       
   145 
       
   146 /*!
       
   147     Destroys the bindable map.
       
   148 */
       
   149 QDeclarativePropertyMap::~QDeclarativePropertyMap()
       
   150 {
       
   151 }
       
   152 
       
   153 /*!
       
   154     Clears the value (if any) associated with \a key.
       
   155 */
       
   156 void QDeclarativePropertyMap::clear(const QString &key)
       
   157 {
       
   158     Q_D(QDeclarativePropertyMap);
       
   159     d->mo->setValue(key.toUtf8(), QVariant());
       
   160 }
       
   161 
       
   162 /*!
       
   163     Returns the value associated with \a key.
       
   164 
       
   165     If no value has been set for this key (or if the value has been cleared),
       
   166     an invalid QVariant is returned.
       
   167 */
       
   168 QVariant QDeclarativePropertyMap::value(const QString &key) const
       
   169 {
       
   170     Q_D(const QDeclarativePropertyMap);
       
   171     return d->mo->value(key.toUtf8());
       
   172 }
       
   173 
       
   174 /*!
       
   175     Sets the value associated with \a key to \a value.
       
   176 
       
   177     If the key doesn't exist, it is automatically created.
       
   178 */
       
   179 void QDeclarativePropertyMap::insert(const QString &key, const QVariant &value)
       
   180 {
       
   181     Q_D(QDeclarativePropertyMap);
       
   182     d->mo->setValue(key.toUtf8(), value);
       
   183 }
       
   184 
       
   185 /*!
       
   186     Returns the list of keys.
       
   187 
       
   188     Keys that have been cleared will still appear in this list, even though their
       
   189     associated values are invalid QVariants.
       
   190 */
       
   191 QStringList QDeclarativePropertyMap::keys() const
       
   192 {
       
   193     Q_D(const QDeclarativePropertyMap);
       
   194     return d->keys;
       
   195 }
       
   196 
       
   197 /*!
       
   198     \overload
       
   199 
       
   200     Same as size().
       
   201 */
       
   202 int QDeclarativePropertyMap::count() const
       
   203 {
       
   204     Q_D(const QDeclarativePropertyMap);
       
   205     return d->keys.count();
       
   206 }
       
   207 
       
   208 /*!
       
   209     Returns the number of keys in the map.
       
   210 
       
   211     \sa isEmpty(), count()
       
   212 */
       
   213 int QDeclarativePropertyMap::size() const
       
   214 {
       
   215     Q_D(const QDeclarativePropertyMap);
       
   216     return d->keys.size();
       
   217 }
       
   218 
       
   219 /*!
       
   220     Returns true if the map contains no keys; otherwise returns
       
   221     false.
       
   222 
       
   223     \sa size()
       
   224 */
       
   225 bool QDeclarativePropertyMap::isEmpty() const
       
   226 {
       
   227     Q_D(const QDeclarativePropertyMap);
       
   228     return d->keys.isEmpty();
       
   229 }
       
   230 
       
   231 /*!
       
   232     Returns true if the map contains \a key.
       
   233 
       
   234     \sa size()
       
   235 */
       
   236 bool QDeclarativePropertyMap::contains(const QString &key) const
       
   237 {
       
   238     Q_D(const QDeclarativePropertyMap);
       
   239     return d->keys.contains(key);
       
   240 }
       
   241 
       
   242 /*!
       
   243     Returns the value associated with the key \a key as a modifiable
       
   244     reference.
       
   245 
       
   246     If the map contains no item with key \a key, the function inserts
       
   247     an invalid QVariant into the map with key \a key, and
       
   248     returns a reference to it.
       
   249 
       
   250     \sa insert(), value()
       
   251 */
       
   252 QVariant &QDeclarativePropertyMap::operator[](const QString &key)
       
   253 {
       
   254     //### optimize
       
   255     Q_D(QDeclarativePropertyMap);
       
   256     QByteArray utf8key = key.toUtf8();
       
   257     if (!d->keys.contains(key))
       
   258         d->mo->setValue(utf8key, QVariant());   //force creation -- needed below
       
   259 
       
   260     return (*(d->mo))[utf8key];
       
   261 }
       
   262 
       
   263 /*!
       
   264     \overload
       
   265 
       
   266     Same as value().
       
   267 */
       
   268 QVariant QDeclarativePropertyMap::operator[](const QString &key) const
       
   269 {
       
   270     return value(key);
       
   271 }
       
   272 
       
   273 /*!
       
   274     \fn void QDeclarativePropertyMap::valueChanged(const QString &key, const QVariant &value)
       
   275     This signal is emitted whenever one of the values in the map is changed. \a key
       
   276     is the key corresponding to the \a value that was changed.
       
   277 
       
   278     \note valueChanged() is \bold NOT emitted when changes are made by calling insert()
       
   279     or clear() - it is only emitted when a value is updated from QML.
       
   280 */
       
   281 
       
   282 QT_END_NAMESPACE