summaryrefslogtreecommitdiffstats
path: root/plugin
diff options
context:
space:
mode:
authorAntti Hölttä <AHoelttae@luxoft.com>2019-02-19 15:36:39 +0100
committerAntti Hölttä <AHoelttae@luxoft.com>2019-03-18 16:42:31 +0100
commit8489f36322c585ec78199e6eb183000c74afae19 (patch)
tree8989b7cf6275b8b6cbffaa3b44467f5bd4ecdbf5 /plugin
parenta5120f26d509a3464c79404de84e9428b8ddc690 (diff)
Add redirect feature for manually fine tuning the cursor's movement
Cursornavigation now has a property redirects, that allows defining exceptions to the navigation behaviour. A redirect allows defining a starting and an ending angle and a target object. If the move command's direction falls between the limits, the algorithm is bypassed and cursor is moved to the target object.
Diffstat (limited to 'plugin')
-rw-r--r--plugin/cursornavigation.cpp30
-rw-r--r--plugin/cursornavigation.h4
-rw-r--r--plugin/cursornavigationattached.cpp61
-rw-r--r--plugin/cursornavigationattached.h12
-rw-r--r--plugin/plugin.cpp2
-rw-r--r--plugin/plugin.pro6
-rw-r--r--plugin/redirect.cpp68
-rw-r--r--plugin/redirect.h41
8 files changed, 193 insertions, 31 deletions
diff --git a/plugin/cursornavigation.cpp b/plugin/cursornavigation.cpp
index bf2d390..e069efc 100644
--- a/plugin/cursornavigation.cpp
+++ b/plugin/cursornavigation.cpp
@@ -3,6 +3,7 @@
#include "spatialnavigation4dir.h"
#include <QQuickWindow>
#include <QQuickItem>
+#include <QtMath>
const char CursorNavigation::windowPropertyName[] = "cursor_navigation";
@@ -22,27 +23,38 @@ CursorNavigation::CursorNavigation(QQuickWindow *parent)
bool CursorNavigation::move(qreal angle, qreal tolerance, bool discrete)
{
- CursorNavigationAttached *nextItem = find(angle, tolerance, discrete);
+ QQuickItem *foundItem = find(angle, tolerance, discrete);
+ CursorNavigationAttached *nextItem = cursorNavigationAttachment(foundItem);
if (nextItem) {
setCursorOnItem(nextItem);
return true;
+ } else if (foundItem) {
+ foundItem->forceActiveFocus();
+ return true;
}
return false;
}
-CursorNavigationAttached *CursorNavigation::find(qreal angle, qreal tolerance, bool discrete)
+QQuickItem *CursorNavigation::find(qreal angle, qreal tolerance, bool discrete)
{
+ if (!m_currentItem)
+ return defaultItem()->item();
+
+ if (m_currentItem->m_redirects.size()) {
+ for (auto redirect : m_currentItem->m_redirects) {
+ if (redirect->angleIsIncluded(angle)) {
+ if (!redirect->target())
+ qWarning() << "Redirect target is null";
+ return redirect->target();
+ }
+ }
+ }
+
CursorNavigationAttached *nextItem = nullptr;
CursorNavigationAttached *parent = m_currentItem ?
m_currentItem->m_parentNavigable :
m_rootItem;
-
- if (!m_currentItem)
- return defaultItem();
-
- //qWarning() << "find next item, angle = " << angle << " tolerance = " << tolerance << " discrete = " << discrete;
-
QList<CursorNavigationAttached*> candidates;
do {
@@ -64,7 +76,7 @@ CursorNavigationAttached *CursorNavigation::find(qreal angle, qreal tolerance, b
nextItem = m_navigation360.getNextCandidate(candidates, m_currentItem, cmd);
}
- return nextItem;
+ return nextItem ? nextItem->item() : nullptr;
}
bool CursorNavigation::action(Action action)
diff --git a/plugin/cursornavigation.h b/plugin/cursornavigation.h
index a32a357..ad1cf31 100644
--- a/plugin/cursornavigation.h
+++ b/plugin/cursornavigation.h
@@ -25,10 +25,8 @@ public:
//void setMagnitude(const QVector2D& vector);
//move the cursor
bool move(qreal angle, qreal tolerance, bool discrete);
- bool move(const QVector2D& vector, qreal tolerance, bool discrete);
//find the next item without moving the cursor
- CursorNavigationAttached *find(qreal angle, qreal tolerance, bool discrete);
- CursorNavigationAttached *find(const QVector2D& vector, qreal tolerance, bool discrete);
+ QQuickItem *find(qreal angle, qreal tolerance, bool discrete);
bool action(Action action);
static CursorNavigationAttached *qmlAttachedProperties(QObject *object);
diff --git a/plugin/cursornavigationattached.cpp b/plugin/cursornavigationattached.cpp
index a897327..133890e 100644
--- a/plugin/cursornavigationattached.cpp
+++ b/plugin/cursornavigationattached.cpp
@@ -92,10 +92,10 @@ void CursorNavigationAttached::setMagnitude(QVector2D vector)
void CursorNavigationAttached::move(qreal angle, qreal tolerance)
{
- qWarning() << "move";
- qreal a = qDegreesToRadians(angle);
- qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
if (m_cursorNavigation) {
+ qWarning() << "move";
+ qreal a = qDegreesToRadians(angle);
+ qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
CursorNavigationAttached *item = m_cursorNavigation->m_currentItem;
if (m_cursorNavigation->move(a, t, false) && item)
item->moved(a,t);
@@ -104,10 +104,10 @@ void CursorNavigationAttached::move(qreal angle, qreal tolerance)
void CursorNavigationAttached::move(QVector2D vector, qreal tolerance)
{
- qWarning() << "move (vector)";
- qreal a = qAtan2(vector.y(), vector.x());
- qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
if (m_cursorNavigation) {
+ qWarning() << "move (vector)";
+ qreal a = qAtan2(vector.y(), vector.x());
+ qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
CursorNavigationAttached *item = m_cursorNavigation->m_currentItem;
if (m_cursorNavigation->move(a, t, false) && item)
item->moved(a,t);
@@ -116,24 +116,20 @@ void CursorNavigationAttached::move(QVector2D vector, qreal tolerance)
QQuickItem *CursorNavigationAttached::find(qreal angle, qreal tolerance)
{
- qreal a = qDegreesToRadians(angle);
- qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
if (m_cursorNavigation) {
- CursorNavigationAttached *item = m_cursorNavigation->find(a, t, false);
- if (item)
- return item->item();
+ qreal a = qDegreesToRadians(angle);
+ qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
+ return m_cursorNavigation->find(a, t, false);
}
return nullptr;
}
QQuickItem *CursorNavigationAttached::find(QVector2D vector, qreal tolerance)
{
- qreal a = qAtan2(vector.y(), vector.x());
- qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
if (m_cursorNavigation) {
- CursorNavigationAttached *item = m_cursorNavigation->find(a, t, false);
- if (item)
- return item->item();
+ qreal a = qAtan2(vector.y(), vector.x());
+ qreal t = qDegreesToRadians(qFabs(std::fmod(tolerance, 180)));
+ return m_cursorNavigation->find(a, t, false);
}
return nullptr;
}
@@ -234,6 +230,15 @@ QQuickItem *CursorNavigationAttached::escapeTarget() const
return m_escapeTarget;
}
+QQmlListProperty<Redirect> CursorNavigationAttached::redirects()
+{
+ return QQmlListProperty<Redirect>(this, this,
+ &CursorNavigationAttached::appendRedirect,
+ &CursorNavigationAttached::redirectCount,
+ &CursorNavigationAttached::redirect,
+ &CursorNavigationAttached::clearRedirects);
+}
+
bool CursorNavigationAttached::available() const
{
if (m_acceptsCursor && item()->isVisible() && item()->isEnabled()) {
@@ -252,3 +257,27 @@ void CursorNavigationAttached::setHasCursor(bool hasCursor)
}
}
+void CursorNavigationAttached::appendRedirect(QQmlListProperty<Redirect> *property, Redirect *redirect)
+{
+ CursorNavigationAttached *cna = static_cast<CursorNavigationAttached*>(property->object);
+ cna->m_redirects.append(redirect);
+}
+
+int CursorNavigationAttached::redirectCount(QQmlListProperty<Redirect> *property)
+{
+ CursorNavigationAttached *cna = static_cast<CursorNavigationAttached*>(property->object);
+ return cna->m_redirects.count();
+}
+
+Redirect *CursorNavigationAttached::redirect(QQmlListProperty<Redirect> *property, int index)
+{
+ CursorNavigationAttached *cna = static_cast<CursorNavigationAttached*>(property->object);
+ return cna->m_redirects.at(index);
+}
+
+void CursorNavigationAttached::clearRedirects(QQmlListProperty<Redirect> *property)
+{
+ CursorNavigationAttached *cna = static_cast<CursorNavigationAttached*>(property->object);
+ cna->m_redirects.clear();
+}
+
diff --git a/plugin/cursornavigationattached.h b/plugin/cursornavigationattached.h
index f3c729d..7c5e99a 100644
--- a/plugin/cursornavigationattached.h
+++ b/plugin/cursornavigationattached.h
@@ -4,6 +4,8 @@
//#include <qqml.h>
#include <QObject>
#include <QList>
+#include <QQmlListProperty>
+#include "redirect.h"
class CursorNavigation;
class QQuickItem;
@@ -22,7 +24,7 @@ class CursorNavigationAttached : public QObject
Q_PROPERTY(bool trapsCursor READ trapsCursor WRITE setTrapsCursor NOTIFY trapsCursorChanged)
//item to select when
Q_PROPERTY(QQuickItem *escapeTarget READ escapeTarget WRITE setEscapeTarget NOTIFY escapeTargetChanged)
-
+ Q_PROPERTY(QQmlListProperty<Redirect> redirects READ redirects)
public:
CursorNavigationAttached(QQuickItem *parent);
@@ -32,6 +34,8 @@ public:
bool hasCursor() const;
bool trapsCursor() const;
QQuickItem *escapeTarget() const;
+ QQmlListProperty<Redirect> redirects();
+
/* indicates if the item is currently available for the navigation.
* item might not be availble if it is disabled, invisible, outside of its
* parent's geometry or simply not accepting cursor
@@ -93,6 +97,11 @@ private:
void setHasCursor(bool hasCursor);
//QList<CursorNavigationAttached*> &siblings();
+ static void appendRedirect(QQmlListProperty<Redirect> *property, Redirect *redirect);
+ static int redirectCount(QQmlListProperty<Redirect> *property);
+ static Redirect *redirect(QQmlListProperty<Redirect> *property, int index);
+ static void clearRedirects(QQmlListProperty<Redirect> *property);
+
CursorNavigation *m_cursorNavigation;
CursorNavigationAttached *m_parentNavigable;
QList<CursorNavigationAttached*> m_children;
@@ -103,6 +112,7 @@ private:
friend class CursorNavigation;
QQuickItem * m_escapeTarget;
+ QVector<Redirect*> m_redirects;
};
#endif // CURSORNAVIGATIONATTACHED_H
diff --git a/plugin/plugin.cpp b/plugin/plugin.cpp
index 26d156a..87cc430 100644
--- a/plugin/plugin.cpp
+++ b/plugin/plugin.cpp
@@ -1,5 +1,6 @@
#include "plugin.h"
#include "cursornavigation.h"
+#include "redirect.h"
#include "qqml.h"
CursorNavigationPlugin::CursorNavigationPlugin()
@@ -10,4 +11,5 @@ void CursorNavigationPlugin::registerTypes(const char *uri)
{
qmlRegisterUncreatableType<CursorNavigation>(uri, 1, 0, "CursorNavigation",
QStringLiteral("CursorNavigation is not creatable, use the attached properties."));
+ qmlRegisterType<Redirect>(uri, 1, 0, "Redirect");
}
diff --git a/plugin/plugin.pro b/plugin/plugin.pro
index 4d7fed9..b5cdee7 100644
--- a/plugin/plugin.pro
+++ b/plugin/plugin.pro
@@ -16,7 +16,8 @@ SOURCES += \
cursornavigationalgorithm.cpp \
spatialnavigation4dir.cpp \
inputtypes.cpp \
- spatialnavigation360.cpp
+ spatialnavigation360.cpp \
+ redirect.cpp
HEADERS += \
plugin.h \
@@ -26,7 +27,8 @@ HEADERS += \
inputtypes.h \
cursornavigationalgorithm.h \
spatialnavigation4dir.h \
- spatialnavigation360.h
+ spatialnavigation360.h \
+ redirect.h
pluginfiles.files += qmldir
diff --git a/plugin/redirect.cpp b/plugin/redirect.cpp
new file mode 100644
index 0000000..3c33571
--- /dev/null
+++ b/plugin/redirect.cpp
@@ -0,0 +1,68 @@
+#include "redirect.h"
+#include <QQuickItem>
+#include <QtMath>
+#include "inputtypes.h"
+
+Redirect::Redirect(QObject *parent)
+:QObject(parent)
+,m_start(-1)
+,m_end(-1)
+,m_target(nullptr)
+{
+}
+
+Redirect::~Redirect()
+{
+}
+
+qreal Redirect::start() const
+{
+ return m_start;
+}
+
+qreal Redirect::end() const
+{
+ return m_end;
+}
+
+QQuickItem *Redirect::target() const
+{
+ return m_target;
+}
+
+void Redirect::setStart(qreal start)
+{
+ m_start = start;
+ m_startR = CursorNavigationCommand::fitAngle(qDegreesToRadians(start));
+}
+
+void Redirect::setEnd(qreal end)
+{
+ m_end = end;
+ m_endR = CursorNavigationCommand::fitAngle(qDegreesToRadians(end));
+}
+
+void Redirect::setTarget(QQuickItem *target)
+{
+ if (m_target) {
+ disconnect(m_target, &QObject::destroyed, this, &Redirect::onTargetDestroyed);
+ }
+ m_target = target;
+ if (m_target) {
+ connect(m_target, &QObject::destroyed, this, &Redirect::onTargetDestroyed);
+ }
+}
+
+bool Redirect::angleIsIncluded(qreal angle)
+{
+ if (m_startR > m_endR)
+ return angle >= m_startR || angle <= m_endR;
+ else
+ return angle >= m_startR && angle <= m_endR;
+}
+
+void Redirect::onTargetDestroyed()
+{
+ m_target = nullptr;
+}
+
diff --git a/plugin/redirect.h b/plugin/redirect.h
new file mode 100644
index 0000000..232f07b
--- /dev/null
+++ b/plugin/redirect.h
@@ -0,0 +1,41 @@
+#ifndef REDIRECT_H
+#define REDIRECT_H
+
+#include <QObject>
+
+class QQuickItem;
+
+class Redirect : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal start READ start WRITE setStart)
+ Q_PROPERTY(qreal end READ end WRITE setEnd)
+ Q_PROPERTY(QQuickItem *target READ target WRITE setTarget)
+public:
+ Redirect(QObject *parent = nullptr);
+ virtual ~Redirect();
+
+ qreal start() const;
+ qreal end() const;
+ QQuickItem *target() const;
+
+ void setStart(qreal start);
+ void setEnd(qreal end);
+ void setTarget(QQuickItem *target);
+
+ bool angleIsIncluded(qreal angle);
+
+private slots:
+ void onTargetDestroyed();
+
+private:
+ qreal m_start;
+ qreal m_end;
+ //fitted angles in radians
+ qreal m_startR;
+ qreal m_endR;
+ QQuickItem *m_target;
+};
+
+#endif // REDIRECT_H