src/declarative/qml/qdeclarativeboundsignal.cpp
changeset 30 5dc02b23752f
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 "private/qdeclarativeboundsignal_p.h"
       
    43 
       
    44 #include "private/qmetaobjectbuilder_p.h"
       
    45 #include "private/qdeclarativeengine_p.h"
       
    46 #include "private/qdeclarativeexpression_p.h"
       
    47 #include "private/qdeclarativecontext_p.h"
       
    48 #include "private/qdeclarativemetatype_p.h"
       
    49 #include "qdeclarative.h"
       
    50 #include "qdeclarativecontext.h"
       
    51 #include "private/qdeclarativeglobal_p.h"
       
    52 
       
    53 #include <QtCore/qdebug.h>
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 class QDeclarativeBoundSignalParameters : public QObject
       
    58 {
       
    59 Q_OBJECT
       
    60 public:
       
    61     QDeclarativeBoundSignalParameters(const QMetaMethod &, QObject * = 0);
       
    62     ~QDeclarativeBoundSignalParameters();
       
    63 
       
    64     void setValues(void **);
       
    65     void clearValues();
       
    66 
       
    67 private:
       
    68     friend class MetaObject;
       
    69     int metaCall(QMetaObject::Call, int _id, void **);
       
    70     struct MetaObject : public QAbstractDynamicMetaObject {
       
    71         MetaObject(QDeclarativeBoundSignalParameters *b)
       
    72             : parent(b) {}
       
    73 
       
    74         int metaCall(QMetaObject::Call c, int id, void **a) { 
       
    75             return parent->metaCall(c, id, a);
       
    76         }
       
    77         QDeclarativeBoundSignalParameters *parent;
       
    78     };
       
    79 
       
    80     int *types;
       
    81     void **values;
       
    82     QMetaObject *myMetaObject;
       
    83 };
       
    84 
       
    85 static int evaluateIdx = -1;
       
    86 
       
    87 QDeclarativeAbstractBoundSignal::QDeclarativeAbstractBoundSignal(QObject *parent)
       
    88 : QObject(parent)
       
    89 {
       
    90 }
       
    91 
       
    92 QDeclarativeAbstractBoundSignal::~QDeclarativeAbstractBoundSignal()
       
    93 {
       
    94 }
       
    95 
       
    96 QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMethod &signal, 
       
    97                                QObject *parent)
       
    98 : m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
       
    99 {
       
   100     // This is thread safe.  Although it may be updated by two threads, they
       
   101     // will both set it to the same value - so the worst thing that can happen
       
   102     // is that they both do the work to figure it out.  Boo hoo.
       
   103     if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
       
   104 
       
   105     QDeclarative_setParent_noEvent(this, parent);
       
   106     QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
       
   107 }
       
   108 
       
   109 QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val, 
       
   110                                QObject *scope, const QMetaMethod &signal,
       
   111                                QObject *parent)
       
   112 : m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
       
   113 {
       
   114     // This is thread safe.  Although it may be updated by two threads, they
       
   115     // will both set it to the same value - so the worst thing that can happen
       
   116     // is that they both do the work to figure it out.  Boo hoo.
       
   117     if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
       
   118 
       
   119     QDeclarative_setParent_noEvent(this, parent);
       
   120     QMetaObject::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
       
   121 
       
   122     m_expression = new QDeclarativeExpression(ctxt, scope, val);
       
   123 }
       
   124 
       
   125 QDeclarativeBoundSignal::~QDeclarativeBoundSignal()
       
   126 {
       
   127     delete m_expression;
       
   128     m_expression = 0;
       
   129 }
       
   130 
       
   131 int QDeclarativeBoundSignal::index() const 
       
   132 { 
       
   133     return m_signal.methodIndex();
       
   134 }
       
   135 
       
   136 /*!
       
   137     Returns the signal expression.
       
   138 */
       
   139 QDeclarativeExpression *QDeclarativeBoundSignal::expression() const
       
   140 {
       
   141     return m_expression;
       
   142 }
       
   143 
       
   144 /*!
       
   145     Sets the signal expression to \a e.  Returns the current signal expression,
       
   146     or null if there is no signal expression.
       
   147 
       
   148     The QDeclarativeBoundSignal instance takes ownership of \a e.  The caller is 
       
   149     assumes ownership of the returned QDeclarativeExpression.
       
   150 */
       
   151 QDeclarativeExpression *QDeclarativeBoundSignal::setExpression(QDeclarativeExpression *e)
       
   152 {
       
   153     QDeclarativeExpression *rv = m_expression;
       
   154     m_expression = e;
       
   155     if (m_expression) m_expression->setNotifyOnValueChanged(false);
       
   156     return rv;
       
   157 }
       
   158 
       
   159 QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o)
       
   160 {
       
   161     QDeclarativeAbstractBoundSignal *s = qobject_cast<QDeclarativeAbstractBoundSignal*>(o);
       
   162     return static_cast<QDeclarativeBoundSignal *>(s);
       
   163 }
       
   164 
       
   165 int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
       
   166 {
       
   167     if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
       
   168         m_isEvaluating = true;
       
   169         if (!m_paramsValid) {
       
   170             if (!m_signal.parameterTypes().isEmpty())
       
   171                 m_params = new QDeclarativeBoundSignalParameters(m_signal, this);
       
   172             m_paramsValid = true;
       
   173         }
       
   174 
       
   175         if (m_params) m_params->setValues(a);
       
   176         if (m_expression && m_expression->engine()) {
       
   177             QDeclarativeExpressionPrivate::get(m_expression)->value(m_params);
       
   178             if (m_expression && m_expression->hasError())
       
   179                 QDeclarativeEnginePrivate::warning(m_expression->engine(), m_expression->error());
       
   180         }
       
   181         if (m_params) m_params->clearValues();
       
   182         m_isEvaluating = false;
       
   183         return -1;
       
   184     } else {
       
   185         return QObject::qt_metacall(c, id, a);
       
   186     }
       
   187 }
       
   188 
       
   189 QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method, 
       
   190                                                    QObject *parent)
       
   191 : QObject(parent), types(0), values(0)
       
   192 {
       
   193     MetaObject *mo = new MetaObject(this);
       
   194 
       
   195     // ### Optimize!
       
   196     // ### Ensure only supported types are allowed, otherwise it might crash
       
   197     QMetaObjectBuilder mob;
       
   198     mob.setSuperClass(&QDeclarativeBoundSignalParameters::staticMetaObject);
       
   199     mob.setClassName("QDeclarativeBoundSignalParameters");
       
   200 
       
   201     QList<QByteArray> paramTypes = method.parameterTypes();
       
   202     QList<QByteArray> paramNames = method.parameterNames();
       
   203     types = new int[paramTypes.count()];
       
   204     for (int ii = 0; ii < paramTypes.count(); ++ii) {
       
   205         const QByteArray &type = paramTypes.at(ii);
       
   206         const QByteArray &name = paramNames.at(ii);
       
   207 
       
   208         if (name.isEmpty() || type.isEmpty()) {
       
   209             types[ii] = 0;
       
   210             continue;
       
   211         }
       
   212 
       
   213         QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
       
   214         if (QDeclarativeMetaType::isQObject(t)) {
       
   215             types[ii] = QMetaType::QObjectStar;
       
   216             QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
       
   217             prop.setWritable(false);
       
   218         } else {
       
   219             types[ii] = t;
       
   220             QMetaPropertyBuilder prop = mob.addProperty(name, type);
       
   221             prop.setWritable(false);
       
   222         }
       
   223     }
       
   224     myMetaObject = mob.toMetaObject();
       
   225     *static_cast<QMetaObject *>(mo) = *myMetaObject;
       
   226 
       
   227     d_ptr->metaObject = mo;
       
   228 }
       
   229 
       
   230 QDeclarativeBoundSignalParameters::~QDeclarativeBoundSignalParameters()
       
   231 {
       
   232     delete [] types;
       
   233     qFree(myMetaObject);
       
   234 }
       
   235 
       
   236 void QDeclarativeBoundSignalParameters::setValues(void **v)
       
   237 {
       
   238     values = v;
       
   239 }
       
   240 
       
   241 void QDeclarativeBoundSignalParameters::clearValues()
       
   242 {
       
   243     values = 0;
       
   244 }
       
   245 
       
   246 int QDeclarativeBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
       
   247 {
       
   248     if (!values)
       
   249         return -1;
       
   250 
       
   251     if (c == QMetaObject::ReadProperty && id >= 1) {
       
   252         QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]);
       
   253         return -1;
       
   254     } else {
       
   255         return qt_metacall(c, id, a);
       
   256     }
       
   257 }
       
   258 
       
   259 QT_END_NAMESPACE
       
   260 
       
   261 #include <qdeclarativeboundsignal.moc>