aboutsummaryrefslogtreecommitdiffstats
path: root/plugin
diff options
context:
space:
mode:
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);
};