/**************************************************************************** | |
** | |
** 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> |