diff options
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/cursornavigation.cpp | 69 | ||||
-rw-r--r-- | plugin/cursornavigation.h | 14 | ||||
-rw-r--r-- | plugin/cursornavigationalgorithm.cpp | 3 | ||||
-rw-r--r-- | plugin/cursornavigationalgorithm.h | 15 | ||||
-rw-r--r-- | plugin/cursornavigationattached.cpp | 24 | ||||
-rw-r--r-- | plugin/cursornavigationattached.h | 18 | ||||
-rw-r--r-- | plugin/itemregister.cpp | 19 | ||||
-rw-r--r-- | plugin/itemregister.h | 9 | ||||
-rw-r--r-- | plugin/spatialnavigation4dir.cpp | 35 | ||||
-rw-r--r-- | plugin/spatialnavigation4dir.h | 9 |
10 files changed, 148 insertions, 67 deletions
diff --git a/plugin/cursornavigation.cpp b/plugin/cursornavigation.cpp index 83abae2..7e4ba81 100644 --- a/plugin/cursornavigation.cpp +++ b/plugin/cursornavigation.cpp @@ -11,8 +11,9 @@ CursorNavigation::CursorNavigation(QQuickWindow *parent) ,m_window(parent) ,m_inputAdapter(parent, this) ,m_currentItem(nullptr) +,m_rootItem(nullptr) { - m_algorithms.push_back(new SpatialNavigation4Dir(&m_itemRegister)); + m_algorithms.push_back(new SpatialNavigation4Dir()); connect(m_window, &QQuickWindow::activeFocusItemChanged, this, &CursorNavigation::onActiveFocusItemChanged); onActiveFocusItemChanged(); @@ -20,10 +21,14 @@ CursorNavigation::CursorNavigation(QQuickWindow *parent) bool CursorNavigation::inputCommand(CursorNavigationCommand cmd) { - QQuickItem *nextItem = nullptr; + CursorNavigationAttached *nextItem = nullptr; + + QList<CursorNavigationAttached*> &candidates = m_currentItem ? + m_currentItem->m_parentNavigable->m_children : + m_rootItem.m_children; for (auto alg : m_algorithms) { - nextItem = alg->getNextCandidate(m_itemRegister.items(), m_currentItem, cmd); + nextItem = alg->getNextCandidate(candidates, m_currentItem, cmd); if (nextItem) { setCursorOnItem(nextItem); break; @@ -75,21 +80,24 @@ CursorNavigation *CursorNavigation::cursorNavigationForWindow(QQuickWindow *wind return cursorNavigation; } -void CursorNavigation::setCursorOnItem(QQuickItem *item) +CursorNavigationAttached *CursorNavigation::cursorNavigationAttachment(QQuickItem *item) +{ + return dynamic_cast<CursorNavigationAttached *>(qmlAttachedPropertiesObject<CursorNavigation>(item, false)); +} + +void CursorNavigation::setCursorOnItem(CursorNavigationAttached *item) { + qWarning() << "set cursor on item " << item << " , currentItem " << m_currentItem; if (item != m_currentItem) { if (m_currentItem) { - CursorNavigationAttached *current=cursorNavigationAttachment(m_currentItem); - Q_ASSERT(current); - m_currentItem->setFocus(false); - current->setHasCursor(false); + m_currentItem->setHasCursor(false); + //m_currentItem->item()->setFocus(false); } - CursorNavigationAttached *next=cursorNavigationAttachment(item); - if (next) { - next->setHasCursor(true); + if (item) { + item->setHasCursor(true); m_currentItem = item; - m_currentItem->setFocus(true); - qWarning() << "Set cursor to " << item; + m_currentItem->item()->setFocus(true); + qWarning() << "Set cursor to " << item->item(); } else { qWarning() << "Set cursor to NULL"; m_currentItem = nullptr; @@ -100,11 +108,40 @@ void CursorNavigation::setCursorOnItem(QQuickItem *item) void CursorNavigation::onActiveFocusItemChanged() { qWarning() << "onActiveFocusItemChanged, item:" << m_window->activeFocusItem(); - setCursorOnItem(m_window->activeFocusItem()); + setCursorOnItem(cursorNavigationAttachment(m_window->activeFocusItem())); } -CursorNavigationAttached *CursorNavigation::cursorNavigationAttachment(QQuickItem *item) +void CursorNavigation::registerItem(CursorNavigationAttached* item) { - return static_cast<CursorNavigationAttached *>(qmlAttachedPropertiesObject<CursorNavigation>(item, false)); + qWarning() << "register item " << item; + if (!item) + return; + + //find first cursor navigable parent + QQuickItem *parentItem = item->item()->parentItem(); + CursorNavigationAttached *parentCNA=nullptr; + while (parentItem) { + if ((parentCNA=CursorNavigation::cursorNavigationAttachment(parentItem))) + break; + parentItem = parentItem->parentItem(); + } + + if (parentCNA) { + item->m_parentNavigable=parentCNA; + parentCNA->m_children.append(item); + } else { + m_rootItem.m_children.append(item); + item->m_parentNavigable=&m_rootItem; + } +} + +void CursorNavigation::unregisterItem(CursorNavigationAttached* item) +{ + qWarning() << "unregister item " << item; + if (item == m_currentItem) + setCursorOnItem(nullptr); + + if (item->m_parentNavigable) + item->m_parentNavigable->m_children.removeOne(item); } diff --git a/plugin/cursornavigation.h b/plugin/cursornavigation.h index 2217679..7e61ee9 100644 --- a/plugin/cursornavigation.h +++ b/plugin/cursornavigation.h @@ -25,20 +25,22 @@ public: static CursorNavigation *cursorNavigationForWindow(QQuickWindow *window); + static CursorNavigationAttached *cursorNavigationAttachment(QQuickItem *item); + private: - void setCursorOnItem(QQuickItem *item); + void setCursorOnItem(CursorNavigationAttached *item); void onActiveFocusItemChanged(); - - static CursorNavigationAttached *cursorNavigationAttachment(QQuickItem *item); + void registerItem(CursorNavigationAttached* item); + void unregisterItem(CursorNavigationAttached* item); private: static const char windowPropertyName[]; QQuickWindow *m_window; InputAdapter m_inputAdapter; - QQuickItem *m_currentItem; //item that currently has the cursor + CursorNavigationAttached *m_currentItem; //item that currently has the cursor QList<CursorNavigationAlgorithm*> m_algorithms; - ItemRegister m_itemRegister; - + //a root item that is not tied to any actual QQuickItem + CursorNavigationAttached m_rootItem; friend class CursorNavigationAttached; }; diff --git a/plugin/cursornavigationalgorithm.cpp b/plugin/cursornavigationalgorithm.cpp index d21c81c..0676434 100644 --- a/plugin/cursornavigationalgorithm.cpp +++ b/plugin/cursornavigationalgorithm.cpp @@ -1,8 +1,7 @@ #include "cursornavigationalgorithm.h" #include "itemregister.h" -CursorNavigationAlgorithm::CursorNavigationAlgorithm(ItemRegister *itemRegister) -:m_itemRegister(itemRegister) +CursorNavigationAlgorithm::CursorNavigationAlgorithm() { } diff --git a/plugin/cursornavigationalgorithm.h b/plugin/cursornavigationalgorithm.h index 02f247a..0c262c1 100644 --- a/plugin/cursornavigationalgorithm.h +++ b/plugin/cursornavigationalgorithm.h @@ -4,22 +4,19 @@ #include <QList> #include "inputtypes.h" -class ItemRegister; -class QQuickItem; +class CursorNavigationAttached; class CursorNavigationAlgorithm { public: - CursorNavigationAlgorithm(ItemRegister *itemRegister); + CursorNavigationAlgorithm(); virtual ~CursorNavigationAlgorithm(); - virtual QQuickItem* getNextCandidate(const QList<QQuickItem*> &candidates, - const QQuickItem *currentItem, - const CursorNavigationCommand& cmd) = 0; - -private: - ItemRegister *m_itemRegister; + virtual CursorNavigationAttached* getNextCandidate( + const QList<CursorNavigationAttached*> &candidates, + const CursorNavigationAttached *currentItem, + const CursorNavigationCommand& cmd) = 0; }; diff --git a/plugin/cursornavigationattached.cpp b/plugin/cursornavigationattached.cpp index 50b3686..9d4aafe 100644 --- a/plugin/cursornavigationattached.cpp +++ b/plugin/cursornavigationattached.cpp @@ -5,19 +5,28 @@ CursorNavigationAttached::CursorNavigationAttached(QQuickItem *parent) :QObject(parent), -m_acceptsCursor(true), m_cursorNavigation(nullptr), +m_parentNavigable(nullptr), +m_acceptsCursor(true), m_hasCursor(false) { - connect(parent, &QQuickItem::windowChanged, this, &CursorNavigationAttached::onWindowChanged); + if (parent) + connect(parent, &QQuickItem::windowChanged, this, &CursorNavigationAttached::onWindowChanged); - if (item()->window()) + if (parent && item() && item()->window()) { qDebug() << "Item has a window already"; onWindowChanged(item()->window()); } } +CursorNavigationAttached::~CursorNavigationAttached() +{ + qWarning() << "~CursorNavigationAttached"; + if (m_cursorNavigation) + m_cursorNavigation->unregisterItem(this); +} + bool CursorNavigationAttached::acceptsCursor() const { return m_acceptsCursor; @@ -53,7 +62,7 @@ void CursorNavigationAttached::onWindowChanged(QQuickWindow *window) { qDebug() << "window changed, window = " << window; if (m_cursorNavigation) - m_cursorNavigation->m_itemRegister.unregisterItem(item()); + m_cursorNavigation->unregisterItem(this); if (window) { m_cursorNavigation = CursorNavigation::cursorNavigationForWindow(window); @@ -62,7 +71,7 @@ void CursorNavigationAttached::onWindowChanged(QQuickWindow *window) } if (m_cursorNavigation) - m_cursorNavigation->m_itemRegister.registerItem(item()); + m_cursorNavigation->registerItem(this); //emit focusManagerChanged(); } @@ -80,3 +89,8 @@ void CursorNavigationAttached::setHasCursor(bool hasCursor) emit hasCursorChanged(m_hasCursor); } } + +QList<CursorNavigationAttached *> &CursorNavigationAttached::siblings() +{ + return m_parentNavigable->m_children; +} diff --git a/plugin/cursornavigationattached.h b/plugin/cursornavigationattached.h index 2be0f72..1a8314c 100644 --- a/plugin/cursornavigationattached.h +++ b/plugin/cursornavigationattached.h @@ -3,6 +3,7 @@ //#include <qqml.h> #include <QObject> +#include <QList> class CursorNavigation; class QQuickItem; @@ -13,15 +14,17 @@ class CursorNavigationAttached : public QObject Q_OBJECT //is available for cursor navigation Q_PROPERTY(bool acceptsCursor READ acceptsCursor WRITE setAcceptsCursor NOTIFY acceptsCursorChanged) - //is available for cursor navigation + //indicates if item is currently selected, indicated also by activeFocus property Q_PROPERTY(bool hasCursor READ hasCursor NOTIFY hasCursorChanged) - //traps cursor. a trapped cursor can not be traversed outside of the item that traps it + //indicates if one of children is currently selected + Q_PROPERTY(bool childHasCursor READ hasCursor NOTIFY hasCursorChanged) + //traps cursor. a trapped cursor can not be traversed outside of the item that traps it until the escape input is given Q_PROPERTY(bool trapsCursor READ trapsCursor WRITE setTrapsCursor NOTIFY trapsCursorChanged) - //proxy cursor to other items - //Q_PROPERTY(QQmlListProperty<QQuickItem> preferredCursorTargets READ preferredCursorTargetsQML) + public: CursorNavigationAttached(QQuickItem *parent); + ~CursorNavigationAttached(); bool acceptsCursor() const; void setAcceptsCursor(bool acceptsCursor); @@ -31,6 +34,8 @@ public: bool trapsCursor() const; void setTrapsCursor(bool trapsCursor); + QQuickItem *item() const; + signals: void acceptsCursorChanged(bool acceptsCursor); void hasCursorChanged(bool hasCursor); @@ -40,10 +45,13 @@ private slots: void onWindowChanged(QQuickWindow *window); private: - QQuickItem *item() const; void setHasCursor(bool hasCursor); + QList<CursorNavigationAttached*> &siblings(); CursorNavigation *m_cursorNavigation; + CursorNavigationAttached *m_parentNavigable; + QList<CursorNavigationAttached*> m_children; + bool m_acceptsCursor; bool m_hasCursor; bool m_trapsCursor; diff --git a/plugin/itemregister.cpp b/plugin/itemregister.cpp index f4555f1..24c6b07 100644 --- a/plugin/itemregister.cpp +++ b/plugin/itemregister.cpp @@ -1,4 +1,5 @@ -#include "itemregister.h" +/*#include "itemregister.h" +#include "cursornavigation.h" #include <QQuickItem> ItemRegister::ItemRegister() @@ -11,6 +12,18 @@ void ItemRegister::registerItem(QQuickItem* item) if (!item) return; + //find first cursor navigable parent + QQuickItem *parentItem = item->parentItem(); + CursorNavigationAttached *parentCNA; + while (parentItem) { + if ((parentCNA=CursorNavigation::cursorNavigationAttachment(parentItem))) + break; + parentItem = parentItem->parentItem(); + } + + if (parentCNA) + parentCNA->m_children.append(); + m_items.append(item); connect(item, &QQuickItem::destroyed, this, &ItemRegister::onItemDestroyed); } @@ -24,8 +37,9 @@ void ItemRegister::unregisterItem(QQuickItem* item) m_items.removeOne(item); } -const QList<QQuickItem*> ItemRegister::items() const +const QList<QQuickItem*> ItemRegister::siblingItems(QQuickItem *item) const { + //find the items that are within the same scope as the argument item return m_items; } @@ -34,3 +48,4 @@ void ItemRegister::onItemDestroyed(QObject *obj) QQuickItem *item=static_cast<QQuickItem*>(obj); m_items.removeOne(item); } +*/ diff --git a/plugin/itemregister.h b/plugin/itemregister.h index 479bca7..9c9430a 100644 --- a/plugin/itemregister.h +++ b/plugin/itemregister.h @@ -1,4 +1,4 @@ -#ifndef ITEMREGISTER_H +/*#ifndef ITEMREGISTER_H #define ITEMREGISTER_H #include <QObject> @@ -16,15 +16,20 @@ public: void registerItem(QQuickItem* item); void unregisterItem(QQuickItem* item); - const QList<QQuickItem*> items() const; + //find the items that are within the same scope as the argument item + const QList<QQuickItem*> siblingItems(QQuickItem* item) const; private Q_SLOTS: void onItemDestroyed(QObject *obj); private: + //find the item's first parent that is cursor navigable + QQuickItem *findParent(QQuickItem* item); + //for now the data structure is just a list. could be replaced with something more efficient for the final purpose QList<QQuickItem*> m_items; }; #endif // ITEMREGISTER_H +*/ diff --git a/plugin/spatialnavigation4dir.cpp b/plugin/spatialnavigation4dir.cpp index fa1657e..a6965b0 100644 --- a/plugin/spatialnavigation4dir.cpp +++ b/plugin/spatialnavigation4dir.cpp @@ -1,4 +1,5 @@ #include "spatialnavigation4dir.h" +#include "cursornavigationattached.h" #include <QQuickItem> #include <QDebug> #include <algorithm> @@ -15,15 +16,15 @@ float distanceSquared(const QRectF& item1, const QRectF& item2) return dx*dx+dy*dy; } -SpatialNavigation4Dir::SpatialNavigation4Dir(ItemRegister *itemRegister) - :CursorNavigationAlgorithm (itemRegister) +SpatialNavigation4Dir::SpatialNavigation4Dir() { } -QQuickItem* SpatialNavigation4Dir::getNextCandidate(const QList<QQuickItem*> &candidates, - const QQuickItem *currentItem, - const CursorNavigationCommand &cmd) +CursorNavigationAttached* SpatialNavigation4Dir::getNextCandidate( + const QList<CursorNavigationAttached*> &candidates, + const CursorNavigationAttached *currentItem, + const CursorNavigationCommand &cmd) { if (candidates.isEmpty()) return nullptr; @@ -47,8 +48,8 @@ QQuickItem* SpatialNavigation4Dir::getNextCandidate(const QList<QQuickItem*> &ca std::function<bool(const QRectF&)> isInProjection; //scene coords of the current item - const QRectF currentItemSceneRect = currentItem->mapRectToScene(QRectF( 0, 0, - currentItem->width(), currentItem->height() )); + const QRectF currentItemSceneRect = currentItem->item()->mapRectToScene(QRectF( 0, 0, + currentItem->item()->width(), currentItem->item()->height() )); //NOTICE: overlapping candidates will be ignored for now (TODO, this needs to be changed) @@ -90,21 +91,22 @@ QQuickItem* SpatialNavigation4Dir::getNextCandidate(const QList<QQuickItem*> &ca return nullptr; } - std::pair<QQuickItem*,int> closest(nullptr,0); + std::pair<CursorNavigationAttached*,int> closest(nullptr,0); //qDebug() << "current: x=" << currentItemSceneRect.x() << " y=" << currentItemSceneRect.y(); for (auto candidate : candidates) { - if (!candidate->isVisible() || !candidate->isEnabled()) { + QQuickItem *candidateItem = candidate->item(); + if (!candidateItem->isVisible() || !candidateItem->isEnabled()) { //qDebug() << "skipping a invisible/disabled item"; continue; } //scene coords of the candidate - QRectF candidateSceneRect = candidate->mapRectToScene( + QRectF candidateSceneRect = candidateItem->mapRectToScene( QRect( 0, 0, - candidate->width(), candidate->height() )); + candidateItem->width(), candidateItem->height() )); //qDebug() << "x=" << candidateSceneRect.x() << " y=" << candidateSceneRect.y(); @@ -122,9 +124,9 @@ QQuickItem* SpatialNavigation4Dir::getNextCandidate(const QList<QQuickItem*> &ca if (closest.first) { - qDebug() << "chosen one: " << closest.first->mapRectToScene( + qDebug() << "chosen one: " << closest.first->item()->mapRectToScene( QRect( 0, 0, - closest.first->width(), closest.first->height() )); + closest.first->item()->width(), closest.first->item()->height() )); } if (!closest.first) { @@ -132,15 +134,16 @@ QQuickItem* SpatialNavigation4Dir::getNextCandidate(const QList<QQuickItem*> &ca for (auto candidate : candidates) { - if (!candidate->isVisible() || !candidate->isEnabled()) { + QQuickItem *candidateItem = candidate->item(); + if (!candidateItem->isVisible() || !candidateItem->isEnabled()) { //qDebug() << "skipping a invisible/disabled item"; continue; } //scene coords of the candidate - QRectF candidateSceneRect = candidate->mapRectToScene( + QRectF candidateSceneRect = candidateItem->mapRectToScene( QRect( 0, 0, - candidate->width(), candidate->height() )); + candidateItem->width(), candidateItem->height() )); if (isInDirection(candidateSceneRect)) { diff --git a/plugin/spatialnavigation4dir.h b/plugin/spatialnavigation4dir.h index a91c505..7052ecc 100644 --- a/plugin/spatialnavigation4dir.h +++ b/plugin/spatialnavigation4dir.h @@ -6,11 +6,12 @@ class SpatialNavigation4Dir : public CursorNavigationAlgorithm { public: - SpatialNavigation4Dir(ItemRegister *itemRegister); + SpatialNavigation4Dir(); - virtual QQuickItem* getNextCandidate(const QList<QQuickItem*> &candidates, - const QQuickItem *currentItem, - const CursorNavigationCommand &cmd); + virtual CursorNavigationAttached* getNextCandidate( + const QList<CursorNavigationAttached*> &candidates, + const CursorNavigationAttached *currentItem, + const CursorNavigationCommand &cmd); }; |