diff options
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 157 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 5 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 6 |
3 files changed, 166 insertions, 2 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 53773553ee..67c4fd2140 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1863,6 +1863,11 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus) */ /*! + \fn void QQuickItem::activeFocusOnTabChanged(bool) + \internal +*/ + +/*! \fn void QQuickItem::childrenChanged() \internal */ @@ -2023,6 +2028,93 @@ QQuickItem::~QQuickItem() } /*! + \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 + \return Whether the next item in the focus chain is found or not + + If \a next is true, the next item visited will be in depth-first order relative to \a item. + If \a next is false, the next item visited will be in reverse depth-first order relative to \a item. +*/ +bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward) +{ + Q_ASSERT(item); + Q_ASSERT(item->activeFocusOnTab()); + + QQuickItem *from = 0; + if (forward) { + from = item->parentItem(); + } else { + if (!item->childItems().isEmpty()) + from = item->childItems().first(); + else + from = item->parentItem(); + } + bool skip = false; + QQuickItem *current = item; + do { + skip = false; + QQuickItem *last = current; + + bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible(); + + // coming from parent: check children + if (hasChildren && from == current->parentItem()) { + if (forward) { + current = current->childItems().first(); + } else { + current = current->childItems().last(); + if (!current->childItems().isEmpty()) + skip = true; + } + } else if (hasChildren && forward && from != current->childItems().last()) { + // not last child going forwards + int nextChild = current->childItems().indexOf(from) + 1; + current = current->childItems().at(nextChild); + } else if (hasChildren && !forward && from != current->childItems().first()) { + // not first child going backwards + int prevChild = current->childItems().indexOf(from) - 1; + current = current->childItems().at(prevChild); + if (!current->childItems().isEmpty()) + skip = true; + // back to the parent + } else if (current->parentItem()) { + current = current->parentItem(); + // we would evaluate the parent twice, thus we skip + if (forward) { + skip = true; + } else if (!forward && !current->childItems().isEmpty()) { + if (last != current->childItems().first()) { + skip = true; + } else if (last == current->childItems().first()) { + if (current->isFocusScope() && current->activeFocusOnTab() && current->hasActiveFocus()) + skip = true; + } + } + } else if (hasChildren) { + // Wrap around after checking all items forward + if (forward) { + current = current->childItems().first(); + } else { + current = current->childItems().last(); + if (!current->childItems().isEmpty()) + skip = true; + } + } + + from = last; + } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()); + + if (current == item) + return false; + + current->forceActiveFocus(); + + return true; +} + +/*! \qmlproperty Item QtQuick2::Item::parent This property holds the visual parent of the item. @@ -2522,6 +2614,7 @@ QQuickItemPrivate::QQuickItemPrivate() , isAccessible(false) , culled(false) , hasCursor(false) + , activeFocusOnTab(false) , dirtyAttributes(0) , nextDirtyItem(0) , prevDirtyItem(0) @@ -4170,6 +4263,23 @@ void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e) else extra->keyHandler->keyReleased(e, true); } + + if (e->isAccepted()) + return; + + //only care about KeyPress now + if (q->activeFocusOnTab() && e->type() == QEvent::KeyPress) { + bool res = false; + if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier? + if (e->key() == Qt::Key_Backtab + || (e->key() == Qt::Key_Tab && (e->modifiers() & Qt::ShiftModifier))) + res = QQuickItemPrivate::focusNextPrev(q, false); + else if (e->key() == Qt::Key_Tab) + res = QQuickItemPrivate::focusNextPrev(q, true); + if (res) + e->setAccepted(true); + } + } } #ifndef QT_NO_IM @@ -5332,6 +5442,53 @@ void QQuickItem::setSmooth(bool smooth) } /*! + \qmlproperty bool QtQuick2::Item::activeFocusOnTab + + This property holds whether the item wants to be in tab focus + chain. By default this is set to false. + + The tab focus chain traverses elements by visiting first the + parent, and then its children in the order they occur in the + children property. Pressing the tab key on an item in the tab + focus chain will move keyboard focus to the next item in the + chain. Pressing BackTab (normally Shift+Tab) will move focus + to the previous item. + + To set up a manual tab focus chain, see \l KeyNavigation. Tab + key events used by Keys or KeyNavigation have precedence over + focus chain behavior, ignore the events in other key handlers + to allow it to propagate. +*/ +/*! + \property QQuickItem::activeFocusOnTab + + This property holds whether the item wants to be in tab focus + chain. By default this is set to false. +*/ +bool QQuickItem::activeFocusOnTab() const +{ + Q_D(const QQuickItem); + return d->activeFocusOnTab; +} +void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab) +{ + Q_D(QQuickItem); + if (d->activeFocusOnTab == activeFocusOnTab) + return; + + if (window()) { + if ((this == window()->activeFocusItem()) && !activeFocusOnTab) { + qWarning("QQuickItem: Cannot set activeFocusOnTab to false once item is the active focus item."); + return; + } + } + + d->activeFocusOnTab = activeFocusOnTab; + + emit activeFocusOnTabChanged(activeFocusOnTab); +} + +/*! \qmlproperty bool QtQuick2::Item::antialiasing Primarily used in Rectangle and image based elements to decide if the item should diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 71681698b9..c37bc10bdd 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -132,6 +132,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PROPERTY(bool focus READ hasFocus WRITE setFocus NOTIFY focusChanged FINAL) Q_PROPERTY(bool activeFocus READ hasActiveFocus NOTIFY activeFocusChanged FINAL) + Q_PROPERTY(bool activeFocusOnTab READ activeFocusOnTab WRITE setActiveFocusOnTab NOTIFY activeFocusOnTabChanged FINAL) Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged) @@ -261,6 +262,9 @@ public: bool smooth() const; void setSmooth(bool); + bool activeFocusOnTab() const; + void setActiveFocusOnTab(bool); + bool antialiasing() const; void setAntialiasing(bool); @@ -345,6 +349,7 @@ Q_SIGNALS: void stateChanged(const QString &); void focusChanged(bool); void activeFocusChanged(bool); + void activeFocusOnTabChanged(bool); void parentChanged(QQuickItem *); void transformOriginChanged(TransformOrigin); void smoothChanged(bool); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 8f6865b40b..4bd9d82c20 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -396,8 +396,8 @@ public: bool antialiasing:1; bool focus:1; bool activeFocus:1; - bool notifiedFocus:1; // Bit 16 + bool notifiedFocus:1; bool notifiedActiveFocus:1; bool filtersChildMouseEvents:1; bool explicitVisible:1; @@ -413,8 +413,8 @@ public: bool isAccessible:1; bool culled:1; bool hasCursor:1; - // bool dummy:1 // Bit 32 + bool activeFocusOnTab:1; enum DirtyType { TransformOrigin = 0x00000001, @@ -484,6 +484,8 @@ public: QTransform itemToWindowTransform() const; void itemToParentTransform(QTransform &) const; + static bool focusNextPrev(QQuickItem *item, bool forward); + qreal x; qreal y; qreal width; |