diff -r 5dc02b23752f -r 3e2da88830cd src/declarative/graphicsitems/qdeclarativeitem.cpp --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp Tue Jul 06 15:10:48 2010 +0300 +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp Wed Aug 18 10:37:55 2010 +0300 @@ -63,12 +63,10 @@ #include #include +#include + QT_BEGIN_NAMESPACE -#ifndef FLT_MAX -#define FLT_MAX 1E+37 -#endif - /*! \qmlclass Transform QGraphicsTransform \since 4.7 @@ -86,20 +84,22 @@ The Transform elements let you create and control advanced transformations that can be configured independently using specialized properties. - You can assign any number of Transform elements to an Item. Each Transform is applied in order, - one at a time, to the Item it's assigned to. + You can assign any number of Transform elements to an \l Item. Each Transform is applied in order, + one at a time. */ /*! - \qmlclass Translate QGraphicsTranslate + \qmlclass Translate QDeclarativeTranslate \since 4.7 \brief The Translate object provides a way to move an Item without changing its x or y properties. The Translate object provides independent control over position in addition to the Item's x and y properties. - The following example moves the Y axis of the Rectangles while still allowing the Row element + The following example moves the Y axis of the \l Rectangle elements while still allowing the \l Row element to lay the items out as if they had not been transformed: \qml + import Qt 4.7 + Row { Rectangle { width: 100; height: 100 @@ -113,6 +113,8 @@ } } \endqml + + \image translate.png */ /*! @@ -130,9 +132,9 @@ /*! \qmlclass Scale QGraphicsScale \since 4.7 - \brief The Scale object provides a way to scale an Item. - - The Scale object gives more control over scaling than using Item's scale property. Specifically, + \brief The Scale element provides a way to scale an Item. + + The Scale element gives more control over scaling than using \l Item's \l{Item::scale}{scale} property. Specifically, it allows a different scale for the x and y axes, and allows the scale to be relative to an arbitrary point. @@ -144,6 +146,8 @@ transform: Scale { origin.x: 25; origin.y: 25; xScale: 3} } \endqml + + \sa Rotation, Translate */ /*! @@ -171,7 +175,7 @@ \since 4.7 \brief The Rotation object provides a way to rotate an Item. - The Rotation object gives more control over rotation than using Item's rotation property. + The Rotation object gives more control over rotation than using \l Item's \l{Item::rotation}{rotation} property. Specifically, it allows (z axis) rotation to be relative to an arbitrary point. The following example rotates a Rectangle around its interior point 25, 25: @@ -190,6 +194,8 @@ \snippet doc/src/snippets/declarative/rotation.qml 0 \image axisrotation.png + + \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example} */ /*! @@ -225,9 +231,10 @@ \brief The QDeclarativeContents class gives access to the height and width of an item's contents. */ - -QDeclarativeContents::QDeclarativeContents() : m_x(0), m_y(0), m_width(0), m_height(0) +QDeclarativeContents::QDeclarativeContents(QDeclarativeItem *item) : m_item(item), m_x(0), m_y(0), m_width(0), m_height(0) { + //### optimize + connect(this, SIGNAL(rectChanged(QRectF)), m_item, SIGNAL(childrenRectChanged(QRectF))); } QDeclarativeContents::~QDeclarativeContents() @@ -322,12 +329,8 @@ emit rectChanged(rectF()); } -void QDeclarativeContents::setItem(QDeclarativeItem *item) +void QDeclarativeContents::complete() { - m_item = item; - //### optimize - connect(this, SIGNAL(rectChanged(QRectF)), m_item, SIGNAL(childrenRectChanged(QRectF))); - QList children = m_item->childItems(); for (int i = 0; i < children.count(); ++i) { QDeclarativeItem *child = qobject_cast(children.at(i)); @@ -337,33 +340,31 @@ //###what about changes to visibility? } - //### defer until componentComplete - calcHeight(); - calcWidth(); + calcGeometry(); } void QDeclarativeContents::itemGeometryChanged(QDeclarativeItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry) { - if (newGeometry.width() != oldGeometry.width()) - calcWidth(changed); - if (newGeometry.height() != oldGeometry.height()) - calcHeight(changed); + Q_UNUSED(changed) + //### we can only pass changed if the left edge has moved left, or the right edge has moved right + if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x()) + calcWidth(/*changed*/); + if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y()) + calcHeight(/*changed*/); } void QDeclarativeContents::itemDestroyed(QDeclarativeItem *item) { if (item) QDeclarativeItemPrivate::get(item)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed); - calcWidth(); - calcHeight(); + calcGeometry(); } void QDeclarativeContents::childRemoved(QDeclarativeItem *item) { if (item) QDeclarativeItemPrivate::get(item)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed); - calcWidth(); - calcHeight(); + calcGeometry(); } void QDeclarativeContents::childAdded(QDeclarativeItem *item) @@ -417,7 +418,7 @@ /*! - \qmlclass KeyNavigation + \qmlclass KeyNavigation QDeclarativeKeyNavigationAttached \since 4.7 \brief The KeyNavigation attached property supports key navigation by arrow keys. @@ -711,7 +712,7 @@ } /*! - \qmlclass Keys + \qmlclass Keys QDeclarativeKeysAttached \since 4.7 \brief The Keys attached property provides key handling to Items. @@ -722,7 +723,7 @@ The signal properties have a \l KeyEvent parameter, named \e event which contains details of the event. If a key is handled \e event.accepted should be set to true to prevent the - event from propagating up the item heirarchy. + event from propagating up the item hierarchy. \code Item { @@ -1385,26 +1386,6 @@ */ /*! - \property QDeclarativeItem::baseline - \internal -*/ - -/*! - \property QDeclarativeItem::focus - \internal -*/ - -/*! - \property QDeclarativeItem::wantsFocus - \internal -*/ - -/*! - \property QDeclarativeItem::transformOrigin - \internal -*/ - -/*! \fn void QDeclarativeItem::childrenRectChanged(const QRectF &) \internal */ @@ -1449,7 +1430,7 @@ */ /*! - \fn void QDeclarativeItem::wantsFocusChanged(bool) + \fn void QDeclarativeItem::activeFocusChanged(bool) \internal */ @@ -1531,6 +1512,9 @@ \endqml The default transform origin is \c Item.Center. + + To set an arbitrary transform origin point use the \l Scale or \l Rotation + transform elements. */ /*! @@ -1598,7 +1582,7 @@ Returns true if construction of the QML component is complete; otherwise returns false. - It is often desireable to delay some processing until the component is + It is often desirable to delay some processing until the component is completed. \sa componentComplete() @@ -1606,7 +1590,7 @@ bool QDeclarativeItem::isComponentComplete() const { Q_D(const QDeclarativeItem); - return d->_componentComplete; + return d->componentComplete; } void QDeclarativeItemPrivate::data_append(QDeclarativeListProperty *prop, QObject *o) @@ -1629,7 +1613,7 @@ QObject *QDeclarativeItemPrivate::resources_at(QDeclarativeListProperty *prop, int index) { - QObjectList children = prop->object->children(); + const QObjectList children = prop->object->children(); if (index < children.count()) return children.at(index); else @@ -1746,8 +1730,9 @@ { Q_D(QDeclarativeItem); if (!d->_contents) { - d->_contents = new QDeclarativeContents; - d->_contents->setItem(this); + d->_contents = new QDeclarativeContents(this); + if (d->componentComplete) + d->_contents->complete(); } return d->_contents->rectF(); } @@ -1966,6 +1951,9 @@ return v; } +/*! + \internal + */ void QDeclarativeItem::keyPressPreHandler(QKeyEvent *event) { Q_D(QDeclarativeItem); @@ -1976,6 +1964,9 @@ d->doneEventPreHandler = true; } +/*! + \internal + */ void QDeclarativeItem::keyReleasePreHandler(QKeyEvent *event) { Q_D(QDeclarativeItem); @@ -1986,6 +1977,9 @@ d->doneEventPreHandler = true; } +/*! + \internal + */ void QDeclarativeItem::inputMethodPreHandler(QInputMethodEvent *event) { Q_D(QDeclarativeItem); @@ -1996,7 +1990,6 @@ d->doneEventPreHandler = true; } - /*! \internal */ @@ -2055,20 +2048,6 @@ } /*! - \qmlproperty AnchorLine Item::top - \qmlproperty AnchorLine Item::bottom - \qmlproperty AnchorLine Item::left - \qmlproperty AnchorLine Item::right - \qmlproperty AnchorLine Item::horizontalCenter - \qmlproperty AnchorLine Item::verticalCenter - \qmlproperty AnchorLine Item::baseline - - The anchor lines of the item. - - For more information see \l {anchor-layout}{Anchor Layouts}. -*/ - -/*! \qmlproperty AnchorLine Item::anchors.top \qmlproperty AnchorLine Item::anchors.bottom \qmlproperty AnchorLine Item::anchors.left @@ -2093,7 +2072,7 @@ relationship with other items. Margins apply to top, bottom, left, right, and fill anchors. - The margins property can be used to set all of the various margins at once, to the same value. + The \c anchors.margins property can be used to set all of the various margins at once, to the same value. Offsets apply for horizontal center, vertical center, and baseline anchors. @@ -2128,10 +2107,12 @@ \endqml \endtable - anchors.fill provides a convenient way for one item to have the + \c anchors.fill provides a convenient way for one item to have the same geometry as another item, and is equivalent to connecting all four directional anchors. + To clear an anchor value, set it to \c undefined. + \note You can only anchor an item to siblings or a parent. For more information see \l {anchor-layout}{Anchor Layouts}. @@ -2141,7 +2122,7 @@ \property QDeclarativeItem::baselineOffset \brief The position of the item's baseline in local coordinates. - The baseline of a Text item is the imaginary line on which the text + The baseline of a \l Text item is the imaginary line on which the text sits. Controls containing text usually set their baseline to the baseline of their text. @@ -2150,19 +2131,19 @@ qreal QDeclarativeItem::baselineOffset() const { Q_D(const QDeclarativeItem); - if (!d->_baselineOffset.isValid()) { + if (!d->baselineOffset.isValid()) { return 0.0; } else - return d->_baselineOffset; + return d->baselineOffset; } void QDeclarativeItem::setBaselineOffset(qreal offset) { Q_D(QDeclarativeItem); - if (offset == d->_baselineOffset) + if (offset == d->baselineOffset) return; - d->_baselineOffset = offset; + d->baselineOffset = offset; for(int ii = 0; ii < d->changeListeners.count(); ++ii) { const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); @@ -2198,6 +2179,8 @@ } \endqml \endtable + + \sa transform, Rotation */ /*! @@ -2234,6 +2217,8 @@ } \endqml \endtable + + \sa transform, Scale */ /*! @@ -2291,7 +2276,7 @@ bool QDeclarativeItem::keepMouseGrab() const { Q_D(const QDeclarativeItem); - return d->_keepMouse; + return d->keepMouse; } /*! @@ -2315,7 +2300,7 @@ void QDeclarativeItem::setKeepMouseGrab(bool keep) { Q_D(QDeclarativeItem); - d->_keepMouse = keep; + d->keepMouse = keep; } /*! @@ -2371,12 +2356,12 @@ } /*! - \qmlmethod Item::forceFocus() - - Force the focus on the item. - This method sets the focus on the item and makes sure that all the focus scopes higher in the object hierarchy are given focus. + \qmlmethod Item::forceActiveFocus() + + Force active focus on the item. + This method sets focus on the item and makes sure that all the focus scopes higher in the object hierarchy are also given focus. */ -void QDeclarativeItem::forceFocus() +void QDeclarativeItem::forceActiveFocus() { setFocus(true); QGraphicsItem *parent = parentItem(); @@ -2387,10 +2372,45 @@ } } + +/*! + \qmlmethod Item::childAt(real x, real y) + + Returns the visible child item at point (\a x, \a y), which is in this + item's coordinate system, or \c null if there is no such item. + */ +QDeclarativeItem *QDeclarativeItem::childAt(qreal x, qreal y) const +{ + const QList children = childItems(); + for (int i = children.count()-1; i >= 0; --i) { + if (QDeclarativeItem *child = qobject_cast(children.at(i))) { + if (child->isVisible() && child->x() <= x + && child->x() + child->width() >= x + && child->y() <= y + && child->y() + child->height() >= y) + return child; + } + } + return 0; +} + void QDeclarativeItemPrivate::focusChanged(bool flag) { Q_Q(QDeclarativeItem); - emit q->focusChanged(flag); + if (!(flags & QGraphicsItem::ItemIsFocusScope) && parent) + emit q->activeFocusChanged(flag); //see also QDeclarativeItemPrivate::subFocusItemChange() + + bool inScope = false; + QGraphicsItem *p = parent; + while (p) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + inScope = true; + break; + } + p = p->parentItem(); + } + if (!inScope) + emit q->focusChanged(flag); } /*! \internal */ @@ -2473,7 +2493,7 @@ \qmlproperty bool Item::clip This property holds whether clipping is enabled. - if clipping is enabled, an item will clip its own painting, as well + If clipping is enabled, an item will clip its own painting, as well as the painting of its children, to its bounding rectangle. Non-rectangular clipping regions are not supported for performance reasons. @@ -2513,11 +2533,6 @@ \sa {qmlstates}{States} */ -/*! - \property QDeclarativeItem::state - \internal -*/ - /*! \internal */ QString QDeclarativeItemPrivate::state() const { @@ -2540,11 +2555,6 @@ For more information see \l Transform. */ -/*! - \property QDeclarativeItem::transform - \internal -*/ - /*! \internal */ QDeclarativeListProperty QDeclarativeItem::transform() { @@ -2564,7 +2574,7 @@ void QDeclarativeItem::classBegin() { Q_D(QDeclarativeItem); - d->_componentComplete = false; + d->componentComplete = false; if (d->_stateGroup) d->_stateGroup->classBegin(); if (d->_anchors) @@ -2575,14 +2585,14 @@ \internal componentComplete() is called when all items in the component - have been constructed. It is often desireable to delay some + have been constructed. It is often desirable to delay some processing until the component is complete an all bindings in the component have been resolved. */ void QDeclarativeItem::componentComplete() { Q_D(QDeclarativeItem); - d->_componentComplete = true; + d->componentComplete = true; if (d->_stateGroup) d->_stateGroup->componentComplete(); if (d->_anchors) { @@ -2591,6 +2601,8 @@ } if (d->keyHandler) d->keyHandler->componentComplete(); + if (d->_contents) + d->_contents->complete(); } QDeclarativeStateGroup *QDeclarativeItemPrivate::_states() @@ -2598,7 +2610,7 @@ Q_Q(QDeclarativeItem); if (!_stateGroup) { _stateGroup = new QDeclarativeStateGroup; - if (!_componentComplete) + if (!componentComplete) _stateGroup->classBegin(); QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)), q, SIGNAL(stateChanged(QString))); @@ -2675,14 +2687,14 @@ if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) { - d->focusChanged(hasFocus()); + d->focusChanged(hasActiveFocus()); } return rv; } } /*! - \reimp + \internal Note that unlike QGraphicsItems, QDeclarativeItem::itemChange() is \e not called during initial widget polishing. Items wishing to optimize start-up construction @@ -2831,6 +2843,26 @@ } /*! + \property QDeclarativeItem::focus + \internal +*/ + +/*! + \property QDeclarativeItem::transform + \internal +*/ + +/*! + \property QDeclarativeItem::transformOrigin + \internal +*/ + +/*! + \property QDeclarativeItem::activeFocus + \internal +*/ + +/*! \internal Return the width of the item */ @@ -3069,31 +3101,86 @@ } /*! - \qmlproperty bool Item::wantsFocus - - This property indicates whether the item has has an active focus request. - - \sa {qmlfocus}{Keyboard Focus} + \qmlproperty bool Item::activeFocus + + This property indicates whether the item has active focus. + + An item with active focus will receive keyboard input, + or is a FocusScope ancestor of the item that will receive keyboard input. + + Usually, activeFocus is gained by setting focus on an item and its enclosing + FocusScopes. In the following example \c input will have activeFocus. + \qml + Rectangle { + FocusScope { + focus: true + TextInput { + id: input + focus: true + } + } + } + \endqml + + \sa focus, {qmlfocus}{Keyboard Focus} */ /*! \internal */ -bool QDeclarativeItem::wantsFocus() const +bool QDeclarativeItem::hasActiveFocus() const { - return focusItem() != 0; + Q_D(const QDeclarativeItem); + return focusItem() == this || + (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0) || + (!parentItem() && focusItem() != 0); } /*! \qmlproperty bool Item::focus - This property indicates whether the item has keyboard input focus. Set this - property to true to request focus. - - \sa {qmlfocus}{Keyboard Focus} + This property indicates whether the item has focus within the enclosing focus scope. If true, this item + will gain active focus when the enclosing focus scope gains active focus. + In the following example, \c input will be given active focus when \c scope gains active focus. + \qml + Rectangle { + FocusScope { + id: scope + TextInput { + id: input + focus: true + } + } + } + \endqml + + For the purposes of this property, the top level item in the scene + is assumed to act like a focus scope, and to always have active focus + when the scene has focus. On a practical level, that means the following + QML will give active focus to \c input on startup. + + \qml + Rectangle { + TextInput { + id: input + focus: true + } + } + \endqml + + \sa activeFocus, {qmlfocus}{Keyboard Focus} */ /*! \internal */ bool QDeclarativeItem::hasFocus() const { - return QGraphicsItem::hasFocus(); + Q_D(const QDeclarativeItem); + QGraphicsItem *p = d->parent; + while (p) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + return p->focusScopeItem() == this; + } + p = p->parentItem(); + } + + return hasActiveFocus() ? true : (!QGraphicsItem::parentItem() ? true : false); } /*! \internal */ @@ -3131,6 +3218,7 @@ return QGraphicsObject::event(ev); } +#ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, QDeclarativeItem *item) { if (!item) { @@ -3144,42 +3232,58 @@ << ", z =" << item->zValue() << ')'; return debug; } - -int QDeclarativeItemPrivate::consistentTime = -1; -void QDeclarativeItemPrivate::setConsistentTime(int t) +#endif + +qint64 QDeclarativeItemPrivate::consistentTime = -1; +void QDeclarativeItemPrivate::setConsistentTime(qint64 t) { consistentTime = t; } -QTime QDeclarativeItemPrivate::currentTime() -{ - if (consistentTime == -1) - return QTime::currentTime(); - else - return QTime(0, 0).addMSecs(consistentTime); -} - -void QDeclarativeItemPrivate::start(QTime &t) -{ - t = currentTime(); -} - -int QDeclarativeItemPrivate::elapsed(QTime &t) +class QElapsedTimerConsistentTimeHack { - int n = t.msecsTo(currentTime()); - if (n < 0) // passed midnight - n += 86400 * 1000; - return n; +public: + void start() { + t1 = QDeclarativeItemPrivate::consistentTime; + t2 = 0; + } + qint64 elapsed() { + return QDeclarativeItemPrivate::consistentTime - t1; + } + qint64 restart() { + qint64 val = QDeclarativeItemPrivate::consistentTime - t1; + t1 = QDeclarativeItemPrivate::consistentTime; + t2 = 0; + return val; + } + +private: + qint64 t1; + qint64 t2; +}; + +void QDeclarativeItemPrivate::start(QElapsedTimer &t) +{ + if (QDeclarativeItemPrivate::consistentTime == -1) + t.start(); + else + ((QElapsedTimerConsistentTimeHack*)&t)->start(); } -int QDeclarativeItemPrivate::restart(QTime &t) +qint64 QDeclarativeItemPrivate::elapsed(QElapsedTimer &t) { - QTime time = currentTime(); - int n = t.msecsTo(time); - if (n < 0) // passed midnight - n += 86400*1000; - t = time; - return n; + if (QDeclarativeItemPrivate::consistentTime == -1) + return t.elapsed(); + else + return ((QElapsedTimerConsistentTimeHack*)&t)->elapsed(); +} + +qint64 QDeclarativeItemPrivate::restart(QElapsedTimer &t) +{ + if (QDeclarativeItemPrivate::consistentTime == -1) + return t.restart(); + else + return ((QElapsedTimerConsistentTimeHack*)&t)->restart(); } QT_END_NAMESPACE