From fbe75056a6ca179504b33c74d741c540f5b22dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20H=C3=B6ltt=C3=A4?= Date: Tue, 6 Nov 2018 15:39:36 +0100 Subject: More on scopes, works to some extent in the test program Scope may be entered and escaped. Navigable items may have escape targets defined --- plugin/cursornavigation.cpp | 92 ++++++++++++++++++++++++++++-------- plugin/cursornavigation.h | 12 +++-- plugin/cursornavigationalgorithm.cpp | 1 - plugin/cursornavigationattached.cpp | 21 ++++++-- plugin/cursornavigationattached.h | 17 +++++-- plugin/inputadapter.cpp | 4 +- plugin/inputtypes.h | 36 ++++++++++++++ plugin/itemregister.cpp | 51 -------------------- plugin/itemregister.h | 35 -------------- plugin/plugin.pro | 2 - 10 files changed, 150 insertions(+), 121 deletions(-) delete mode 100644 plugin/itemregister.cpp delete mode 100644 plugin/itemregister.h (limited to 'plugin') diff --git a/plugin/cursornavigation.cpp b/plugin/cursornavigation.cpp index 7e4ba81..0011cb2 100644 --- a/plugin/cursornavigation.cpp +++ b/plugin/cursornavigation.cpp @@ -9,33 +9,26 @@ const char CursorNavigation::windowPropertyName[] = "cursor_navigation"; CursorNavigation::CursorNavigation(QQuickWindow *parent) :QObject(parent) ,m_window(parent) -,m_inputAdapter(parent, this) +,m_inputAdapter(m_window->contentItem(), this) ,m_currentItem(nullptr) -,m_rootItem(nullptr) +,m_rootItem(new CursorNavigationAttached(nullptr)) { + m_rootItem->setParent(m_window->contentItem()); + m_algorithms.push_back(new SpatialNavigation4Dir()); connect(m_window, &QQuickWindow::activeFocusItemChanged, this, &CursorNavigation::onActiveFocusItemChanged); onActiveFocusItemChanged(); } -bool CursorNavigation::inputCommand(CursorNavigationCommand cmd) +bool CursorNavigation::inputCommand(const CursorNavigationCommand &cmd) { - CursorNavigationAttached *nextItem = nullptr; - - QList &candidates = m_currentItem ? - m_currentItem->m_parentNavigable->m_children : - m_rootItem.m_children; - for (auto alg : m_algorithms) { - nextItem = alg->getNextCandidate(candidates, m_currentItem, cmd); - if (nextItem) { - setCursorOnItem(nextItem); - break; - } + if (cmd.action == CursorNavigationCommand::NoAction) { + return handleDirectionCommand(cmd); + } else { + return handleActionCommand(cmd); } - - return true; } CursorNavigationAttached *CursorNavigation::qmlAttachedProperties(QObject *object) @@ -96,7 +89,8 @@ void CursorNavigation::setCursorOnItem(CursorNavigationAttached *item) if (item) { item->setHasCursor(true); m_currentItem = item; - m_currentItem->item()->setFocus(true); + m_currentItem->item()->forceActiveFocus(); + //m_currentItem->item()->setFocus(true); qWarning() << "Set cursor to " << item->item(); } else { qWarning() << "Set cursor to NULL"; @@ -130,8 +124,8 @@ void CursorNavigation::registerItem(CursorNavigationAttached* item) item->m_parentNavigable=parentCNA; parentCNA->m_children.append(item); } else { - m_rootItem.m_children.append(item); - item->m_parentNavigable=&m_rootItem; + m_rootItem->m_children.append(item); + item->m_parentNavigable=m_rootItem; } } @@ -145,3 +139,63 @@ void CursorNavigation::unregisterItem(CursorNavigationAttached* item) item->m_parentNavigable->m_children.removeOne(item); } +bool CursorNavigation::handleDirectionCommand(const CursorNavigationCommand &cmd) +{ + qWarning() << "handleDirectionCommand"; + CursorNavigationAttached *nextItem = nullptr; + + QList &candidates = m_currentItem ? + m_currentItem->m_parentNavigable->m_children : + m_rootItem->m_children; + + for (auto alg : m_algorithms) { + nextItem = alg->getNextCandidate(candidates, m_currentItem, cmd); + if (nextItem) { + setCursorOnItem(nextItem); + break; + } + } + + return true; +} + +bool CursorNavigation::handleActionCommand(const CursorNavigationCommand &cmd) +{ + qWarning() << "handleActionCommand, cmd.action= " << cmd.action; + switch (cmd.action) { + case CursorNavigationCommand::Forward: + break; + case CursorNavigationCommand::Back: + break; + case CursorNavigationCommand::Activate: + break; + case CursorNavigationCommand::Escape: { + /* if item has escapeTrgate defined, set focus to that. otherwise leave + * scope, ie. go back to parent's parent in the hierarchy and set focus + * (back) to it (setting the focus further to one of its children + * depends on the focus mechanism). + * if we are already at the root item's children, nothing happens + */ + if (!m_currentItem) + break; + + QQuickItem *escapeTarget = m_currentItem->m_parentNavigable->escapeTarget(); + if (!escapeTarget) { + if (m_currentItem->m_parentNavigable == m_rootItem) { + break; + } + escapeTarget = m_currentItem->m_parentNavigable->m_parentNavigable->item(); + } + qWarning() << "escaping, target = " << escapeTarget; + setCursorOnItem(nullptr); + escapeTarget->forceActiveFocus(); + onActiveFocusItemChanged(); + //escapeTarget->setFocus(true); + break; + } + + default: + break; + } +} + diff --git a/plugin/cursornavigation.h b/plugin/cursornavigation.h index 7e61ee9..12468e4 100644 --- a/plugin/cursornavigation.h +++ b/plugin/cursornavigation.h @@ -2,12 +2,12 @@ #define CURSORNAVIGATION_H #include "cursornavigationattached.h" -#include "itemregister.h" #include "inputtypes.h" #include "inputadapter.h" #include #include +#include class QQuickItem; class CursorNavigationAlgorithm; @@ -19,7 +19,9 @@ class CursorNavigation : public QObject public: CursorNavigation(QQuickWindow *parent); - bool inputCommand(CursorNavigationCommand cmd); + bool inputCommand(const CursorNavigationCommand &cmd); + void move(QVector2D moveVector); + void action(); static CursorNavigationAttached *qmlAttachedProperties(QObject *object); @@ -33,6 +35,9 @@ private: void registerItem(CursorNavigationAttached* item); void unregisterItem(CursorNavigationAttached* item); + bool handleDirectionCommand(const CursorNavigationCommand &cmd); + bool handleActionCommand(const CursorNavigationCommand &cmd); + private: static const char windowPropertyName[]; QQuickWindow *m_window; @@ -40,7 +45,8 @@ private: CursorNavigationAttached *m_currentItem; //item that currently has the cursor QList m_algorithms; //a root item that is not tied to any actual QQuickItem - CursorNavigationAttached m_rootItem; + CursorNavigationAttached *m_rootItem; + QStack m_scopeStack; friend class CursorNavigationAttached; }; diff --git a/plugin/cursornavigationalgorithm.cpp b/plugin/cursornavigationalgorithm.cpp index 0676434..c08761f 100644 --- a/plugin/cursornavigationalgorithm.cpp +++ b/plugin/cursornavigationalgorithm.cpp @@ -1,5 +1,4 @@ #include "cursornavigationalgorithm.h" -#include "itemregister.h" CursorNavigationAlgorithm::CursorNavigationAlgorithm() { diff --git a/plugin/cursornavigationattached.cpp b/plugin/cursornavigationattached.cpp index 9d4aafe..9a939ff 100644 --- a/plugin/cursornavigationattached.cpp +++ b/plugin/cursornavigationattached.cpp @@ -8,7 +8,8 @@ CursorNavigationAttached::CursorNavigationAttached(QQuickItem *parent) m_cursorNavigation(nullptr), m_parentNavigable(nullptr), m_acceptsCursor(true), -m_hasCursor(false) +m_hasCursor(false), +m_escapeTarget(nullptr) { if (parent) connect(parent, &QQuickItem::windowChanged, this, &CursorNavigationAttached::onWindowChanged); @@ -82,6 +83,20 @@ QQuickItem *CursorNavigationAttached::item() const return static_cast(parent()); } +QQuickItem *CursorNavigationAttached::escapeTarget() const +{ + return m_escapeTarget; +} + +void CursorNavigationAttached::setEscapeTarget(QQuickItem *escapeTarget) +{ + if (m_escapeTarget == escapeTarget) + return; + + m_escapeTarget = escapeTarget; + emit escapeTargetChanged(m_escapeTarget); +} + void CursorNavigationAttached::setHasCursor(bool hasCursor) { if (hasCursor != m_hasCursor) { @@ -90,7 +105,7 @@ void CursorNavigationAttached::setHasCursor(bool hasCursor) } } -QList &CursorNavigationAttached::siblings() +/*QList &CursorNavigationAttached::siblings() { return m_parentNavigable->m_children; -} +}*/ diff --git a/plugin/cursornavigationattached.h b/plugin/cursornavigationattached.h index 1a8314c..0f3f927 100644 --- a/plugin/cursornavigationattached.h +++ b/plugin/cursornavigationattached.h @@ -20,6 +20,8 @@ class CursorNavigationAttached : public QObject 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) + //item to select when + Q_PROPERTY(QQuickItem *escapeTarget READ escapeTarget WRITE setEscapeTarget NOTIFY escapeTargetChanged) public: @@ -27,26 +29,30 @@ public: ~CursorNavigationAttached(); bool acceptsCursor() const; - void setAcceptsCursor(bool acceptsCursor); - bool hasCursor() const; - bool trapsCursor() const; - void setTrapsCursor(bool trapsCursor); + QQuickItem *escapeTarget() const; QQuickItem *item() const; +public slots: + void setAcceptsCursor(bool acceptsCursor); + void setTrapsCursor(bool trapsCursor); + void setEscapeTarget(QQuickItem * escapeTarget); + signals: void acceptsCursorChanged(bool acceptsCursor); void hasCursorChanged(bool hasCursor); void trapsCursorChanged(bool trapsCursor); + void escapeTargetChanged(QQuickItem * escapeTarget); + private slots: void onWindowChanged(QQuickWindow *window); private: void setHasCursor(bool hasCursor); - QList &siblings(); + //QList &siblings(); CursorNavigation *m_cursorNavigation; CursorNavigationAttached *m_parentNavigable; @@ -57,6 +63,7 @@ private: bool m_trapsCursor; friend class CursorNavigation; + QQuickItem * m_escapeTarget; }; #endif // CURSORNAVIGATIONATTACHED_H diff --git a/plugin/inputadapter.cpp b/plugin/inputadapter.cpp index 5814e5d..99eeb4f 100644 --- a/plugin/inputadapter.cpp +++ b/plugin/inputadapter.cpp @@ -58,10 +58,10 @@ bool InputAdapter::handleKeyEvent(QKeyEvent *event) cmd.action = CursorNavigationCommand::Escape; break; case Qt::Key_Tab: - cmd.action = CursorNavigationCommand::Escape; + cmd.action = CursorNavigationCommand::Forward; break; case Qt::Key_Backtab: - cmd.action = CursorNavigationCommand::Escape; + cmd.action = CursorNavigationCommand::Back; break; default: return false; diff --git a/plugin/inputtypes.h b/plugin/inputtypes.h index bf7e82e..efe7f8a 100644 --- a/plugin/inputtypes.h +++ b/plugin/inputtypes.h @@ -1,6 +1,9 @@ #ifndef INPUTTYPES_H #define INPUTTYPES_H +//TODO: make these into classes w accessors + +//generic of way of describing the input that cursor management can handle struct CursorNavigationCommand { enum Action @@ -30,4 +33,37 @@ struct CursorNavigationCommand }; +/*feedback datatype returned for commands, describing command results + *this could be used for example to indicate that a end of a list has been reached, + *that might produce force feedback on certain inut devices + */ +enum CommandResult +{ + Succesful = 0, + AreaBoundsReached, + ListEndReached +}; + +//describing which boundary was met +enum Boundary { + Undefined = 0, + Top = 1, + Bottom = 2, + Right = 4, + Left = 8 +}; + +class CursorNavigationFeedback +{ +// Q_GADGET +// Q_PROPERTY(CommandResult READ commandResult NOTIFY commandResultChanged ) +// Q_PROPERTY(CommandResult READ commandResult NOTIFY commandResultChanged ) + + //feedback cases; + //-cmd succesfull + //-end of list reached (or just the end of whatever selection area maybe) + //-fell back to the previous scope +}; + + #endif // INPUTTYPES_H diff --git a/plugin/itemregister.cpp b/plugin/itemregister.cpp deleted file mode 100644 index 24c6b07..0000000 --- a/plugin/itemregister.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/*#include "itemregister.h" -#include "cursornavigation.h" -#include - -ItemRegister::ItemRegister() -{ - -} - -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); -} - -void ItemRegister::unregisterItem(QQuickItem* item) -{ - if (!item) - return; - - disconnect(item, &QQuickItem::destroyed, this, &ItemRegister::onItemDestroyed); - m_items.removeOne(item); -} - -const QList ItemRegister::siblingItems(QQuickItem *item) const -{ - //find the items that are within the same scope as the argument item - return m_items; -} - -void ItemRegister::onItemDestroyed(QObject *obj) -{ - QQuickItem *item=static_cast(obj); - m_items.removeOne(item); -} -*/ diff --git a/plugin/itemregister.h b/plugin/itemregister.h deleted file mode 100644 index 9c9430a..0000000 --- a/plugin/itemregister.h +++ /dev/null @@ -1,35 +0,0 @@ -/*#ifndef ITEMREGISTER_H -#define ITEMREGISTER_H - -#include - -class QQuickItem; - -//keeps track of items that are cursor navigable -class ItemRegister : public QObject -{ - Q_OBJECT - -public: - ItemRegister(); - - void registerItem(QQuickItem* item); - void unregisterItem(QQuickItem* item); - - //find the items that are within the same scope as the argument item - const QList 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 m_items; - -}; - -#endif // ITEMREGISTER_H -*/ diff --git a/plugin/plugin.pro b/plugin/plugin.pro index 72c6b96..6f1a4c3 100644 --- a/plugin/plugin.pro +++ b/plugin/plugin.pro @@ -12,7 +12,6 @@ SOURCES += \ plugin.cpp \ cursornavigation.cpp \ cursornavigationattached.cpp \ - itemregister.cpp \ inputadapter.cpp \ cursornavigationalgorithm.cpp \ spatialnavigation4dir.cpp \ @@ -22,7 +21,6 @@ HEADERS += \ plugin.h \ cursornavigation.h \ cursornavigationattached.h \ - itemregister.h \ inputadapter.h \ inputtypes.h \ cursornavigationalgorithm.h \ -- cgit v1.2.3