summaryrefslogtreecommitdiffstats
path: root/plugin
diff options
context:
space:
mode:
authorAntti Hölttä <AHoelttae@luxoft.com>2018-10-30 15:40:04 +0100
committerAntti Hölttä <AHoelttae@luxoft.com>2019-03-18 16:30:59 +0100
commit00fa5d9215d32124292fe3e45372acebac7b9d31 (patch)
tree021b35b301ae990ac9842f5ebf21d8c51db718a5 /plugin
parent2f4ec044ee4c7cf14481e1e0b86fecf804fcd770 (diff)
Refactor item registration with scopes in mind
ItemRegister class removed and items now keep track of their own cursor navigable child items. Navigation happens now only between siblings.
Diffstat (limited to 'plugin')
-rw-r--r--plugin/cursornavigation.cpp69
-rw-r--r--plugin/cursornavigation.h14
-rw-r--r--plugin/cursornavigationalgorithm.cpp3
-rw-r--r--plugin/cursornavigationalgorithm.h15
-rw-r--r--plugin/cursornavigationattached.cpp24
-rw-r--r--plugin/cursornavigationattached.h18
-rw-r--r--plugin/itemregister.cpp19
-rw-r--r--plugin/itemregister.h9
-rw-r--r--plugin/spatialnavigation4dir.cpp35
-rw-r--r--plugin/spatialnavigation4dir.h9
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);
};