aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickitem.cpp')
-rw-r--r--src/quick/items/qquickitem.cpp209
1 files changed, 171 insertions, 38 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 4ce9b15921..d0417c80f3 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -58,6 +58,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qnumeric.h>
+#include <QtGui/qpa/qplatformtheme.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlengine_p.h>
@@ -1365,7 +1366,7 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
\brief Property used to mirror layout behavior
The LayoutMirroring attached property is used to horizontally mirror \l {anchor-layout}{Item anchors},
- \l{Item Layouts}{positioner} types (such as \l Row and \l Grid)
+ \l{Item Positioners}{positioner} types (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 types like \l Grid and \l Row reverse the
horizontal layout of child items.
@@ -1405,7 +1406,7 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
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{Item Layouts}{positioner} types
+ and right anchors become left. For \l{Item Positioners}{positioner} types
(such as \l Row and \l Grid) and view types (such as \l {GridView}{GridView} and \l {ListView}{ListView})
this also mirrors the horizontal layout direction of the item.
@@ -1573,7 +1574,7 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
/*!
\class QQuickItem
- \brief The QQuickItem class provides the most basic of all visual items in QtQuick.
+ \brief The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
\inmodule QtQuick
All visual items in Qt Quick inherit from QQuickItem. Although a QQuickItem
@@ -2037,6 +2038,44 @@ QQuickItem::~QQuickItem()
/*!
\internal
+*/
+bool QQuickItemPrivate::qt_tab_all_widgets()
+{
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ return theme->themeHint(QPlatformTheme::TabAllWidgets).toBool();
+ return true;
+}
+
+/*!
+ \internal
+*/
+bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
+{
+ bool result = true;
+
+ if (!item->window())
+ return false;
+
+ if (item == item->window()->contentItem())
+ return true;
+
+#ifndef QT_NO_ACCESSIBILITY
+ result = false;
+ if (QObject *acc = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(item, false)) {
+ int role = acc->property("role").toInt();
+ if (role == QAccessible::EditableText
+ || role == QAccessible::Table
+ || role == QAccessible::List
+ || role == QAccessible::SpinBox)
+ result = true;
+ }
+#endif
+
+ return result;
+}
+
+/*!
+ \internal
\brief QQuickItemPrivate::focusNextPrev focuses the next/prev item in the tab-focus-chain
\param item The item that currently has the focus
\param forward The direction
@@ -2047,8 +2086,21 @@ QQuickItem::~QQuickItem()
*/
bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
{
+ QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward);
+
+ if (next == item)
+ return false;
+
+ next->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+
+ return true;
+}
+
+QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward)
+{
Q_ASSERT(item);
- Q_ASSERT(item->activeFocusOnTab());
+
+ bool all = QQuickItemPrivate::qt_tab_all_widgets();
QQuickItem *from = 0;
if (forward) {
@@ -2060,6 +2112,10 @@ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
from = item->parentItem();
}
bool skip = false;
+ const QQuickItem * const contentItem = item->window()->contentItem();
+ const QQuickItem * const originalItem = item;
+ QQuickItem * startItem = item;
+ QQuickItem * firstFromItem = from;
QQuickItem *current = item;
do {
skip = false;
@@ -2110,16 +2166,29 @@ bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
skip = true;
}
}
-
from = last;
- } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible());
-
- if (current == item)
- return false;
-
- current->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ if (current == startItem && from == firstFromItem) {
+ // wrapped around, avoid endless loops
+ if (originalItem == contentItem) {
+#ifdef FOCUS_DEBUG
+ qDebug() << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
+#endif
+ return item->window()->contentItem();
+ } else {
+#ifdef FOCUS_DEBUG
+ qDebug() << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
+#endif
+ return startItem;
+ }
+ }
+ if (!firstFromItem) { //start from root
+ startItem = current;
+ firstFromItem = from;
+ }
+ } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()
+ || !(all || QQuickItemPrivate::canAcceptTabFocus(current)));
- return true;
+ return current;
}
/*!
@@ -2255,7 +2324,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
}
}
- d->resolveLayoutMirror();
+ if (d->parentItem)
+ d->resolveLayoutMirror();
d->itemChange(ItemParentHasChanged, d->parentItem);
@@ -2341,13 +2411,16 @@ void QQuickItem::stackAfter(const QQuickItem *sibling)
QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
}
+/*! \fn void QQuickItem::windowChanged(QQuickWindow *window)
+ This signal is emitted when the item's \a window changes.
+*/
+
/*!
Returns the window in which this item is rendered.
- The item does not have a window until it has been assigned into a scene. To
- get notification about this, reimplement the itemChange() function and
- listen for the ItemSceneChange change. The itemChange() function is called
- both when the item is entered into a scene and when it is removed from a scene.
+ The item does not have a window until it has been assigned into a scene. The
+ \l windowChanged signal provides a notification both when the item is entered
+ into a scene and when it is removed from a scene.
*/
QQuickWindow *QQuickItem::window() const
{
@@ -2498,8 +2571,7 @@ void QQuickItemPrivate::derefWindow()
if (c->cursorItem == q)
c->cursorItem = 0;
#endif
- if ( hoverEnabled )
- c->hoverItems.removeAll(q);
+ c->hoverItems.removeAll(q);
if (itemNodeInstance)
c->cleanup(itemNodeInstance);
if (!parentItem)
@@ -2688,9 +2760,26 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
} else {
if (o->inherits("QGraphicsItem"))
qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className());
+ else {
+ QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o);
+ QQuickItem *item = that;
+ QQuickWindow *itemWindow = that->window();
+ while (!itemWindow && item && item->parentItem()) {
+ item = item->parentItem();
+ itemWindow = item->window();
+ }
+
+ if (thisWindow) {
+ if (itemWindow)
+ thisWindow->setTransientParent(itemWindow);
+ else
+ QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)),
+ thisWindow, SLOT(setTransientParent_helper(QQuickWindow*)));
+ }
+ o->setParent(that);
+ }
- // XXX todo - do we really want this behavior?
- o->setParent(that);
+ resources_append(prop, o);
}
}
@@ -2768,30 +2857,38 @@ void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property)
QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, int index)
{
- const QObjectList children = prop->object->children();
- if (index < children.count())
- return children.at(index);
- else
- return 0;
+ QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+ return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.value(index) : 0;
}
-void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *o)
+void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
{
- // XXX todo - do we really want this behavior?
- o->setParent(prop->object);
+ QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
+ QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
+ if (!quickItemPrivate->extra.value().resourcesList.contains(object)) {
+ quickItemPrivate->extra.value().resourcesList.append(object);
+ qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
+ quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
+ }
}
int QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
{
- return prop->object->children().count();
+ QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+ return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.count() : 0;
}
void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
{
- // XXX todo - do we really want this behavior?
- const QObjectList children = prop->object->children();
- for (int index = 0; index < children.count(); index++)
- children.at(index)->setParent(0);
+ QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
+ QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
+ if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
+ foreach (QObject *object, quickItemPrivate->extra->resourcesList) {
+ qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
+ quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
+ }
+ quickItemPrivate->extra->resourcesList.clear();
+ }
}
QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, int index)
@@ -2938,6 +3035,12 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
p->dirty(QQuickItemPrivate::Transform);
}
+void QQuickItemPrivate::_q_resourceObjectDeleted(QObject *object)
+{
+ if (extra.isAllocated() && extra->resourcesList.contains(object))
+ extra->resourcesList.removeAll(object);
+}
+
/*!
\qmlproperty AnchorLine QtQuick2::Item::anchors.top
\qmlproperty AnchorLine QtQuick2::Item::anchors.bottom
@@ -3917,6 +4020,28 @@ void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
}
/*!
+ \qmlmethod QtQuick2::Item::nextItemInFocusChain(bool forward)
+
+ \since QtQuick 2.1
+
+ Returns the item in the focus chain which is next to this item.
+ If \a forward is \c true, or not supplied, it is the next item in
+ the forwards direction. If \a forward is \c false, it is the next
+ item in the backwards direction.
+*/
+/*!
+ Returns the item in the focus chain which is next to this item.
+ If \a forward is \c true, or not supplied, it is the next item in
+ the forwards direction. If \a forward is \c false, it is the next
+ item in the backwards direction.
+*/
+
+QQuickItem *QQuickItem::nextItemInFocusChain(bool forward)
+{
+ return QQuickItemPrivate::nextPrevItemInTabFocusChain(this, forward);
+}
+
+/*!
\qmlmethod QtQuick2::Item::childAt(real x, real y)
Returns the first visible child item found at point (\a x, \a y) within
@@ -4280,7 +4405,8 @@ void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
return;
//only care about KeyPress now
- if (q->activeFocusOnTab() && e->type() == QEvent::KeyPress) {
+ if ((q == q->window()->contentItem() || q->activeFocusOnTab())
+ && e->type() == QEvent::KeyPress) {
bool res = false;
if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
if (e->key() == Qt::Key_Backtab
@@ -4417,11 +4543,18 @@ void QQuickItemPrivate::deliverDragEvent(QEvent *e)
\a value contains extra information relating to the change, when
applicable.
+
+ If you re-implement this method in a subclass, be sure to call
+ \code
+ QQuickItem::itemChange(change, value);
+ \endcode
+ typically at the end of your implementation, to ensure the
+ \l windowChanged signal will be emitted.
*/
void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
{
- Q_UNUSED(change);
- Q_UNUSED(value);
+ if (change == ItemSceneChange)
+ emit windowChanged(value.window);
}
#ifndef QT_NO_IM
@@ -5489,7 +5622,7 @@ void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab)
return;
if (window()) {
- if ((this == window()->activeFocusItem()) && !activeFocusOnTab) {
+ if ((this == window()->activeFocusItem()) && this != window()->contentItem() && !activeFocusOnTab) {
qWarning("QQuickItem: Cannot set activeFocusOnTab to false once item is the active focus item.");
return;
}