diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-04-28 05:05:53 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-04-28 05:05:53 (GMT) |
commit | 2b8abf28d10a6d064fe116892161289be5ffb391 (patch) | |
tree | 6a1123766682c82bddbdf358316f26e11f6976c7 | |
parent | d7ffaa8ccbf881d25004b9a710259701d1a8c9bc (diff) | |
parent | a6ffd7c7c28066f2794579bc40e7b9517e76d1ff (diff) | |
download | Qt-2b8abf28d10a6d064fe116892161289be5ffb391.zip Qt-2b8abf28d10a6d064fe116892161289be5ffb391.tar.gz Qt-2b8abf28d10a6d064fe116892161289be5ffb391.tar.bz2 |
Merge branch 'kinetic-declarativeui' of ../kinetic into kinetic-declarativeui-qfx
Conflicts:
examples/declarative/mouseregion/mouse.qml
27 files changed, 407 insertions, 194 deletions
diff --git a/examples/declarative/mouseregion/mouse.qml b/examples/declarative/mouseregion/mouse.qml index 070543c..7aaf51a 100644 --- a/examples/declarative/mouseregion/mouse.qml +++ b/examples/declarative/mouseregion/mouse.qml @@ -1,48 +1,24 @@ -Rect { - color: "white" - width: 200 - height: 200 - Rect { - width: 50 - height: 50 - color: "red" - Text { - text: "Click" - anchors.centeredIn: parent - } - MouseRegion { - onPressed: { print('press (x: ' + mouse.x + ' y: ' + mouse.y + ')') } - onReleased: { print('release (x: ' + mouse.x + ' y: ' + mouse.y + ' isClick: ' + mouse.isClick + ' wasHeld: ' + mouse.wasHeld + ')') } - onClicked: { print('click (x: ' + mouse.x + ' y: ' + mouse.y + ' wasHeld: ' + mouse.wasHeld + ')') } - onDoubleClicked: { print('double click (x: ' + mouse.x + ' y: ' + mouse.y + ')') } - onPressAndHold: { print('press and hold') } - onExitedWhilePressed: { print('exiting while pressed') } - onReenteredWhilePressed: { print('reentering while pressed') } - anchors.fill: parent - } - } - Rect { - y: 100 - width: 50 - height: 50 - color: "blue" - Text { - text: "Drag" - anchors.centeredIn: parent - } - MouseRegion { - drag.target: parent - drag.axis: "x" - drag.xmin: 0 - drag.xmax: 150 - onPressed: { print('press') } - onReleased: { print('release (isClick: ' + mouse.isClick + ') (wasHeld: ' + mouse.wasHeld + ')') } - onClicked: { print('click' + '(wasHeld: ' + mouse.wasHeld + ')') } - onDoubleClicked: { print('double click') } - onPressAndHold: { print('press and hold') } - onExitedWhilePressed: { print('exiting while pressed') } - onReenteredWhilePressed: { print('reentering while pressed') } - anchors.fill: parent - } - } -} +<Rect color="white" width="200" height="200"> + <Rect width="50" height="50" color="red"> + <Text text="Click" anchors.centeredIn="{parent}"/> + <MouseRegion onPressed="print('press (x: ' + mouse.x + ' y: ' + mouse.y + ' button: ' + (mouse.button == Qt.RightButton ? 'right' : 'left') + ' Shift: ' + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')')" + onReleased="print('release (x: ' + mouse.x + ' y: ' + mouse.y + ' isClick: ' + mouse.isClick + ' wasHeld: ' + mouse.wasHeld + ')')" + onClicked="print('click (x: ' + mouse.x + ' y: ' + mouse.y + ' wasHeld: ' + mouse.wasHeld + ')')" + onDoubleClicked="print('double click (x: ' + mouse.x + ' y: ' + mouse.y + ')')" + onPressAndHold="print('press and hold')" + onExitedWhilePressed="print('exiting while pressed')" + onReenteredWhilePressed="print('reentering while pressed')" anchors.fill="{parent}"/> + </Rect> + <Rect y="100" width="50" height="50" color="blue"> + <Text text="Drag" anchors.centeredIn="{parent}"/> + <MouseRegion drag.target="{parent}" + drag.axis="x" drag.xmin="0" drag.xmax="150" + onPressed="print('press')" + onReleased="print('release (isClick: ' + mouse.isClick + ') (wasHeld: ' + mouse.wasHeld + ')')" + onClicked="print('click' + '(wasHeld: ' + mouse.wasHeld + ')')" + onDoubleClicked="print('double click')" + onPressAndHold="print('press and hold')" + onExitedWhilePressed="print('exiting while pressed')" + onReenteredWhilePressed="print('reentering while pressed')" anchors.fill="{parent}"/> + </Rect> +</Rect> diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp index 4d2cc5b..572bc43 100644 --- a/src/declarative/canvas/qsimplecanvas.cpp +++ b/src/declarative/canvas/qsimplecanvas.cpp @@ -411,6 +411,7 @@ QGraphicsSceneMouseEvent *QSimpleCanvasPrivate::mouseEventToSceneMouseEvent(QMou QGraphicsSceneMouseEvent *me = new QGraphicsSceneMouseEvent(t); me->setButton(e->button()); me->setButtons(e->buttons()); + me->setModifiers(e->modifiers()); me->setPos(item); me->setScreenPos(e->pos()); me->setScenePos(e->pos()); diff --git a/src/declarative/fx/qfxevents.cpp b/src/declarative/fx/qfxevents.cpp index a3fa6af..804446b 100644 --- a/src/declarative/fx/qfxevents.cpp +++ b/src/declarative/fx/qfxevents.cpp @@ -42,10 +42,74 @@ #include "qfxevents_p.h" QT_BEGIN_NAMESPACE +/*! + \qmlclass KeyEvent QFxKeyEvent + \brief The KeyEvent element provides information about a key event. + + For example, the following changes the Item's state property when the Enter + key is pressed: + \code + <Item focus="true"> + <onKeyPress>if (event.key == Qt.Key_Enter) state = 'ShowDetails';</onKeyPress> + </Item> + \endcode + + The \l KeyActions element could also be used to achieve the above with + a clearer syntax. + + \sa KeyActions +*/ + +/*! + \internal + \class QFxKeyEvent +*/ + +/*! + \qmlproperty int KeyEvent::key + + This property holds the code of the key that was pressed or released. + + See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are + independent of the underlying window system. Note that this + function does not distinguish between capital and non-capital + letters, use the text() function (returning the Unicode text the + key generated) for this purpose. + + A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not + the result of a known key; for example, it may be the result of + a compose sequence, a keyboard macro, or due to key event + compression. +*/ + +/*! + \qmlproperty string KeyEvent::text + + This property holds the Unicode text that the key generated. + The text returned can be an empty string in cases where modifier keys, + such as Shift, Control, Alt, and Meta, are being pressed or released. + In such cases \c key will contain a valid value +*/ + +/*! + \qmlproperty bool KeyEvent::isAutoRepeat + + This property holds whether this event comes from an auto-repeating key. +*/ + +/*! + \qmlproperty int KeyEvent::count + + This property holds the number of keys involved in this event. If \l KeyEvent::text + is not empty, this is simply the length of the string. +*/ /*! \qmlclass MouseEvent QFxMouseEvent \brief The MouseEvent element provides information about a mouse event. + + The position of the mouse can be found via the x and y properties. + The button that caused the event is available via the button property. */ /*! @@ -61,9 +125,58 @@ QT_BEGIN_NAMESPACE */ /*! - \qmlproperty enum button + \qmlproperty enum MouseEvent::button + + This property holds the button that caused the event. It can be one of: + \list + \o Qt.LeftButton + \o Qt.RightButton + \o Qt.MidButton + \endlist +*/ + +/*! + \qmlproperty int MouseEvent::buttons + + This property holds the mouse buttons pressed when the event was generated. + For mouse move events, this is all buttons that are pressed down. For mouse + press and double click events this includes the button that caused the event. + For mouse release events this excludes the button that caused the event. + + It contains a bitwise combination of: + \list + \o Qt.LeftButton + \o Qt.RightButton + \o Qt.MidButton + \endlist +*/ + +/*! + \qmlproperty int MouseEvent::modifiers + + This property holds the keyboard modifier flags that existed immediately + before the event occurred. + + It contains a bitwise combination of: + \list + \o Qt.NoModifier - No modifier key is pressed. + \o Qt.ShiftModifier - A Shift key on the keyboard is pressed. + \o Qt.ControlModifier - A Ctrl key on the keyboard is pressed. + \o Qt.AltModifier - An Alt key on the keyboard is pressed. + \o Qt.MetaModifier - A Meta key on the keyboard is pressed. + \o Qt.KeypadModifier - A keypad button is pressed. + \endlist - This property holds the button that caused the event. + For example, to react to a Shift key + Left mouse button click: + \code + <MouseRegion> + <onClick> + <![CDATA[ + if (mouse.button == Qt.LeftButton && mouse.modifiers & Qt.ShiftModifier) doSomething(); + ]]> + </onclick> + </MouseRegion> + \endcode */ QML_DEFINE_NOCREATE_TYPE(QFxKeyEvent); diff --git a/src/declarative/fx/qfxevents_p.h b/src/declarative/fx/qfxevents_p.h index d096a90..30717ef 100644 --- a/src/declarative/fx/qfxevents_p.h +++ b/src/declarative/fx/qfxevents_p.h @@ -52,12 +52,12 @@ QT_BEGIN_NAMESPACE class QFxKeyEvent : public QObject { Q_OBJECT - Q_PROPERTY(int key READ key); - Q_PROPERTY(QString text READ text); - Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers); - Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat); - Q_PROPERTY(int count READ count); - Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted); + Q_PROPERTY(int key READ key) + Q_PROPERTY(QString text READ text) + Q_PROPERTY(int modifiers READ modifiers) + Q_PROPERTY(bool isAutoRepeat READ isAutoRepeat) + Q_PROPERTY(int count READ count) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) public: QFxKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1) @@ -67,7 +67,7 @@ public: int key() const { return event.key(); } QString text() const { return event.text(); } - Qt::KeyboardModifiers modifiers() const { return event.modifiers(); } + int modifiers() const { return event.modifiers(); } bool isAutoRepeat() const { return event.isAutoRepeat(); } int count() const { return event.count(); } @@ -83,14 +83,14 @@ QML_DECLARE_TYPE(QFxKeyEvent); class QFxMouseEvent : public QObject { Q_OBJECT - Q_PROPERTY(int x READ x); - Q_PROPERTY(int y READ y); - Q_PROPERTY(Qt::MouseButton button READ button); - Q_PROPERTY(Qt::MouseButtons buttons READ buttons); - Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers); - Q_PROPERTY(bool wasHeld READ wasHeld); - Q_PROPERTY(bool isClick READ isClick); - Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted); + Q_PROPERTY(int x READ x) + Q_PROPERTY(int y READ y) + Q_PROPERTY(int button READ button) + Q_PROPERTY(int buttons READ buttons) + Q_PROPERTY(int modifiers READ modifiers) + Q_PROPERTY(bool wasHeld READ wasHeld) + Q_PROPERTY(bool isClick READ isClick) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) public: QFxMouseEvent(int x, int y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers @@ -100,9 +100,9 @@ public: int x() const { return _x; } int y() const { return _y; } - Qt::MouseButton button() const { return _button; } - Qt::MouseButtons buttons() const { return _buttons; } - Qt::KeyboardModifiers modifiers() const { return _modifiers; } + int button() const { return _button; } + int buttons() const { return _buttons; } + int modifiers() const { return _modifiers; } bool wasHeld() const { return _wasHeld; } bool isClick() const { return _isClick; } diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index 5e4baac..25c1565 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -79,12 +79,9 @@ public: } static QFxGridViewAttached *properties(QObject *obj) { - if(!attachedProperties.contains(obj)) { - QFxGridViewAttached *rv = new QFxGridViewAttached(obj); - attachedProperties.insert(obj, rv); - return rv; - } - return attachedProperties.value(obj); + QFxGridViewAttached *rv = new QFxGridViewAttached(obj); + attachedProperties.insert(obj, rv); + return rv; } void emitAdd() { emit add(); } diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 644e812..e3568e0 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -322,33 +322,27 @@ void QFxContents::setItem(QFxItem *item) */ /*! - \fn void QFxItem::keyPress(QObject *event) + \qmlsignal Item::onKeyPress(event) - This signal is emitted when a key is pressed. + This handler is called when a key is pressed. - The key event is available in QML via the QFxKeyEvent \a event - property. + The key event is available via the KeyEvent \a event. \qml <Item onKeyPress="if (event.key == Qt.Key_Enter) state='Enter'"/> \endqml - - \sa keyRelease() */ /*! - \fn void QFxItem::keyRelease(QObject *event) + \qmlsignal Item::onKeyRelease(event) - This signal is emitted when a key is released. + This handler is called when a key is released. - The key event is available in QML via the QFxKeyEvent \a event - property. + The key event is available in via the KeyEvent \a event. \qml <Item onKeyRelease="if (event.key == Qt.Key_Enter) state='Enter'"/> \endqml - - \sa keyPress() */ /*! diff --git a/src/declarative/fx/qfxkeyactions.cpp b/src/declarative/fx/qfxkeyactions.cpp index d16c305..3bd7d00 100644 --- a/src/declarative/fx/qfxkeyactions.cpp +++ b/src/declarative/fx/qfxkeyactions.cpp @@ -239,12 +239,7 @@ void QFxKeyActions::setEnabled(bool e) } /*! - \qmlproperty string KeyActions::keyA - \qmlproperty string KeyActions::keyB - \qmlproperty string KeyActions::keyC - \qmlproperty ... KeyActions::... - \qmlproperty string KeyActions::keyY - \qmlproperty string KeyActions::keyZ + \qmlproperty string KeyActions::keyA...keyZ The action to take for the given letter. @@ -569,11 +564,7 @@ void QFxKeyActions::setKey_Down(const QString &s) } /*! - \qmlproperty string KeyActions::digit0 - \qmlproperty string KeyActions::digit1 - \qmlproperty string KeyActions::digit2 - \qmlproperty ... KeyActions::... - \qmlproperty string KeyActions::digit9 + \qmlproperty string KeyActions::digit0...digit9 The action to take for the given number key. diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index e03ec47..c85d8ce 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -98,12 +98,9 @@ public: } static QFxListViewAttached *properties(QObject *obj) { - if(!attachedProperties.contains(obj)) { - QFxListViewAttached *rv = new QFxListViewAttached(obj); - attachedProperties.insert(obj, rv); - return rv; - } - return attachedProperties.value(obj); + QFxListViewAttached *rv = new QFxListViewAttached(obj); + attachedProperties.insert(obj, rv); + return rv; } void emitAdd() { emit add(); } diff --git a/src/declarative/fx/qfxmouseregion.cpp b/src/declarative/fx/qfxmouseregion.cpp index be56786..f7b6c57 100644 --- a/src/declarative/fx/qfxmouseregion.cpp +++ b/src/declarative/fx/qfxmouseregion.cpp @@ -155,7 +155,7 @@ void QFxDrag::setYmax(int m) </Rect> \endcode - Many MouseRegion signals pass a \l {qml-mouseevent}{mouse} parameter that contains + Many MouseRegion signals pass a \l {MouseEvent}{mouse} parameter that contains additional information about the mouse event, such as the position, button, and any key modifiers. @@ -163,13 +163,15 @@ void QFxDrag::setYmax(int m) example extended so as to give a different color when you right click. \code <Rect width="100" height="100"> - <MouseRegion anchors.fill="{parent}" onClick="if(mouse.button=='Right') { parent.color='blue';} else { parent.color = 'red';}"/> + <MouseRegion anchors.fill="{parent}" onClick="if(mouse.button==Qt.RightButton) { parent.color='blue';} else { parent.color = 'red';}"/> </Rect> \endcode For basic key handling, see \l KeyActions. MouseRegion is an invisible element: it is never painted. + + \sa MouseEvent */ /*! @@ -201,6 +203,15 @@ void QFxDrag::setYmax(int m) */ /*! + \qmlsignal MouseRegion::onPositionChanged(mouse) + + This handler is called when the mouse position changes. + + The \l {MouseEvent}{mouse} parameter provides information about the mouse, including the x and y + position, and any buttons currently pressed. +*/ + +/*! \qmlsignal MouseRegion::onClicked(mouse) This handler is called when there is a click. A click is defined as a press followed by a release, @@ -215,8 +226,8 @@ void QFxDrag::setYmax(int m) \qmlsignal MouseRegion::onPressed(mouse) This handler is called when there is a press. - The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y - position of the release of the click, and whether the click wasHeld. + The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y + position and which button was pressed. */ /*! @@ -231,8 +242,8 @@ void QFxDrag::setYmax(int m) \qmlsignal MouseRegion::onPressAndHold(mouse) This handler is called when there is a long press (currently 800ms). - The \l {MouseEvent}{mouse} parameter provides information about the click, including the x and y - position of the release of the click, and whether the click wasHeld. + The \l {MouseEvent}{mouse} parameter provides information about the press, including the x and y + position of the press, and which button is pressed. */ /*! @@ -309,24 +320,6 @@ void QFxMouseRegion::setEnabled(bool a) d->absorb = a; } -void QFxMouseRegionPrivate::bindButtonValue(Qt::MouseButton b) -{ - Q_Q(QFxMouseRegion); - QString bString; - switch(b){ - case Qt::LeftButton: - bString = QLatin1String("Left"); break; - case Qt::RightButton: - bString = QLatin1String("Right"); break; - case Qt::MidButton: - bString = QLatin1String("Middle"); break; - default: - bString = QLatin1String("None"); break; - } - // ### is this needed anymore? - qmlContext(q)->setContextProperty(QLatin1String("mouseButton"), bString); -} - void QFxMouseRegion::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QFxMouseRegion); @@ -348,9 +341,7 @@ void QFxMouseRegion::mousePressEvent(QGraphicsSceneMouseEvent *event) // ### we should only start timer if pressAndHold is connected to (but connectNotify doesn't work) d->pressAndHoldTimer.start(PressAndHoldDelay, this); setKeepMouseGrab(false); - d->bindButtonValue(event->button()); setPressed(true); - emit positionChanged(); event->accept(); } } @@ -424,7 +415,8 @@ void QFxMouseRegion::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } } d->moved = true; - emit positionChanged(); + QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress); + emit positionChanged(&me); event->accept(); } @@ -547,9 +539,10 @@ void QFxMouseRegion::setPressed(bool p) if(d->pressed != p) { d->pressed = p; QFxMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress); - if(d->pressed) + if(d->pressed) { + emit positionChanged(&me); emit pressed(&me); - else { + } else { emit released(&me); if (isclick) emit clicked(&me); diff --git a/src/declarative/fx/qfxmouseregion.h b/src/declarative/fx/qfxmouseregion.h index 2e2a1d4..2ba4a50 100644 --- a/src/declarative/fx/qfxmouseregion.h +++ b/src/declarative/fx/qfxmouseregion.h @@ -121,7 +121,7 @@ public: Q_SIGNALS: void hoveredChanged(); void pressedChanged(); - void positionChanged(); + void positionChanged(QFxMouseEvent *mouse); void pressed(QFxMouseEvent *mouse); void pressAndHold(QFxMouseEvent *mouse); diff --git a/src/declarative/fx/qfxmouseregion_p.h b/src/declarative/fx/qfxmouseregion_p.h index e9d1986..d72b423 100644 --- a/src/declarative/fx/qfxmouseregion_p.h +++ b/src/declarative/fx/qfxmouseregion_p.h @@ -66,7 +66,7 @@ class QFxMouseRegionPrivate : public QFxItemPrivate public: QFxMouseRegionPrivate() - : absorb(true), hovered(false), inside(true), pressed(false), longPress(0), drag(0) + : absorb(true), hovered(false), inside(true), pressed(false), longPress(false), drag(0) { } @@ -77,25 +77,24 @@ public: q->setOptions(QSimpleCanvasItem::HoverEvents | QSimpleCanvasItem::MouseEvents); } - void bindButtonValue(Qt::MouseButton); - void saveEvent(QGraphicsSceneMouseEvent *event) { lastPos = event->pos(); lastButton = event->button(); lastButtons = event->buttons(); lastModifiers = event->modifiers(); + qDebug() << "modifiers" << lastModifiers; } - bool absorb; - bool hovered; - bool inside; - bool pressed; - bool longPress; + bool absorb : 1; + bool hovered : 1; + bool inside : 1; + bool pressed : 1; + bool longPress : 1; + bool moved : 1; + bool dragX : 1; + bool dragY : 1; + bool dragged : 1; QFxDrag drag; - bool moved; - bool dragX; - bool dragY; - bool dragged; QPointF start; QPointF startScene; int startX; diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp index 1bf7dda..59c7cd1 100644 --- a/src/declarative/fx/qfxpathview.cpp +++ b/src/declarative/fx/qfxpathview.cpp @@ -830,11 +830,9 @@ void QFxPathViewPrivate::snapToCurrent() QHash<QObject*, QObject*> QFxPathView::attachedProperties; QObject *QFxPathView::qmlAttachedProperties(QObject *obj) { - if(!attachedProperties.contains(obj)) { - QFxPathViewAttached *rv = new QFxPathViewAttached(obj); - attachedProperties.insert(obj, rv); - } - return attachedProperties.value(obj); + QFxPathViewAttached *rv = new QFxPathViewAttached(obj); + attachedProperties.insert(obj, rv); + return rv; } QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxrepeater.cpp b/src/declarative/fx/qfxrepeater.cpp index ad4081b..78e9f51 100644 --- a/src/declarative/fx/qfxrepeater.cpp +++ b/src/declarative/fx/qfxrepeater.cpp @@ -235,6 +235,15 @@ void QFxRepeater::setComponent(QmlComponent *_c) /*! \internal */ +void QFxRepeater::componentComplete() +{ + QFxItem::componentComplete(); + regenerate(); +} + +/*! + \internal + */ void QFxRepeater::parentChanged(QSimpleCanvasItem *o, QSimpleCanvasItem *n) { QFxItem::parentChanged(o, n); @@ -250,7 +259,7 @@ void QFxRepeater::regenerate() qDeleteAll(d->deletables); d->deletables.clear(); - if(!d->component || !itemParent()) + if(!d->component || !itemParent() || !isComponentComplete()) return; QFxItem *lastItem = this; diff --git a/src/declarative/fx/qfxrepeater.h b/src/declarative/fx/qfxrepeater.h index f6c4584..8efd281 100644 --- a/src/declarative/fx/qfxrepeater.h +++ b/src/declarative/fx/qfxrepeater.h @@ -72,6 +72,7 @@ private: void regenerate(); protected: + virtual void componentComplete(); virtual void parentChanged(QSimpleCanvasItem *, QSimpleCanvasItem *); QFxRepeater(QFxRepeaterPrivate &dd, QFxItem *parent); diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h index fb288b7..2d8d83e 100644 --- a/src/declarative/qml/qml.h +++ b/src/declarative/qml/qml.h @@ -92,6 +92,22 @@ class QmlContext; class QmlEngine; Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *); Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *); +Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *); + +template<typename T> +QObject *qmlAttachedPropertiesObject(const QObject *obj) +{ + // ### is this threadsafe? + static int idx = -1; + + if(idx == -1) + idx = QmlMetaType::attachedPropertiesFuncId(&T::staticMetaObject); + + if(idx == -1 || !obj) + return 0; + + return qmlAttachedPropertiesObjectById(obj, idx); +} QML_DECLARE_TYPE(QObject); Q_DECLARE_METATYPE(QVariant); diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 523a31b..00e3ccb 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -56,7 +56,8 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlmetaproperty_p.h \ qml/qmlcontext_p.h \ qml/qmlcompositetypemanager_p.h \ - qml/qmllist.h + qml/qmllist.h \ + qml/qmldeclarativedata_p.h # for qtscript debugger QT += scripttools diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 7d9dd5f..d55647c 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -911,8 +911,10 @@ bool QmlCompiler::compileAttachedProperty(QmlParser::Property *prop, QmlInstruction fetch; fetch.type = QmlInstruction::FetchAttached; fetch.line = prop->line; - int ref = output->indexForByteArray(prop->name); - fetch.fetchAttached.idx = ref; + int id = QmlMetaType::attachedPropertiesFuncId(prop->name); + if(id == -1) + COMPILE_EXCEPTION("Non-existant attached property object" << prop->name); + fetch.fetchAttached.id = id; output->bytecode << fetch; COMPILE_CHECK(compileFetchedObject(prop->value, ctxt + 1)); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index aa0bf3e..3772885 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -44,6 +44,7 @@ #include <qmlcontext.h> #include <private/qobject_p.h> +#include <private/qmldeclarativedata_p.h> #include <qhash.h> #include <qscriptvalue.h> @@ -82,12 +83,7 @@ public: }; void addDefaultObject(QObject *, Priority); - class ContextData : public QDeclarativeData - { - public: - QmlContext *context; - }; - ContextData contextData; + QmlSimpleDeclarativeData contextData; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h new file mode 100644 index 0000000..a934442 --- /dev/null +++ b/src/declarative/qml/qmldeclarativedata_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLDECLARATIVEDATA_P_H +#define QMLDECLARATIVEDATA_P_H + +#include <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +class QmlSimpleDeclarativeData : public QDeclarativeData +{ +public: + QmlSimpleDeclarativeData() : flags(0), context(0) {} + + enum Flag { Extended = 0x00000001 }; + quint32 flags; + QmlContext *context; +}; + +class QmlExtendedDeclarativeData : public QmlSimpleDeclarativeData +{ +public: + QmlExtendedDeclarativeData() { flags = Extended; } + + virtual void destroyed(QObject *); + QHash<int, QObject *> attachedProperties; +}; + +QT_END_NAMESPACE + +#endif // QMLDECLARATIVEDATA_P_H diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index db229ba..5e698c2 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -599,10 +599,32 @@ QNetworkAccessManager *QmlEngine::networkAccessManager() const QmlContext *QmlEngine::contextForObject(const QObject *object) { QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object)); - if(priv->declarativeData) { - return static_cast<QmlContextPrivate::ContextData *>(priv->declarativeData)->context; + + QmlSimpleDeclarativeData *data = + static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); + + return data?data->context:0; +} + +void QmlEngine::setContextForObject(QObject *object, QmlContext *context) +{ + QObjectPrivate *priv = QObjectPrivate::get(object); + + QmlSimpleDeclarativeData *data = + static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); + + if(data && data->context) { + qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext"); + return; + } + + if(!data) { + priv->declarativeData = &context->d_func()->contextData; } else { - return 0; + // ### - Don't have to use extended data here + QmlExtendedDeclarativeData *data = new QmlExtendedDeclarativeData; + data->context = context; + priv->declarativeData = data; } } @@ -617,15 +639,45 @@ QmlEngine *qmlEngine(const QObject *obj) return context?context->engine():0; } - -void QmlEngine::setContextForObject(QObject *object, QmlContext *context) +QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object) { - QObjectPrivate *priv = QObjectPrivate::get(object); - if(priv->declarativeData) { - qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext"); - return; + QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object)); + + + QmlSimpleDeclarativeData *data = static_cast<QmlSimpleDeclarativeData *>(priv->declarativeData); + + QmlExtendedDeclarativeData *edata = (data && data->flags & QmlSimpleDeclarativeData::Extended)?static_cast<QmlExtendedDeclarativeData *>(data):0; + + if(edata) { + QObject *rv = edata->attachedProperties.value(id); + if(rv) + return rv; } - priv->declarativeData = &context->d_func()->contextData; + + QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id); + if(!pf) + return 0; + + QObject *rv = pf(const_cast<QObject *>(object)); + + if(rv) { + if(!edata) { + + edata = new QmlExtendedDeclarativeData; + if(data) edata->context = data->context; + priv->declarativeData = edata; + + } + + edata->attachedProperties.insert(id, rv); + } + + return rv; +} + +void QmlExtendedDeclarativeData::destroyed(QObject *) +{ + delete this; } /*! \internal */ diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 9938022..848c8db 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -173,7 +173,7 @@ void QmlCompiledComponent::dump(QmlInstruction *instr, int idx) qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t" << instr->assignObject.property << "\t" << instr->assignObject.castValue << "\t\t" << ((instr->assignObject.property == -1)?QByteArray("default"):datas.at(instr->assignObject.property)); break; case QmlInstruction::FetchAttached: - qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.idx << "\t\t\t" << primitives.at(instr->fetchAttached.idx); + qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id; break; case QmlInstruction::FetchQmlList: qWarning() << idx << "\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 40a0b84..440b54a 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -280,7 +280,7 @@ public: int count; } createComponent; struct { - int idx; + int id; } fetchAttached; struct { int property; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index e7f7cfb..780f8a8 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -550,7 +550,7 @@ QObject *QmlMetaPropertyPrivate::attachedObject() const if(attachedFunc == -1) return 0; else - return QmlMetaType::attachedPropertiesFuncById(attachedFunc)(object); + return qmlAttachedPropertiesObjectById(attachedFunc, object); } /*! diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 51d5607..c12f01a 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -643,6 +643,18 @@ int QmlMetaType::attachedPropertiesFuncId(const QByteArray &name) return -1; } +int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo) +{ + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + + QmlType *type = data->metaObjectToType.value(mo); + if(type && type->attachedPropertiesFunction()) + return type->index(); + else + return -1; +} + QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id) { if(id < 0) diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 3daa14b..c17d47f 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -90,6 +90,7 @@ public: static const QMetaObject *metaObjectForType(const QByteArray &); static const QMetaObject *metaObjectForType(int); static int attachedPropertiesFuncId(const QByteArray &); + static int attachedPropertiesFuncId(const QMetaObject *); static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int); static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &); diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index b6d9173..62a0864 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -860,14 +860,10 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in #endif QObject *target = stack.top(); - QmlAttachedPropertiesFunc attachFunc = - QmlMetaType::attachedPropertiesFunc(datas.at(instr.fetchAttached.idx)); - if(!attachFunc) - VME_EXCEPTION("No such attached object" << primitives.at(instr.fetchAttached.idx)); + QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); - QObject *qmlObject = attachFunc(target); if(!qmlObject) - VME_EXCEPTION("Internal error - unable to create attached object" << primitives.at(instr.fetchAttached.idx)); + VME_EXCEPTION("Unable to create attached object"); stack.push(qmlObject); } diff --git a/src/declarative/widgets/graphicslayouts.cpp b/src/declarative/widgets/graphicslayouts.cpp index 1ecde71..8e0081b 100644 --- a/src/declarative/widgets/graphicslayouts.cpp +++ b/src/declarative/widgets/graphicslayouts.cpp @@ -150,18 +150,17 @@ void QGraphicsLinearLayoutObject::updateAlignment(QGraphicsLayoutItem *item, Qt: QHash<QGraphicsLayoutItem*, QObject*> QGraphicsLinearLayoutObject::attachedProperties; QObject *QGraphicsLinearLayoutObject::qmlAttachedProperties(QObject *obj) { + // ### This is not allowed - you must attach to any object if (!qobject_cast<QGraphicsLayoutItem*>(obj)) return 0; - if(!attachedProperties.contains(qobject_cast<QGraphicsLayoutItem*>(obj))) { - LinearLayoutAttached *rv = new LinearLayoutAttached(obj); - /*if (QGraphicsLinearLayoutObject *lo = qobject_cast<QGraphicsLinearLayoutObject*>(obj->parent())) - QObject::connect(rv, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)), - lo, SLOT(updateStretch(QGraphicsLayoutItem*,int))); - QObject::connect(rv, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)), - lo, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));*/ - attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv); - } - return attachedProperties.value(qobject_cast<QGraphicsLayoutItem*>(obj)); + LinearLayoutAttached *rv = new LinearLayoutAttached(obj); + /*if (QGraphicsLinearLayoutObject *lo = qobject_cast<QGraphicsLinearLayoutObject*>(obj->parent())) + QObject::connect(rv, SIGNAL(stretchChanged(QGraphicsLayoutItem*,int)), + lo, SLOT(updateStretch(QGraphicsLayoutItem*,int))); + QObject::connect(rv, SIGNAL(alignmentChanged(QGraphicsLayoutItem*,Qt::Alignment)), + lo, SLOT(updateAlignment(QGraphicsLayoutItem*,Qt::Alignment)));*/ + attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv); + return rv; } ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -311,13 +310,12 @@ qreal QGraphicsGridLayoutObject::spacing() const QHash<QGraphicsLayoutItem*, QObject*> QGraphicsGridLayoutObject::attachedProperties; QObject *QGraphicsGridLayoutObject::qmlAttachedProperties(QObject *obj) { + // ### This is not allowed - you must attach to any object if (!qobject_cast<QGraphicsLayoutItem*>(obj)) return 0; - if(!attachedProperties.contains(qobject_cast<QGraphicsLayoutItem*>(obj))) { - GridLayoutAttached *rv = new GridLayoutAttached(obj); - attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv); - } - return attachedProperties.value(qobject_cast<QGraphicsLayoutItem*>(obj)); + GridLayoutAttached *rv = new GridLayoutAttached(obj); + attachedProperties.insert(qobject_cast<QGraphicsLayoutItem*>(obj), rv); + return rv; } QT_END_NAMESPACE |