/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
**
**
**
+**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qquickitem.h"
#include "qquickcanvas.h"
-#include <QtDeclarative/qjsengine.h>
+#include <QtQml/qjsengine.h>
#include "qquickcanvas_p.h"
#include "qquickevents_p_p.h"
+#include "qquickscreen_p.h"
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlinfo.h>
#include <QtGui/qpen.h>
#include <QtGui/qcursor.h>
#include <QtGui/qguiapplication.h>
-#include <QtGui/qinputpanel.h>
+#include <QtGui/qinputmethod.h>
#include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qnumeric.h>
-#include <private/qdeclarativeengine_p.h>
-#include <QtQuick/private/qdeclarativestategroup_p.h>
-#include <private/qdeclarativeopenmetaobject_p.h>
-#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qqmlglobal_p.h>
+#include <private/qqmlengine_p.h>
+#include <QtQuick/private/qquickstategroup_p.h>
+#include <private/qqmlopenmetaobject_p.h>
+#include <QtQuick/private/qquickstate_p.h>
#include <private/qlistmodelinterface_p.h>
#include <private/qquickitem_p.h>
+#include <private/qqmlaccessors_p.h>
+#include <QtQuick/private/qquickaccessibleattached_p.h>
#include <float.h>
-// XXX todo Readd parentNotifier for faster parent bindings
// XXX todo Check that elements that create items handle memory correctly after visual ownership change
QT_BEGIN_NAMESPACE
+static void QQuickItem_parentNotifier(QObject *o, intptr_t, QQmlNotifier **n)
+{
+ QQuickItemPrivate *d = QQuickItemPrivate::get(static_cast<QQuickItem *>(o));
+ *n = &d->parentNotifier;
+}
+
+QML_PRIVATE_ACCESSOR(QQuickItem, QQuickItem *, parent, parentItem)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, x, x)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, y, y)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, width, width)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, height, height)
+
+static QQmlAccessors QQuickItem_parent = { QQuickItem_parentRead, QQuickItem_parentNotifier };
+static QQmlAccessors QQuickItem_x = { QQuickItem_xRead, 0 };
+static QQmlAccessors QQuickItem_y = { QQuickItem_yRead, 0 };
+static QQmlAccessors QQuickItem_width = { QQuickItem_widthRead, 0 };
+static QQmlAccessors QQuickItem_height = { QQuickItem_heightRead, 0 };
+
+QML_DECLARE_PROPERTIES(QQuickItem) {
+ { QML_PROPERTY_NAME(parent), 0, &QQuickItem_parent },
+ { QML_PROPERTY_NAME(x), 0, &QQuickItem_x },
+ { QML_PROPERTY_NAME(y), 0, &QQuickItem_y },
+ { QML_PROPERTY_NAME(width), 0, &QQuickItem_width },
+ { QML_PROPERTY_NAME(height), 0, &QQuickItem_height }
+};
+
+void QQuickItemPrivate::registerAccessorProperties()
+{
+ QML_DEFINE_PROPERTIES(QQuickItem);
+}
+
/*!
\qmlclass Transform QQuickTransform
\inqmlmodule QtQuick 2
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
+ import QtQuick 2.0
Row {
Rectangle {
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
+ \snippet doc/src/snippets/qml/rotation.qml 0
\image axisrotation.png
{
QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):0;
if (p) {
- m_next = p->keyHandler;
- p->keyHandler = this;
+ m_next = p->extra.value().keyHandler;
+ p->extra->keyHandler = this;
}
}
The following example provides key navigation for a 2x2 grid of items:
- \snippet doc/src/snippets/declarative/keynavigation.qml 0
+ \snippet doc/src/snippets/qml/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
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
+ \snippet doc/src/snippets/qml/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
+ \snippet doc/src/snippets/qml/keys/keys-handler.qml key item
See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
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
+ \snippet doc/src/snippets/qml/layoutmirroring.qml 0
\image layoutmirroring.png
{
if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
itemPrivate = QQuickItemPrivate::get(item);
- itemPrivate->attachedLayoutDirection = this;
+ itemPrivate->extra.value().layoutDirectionAttached = this;
} else
qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
}
emit _anchors->mirroredChanged();
}
mirrorChange();
- if (attachedLayoutDirection) {
- emit attachedLayoutDirection->enabledChanged();
+ if (extra.isAllocated() && extra->layoutDirectionAttached) {
+ emit extra->layoutDirectionAttached->enabledChanged();
}
}
}
+void QQuickItemPrivate::setAccessibleFlagAndListener()
+{
+ Q_Q(QQuickItem);
+ QQuickItem *item = q;
+ while (item) {
+ if (item->d_func()->isAccessible)
+ break; // already set - grandparents should have the flag set as well.
+
+ if (item->canvas() && item->canvas()->rootItem() == item)
+ break; // don't add a listener to the canvas root item
+
+ item->d_func()->isAccessible = true;
+ item = item->d_func()->parentItem;
+ }
+}
+
/*!
\class QQuickItem
\brief The QQuickItem class provides the most basic of all visual items in QML.
\inmodule QtQuick
- All visual items in Qt Declarative inherit from QQuickItem. Although QQuickItem
+ All visual items in Qt Quick inherit from QQuickItem. Although QQuickItem
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.
/*!
\qmlclass Item QQuickItem
+ \inherits QtObject
\inqmlmodule QtQuick 2
\ingroup qml-basic-visual-elements
\brief The Item is the most basic of all visual items in QML.
- All visual items in Qt Declarative inherit from Item. Although Item
+ All visual items in Qt Quick 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.
if (change.types & QQuickItemPrivate::Destroyed)
change.listener->itemDestroyed(this);
}
+
d->changeListeners.clear();
- delete d->_anchorLines; d->_anchorLines = 0;
+
+ if (d->extra.isAllocated()) {
+ delete d->extra->contents; d->extra->contents = 0;
+ delete d->extra->layer; d->extra->layer = 0;
+ }
+
delete d->_anchors; d->_anchors = 0;
delete d->_stateGroup; d->_stateGroup = 0;
- delete d->_contents; d->_contents = 0;
}
/*!
if (parentItem == d->parentItem)
return;
+ if (parentItem) {
+ QQuickItem *itemAncestor = parentItem->parentItem();
+ while (itemAncestor != 0) {
+ if (itemAncestor == this) {
+ qWarning("QQuickItem::setParentItem: Parent is already part of this items subtree.");
+ return;
+ }
+ itemAncestor = itemAncestor->parentItem();
+ }
+ }
+
d->removeFromDirtyList();
QQuickItem *oldParentItem = d->parentItem;
QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
QQuickCanvasPrivate::DontChangeFocusProperty);
+ const bool wasVisible = isVisible();
op->removeChild(this);
+ if (wasVisible) {
+ emit oldParentItem->visibleChildrenChanged();
+ }
+ } else if (d->canvas) {
+ QQuickCanvasPrivate::get(d->canvas)->parentlessItems.remove(this);
}
d->parentItem = parentItem;
QQuickItemPrivate::get(d->parentItem)->addChild(this);
d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
- d->setEffectiveEnableRecur(d->calcEffectiveEnable());
+ d->setEffectiveEnableRecur(0, d->calcEffectiveEnable());
if (scopeFocusedItem && d->parentItem && d->canvas) {
// We need to test whether this item becomes scope focused
d->itemChange(ItemParentHasChanged, d->parentItem);
+ d->parentNotifier.notify();
+ if (d->isAccessible && d->parentItem) {
+ d->parentItem->d_func()->setAccessibleFlagAndListener();
+ }
+
emit parentChanged(d->parentItem);
+ if (isVisible() && d->parentItem)
+ emit d->parentItem->visibleChildrenChanged();
}
void QQuickItem::stackBefore(const QQuickItem *sibling)
// the childItems list. This is by far the most common case.
bool haveZ = false;
for (int i = 0; i < childItems.count(); ++i) {
- if (QQuickItemPrivate::get(childItems.at(i))->z != 0.) {
+ if (QQuickItemPrivate::get(childItems.at(i))->z() != 0.) {
haveZ = true;
break;
}
{
if (!focusScope) {
QQuickItem *fs = item->parentItem();
- while (!fs->isFocusScope())
+ while (fs->parentItem() && !fs->isFocusScope())
fs = fs->parentItem();
focusScope = fs;
}
c->hoverItems.removeAll(q);
if (itemNodeInstance)
c->cleanup(itemNodeInstance);
+ if (!parentItem)
+ c->parentlessItems.remove(q);
}
canvas = c;
QQuickCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
itemNodeInstance = 0;
- opacityNode = 0;
- clipNode = 0;
- rootNode = 0;
+
+ if (extra.isAllocated()) {
+ extra->opacityNode = 0;
+ extra->clipNode = 0;
+ extra->rootNode = 0;
+ extra->beforePaintNode = 0;
+ }
+
groupNode = 0;
paintNode = 0;
- beforePaintNode = 0;
InitializationState _dummy;
InitializationState *childState = state;
childState = &_dummy;
}
+ if (!parentItem && canvas)
+ QQuickCanvasPrivate::get(canvas)->parentlessItems.insert(q);
+
for (int ii = 0; ii < childItems.count(); ++ii) {
QQuickItem *child = childItems.at(ii);
QQuickItemPrivate::get(child)->initCanvas(childState, c);
dirty(Canvas);
+ if (extra.isAllocated() && extra->screenAttached)
+ extra->screenAttached->canvasChanged(c);
itemChange(QQuickItem::ItemSceneChange, c);
}
t = m.toTransform();
}
- if (scale != 1. || rotation != 0.) {
+ if (scale() != 1. || rotation() != 0.) {
QPointF tp = computeTransformOrigin();
t.translate(tp.x(), tp.y());
- t.scale(scale, scale);
- t.rotate(rotation);
+ t.scale(scale(), scale());
+ t.rotate(rotation());
t.translate(-tp.x(), -tp.y());
}
}
}
QQuickItemPrivate::QQuickItemPrivate()
-: _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QQuickItem::Center),
-
- flags(0), widthValid(false), heightValid(false), componentComplete(true),
+: _anchors(0), _stateGroup(0),
+ flags(0), widthValid(false), heightValid(false), baselineOffsetValid(false), componentComplete(true),
keepMouse(false), keepTouch(false), hoverEnabled(false), smooth(false), focus(false), activeFocus(false), notifiedFocus(false),
notifiedActiveFocus(false), filtersChildMouseEvents(false), explicitVisible(true),
effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false),
inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
inheritMirrorFromParent(false), inheritMirrorFromItem(false), childrenDoNotOverlap(false),
+ staticSubtreeGeometry(false),
+ isAccessible(false),
+
+ dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
canvas(0), parentItem(0), sortedChildItems(&childItems),
subFocusItem(0),
x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
- z(0), scale(1), rotation(0), opacity(1),
-
- attachedLayoutDirection(0), acceptedMouseButtons(0),
- imHints(Qt::ImhMultiLine),
-
- keyHandler(0),
- dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
+ baselineOffset(0),
- itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
- , beforePaintNode(0), effectRefCount(0), hideRefCount(0)
+ itemNodeInstance(0), groupNode(0), paintNode(0)
{
}
#endif
Q_Q(QQuickItem);
- baselineOffset.invalidate();
+
+ registerAccessorProperties();
+
+ baselineOffsetValid = false;
if (parent) {
q->setParentItem(parent);
}
}
-void QQuickItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
{
if (!o)
return;
specify it.
*/
-int QQuickItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
+int QQuickItemPrivate::data_count(QQmlListProperty<QObject> *prop)
{
Q_UNUSED(prop);
// XXX todo
return 0;
}
-QObject *QQuickItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
+QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *prop, int i)
{
Q_UNUSED(prop);
Q_UNUSED(i);
return 0;
}
-void QQuickItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
+void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *prop)
{
Q_UNUSED(prop);
// XXX todo
}
-QObject *QQuickItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
+QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, int index)
{
const QObjectList children = prop->object->children();
if (index < children.count())
return 0;
}
-void QQuickItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *o)
{
// XXX todo - do we really want this behavior?
o->setParent(prop->object);
}
-int QQuickItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
+int QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
{
return prop->object->children().count();
}
-void QQuickItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
+void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
{
// XXX todo - do we really want this behavior?
const QObjectList children = prop->object->children();
children.at(index)->setParent(0);
}
-QQuickItem *QQuickItemPrivate::children_at(QDeclarativeListProperty<QQuickItem> *prop, int index)
+QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, int index)
{
QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
if (index >= p->childItems.count() || index < 0)
return p->childItems.at(index);
}
-void QQuickItemPrivate::children_append(QDeclarativeListProperty<QQuickItem> *prop, QQuickItem *o)
+void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *o)
{
if (!o)
return;
o->setParentItem(that);
}
-int QQuickItemPrivate::children_count(QDeclarativeListProperty<QQuickItem> *prop)
+int QQuickItemPrivate::children_count(QQmlListProperty<QQuickItem> *prop)
{
QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
return p->childItems.count();
}
-void QQuickItemPrivate::children_clear(QDeclarativeListProperty<QQuickItem> *prop)
+void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
{
QQuickItem *that = static_cast<QQuickItem *>(prop->object);
QQuickItemPrivate *p = QQuickItemPrivate::get(that);
p->childItems.at(0)->setParentItem(0);
}
-int QQuickItemPrivate::transform_count(QDeclarativeListProperty<QQuickTransform> *prop)
+void QQuickItemPrivate::visibleChildren_append(QQmlListProperty<QQuickItem>*, QQuickItem *self)
+{
+ // do nothing
+ qmlInfo(self) << "QQuickItem: visibleChildren property is readonly and cannot be assigned to.";
+}
+
+int QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
+{
+ QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+ int visibleCount = 0;
+ int c = p->childItems.count();
+ while (c--) {
+ if (p->childItems.at(c)->isVisible()) visibleCount++;
+ }
+
+ return visibleCount;
+}
+
+QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> *prop, int index)
+{
+ QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+ const int childCount = p->childItems.count();
+ if (index >= childCount || index < 0)
+ return 0;
+
+ int visibleCount = -1;
+ for (int i = 0; i < childCount; i++) {
+ if (p->childItems.at(i)->isVisible()) visibleCount++;
+ if (visibleCount == index) return p->childItems.at(i);
+ }
+ return 0;
+}
+
+int QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop)
{
QQuickItem *that = static_cast<QQuickItem *>(prop->object);
- return QQuickItemPrivate::get(that)->transforms.count();
+ QQuickItemPrivate *p = QQuickItemPrivate::get(that);
+
+ return p->transforms.count();
}
void QQuickTransform::appendToItem(QQuickItem *item)
p->dirty(QQuickItemPrivate::Transform);
}
-void QQuickItemPrivate::transform_append(QDeclarativeListProperty<QQuickTransform> *prop, QQuickTransform *transform)
+void QQuickItemPrivate::transform_append(QQmlListProperty<QQuickTransform> *prop, QQuickTransform *transform)
{
if (!transform)
return;
transform->appendToItem(that);
}
-QQuickTransform *QQuickItemPrivate::transform_at(QDeclarativeListProperty<QQuickTransform> *prop, int idx)
+QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransform> *prop, int idx)
{
QQuickItem *that = static_cast<QQuickItem *>(prop->object);
QQuickItemPrivate *p = QQuickItemPrivate::get(that);
return p->transforms.at(idx);
}
-void QQuickItemPrivate::transform_clear(QDeclarativeListProperty<QQuickTransform> *prop)
+void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
{
QQuickItem *that = static_cast<QQuickItem *>(prop->object);
QQuickItemPrivate *p = QQuickItemPrivate::get(that);
return _anchors;
}
-QQuickItemPrivate::AnchorLines *QQuickItemPrivate::anchorLines() const
-{
- Q_Q(const QQuickItem);
- if (!_anchorLines) _anchorLines =
- new AnchorLines(const_cast<QQuickItem *>(q));
- return _anchorLines;
-}
-
void QQuickItemPrivate::siblingOrderChanged()
{
Q_Q(QQuickItem);
}
}
-QDeclarativeListProperty<QObject> QQuickItemPrivate::data()
+QQmlListProperty<QObject> QQuickItemPrivate::data()
{
- return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append,
+ return QQmlListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append,
QQuickItemPrivate::data_count,
QQuickItemPrivate::data_at,
QQuickItemPrivate::data_clear);
QRectF QQuickItem::childrenRect()
{
Q_D(QQuickItem);
- if (!d->_contents) {
- d->_contents = new QQuickContents(this);
+ if (!d->extra.isAllocated() || !d->extra->contents) {
+ d->extra.value().contents = new QQuickContents(this);
if (d->componentComplete)
- d->_contents->complete();
+ d->extra->contents->complete();
}
- return d->_contents->rectF();
+ return d->extra->contents->rectF();
}
QList<QQuickItem *> QQuickItem::childItems() const
{
}
+void QQuickItem::sendAccessibilityUpdate()
+{
+}
+
+void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
+{
+ changeListeners.append(ChangeListener(listener, types));
+}
+
void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
{
ChangeListener change(listener, types);
changeListeners.append(change);
}
-void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
+void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
+ GeometryChangeTypes types)
{
ChangeListener change(listener, types);
if (types == NoChange) {
void QQuickItem::focusInEvent(QFocusEvent *)
{
+ QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, 0));
}
void QQuickItem::focusOutEvent(QFocusEvent *)
}
}
-Qt::InputMethodHints QQuickItem::inputMethodHints() const
-{
- Q_D(const QQuickItem);
- return d->imHints;
-}
-
-void QQuickItem::setInputMethodHints(Qt::InputMethodHints hints)
-{
- Q_D(QQuickItem);
- d->imHints = hints;
-
- if (!d->canvas || d->canvas->activeFocusItem() != this)
- return;
-
- QInputPanel *p = qApp->inputPanel();
- if (p->inputItem() == this)
- qApp->inputPanel()->update(Qt::ImHints);
-}
-
-void QQuickItem::updateMicroFocus()
-{
- QInputPanel *p = qApp->inputPanel();
- if (p->inputItem() == this)
- qApp->inputPanel()->update(Qt::ImQueryInput);
-}
-
QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QQuickItem);
v = (bool)(flags() & ItemAcceptsInputMethod);
break;
case Qt::ImHints:
- v = (int)inputMethodHints();
- break;
case Qt::ImCursorRectangle:
case Qt::ImFont:
case Qt::ImCursorPosition:
case Qt::ImMaximumTextLength:
case Qt::ImAnchorPosition:
case Qt::ImPreferredLanguage:
- if (d->keyHandler)
- v = d->keyHandler->inputMethodQuery(query);
+ if (d->extra.isAllocated() && d->extra->keyHandler)
+ v = d->extra->keyHandler->inputMethodQuery(query);
default:
break;
}
QQuickAnchorLine QQuickItemPrivate::left() const
{
- return anchorLines()->left;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Left);
}
QQuickAnchorLine QQuickItemPrivate::right() const
{
- return anchorLines()->right;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Right);
}
QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
{
- return anchorLines()->hCenter;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::HCenter);
}
QQuickAnchorLine QQuickItemPrivate::top() const
{
- return anchorLines()->top;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Top);
}
QQuickAnchorLine QQuickItemPrivate::bottom() const
{
- return anchorLines()->bottom;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Bottom);
}
QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
{
- return anchorLines()->vCenter;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::VCenter);
}
QQuickAnchorLine QQuickItemPrivate::baseline() const
{
- return anchorLines()->baseline;
+ Q_Q(const QQuickItem);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Baseline);
}
qreal QQuickItem::baselineOffset() const
{
Q_D(const QQuickItem);
- if (!d->baselineOffset.isValid()) {
- return 0.0;
- } else
+ if (d->baselineOffsetValid) {
return d->baselineOffset;
+ } else {
+ return 0.0;
+ }
}
void QQuickItem::setBaselineOffset(qreal offset)
return;
d->baselineOffset = offset;
+ d->baselineOffsetValid = true;
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
}
}
-void QQuickItem::mapFromItem(QDeclarativeV8Function *args) const
+void QQuickItem::mapFromItem(QQmlV8Function *args) const
{
if (args->Length() != 0) {
v8::Local<v8::Value> item = (*args)[0];
return t;
}
-void QQuickItem::mapToItem(QDeclarativeV8Function *args) const
+void QQuickItem::mapToItem(QQmlV8Function *args) const
{
if (args->Length() != 0) {
v8::Local<v8::Value> item = (*args)[0];
return 0;
}
-QDeclarativeListProperty<QObject> QQuickItemPrivate::resources()
+QQmlListProperty<QObject> QQuickItemPrivate::resources()
{
- return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append,
+ return QQmlListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append,
QQuickItemPrivate::resources_count,
QQuickItemPrivate::resources_at,
QQuickItemPrivate::resources_clear);
}
-QDeclarativeListProperty<QQuickItem> QQuickItemPrivate::children()
+QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
{
- return QDeclarativeListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append,
+ return QQmlListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append,
QQuickItemPrivate::children_count,
QQuickItemPrivate::children_at,
QQuickItemPrivate::children_clear);
}
-QDeclarativeListProperty<QDeclarativeState> QQuickItemPrivate::states()
+/*!
+ \qmlproperty real QtQuick2::Item::visibleChildren
+ This read-only property lists all of the item's children that are currently visible.
+ Note that a child's visibility may have changed explicitly, or because the visibility
+ of this (it's parent) item or another grandparent changed.
+*/
+QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren()
+{
+ return QQmlListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::visibleChildren_append,
+ QQuickItemPrivate::visibleChildren_count,
+ QQuickItemPrivate::visibleChildren_at);
+
+}
+
+QQmlListProperty<QQuickState> QQuickItemPrivate::states()
{
return _states()->statesProperty();
}
-QDeclarativeListProperty<QDeclarativeTransition> QQuickItemPrivate::transitions()
+QQmlListProperty<QQuickTransition> QQuickItemPrivate::transitions()
{
return _states()->transitionsProperty();
}
d->setState(state);
}
-QDeclarativeListProperty<QQuickTransform> QQuickItem::transform()
+QQmlListProperty<QQuickTransform> QQuickItem::transform()
{
- return QDeclarativeListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append,
+ return QQmlListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append,
QQuickItemPrivate::transform_count,
QQuickItemPrivate::transform_at,
QQuickItemPrivate::transform_clear);
d->_stateGroup->classBegin();
if (d->_anchors)
d->_anchors->classBegin();
+ if (d->extra.isAllocated() && d->extra->layer)
+ d->extra->layer->classBegin();
}
void QQuickItem::componentComplete()
d->_anchors->componentComplete();
QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete();
}
- if (d->keyHandler)
- d->keyHandler->componentComplete();
- if (d->_contents)
- d->_contents->complete();
+
+ if (d->extra.isAllocated() && d->extra->layer)
+ d->extra->layer->componentComplete();
+
+ if (d->extra.isAllocated() && d->extra->keyHandler)
+ d->extra->keyHandler->componentComplete();
+
+ if (d->extra.isAllocated() && d->extra->contents)
+ d->extra->contents->complete();
}
-QDeclarativeStateGroup *QQuickItemPrivate::_states()
+QQuickStateGroup *QQuickItemPrivate::_states()
{
Q_Q(QQuickItem);
if (!_stateGroup) {
- _stateGroup = new QDeclarativeStateGroup;
+ _stateGroup = new QQuickStateGroup;
if (!componentComplete)
_stateGroup->classBegin();
FAST_CONNECT(_stateGroup, SIGNAL(stateChanged(QString)),
return _stateGroup;
}
-QQuickItemPrivate::AnchorLines::AnchorLines(QQuickItem *q)
-{
- left.item = q;
- left.anchorLine = QQuickAnchorLine::Left;
- right.item = q;
- right.anchorLine = QQuickAnchorLine::Right;
- hCenter.item = q;
- hCenter.anchorLine = QQuickAnchorLine::HCenter;
- top.item = q;
- top.anchorLine = QQuickAnchorLine::Top;
- bottom.item = q;
- bottom.anchorLine = QQuickAnchorLine::Bottom;
- vCenter.item = q;
- vCenter.anchorLine = QQuickAnchorLine::VCenter;
- baseline.item = q;
- baseline.anchorLine = QQuickAnchorLine::Baseline;
-}
-
QPointF QQuickItemPrivate::computeTransformOrigin() const
{
- switch (origin) {
+ switch (origin()) {
default:
case QQuickItem::TopLeft:
return QPointF(0, 0);
void QQuickItemPrivate::transformChanged()
{
+ if (extra.isAllocated() && extra->layer)
+ extra->layer->updateMatrix();
}
void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
Q_Q(QQuickItem);
Q_ASSERT(e->isAccepted());
- if (keyHandler) {
+ if (extra.isAllocated() && extra->keyHandler) {
if (e->type() == QEvent::KeyPress)
- keyHandler->keyPressed(e, false);
+ extra->keyHandler->keyPressed(e, false);
else
- keyHandler->keyReleased(e, false);
+ extra->keyHandler->keyReleased(e, false);
if (e->isAccepted())
return;
if (e->isAccepted())
return;
- if (keyHandler) {
+ if (extra.isAllocated() && extra->keyHandler) {
e->accept();
if (e->type() == QEvent::KeyPress)
- keyHandler->keyPressed(e, true);
+ extra->keyHandler->keyPressed(e, true);
else
- keyHandler->keyReleased(e, true);
+ extra->keyHandler->keyReleased(e, true);
}
}
Q_Q(QQuickItem);
Q_ASSERT(e->isAccepted());
- if (keyHandler) {
- keyHandler->inputMethodEvent(e, false);
+ if (extra.isAllocated() && extra->keyHandler) {
+ extra->keyHandler->inputMethodEvent(e, false);
if (e->isAccepted())
return;
if (e->isAccepted())
return;
- if (keyHandler) {
+ if (extra.isAllocated() && extra->keyHandler) {
e->accept();
- keyHandler->inputMethodEvent(e, true);
+ extra->keyHandler->inputMethodEvent(e, true);
}
}
Q_UNUSED(value);
}
+/*!
+ Notify input method on updated query values if needed. \a indicates changed attributes.
+*/
+void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
+{
+ if (hasActiveFocus())
+ qApp->inputMethod()->update(queries);
+}
+
/*! \internal */
// XXX todo - do we want/need this anymore?
// Note that it's now used for varying clip rect
QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
{
Q_D(const QQuickItem);
- return d->origin;
+ return d->origin();
}
void QQuickItem::setTransformOrigin(TransformOrigin origin)
{
Q_D(QQuickItem);
- if (origin == d->origin)
+ if (origin == d->origin())
return;
- d->origin = origin;
+ d->extra.value().origin = origin;
d->dirty(QQuickItemPrivate::TransformOrigin);
- emit transformOriginChanged(d->origin);
+ emit transformOriginChanged(d->origin());
}
QPointF QQuickItem::transformOriginPoint() const
{
Q_D(const QQuickItem);
- if (!d->transformOriginPoint.isNull())
- return d->transformOriginPoint;
+ if (d->extra.isAllocated() && !d->extra->userTransformOriginPoint.isNull())
+ return d->extra->userTransformOriginPoint;
return d->computeTransformOrigin();
}
void QQuickItem::setTransformOriginPoint(const QPointF &point)
{
Q_D(QQuickItem);
- if (d->transformOriginPoint == point)
+ if (d->extra.value().userTransformOriginPoint == point)
return;
- d->transformOriginPoint = point;
+ d->extra->userTransformOriginPoint = point;
d->dirty(QQuickItemPrivate::TransformOrigin);
}
qreal QQuickItem::z() const
{
Q_D(const QQuickItem);
- return d->z;
+ return d->z();
}
void QQuickItem::setZ(qreal v)
{
Q_D(QQuickItem);
- if (d->z == v)
+ if (d->z() == v)
return;
- d->z = v;
+ d->extra.value().z = v;
d->dirty(QQuickItemPrivate::ZValue);
if (d->parentItem) {
}
emit zChanged();
+
+ if (d->extra.isAllocated() && d->extra->layer)
+ d->extra->layer->updateZ();
}
qreal QQuickItem::rotation() const
{
Q_D(const QQuickItem);
- return d->rotation;
+ return d->rotation();
}
void QQuickItem::setRotation(qreal r)
{
Q_D(QQuickItem);
- if (d->rotation == r)
+ if (d->rotation() == r)
return;
- d->rotation = r;
+ d->extra.value().rotation = r;
d->dirty(QQuickItemPrivate::BasicTransform);
qreal QQuickItem::scale() const
{
Q_D(const QQuickItem);
- return d->scale;
+ return d->scale();
}
void QQuickItem::setScale(qreal s)
{
Q_D(QQuickItem);
- if (d->scale == s)
+ if (d->scale() == s)
return;
- d->scale = s;
+ d->extra.value().scale = s;
d->dirty(QQuickItemPrivate::BasicTransform);
qreal QQuickItem::opacity() const
{
Q_D(const QQuickItem);
- return d->opacity;
+ return d->opacity();
}
void QQuickItem::setOpacity(qreal o)
{
Q_D(QQuickItem);
- if (d->opacity == o)
+ if (d->opacity() == o)
return;
- d->opacity = o;
+ d->extra.value().opacity = o;
d->dirty(QQuickItemPrivate::OpacityValue);
d->explicitVisible = v;
- d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+ const bool childVisibilityChanged = d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+ if (childVisibilityChanged && d->parentItem)
+ emit d->parentItem->visibleChildrenChanged(); // signal the parent, not this!
}
bool QQuickItem::isEnabled() const
d->explicitEnable = e;
- d->setEffectiveEnableRecur(d->calcEffectiveEnable());
+ QQuickItem *scope = parentItem();
+ while (scope && !scope->isFocusScope())
+ scope = scope->parentItem();
+
+ d->setEffectiveEnableRecur(scope, d->calcEffectiveEnable());
}
bool QQuickItemPrivate::calcEffectiveVisible() const
return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
}
-void QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
+bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
{
Q_Q(QQuickItem);
if (newEffectiveVisible && !explicitVisible) {
// This item locally overrides visibility
- return;
+ return false; // effective visibility didn't change
}
if (newEffectiveVisible == effectiveVisible) {
// No change necessary
- return;
+ return false; // effective visibility didn't change
}
effectiveVisible = newEffectiveVisible;
q->ungrabMouse();
}
+ bool childVisibilityChanged = false;
for (int ii = 0; ii < childItems.count(); ++ii)
- QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
+ childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
- for (int ii = 0; ii < changeListeners.count(); ++ii) {
- const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
- if (change.types & QQuickItemPrivate::Visibility)
- change.listener->itemVisibilityChanged(q);
- }
+ itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible);
+
+ if (isAccessible)
+ QAccessible::updateAccessibility(QAccessibleEvent(effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide, q, 0));
emit q->visibleChanged();
+ if (childVisibilityChanged)
+ emit q->visibleChildrenChanged();
+
+ return true; // effective visibility DID change
}
bool QQuickItemPrivate::calcEffectiveEnable() const
return explicitEnable && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveEnable);
}
-void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
+void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffectiveEnable)
{
Q_Q(QQuickItem);
- // XXX todo - need to fixup focus
-
if (newEffectiveEnable && !explicitEnable) {
// This item locally overrides enable
return;
QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
if (canvasPriv->mouseGrabberItem == q)
q->ungrabMouse();
+ if (scope && !effectiveEnable && activeFocus) {
+ canvasPriv->clearFocusInScope(
+ scope, q, QQuickCanvasPrivate::DontChangeFocusProperty | QQuickCanvasPrivate::DontChangeSubFocusItem);
+ }
}
- for (int ii = 0; ii < childItems.count(); ++ii)
- QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
+ for (int ii = 0; ii < childItems.count(); ++ii) {
+ QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(
+ flags & QQuickItem::ItemIsFocusScope ? q : scope, newEffectiveEnable);
+ }
+
+ if (canvas && scope && effectiveEnable && focus) {
+ QQuickCanvasPrivate::get(canvas)->setFocusInScope(
+ scope, q, QQuickCanvasPrivate::DontChangeFocusProperty | QQuickCanvasPrivate::DontChangeSubFocusItem);
+ }
emit q->enabledChanged();
}
DIRTY_TO_STRING(EffectReference);
DIRTY_TO_STRING(Visible);
DIRTY_TO_STRING(HideReference);
+ DIRTY_TO_STRING(PerformanceHints);
return rv;
}
void QQuickItemPrivate::refFromEffectItem(bool hide)
{
- ++effectRefCount;
- if (1 == effectRefCount) {
+ ++extra.value().effectRefCount;
+ if (1 == extra->effectRefCount) {
dirty(EffectReference);
if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
}
if (hide) {
- if (++hideRefCount == 1)
+ if (++extra->hideRefCount == 1)
dirty(HideReference);
}
}
void QQuickItemPrivate::derefFromEffectItem(bool unhide)
{
- Q_ASSERT(effectRefCount);
- --effectRefCount;
- if (0 == effectRefCount) {
+ Q_ASSERT(extra->effectRefCount);
+ --extra->effectRefCount;
+ if (0 == extra->effectRefCount) {
dirty(EffectReference);
if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
}
if (unhide) {
- if (--hideRefCount == 0)
+ if (--extra->hideRefCount == 0)
dirty(HideReference);
}
}
\qml
// Label.qml
- import QtQuick 1.1
+ import QtQuick 2.0
Item {
property alias icon: image.source
Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
{
Q_D(const QQuickItem);
- return d->acceptedMouseButtons;
+ return d->acceptedMouseButtons();
}
void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
{
Q_D(QQuickItem);
- d->acceptedMouseButtons = buttons;
+ if (buttons & Qt::LeftButton)
+ d->extra.setFlag();
+ else
+ d->extra.clearFlag();
+
+ buttons &= ~Qt::LeftButton;
+ if (buttons || d->extra.isAllocated())
+ d->extra.value().acceptedMouseButtons = buttons;
}
bool QQuickItem::filtersChildMouseEvents() const
This function can be called from any thread.
*/
+bool QQuickItem::isTextureProvider() const
+{
+ Q_D(const QQuickItem);
+ return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
+ d->extra->layer->effectSource()->isTextureProvider() : false;
+}
+
/*!
\fn QSGTextureProvider *QQuickItem::textureProvider() const
This function may only be called on the rendering thread.
*/
+QSGTextureProvider *QQuickItem::textureProvider() const
+{
+ Q_D(const QQuickItem);
+ return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
+ d->extra->layer->effectSource()->textureProvider() : 0;
+}
+
+QQuickItemLayer *QQuickItemPrivate::layer() const
+{
+ if (!extra.isAllocated() || !extra->layer) {
+ extra.value().layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
+ if (!componentComplete)
+ extra->layer->classBegin();
+ }
+ return extra->layer;
+}
+
+QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
+ : m_item(item)
+ , m_enabled(false)
+ , m_mipmap(false)
+ , m_smooth(false)
+ , m_componentComplete(true)
+ , m_wrapMode(QQuickShaderEffectSource::ClampToEdge)
+ , m_format(QQuickShaderEffectSource::RGBA)
+ , m_name("source")
+ , m_effectComponent(0)
+ , m_effect(0)
+ , m_effectSource(0)
+{
+}
+
+QQuickItemLayer::~QQuickItemLayer()
+{
+ delete m_effectSource;
+ delete m_effect;
+}
+
+
+
+/*!
+ \qmlproperty bool QtQuick2::Item::layer.enabled
+
+ Holds wether the item is layered or not. Layering is disabled by default.
+
+ A layered item is rendered into an offscreen surface and cached until
+ it is changed. Enabling layering for complex QML item hierarchies can
+ some times be an optimization.
+
+ None of the other layer properties have any effect when the layer
+ is disabled.
+ */
+
+void QQuickItemLayer::setEnabled(bool e)
+{
+ if (e == m_enabled)
+ return;
+ m_enabled = e;
+ if (m_componentComplete) {
+ if (m_enabled)
+ activate();
+ else
+ deactivate();
+ }
+
+ emit enabledChanged(e);
+}
+
+void QQuickItemLayer::classBegin()
+{
+ Q_ASSERT(!m_effectSource);
+ Q_ASSERT(!m_effect);
+ m_componentComplete = false;
+}
+
+void QQuickItemLayer::componentComplete()
+{
+ Q_ASSERT(!m_componentComplete);
+ m_componentComplete = true;
+ if (m_enabled)
+ activate();
+}
+
+void QQuickItemLayer::activate()
+{
+ Q_ASSERT(!m_effectSource);
+ m_effectSource = new QQuickShaderEffectSource();
+
+ QQuickItem *parentItem = m_item->parentItem();
+ if (parentItem) {
+ m_effectSource->setParentItem(parentItem);
+ m_effectSource->stackAfter(m_item);
+ }
+
+ m_effectSource->setSourceItem(m_item);
+ m_effectSource->setHideSource(true);
+ m_effectSource->setSmooth(m_smooth);
+ m_effectSource->setTextureSize(m_size);
+ m_effectSource->setSourceRect(m_sourceRect);
+ m_effectSource->setMipmap(m_mipmap);
+ m_effectSource->setWrapMode(m_wrapMode);
+ m_effectSource->setFormat(m_format);
+
+ if (m_effectComponent)
+ activateEffect();
+
+ m_effectSource->setVisible(m_item->isVisible() && !m_effect);
+
+ updateZ();
+ updateGeometry();
+ updateOpacity();
+ updateMatrix();
+
+ QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
+ id->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
+}
+
+void QQuickItemLayer::deactivate()
+{
+ Q_ASSERT(m_effectSource);
+
+ if (m_effectComponent)
+ deactivateEffect();
+
+ delete m_effectSource;
+ m_effectSource = 0;
+
+ QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
+ id->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
+}
+
+void QQuickItemLayer::activateEffect()
+{
+ Q_ASSERT(m_effectSource);
+ Q_ASSERT(m_effectComponent);
+ Q_ASSERT(!m_effect);
+
+ QObject *created = m_effectComponent->create();
+ m_effect = qobject_cast<QQuickItem *>(created);
+ if (!m_effect) {
+ qWarning("Item: layer.effect is not a QML Item.");
+ delete created;
+ return;
+ }
+ QQuickItem *parentItem = m_item->parentItem();
+ if (parentItem) {
+ m_effect->setParentItem(parentItem);
+ m_effect->stackAfter(m_effectSource);
+ }
+ m_effect->setVisible(m_item->isVisible());
+ m_effect->setProperty(m_name, qVariantFromValue<QObject *>(m_effectSource));
+}
+
+void QQuickItemLayer::deactivateEffect()
+{
+ Q_ASSERT(m_effectSource);
+ Q_ASSERT(m_effectComponent);
+
+ delete m_effect;
+ m_effect = 0;
+}
+
+
+/*!
+ \qmlproperty Component QtQuick2::Item::layer.effect
+
+ Holds the effect that is applied to this layer.
+
+ The effect is typically a \l ShaderEffect component, although any \l Item component can be
+ assigned. The effect should have a source texture property with a name matching \l samplerName.
+
+ \sa samplerName
+ */
+
+void QQuickItemLayer::setEffect(QQmlComponent *component)
+{
+ if (component == m_effectComponent)
+ return;
+
+ bool updateNeeded = false;
+ if (m_effectSource && m_effectComponent) {
+ deactivateEffect();
+ updateNeeded = true;
+ }
+
+ m_effectComponent = component;
+
+ if (m_effectSource && m_effectComponent) {
+ activateEffect();
+ updateNeeded = true;
+ }
+
+ if (updateNeeded) {
+ updateZ();
+ updateGeometry();
+ updateOpacity();
+ updateMatrix();
+ m_effectSource->setVisible(m_item->isVisible() && !m_effect);
+ }
+
+ emit effectChanged(component);
+}
+
+
+/*!
+ \qmlproperty bool QtQuick2::Item::layer.mipmap
+
+ If this property is true, mipmaps are generated for the texture.
+
+ \note Some OpenGL ES 2 implementations do not support mipmapping of
+ non-power-of-two textures.
+ */
+
+void QQuickItemLayer::setMipmap(bool mipmap)
+{
+ if (mipmap == m_mipmap)
+ return;
+ m_mipmap = mipmap;
+
+ if (m_effectSource)
+ m_effectSource->setMipmap(m_mipmap);
+
+ emit mipmapChanged(mipmap);
+}
+
+
+/*!
+ \qmlproperty enumeration QtQuick2::Item::layer.format
+
+ This property defines the internal OpenGL format of the texture.
+ Modifying this property makes most sense when the \a layer.effect is also
+ specified. Depending on the OpenGL implementation, this property might
+ allow you to save some texture memory.
+
+ \list
+ \o ShaderEffectSource.Alpha - GL_ALPHA
+ \o ShaderEffectSource.RGB - GL_RGB
+ \o ShaderEffectSource.RGBA - GL_RGBA
+ \endlist
+
+ \note Some OpenGL implementations do not support the GL_ALPHA format.
+ */
+
+void QQuickItemLayer::setFormat(QQuickShaderEffectSource::Format f)
+{
+ if (f == m_format)
+ return;
+ m_format = f;
+
+ if (m_effectSource)
+ m_effectSource->setFormat(m_format);
+
+ emit formatChanged(m_format);
+}
+
+
+/*!
+ \qmlproperty enumeration QtQuick2::Item::layer.sourceRect
+
+ This property defines which rectangular area of the \l sourceItem to
+ render into the texture. The source rectangle can be larger than
+ \l sourceItem itself. If the rectangle is null, which is the default,
+ the whole \l sourceItem is rendered to texture.
+ */
+
+void QQuickItemLayer::setSourceRect(const QRectF &sourceRect)
+{
+ if (sourceRect == m_sourceRect)
+ return;
+ m_sourceRect = sourceRect;
+
+ if (m_effectSource)
+ m_effectSource->setSourceRect(m_sourceRect);
+
+ emit sourceRectChanged(sourceRect);
+}
+
+
+
+/*!
+ \qmlproperty bool QtQuick2::Item::layer.smooth
+
+ Holds whether the layer is smoothly transformed.
+ */
+
+void QQuickItemLayer::setSmooth(bool s)
+{
+ if (m_smooth == s)
+ return;
+ m_smooth = s;
+
+ if (m_effectSource)
+ m_effectSource->setSmooth(m_smooth);
+
+ emit smoothChanged(s);
+}
+
+
+
+/*!
+ \qmlproperty size QtQuick2::Item::layer.textureSize
+
+ This property holds the requested pixel size of the layers texture. If it is empty,
+ which is the default, the size of the item is used.
+
+ \note Some platforms have a limit on how small framebuffer objects can be,
+ which means the actual texture size might be larger than the requested
+ size.
+ */
+
+void QQuickItemLayer::setSize(const QSize &size)
+{
+ if (size == m_size)
+ return;
+ m_size = size;
+
+ if (m_effectSource)
+ m_effectSource->setTextureSize(size);
+
+ emit sizeChanged(size);
+}
+
+
+
+/*!
+ \qmlproperty enumeration QtQuick2::Item::layer.wrapMode
+
+ This property defines the OpenGL wrap modes associated with the texture.
+ Modifying this property makes most sense when the \a layer.effect is
+ specified.
+
+ \list
+ \o ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically
+ \o ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
+ \o ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
+ \o ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically
+ \endlist
+
+ \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
+ wrap mode with non-power-of-two textures.
+ */
+
+void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
+{
+ if (mode != m_wrapMode)
+ return;
+ m_wrapMode = mode;
+
+ if (m_effectSource)
+ m_effectSource->setWrapMode(m_wrapMode);
+
+ emit wrapModeChanged(mode);
+}
+
+/*!
+ \qmlproperty string QtQuick2::Item::layer.samplerName
+
+ Holds the name of the effect's source texture property.
+
+ samplerName needs to match the name of the effect's source texture property
+ so that the Item can pass the layer's offscreen surface to the effect correctly.
+
+ \sa effect, ShaderEffect
+ */
+
+void QQuickItemLayer::setName(const QByteArray &name) {
+ if (m_name == name)
+ return;
+ if (m_effect) {
+ m_effect->setProperty(m_name, QVariant());
+ m_effect->setProperty(name, qVariantFromValue<QObject *>(m_effectSource));
+ }
+ m_name = name;
+ emit nameChanged(name);
+}
+
+void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
+{
+ Q_UNUSED(item)
+ updateOpacity();
+}
+
+void QQuickItemLayer::itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &)
+{
+ updateGeometry();
+}
+
+void QQuickItemLayer::itemParentChanged(QQuickItem *item, QQuickItem *parent)
+{
+ Q_UNUSED(item)
+ Q_ASSERT(item == m_item);
+ Q_ASSERT(parent != m_effectSource);
+ Q_ASSERT(parent == 0 || parent != m_effect);
+
+ m_effectSource->setParentItem(parent);
+ if (parent)
+ m_effectSource->stackAfter(m_item);
+
+ if (m_effect) {
+ m_effect->setParentItem(parent);
+ if (parent)
+ m_effect->stackAfter(m_effectSource);
+ }
+}
+
+void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
+{
+ m_effectSource->stackAfter(m_item);
+ if (m_effect)
+ m_effect->stackAfter(m_effectSource);
+}
+
+void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
+{
+ QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+ Q_ASSERT(l);
+ l->setVisible(m_item->isVisible());
+}
+
+void QQuickItemLayer::updateZ()
+{
+ if (!m_componentComplete || !m_enabled)
+ return;
+ QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+ Q_ASSERT(l);
+ l->setZ(m_item->z());
+}
+
+void QQuickItemLayer::updateOpacity()
+{
+ QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+ Q_ASSERT(l);
+ l->setOpacity(m_item->opacity());
+}
+
+void QQuickItemLayer::updateGeometry()
+{
+ QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+ Q_ASSERT(l);
+ QRectF bounds = m_item->boundingRect();
+ l->setWidth(bounds.width());
+ l->setHeight(bounds.height());
+ l->setX(bounds.x() + m_item->x());
+ l->setY(bounds.y() + m_item->y());
+}
+
+void QQuickItemLayer::updateMatrix()
+{
+ // Called directly from transformChanged(), so needs some extra
+ // checks.
+ if (!m_componentComplete || !m_enabled)
+ return;
+ QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+ Q_ASSERT(l);
+ QQuickItemPrivate *ld = QQuickItemPrivate::get(l);
+ l->setScale(m_item->scale());
+ l->setRotation(m_item->rotation());
+ ld->transforms = QQuickItemPrivate::get(m_item)->transforms;
+ if (ld->origin() != QQuickItemPrivate::get(m_item)->origin())
+ ld->extra.value().origin = QQuickItemPrivate::get(m_item)->origin();
+ ld->dirty(QQuickItemPrivate::Transform);
+}
+
+QQuickItemPrivate::ExtraData::ExtraData()
+: z(0), scale(1), rotation(0), opacity(1),
+ contents(0), screenAttached(0), layoutDirectionAttached(0),
+ keyHandler(0), layer(0), effectRefCount(0), hideRefCount(0),
+ opacityNode(0), clipNode(0), rootNode(0), beforePaintNode(0),
+ acceptedMouseButtons(0), origin(QQuickItem::Center)
+{
+}
+
QT_END_NAMESPACE
#include <moc_qquickitem.cpp>