| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtDeclarative 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 "qdeclarativeitem.h" |
| |
| #include "private/qdeclarativeevents_p_p.h" |
| #include <private/qdeclarativeengine_p.h> |
| #include <private/qgraphicsitem_p.h> |
| #include <QtDeclarative/private/qdeclarativeitem_p.h> |
| |
| #include <qdeclarativeengine.h> |
| #include <qdeclarativeopenmetaobject_p.h> |
| #include <qdeclarativestate_p.h> |
| #include <qdeclarativeview.h> |
| #include <qdeclarativestategroup_p.h> |
| #include <qdeclarativecomponent.h> |
| #include <qdeclarativeinfo.h> |
| |
| #include <QDebug> |
| #include <QPen> |
| #include <QEvent> |
| #include <QGraphicsSceneMouseEvent> |
| #include <QtCore/qnumeric.h> |
| #include <QtScript/qscriptengine.h> |
| #include <QtGui/qgraphicstransform.h> |
| #include <qlistmodelinterface_p.h> |
| |
| #include <float.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| \qmlclass Transform QGraphicsTransform |
| \ingroup qml-transform-elements |
| \since 4.7 |
| \brief The Transform elements provide a way of building advanced transformations on Items. |
| |
| The Transform element is a base type which cannot be instantiated directly. |
| The following concrete Transform types are available: |
| |
| \list |
| \o \l Rotation |
| \o \l Scale |
| \o \l Translate |
| \endlist |
| |
| 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 \l Item. Each Transform is applied in order, |
| one at a time. |
| */ |
| |
| /*! |
| \qmlclass Translate QDeclarativeTranslate |
| \ingroup qml-transform-elements |
| \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 \l Rectangle elements while still allowing the \l Row element |
| to lay the items out as if they had not been transformed: |
| \qml |
| import QtQuick 1.0 |
| |
| Row { |
| Rectangle { |
| width: 100; height: 100 |
| color: "blue" |
| transform: Translate { y: 20 } |
| } |
| Rectangle { |
| width: 100; height: 100 |
| color: "red" |
| transform: Translate { y: -20 } |
| } |
| } |
| \endqml |
| |
| \image translate.png |
| */ |
| |
| /*! |
| \qmlproperty real Translate::x |
| |
| The translation along the X axis. |
| */ |
| |
| /*! |
| \qmlproperty real Translate::y |
| |
| The translation along the Y axis. |
| */ |
| |
| /*! |
| \qmlclass Scale QGraphicsScale |
| \ingroup qml-transform-elements |
| \since 4.7 |
| \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. |
| |
| The following example scales the X axis of the Rectangle, relative to its interior point 25, 25: |
| \qml |
| Rectangle { |
| width: 100; height: 100 |
| color: "blue" |
| transform: Scale { origin.x: 25; origin.y: 25; xScale: 3} |
| } |
| \endqml |
| |
| \sa Rotation, Translate |
| */ |
| |
| /*! |
| \qmlproperty real Scale::origin.x |
| \qmlproperty real Scale::origin.y |
| |
| The point that the item is scaled from (i.e., the point that stays fixed relative to the parent as |
| the rest of the item grows). By default the origin is 0, 0. |
| */ |
| |
| /*! |
| \qmlproperty real Scale::xScale |
| |
| The scaling factor for the X axis. |
| */ |
| |
| /*! |
| \qmlproperty real Scale::yScale |
| |
| The scaling factor for the Y axis. |
| */ |
| |
| /*! |
| \qmlclass Rotation QGraphicsRotation |
| \ingroup qml-transform-elements |
| \since 4.7 |
| \brief The Rotation object provides a way to rotate an Item. |
| |
| 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: |
| \qml |
| Rectangle { |
| width: 100; height: 100 |
| color: "blue" |
| transform: Rotation { origin.x: 25; origin.y: 25; angle: 45} |
| } |
| \endqml |
| |
| Rotation also provides a way to specify 3D-like rotations for Items. For these types of |
| rotations you must specify the axis to rotate around in addition to the origin point. |
| |
| The following example shows various 3D-like rotations applied to an \l Image. |
| \snippet doc/src/snippets/declarative/rotation.qml 0 |
| |
| \image axisrotation.png |
| |
| \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example} |
| */ |
| |
| /*! |
| \qmlproperty real Rotation::origin.x |
| \qmlproperty real Rotation::origin.y |
| |
| The origin point of the rotation (i.e., the point that stays fixed relative to the parent as |
| the rest of the item rotates). By default the origin is 0, 0. |
| */ |
| |
| /*! |
| \qmlproperty real Rotation::axis.x |
| \qmlproperty real Rotation::axis.y |
| \qmlproperty real Rotation::axis.z |
| |
| The axis to rotate around. For simple (2D) rotation around a point, you do not need to specify an axis, |
| as the default axis is the z axis (\c{ axis { x: 0; y: 0; z: 1 } }). |
| |
| For a typical 3D-like rotation you will usually specify both the origin and the axis. |
| |
| \image 3d-rotation-axis.png |
| */ |
| |
| /*! |
| \qmlproperty real Rotation::angle |
| |
| The angle to rotate, in degrees clockwise. |
| */ |
| |
| 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() |
| { |
| QList<QGraphicsItem *> children = m_item->childItems(); |
| for (int i = 0; i < children.count(); ++i) { |
| QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i)); |
| if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects? |
| continue; |
| QDeclarativeItemPrivate::get(child)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed); |
| } |
| } |
| |
| QRectF QDeclarativeContents::rectF() const |
| { |
| return QRectF(m_x, m_y, m_width, m_height); |
| } |
| |
| void QDeclarativeContents::calcHeight(QDeclarativeItem *changed) |
| { |
| qreal oldy = m_y; |
| qreal oldheight = m_height; |
| |
| if (changed) { |
| qreal top = oldy; |
| qreal bottom = oldy + oldheight; |
| qreal y = changed->y(); |
| if (y + changed->height() > bottom) |
| bottom = y + changed->height(); |
| if (y < top) |
| top = y; |
| m_y = top; |
| m_height = bottom - top; |
| } else { |
| qreal top = FLT_MAX; |
| qreal bottom = 0; |
| QList<QGraphicsItem *> children = m_item->childItems(); |
| for (int i = 0; i < children.count(); ++i) { |
| QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i)); |
| if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects? |
| continue; |
| qreal y = child->y(); |
| if (y + child->height() > bottom) |
| bottom = y + child->height(); |
| if (y < top) |
| top = y; |
| } |
| if (!children.isEmpty()) |
| m_y = top; |
| m_height = qMax(bottom - top, qreal(0.0)); |
| } |
| |
| if (m_height != oldheight || m_y != oldy) |
| emit rectChanged(rectF()); |
| } |
| |
| void QDeclarativeContents::calcWidth(QDeclarativeItem *changed) |
| { |
| qreal oldx = m_x; |
| qreal oldwidth = m_width; |
| |
| if (changed) { |
| qreal left = oldx; |
| qreal right = oldx + oldwidth; |
| qreal x = changed->x(); |
| if (x + changed->width() > right) |
| right = x + changed->width(); |
| if (x < left) |
| left = x; |
| m_x = left; |
| m_width = right - left; |
| } else { |
| qreal left = FLT_MAX; |
| qreal right = 0; |
| QList<QGraphicsItem *> children = m_item->childItems(); |
| for (int i = 0; i < children.count(); ++i) { |
| QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i)); |
| if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects? |
| continue; |
| qreal x = child->x(); |
| if (x + child->width() > right) |
| right = x + child->width(); |
| if (x < left) |
| left = x; |
| } |
| if (!children.isEmpty()) |
| m_x = left; |
| m_width = qMax(right - left, qreal(0.0)); |
| } |
| |
| if (m_width != oldwidth || m_x != oldx) |
| emit rectChanged(rectF()); |
| } |
| |
| void QDeclarativeContents::complete() |
| { |
| QList<QGraphicsItem *> children = m_item->childItems(); |
| for (int i = 0; i < children.count(); ++i) { |
| QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i)); |
| if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects? |
| continue; |
| QDeclarativeItemPrivate::get(child)->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed); |
| //###what about changes to visibility? |
| } |
| |
| calcGeometry(); |
| } |
| |
| void QDeclarativeContents::itemGeometryChanged(QDeclarativeItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry) |
| { |
| 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); |
| calcGeometry(); |
| } |
| |
| void QDeclarativeContents::childRemoved(QDeclarativeItem *item) |
| { |
| if (item) |
| QDeclarativeItemPrivate::get(item)->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed); |
| calcGeometry(); |
| } |
| |
| void QDeclarativeContents::childAdded(QDeclarativeItem *item) |
| { |
| if (item) |
| QDeclarativeItemPrivate::get(item)->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry | QDeclarativeItemPrivate::Destroyed); |
| calcWidth(item); |
| calcHeight(item); |
| } |
| |
| QDeclarativeItemKeyFilter::QDeclarativeItemKeyFilter(QDeclarativeItem *item) |
| : m_processPost(false), m_next(0) |
| { |
| QDeclarativeItemPrivate *p = |
| item?static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(item)):0; |
| if (p) { |
| m_next = p->keyHandler; |
| p->keyHandler = this; |
| } |
| } |
| |
| QDeclarativeItemKeyFilter::~QDeclarativeItemKeyFilter() |
| { |
| } |
| |
| void QDeclarativeItemKeyFilter::keyPressed(QKeyEvent *event, bool post) |
| { |
| if (m_next) m_next->keyPressed(event, post); |
| } |
| |
| void QDeclarativeItemKeyFilter::keyReleased(QKeyEvent *event, bool post) |
| { |
| if (m_next) m_next->keyReleased(event, post); |
| } |
| |
| void QDeclarativeItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post) |
| { |
| if (m_next) m_next->inputMethodEvent(event, post); |
| } |
| |
| QVariant QDeclarativeItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const |
| { |
| if (m_next) return m_next->inputMethodQuery(query); |
| return QVariant(); |
| } |
| |
| void QDeclarativeItemKeyFilter::componentComplete() |
| { |
| if (m_next) m_next->componentComplete(); |
| } |
| |
| |
| /*! |
| \qmlclass KeyNavigation QDeclarativeKeyNavigationAttached |
| \ingroup qml-basic-interaction-elements |
| \since 4.7 |
| \brief The KeyNavigation attached property supports key navigation by arrow keys. |
| |
| Key-based user interfaces commonly allow the use of arrow keys to navigate between |
| focusable items. The KeyNavigation attached property enables this behavior by providing a |
| convenient way to specify the item that should gain focus when an arrow or tab key is pressed. |
| |
| The following example provides key navigation for a 2x2 grid of items: |
| |
| \snippet doc/src/snippets/declarative/keynavigation.qml 0 |
| |
| The top-left item initially receives focus by setting \l {Item::}{focus} to |
| \c true. When an arrow key is pressed, the focus will move to the |
| appropriate item, as defined by the value that has been set for |
| the KeyNavigation \l left, \l right, \l up or \l down properties. |
| |
| Note that if a KeyNavigation attached property receives the key press and release |
| events for a requested arrow or tab key, the event is accepted and does not |
| propagate any further. |
| |
| By default, KeyNavigation receives key events after the item to which it is attached. |
| If the item accepts the key event, the KeyNavigation attached property will not |
| receive an event for that key. Setting the \l priority property to |
| \c KeyNavigation.BeforeItem allows the event to be used for key navigation |
| before the item, rather than after. |
| |
| If item to which the focus is switching is not enabled or visible, an attempt will |
| be made to skip this item and focus on the next. This is possible if there are |
| a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled |
| or visible, they will also be skipped. |
| |
| \sa {Keys}{Keys attached property} |
| */ |
| |
| /*! |
| \qmlproperty Item KeyNavigation::left |
| \qmlproperty Item KeyNavigation::right |
| \qmlproperty Item KeyNavigation::up |
| \qmlproperty Item KeyNavigation::down |
| \qmlproperty Item KeyNavigation::tab |
| \qmlproperty Item KeyNavigation::backtab |
| |
| These properties hold the item to assign focus to |
| when the left, right, up or down cursor keys, or the |
| tab key are pressed. |
| */ |
| |
| /*! |
| \qmlproperty Item KeyNavigation::tab |
| \qmlproperty Item KeyNavigation::backtab |
| |
| These properties hold the item to assign focus to |
| when the Tab key or Shift+Tab key combination (Backtab) are pressed. |
| */ |
| |
| QDeclarativeKeyNavigationAttached::QDeclarativeKeyNavigationAttached(QObject *parent) |
| : QObject(*(new QDeclarativeKeyNavigationAttachedPrivate), parent), |
| QDeclarativeItemKeyFilter(qobject_cast<QDeclarativeItem*>(parent)) |
| { |
| m_processPost = true; |
| } |
| |
| QDeclarativeKeyNavigationAttached * |
| QDeclarativeKeyNavigationAttached::qmlAttachedProperties(QObject *obj) |
| { |
| return new QDeclarativeKeyNavigationAttached(obj); |
| } |
| |
| QDeclarativeItem *QDeclarativeKeyNavigationAttached::left() const |
| { |
| Q_D(const QDeclarativeKeyNavigationAttached); |
| return d->left; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setLeft(QDeclarativeItem *i) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| if (d->left == i) |
| return; |
| d->left = i; |
| emit leftChanged(); |
| } |
| |
| QDeclarativeItem *QDeclarativeKeyNavigationAttached::right() const |
| { |
| Q_D(const QDeclarativeKeyNavigationAttached); |
| return d->right; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setRight(QDeclarativeItem *i) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| if (d->right == i) |
| return; |
| d->right = i; |
| emit rightChanged(); |
| } |
| |
| QDeclarativeItem *QDeclarativeKeyNavigationAttached::up() const |
| { |
| Q_D(const QDeclarativeKeyNavigationAttached); |
| return d->up; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setUp(QDeclarativeItem *i) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| if (d->up == i) |
| return; |
| d->up = i; |
| emit upChanged(); |
| } |
| |
| QDeclarativeItem *QDeclarativeKeyNavigationAttached::down() const |
| { |
| Q_D(const QDeclarativeKeyNavigationAttached); |
| return d->down; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setDown(QDeclarativeItem *i) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| if (d->down == i) |
| return; |
| d->down = i; |
| emit downChanged(); |
| } |
| |
| QDeclarativeItem *QDeclarativeKeyNavigationAttached::tab() const |
| { |
| Q_D(const QDeclarativeKeyNavigationAttached); |
| return d->tab; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setTab(QDeclarativeItem *i) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| if (d->tab == i) |
| return; |
| d->tab = i; |
| emit tabChanged(); |
| } |
| |
| QDeclarativeItem *QDeclarativeKeyNavigationAttached::backtab() const |
| { |
| Q_D(const QDeclarativeKeyNavigationAttached); |
| return d->backtab; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setBacktab(QDeclarativeItem *i) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| if (d->backtab == i) |
| return; |
| d->backtab = i; |
| emit backtabChanged(); |
| } |
| |
| /*! |
| \qmlproperty enumeration KeyNavigation::priority |
| |
| This property determines whether the keys are processed before |
| or after the attached item's own key handling. |
| |
| \list |
| \o KeyNavigation.BeforeItem - process the key events before normal |
| item key processing. If the event is used for key navigation, it will be accepted and will not |
| be passed on to the item. |
| \o KeyNavigation.AfterItem (default) - process the key events after normal item key |
| handling. If the item accepts the key event it will not be |
| handled by the KeyNavigation attached property handler. |
| \endlist |
| */ |
| QDeclarativeKeyNavigationAttached::Priority QDeclarativeKeyNavigationAttached::priority() const |
| { |
| return m_processPost ? AfterItem : BeforeItem; |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setPriority(Priority order) |
| { |
| bool processPost = order == AfterItem; |
| if (processPost != m_processPost) { |
| m_processPost = processPost; |
| emit priorityChanged(); |
| } |
| } |
| |
| void QDeclarativeKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| event->ignore(); |
| |
| if (post != m_processPost) { |
| QDeclarativeItemKeyFilter::keyPressed(event, post); |
| return; |
| } |
| |
| bool mirror = false; |
| switch(event->key()) { |
| case Qt::Key_Left: { |
| if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent())) |
| mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror; |
| QDeclarativeItem* leftItem = mirror ? d->right : d->left; |
| if (leftItem) { |
| setFocusNavigation(leftItem, mirror ? "right" : "left"); |
| event->accept(); |
| } |
| break; |
| } |
| case Qt::Key_Right: { |
| if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent())) |
| mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror; |
| QDeclarativeItem* rightItem = mirror ? d->left : d->right; |
| if (rightItem) { |
| setFocusNavigation(rightItem, mirror ? "left" : "right"); |
| event->accept(); |
| } |
| break; |
| } |
| case Qt::Key_Up: |
| if (d->up) { |
| setFocusNavigation(d->up, "up"); |
| event->accept(); |
| } |
| break; |
| case Qt::Key_Down: |
| if (d->down) { |
| setFocusNavigation(d->down, "down"); |
| event->accept(); |
| } |
| break; |
| case Qt::Key_Tab: |
| if (d->tab) { |
| setFocusNavigation(d->tab, "tab"); |
| event->accept(); |
| } |
| break; |
| case Qt::Key_Backtab: |
| if (d->backtab) { |
| setFocusNavigation(d->backtab, "backtab"); |
| event->accept(); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event, post); |
| } |
| |
| void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post) |
| { |
| Q_D(QDeclarativeKeyNavigationAttached); |
| event->ignore(); |
| |
| if (post != m_processPost) { |
| QDeclarativeItemKeyFilter::keyReleased(event, post); |
| return; |
| } |
| |
| bool mirror = false; |
| switch(event->key()) { |
| case Qt::Key_Left: |
| if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent())) |
| mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror; |
| if (mirror ? d->right : d->left) |
| event->accept(); |
| break; |
| case Qt::Key_Right: |
| if (QDeclarativeItem *parentItem = qobject_cast<QDeclarativeItem*>(parent())) |
| mirror = QDeclarativeItemPrivate::get(parentItem)->effectiveLayoutMirror; |
| if (mirror ? d->left : d->right) |
| event->accept(); |
| break; |
| case Qt::Key_Up: |
| if (d->up) { |
| event->accept(); |
| } |
| break; |
| case Qt::Key_Down: |
| if (d->down) { |
| event->accept(); |
| } |
| break; |
| case Qt::Key_Tab: |
| if (d->tab) { |
| event->accept(); |
| } |
| break; |
| case Qt::Key_Backtab: |
| if (d->backtab) { |
| event->accept(); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post); |
| } |
| |
| void QDeclarativeKeyNavigationAttached::setFocusNavigation(QDeclarativeItem *currentItem, const char *dir) |
| { |
| QDeclarativeItem *initialItem = currentItem; |
| bool isNextItem = false; |
| do { |
| isNextItem = false; |
| if (currentItem->isVisible() && currentItem->isEnabled()) { |
| currentItem->setFocus(true); |
| } else { |
| QObject *attached = |
| qmlAttachedPropertiesObject<QDeclarativeKeyNavigationAttached>(currentItem, false); |
| if (attached) { |
| QDeclarativeItem *tempItem = qvariant_cast<QDeclarativeItem*>(attached->property(dir)); |
| if (tempItem) { |
| currentItem = tempItem; |
| isNextItem = true; |
| } |
| } |
| } |
| } |
| while (currentItem != initialItem && isNextItem); |
| } |
| |
| /*! |
| \qmlclass LayoutMirroring QDeclarativeLayoutMirroringAttached |
| \since QtQuick 1.1 |
| \ingroup qml-utility-elements |
| \brief The LayoutMirroring attached property is used to mirror layout behavior. |
| |
| The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors}, |
| \l{Using QML Positioner and Repeater Items}{positioner} elements (such as \l Row and \l Grid) |
| and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left |
| anchors become right anchors, and positioner elements like \l Grid and \l Row reverse the |
| horizontal layout of child items. |
| |
| Mirroring is enabled for an item by setting the \l enabled property to true. By default, this |
| only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring |
| behavior to all child elements as well. If the \c LayoutMirroring attached property has not been defined |
| for an item, mirroring is not enabled. |
| |
| The following example shows mirroring in action. The \l Row below is specified as being anchored |
| to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally |
| reversed and it is now anchored to the right. Also, since items in a \l Row are positioned |
| from left to right by default, they are now positioned from right to left instead, as demonstrated |
| by the numbering and opacity of the items: |
| |
| \snippet doc/src/snippets/declarative/layoutmirroring.qml 0 |
| |
| \image layoutmirroring.png |
| |
| Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left |
| layout versions of an application to target different language areas. The \l childrenInherit |
| property allows layout mirroring to be applied without manually setting layout configurations |
| for every item in an application. Keep in mind, however, that mirroring does not affect any |
| positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with |
| mirroring enabled, it will often be necessary to apply some layout fixes to support the |
| desired layout direction. Also, it may be necessary to disable the mirroring of individual |
| child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if |
| mirroring is not the desired behavior, or if the child item already implements mirroring in |
| some custom way. |
| |
| See \l {QML Right-to-left User Interfaces} for further details on using \c LayoutMirroring and |
| other related features to implement right-to-left support for an application. |
| */ |
| |
| /*! |
| \qmlproperty bool LayoutMirroring::enabled |
| |
| This property holds whether the item's layout is mirrored horizontally. Setting this to true |
| horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right, |
| and right anchors become left. For \l{Using QML Positioner and Repeater Items}{positioner} elements |
| (such as \l Row and \l Grid) and view elements (such as \l {GridView}{GridView} and \l {ListView}{ListView}) |
| this also mirrors the horizontal layout direction of the item. |
| |
| The default value is false. |
| */ |
| |
| /*! |
| \qmlproperty bool LayoutMirroring::childrenInherit |
| |
| This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item |
| is inherited by its children. |
| |
| The default value is false. |
| */ |
| |
| QDeclarativeLayoutMirroringAttached::QDeclarativeLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0) |
| { |
| if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent)) { |
| itemPrivate = QDeclarativeItemPrivate::get(item); |
| itemPrivate->attachedLayoutDirection = this; |
| } else |
| qmlInfo(parent) << tr("LayoutDirection attached property only works with Items"); |
| } |
| |
| QDeclarativeLayoutMirroringAttached * QDeclarativeLayoutMirroringAttached::qmlAttachedProperties(QObject *object) |
| { |
| return new QDeclarativeLayoutMirroringAttached(object); |
| } |
| |
| bool QDeclarativeLayoutMirroringAttached::enabled() const |
| { |
| return itemPrivate ? itemPrivate->effectiveLayoutMirror : false; |
| } |
| |
| void QDeclarativeLayoutMirroringAttached::setEnabled(bool enabled) |
| { |
| if (!itemPrivate) |
| return; |
| |
| itemPrivate->isMirrorImplicit = false; |
| if (enabled != itemPrivate->effectiveLayoutMirror) { |
| itemPrivate->setLayoutMirror(enabled); |
| if (itemPrivate->inheritMirrorFromItem) |
| itemPrivate->resolveLayoutMirror(); |
| } |
| } |
| |
| void QDeclarativeLayoutMirroringAttached::resetEnabled() |
| { |
| if (itemPrivate && !itemPrivate->isMirrorImplicit) { |
| itemPrivate->isMirrorImplicit = true; |
| itemPrivate->resolveLayoutMirror(); |
| } |
| } |
| |
| bool QDeclarativeLayoutMirroringAttached::childrenInherit() const |
| { |
| return itemPrivate ? itemPrivate->inheritMirrorFromItem : false; |
| } |
| |
| void QDeclarativeLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) { |
| if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) { |
| itemPrivate->inheritMirrorFromItem = childrenInherit; |
| itemPrivate->resolveLayoutMirror(); |
| childrenInheritChanged(); |
| } |
| } |
| |
| void QDeclarativeItemPrivate::resolveLayoutMirror() |
| { |
| Q_Q(QDeclarativeItem); |
| if (QDeclarativeItem *parentItem = q->parentItem()) { |
| QDeclarativeItemPrivate *parentPrivate = QDeclarativeItemPrivate::get(parentItem); |
| setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent); |
| } else { |
| setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem); |
| } |
| } |
| |
| void QDeclarativeItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit) |
| { |
| inherit = inherit || inheritMirrorFromItem; |
| if (!isMirrorImplicit && inheritMirrorFromItem) |
| mirror = effectiveLayoutMirror; |
| if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent) |
| return; |
| |
| inheritMirrorFromParent = inherit; |
| inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false; |
| |
| if (isMirrorImplicit) |
| setLayoutMirror(inherit ? inheritedLayoutMirror : false); |
| for (int i = 0; i < children.count(); ++i) { |
| if (QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i))) { |
| QDeclarativeItemPrivate *childPrivate = QDeclarativeItemPrivate::get(child); |
| childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent); |
| } |
| } |
| } |
| |
| void QDeclarativeItemPrivate::setLayoutMirror(bool mirror) |
| { |
| if (mirror != effectiveLayoutMirror) { |
| effectiveLayoutMirror = mirror; |
| if (_anchors) { |
| _anchors->d_func()->fillChanged(); |
| _anchors->d_func()->centerInChanged(); |
| _anchors->d_func()->updateHorizontalAnchors(); |
| } |
| mirrorChange(); |
| if (attachedLayoutDirection) { |
| emit attachedLayoutDirection->enabledChanged(); |
| } |
| } |
| } |
| |
| /*! |
| \qmlclass Keys QDeclarativeKeysAttached |
| \ingroup qml-basic-interaction-elements |
| \since 4.7 |
| \brief The Keys attached property provides key handling to Items. |
| |
| All visual primitives support key handling via the Keys |
| attached property. Keys can be handled via the onPressed |
| and onReleased signal properties. |
| |
| 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 hierarchy. |
| |
| \section1 Example Usage |
| |
| The following example shows how the general onPressed handler can |
| be used to test for a certain key; in this case, the left cursor |
| key: |
| |
| \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item |
| |
| Some keys may alternatively be handled via specific signal properties, |
| for example \e onSelectPressed. These handlers automatically set |
| \e event.accepted to true. |
| |
| \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item |
| |
| See \l{Qt::Key}{Qt.Key} for the list of keyboard codes. |
| |
| \section1 Key Handling Priorities |
| |
| The Keys attached property can be configured to handle key events |
| before or after the item it is attached to. This makes it possible |
| to intercept events in order to override an item's default behavior, |
| or act as a fallback for keys not handled by the item. |
| |
| If \l priority is Keys.BeforeItem (default) the order of key event processing is: |
| |
| \list 1 |
| \o Items specified in \c forwardTo |
| \o specific key handlers, e.g. onReturnPressed |
| \o onKeyPress, onKeyRelease handlers |
| \o Item specific key handling, e.g. TextInput key handling |
| \o parent item |
| \endlist |
| |
| If priority is Keys.AfterItem the order of key event processing is: |
| |
| \list 1 |
| \o Item specific key handling, e.g. TextInput key handling |
| \o Items specified in \c forwardTo |
| \o specific key handlers, e.g. onReturnPressed |
| \o onKeyPress, onKeyRelease handlers |
| \o parent item |
| \endlist |
| |
| If the event is accepted during any of the above steps, key |
| propagation stops. |
| |
| \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property} |
| */ |
| |
| /*! |
| \qmlproperty bool Keys::enabled |
| |
| This flags enables key handling if true (default); otherwise |
| no key handlers will be called. |
| */ |
| |
| /*! |
| \qmlproperty enumeration Keys::priority |
| |
| This property determines whether the keys are processed before |
| or after the attached item's own key handling. |
| |
| \list |
| \o Keys.BeforeItem (default) - process the key events before normal |
| item key processing. If the event is accepted it will not |
| be passed on to the item. |
| \o Keys.AfterItem - process the key events after normal item key |
| handling. If the item accepts the key event it will not be |
| handled by the Keys attached property handler. |
| \endlist |
| */ |
| |
| /*! |
| \qmlproperty list<Object> Keys::forwardTo |
| |
| This property provides a way to forward key presses, key releases, and keyboard input |
| coming from input methods to other items. This can be useful when you want |
| one item to handle some keys (e.g. the up and down arrow keys), and another item to |
| handle other keys (e.g. the left and right arrow keys). Once an item that has been |
| forwarded keys accepts the event it is no longer forwarded to items later in the |
| list. |
| |
| This example forwards key events to two lists: |
| \qml |
| Item { |
| ListView { |
| id: list1 |
| // ... |
| } |
| ListView { |
| id: list2 |
| // ... |
| } |
| Keys.forwardTo: [list1, list2] |
| focus: true |
| } |
| \endqml |
| */ |
| |
| /*! |
| \qmlsignal Keys::onPressed(KeyEvent event) |
| |
| This handler is called when a key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onReleased(KeyEvent event) |
| |
| This handler is called when a key has been released. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit0Pressed(KeyEvent event) |
| |
| This handler is called when the digit '0' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit1Pressed(KeyEvent event) |
| |
| This handler is called when the digit '1' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit2Pressed(KeyEvent event) |
| |
| This handler is called when the digit '2' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit3Pressed(KeyEvent event) |
| |
| This handler is called when the digit '3' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit4Pressed(KeyEvent event) |
| |
| This handler is called when the digit '4' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit5Pressed(KeyEvent event) |
| |
| This handler is called when the digit '5' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit6Pressed(KeyEvent event) |
| |
| This handler is called when the digit '6' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit7Pressed(KeyEvent event) |
| |
| This handler is called when the digit '7' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit8Pressed(KeyEvent event) |
| |
| This handler is called when the digit '8' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDigit9Pressed(KeyEvent event) |
| |
| This handler is called when the digit '9' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onLeftPressed(KeyEvent event) |
| |
| This handler is called when the Left arrow has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onRightPressed(KeyEvent event) |
| |
| This handler is called when the Right arrow has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onUpPressed(KeyEvent event) |
| |
| This handler is called when the Up arrow has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDownPressed(KeyEvent event) |
| |
| This handler is called when the Down arrow has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onTabPressed(KeyEvent event) |
| |
| This handler is called when the Tab key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onBacktabPressed(KeyEvent event) |
| |
| This handler is called when the Shift+Tab key combination (Backtab) has |
| been pressed. The \a event parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onAsteriskPressed(KeyEvent event) |
| |
| This handler is called when the Asterisk '*' has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onEscapePressed(KeyEvent event) |
| |
| This handler is called when the Escape key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onReturnPressed(KeyEvent event) |
| |
| This handler is called when the Return key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onEnterPressed(KeyEvent event) |
| |
| This handler is called when the Enter key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onDeletePressed(KeyEvent event) |
| |
| This handler is called when the Delete key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onSpacePressed(KeyEvent event) |
| |
| This handler is called when the Space key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onBackPressed(KeyEvent event) |
| |
| This handler is called when the Back key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onCancelPressed(KeyEvent event) |
| |
| This handler is called when the Cancel key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onSelectPressed(KeyEvent event) |
| |
| This handler is called when the Select key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onYesPressed(KeyEvent event) |
| |
| This handler is called when the Yes key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onNoPressed(KeyEvent event) |
| |
| This handler is called when the No key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onContext1Pressed(KeyEvent event) |
| |
| This handler is called when the Context1 key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onContext2Pressed(KeyEvent event) |
| |
| This handler is called when the Context2 key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onContext3Pressed(KeyEvent event) |
| |
| This handler is called when the Context3 key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onContext4Pressed(KeyEvent event) |
| |
| This handler is called when the Context4 key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onCallPressed(KeyEvent event) |
| |
| This handler is called when the Call key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onHangupPressed(KeyEvent event) |
| |
| This handler is called when the Hangup key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onFlipPressed(KeyEvent event) |
| |
| This handler is called when the Flip key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onMenuPressed(KeyEvent event) |
| |
| This handler is called when the Menu key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onVolumeUpPressed(KeyEvent event) |
| |
| This handler is called when the VolumeUp key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| /*! |
| \qmlsignal Keys::onVolumeDownPressed(KeyEvent event) |
| |
| This handler is called when the VolumeDown key has been pressed. The \a event |
| parameter provides information about the event. |
| */ |
| |
| const QDeclarativeKeysAttached::SigMap QDeclarativeKeysAttached::sigMap[] = { |
| { Qt::Key_Left, "leftPressed" }, |
| { Qt::Key_Right, "rightPressed" }, |
| { Qt::Key_Up, "upPressed" }, |
| { Qt::Key_Down, "downPressed" }, |
| { Qt::Key_Tab, "tabPressed" }, |
| { Qt::Key_Backtab, "backtabPressed" }, |
| { Qt::Key_Asterisk, "asteriskPressed" }, |
| { Qt::Key_NumberSign, "numberSignPressed" }, |
| { Qt::Key_Escape, "escapePressed" }, |
| { Qt::Key_Return, "returnPressed" }, |
| { Qt::Key_Enter, "enterPressed" }, |
| { Qt::Key_Delete, "deletePressed" }, |
| { Qt::Key_Space, "spacePressed" }, |
| { Qt::Key_Back, "backPressed" }, |
| { Qt::Key_Cancel, "cancelPressed" }, |
| { Qt::Key_Select, "selectPressed" }, |
| { Qt::Key_Yes, "yesPressed" }, |
| { Qt::Key_No, "noPressed" }, |
| { Qt::Key_Context1, "context1Pressed" }, |
| { Qt::Key_Context2, "context2Pressed" }, |
| { Qt::Key_Context3, "context3Pressed" }, |
| { Qt::Key_Context4, "context4Pressed" }, |
| { Qt::Key_Call, "callPressed" }, |
| { Qt::Key_Hangup, "hangupPressed" }, |
| { Qt::Key_Flip, "flipPressed" }, |
| { Qt::Key_Menu, "menuPressed" }, |
| { Qt::Key_VolumeUp, "volumeUpPressed" }, |
| { Qt::Key_VolumeDown, "volumeDownPressed" }, |
| { 0, 0 } |
| }; |
| |
| bool QDeclarativeKeysAttachedPrivate::isConnected(const char *signalName) |
| { |
| return isSignalConnected(signalIndex(signalName)); |
| } |
| |
| QDeclarativeKeysAttached::QDeclarativeKeysAttached(QObject *parent) |
| : QObject(*(new QDeclarativeKeysAttachedPrivate), parent), |
| QDeclarativeItemKeyFilter(qobject_cast<QDeclarativeItem*>(parent)) |
| { |
| Q_D(QDeclarativeKeysAttached); |
| m_processPost = false; |
| d->item = qobject_cast<QDeclarativeItem*>(parent); |
| } |
| |
| QDeclarativeKeysAttached::~QDeclarativeKeysAttached() |
| { |
| } |
| |
| QDeclarativeKeysAttached::Priority QDeclarativeKeysAttached::priority() const |
| { |
| return m_processPost ? AfterItem : BeforeItem; |
| } |
| |
| void QDeclarativeKeysAttached::setPriority(Priority order) |
| { |
| bool processPost = order == AfterItem; |
| if (processPost != m_processPost) { |
| m_processPost = processPost; |
| emit priorityChanged(); |
| } |
| } |
| |
| void QDeclarativeKeysAttached::componentComplete() |
| { |
| Q_D(QDeclarativeKeysAttached); |
| if (d->item) { |
| for (int ii = 0; ii < d->targets.count(); ++ii) { |
| QGraphicsItem *targetItem = d->finalFocusProxy(d->targets.at(ii)); |
| if (targetItem && (targetItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { |
| d->item->setFlag(QGraphicsItem::ItemAcceptsInputMethod); |
| break; |
| } |
| } |
| } |
| } |
| |
| void QDeclarativeKeysAttached::keyPressed(QKeyEvent *event, bool post) |
| { |
| Q_D(QDeclarativeKeysAttached); |
| if (post != m_processPost || !d->enabled || d->inPress) { |
| event->ignore(); |
| QDeclarativeItemKeyFilter::keyPressed(event, post); |
| return; |
| } |
| |
| // first process forwards |
| if (d->item && d->item->scene()) { |
| d->inPress = true; |
| for (int ii = 0; ii < d->targets.count(); ++ii) { |
| QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); |
| if (i && i->isVisible()) { |
| d->item->scene()->sendEvent(i, event); |
| if (event->isAccepted()) { |
| d->inPress = false; |
| return; |
| } |
| } |
| } |
| d->inPress = false; |
| } |
| |
| QDeclarativeKeyEvent ke(*event); |
| QByteArray keySignal = keyToSignal(event->key()); |
| if (!keySignal.isEmpty()) { |
| keySignal += "(QDeclarativeKeyEvent*)"; |
| if (d->isConnected(keySignal)) { |
| // If we specifically handle a key then default to accepted |
| ke.setAccepted(true); |
| int idx = QDeclarativeKeysAttached::staticMetaObject.indexOfSignal(keySignal); |
| metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QDeclarativeKeyEvent*, &ke)); |
| } |
| } |
| if (!ke.isAccepted()) |
| emit pressed(&ke); |
| event->setAccepted(ke.isAccepted()); |
| |
| if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyPressed(event, post); |
| } |
| |
| void QDeclarativeKeysAttached::keyReleased(QKeyEvent *event, bool post) |
| { |
| Q_D(QDeclarativeKeysAttached); |
| if (post != m_processPost || !d->enabled || d->inRelease) { |
| event->ignore(); |
| QDeclarativeItemKeyFilter::keyReleased(event, post); |
| return; |
| } |
| |
| if (d->item && d->item->scene()) { |
| d->inRelease = true; |
| for (int ii = 0; ii < d->targets.count(); ++ii) { |
| QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); |
| if (i && i->isVisible()) { |
| d->item->scene()->sendEvent(i, event); |
| if (event->isAccepted()) { |
| d->inRelease = false; |
| return; |
| } |
| } |
| } |
| d->inRelease = false; |
| } |
| |
| QDeclarativeKeyEvent ke(*event); |
| emit released(&ke); |
| event->setAccepted(ke.isAccepted()); |
| |
| if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post); |
| } |
| |
| void QDeclarativeKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post) |
| { |
| Q_D(QDeclarativeKeysAttached); |
| if (post == m_processPost && d->item && !d->inIM && d->item->scene()) { |
| d->inIM = true; |
| for (int ii = 0; ii < d->targets.count(); ++ii) { |
| QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); |
| if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { |
| d->item->scene()->sendEvent(i, event); |
| if (event->isAccepted()) { |
| d->imeItem = i; |
| d->inIM = false; |
| return; |
| } |
| } |
| } |
| d->inIM = false; |
| } |
| if (!event->isAccepted()) QDeclarativeItemKeyFilter::inputMethodEvent(event, post); |
| } |
| |
| class QDeclarativeItemAccessor : public QGraphicsItem |
| { |
| public: |
| QVariant doInputMethodQuery(Qt::InputMethodQuery query) const { |
| return QGraphicsItem::inputMethodQuery(query); |
| } |
| }; |
| |
| QVariant QDeclarativeKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const |
| { |
| Q_D(const QDeclarativeKeysAttached); |
| if (d->item) { |
| for (int ii = 0; ii < d->targets.count(); ++ii) { |
| QGraphicsItem *i = d->finalFocusProxy(d->targets.at(ii)); |
| if (i && i->isVisible() && (i->flags() & QGraphicsItem::ItemAcceptsInputMethod) && i == d->imeItem) { //### how robust is i == d->imeItem check? |
| QVariant v = static_cast<QDeclarativeItemAccessor *>(i)->doInputMethodQuery(query); |
| if (v.userType() == QVariant::RectF) |
| v = d->item->mapRectFromItem(i, v.toRectF()); //### cost? |
| return v; |
| } |
| } |
| } |
| return QDeclarativeItemKeyFilter::inputMethodQuery(query); |
| } |
| |
| QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObject *obj) |
| { |
| return new QDeclarativeKeysAttached(obj); |
| } |
| |
| /*! |
| \class QDeclarativeItem |
| \since 4.7 |
| \brief The QDeclarativeItem class provides the most basic of all visual items in QML. |
| |
| All visual items in Qt Declarative inherit from QDeclarativeItem. Although QDeclarativeItem |
| has no visual appearance, it defines all the properties that are |
| common across visual items - such as the x and y position, the |
| width and height, \l {anchor-layout}{anchoring} and key handling. |
| |
| You can subclass QDeclarativeItem to provide your own custom visual item that inherits |
| these features. Note that, because it does not draw anything, QDeclarativeItem sets the |
| QGraphicsItem::ItemHasNoContents flag. If you subclass QDeclarativeItem to create a visual |
| item, you will need to unset this flag. |
| |
| */ |
| |
| /*! |
| \qmlclass Item QDeclarativeItem |
| \ingroup qml-basic-visual-elements |
| \since 4.7 |
| \brief The Item is the most basic of all visual items in QML. |
| |
| All visual items in Qt Declarative inherit from Item. Although Item |
| has no visual appearance, it defines all the properties that are |
| common across visual items - such as the x and y position, the |
| width and height, \l {anchor-layout}{anchoring} and key handling. |
| |
| Item is also useful for grouping items together. |
| |
| \qml |
| Item { |
| Image { |
| source: "tile.png" |
| } |
| Image { |
| x: 80 |
| width: 100 |
| height: 100 |
| source: "tile.png" |
| } |
| Image { |
| x: 190 |
| width: 100 |
| height: 100 |
| fillMode: Image.Tile |
| source: "tile.png" |
| } |
| } |
| \endqml |
| |
| |
| \section1 Key Handling |
| |
| Key handling is available to all Item-based visual elements via the \l {Keys}{Keys} |
| attached property. The \e Keys attached property provides basic handlers such |
| as \l {Keys::onPressed}{onPressed} and \l {Keys::onReleased}{onReleased}, |
| as well as handlers for specific keys, such as |
| \l {Keys::onCancelPressed}{onCancelPressed}. The example below |
| assigns \l {qmlfocus}{focus} to the item and handles |
| the Left key via the general \e onPressed handler and the Select key via the |
| onSelectPressed handler: |
| |
| \qml |
| Item { |
| focus: true |
| Keys.onPressed: { |
| if (event.key == Qt.Key_Left) { |
| console.log("move left"); |
| event.accepted = true; |
| } |
| } |
| Keys.onSelectPressed: console.log("Selected"); |
| } |
| \endqml |
| |
| See the \l {Keys}{Keys} attached property for detailed documentation. |
| |
| \section1 Layout Mirroring |
| |
| Item layouts can be mirrored using the \l {LayoutMirroring}{LayoutMirroring} attached property. |
| |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::childrenRectChanged(const QRectF &) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::baselineOffsetChanged(qreal) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::stateChanged(const QString &state) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::parentChanged(QDeclarativeItem *) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::smoothChanged(bool) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::clipChanged(bool) |
| \internal |
| */ |
| |
| /*! \fn void QDeclarativeItem::transformOriginChanged(TransformOrigin) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::focusChanged(bool) |
| \internal |
| */ |
| |
| /*! |
| \fn void QDeclarativeItem::activeFocusChanged(bool) |
| \internal |
| */ |
| |
| // ### Must fix |
| struct RegisterAnchorLineAtStartup { |
| RegisterAnchorLineAtStartup() { |
| qRegisterMetaType<QDeclarativeAnchorLine>("QDeclarativeAnchorLine"); |
| } |
| }; |
| static RegisterAnchorLineAtStartup registerAnchorLineAtStartup; |
| |
| |
| /*! |
| \fn QDeclarativeItem::QDeclarativeItem(QDeclarativeItem *parent) |
| |
| Constructs a QDeclarativeItem with the given \a parent. |
| */ |
| QDeclarativeItem::QDeclarativeItem(QDeclarativeItem* parent) |
| : QGraphicsObject(*(new QDeclarativeItemPrivate), parent, 0) |
| { |
| Q_D(QDeclarativeItem); |
| d->init(parent); |
| } |
| |
| /*! \internal |
| */ |
| QDeclarativeItem::QDeclarativeItem(QDeclarativeItemPrivate &dd, QDeclarativeItem *parent) |
| : QGraphicsObject(dd, parent, 0) |
| { |
| Q_D(QDeclarativeItem); |
| d->init(parent); |
| } |
| |
| /*! |
| Destroys the QDeclarativeItem. |
| */ |
| QDeclarativeItem::~QDeclarativeItem() |
| { |
| Q_D(QDeclarativeItem); |
| for (int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| QDeclarativeAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate(); |
| if (anchor) |
| anchor->clearItem(this); |
| } |
| if (!d->parent || (parentItem() && !parentItem()->QGraphicsItem::d_ptr->inDestructor)) { |
| for (int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| QDeclarativeAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate(); |
| if (anchor && anchor->item && anchor->item->parentItem() != this) //child will be deleted anyway |
| anchor->updateOnComplete(); |
| } |
| } |
| for(int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); |
| if (change.types & QDeclarativeItemPrivate::Destroyed) |
| change.listener->itemDestroyed(this); |
| } |
| d->changeListeners.clear(); |
| delete d->_anchorLines; d->_anchorLines = 0; |
| delete d->_anchors; d->_anchors = 0; |
| delete d->_stateGroup; d->_stateGroup = 0; |
| delete d->_contents; d->_contents = 0; |
| } |
| |
| /*! |
| \qmlproperty enumeration Item::transformOrigin |
| This property holds the origin point around which scale and rotation transform. |
| |
| Nine transform origins are available, as shown in the image below. |
| |
| \image declarative-transformorigin.png |
| |
| This example rotates an image around its bottom-right corner. |
| \qml |
| Image { |
| source: "myimage.png" |
| transformOrigin: Item.BottomRight |
| rotation: 45 |
| } |
| \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. |
| */ |
| |
| /*! |
| \qmlproperty Item Item::parent |
| This property holds the parent of the item. |
| */ |
| |
| /*! |
| \property QDeclarativeItem::parent |
| This property holds the parent of the item. |
| */ |
| void QDeclarativeItem::setParentItem(QDeclarativeItem *parent) |
| { |
| QGraphicsObject::setParentItem(parent); |
| } |
| |
| /*! |
| Returns the QDeclarativeItem parent of this item. |
| */ |
| QDeclarativeItem *QDeclarativeItem::parentItem() const |
| { |
| return qobject_cast<QDeclarativeItem *>(QGraphicsObject::parentItem()); |
| } |
| |
| /*! |
| \qmlproperty real Item::childrenRect.x |
| \qmlproperty real Item::childrenRect.y |
| \qmlproperty real Item::childrenRect.width |
| \qmlproperty real Item::childrenRect.height |
| |
| The childrenRect properties allow an item access to the geometry of its |
| children. This property is useful if you have an item that needs to be |
| sized to fit its children. |
| */ |
| |
| |
| /*! |
| \qmlproperty list<Item> Item::children |
| \qmlproperty list<Object> Item::resources |
| |
| The children property contains the list of visual children of this item. |
| The resources property contains non-visual resources that you want to |
| reference by name. |
| |
| Generally you can rely on Item's default property to handle all this for |
| you, but it can come in handy in some cases. |
| |
| \qml |
| Item { |
| children: [ |
| Text {}, |
| Rectangle {} |
| ] |
| resources: [ |
| Component { |
| id: myComponent |
| Text {} |
| } |
| ] |
| } |
| \endqml |
| */ |
| |
| /*! |
| Returns true if construction of the QML component is complete; otherwise |
| returns false. |
| |
| It is often desirable to delay some processing until the component is |
| completed. |
| |
| \sa componentComplete() |
| */ |
| bool QDeclarativeItem::isComponentComplete() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->componentComplete; |
| } |
| |
| void QDeclarativeItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o) |
| { |
| if (!o) |
| return; |
| |
| QDeclarativeItem *that = static_cast<QDeclarativeItem *>(prop->object); |
| |
| // This test is measurably (albeit only slightly) faster than qobject_cast<>() |
| const QMetaObject *mo = o->metaObject(); |
| while (mo && mo != &QGraphicsObject::staticMetaObject) mo = mo->d.superdata; |
| |
| if (mo) { |
| QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(o); |
| QDeclarativeItemPrivate *contentItemPrivate = static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(graphicsObject)); |
| if (contentItemPrivate->componentComplete) { |
| graphicsObject->setParentItem(that); |
| } else { |
| contentItemPrivate->setParentItemHelper(that, /*newParentVariant=*/0, /*thisPointerVariant=*/0); |
| } |
| } else { |
| o->setParent(that); |
| } |
| } |
| |
| static inline int children_count_helper(QDeclarativeListProperty<QObject> *prop) |
| { |
| QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(prop->object)); |
| return d->children.count(); |
| } |
| |
| static inline QObject *children_at_helper(QDeclarativeListProperty<QObject> *prop, int index) |
| { |
| QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(prop->object)); |
| if (index >= 0 && index < d->children.count()) |
| return d->children.at(index)->toGraphicsObject(); |
| else |
| return 0; |
| } |
| |
| static inline void children_clear_helper(QDeclarativeListProperty<QObject> *prop) |
| { |
| QDeclarativeItemPrivate *d = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(prop->object))); |
| int childCount = d->children.count(); |
| if (d->componentComplete) { |
| for (int index = 0 ;index < childCount; index++) |
| d->children.at(0)->setParentItem(0); |
| } else { |
| for (int index = 0 ;index < childCount; index++) |
| QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, /*newParentVariant=*/0, /*thisPointerVariant=*/0); |
| } |
| } |
| |
| int QDeclarativeItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop) |
| { |
| return resources_count(prop) + children_count_helper(prop); |
| } |
| |
| QObject *QDeclarativeItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i) |
| { |
| int resourcesCount = resources_count(prop); |
| if (i < resourcesCount) |
| return resources_at(prop, i); |
| const int j = i - resourcesCount; |
| if (j < children_count_helper(prop)) |
| return children_at_helper(prop, j); |
| return 0; |
| } |
| |
| void QDeclarativeItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop) |
| { |
| resources_clear(prop); |
| children_clear_helper(prop); |
| } |
| |
| QObject *QDeclarativeItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index) |
| { |
| const QObjectList children = prop->object->children(); |
| if (index < children.count()) |
| return children.at(index); |
| else |
| return 0; |
| } |
| |
| void QDeclarativeItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o) |
| { |
| o->setParent(prop->object); |
| } |
| |
| int QDeclarativeItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop) |
| { |
| return prop->object->children().count(); |
| } |
| |
| void QDeclarativeItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop) |
| { |
| const QObjectList children = prop->object->children(); |
| for (int index = 0; index < children.count(); index++) |
| children.at(index)->setParent(0); |
| } |
| |
| int QDeclarativeItemPrivate::transform_count(QDeclarativeListProperty<QGraphicsTransform> *list) |
| { |
| QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object); |
| if (object) { |
| QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); |
| return d->transformData ? d->transformData->graphicsTransforms.size() : 0; |
| } else { |
| return 0; |
| } |
| } |
| |
| void QDeclarativeItemPrivate::transform_append(QDeclarativeListProperty<QGraphicsTransform> *list, QGraphicsTransform *item) |
| { |
| QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object); |
| if (object && item) // QGraphicsItem applies the list in the wrong order, so we prepend. |
| QGraphicsItemPrivate::get(object)->prependGraphicsTransform(item); |
| } |
| |
| QGraphicsTransform *QDeclarativeItemPrivate::transform_at(QDeclarativeListProperty<QGraphicsTransform> *list, int idx) |
| { |
| QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object); |
| if (object) { |
| QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); |
| if (!d->transformData) |
| return 0; |
| return d->transformData->graphicsTransforms.at(idx); |
| } else { |
| return 0; |
| } |
| } |
| |
| void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphicsTransform> *list) |
| { |
| QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object); |
| if (object) { |
| QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); |
| if (!d->transformData) |
| return; |
| object->setTransformations(QList<QGraphicsTransform *>()); |
| } |
| } |
| |
| void QDeclarativeItemPrivate::parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e) |
| { |
| QDeclarativeItem *item = static_cast<QDeclarativeItem*>(o); |
| if (e) |
| e->connect(&item->d_func()->parentNotifier); |
| *((QDeclarativeItem **)rv) = item->parentItem(); |
| } |
| |
| /*! |
| \qmlproperty list<Object> Item::data |
| \default |
| |
| The data property allows you to freely mix visual children and resources |
| in an item. If you assign a visual item to the data list it becomes |
| a child and if you assign any other object type, it is added as a resource. |
| |
| So you can write: |
| \qml |
| Item { |
| Text {} |
| Rectangle {} |
| Timer {} |
| } |
| \endqml |
| |
| instead of: |
| \qml |
| Item { |
| children: [ |
| Text {}, |
| Rectangle {} |
| ] |
| resources: [ |
| Timer {} |
| ] |
| } |
| \endqml |
| |
| data is a behind-the-scenes property: you should never need to explicitly |
| specify it. |
| */ |
| |
| QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::data() |
| { |
| return QDeclarativeListProperty<QObject>(q_func(), 0, QDeclarativeItemPrivate::data_append, |
| QDeclarativeItemPrivate::data_count, |
| QDeclarativeItemPrivate::data_at, |
| QDeclarativeItemPrivate::data_clear |
| ); |
| } |
| |
| /*! |
| \property QDeclarativeItem::childrenRect |
| \brief The geometry of an item's children. |
| |
| This property holds the (collective) position and size of the item's children. |
| */ |
| QRectF QDeclarativeItem::childrenRect() |
| { |
| Q_D(QDeclarativeItem); |
| if (!d->_contents) { |
| d->_contents = new QDeclarativeContents(this); |
| if (d->componentComplete) |
| d->_contents->complete(); |
| } |
| return d->_contents->rectF(); |
| } |
| |
| bool QDeclarativeItem::clip() const |
| { |
| return flags() & ItemClipsChildrenToShape; |
| } |
| |
| void QDeclarativeItem::setClip(bool c) |
| { |
| if (clip() == c) |
| return; |
| setFlag(ItemClipsChildrenToShape, c); |
| emit clipChanged(c); |
| } |
| |
| /*! |
| \qmlproperty real Item::x |
| \qmlproperty real Item::y |
| \qmlproperty real Item::width |
| \qmlproperty real Item::height |
| |
| Defines the item's position and size relative to its parent. |
| |
| \qml |
| Item { x: 100; y: 100; width: 100; height: 100 } |
| \endqml |
| */ |
| |
| /*! |
| \qmlproperty real Item::z |
| |
| Sets the stacking order of sibling items. By default the stacking order is 0. |
| |
| Items with a higher stacking value are drawn on top of siblings with a |
| lower stacking order. Items with the same stacking value are drawn |
| bottom up in the order they appear. Items with a negative stacking |
| value are drawn under their parent's content. |
| |
| The following example shows the various effects of stacking order. |
| |
| \table |
| \row |
| \o \image declarative-item_stacking1.png |
| \o Same \c z - later children above earlier children: |
| \qml |
| Item { |
| Rectangle { |
| color: "red" |
| width: 100; height: 100 |
| } |
| Rectangle { |
| color: "blue" |
| x: 50; y: 50; width: 100; height: 100 |
| } |
| } |
| \endqml |
| \row |
| \o \image declarative-item_stacking2.png |
| \o Higher \c z on top: |
| \qml |
| Item { |
| Rectangle { |
| z: 1 |
| color: "red" |
| width: 100; height: 100 |
| } |
| Rectangle { |
| color: "blue" |
| x: 50; y: 50; width: 100; height: 100 |
| } |
| } |
| \endqml |
| \row |
| \o \image declarative-item_stacking3.png |
| \o Same \c z - children above parents: |
| \qml |
| Item { |
| Rectangle { |
| color: "red" |
| width: 100; height: 100 |
| Rectangle { |
| color: "blue" |
| x: 50; y: 50; width: 100; height: 100 |
| } |
| } |
| } |
| \endqml |
| \row |
| \o \image declarative-item_stacking4.png |
| \o Lower \c z below: |
| \qml |
| Item { |
| Rectangle { |
| color: "red" |
| width: 100; height: 100 |
| Rectangle { |
| z: -1 |
| color: "blue" |
| x: 50; y: 50; width: 100; height: 100 |
| } |
| } |
| } |
| \endqml |
| \endtable |
| */ |
| |
| /*! |
| \qmlproperty bool Item::visible |
| |
| This property holds whether the item is visible. By default this is true. |
| |
| Setting this property directly affects the \c visible value of child |
| items. When set to \c false, the \c visible values of all child items also |
| become \c false. When set to \c true, the \c visible values of child items |
| are returned to \c true, unless they have explicitly been set to \c false. |
| |
| (Because of this flow-on behavior, using the \c visible property may not |
| have the intended effect if a property binding should only respond to |
| explicit property changes. In such cases it may be better to use the |
| \l opacity property instead.) |
| |
| Setting this property to \c false automatically causes \l focus to be set |
| to \c false, and this item will longer receive mouse and keyboard events. |
| (In contrast, setting the \l opacity to 0 does not affect the \l focus |
| property and the receiving of key events.) |
| |
| \note This property's value is only affected by changes to this property or |
| the parent's \c visible property. It does not change, for example, if this |
| item moves off-screen, or if the \l opacity changes to 0. |
| */ |
| |
| |
| /*! |
| This function is called to handle this item's changes in |
| geometry from \a oldGeometry to \a newGeometry. If the two |
| geometries are the same, it doesn't do anything. |
| */ |
| void QDeclarativeItem::geometryChanged(const QRectF &newGeometry, |
| const QRectF &oldGeometry) |
| { |
| Q_D(QDeclarativeItem); |
| |
| if (d->_anchors) |
| d->_anchors->d_func()->updateMe(); |
| |
| if (transformOrigin() != QDeclarativeItem::TopLeft |
| && (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height())) { |
| if (d->transformData) { |
| QPointF origin = d->computeTransformOrigin(); |
| if (transformOriginPoint() != origin) |
| setTransformOriginPoint(origin); |
| } else { |
| d->transformOriginDirty = true; |
| } |
| } |
| |
| for(int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); |
| if (change.types & QDeclarativeItemPrivate::Geometry) |
| change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); |
| } |
| |
| if (newGeometry.width() != oldGeometry.width()) |
| emit widthChanged(); |
| if (newGeometry.height() != oldGeometry.height()) |
| emit heightChanged(); |
| } |
| |
| void QDeclarativeItemPrivate::removeItemChangeListener(QDeclarativeItemChangeListener *listener, ChangeTypes types) |
| { |
| ChangeListener change(listener, types); |
| changeListeners.removeOne(change); |
| } |
| |
| /*! \internal */ |
| void QDeclarativeItem::keyPressEvent(QKeyEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| keyPressPreHandler(event); |
| if (event->isAccepted()) |
| return; |
| if (d->keyHandler) |
| d->keyHandler->keyPressed(event, true); |
| else |
| event->ignore(); |
| } |
| |
| /*! \internal */ |
| void QDeclarativeItem::keyReleaseEvent(QKeyEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| keyReleasePreHandler(event); |
| if (event->isAccepted()) |
| return; |
| if (d->keyHandler) |
| d->keyHandler->keyReleased(event, true); |
| else |
| event->ignore(); |
| } |
| |
| /*! \internal */ |
| void QDeclarativeItem::inputMethodEvent(QInputMethodEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| inputMethodPreHandler(event); |
| if (event->isAccepted()) |
| return; |
| if (d->keyHandler) |
| d->keyHandler->inputMethodEvent(event, true); |
| else |
| event->ignore(); |
| } |
| |
| /*! \internal */ |
| QVariant QDeclarativeItem::inputMethodQuery(Qt::InputMethodQuery query) const |
| { |
| Q_D(const QDeclarativeItem); |
| QVariant v; |
| if (d->keyHandler) |
| v = d->keyHandler->inputMethodQuery(query); |
| |
| if (!v.isValid()) |
| v = QGraphicsObject::inputMethodQuery(query); |
| |
| return v; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItem::keyPressPreHandler(QKeyEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| if (d->keyHandler && !d->doneEventPreHandler) |
| d->keyHandler->keyPressed(event, false); |
| else |
| event->ignore(); |
| d->doneEventPreHandler = true; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItem::keyReleasePreHandler(QKeyEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| if (d->keyHandler && !d->doneEventPreHandler) |
| d->keyHandler->keyReleased(event, false); |
| else |
| event->ignore(); |
| d->doneEventPreHandler = true; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItem::inputMethodPreHandler(QInputMethodEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| if (d->keyHandler && !d->doneEventPreHandler) |
| d->keyHandler->inputMethodEvent(event, false); |
| else |
| event->ignore(); |
| d->doneEventPreHandler = true; |
| } |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::left() const |
| { |
| return anchorLines()->left; |
| } |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::right() const |
| { |
| return anchorLines()->right; |
| } |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::horizontalCenter() const |
| { |
| return anchorLines()->hCenter; |
| } |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::top() const |
| { |
| return anchorLines()->top; |
| } |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::bottom() const |
| { |
| return anchorLines()->bottom; |
| } |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::verticalCenter() const |
| { |
| return anchorLines()->vCenter; |
| } |
| |
| |
| /*! |
| \internal |
| */ |
| QDeclarativeAnchorLine QDeclarativeItemPrivate::baseline() const |
| { |
| return anchorLines()->baseline; |
| } |
| |
| /*! |
| \qmlproperty AnchorLine Item::anchors.top |
| \qmlproperty AnchorLine Item::anchors.bottom |
| \qmlproperty AnchorLine Item::anchors.left |
| \qmlproperty AnchorLine Item::anchors.right |
| \qmlproperty AnchorLine Item::anchors.horizontalCenter |
| \qmlproperty AnchorLine Item::anchors.verticalCenter |
| \qmlproperty AnchorLine Item::anchors.baseline |
| |
| \qmlproperty Item Item::anchors.fill |
| \qmlproperty Item Item::anchors.centerIn |
| |
| \qmlproperty real Item::anchors.margins |
| \qmlproperty real Item::anchors.topMargin |
| \qmlproperty real Item::anchors.bottomMargin |
| \qmlproperty real Item::anchors.leftMargin |
| \qmlproperty real Item::anchors.rightMargin |
| \qmlproperty real Item::anchors.horizontalCenterOffset |
| \qmlproperty real Item::anchors.verticalCenterOffset |
| \qmlproperty real Item::anchors.baselineOffset |
| |
| \qmlproperty bool Item::anchors.mirrored |
| |
| Anchors provide a way to position an item by specifying its |
| relationship with other items. |
| |
| Margins apply to top, bottom, left, right, and fill anchors. |
| The \c anchors.margins property can be used to set all of the various margins at once, to the same value. |
| Note that margins are anchor-specific and are not applied if an item does not |
| use anchors. |
| |
| Offsets apply for horizontal center, vertical center, and baseline anchors. |
| |
| \table |
| \row |
| \o \image declarative-anchors_example.png |
| \o Text anchored to Image, horizontally centered and vertically below, with a margin. |
| \qml |
| Item { |
| Image { |
| id: pic |
| // ... |
| } |
| Text { |
| id: label |
| anchors.horizontalCenter: pic.horizontalCenter |
| anchors.top: pic.bottom |
| anchors.topMargin: 5 |
| // ... |
| } |
| } |
| \endqml |
| \row |
| \o \image declarative-anchors_example2.png |
| \o |
| Left of Text anchored to right of Image, with a margin. The y |
| property of both defaults to 0. |
| |
| \qml |
| Item { |
| Image { |
| id: pic |
| // ... |
| } |
| Text { |
| id: label |
| anchors.left: pic.right |
| anchors.leftMargin: 5 |
| // ... |
| } |
| } |
| \endqml |
| \endtable |
| |
| \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. |
| |
| \c anchors.mirrored returns true it the layout has been \l {LayoutMirroring}{mirrored}. |
| |
| \note You can only anchor an item to siblings or a parent. |
| |
| For more information see \l {anchor-layout}{Anchor Layouts}. |
| */ |
| |
| /*! |
| \property QDeclarativeItem::baselineOffset |
| \brief The position of the item's baseline in local coordinates. |
| |
| 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. |
| |
| For non-text items, a default baseline offset of 0 is used. |
| */ |
| qreal QDeclarativeItem::baselineOffset() const |
| { |
| Q_D(const QDeclarativeItem); |
| if (!d->baselineOffset.isValid()) { |
| return 0.0; |
| } else |
| return d->baselineOffset; |
| } |
| |
| void QDeclarativeItem::setBaselineOffset(qreal offset) |
| { |
| Q_D(QDeclarativeItem); |
| if (offset == d->baselineOffset) |
| return; |
| |
| d->baselineOffset = offset; |
| |
| for(int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); |
| if (change.types & QDeclarativeItemPrivate::Geometry) { |
| QDeclarativeAnchorsPrivate *anchor = change.listener->anchorPrivate(); |
| if (anchor) |
| anchor->updateVerticalAnchors(); |
| } |
| } |
| emit baselineOffsetChanged(offset); |
| } |
| |
| /*! |
| \qmlproperty real Item::rotation |
| This property holds the rotation of the item in degrees clockwise. |
| |
| This specifies how many degrees to rotate the item around its transformOrigin. |
| The default rotation is 0 degrees (i.e. not rotated at all). |
| |
| \table |
| \row |
| \o \image declarative-rotation.png |
| \o |
| \qml |
| Rectangle { |
| color: "blue" |
| width: 100; height: 100 |
| Rectangle { |
| color: "red" |
| x: 25; y: 25; width: 50; height: 50 |
| rotation: 30 |
| } |
| } |
| \endqml |
| \endtable |
| |
| \sa transform, Rotation |
| */ |
| |
| /*! |
| \qmlproperty real Item::scale |
| This property holds the scale of the item. |
| |
| A scale of less than 1 means the item will be displayed smaller than |
| normal, and a scale of greater than 1 means the item will be |
| displayed larger than normal. A negative scale means the item will |
| be mirrored. |
| |
| By default, items are displayed at a scale of 1 (i.e. at their |
| normal size). |
| |
| Scaling is from the item's transformOrigin. |
| |
| \table |
| \row |
| \o \image declarative-scale.png |
| \o |
| \qml |
| Rectangle { |
| color: "blue" |
| width: 100; height: 100 |
| Rectangle { |
| color: "green" |
| width: 25; height: 25 |
| } |
| Rectangle { |
| color: "red" |
| x: 25; y: 25; width: 50; height: 50 |
| scale: 1.4 |
| } |
| } |
| \endqml |
| \endtable |
| |
| \sa transform, Scale |
| */ |
| |
| /*! |
| \qmlproperty real Item::opacity |
| |
| This property holds the opacity of the item. Opacity is specified as a |
| number between 0 (fully transparent) and 1 (fully opaque). The default is 1. |
| |
| When this property is set, the specified opacity is also applied |
| individually to child items. In almost all cases this is what you want, |
| but in some cases it may produce undesired results. For example in the |
| second set of rectangles below, the red rectangle has specified an opacity |
| of 0.5, which affects the opacity of its blue child rectangle even though |
| the child has not specified an opacity. |
| |
| \table |
| \row |
| \o \image declarative-item_opacity1.png |
| \o |
| \qml |
| Item { |
| Rectangle { |
| color: "red" |
| width: 100; height: 100 |
| Rectangle { |
| color: "blue" |
| x: 50; y: 50; width: 100; height: 100 |
| } |
| } |
| } |
| \endqml |
| \row |
| \o \image declarative-item_opacity2.png |
| \o |
| \qml |
| Item { |
| Rectangle { |
| opacity: 0.5 |
| color: "red" |
| width: 100; height: 100 |
| Rectangle { |
| color: "blue" |
| x: 50; y: 50; width: 100; height: 100 |
| } |
| } |
| } |
| \endqml |
| \endtable |
| |
| If an item's opacity is set to 0, the item will no longer receive mouse |
| events, but will continue to receive key events and will retain the keyboard |
| \l focus if it has been set. (In contrast, setting the \l visible property |
| to \c false stops both mouse and keyboard events, and also removes focus |
| from the item.) |
| */ |
| |
| /*! |
| Returns a value indicating whether mouse input should |
| remain with this item exclusively. |
| |
| \sa setKeepMouseGrab() |
| */ |
| bool QDeclarativeItem::keepMouseGrab() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->keepMouse; |
| } |
| |
| /*! |
| The flag indicating whether the mouse should remain |
| with this item is set to \a keep. |
| |
| This is useful for items that wish to grab and keep mouse |
| interaction following a predefined gesture. For example, |
| an item that is interested in horizontal mouse movement |
| may set keepMouseGrab to true once a threshold has been |
| exceeded. Once keepMouseGrab has been set to true, filtering |
| items will not react to mouse events. |
| |
| If the item does not indicate that it wishes to retain mouse grab, |
| a filtering item may steal the grab. For example, Flickable may attempt |
| to steal a mouse grab if it detects that the user has begun to |
| move the viewport. |
| |
| \sa keepMouseGrab() |
| */ |
| void QDeclarativeItem::setKeepMouseGrab(bool keep) |
| { |
| Q_D(QDeclarativeItem); |
| d->keepMouse = keep; |
| } |
| |
| /*! |
| \qmlmethod object Item::mapFromItem(Item item, real x, real y) |
| |
| Maps the point (\a x, \a y), which is in \a item's coordinate system, to |
| this item's coordinate system, and returns an object with \c x and \c y |
| properties matching the mapped cooordinate. |
| |
| If \a item is a \c null value, this maps the point from the coordinate |
| system of the root QML view. |
| */ |
| QScriptValue QDeclarativeItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const |
| { |
| QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject(); |
| QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject()); |
| if (!itemObj && !item.isNull()) { |
| qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item"; |
| return 0; |
| } |
| |
| // If QGraphicsItem::mapFromItem() is called with 0, behaves the same as mapFromScene() |
| QPointF p = qobject_cast<QGraphicsItem*>(this)->mapFromItem(itemObj, x, y); |
| sv.setProperty(QLatin1String("x"), p.x()); |
| sv.setProperty(QLatin1String("y"), p.y()); |
| return sv; |
| } |
| |
| /*! |
| \qmlmethod object Item::mapToItem(Item item, real x, real y) |
| |
| Maps the point (\a x, \a y), which is in this item's coordinate system, to |
| \a item's coordinate system, and returns an object with \c x and \c y |
| properties matching the mapped cooordinate. |
| |
| If \a item is a \c null value, this maps \a x and \a y to the coordinate |
| system of the root QML view. |
| */ |
| QScriptValue QDeclarativeItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const |
| { |
| QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject(); |
| QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject()); |
| if (!itemObj && !item.isNull()) { |
| qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item"; |
| return 0; |
| } |
| |
| // If QGraphicsItem::mapToItem() is called with 0, behaves the same as mapToScene() |
| QPointF p = qobject_cast<QGraphicsItem*>(this)->mapToItem(itemObj, x, y); |
| sv.setProperty(QLatin1String("x"), p.x()); |
| sv.setProperty(QLatin1String("y"), p.y()); |
| return sv; |
| } |
| |
| /*! |
| \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::forceActiveFocus() |
| { |
| setFocus(true); |
| QGraphicsItem *parent = parentItem(); |
| while (parent) { |
| if (parent->flags() & QGraphicsItem::ItemIsFocusScope) |
| parent->setFocus(Qt::OtherFocusReason); |
| parent = parent->parentItem(); |
| } |
| } |
| |
| |
| /*! |
| \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<QGraphicsItem *> children = childItems(); |
| for (int i = children.count()-1; i >= 0; --i) { |
| if (QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(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); |
| if (!(flags & QGraphicsItem::ItemIsFocusScope) && parent) |
| emit q->activeFocusChanged(flag); //see also QDeclarativeItemPrivate::subFocusItemChange() |
| emit q->focusChanged(flag); |
| } |
| |
| QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::resources() |
| { |
| return QDeclarativeListProperty<QObject>(q_func(), 0, QDeclarativeItemPrivate::resources_append, |
| QDeclarativeItemPrivate::resources_count, |
| QDeclarativeItemPrivate::resources_at, |
| QDeclarativeItemPrivate::resources_clear |
| ); |
| } |
| |
| /*! |
| \qmlproperty list<State> Item::states |
| This property holds a list of states defined by the item. |
| |
| \qml |
| Item { |
| states: [ |
| State { |
| // ... |
| }, |
| State { |
| // ... |
| } |
| // ... |
| ] |
| } |
| \endqml |
| |
| \sa {qmlstate}{States} |
| */ |
| |
| QDeclarativeListProperty<QDeclarativeState> QDeclarativeItemPrivate::states() |
| { |
| return _states()->statesProperty(); |
| } |
| |
| /*! |
| \qmlproperty list<Transition> Item::transitions |
| This property holds a list of transitions defined by the item. |
| |
| \qml |
| Item { |
| transitions: [ |
| Transition { |
| // ... |
| }, |
| Transition { |
| // ... |
| } |
| // ... |
| ] |
| } |
| \endqml |
| |
| \sa {QML Animation and Transitions}{Transitions} |
| */ |
| |
| |
| QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeItemPrivate::transitions() |
| { |
| return _states()->transitionsProperty(); |
| } |
| |
| /* |
| \qmlproperty list<Filter> Item::filter |
| This property holds a list of graphical filters to be applied to the item. |
| |
| \l {Filter}{Filters} include things like \l {Blur}{blurring} |
| the item, or giving it a \l Reflection. Some |
| filters may not be available on all canvases; if a filter is not |
| available on a certain canvas, it will simply not be applied for |
| that canvas (but the QML will still be considered valid). |
| |
| \qml |
| Item { |
| filter: [ |
| Blur { |
| // ... |
| }, |
| Reflection { |
| // ... |
| } |
| // ... |
| ] |
| } |
| \endqml |
| */ |
| |
| /*! |
| \qmlproperty bool Item::clip |
| This property holds whether clipping is enabled. The default clip value is \c false. |
| |
| 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. |
| */ |
| |
| /*! |
| \property QDeclarativeItem::clip |
| This property holds whether clipping is enabled. The default clip value is \c false. |
| |
| If clipping is enabled, an item will clip its own painting, as well |
| as the painting of its children, to its bounding rectangle. If you set |
| clipping during an item's paint operation, remember to re-set it to |
| prevent clipping the rest of your scene. |
| |
| Non-rectangular clipping regions are not supported for performance reasons. |
| */ |
| |
| /*! |
| \qmlproperty string Item::state |
| |
| This property holds the name of the current state of the item. |
| |
| This property is often used in scripts to change between states. For |
| example: |
| |
| \js |
| function toggle() { |
| if (button.state == 'On') |
| button.state = 'Off'; |
| else |
| button.state = 'On'; |
| } |
| \endjs |
| |
| If the item is in its base state (i.e. no explicit state has been |
| set), \c state will be a blank string. Likewise, you can return an |
| item to its base state by setting its current state to \c ''. |
| |
| \sa {qmlstates}{States} |
| */ |
| |
| QString QDeclarativeItemPrivate::state() const |
| { |
| if (!_stateGroup) |
| return QString(); |
| else |
| return _stateGroup->state(); |
| } |
| |
| void QDeclarativeItemPrivate::setState(const QString &state) |
| { |
| _states()->setState(state); |
| } |
| |
| /*! |
| \qmlproperty list<Transform> Item::transform |
| This property holds the list of transformations to apply. |
| |
| For more information see \l Transform. |
| */ |
| |
| /*! \internal */ |
| QDeclarativeListProperty<QGraphicsTransform> QDeclarativeItem::transform() |
| { |
| Q_D(QDeclarativeItem); |
| return QDeclarativeListProperty<QGraphicsTransform>(this, 0, d->transform_append, d->transform_count, |
| d->transform_at, d->transform_clear); |
| } |
| |
| /*! |
| \internal |
| |
| classBegin() is called when the item is constructed, but its |
| properties have not yet been set. |
| |
| \sa componentComplete(), isComponentComplete() |
| */ |
| void QDeclarativeItem::classBegin() |
| { |
| Q_D(QDeclarativeItem); |
| d->componentComplete = false; |
| if (d->_stateGroup) |
| d->_stateGroup->classBegin(); |
| if (d->_anchors) |
| d->_anchors->classBegin(); |
| } |
| |
| /*! |
| \internal |
| |
| componentComplete() is called when all items in the component |
| 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; |
| if (d->_stateGroup) |
| d->_stateGroup->componentComplete(); |
| if (d->_anchors) { |
| d->_anchors->componentComplete(); |
| d->_anchors->d_func()->updateOnComplete(); |
| } |
| if (d->keyHandler) |
| d->keyHandler->componentComplete(); |
| if (d->_contents) |
| d->_contents->complete(); |
| } |
| |
| QDeclarativeStateGroup *QDeclarativeItemPrivate::_states() |
| { |
| Q_Q(QDeclarativeItem); |
| if (!_stateGroup) { |
| _stateGroup = new QDeclarativeStateGroup; |
| if (!componentComplete) |
| _stateGroup->classBegin(); |
| QObject::connect(_stateGroup, SIGNAL(stateChanged(QString)), |
| q, SIGNAL(stateChanged(QString))); |
| } |
| |
| return _stateGroup; |
| } |
| |
| QDeclarativeItemPrivate::AnchorLines::AnchorLines(QGraphicsObject *q) |
| { |
| left.item = q; |
| left.anchorLine = QDeclarativeAnchorLine::Left; |
| right.item = q; |
| right.anchorLine = QDeclarativeAnchorLine::Right; |
| hCenter.item = q; |
| hCenter.anchorLine = QDeclarativeAnchorLine::HCenter; |
| top.item = q; |
| top.anchorLine = QDeclarativeAnchorLine::Top; |
| bottom.item = q; |
| bottom.anchorLine = QDeclarativeAnchorLine::Bottom; |
| vCenter.item = q; |
| vCenter.anchorLine = QDeclarativeAnchorLine::VCenter; |
| baseline.item = q; |
| baseline.anchorLine = QDeclarativeAnchorLine::Baseline; |
| } |
| |
| QPointF QDeclarativeItemPrivate::computeTransformOrigin() const |
| { |
| Q_Q(const QDeclarativeItem); |
| |
| QRectF br = q->boundingRect(); |
| |
| switch(origin) { |
| default: |
| case QDeclarativeItem::TopLeft: |
| return QPointF(0, 0); |
| case QDeclarativeItem::Top: |
| return QPointF(br.width() / 2., 0); |
| case QDeclarativeItem::TopRight: |
| return QPointF(br.width(), 0); |
| case QDeclarativeItem::Left: |
| return QPointF(0, br.height() / 2.); |
| case QDeclarativeItem::Center: |
| return QPointF(br.width() / 2., br.height() / 2.); |
| case QDeclarativeItem::Right: |
| return QPointF(br.width(), br.height() / 2.); |
| case QDeclarativeItem::BottomLeft: |
| return QPointF(0, br.height()); |
| case QDeclarativeItem::Bottom: |
| return QPointF(br.width() / 2., br.height()); |
| case QDeclarativeItem::BottomRight: |
| return QPointF(br.width(), br.height()); |
| } |
| } |
| |
| /*! \internal */ |
| bool QDeclarativeItem::sceneEvent(QEvent *event) |
| { |
| Q_D(QDeclarativeItem); |
| if (event->type() == QEvent::KeyPress) { |
| QKeyEvent *k = static_cast<QKeyEvent *>(event); |
| if ((k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) && |
| !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { |
| keyPressEvent(static_cast<QKeyEvent *>(event)); |
| if (!event->isAccepted()) |
| return QGraphicsItem::sceneEvent(event); |
| else |
| return true; |
| } else { |
| return QGraphicsItem::sceneEvent(event); |
| } |
| } else { |
| bool rv = QGraphicsItem::sceneEvent(event); |
| |
| if (event->type() == QEvent::FocusIn || |
| event->type() == QEvent::FocusOut) { |
| d->focusChanged(hasActiveFocus()); |
| } |
| return rv; |
| } |
| } |
| |
| /*! |
| \internal |
| |
| Note that unlike QGraphicsItems, QDeclarativeItem::itemChange() is \e not called |
| during initial widget polishing. Items wishing to optimize start-up construction |
| should instead consider using componentComplete(). |
| */ |
| QVariant QDeclarativeItem::itemChange(GraphicsItemChange change, |
| const QVariant &value) |
| { |
| Q_D(QDeclarativeItem); |
| switch (change) { |
| case ItemParentHasChanged: |
| d->resolveLayoutMirror(); |
| emit parentChanged(parentItem()); |
| d->parentNotifier.notify(); |
| break; |
| case ItemVisibleHasChanged: { |
| for(int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); |
| if (change.types & QDeclarativeItemPrivate::Visibility) { |
| change.listener->itemVisibilityChanged(this); |
| } |
| } |
| } |
| break; |
| case ItemOpacityHasChanged: { |
| for(int ii = 0; ii < d->changeListeners.count(); ++ii) { |
| const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); |
| if (change.types & QDeclarativeItemPrivate::Opacity) { |
| change.listener->itemOpacityChanged(this); |
| } |
| } |
| } |
| break; |
| case ItemChildAddedChange: |
| if (d->_contents && d->componentComplete) |
| d->_contents->childAdded(qobject_cast<QDeclarativeItem*>( |
| value.value<QGraphicsItem*>())); |
| break; |
| case ItemChildRemovedChange: |
| if (d->_contents && d->componentComplete) |
| d->_contents->childRemoved(qobject_cast<QDeclarativeItem*>( |
| value.value<QGraphicsItem*>())); |
| break; |
| default: |
| break; |
| } |
| |
| return QGraphicsItem::itemChange(change, value); |
| } |
| |
| /*! \internal */ |
| QRectF QDeclarativeItem::boundingRect() const |
| { |
| Q_D(const QDeclarativeItem); |
| return QRectF(0, 0, d->mWidth, d->mHeight); |
| } |
| |
| /*! |
| \enum QDeclarativeItem::TransformOrigin |
| |
| Controls the point about which simple transforms like scale apply. |
| |
| \value TopLeft The top-left corner of the item. |
| \value Top The center point of the top of the item. |
| \value TopRight The top-right corner of the item. |
| \value Left The left most point of the vertical middle. |
| \value Center The center of the item. |
| \value Right The right most point of the vertical middle. |
| \value BottomLeft The bottom-left corner of the item. |
| \value Bottom The center point of the bottom of the item. |
| \value BottomRight The bottom-right corner of the item. |
| */ |
| |
| /*! |
| Returns the current transform origin. |
| */ |
| QDeclarativeItem::TransformOrigin QDeclarativeItem::transformOrigin() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->origin; |
| } |
| |
| /*! |
| Set the transform \a origin. |
| */ |
| void QDeclarativeItem::setTransformOrigin(TransformOrigin origin) |
| { |
| Q_D(QDeclarativeItem); |
| if (origin != d->origin) { |
| d->origin = origin; |
| if (d->transformData) |
| QGraphicsItem::setTransformOriginPoint(d->computeTransformOrigin()); |
| else |
| d->transformOriginDirty = true; |
| emit transformOriginChanged(d->origin); |
| } |
| } |
| |
| void QDeclarativeItemPrivate::transformChanged() |
| { |
| Q_Q(QDeclarativeItem); |
| if (transformOriginDirty) { |
| q->QGraphicsItem::setTransformOriginPoint(computeTransformOrigin()); |
| transformOriginDirty = false; |
| } |
| } |
| |
| /*! |
| \property QDeclarativeItem::smooth |
| \brief whether the item is smoothly transformed. |
| |
| This property is provided purely for the purpose of optimization. Turning |
| smooth transforms off is faster, but looks worse; turning smooth |
| transformations on is slower, but looks better. |
| |
| By default smooth transformations are off. |
| */ |
| |
| /*! |
| Returns true if the item should be drawn with antialiasing and |
| smooth pixmap filtering, false otherwise. |
| |
| The default is false. |
| |
| \sa setSmooth() |
| */ |
| bool QDeclarativeItem::smooth() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->smooth; |
| } |
| |
| /*! |
| Sets whether the item should be drawn with antialiasing and |
| smooth pixmap filtering to \a smooth. |
| |
| \sa smooth() |
| */ |
| void QDeclarativeItem::setSmooth(bool smooth) |
| { |
| Q_D(QDeclarativeItem); |
| if (d->smooth == smooth) |
| return; |
| d->smooth = smooth; |
| emit smoothChanged(smooth); |
| update(); |
| } |
| |
| /*! |
| \property QDeclarativeItem::anchors |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::left |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::right |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::horizontalCenter |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::top |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::bottom |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::verticalCenter |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::focus |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::transform |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::transformOrigin |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::activeFocus |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::baseline |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::data |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::resources |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::state |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::states |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::transformOriginPoint |
| \internal |
| */ |
| |
| /*! |
| \property QDeclarativeItem::transitions |
| \internal |
| */ |
| |
| /*! |
| \internal |
| Return the width of the item |
| */ |
| qreal QDeclarativeItem::width() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->width(); |
| } |
| |
| /*! |
| \internal |
| Set the width of the item |
| */ |
| void QDeclarativeItem::setWidth(qreal w) |
| { |
| Q_D(QDeclarativeItem); |
| d->setWidth(w); |
| } |
| |
| /*! |
| \internal |
| Reset the width of the item |
| */ |
| void QDeclarativeItem::resetWidth() |
| { |
| Q_D(QDeclarativeItem); |
| d->resetWidth(); |
| } |
| |
| /*! |
| \internal |
| Return the width of the item |
| */ |
| qreal QDeclarativeItemPrivate::width() const |
| { |
| return mWidth; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItemPrivate::setWidth(qreal w) |
| { |
| Q_Q(QDeclarativeItem); |
| if (qIsNaN(w)) |
| return; |
| |
| widthValid = true; |
| if (mWidth == w) |
| return; |
| |
| qreal oldWidth = mWidth; |
| |
| q->prepareGeometryChange(); |
| mWidth = w; |
| |
| q->geometryChanged(QRectF(q->x(), q->y(), width(), height()), |
| QRectF(q->x(), q->y(), oldWidth, height())); |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItemPrivate::resetWidth() |
| { |
| Q_Q(QDeclarativeItem); |
| widthValid = false; |
| q->setImplicitWidth(q->implicitWidth()); |
| } |
| |
| void QDeclarativeItemPrivate::implicitWidthChanged() |
| { |
| Q_Q(QDeclarativeItem); |
| emit q->implicitWidthChanged(); |
| } |
| |
| qreal QDeclarativeItemPrivate::implicitWidth() const |
| { |
| return mImplicitWidth; |
| } |
| |
| /*! |
| Returns the width of the item that is implied by other properties that determine the content. |
| */ |
| qreal QDeclarativeItem::implicitWidth() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->implicitWidth(); |
| } |
| |
| /*! |
| Sets the implied width of the item to \a w. |
| This is the width implied by other properties that determine the content. |
| */ |
| void QDeclarativeItem::setImplicitWidth(qreal w) |
| { |
| Q_D(QDeclarativeItem); |
| bool changed = w != d->mImplicitWidth; |
| d->mImplicitWidth = w; |
| if (d->mWidth == w || widthValid()) { |
| if (changed) |
| d->implicitWidthChanged(); |
| return; |
| } |
| |
| qreal oldWidth = d->mWidth; |
| |
| prepareGeometryChange(); |
| d->mWidth = w; |
| |
| geometryChanged(QRectF(x(), y(), width(), height()), |
| QRectF(x(), y(), oldWidth, height())); |
| |
| if (changed) |
| d->implicitWidthChanged(); |
| } |
| |
| /*! |
| Returns whether the width property has been set explicitly. |
| */ |
| bool QDeclarativeItem::widthValid() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->widthValid; |
| } |
| |
| /*! |
| \internal |
| Return the height of the item |
| */ |
| qreal QDeclarativeItem::height() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->height(); |
| } |
| |
| /*! |
| \internal |
| Set the height of the item |
| */ |
| void QDeclarativeItem::setHeight(qreal h) |
| { |
| Q_D(QDeclarativeItem); |
| d->setHeight(h); |
| } |
| |
| /*! |
| \internal |
| Reset the height of the item |
| */ |
| void QDeclarativeItem::resetHeight() |
| { |
| Q_D(QDeclarativeItem); |
| d->resetHeight(); |
| } |
| |
| /*! |
| \internal |
| */ |
| qreal QDeclarativeItemPrivate::height() const |
| { |
| return mHeight; |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItemPrivate::setHeight(qreal h) |
| { |
| Q_Q(QDeclarativeItem); |
| if (qIsNaN(h)) |
| return; |
| |
| heightValid = true; |
| if (mHeight == h) |
| return; |
| |
| qreal oldHeight = mHeight; |
| |
| q->prepareGeometryChange(); |
| mHeight = h; |
| |
| q->geometryChanged(QRectF(q->x(), q->y(), width(), height()), |
| QRectF(q->x(), q->y(), width(), oldHeight)); |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItemPrivate::resetHeight() |
| { |
| Q_Q(QDeclarativeItem); |
| heightValid = false; |
| q->setImplicitHeight(q->implicitHeight()); |
| } |
| |
| void QDeclarativeItemPrivate::implicitHeightChanged() |
| { |
| Q_Q(QDeclarativeItem); |
| emit q->implicitHeightChanged(); |
| } |
| |
| qreal QDeclarativeItemPrivate::implicitHeight() const |
| { |
| return mImplicitHeight; |
| } |
| |
| /*! |
| Returns the height of the item that is implied by other properties that determine the content. |
| */ |
| qreal QDeclarativeItem::implicitHeight() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->implicitHeight(); |
| } |
| |
| /*! |
| \qmlproperty real Item::implicitWidth |
| \qmlproperty real Item::implicitHeight |
| \since QtQuick 1.1 |
| |
| Defines the natural width or height of the Item if no \l width or \l height is specified. |
| |
| The default implicit size for most items is 0x0, however some elements have an inherent |
| implicit size which cannot be overridden, e.g. Image, Text. |
| |
| Setting the implicit size is useful for defining components that have a preferred size |
| based on their content, for example: |
| |
| \qml |
| // Label.qml |
| import QtQuick 1.1 |
| |
| Item { |
| property alias icon: image.source |
| property alias label: text.text |
| implicitWidth: text.implicitWidth + image.implicitWidth |
| implicitHeight: Math.max(text.implicitHeight, image.implicitHeight) |
| Image { id: image } |
| Text { |
| id: text |
| wrapMode: Text.Wrap |
| anchors.left: image.right; anchors.right: parent.right |
| anchors.verticalCenter: parent.verticalCenter |
| } |
| } |
| \endqml |
| |
| \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly |
| incurs a performance penalty as the text must be laid out twice. |
| */ |
| |
| |
| /*! |
| Sets the implied height of the item to \a h. |
| This is the height implied by other properties that determine the content. |
| */ |
| void QDeclarativeItem::setImplicitHeight(qreal h) |
| { |
| Q_D(QDeclarativeItem); |
| bool changed = h != d->mImplicitHeight; |
| d->mImplicitHeight = h; |
| if (d->mHeight == h || heightValid()) { |
| if (changed) |
| d->implicitHeightChanged(); |
| return; |
| } |
| |
| qreal oldHeight = d->mHeight; |
| |
| prepareGeometryChange(); |
| d->mHeight = h; |
| |
| geometryChanged(QRectF(x(), y(), width(), height()), |
| QRectF(x(), y(), width(), oldHeight)); |
| |
| if (changed) |
| d->implicitHeightChanged(); |
| } |
| |
| /*! |
| Returns whether the height property has been set explicitly. |
| */ |
| bool QDeclarativeItem::heightValid() const |
| { |
| Q_D(const QDeclarativeItem); |
| return d->heightValid; |
| } |
| |
| /*! \internal */ |
| void QDeclarativeItem::setSize(const QSizeF &size) |
| { |
| Q_D(QDeclarativeItem); |
| d->heightValid = true; |
| d->widthValid = true; |
| |
| if (d->height() == size.height() && d->width() == size.width()) |
| return; |
| |
| qreal oldHeight = d->height(); |
| qreal oldWidth = d->width(); |
| |
| prepareGeometryChange(); |
| d->setHeight(size.height()); |
| d->setWidth(size.width()); |
| |
| geometryChanged(QRectF(x(), y(), width(), height()), |
| QRectF(x(), y(), oldWidth, oldHeight)); |
| } |
| |
| /*! |
| \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::hasActiveFocus() const |
| { |
| Q_D(const QDeclarativeItem); |
| return focusItem() == this || |
| (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0); |
| } |
| |
| /*! |
| \qmlproperty bool Item::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 scene as a whole is assumed to act like a focus scope. |
| 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 |
| { |
| Q_D(const QDeclarativeItem); |
| QGraphicsItem *p = d->parent; |
| while (p) { |
| if (p->flags() & QGraphicsItem::ItemIsFocusScope) { |
| return p->focusScopeItem() == this; |
| } |
| p = p->parentItem(); |
| } |
| |
| return hasActiveFocus(); |
| } |
| |
| /*! \internal */ |
| void QDeclarativeItem::setFocus(bool focus) |
| { |
| if (focus) |
| QGraphicsItem::setFocus(Qt::OtherFocusReason); |
| else |
| QGraphicsItem::clearFocus(); |
| } |
| |
| /*! |
| \internal |
| */ |
| void QDeclarativeItem::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) |
| { |
| } |
| |
| /*! |
| \internal |
| */ |
| bool QDeclarativeItem::event(QEvent *ev) |
| { |
| Q_D(QDeclarativeItem); |
| switch (ev->type()) { |
| case QEvent::KeyPress: |
| case QEvent::KeyRelease: |
| case QEvent::InputMethod: |
| d->doneEventPreHandler = false; |
| break; |
| default: |
| break; |
| } |
| |
| return QGraphicsObject::event(ev); |
| } |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| QDebug operator<<(QDebug debug, QDeclarativeItem *item) |
| { |
| if (!item) { |
| debug << "QDeclarativeItem(0)"; |
| return debug; |
| } |
| |
| debug << item->metaObject()->className() << "(this =" << ((void*)item) |
| << ", parent =" << ((void*)item->parentItem()) |
| << ", geometry =" << QRectF(item->pos(), QSizeF(item->width(), item->height())) |
| << ", z =" << item->zValue() << ')'; |
| return debug; |
| } |
| #endif |
| |
| qint64 QDeclarativeItemPrivate::consistentTime = -1; |
| void QDeclarativeItemPrivate::setConsistentTime(qint64 t) |
| { |
| consistentTime = t; |
| } |
| |
| class QElapsedTimerConsistentTimeHack |
| { |
| 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(); |
| } |
| |
| qint64 QDeclarativeItemPrivate::elapsed(QElapsedTimer &t) |
| { |
| 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 |
| |
| #include <moc_qdeclarativeitem.cpp> |