[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [calligra/krita-new-move-tool-kazakov] krita/ui: Fixed the second half of bug 302758
From: Dmitry Kazakov <dimula73 () gmail ! com>
Date: 2012-11-12 15:34:47
Message-ID: 20121112153447.36FE0A6091 () git ! kde ! org
[Download RAW message or body]
Git commit ac7eea24b10c0920fbef3e65f59db2722998d30e by Dmitry Kazakov.
Committed on 12/11/2012 at 16:33.
Pushed by dkazakov into branch 'krita-new-move-tool-kazakov'.
Fixed the second half of bug 302758
This patch almost rewrites the KisInputManager to fix the mentioned
bug. Now all the state transitions of the actions are controlled by
a special class KisShorcutMatcher. This class is easily controlled by
a separate unittest. The work of the actions is now can be represented
by a simple state machine with three states (see docs for class
KisStrokeShortcut).
CCBUG:302758
M +4 -1 krita/ui/CMakeLists.txt
M +39 -18 krita/ui/input/kis_abstract_input_action.cpp
M +50 -23 krita/ui/input/kis_abstract_input_action.h
A +68 -0 krita/ui/input/kis_abstract_shortcut.cpp [License: GPL (v2+)]
A +72 -0 krita/ui/input/kis_abstract_shortcut.h [License: GPL (v2+)]
M +16 -16 krita/ui/input/kis_alternate_invocation_action.cpp
M +3 -5 krita/ui/input/kis_alternate_invocation_action.h
M +16 -16 krita/ui/input/kis_change_primary_setting_action.cpp
M +3 -5 krita/ui/input/kis_change_primary_setting_action.h
M +218 -279 krita/ui/input/kis_input_manager.cpp
M +4 -9 krita/ui/input/kis_input_manager.h
A +70 -0 krita/ui/input/kis_key_shortcut.cpp [License: GPL (v2+)]
A +54 -0 krita/ui/input/kis_key_shortcut.h [License: GPL (v2+)]
M +17 -38 krita/ui/input/kis_pan_action.cpp
M +4 -4 krita/ui/input/kis_pan_action.h
M +25 -57 krita/ui/input/kis_rotate_canvas_action.cpp
M +4 -9 krita/ui/input/kis_rotate_canvas_action.h
D +0 -162 krita/ui/input/kis_shortcut.cpp
D +0 -120 krita/ui/input/kis_shortcut.h
A +287 -0 krita/ui/input/kis_shortcut_matcher.cpp [License: GPL (v2+)]
A +143 -0 krita/ui/input/kis_shortcut_matcher.h [License: GPL (v2+)]
M +3 -12 krita/ui/input/kis_show_palette_action.cpp
M +1 -3 krita/ui/input/kis_show_palette_action.h
A +72 -0 krita/ui/input/kis_stroke_shortcut.cpp [License: GPL (v2+)]
A +80 -0 krita/ui/input/kis_stroke_shortcut.h [License: GPL (v2+)]
M +33 -50 krita/ui/input/kis_tool_invocation_action.cpp
M +3 -5 krita/ui/input/kis_tool_invocation_action.h
M +19 -47 krita/ui/input/kis_zoom_action.cpp
M +4 -8 krita/ui/input/kis_zoom_action.h
M +6 -0 krita/ui/tests/CMakeLists.txt
A +357 -0 krita/ui/tests/kis_input_manager_test.cpp [License: GPL (v2+)]
C +14 -19 krita/ui/tests/kis_input_manager_test.h [from: \
krita/ui/input/kis_show_palette_action.h - 053% similarity] [License: GPL]
http://commits.kde.org/calligra/ac7eea24b10c0920fbef3e65f59db2722998d30e
diff --git a/krita/ui/CMakeLists.txt b/krita/ui/CMakeLists.txt
index 640d0a6..a0cb7d6 100644
--- a/krita/ui/CMakeLists.txt
+++ b/krita/ui/CMakeLists.txt
@@ -189,7 +189,6 @@ set(kritaui_LIB_SRCS
# widgets/kis_light_source.cpp
# widgets/kis_light_stage.cpp
input/kis_input_manager.cpp
- input/kis_shortcut.cpp
input/kis_abstract_input_action.cpp
input/kis_tool_invocation_action.cpp
input/kis_pan_action.cpp
@@ -198,6 +197,10 @@ set(kritaui_LIB_SRCS
input/kis_zoom_action.cpp
input/kis_show_palette_action.cpp
input/kis_change_primary_setting_action.cpp
+ input/kis_abstract_shortcut.cpp
+ input/kis_key_shortcut.cpp
+ input/kis_stroke_shortcut.cpp
+ input/kis_shortcut_matcher.cpp
kis_ui_action_factory.cpp
kis_ui_action_factory_registry.cpp
actions/kis_selection_action_factories.cpp
diff --git a/krita/ui/input/kis_abstract_input_action.cpp \
b/krita/ui/input/kis_abstract_input_action.cpp index ace6b20..7eb4c69 100644
--- a/krita/ui/input/kis_abstract_input_action.cpp
+++ b/krita/ui/input/kis_abstract_input_action.cpp
@@ -19,6 +19,7 @@
#include "kis_abstract_input_action.h"
#include <QPointF>
+#include <QMouseEvent>
#include <KLocalizedString>
class KisAbstractInputAction::Private
@@ -30,7 +31,7 @@ public:
QString description;
QHash<QString, int> indexes;
- QPointF mousePosition;
+ QPointF lastMousePosition;
};
KisAbstractInputAction::KisAbstractInputAction(KisInputManager* manager) : d(new \
Private) @@ -44,9 +45,44 @@ KisAbstractInputAction::~KisAbstractInputAction()
delete d;
}
-bool KisAbstractInputAction::handleTablet() const
+void KisAbstractInputAction::activate()
{
- return false;
+}
+
+void KisAbstractInputAction::deactivate()
+{
+}
+
+void KisAbstractInputAction::begin(int shortcut, QEvent *event)
+{
+ Q_UNUSED(shortcut);
+
+ QMouseEvent *mouseEvent;
+ if (event && (mouseEvent = dynamic_cast<QMouseEvent*>(event))) {
+ d->lastMousePosition = mouseEvent->posF();
+ }
+}
+
+void KisAbstractInputAction::inputEvent(QEvent* event)
+{
+ QMouseEvent *mouseEvent;
+ if (event && (mouseEvent = dynamic_cast<QMouseEvent*>(event))) {
+ if (mouseEvent->type() == QEvent::MouseMove) {
+ mouseMoved(d->lastMousePosition, mouseEvent->posF());
+ }
+ d->lastMousePosition = mouseEvent->posF();
+ }
+}
+
+void KisAbstractInputAction::end(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+void KisAbstractInputAction::mouseMoved(const QPointF &lastPos, const QPointF &pos)
+{
+ Q_UNUSED(lastPos);
+ Q_UNUSED(pos);
}
KisInputManager* KisAbstractInputAction::inputManager() const
@@ -83,18 +119,3 @@ void KisAbstractInputAction::setShortcutIndexes(const QHash< \
QString, int >& ind {
d->indexes = indexes;
}
-
-bool KisAbstractInputAction::isBlockingAutoRepeat() const
-{
- return false;
-}
-
-QPointF KisAbstractInputAction::mousePosition() const
-{
- return d->mousePosition;
-}
-
-void KisAbstractInputAction::setMousePosition(const QPointF &position)
-{
- d->mousePosition = position;
-}
diff --git a/krita/ui/input/kis_abstract_input_action.h \
b/krita/ui/input/kis_abstract_input_action.h index 802ae27..6c78016 100644
--- a/krita/ui/input/kis_abstract_input_action.h
+++ b/krita/ui/input/kis_abstract_input_action.h
@@ -20,6 +20,7 @@
#define KIS_ABSTRACT_INPUT_ACTION_H
#include <QHash>
+#include "krita_export.h"
class QPointF;
class QEvent;
@@ -30,15 +31,27 @@ class KisInputManager;
*
* Input actions represent actions to be performed when interacting
* with the canvas. They are managed by KisInputManager and activated
- * when KisShortcut detects it matches a certain set of inputs.
+ * when KisKeyShortcut or KisStrokeShortcut detects it matches a certain
+ * set of inputs.
*
* The begin() method uses an index for the type of behaviour to activate.
* This index can be used to trigger behaviour when different events occur.
- * For example, in the Pan action, this is used to have a single toggle
- * behaviour and four additional options to pan a fixed amount in a certain
- * direction. Each action will always have at least one behaviour.
+ *
+ * The events can be of two types:
+ * 1) Key events. The input manager calls begin() and end() sequentially
+ * with an \p index parameter to begin() representing the type of
+ * action that should be performed. The \p event parameter of both
+ * calls in null.
+ * 2) Stroke events. The input manager calls begin() and end() on the
+ * corresponding mouse down and up events. The \p event parameter
+ * will be of QMouseEvent type, representing the event happened.
+ * All the mouse move events between begin() and end() will be
+ * redirected to the inputEvent() method.
+ *
+ * You can fetch the QTabletEvent data for the current mouse event
+ * with inputManager()->lastTabletEvent().
*/
-class KisAbstractInputAction
+class KRITAUI_EXPORT KisAbstractInputAction
{
public:
/**
@@ -53,27 +66,48 @@ public:
virtual ~KisAbstractInputAction();
/**
+ * The method is called when the action is yet to be started,
+ * that is, e.g. the user has pressed all the modifiers for the
+ * action but hasn't started painting yet. This method is a right
+ * place to show the user what he is going to do, e.g. change the
+ * cursor.
+ */
+ virtual void activate();
+
+ /**
+ * The method is called when the action is not a candidate for
+ * the starting anymore. The action should revert everything that
+ * was done in activate() method.
+ *
+ * \see activate()
+ */
+ virtual void deactivate();
+
+ /**
* Begin the action.
*
* \param shortcut The index of the behaviour to trigger.
+ * \param event The mouse event that has triggered this action.
+ * Is null for keyboard-activated actions.
*/
- virtual void begin(int shortcut) = 0;
+ virtual void begin(int shortcut, QEvent *event);
/**
* End the action.
+ * \param event The mouse event that has finished this action.
+ * Is null for keyboard-activated actions.
*/
- virtual void end() = 0;
+ virtual void end(QEvent *event);
/**
* Process an input event.
*
+ * By default handles MouseMove events and passes the data to
+ * a convenience mouseMoved() method
+ *
* \param event An event to process.
*/
- virtual void inputEvent(QEvent* event) = 0;
+ virtual void inputEvent(QEvent* event);
/**
- * Does this action handle tablet events in a special way?
- */
- virtual bool handleTablet() const;
- /**
* The indexes of shortcut behaviours available.
*/
virtual QHash<QString, int> shortcutIndexes() const;
@@ -86,11 +120,6 @@ public:
*/
virtual QString description() const;
- /**
- * Does this action block auto repeat events?
- */
- virtual bool isBlockingAutoRepeat() const;
-
protected:
/**
* The input manager this action belongs to.
@@ -114,14 +143,12 @@ protected:
* \param indexes The new indexes.
*/
void setShortcutIndexes(const QHash<QString, int> &indexes);
+
/**
- * Return the locally cached mouse position.
- */
- QPointF mousePosition() const;
- /**
- * Set a mouse position to cache locally.
+ * Convenience method for handling the mouse moves. It is
+ * called by the default implementation of inputEvent
*/
- void setMousePosition(const QPointF &position);
+ virtual void mouseMoved(const QPointF &lastPos, const QPointF &pos);
private:
class Private;
diff --git a/krita/ui/input/kis_abstract_shortcut.cpp \
b/krita/ui/input/kis_abstract_shortcut.cpp new file mode 100644
index 0000000..661006b
--- /dev/null
+++ b/krita/ui/input/kis_abstract_shortcut.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_abstract_shortcut.h"
+
+struct KisAbstractShortcut::Private
+{
+ KisAbstractInputAction *action;
+ int shortcutIndex;
+};
+
+KisAbstractShortcut::KisAbstractShortcut(KisAbstractInputAction *action, int index)
+ : m_d(new Private)
+{
+ m_d->action = action;
+ m_d->shortcutIndex = index;
+}
+
+KisAbstractShortcut::~KisAbstractShortcut()
+{
+ delete m_d;
+}
+
+KisAbstractInputAction* KisAbstractShortcut::action() const
+{
+ return m_d->action;
+}
+
+void KisAbstractShortcut::setAction(KisAbstractInputAction* action)
+{
+ m_d->action = action;
+}
+
+int KisAbstractShortcut::shortcutIndex() const
+{
+ return m_d->shortcutIndex;
+}
+
+void KisAbstractShortcut::setShortcutIndex(int index)
+{
+ m_d->shortcutIndex = index;
+}
+
+bool KisAbstractShortcut::compareKeys(const QList<Qt::Key> &keys1,
+ const QList<Qt::Key> &keys2)
+{
+ if (keys1.size() != keys2.size()) return false;
+
+ foreach(Qt::Key key, keys1) {
+ if (!keys2.contains(key)) return false;
+ }
+ return true;
+}
diff --git a/krita/ui/input/kis_abstract_shortcut.h \
b/krita/ui/input/kis_abstract_shortcut.h new file mode 100644
index 0000000..8ea368c
--- /dev/null
+++ b/krita/ui/input/kis_abstract_shortcut.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_ABSTRACT_SHORTCUT_H
+#define __KIS_ABSTRACT_SHORTCUT_H
+
+#include <Qt>
+#include <QList>
+#include <krita_export.h>
+class KisAbstractInputAction;
+
+
+class KRITAUI_EXPORT KisAbstractShortcut
+{
+public:
+ KisAbstractShortcut(KisAbstractInputAction *action, int index);
+ virtual ~KisAbstractShortcut();
+
+ /**
+ * The priority of the shortcut. The shortcut with the
+ * greatest value will be chosen for executution
+ */
+ virtual int priority() const = 0;
+
+ /**
+ * The action associated with this shortcut.
+ */
+ KisAbstractInputAction* action() const;
+
+ /**
+ * Set the action associated with this shortcut.
+ */
+ void setAction(KisAbstractInputAction *action);
+
+ /**
+ * The index of the shortcut.
+ *
+ * \see KisAbstractInputAction::begin()
+ */
+ int shortcutIndex() const;
+
+ /**
+ * Set the index of the shortcut.
+ */
+ void setShortcutIndex(int index);
+
+protected:
+ bool compareKeys(const QList<Qt::Key> &keys1,
+ const QList<Qt::Key> &keys2);
+
+private:
+ class Private;
+ Private * const m_d;
+};
+
+#endif /* __KIS_ABSTRACT_SHORTCUT_H */
diff --git a/krita/ui/input/kis_alternate_invocation_action.cpp \
b/krita/ui/input/kis_alternate_invocation_action.cpp index b7fbd77..656fc46 100644
--- a/krita/ui/input/kis_alternate_invocation_action.cpp
+++ b/krita/ui/input/kis_alternate_invocation_action.cpp
@@ -37,28 +37,28 @@ KisAlternateInvocationAction::~KisAlternateInvocationAction()
{
}
-void KisAlternateInvocationAction::begin(int /*shortcut*/)
+void KisAlternateInvocationAction::begin(int shortcut, QEvent *event)
{
- QMouseEvent mevent(QEvent::MouseButtonPress, \
inputManager()->mousePosition().toPoint(), Qt::LeftButton, Qt::LeftButton, \
Qt::ControlModifier);
- inputManager()->toolProxy()->mousePressEvent(&mevent, \
inputManager()->mousePosition());
-}
+ KisAbstractInputAction::begin(shortcut, event);
-void KisAlternateInvocationAction::end()
-{
- QMouseEvent mevent(QEvent::MouseButtonRelease, mousePosition().toPoint(), \
Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
- inputManager()->toolProxy()->mouseReleaseEvent(&mevent, mousePosition());
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+ QMouseEvent targetEvent(QEvent::MouseButtonPress, mouseEvent->pos(), \
Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); + \
inputManager()->toolProxy()->mousePressEvent(&targetEvent, \
inputManager()->widgetToPixel(mouseEvent->posF())); }
-void KisAlternateInvocationAction::inputEvent(QEvent* event)
+void KisAlternateInvocationAction::end(QEvent *event)
{
- if(event->type() == QEvent::MouseMove) {
- QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
- setMousePosition(inputManager()->widgetToPixel(mevent->posF()));
- inputManager()->toolProxy()->mouseMoveEvent(mevent, mousePosition());
- }
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+ QMouseEvent targetEvent(QEvent::MouseButtonRelease, mouseEvent->pos(), \
Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier); + \
inputManager()->toolProxy()->mouseReleaseEvent(&targetEvent, \
inputManager()->widgetToPixel(mouseEvent->posF())); +
+ KisAbstractInputAction::end(event);
}
-bool KisAlternateInvocationAction::isBlockingAutoRepeat() const
+void KisAlternateInvocationAction::mouseMoved(const QPointF &lastPos, const QPointF \
&pos) {
- return true;
+ Q_UNUSED(lastPos);
+
+ QMouseEvent targetEvent(QEvent::MouseButtonRelease, pos.toPoint(), Qt::NoButton, \
Qt::LeftButton, Qt::ControlModifier); + \
inputManager()->toolProxy()->mouseMoveEvent(&targetEvent, \
inputManager()->widgetToPixel(pos)); }
diff --git a/krita/ui/input/kis_alternate_invocation_action.h \
b/krita/ui/input/kis_alternate_invocation_action.h index 9da4dc8..bd5fa2d 100644
--- a/krita/ui/input/kis_alternate_invocation_action.h
+++ b/krita/ui/input/kis_alternate_invocation_action.h
@@ -34,11 +34,9 @@ public:
explicit KisAlternateInvocationAction(KisInputManager *manager);
virtual ~KisAlternateInvocationAction();
- virtual void begin(int /*shortcut*/);
- virtual void end();
- virtual void inputEvent(QEvent* event);
-
- virtual bool isBlockingAutoRepeat() const;
+ void begin(int shortcut, QEvent *event);
+ void end(QEvent *event);
+ void mouseMoved(const QPointF &lastPos, const QPointF &pos);
};
#endif // KIS_ALTERNATE_INVOCATION_ACTION_H
diff --git a/krita/ui/input/kis_change_primary_setting_action.cpp \
b/krita/ui/input/kis_change_primary_setting_action.cpp index bcff0c8..9f60cfc 100644
--- a/krita/ui/input/kis_change_primary_setting_action.cpp
+++ b/krita/ui/input/kis_change_primary_setting_action.cpp
@@ -35,28 +35,28 @@ KisChangePrimarySettingAction::~KisChangePrimarySettingAction()
}
-void KisChangePrimarySettingAction::begin(int shortcut)
+void KisChangePrimarySettingAction::begin(int shortcut, QEvent *event)
{
- QMouseEvent mevent(QEvent::MouseButtonPress, \
inputManager()->mousePosition().toPoint(), Qt::LeftButton, Qt::LeftButton, \
Qt::ShiftModifier);
- inputManager()->toolProxy()->mousePressEvent(&mevent, \
inputManager()->mousePosition());
-}
+ KisAbstractInputAction::begin(shortcut, event);
-void KisChangePrimarySettingAction::end()
-{
- QMouseEvent mevent(QEvent::MouseButtonRelease, mousePosition().toPoint(), \
Qt::LeftButton, Qt::LeftButton, Qt::ShiftModifier);
- inputManager()->toolProxy()->mouseReleaseEvent(&mevent, mousePosition());
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+ QMouseEvent targetEvent(QEvent::MouseButtonPress, mouseEvent->pos(), \
Qt::LeftButton, Qt::LeftButton, Qt::ShiftModifier); + \
inputManager()->toolProxy()->mousePressEvent(&targetEvent, \
inputManager()->widgetToPixel(mouseEvent->posF())); }
-void KisChangePrimarySettingAction::inputEvent(QEvent* event)
+void KisChangePrimarySettingAction::end(QEvent *event)
{
- if(event->type() == QEvent::MouseMove) {
- QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
- setMousePosition(inputManager()->widgetToPixel(mevent->posF()));
- inputManager()->toolProxy()->mouseMoveEvent(mevent, mousePosition());
- }
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+ QMouseEvent targetEvent(QEvent::MouseButtonRelease, mouseEvent->pos(), \
Qt::LeftButton, Qt::LeftButton, Qt::ShiftModifier); + \
inputManager()->toolProxy()->mouseReleaseEvent(&targetEvent, \
inputManager()->widgetToPixel(mouseEvent->posF())); +
+ KisAbstractInputAction::end(event);
}
-bool KisChangePrimarySettingAction::isBlockingAutoRepeat() const
+void KisChangePrimarySettingAction::mouseMoved(const QPointF &lastPos, const QPointF \
&pos) {
- return true;
+ Q_UNUSED(lastPos);
+
+ QMouseEvent targetEvent(QEvent::MouseButtonRelease, pos.toPoint(), Qt::NoButton, \
Qt::LeftButton, Qt::ShiftModifier); + \
inputManager()->toolProxy()->mouseMoveEvent(&targetEvent, \
inputManager()->widgetToPixel(pos)); }
diff --git a/krita/ui/input/kis_change_primary_setting_action.h \
b/krita/ui/input/kis_change_primary_setting_action.h index 7fceeee..0efc167 100644
--- a/krita/ui/input/kis_change_primary_setting_action.h
+++ b/krita/ui/input/kis_change_primary_setting_action.h
@@ -33,11 +33,9 @@ public:
explicit KisChangePrimarySettingAction(KisInputManager* manager);
virtual ~KisChangePrimarySettingAction();
- virtual void begin(int shortcut);
- virtual void end();
- virtual void inputEvent(QEvent* event);
-
- virtual bool isBlockingAutoRepeat() const;
+ void begin(int shortcut, QEvent *event);
+ void end(QEvent *event);
+ void mouseMoved(const QPointF &lastPos, const QPointF &pos);
};
#endif // KISCHANGEPRIMARYSETTINGACTION_H
diff --git a/krita/ui/input/kis_input_manager.cpp \
b/krita/ui/input/kis_input_manager.cpp index 98475be..c77000e 100644
--- a/krita/ui/input/kis_input_manager.cpp
+++ b/krita/ui/input/kis_input_manager.cpp
@@ -34,7 +34,6 @@
#include <kis_canvas_resource_provider.h>
#include <ko_favorite_resource_manager.h>
-#include "kis_shortcut.h"
#include "kis_abstract_input_action.h"
#include "kis_tool_invocation_action.h"
#include "kis_pan_action.h"
@@ -44,174 +43,136 @@
#include "kis_show_palette_action.h"
#include "kis_change_primary_setting_action.h"
+#include "kis_shortcut_matcher.h"
+#include "kis_stroke_shortcut.h"
+#include "kis_key_shortcut.h"
+
class KisInputManager::Private
{
public:
Private(KisInputManager *qq)
: q(qq)
, toolProxy(0)
- , currentAction(0)
- , currentShortcut(0)
- , tabletPressEvent(0)
, setMirrorMode(false)
- , fixedAction(false)
+ , forwardAllEventsToTool(false)
+ , lastTabletEvent(0)
{ }
- void match(QEvent *event);
+ bool tryHidePopupPalette();
+ bool trySetMirrorMode(const QPointF &mousePosition);
+ void saveTabletEvent(const QTabletEvent *event);
+ void resetSavedTabletEvent();
+ void addStrokeShortcut(KisAbstractInputAction* action, int index,
+ const QList<Qt::Key> &modifiers,
+ const QList<Qt::MouseButton> &buttons);
+ void addKeyShortcut(KisAbstractInputAction* action, int index,
+ const QList<Qt::Key> &modifiers,
+ Qt::Key key);
+ bool processUnhandledEvent(QEvent *event);
void setupActions();
- KisShortcut *createShortcut(KisAbstractInputAction* action, int index);
- void clearState();
KisInputManager *q;
KisCanvas2 *canvas;
KoToolProxy *toolProxy;
- KisAbstractInputAction* currentAction;
- KisShortcut* currentShortcut;
-
- QList<KisShortcut*> shortcuts;
- QList<KisAbstractInputAction*> actions;
-
- QList<KisShortcut*> potentialShortcuts;
-
- QPointF mousePosition;
+ bool setMirrorMode;
+ bool forwardAllEventsToTool;
- QTabletEvent *tabletPressEvent;
+ KisShortcutMatcher matcher;
+ QTabletEvent *lastTabletEvent;
- bool setMirrorMode;
- bool fixedAction;
+ KisAbstractInputAction *defaultInputAction;
};
-void KisInputManager::Private::match(QEvent* event)
-{
- if (fixedAction) {
- return;
- }
- //Go through all possible shortcuts and update their state.
- foreach (KisShortcut* shortcut, potentialShortcuts) {
- shortcut->match(event);
- if(shortcut->matchLevel() == KisShortcut::NoMatch) {
- //There is no chance of this shortcut matching anything with the current \
input,
- //so remove it from the list of shortcuts to search through.
- potentialShortcuts.removeOne(shortcut);
- }
- }
-
- if (potentialShortcuts.count() == 0) {
- //With the current input, there is simply no shortcut that matches,
- //so restart the matching.
- potentialShortcuts = shortcuts;
- return;
- }
+static inline QList<Qt::Key> KEYS() {
+ return QList<Qt::Key>();
+}
+static inline QList<Qt::Key> KEYS(Qt::Key key) {
+ return QList<Qt::Key>() << key;
+}
+static inline QList<Qt::Key> KEYS(Qt::Key key1, Qt::Key key2) {
+ return QList<Qt::Key>() << key1 << key2;
+}
+static inline QList<Qt::MouseButton> BUTTONS(Qt::MouseButton button) {
+ return QList<Qt::MouseButton>() << button;
+}
+static inline QList<Qt::MouseButton> BUTTONS(Qt::MouseButton button1, \
Qt::MouseButton button2) { + return QList<Qt::MouseButton>() << button1 << \
button2; +}
- if (potentialShortcuts.count() == 1 || event->type() == QEvent::MouseButtonPress \
|| event->type() == QEvent::MouseButtonDblClick) {
- //Either we have only one possible match or we reached the queue threshold.
- KisShortcut* completedShortcut = 0;
- foreach (KisShortcut* shortcut, potentialShortcuts) {
- if (shortcut->matchLevel() == KisShortcut::CompleteMatch) {
- //Set the matched shortcut to the one with the highest \
priority.std::
- if (!completedShortcut || completedShortcut->priority() < \
shortcut->priority()) {
- completedShortcut = shortcut;
- }
- } else {
- shortcut->clear();
- }
- }
+void KisInputManager::Private::addStrokeShortcut(KisAbstractInputAction* action, int \
index, + const QList<Qt::Key> \
&modifiers, + const \
QList<Qt::MouseButton> &buttons) +{
+ KisStrokeShortcut *strokeShortcut =
+ new KisStrokeShortcut(action, index);
+ strokeShortcut->setButtons(modifiers, buttons);
+ matcher.addShortcut(strokeShortcut);
+}
- //We really do have a matched action, so lets activate it.
- if (completedShortcut) {
- currentShortcut = completedShortcut;
- currentAction = completedShortcut->action();
- currentAction->begin(completedShortcut->shortcutIndex());
- }
- }
+void KisInputManager::Private::addKeyShortcut(KisAbstractInputAction* action, int \
index, + const QList<Qt::Key> \
&modifiers, + Qt::Key key)
+{
+ KisKeyShortcut *keyShortcut =
+ new KisKeyShortcut(action, index);
+ keyShortcut->setKey(modifiers, key);
+ matcher.addShortcut(keyShortcut);
}
void KisInputManager::Private::setupActions()
{
+#if QT_VERSION >= 0x040700
+ Qt::MouseButton middleButton = Qt::MiddleButton;
+#else
+ Qt::MouseButton middleButton = Qt::MidButton;
+#endif
+
//Create all the actions.
KisAbstractInputAction* action = new KisToolInvocationAction(q);
- actions.append(action);
-
- KisShortcut* shortcut = createShortcut(action, \
KisToolInvocationAction::ActivateShortcut);
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::LeftButton);
-
- shortcut = createShortcut(action, KisToolInvocationAction::ConfirmShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Return);
+ matcher.addAction(action);
+ addStrokeShortcut(action, KisToolInvocationAction::ActivateShortcut, KEYS(), \
BUTTONS(Qt::LeftButton)); + addKeyShortcut(action, \
KisToolInvocationAction::ConfirmShortcut, KEYS(), Qt::Key_Return); + \
defaultInputAction = action;
action = new KisAlternateInvocationAction(q);
- actions.append(action);
-
- shortcut = createShortcut(action, 0);
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::LeftButton);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Control);
+ matcher.addAction(action);
+ addStrokeShortcut(action, 0, KEYS(Qt::Key_Control), BUTTONS(Qt::LeftButton));
action = new KisChangePrimarySettingAction(q);
- actions.append(action);
+ matcher.addAction(action);
+ addStrokeShortcut(action, 0, KEYS(Qt::Key_Shift), BUTTONS(Qt::LeftButton));
- shortcut = createShortcut(action, 0);
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::LeftButton);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Shift);
action = new KisPanAction(q);
- actions.append(action);
+ matcher.addAction(action);
- shortcut = createShortcut(action, KisPanAction::PanToggleShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Space);
+ addStrokeShortcut(action, KisPanAction::PanToggleShortcut, KEYS(Qt::Key_Space), \
BUTTONS(Qt::LeftButton)); + addStrokeShortcut(action, \
KisPanAction::PanToggleShortcut, KEYS(), BUTTONS(middleButton));
- shortcut = createShortcut(action, KisPanAction::PanToggleShortcut);
-#if QT_VERSION >= 0x040700
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::MiddleButton);
-#else
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::MidButton);
-#endif
+ addKeyShortcut(action, KisPanAction::PanLeftShortcut, KEYS(), Qt::Key_Left);
+ addKeyShortcut(action, KisPanAction::PanRightShortcut, KEYS(), Qt::Key_Right);
+ addKeyShortcut(action, KisPanAction::PanUpShortcut, KEYS(), Qt::Key_Up);
+ addKeyShortcut(action, KisPanAction::PanDownShortcut, KEYS(), Qt::Key_Down);
- shortcut = createShortcut(action, KisPanAction::PanLeftShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Left);
- shortcut = createShortcut(action, KisPanAction::PanRightShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Right);
- shortcut = createShortcut(action, KisPanAction::PanUpShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Up);
- shortcut = createShortcut(action, KisPanAction::PanDownShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Down);
action = new KisRotateCanvasAction(q);
- actions.append(action);
+ matcher.addAction(action);
- shortcut = createShortcut(action, KisRotateCanvasAction::RotateToggleShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Space);
+ addStrokeShortcut(action, KisPanAction::PanToggleShortcut, KEYS(Qt::Key_Shift, \
Qt::Key_Space), BUTTONS(Qt::LeftButton)); + addStrokeShortcut(action, \
KisPanAction::PanToggleShortcut, KEYS(Qt::Key_Shift), BUTTONS(middleButton));
- shortcut = createShortcut(action, KisRotateCanvasAction::RotateToggleShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Shift);
-#if QT_VERSION >= 0x040700
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::MiddleButton);
-#else
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::MidButton);
-#endif
+ addKeyShortcut(action, KisRotateCanvasAction::RotateLeftShortcut, KEYS(), \
Qt::Key_4); + addKeyShortcut(action, KisRotateCanvasAction::RotateResetShortcut, \
KEYS(), Qt::Key_5); + addKeyShortcut(action, \
KisRotateCanvasAction::RotateRightShortcut, KEYS(), Qt::Key_6);
- shortcut = createShortcut(action, KisRotateCanvasAction::RotateLeftShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_4);
-
- shortcut = createShortcut(action, KisRotateCanvasAction::RotateRightShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_6);
-
- shortcut = createShortcut(action, KisRotateCanvasAction::RotateResetShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_5);
action = new KisZoomAction(q);
- actions.append(action);
-
- shortcut = createShortcut(action, KisZoomAction::ZoomToggleShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Control << Qt::Key_Space);
+ matcher.addAction(action);
- shortcut = createShortcut(action, KisZoomAction::ZoomToggleShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Control);
-#if QT_VERSION >= 0x040700
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::MiddleButton);
-#else
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::MidButton);
-#endif
+ addStrokeShortcut(action, KisZoomAction::ZoomToggleShortcut, \
KEYS(Qt::Key_Control, Qt::Key_Space), BUTTONS(Qt::LeftButton)); + \
addStrokeShortcut(action, KisZoomAction::ZoomToggleShortcut, KEYS(Qt::Key_Control), \
BUTTONS(middleButton));
/**
* FIXME: Zooming with Wheel is implemented on a level of
@@ -229,57 +190,84 @@ void KisInputManager::Private::setupActions()
// shortcut = createShortcut(action, KisZoomAction::ZoomOutShortcut);
// shortcut->setWheel(KisShortcut::WheelDown);
- shortcut = createShortcut(action, KisZoomAction::ZoomInShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Plus);
- shortcut = createShortcut(action, KisZoomAction::ZoomOutShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_Minus);
+ addKeyShortcut(action, KisZoomAction::ZoomInShortcut, KEYS(), Qt::Key_Plus);
+ addKeyShortcut(action, KisZoomAction::ZoomOutShortcut, KEYS(), Qt::Key_Minus);
- shortcut = createShortcut(action, KisZoomAction::ZoomResetShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_1);
- shortcut = createShortcut(action, KisZoomAction::ZoomToPageShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_2);
- shortcut = createShortcut(action, KisZoomAction::ZoomToWidthShortcut);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_3);
+ addKeyShortcut(action, KisZoomAction::ZoomResetShortcut, KEYS(), Qt::Key_1);
+ addKeyShortcut(action, KisZoomAction::ZoomToPageShortcut, KEYS(), Qt::Key_2);
+ addKeyShortcut(action, KisZoomAction::ZoomToWidthShortcut, KEYS(), Qt::Key_3);
action = new KisShowPaletteAction(q);
- actions.append(action);
-
- shortcut = createShortcut(action, 0);
- shortcut->setButtons(QList<Qt::MouseButton>() << Qt::RightButton);
+ matcher.addAction(action);
- shortcut = createShortcut(action, 0);
- shortcut->setKeys(QList<Qt::Key>() << Qt::Key_F);
+ addStrokeShortcut(action, 0, KEYS(), BUTTONS(Qt::RightButton));
+ addKeyShortcut(action, 0, KEYS(), Qt::Key_F);
}
-KisShortcut* KisInputManager::Private::createShortcut(KisAbstractInputAction* \
action, int index) +bool KisInputManager::Private::processUnhandledEvent(QEvent \
*event) {
- KisShortcut* shortcut = new KisShortcut;
- shortcut->setAction(action);
- shortcut->setShortcutIndex(index);
- shortcuts.append(shortcut);
+ bool retval = false;
- return shortcut;
-}
+ if (forwardAllEventsToTool ||
+ event->type() == QEvent::KeyPress ||
+ event->type() == QEvent::KeyRelease) {
-void KisInputManager::Private::clearState()
-{
- if (fixedAction) {
- return;
+ defaultInputAction->inputEvent(event);
+ retval = true;
}
- if (currentShortcut) {
- currentAction->end();
- currentAction = 0;
- currentShortcut = 0;
- potentialShortcuts = shortcuts;
+ return retval && !forwardAllEventsToTool;
+}
- delete tabletPressEvent;
- tabletPressEvent = 0;
+bool KisInputManager::Private::tryHidePopupPalette()
+{
+ if (canvas->favoriteResourceManager()->isPopupPaletteVisible()) {
+ canvas->favoriteResourceManager()->slotShowPopupPalette();
+ return true;
}
+ return false;
+}
- foreach (KisShortcut* shortcut, shortcuts) {
- shortcut->clear();
+bool KisInputManager::Private::trySetMirrorMode(const QPointF &mousePosition)
+{
+ if (setMirrorMode) {
+ canvas->resourceManager()->setResource(KisCanvasResourceProvider::MirrorAxisCenter, \
canvas->image()->documentToPixel(mousePosition)); + \
QApplication::restoreOverrideCursor(); + setMirrorMode = false;
+ return true;
}
+ return false;
+}
+
+void KisInputManager::Private::saveTabletEvent(const QTabletEvent *event)
+{
+ delete lastTabletEvent;
+ lastTabletEvent =
+ new QTabletEvent(event->type(),
+ event->pos(),
+ event->globalPos(),
+ event->hiResGlobalPos(),
+ event->device(),
+ event->pointerType(),
+ event->pressure(),
+ event->xTilt(),
+ event->yTilt(),
+ event->tangentialPressure(),
+ event->rotation(),
+ event->z(),
+ event->modifiers(),
+ event->uniqueId());
+}
+
+void KisInputManager::Private::resetSavedTabletEvent()
+{
+ delete lastTabletEvent;
+ lastTabletEvent = 0;
+}
+
+QTabletEvent* KisInputManager::lastTabletEvent() const
+{
+ return d->lastTabletEvent;
}
KisInputManager::KisInputManager(KisCanvas2 *canvas, KoToolProxy *proxy)
@@ -290,8 +278,6 @@ KisInputManager::KisInputManager(KisCanvas2 *canvas, KoToolProxy \
*proxy)
d->setupActions();
- d->potentialShortcuts = d->shortcuts;
-
/*
* Temporary solution so we can still set the mirror axis.
*
@@ -310,135 +296,101 @@ KisInputManager::KisInputManager(KisCanvas2 *canvas, \
KoToolProxy *proxy)
KisInputManager::~KisInputManager()
{
- qDeleteAll(d->shortcuts);
- qDeleteAll(d->actions);
delete d;
}
bool KisInputManager::eventFilter(QObject* object, QEvent* event)
{
- Q_UNUSED(object)
+ Q_UNUSED(object);
+ bool retval = false;
+
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick: {
- d->mousePosition = widgetToPixel(static_cast<QMouseEvent*>(event)->posF());
-
- //If the palette is visible, then hide it and eat the event.
- if (canvas()->favoriteResourceManager()->isPopupPaletteVisible()) {
- canvas()->favoriteResourceManager()->slotShowPopupPalette();
- return true;
- }
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
- if (d->setMirrorMode) {
- d->canvas->resourceManager()->setResource(KisCanvasResourceProvider::MirrorAxisCenter, \
d->canvas->image()->documentToPixel(d->mousePosition));
- QApplication::restoreOverrideCursor();
- d->setMirrorMode = false;
- return true;
+ if (d->tryHidePopupPalette() || \
d->trySetMirrorMode(widgetToPixel(mouseEvent->posF()))) { + retval = true;
+ } else {
+ retval = d->matcher.buttonPressed(mouseEvent->button(), mouseEvent);
}
- } //Intentional fall through
- case QEvent::KeyPress:
- case QEvent::KeyRelease:
- if (event->type() == QEvent::KeyPress || event->type() == \
QEvent::KeyRelease) {
- QKeyEvent *kevent = static_cast<QKeyEvent*>(event);
- if (kevent->isAutoRepeat()) {
- if (d->currentAction) {
- if (d->currentAction->isBlockingAutoRepeat()) {
- return true; //Ignore auto repeat key events if the action \
is asking for it.
- }
- } else {
- return true; //Always ignore auto repeat key events when we do \
not have a current action.
- }
- }
+ d->resetSavedTabletEvent();
+ break;
+ }
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
+ retval = d->matcher.buttonReleased(mouseEvent->button(), mouseEvent);
+ d->resetSavedTabletEvent();
+ break;
+ }
+ case QEvent::KeyPress: {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+ if (!keyEvent->isAutoRepeat()) {
+ retval = d->matcher.keyPressed((Qt::Key)keyEvent->key());
}
- //Intentional fall through
- case QEvent::MouseButtonRelease:
- if (d->currentAction) { //If we are currently performing an action, we only \
update the state of that action and shortcut.
- d->currentShortcut->match(event);
-
- if ((d->currentShortcut->matchLevel() == KisShortcut::PartialMatch || \
d->currentShortcut->matchLevel() == KisShortcut::NoMatch)
- && !d->fixedAction) {
- d->clearState();
- break;
- }
-
- d->currentAction->inputEvent(event);
- } else { //Try to find a matching shortcut.
- d->match(event);
+
+ /**
+ * Workaround for temporary switching of tools by
+ * KoCanvasControllerWidget. We don't need this switch because
+ * we handle it ourselves.
+ */
+ retval |= !d->forwardAllEventsToTool &&
+ (keyEvent->key() == Qt::Key_Space ||
+ keyEvent->key() == Qt::Key_Escape);
+
+ break;
+ }
+ case QEvent::KeyRelease: {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+ if (!keyEvent->isAutoRepeat()) {
+ retval = d->matcher.keyReleased((Qt::Key)keyEvent->key());
}
- return true;
- case QEvent::MouseMove:
- if (!d->currentAction) {
- QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
+ break;
+ }
+ case QEvent::MouseMove: {
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
+ if (!d->matcher.mouseMoved(mouseEvent)) {
//Update the current tool so things like the brush outline gets updated.
- d->toolProxy->mouseMoveEvent(mevent, widgetToPixel(mevent->posF()));
- } else {
- d->currentAction->inputEvent(event);
- }
- return true;
- case QEvent::Wheel:
- if (d->currentAction) {
- d->currentAction->inputEvent(event);
- } else {
- d->match(event);
- if (d->currentAction) {
- d->clearState();
- }
+ d->toolProxy->mouseMoveEvent(mouseEvent, \
widgetToPixel(mouseEvent->posF())); }
+ retval = true;
+ d->resetSavedTabletEvent();
+ break;
+ }
+ case QEvent::Wheel: {
+ QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
+ KisKeyShortcut::WheelAction action =
+ wheelEvent->delta() > 0 ?
+ KisKeyShortcut::WheelUp : KisKeyShortcut::WheelDown;
+
+ retval = d->matcher.wheelEvent(action);
break;
+ }
case QEvent::Enter:
//Ensure we have focus so we get key events.
d->canvas->canvasWidget()->setFocus();
- return true;
+ break;
case QEvent::Leave:
//Clear all state so we don't have half-matched shortcuts dangling around.
- d->clearState();
- return true;
- case QEvent::TabletPress: {
+ d->matcher.reset();
+ break;
+ case QEvent::TabletPress:
+ case QEvent::TabletMove:
+ case QEvent::TabletRelease: {
//We want both the tablet information and the mouse button state.
- //Since QTabletEvent only provides the tablet information, we save that
- //and then ignore the event so it will generate a mouse event.
- QTabletEvent* tevent = static_cast<QTabletEvent*>(event);
-
- //Since events get deleted once they are processed we need to clone the \
event
- //to save it.
- QTabletEvent* newEvent = new QTabletEvent(QEvent::TabletPress,
- tevent->pos(),
- tevent->globalPos(),
- tevent->hiResGlobalPos(),
- tevent->device(),
- tevent->pointerType(),
- tevent->pressure(),
- tevent->xTilt(),
- tevent->yTilt(),
- tevent->tangentialPressure(),
- tevent->rotation(),
- tevent->z(),
- tevent->modifiers(),
- tevent->uniqueId()
- );
- d->tabletPressEvent = newEvent;
+ //Since QTabletEvent only provides the tablet information, we
+ //save that and then ignore the event so it will generate a mouse
+ //event.
+ QTabletEvent* tabletEvent = static_cast<QTabletEvent*>(event);
+ d->saveTabletEvent(tabletEvent);
event->ignore();
break;
}
- case QEvent::TabletMove:
- //Only process tablet move events if the current action has special code for \
it.
- //In all other cases, we simply ignore it so it will generate a mouse event
- //instead.
- if (d->currentAction && d->currentAction->handleTablet()) {
- d->currentAction->inputEvent(event);
- return true;
- } else {
- event->ignore();
- }
- break;
- case QEvent::TabletRelease:
- //Always ignore tablet release events and have them generate mouse events \
instead.
- event->ignore();
default:
break;
}
- return false;
+ return !retval ? d->processUnhandledEvent(event) : true;
}
KisCanvas2* KisInputManager::canvas() const
@@ -451,16 +403,6 @@ KoToolProxy* KisInputManager::toolProxy() const
return d->toolProxy;
}
-QPointF KisInputManager::mousePosition() const
-{
- return d->mousePosition;
-}
-
-QTabletEvent* KisInputManager::tabletPressEvent() const
-{
- return d->tabletPressEvent;
-}
-
void KisInputManager::setMirrorAxis()
{
d->setMirrorMode = true;
@@ -471,14 +413,11 @@ void KisInputManager::slotToolChanged()
{
QString toolId = KoToolManager::instance()->activeToolId();
if (toolId == "ArtisticTextToolFactoryID" || toolId == "TextToolFactory_ID") {
- d->fixedAction = true;
- if (!d->currentAction) {
- d->currentShortcut = d->shortcuts.at(0);
- d->currentAction = d->currentShortcut->action();
- d->currentAction->begin(d->currentShortcut->shortcutIndex());
- }
+ d->forwardAllEventsToTool = true;
+ d->matcher.suppressAllActions(true);
} else {
- d->fixedAction = false;
+ d->forwardAllEventsToTool = false;
+ d->matcher.suppressAllActions(false);
}
}
diff --git a/krita/ui/input/kis_input_manager.h b/krita/ui/input/kis_input_manager.h
index 8689684..5a269d3 100644
--- a/krita/ui/input/kis_input_manager.h
+++ b/krita/ui/input/kis_input_manager.h
@@ -75,17 +75,12 @@ public:
* The tool proxy of the current application.
*/
KoToolProxy *toolProxy() const;
+
/**
- * The mouse position of the last mouse press event.
- */
- QPointF mousePosition() const;
- /**
- * This method can be used by actions to check whether we are
- * dealing with tablet events.
- *
- * \return A tablet press event if there was one, otherwise 0.
+ * Returns the event object for the last tablet event
+ * happened. Returns null if there was no tablet event recently
*/
- QTabletEvent *tabletPressEvent() const;
+ QTabletEvent *lastTabletEvent() const;
/**
* Convert a widget position to a pixel position.
diff --git a/krita/ui/input/kis_key_shortcut.cpp \
b/krita/ui/input/kis_key_shortcut.cpp new file mode 100644
index 0000000..54c3957
--- /dev/null
+++ b/krita/ui/input/kis_key_shortcut.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_key_shortcut.h"
+
+struct KisKeyShortcut::Private
+{
+ QList<Qt::Key> modifiers;
+ Qt::Key key;
+ bool useWheel;
+ WheelAction wheelAction;
+};
+
+
+KisKeyShortcut::KisKeyShortcut(KisAbstractInputAction *action, int index)
+ : KisAbstractShortcut(action, index),
+ m_d(new Private)
+{
+}
+
+KisKeyShortcut::~KisKeyShortcut()
+{
+ delete m_d;
+}
+
+int KisKeyShortcut::priority() const
+{
+ return m_d->modifiers.size() * 2 + 1;
+}
+
+void KisKeyShortcut::setKey(const QList<Qt::Key> &modifiers, Qt::Key key)
+{
+ m_d->modifiers = modifiers;
+ m_d->key = key;
+ m_d->useWheel = false;
+}
+
+void KisKeyShortcut::setWheel(const QList<Qt::Key> &modifiers, WheelAction \
wheelAction) +{
+ m_d->modifiers = modifiers;
+ m_d->wheelAction = wheelAction;
+ m_d->useWheel = true;
+}
+
+bool KisKeyShortcut::matchKey(const QList<Qt::Key> &modifiers, Qt::Key key)
+{
+ return !m_d->useWheel && key == m_d->key &&
+ compareKeys(modifiers, m_d->modifiers);
+}
+
+bool KisKeyShortcut::matchKey(const QList<Qt::Key> &modifiers, WheelAction \
wheelAction) +{
+ return m_d->useWheel && wheelAction == m_d->wheelAction &&
+ compareKeys(modifiers, m_d->modifiers);
+}
diff --git a/krita/ui/input/kis_key_shortcut.h b/krita/ui/input/kis_key_shortcut.h
new file mode 100644
index 0000000..fb683c2
--- /dev/null
+++ b/krita/ui/input/kis_key_shortcut.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_KEY_SHORTCUT_H
+#define __KIS_KEY_SHORTCUT_H
+
+#include "kis_abstract_shortcut.h"
+
+/**
+ * This class represents a shortcut that is started with simple
+ * key presses only, that is a simple keyboard hotkey or a mouse
+ * wheel rotation by one delta.
+ */
+
+class KRITAUI_EXPORT KisKeyShortcut : public KisAbstractShortcut
+{
+public:
+ enum WheelAction {
+ WheelUp, ///< Mouse wheel moves up.
+ WheelDown ///< Mouse wheel moves down.
+ };
+
+ KisKeyShortcut(KisAbstractInputAction *action, int index);
+ ~KisKeyShortcut();
+
+ int priority() const;
+
+ void setKey(const QList<Qt::Key> &modifiers, Qt::Key key);
+ void setWheel(const QList<Qt::Key> &modifiers, WheelAction wheelAction);
+
+ bool matchKey(const QList<Qt::Key> &modifiers, Qt::Key key);
+ bool matchKey(const QList<Qt::Key> &modifiers, WheelAction wheelAction);
+
+private:
+ class Private;
+ Private * const m_d;
+};
+
+#endif /* __KIS_KEY_SHORTCUT_H */
diff --git a/krita/ui/input/kis_pan_action.cpp b/krita/ui/input/kis_pan_action.cpp
index fbffb1a..cfb7334 100644
--- a/krita/ui/input/kis_pan_action.cpp
+++ b/krita/ui/input/kis_pan_action.cpp
@@ -33,9 +33,8 @@
class KisPanAction::Private
{
public:
- Private() : active(false), panDistance(10) { }
+ Private() : panDistance(10) { }
- bool active;
const int panDistance;
};
@@ -58,13 +57,22 @@ KisPanAction::~KisPanAction()
delete d;
}
-void KisPanAction::begin(int shortcut)
+void KisPanAction::activate()
{
+ QApplication::setOverrideCursor(Qt::OpenHandCursor);
+}
+
+void KisPanAction::deactivate()
+{
+ QApplication::restoreOverrideCursor();
+}
+
+void KisPanAction::begin(int shortcut, QEvent *event)
+{
+ KisAbstractInputAction::begin(shortcut, event);
+
switch (shortcut) {
case PanToggleShortcut:
- setMousePosition(inputManager()->canvas()->coordinatesConverter()->documentToWidget(inputManager()->mousePosition()));
- QApplication::setOverrideCursor(Qt::OpenHandCursor);
- d->active = true;
break;
case PanLeftShortcut:
inputManager()->canvas()->canvasController()->pan(QPoint(d->panDistance, \
0)); @@ -81,37 +89,8 @@ void KisPanAction::begin(int shortcut)
}
}
-void KisPanAction::end()
-{
- d->active = false;
- QApplication::restoreOverrideCursor();
-}
-
-void KisPanAction::inputEvent(QEvent *event)
-{
- switch (event->type()) {
- case QEvent::MouseButtonPress: {
- setMousePosition(static_cast<QMouseEvent*>(event)->posF());
- break;
- }
- case QEvent::MouseMove: {
- QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
- if (mevent->buttons()) {
- QPointF relMovement = -(mevent->posF() - mousePosition());
- inputManager()->canvas()->canvasController()->pan(relMovement.toPoint());
- setMousePosition(mevent->posF());
- QApplication::changeOverrideCursor(Qt::ClosedHandCursor);
- } else {
- QApplication::changeOverrideCursor(Qt::OpenHandCursor);
- }
- break;
- }
- default:
- break;
- }
-}
-
-bool KisPanAction::isBlockingAutoRepeat() const
+void KisPanAction::mouseMoved(const QPointF &lastPos, const QPointF &pos)
{
- return d->active;
+ QPointF relMovement = -(pos - lastPos);
+ inputManager()->canvas()->canvasController()->pan(relMovement.toPoint());
}
diff --git a/krita/ui/input/kis_pan_action.h b/krita/ui/input/kis_pan_action.h
index e2ed64b..9944271 100644
--- a/krita/ui/input/kis_pan_action.h
+++ b/krita/ui/input/kis_pan_action.h
@@ -43,11 +43,11 @@ public:
explicit KisPanAction(KisInputManager *manager);
virtual ~KisPanAction();
- virtual void begin(int shortcut);
- virtual void end();
- virtual void inputEvent(QEvent* event);
+ void activate();
+ void deactivate();
- virtual bool isBlockingAutoRepeat() const;
+ void begin(int shortcut, QEvent *event);
+ void mouseMoved(const QPointF &lastPos, const QPointF &pos);
private:
class Private;
diff --git a/krita/ui/input/kis_rotate_canvas_action.cpp \
b/krita/ui/input/kis_rotate_canvas_action.cpp index 5c4eaf5..be10feb 100644
--- a/krita/ui/input/kis_rotate_canvas_action.cpp
+++ b/krita/ui/input/kis_rotate_canvas_action.cpp
@@ -19,26 +19,15 @@
#include "kis_rotate_canvas_action.h"
#include <QApplication>
-
#include <KLocalizedString>
#include "kis_canvas_controller.h"
-
#include <kis_canvas2.h>
-#include <kis_image.h>
-
#include "kis_input_manager.h"
-class KisRotateCanvasAction::Private
-{
-public:
- Private() : active(false) { }
-
- bool active;
-};
KisRotateCanvasAction::KisRotateCanvasAction(KisInputManager* manager)
- : KisAbstractInputAction(manager), d(new Private)
+ : KisAbstractInputAction(manager)
{
setName(i18n("Rotate Canvas"));
QHash<QString, int> shortcuts;
@@ -51,19 +40,27 @@ KisRotateCanvasAction::KisRotateCanvasAction(KisInputManager* \
manager)
KisRotateCanvasAction::~KisRotateCanvasAction()
{
- delete d;
}
-void KisRotateCanvasAction::begin(int shortcut)
+void KisRotateCanvasAction::activate()
{
+ QApplication::setOverrideCursor(Qt::OpenHandCursor);
+}
+
+void KisRotateCanvasAction::deactivate()
+{
+ QApplication::restoreOverrideCursor();
+}
+
+void KisRotateCanvasAction::begin(int shortcut, QEvent *event)
+{
+ KisAbstractInputAction::begin(shortcut, event);
+
KisCanvasController *canvasController =
dynamic_cast<KisCanvasController*>(inputManager()->canvas()->canvasController());
switch(shortcut) {
case RotateToggleShortcut:
- setMousePosition(inputManager()->canvas()->coordinatesConverter()->documentToWidget(inputManager()->mousePosition()));
- QApplication::setOverrideCursor(Qt::OpenHandCursor);
- d->active = true;
break;
case RotateLeftShortcut:
canvasController->rotateCanvasLeft15();
@@ -77,48 +74,19 @@ void KisRotateCanvasAction::begin(int shortcut)
}
}
-void KisRotateCanvasAction::end()
+void KisRotateCanvasAction::mouseMoved(const QPointF &lastPos, const QPointF &pos)
{
- d->active = false;
- QApplication::restoreOverrideCursor();
-}
+ const KisCoordinatesConverter *converter = \
inputManager()->canvas()->coordinatesConverter(); + QPointF centerPoint = \
converter->flakeToWidget(converter->flakeCenterPoint()); + QPointF oldPoint = \
lastPos - centerPoint; + QPointF newPoint = pos - centerPoint;
-void KisRotateCanvasAction::inputEvent(QEvent* event)
-{
- switch (event->type()) {
- case QEvent::MouseButtonPress: {
- setMousePosition(static_cast<QMouseEvent*>(event)->posF());
- break;
- }
- case QEvent::MouseMove: {
- QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
- if (mevent->buttons()) {
- const KisCoordinatesConverter *converter = \
inputManager()->canvas()->coordinatesConverter();
- QPointF centerPoint = \
converter->flakeToWidget(converter->flakeCenterPoint());
- QPointF oldPoint = mousePosition() - centerPoint;
- QPointF newPoint = mevent->posF() - centerPoint;
+ qreal oldAngle = atan2(oldPoint.y(), oldPoint.x());
+ qreal newAngle = atan2(newPoint.y(), newPoint.x());
- qreal oldAngle = atan2(oldPoint.y(), oldPoint.x());
- qreal newAngle = atan2(newPoint.y(), newPoint.x());
+ float angle = (180 / M_PI) * (newAngle - oldAngle);
- float angle = (180 / M_PI) * (newAngle - oldAngle);
-
- KisCanvasController *canvasController =
- \
dynamic_cast<KisCanvasController*>(inputManager()->canvas()->canvasController());
- canvasController->rotateCanvas(angle);
-
- setMousePosition(mevent->posF());
- QApplication::changeOverrideCursor(Qt::ClosedHandCursor);
- } else {
- QApplication::changeOverrideCursor(Qt::OpenHandCursor);
- }
- }
- default:
- break;
- }
-}
-
-bool KisRotateCanvasAction::isBlockingAutoRepeat() const
-{
- return d->active;
+ KisCanvasController *canvasController =
+ dynamic_cast<KisCanvasController*>(inputManager()->canvas()->canvasController());
+ canvasController->rotateCanvas(angle);
}
diff --git a/krita/ui/input/kis_rotate_canvas_action.h \
b/krita/ui/input/kis_rotate_canvas_action.h index 0ae2a6b..fdaaa60 100644
--- a/krita/ui/input/kis_rotate_canvas_action.h
+++ b/krita/ui/input/kis_rotate_canvas_action.h
@@ -43,15 +43,10 @@ public:
explicit KisRotateCanvasAction(KisInputManager* manager);
virtual ~KisRotateCanvasAction();
- virtual void begin(int shortcut);
- virtual void end();
- virtual void inputEvent(QEvent* event);
-
- virtual bool isBlockingAutoRepeat() const;
-
-private:
- class Private;
- Private * const d;
+ void activate();
+ void deactivate();
+ void begin(int shortcut, QEvent *event);
+ void mouseMoved(const QPointF &lastPos, const QPointF &pos);
};
#endif // KIS_ROTATE_CANVAS_ACTION_H
diff --git a/krita/ui/input/kis_shortcut.cpp b/krita/ui/input/kis_shortcut.cpp
deleted file mode 100644
index 61a40c1..0000000
--- a/krita/ui/input/kis_shortcut.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/* This file is part of the KDE project
- * Copyright (C) 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "kis_shortcut.h"
-
-#include "kis_abstract_input_action.h"
-#include <QEvent>
-#include <QDebug>
-#include <QKeyEvent>
-
-class KisShortcut::Private
-{
-public:
- Private() : wheelState(WheelUndefined), currentWheelState(WheelUndefined), \
action(0), shortcutIndex(0) { }
- QList<Qt::Key> keys;
- QList<Qt::Key> keyState;
- QList<Qt::MouseButton> buttons;
- QList<Qt::MouseButton> buttonState;
- WheelState wheelState;
- WheelState currentWheelState;
-
- KisAbstractInputAction *action;
- int shortcutIndex;
-};
-
-KisShortcut::KisShortcut() : d(new Private)
-{
-}
-
-KisShortcut::~KisShortcut()
-{
- delete d;
-}
-
-int KisShortcut::priority() const
-{
- return d->keys.count() * 2 + d->buttons.count();
-}
-
-KisAbstractInputAction* KisShortcut::action() const
-{
- return d->action;
-}
-
-void KisShortcut::setAction(KisAbstractInputAction* action)
-{
- d->action = action;
-}
-
-int KisShortcut::shortcutIndex() const
-{
- return d->shortcutIndex;
-}
-
-void KisShortcut::setShortcutIndex(int index)
-{
- d->shortcutIndex = index;
-}
-
-void KisShortcut::setButtons(const QList<Qt::MouseButton> &buttons)
-{
- d->buttons = buttons;
- d->buttonState.clear();
-}
-
-void KisShortcut::setKeys(const QList< Qt::Key >& keys)
-{
- d->keys = keys;
- d->keyState.clear();
-}
-
-void KisShortcut::setWheel(KisShortcut::WheelState state)
-{
- d->wheelState = state;
-}
-
-KisShortcut::MatchLevel KisShortcut::matchLevel()
-{
- if (d->keys.count() == d->keyState.count() && d->buttons.count() == \
d->buttonState.count() && (d->wheelState == WheelUndefined || d->currentWheelState == \
d->wheelState)) {
- return CompleteMatch;
- } else if (d->keyState.count() > 0 || d->buttonState.count() > 0) {
- return PartialMatch;
- }
-
- return NoMatch;
-}
-
-void KisShortcut::match(QEvent* event)
-{
- switch (event->type()) {
- case QEvent::KeyPress: {
- QKeyEvent *kevent = static_cast<QKeyEvent*>(event);
- Qt::Key key = static_cast<Qt::Key>(kevent->key());
- if (d->keys.contains(key) && !d->keyState.contains(key)) {
- d->keyState.append(key);
- }
- break;
- }
- case QEvent::KeyRelease: {
- QKeyEvent *kevent = static_cast<QKeyEvent*>(event);
- Qt::Key key = static_cast<Qt::Key>(kevent->key());
- if (d->keyState.contains(key)) {
- d->keyState.removeOne(key);
- }
- break;
- }
- case QEvent::MouseButtonPress: {
- Qt::MouseButton button = static_cast<QMouseEvent*>(event)->button();
- if (d->buttons.contains(button) && !d->buttonState.contains(button)) {
- d->buttonState.append(button);
- }
- break;
- }
- case QEvent::MouseButtonRelease: {
- Qt::MouseButton button = static_cast<QMouseEvent*>(event)->button();
- if (d->buttonState.contains(button)) {
- d->buttonState.removeOne(button);
- }
- break;
- }
- case QEvent::MouseButtonDblClick: {
- Qt::MouseButton button = static_cast<QMouseEvent*>(event)->button();
- if (d->buttons.contains(button) && !d->buttonState.contains(button)) {
- d->buttonState.append(button);
- }
- break;
- }
- case QEvent::Wheel: {
- QWheelEvent *wevent = static_cast<QWheelEvent*>(event);
- if (wevent->delta() > 0) {
- d->currentWheelState = WheelUp;
- } else {
- d->currentWheelState = WheelDown;
- }
- break;
- }
- default:
- break;
- }
-}
-
-void KisShortcut::clear()
-{
- d->buttonState.clear();
- d->keyState.clear();
- d->currentWheelState = WheelUndefined;
-}
diff --git a/krita/ui/input/kis_shortcut.h b/krita/ui/input/kis_shortcut.h
deleted file mode 100644
index fafc428..0000000
--- a/krita/ui/input/kis_shortcut.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* This file is part of the KDE project
- * Copyright (C) 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KISSHORTCUT_H
-#define KISSHORTCUT_H
-
-#include <Qt>
-#include <QList>
-
-class QEvent;
-class KisAbstractInputAction;
-
-/**
- * \brief A combination of keys and buttons used for matching input.
- *
- * The Shortcut class manages a combination of keys and buttons and
- * the state of those buttons. It can be used to detect whether a certain
- * combination of inputs has been activated.
- */
-class KisShortcut
-{
-
-public:
- /**
- * Describes how well recent input matches this shortcut.
- */
- enum MatchLevel {
- NoMatch, ///< No match at all.
- PartialMatch, ///< It may match, with additional input.
- CompleteMatch ///< Completely matches the input sent.
- };
-
- /**
- * States the mouse wheel can be in.
- */
- enum WheelState {
- WheelUndefined, ///< The state is unknown.
- WheelUp, ///< Mouse wheel moves up.
- WheelDown ///< Mouse wheel moves down.
- };
-
- /**
- * Constructor.
- */
- KisShortcut();
- /**
- * Destructor.
- */
- virtual ~KisShortcut();
-
- /**
- */
- int priority() const;
- /**
- * The action associated with this shortcut.
- */
- KisAbstractInputAction* action() const;
- /**
- * Set the action associated with this shortcut.
- */
- void setAction(KisAbstractInputAction *action);
- /**
- * The index of the shortcut.
- *
- * \see KisAbstractInputAction::begin()
- */
- int shortcutIndex() const;
- /**
- * Set the index of the shortcut.
- */
- void setShortcutIndex(int index);
- /**
- * Set the list of keys used by this shortcut.
- */
- void setKeys(const QList<Qt::Key> &keys);
- /**
- * Set the list of buttons used by this shortcut.
- */
- void setButtons(const QList<Qt::MouseButton> &buttons);
- /**
- * Set the wheel state to use for this shortcut.
- */
- void setWheel(WheelState state);
- /**
- * Returns how well this shortcut matches recent input.
- */
- MatchLevel matchLevel();
- /**
- * Try to match input to the keys and buttons used by
- * this shortcut.
- *
- * \param event An event to match.
- */
- void match(QEvent* event);
- /**
- * Clear all state of this shortcut.
- */
- void clear();
-
-private:
- class Private;
- Private * const d;
-};
-
-#endif // KISSHORTCUT_H
diff --git a/krita/ui/input/kis_shortcut_matcher.cpp \
b/krita/ui/input/kis_shortcut_matcher.cpp new file mode 100644
index 0000000..e0e99c2
--- /dev/null
+++ b/krita/ui/input/kis_shortcut_matcher.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_shortcut_matcher.h"
+
+#include <QMouseEvent>
+#include <QTabletEvent>
+
+#include "kis_abstract_input_action.h"
+#include "kis_stroke_shortcut.h"
+
+
+struct KisShortcutMatcher::Private
+{
+ Private() : suppressAllActions(false) {}
+
+ QList<KisKeyShortcut*> keyShortcuts;
+ QList<KisStrokeShortcut*> strokeShortcuts;
+ QList<KisAbstractInputAction*> actions;
+
+ QList<Qt::Key> keys;
+ QList<Qt::MouseButton> buttons;
+
+ KisStrokeShortcut *runningShortcut;
+ KisStrokeShortcut *readyShortcut;
+ QList<KisStrokeShortcut*> readyShortcuts;
+
+ bool suppressAllActions;
+};
+
+KisShortcutMatcher::KisShortcutMatcher()
+ : m_d(new Private)
+{
+ m_d->runningShortcut = 0;
+ m_d->readyShortcut = 0;
+}
+
+KisShortcutMatcher::~KisShortcutMatcher()
+{
+ qDeleteAll(m_d->keyShortcuts);
+ qDeleteAll(m_d->strokeShortcuts);
+ qDeleteAll(m_d->actions);
+ delete m_d;
+}
+
+void KisShortcutMatcher::addShortcut(KisKeyShortcut *shortcut)
+{
+ m_d->keyShortcuts.append(shortcut);
+}
+
+void KisShortcutMatcher::addShortcut(KisStrokeShortcut *shortcut)
+{
+ m_d->strokeShortcuts.append(shortcut);
+}
+
+void KisShortcutMatcher::addAction(KisAbstractInputAction *action)
+{
+ m_d->actions.append(action);
+}
+
+bool KisShortcutMatcher::keyPressed(Qt::Key key)
+{
+ bool retval = false;
+
+ if (m_d->keys.contains(key)) reset();
+
+ if (!m_d->runningShortcut) {
+ retval = tryRunKeyShortcut(key);
+ }
+
+ m_d->keys.append(key);
+
+ if (!m_d->runningShortcut) {
+ prepareReadyShortcuts();
+ tryActivateReadyShortcut();
+ }
+
+ return retval;
+}
+
+bool KisShortcutMatcher::keyReleased(Qt::Key key)
+{
+ if (!m_d->keys.contains(key)) reset();
+ else m_d->keys.removeOne(key);
+
+ if (!m_d->runningShortcut) {
+ prepareReadyShortcuts();
+ tryActivateReadyShortcut();
+ }
+
+ return false;
+}
+
+bool KisShortcutMatcher::buttonPressed(Qt::MouseButton button, QMouseEvent *event)
+{
+ bool retval = false;
+
+ if (m_d->buttons.contains(button)) reset();
+
+ if (!m_d->runningShortcut) {
+ retval = tryRunReadyShortcut(button, event);
+ }
+
+ m_d->buttons.append(button);
+
+ if (!m_d->runningShortcut) {
+ prepareReadyShortcuts();
+ tryActivateReadyShortcut();
+ }
+
+ return retval;
+}
+
+bool KisShortcutMatcher::buttonReleased(Qt::MouseButton button, QMouseEvent *event)
+{
+ bool retval = false;
+
+ if (m_d->runningShortcut) {
+ retval = tryEndRunningShortcut(button, event);
+ }
+
+ if (!m_d->buttons.contains(button)) reset();
+ else m_d->buttons.removeOne(button);
+
+ if (!m_d->runningShortcut) {
+ prepareReadyShortcuts();
+ tryActivateReadyShortcut();
+ }
+
+ return retval;
+}
+
+bool KisShortcutMatcher::wheelEvent(KisKeyShortcut::WheelAction wheelAction)
+{
+ if (m_d->runningShortcut) return false;
+
+ return tryRunWheelShortcut(wheelAction);
+}
+
+bool KisShortcutMatcher::mouseMoved(QMouseEvent *event)
+{
+ if (!m_d->runningShortcut) return false;
+
+ m_d->runningShortcut->action()->inputEvent(event);
+ return true;
+}
+
+void KisShortcutMatcher::reset()
+{
+ m_d->keys.clear();
+ m_d->buttons.clear();
+}
+
+void KisShortcutMatcher::suppressAllActions(bool value)
+{
+ m_d->suppressAllActions = value;
+}
+
+bool KisShortcutMatcher::tryRunWheelShortcut(KisKeyShortcut::WheelAction \
wheelAction) +{
+ return tryRunKeyShortcutImpl(wheelAction);
+}
+
+bool KisShortcutMatcher::tryRunKeyShortcut(Qt::Key key)
+{
+ return tryRunKeyShortcutImpl(key);
+}
+
+template<typename T>
+bool KisShortcutMatcher::tryRunKeyShortcutImpl(T param)
+{
+ if (m_d->suppressAllActions) return false;
+
+ KisKeyShortcut *goodCandidate = 0;
+
+ foreach(KisKeyShortcut *s, m_d->keyShortcuts) {
+ if(s->matchKey(m_d->keys, param) &&
+ (!goodCandidate || s->priority() > goodCandidate->priority())) {
+
+ goodCandidate = s;
+ }
+ }
+
+ if (goodCandidate) {
+ goodCandidate->action()->begin(goodCandidate->shortcutIndex(), 0);
+ goodCandidate->action()->end(0);
+ }
+
+ return goodCandidate;
+}
+
+void KisShortcutMatcher::prepareReadyShortcuts()
+{
+ m_d->readyShortcuts.clear();
+ if (m_d->suppressAllActions) return;
+
+ foreach(KisStrokeShortcut *s, m_d->strokeShortcuts) {
+ if (s->matchReady(m_d->keys, m_d->buttons)) {
+ m_d->readyShortcuts.append(s);
+ }
+ }
+}
+
+bool KisShortcutMatcher::tryRunReadyShortcut(Qt::MouseButton button, QMouseEvent \
*event) +{
+ KisStrokeShortcut *goodCandidate = 0;
+
+ foreach(KisStrokeShortcut *s, m_d->readyShortcuts) {
+ if (s->matchBegin(button) &&
+ (!goodCandidate || s->priority() > goodCandidate->priority())) {
+
+ goodCandidate = s;
+ }
+ }
+
+ if (goodCandidate) {
+ if (m_d->readyShortcut) {
+ if (m_d->readyShortcut != goodCandidate) {
+ m_d->readyShortcut->action()->deactivate();
+ goodCandidate->action()->activate();
+ }
+ m_d->readyShortcut = 0;
+ } else {
+ goodCandidate->action()->activate();
+ }
+
+ goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event);
+ m_d->runningShortcut = goodCandidate;
+ }
+
+ return goodCandidate;
+}
+
+void KisShortcutMatcher::tryActivateReadyShortcut()
+{
+ KisStrokeShortcut *goodCandidate = 0;
+
+ foreach(KisStrokeShortcut *s, m_d->readyShortcuts) {
+ if (!goodCandidate || s->priority() > goodCandidate->priority()) {
+ goodCandidate = s;
+ }
+ }
+
+ if (goodCandidate) {
+ if (m_d->readyShortcut && m_d->readyShortcut != goodCandidate) {
+ m_d->readyShortcut->action()->deactivate();
+ m_d->readyShortcut = 0;
+ }
+
+ if (!m_d->readyShortcut) {
+ goodCandidate->action()->activate();
+ m_d->readyShortcut = goodCandidate;
+ }
+ } else if (m_d->readyShortcut) {
+ m_d->readyShortcut->action()->deactivate();
+ m_d->readyShortcut = 0;
+ }
+}
+
+bool KisShortcutMatcher::tryEndRunningShortcut(Qt::MouseButton button, QMouseEvent \
*event) +{
+ Q_ASSERT(m_d->runningShortcut);
+ Q_ASSERT(!m_d->readyShortcut);
+
+ if (m_d->runningShortcut->matchBegin(button)) {
+ m_d->runningShortcut->action()->end(event);
+ m_d->runningShortcut->action()->deactivate();
+ m_d->runningShortcut = 0;
+ }
+
+ return !m_d->runningShortcut;
+}
diff --git a/krita/ui/input/kis_shortcut_matcher.h \
b/krita/ui/input/kis_shortcut_matcher.h new file mode 100644
index 0000000..0449a6e
--- /dev/null
+++ b/krita/ui/input/kis_shortcut_matcher.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_SHORTCUT_MATCHER_H
+#define __KIS_SHORTCUT_MATCHER_H
+
+#include "kis_abstract_shortcut.h"
+
+#include <QList>
+#include "kis_key_shortcut.h"
+
+class QMouseEvent;
+class QTabletEvent;
+
+class KisStrokeShortcut;
+class KisAbstractInputAction;
+
+/**
+ * The class that manages connections between shortcuts and actions.
+ *
+ * It processes input events and generates state transitions for the
+ * actions basing on the data, represented by the shortcuts.
+ *
+ * \see KisStrokeShortcut
+ * \see KisKeyShortcut
+ */
+class KRITAUI_EXPORT KisShortcutMatcher
+{
+public:
+ KisShortcutMatcher();
+ ~KisShortcutMatcher();
+
+ void addShortcut(KisKeyShortcut *shortcut);
+ void addShortcut(KisStrokeShortcut *shortcut);
+ void addAction(KisAbstractInputAction *action);
+
+ /**
+ * Handles a key press event.
+ *
+ * \return whether the event has been handled successfully and
+ * should be eaten by the events filter
+ */
+ bool keyPressed(Qt::Key key);
+
+ /**
+ * Handles a key release event.
+ *
+ * \return whether the event has been handled successfully and
+ * should be eaten by the events filter
+ */
+ bool keyReleased(Qt::Key key);
+
+ /**
+ * Handles the mouse button press event
+ *
+ * \param button the button that has been pressed
+ * \param event the event that caused this call
+ *
+ * \return whether the event has been handled successfully and
+ * should be eaten by the events filter
+ */
+ bool buttonPressed(Qt::MouseButton button, QMouseEvent *event);
+
+ /**
+ * Handles the mouse button release event
+ *
+ * \param button the button that has been pressed
+ * \param event the event that caused this call
+ *
+ * \return whether the event has been handled successfully and
+ * should be eaten by the events filter
+ */
+ bool buttonReleased(Qt::MouseButton button, QMouseEvent *event);
+
+ /**
+ * Handles the mouse wheel event
+ *
+ * \return whether the event has been handled successfully and
+ * should be eaten by the events filter
+ */
+ bool wheelEvent(KisKeyShortcut::WheelAction wheelAction);
+
+ /**
+ * Handles the mouse move event
+ *
+ * \param event the event that caused this call
+ *
+ * \return whether the event has been handled successfully and
+ * should be eaten by the events filter
+ */
+ bool mouseMoved(QMouseEvent *event);
+
+ /**
+ * Resets the internal state of the matcher
+ *
+ * This should be done when the window has lost the focus for
+ * some time, so that several events could be lost
+ */
+ void reset();
+
+ /**
+ * Disables the start of any actions.
+ *
+ * WARNING: the actions that has been started before this call
+ * will *not* be ended. They will be ended in their usual way,
+ * when the mouse button will be released.
+ */
+ void suppressAllActions(bool value);
+
+private:
+ friend class KisInputManagerTest;
+
+ bool tryRunKeyShortcut(Qt::Key key);
+ bool tryRunWheelShortcut(KisKeyShortcut::WheelAction wheelAction);
+ template<typename T> bool tryRunKeyShortcutImpl(T param);
+
+ void prepareReadyShortcuts();
+
+ bool tryRunReadyShortcut(Qt::MouseButton button, QMouseEvent *event);
+ void tryActivateReadyShortcut();
+ bool tryEndRunningShortcut(Qt::MouseButton button, QMouseEvent *event);
+
+private:
+ class Private;
+ Private * const m_d;
+};
+
+#endif /* __KIS_SHORTCUT_MATCHER_H */
diff --git a/krita/ui/input/kis_show_palette_action.cpp \
b/krita/ui/input/kis_show_palette_action.cpp index 11913a5..1af939c 100644
--- a/krita/ui/input/kis_show_palette_action.cpp
+++ b/krita/ui/input/kis_show_palette_action.cpp
@@ -36,17 +36,8 @@ KisShowPaletteAction::~KisShowPaletteAction()
}
-void KisShowPaletteAction::begin(int /*shortcut*/)
+void KisShowPaletteAction::begin(int, QEvent *event)
{
- inputManager()->canvas()->favoriteResourceManager()->slotShowPopupPalette(inputMa \
nager()->canvas()->coordinatesConverter()->documentToWidget(inputManager()->mousePosition()).toPoint());
-}
-
-void KisShowPaletteAction::end()
-{
-
-}
-
-void KisShowPaletteAction::inputEvent(QEvent* event)
-{
- Q_UNUSED(event);
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+ inputManager()->canvas()->favoriteResourceManager()->slotShowPopupPalette(mouseEvent->pos());
}
diff --git a/krita/ui/input/kis_show_palette_action.h \
b/krita/ui/input/kis_show_palette_action.h index 2485883..ebafab3 100644
--- a/krita/ui/input/kis_show_palette_action.h
+++ b/krita/ui/input/kis_show_palette_action.h
@@ -32,9 +32,7 @@ public:
explicit KisShowPaletteAction(KisInputManager* manager);
virtual ~KisShowPaletteAction();
- virtual void begin(int /*shortcut*/);
- virtual void end();
- virtual void inputEvent(QEvent* event);
+ virtual void begin(int, QEvent *);
};
#endif // KIS_SHOW_PALETTE_ACTION_H
diff --git a/krita/ui/input/kis_stroke_shortcut.cpp \
b/krita/ui/input/kis_stroke_shortcut.cpp new file mode 100644
index 0000000..091ecaa
--- /dev/null
+++ b/krita/ui/input/kis_stroke_shortcut.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_stroke_shortcut.h"
+
+
+struct KisStrokeShortcut::Private
+{
+ QList<Qt::Key> modifiers;
+ QList<Qt::MouseButton> buttons;
+};
+
+
+KisStrokeShortcut::KisStrokeShortcut(KisAbstractInputAction *action, int index)
+ : KisAbstractShortcut(action, index),
+ m_d(new Private)
+{
+}
+
+KisStrokeShortcut::~KisStrokeShortcut()
+{
+ delete m_d;
+}
+
+int KisStrokeShortcut::priority() const
+{
+ return m_d->modifiers.size() * 2 + m_d->buttons.size();
+}
+
+void KisStrokeShortcut::setButtons(const QList<Qt::Key> &modifiers,
+ const QList<Qt::MouseButton> &buttons)
+{
+ Q_ASSERT(buttons.size() > 0);
+
+ m_d->modifiers = modifiers;
+ m_d->buttons = buttons;
+}
+
+bool KisStrokeShortcut::matchReady(const QList<Qt::Key> &modifiers,
+ const QList<Qt::MouseButton> &buttons)
+{
+ if (!compareKeys(m_d->modifiers, modifiers) ||
+ buttons.size() < m_d->buttons.size() - 1) {
+
+ return false;
+ }
+
+ foreach(Qt::MouseButton button, buttons) {
+ if (!m_d->buttons.contains(button)) return false;
+ }
+ return true;
+}
+
+bool KisStrokeShortcut::matchBegin(Qt::MouseButton button)
+{
+ return m_d->buttons.contains(button);
+}
diff --git a/krita/ui/input/kis_stroke_shortcut.h \
b/krita/ui/input/kis_stroke_shortcut.h new file mode 100644
index 0000000..4743148
--- /dev/null
+++ b/krita/ui/input/kis_stroke_shortcut.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_STROKE_SHORTCUT_H
+#define __KIS_STROKE_SHORTCUT_H
+
+#include "kis_abstract_shortcut.h"
+
+/**
+ * This class represents a shortcut that starts an action that can
+ * involve pressing the mouse button and, probably, moving the cursor.
+ *
+ * The stroke shortcut may be represented as a simple state machine:
+ * It transits between 3 states:
+ *
+ * Idle <-> Ready <-> Running
+ *
+ * The possibility of trasition between Idle <-> Ready is defined
+ * with a matchReady() method. The transition Ready <-> Running is
+ * defined by matchBegin(). The Ready state is used for showing the
+ * user the cursor of the upcoming action and the Running state shows
+ * that the action linked to the shortcut should be activated.
+ */
+
+class KRITAUI_EXPORT KisStrokeShortcut : public KisAbstractShortcut
+{
+public:
+ KisStrokeShortcut(KisAbstractInputAction *action, int index);
+ ~KisStrokeShortcut();
+
+ int priority() const;
+
+ /**
+ * Sets the configuration for this shortcut
+ *
+ * \param modifiers keyboard keys that should be holded
+ * for the shortcut to trigger
+ * \param buttons mouse buttons that should be pressed (simultaneously)
+ * for the shortcut to trigger
+ */
+ void setButtons(const QList<Qt::Key> &modifiers,
+ const QList<Qt::MouseButton> &buttons);
+
+ /**
+ * Reports whether all but one buttons and modifiers are pressed
+ * for the shortcut. Such configuration means that the input manager
+ * can show the user that pressing the mouse button will start some
+ * action. This can be done with, e.g. changing the cursor.
+ */
+
+ bool matchReady(const QList<Qt::Key> &modifiers,
+ const QList<Qt::MouseButton> &buttons);
+ /**
+ * Reports whether the shortcut can transit form the "Ready"
+ * to "Running" state. It means that the last button of the shortcut
+ * is pressed.
+ */
+ bool matchBegin(Qt::MouseButton button);
+
+private:
+ class Private;
+ Private * const m_d;
+};
+
+#endif /* __KIS_STROKE_SHORTCUT_H */
diff --git a/krita/ui/input/kis_tool_invocation_action.cpp \
b/krita/ui/input/kis_tool_invocation_action.cpp index a9b6a41..91cb866 100644
--- a/krita/ui/input/kis_tool_invocation_action.cpp
+++ b/krita/ui/input/kis_tool_invocation_action.cpp
@@ -31,18 +31,11 @@
class KisToolInvocationAction::Private
{
public:
- Private(KisToolInvocationAction *qq) : q(qq), useTablet(false) { }
+ Private(KisToolInvocationAction *qq) : q(qq), active(false) { }
QPointF tabletToPixel(const QPointF& globalPos);
KisToolInvocationAction *q;
-
- bool useTablet;
- QTabletEvent::TabletDevice tabletDevice;
- QTabletEvent::PointerType pointerType;
- int tabletZ;
- qint64 tabletID;
-
- Qt::KeyboardModifiers modifiers;
+ bool active;
};
KisToolInvocationAction::KisToolInvocationAction(KisInputManager *manager)
@@ -57,24 +50,19 @@ KisToolInvocationAction::~KisToolInvocationAction()
delete d;
}
-void KisToolInvocationAction::begin(int shortcut)
+void KisToolInvocationAction::begin(int shortcut, QEvent *event)
{
if (shortcut == ActivateShortcut) {
- if (inputManager()->tabletPressEvent()) {
- QTabletEvent *pressEvent = inputManager()->tabletPressEvent();
- inputManager()->toolProxy()->tabletEvent(pressEvent, \
d->tabletToPixel(pressEvent->hiResGlobalPos()));
- d->useTablet = true;
- d->pointerType = pressEvent->pointerType();
- d->tabletDevice = pressEvent->device();
- d->tabletZ = pressEvent->z();
- d->tabletID = pressEvent->uniqueId();
- setMousePosition(d->tabletToPixel(pressEvent->hiResGlobalPos()));
+ QTabletEvent *tabletEvent = inputManager()->lastTabletEvent();
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
- } else {
- QMouseEvent pressEvent(QEvent::MouseButtonPress, \
inputManager()->mousePosition().toPoint(), Qt::LeftButton, \
Qt::LeftButton, 0);
- inputManager()->toolProxy()->mousePressEvent(&pressEvent, \
inputManager()->mousePosition());
- setMousePosition(inputManager()->mousePosition());
+ if (tabletEvent) {
+ inputManager()->toolProxy()->tabletEvent(tabletEvent, \
d->tabletToPixel(tabletEvent->hiResGlobalPos())); + } else if (mouseEvent) {
+ inputManager()->toolProxy()->mousePressEvent(mouseEvent, \
inputManager()->widgetToPixel(mouseEvent->posF())); }
+
+ d->active = true;
} else {
QKeyEvent pressEvent(QEvent::KeyPress, Qt::Key_Return, 0);
inputManager()->toolProxy()->keyPressEvent(&pressEvent);
@@ -83,40 +71,40 @@ void KisToolInvocationAction::begin(int shortcut)
}
}
-void KisToolInvocationAction::end()
+void KisToolInvocationAction::end(QEvent *event)
{
- if(d->useTablet) {
- QTabletEvent releaseEvent(QEvent::TabletRelease, mousePosition().toPoint(), \
mousePosition().toPoint(), mousePosition(), d->tabletDevice, d->pointerType, 0.f, 0, \
0, 0.f, 0.f, d->tabletZ, d->modifiers, d->tabletID);
- inputManager()->toolProxy()->tabletEvent(&releaseEvent, mousePosition());
- d->useTablet = false;
- } else {
- QMouseEvent releaseEvent(QEvent::MouseButtonRelease, \
mousePosition().toPoint(), Qt::LeftButton, Qt::LeftButton, \
d->modifiers);
- inputManager()->toolProxy()->mouseReleaseEvent(&releaseEvent, \
mousePosition()); + if (d->active) {
+ QTabletEvent *tabletEvent = inputManager()->lastTabletEvent();
+ QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
+
+ if (tabletEvent) {
+ inputManager()->toolProxy()->tabletEvent(tabletEvent, \
d->tabletToPixel(tabletEvent->hiResGlobalPos())); + } else {
+ inputManager()->toolProxy()->mouseReleaseEvent(mouseEvent, \
inputManager()->widgetToPixel(mouseEvent->posF())); + }
+
+ d->active = false;
}
+
+ KisAbstractInputAction::end(event);
}
void KisToolInvocationAction::inputEvent(QEvent* event)
{
if(event->type() == QEvent::MouseButtonPress) {
QMouseEvent* mevent = static_cast<QMouseEvent*>(event);
- setMousePosition(inputManager()->widgetToPixel(mevent->posF()));
- d->modifiers = mevent->modifiers();
- inputManager()->toolProxy()->mousePressEvent(mevent, mousePosition());
+ inputManager()->toolProxy()->mousePressEvent(mevent, \
inputManager()->widgetToPixel(mevent->posF())); } else if(event->type() == \
QEvent::MouseButtonRelease) { QMouseEvent* mevent = \
static_cast<QMouseEvent*>(event);
- setMousePosition(inputManager()->widgetToPixel(mevent->posF()));
- d->modifiers = mevent->modifiers();
- inputManager()->toolProxy()->mouseReleaseEvent(mevent, mousePosition());
+ inputManager()->toolProxy()->mouseReleaseEvent(mevent, \
inputManager()->widgetToPixel(mevent->posF())); } else if(event->type() == \
QEvent::MouseMove) { + QTabletEvent* tevent = \
inputManager()->lastTabletEvent(); QMouseEvent* mevent = \
static_cast<QMouseEvent*>(event);
- setMousePosition(inputManager()->widgetToPixel(mevent->posF()));
- d->modifiers = mevent->modifiers();
- inputManager()->toolProxy()->mouseMoveEvent(mevent, mousePosition());
- } else if(event->type() == QEvent::TabletMove) {
- QTabletEvent* tevent = static_cast<QTabletEvent*>(event);
- setMousePosition(d->tabletToPixel(tevent->hiResGlobalPos()));
- d->modifiers = tevent->modifiers();
- inputManager()->toolProxy()->tabletEvent(tevent, mousePosition());
+ if (tevent && tevent->type() == QEvent::TabletMove) {
+ inputManager()->toolProxy()->tabletEvent(tevent, \
d->tabletToPixel(tevent->hiResGlobalPos())); + } else {
+ inputManager()->toolProxy()->mouseMoveEvent(mevent, \
inputManager()->widgetToPixel(mevent->posF())); + }
} else if(event->type() == QEvent::KeyPress) {
QKeyEvent* kevent = static_cast<QKeyEvent*>(event);
inputManager()->toolProxy()->keyPressEvent(kevent);
@@ -126,11 +114,6 @@ void KisToolInvocationAction::inputEvent(QEvent* event)
}
}
-bool KisToolInvocationAction::handleTablet() const
-{
- return true;
-}
-
QPointF KisToolInvocationAction::Private::tabletToPixel(const QPointF &globalPos)
{
const QPointF pos = globalPos - \
q->inputManager()->canvas()->canvasWidget()->mapToGlobal(QPoint(0, \
0));
diff --git a/krita/ui/input/kis_tool_invocation_action.h \
b/krita/ui/input/kis_tool_invocation_action.h index e44a114..a06a003 100644
--- a/krita/ui/input/kis_tool_invocation_action.h
+++ b/krita/ui/input/kis_tool_invocation_action.h
@@ -37,11 +37,9 @@ public:
explicit KisToolInvocationAction(KisInputManager *manager);
virtual ~KisToolInvocationAction();
- virtual void begin(int shortcut);
- virtual void end();
- virtual void inputEvent(QEvent* event);
-
- virtual bool handleTablet() const;
+ void begin(int shortcut, QEvent *event);
+ void end(QEvent *event);
+ void inputEvent(QEvent* event);
private:
class Private;
diff --git a/krita/ui/input/kis_zoom_action.cpp b/krita/ui/input/kis_zoom_action.cpp
index 394c079..82c42a3 100644
--- a/krita/ui/input/kis_zoom_action.cpp
+++ b/krita/ui/input/kis_zoom_action.cpp
@@ -28,16 +28,9 @@
#include <KoCanvasController.h>
#include <KoZoomController.h>
-class KisZoomAction::Private
-{
-public:
- Private() : active(false) { }
-
- bool active;
-};
KisZoomAction::KisZoomAction(KisInputManager* manager)
- : KisAbstractInputAction(manager), d(new Private)
+ : KisAbstractInputAction(manager)
{
setName(i18n("Zoom Canvas"));
@@ -53,17 +46,24 @@ KisZoomAction::KisZoomAction(KisInputManager* manager)
KisZoomAction::~KisZoomAction()
{
- delete d;
}
-void KisZoomAction::begin(int shortcut)
+void KisZoomAction::activate()
+{
+ QApplication::setOverrideCursor(Qt::OpenHandCursor);
+}
+
+void KisZoomAction::deactivate()
+{
+ QApplication::restoreOverrideCursor();
+}
+
+void KisZoomAction::begin(int shortcut, QEvent *event)
{
- switch(shortcut)
- {
+ KisAbstractInputAction::begin(shortcut, event);
+
+ switch(shortcut) {
case ZoomToggleShortcut:
- setMousePosition(inputManager()->canvas()->coordinatesConverter()->documentToWidget(inputManager()->mousePosition()));
- QApplication::setOverrideCursor(Qt::OpenHandCursor);
- d->active = true;
break;
case ZoomInShortcut: {
float zoom = \
inputManager()->canvas()->view()->zoomController()->zoomAction()->effectiveZoom(); @@ \
-105,38 +105,10 @@ void KisZoomAction::begin(int shortcut) }
}
-void KisZoomAction::end()
-{
- d->active = false;
- QApplication::restoreOverrideCursor();
-}
-
-void KisZoomAction::inputEvent(QEvent* event)
+void KisZoomAction::mouseMoved(const QPointF &lastPos, const QPointF &pos)
{
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- setMousePosition(static_cast<QMouseEvent*>(event)->posF());
- break;
- case QEvent::MouseMove: {
- QMouseEvent *mevent = static_cast<QMouseEvent*>(event);
- if(mevent->buttons()) {
- QPointF relMovement = -(mevent->posF() - mousePosition());
-
- float zoom = \
inputManager()->canvas()->view()->zoomController()->zoomAction()->effectiveZoom() + \
relMovement.y() / 100;
- inputManager()->canvas()->view()->zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, \
zoom);
-
- setMousePosition(mevent->posF());
- QApplication::changeOverrideCursor(Qt::ClosedHandCursor);
- } else {
- QApplication::changeOverrideCursor(Qt::OpenHandCursor);
- }
- }
- default:
- break;
- }
-}
+ QPointF relMovement = -(pos - lastPos);
-bool KisZoomAction::isBlockingAutoRepeat() const
-{
- return d->active;
+ float zoom = inputManager()->canvas()->view()->zoomController()->zoomAction()->effectiveZoom() \
+ relMovement.y() / 100; + \
inputManager()->canvas()->view()->zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, \
zoom); }
diff --git a/krita/ui/input/kis_zoom_action.h b/krita/ui/input/kis_zoom_action.h
index 8c37fcc..be09310 100644
--- a/krita/ui/input/kis_zoom_action.h
+++ b/krita/ui/input/kis_zoom_action.h
@@ -43,15 +43,11 @@ public:
explicit KisZoomAction(KisInputManager* manager);
virtual ~KisZoomAction();
- virtual void begin(int shortcut);
- virtual void end();
- virtual void inputEvent(QEvent* event);
+ void activate();
+ void deactivate();
- virtual bool isBlockingAutoRepeat() const;
-
-private:
- class Private;
- Private * const d;
+ void begin(int shortcut, QEvent *event = 0);
+ void mouseMoved(const QPointF &lastPos, const QPointF &pos);
};
#endif // KIS_ZOOM_ACTION_H
diff --git a/krita/ui/tests/CMakeLists.txt b/krita/ui/tests/CMakeLists.txt
index e8f1c21..a7499fe 100644
--- a/krita/ui/tests/CMakeLists.txt
+++ b/krita/ui/tests/CMakeLists.txt
@@ -150,3 +150,9 @@ target_link_libraries(KisModelIndexConverterTest \
${KDE4_KDEUI_LIBS} kritaui kr set(kis_zoom_and_pan_test_SRCS \
kis_zoom_and_pan_test.cpp ../../sdk/tests/testutil.cpp) \
kde4_add_unit_test(KisZoomAndPanTest TESTNAME krita-ui-KisZoomAndPanTest \
${kis_zoom_and_pan_test_SRCS}) target_link_libraries(KisZoomAndPanTest \
${KDE4_KDEUI_LIBS} kritaui kritaimage ${QT_QTTEST_LIBRARY}) +
+########### next target ###############
+
+set(kis_input_manager_test_SRCS kis_input_manager_test.cpp \
../../sdk/tests/testutil.cpp) +kde4_add_unit_test(KisInputManagerTest TESTNAME \
krita-ui-KisInputManagerTest ${kis_input_manager_test_SRCS}) \
+target_link_libraries(KisInputManagerTest ${KDE4_KDEUI_LIBS} kritaui kritaimage \
${QT_QTTEST_LIBRARY})
diff --git a/krita/ui/tests/kis_input_manager_test.cpp \
b/krita/ui/tests/kis_input_manager_test.cpp new file mode 100644
index 0000000..aab8f61
--- /dev/null
+++ b/krita/ui/tests/kis_input_manager_test.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_input_manager_test.h"
+
+#include <qtest_kde.h>
+
+#include <QMouseEvent>
+
+#include "input/kis_key_shortcut.h"
+#include "input/kis_stroke_shortcut.h"
+#include "input/kis_abstract_input_action.h"
+#include "input/kis_shortcut_matcher.h"
+
+
+void KisInputManagerTest::testKeyShortcut()
+{
+ KisKeyShortcut s(0,0);
+ s.setKey(QList<Qt::Key>() << Qt::Key_Shift, Qt::Key_Space);
+
+ QVERIFY(s.matchKey(QList<Qt::Key>() << Qt::Key_Shift, Qt::Key_Space));
+ QVERIFY(!s.matchKey(QList<Qt::Key>() << Qt::Key_Control, Qt::Key_Space));
+ QVERIFY(!s.matchKey(QList<Qt::Key>(), Qt::Key_Space));
+ QVERIFY(!s.matchKey(QList<Qt::Key>() << Qt::Key_Shift, Qt::Key_Escape));
+ QVERIFY(!s.matchKey(QList<Qt::Key>() << Qt::Key_Shift, \
KisKeyShortcut::WheelUp)); +
+ s.setWheel(QList<Qt::Key>() << Qt::Key_Shift, KisKeyShortcut::WheelUp);
+
+ QVERIFY(!s.matchKey(QList<Qt::Key>() << Qt::Key_Shift, Qt::Key_Space));
+ QVERIFY(!s.matchKey(QList<Qt::Key>() << Qt::Key_Control, Qt::Key_Space));
+ QVERIFY(!s.matchKey(QList<Qt::Key>(), Qt::Key_Space));
+ QVERIFY(!s.matchKey(QList<Qt::Key>() << Qt::Key_Shift, Qt::Key_Escape));
+ QVERIFY(s.matchKey(QList<Qt::Key>() << Qt::Key_Shift, KisKeyShortcut::WheelUp));
+}
+
+void KisInputManagerTest::testStrokeShortcut()
+{
+ KisStrokeShortcut s(0,0);
+ s.setButtons(QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ QList<Qt::MouseButton>() << Qt::LeftButton);
+
+ QVERIFY(s.matchReady(QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ QList<Qt::MouseButton>() << Qt::LeftButton));
+
+ QVERIFY(s.matchReady(QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ QList<Qt::MouseButton>()));
+
+ QVERIFY(!s.matchReady(QList<Qt::Key>() << Qt::Key_Control << Qt::Key_Alt,
+ QList<Qt::MouseButton>()));
+
+ QVERIFY(!s.matchReady(QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ QList<Qt::MouseButton>() << Qt::RightButton));
+
+ QVERIFY(s.matchBegin(Qt::LeftButton));
+ QVERIFY(!s.matchBegin(Qt::RightButton));
+}
+
+struct TestingAction : public KisAbstractInputAction
+{
+ TestingAction() : KisAbstractInputAction(0) { reset(); }
+ ~TestingAction() {}
+
+ void begin(int shortcut, QEvent *event) { m_beginIndex = shortcut; \
m_beginNonNull = event;} + void end(QEvent *event) { m_ended = true; m_endNonNull \
= event; } + void inputEvent(QEvent* event) { Q_UNUSED(event); m_gotInput = true; \
} +
+ void reset() {
+ m_beginIndex = -1;
+ m_ended = false;
+ m_gotInput = false;
+ m_beginNonNull = false;
+ m_endNonNull = false;
+ }
+
+
+ int m_beginIndex;
+ bool m_ended;
+ bool m_gotInput;
+ bool m_beginNonNull;
+ bool m_endNonNull;
+};
+
+KisKeyShortcut* createKeyShortcut(KisAbstractInputAction *action,
+ int shortcutIndex,
+ const QList<Qt::Key> &modifiers,
+ Qt::Key key)
+{
+ KisKeyShortcut *s = new KisKeyShortcut(action, shortcutIndex);
+ s->setKey(modifiers, key);
+ return s;
+}
+
+KisStrokeShortcut* createStrokeShortcut(KisAbstractInputAction *action,
+ int shortcutIndex,
+ const QList<Qt::Key> &modifiers,
+ Qt::MouseButton button)
+{
+ KisStrokeShortcut *s = new KisStrokeShortcut(action, shortcutIndex);
+ s->setButtons(modifiers, QList<Qt::MouseButton>() << button);
+ return s;
+}
+
+void KisInputManagerTest::testKeyEvents()
+{
+ KisShortcutMatcher m;
+
+ TestingAction *a = new TestingAction();
+ m.addAction(a);
+
+
+ m.addShortcut(
+ createKeyShortcut(a, 10,
+ QList<Qt::Key>() << Qt::Key_Shift,
+ Qt::Key_Enter));
+
+ m.addShortcut(
+ createKeyShortcut(a, 11,
+ QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ Qt::Key_Enter));
+
+ m.addShortcut(
+ createStrokeShortcut(a, 12,
+ QList<Qt::Key>() << Qt::Key_Shift,
+ Qt::RightButton));
+
+ m.addShortcut(
+ createStrokeShortcut(a, 13,
+ QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ Qt::LeftButton));
+
+ QCOMPARE(a->m_beginIndex, -1);
+
+ // Test event with random values
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPoint(),
+ Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
+
+ // Press Ctrl+Shift
+ QVERIFY(!m.keyPressed(Qt::Key_Shift));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ QVERIFY(!m.keyPressed(Qt::Key_Control));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // Complete Ctrl+Shift+Enter shortcut
+ QVERIFY(m.keyPressed(Qt::Key_Enter));
+ QCOMPARE(a->m_beginIndex, 11);
+ QCOMPARE(a->m_ended, true);
+ QCOMPARE(a->m_beginNonNull, false);
+ QCOMPARE(a->m_endNonNull, false);
+ a->reset();
+
+
+ // Pressing mouse buttons is disabled since Enter is pressed
+ QVERIFY(!m.buttonPressed(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+ QVERIFY(!m.buttonReleased(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // Release Enter, so the system should be ready for new shortcuts
+ QVERIFY(!m.keyReleased(Qt::Key_Enter));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // Complete Ctrl+Shift+LB shortcut
+ QVERIFY(m.buttonPressed(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, 13);
+ QCOMPARE(a->m_ended, false);
+ QCOMPARE(a->m_beginNonNull, true);
+ QCOMPARE(a->m_endNonNull, false);
+ a->reset();
+
+ QVERIFY(m.buttonReleased(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, true);
+ QCOMPARE(a->m_beginNonNull, false);
+ QCOMPARE(a->m_endNonNull, true);
+ a->reset();
+
+
+ // There is no Ctrl+Shift+RB shortcut
+ QVERIFY(!m.buttonPressed(Qt::RightButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ QVERIFY(!m.buttonReleased(Qt::RightButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // Check that Ctrl+Shift+Enter is still enabled
+ QVERIFY(m.keyPressed(Qt::Key_Enter));
+ QCOMPARE(a->m_beginIndex, 11);
+ QCOMPARE(a->m_ended, true);
+ QCOMPARE(a->m_beginNonNull, false);
+ QCOMPARE(a->m_endNonNull, false);
+ a->reset();
+
+ QVERIFY(!m.keyReleased(Qt::Key_Enter));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // Release Ctrl
+ QVERIFY(!m.keyReleased(Qt::Key_Control));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // There is no Shift+LB shortcut
+ QVERIFY(!m.buttonPressed(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ QVERIFY(!m.buttonReleased(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+
+
+ // But there *is* Shift+RB shortcut
+ QVERIFY(m.buttonPressed(Qt::RightButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, 12);
+ QCOMPARE(a->m_ended, false);
+ QCOMPARE(a->m_beginNonNull, true);
+ QCOMPARE(a->m_endNonNull, false);
+ a->reset();
+
+ QVERIFY(m.buttonReleased(Qt::RightButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, true);
+ QCOMPARE(a->m_beginNonNull, false);
+ QCOMPARE(a->m_endNonNull, true);
+ a->reset();
+
+
+ // Check that Shift+Enter still works
+ QVERIFY(m.keyPressed(Qt::Key_Enter));
+ QCOMPARE(a->m_beginIndex, 10);
+ QCOMPARE(a->m_ended, true);
+ QCOMPARE(a->m_beginNonNull, false);
+ QCOMPARE(a->m_endNonNull, false);
+ a->reset();
+}
+
+void KisInputManagerTest::testReleaseUnnecessaryModifiers()
+{
+ KisShortcutMatcher m;
+
+ TestingAction *a = new TestingAction();
+ m.addAction(a);
+
+ m.addShortcut(
+ createStrokeShortcut(a, 13,
+ QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ Qt::LeftButton));
+
+ // Test event with random values
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPoint(),
+ Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
+
+ // Press Ctrl+Shift
+ QVERIFY(!m.keyPressed(Qt::Key_Shift));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ QVERIFY(!m.keyPressed(Qt::Key_Control));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ // Complete Ctrl+Shift+LB shortcut
+ QVERIFY(m.buttonPressed(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, 13);
+ QCOMPARE(a->m_ended, false);
+ a->reset();
+
+ // Release Ctrl
+ QVERIFY(!m.keyReleased(Qt::Key_Control));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, false);
+
+ // Release Shift
+ QVERIFY(!m.keyReleased(Qt::Key_Shift));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, false);
+
+ // Release LB, now it should end
+ QVERIFY(m.buttonReleased(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, true);
+ a->reset();
+}
+
+void KisInputManagerTest::testMouseMoves()
+{
+ KisShortcutMatcher m;
+
+ TestingAction *a = new TestingAction();
+ m.addAction(a);
+
+ m.addShortcut(
+ createStrokeShortcut(a, 13,
+ QList<Qt::Key>() << Qt::Key_Shift << Qt::Key_Control,
+ Qt::LeftButton));
+
+ // Test event with random values
+ QMouseEvent mouseEvent(QEvent::MouseMove, QPoint(),
+ Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
+
+
+ // Press Ctrl+Shift
+ QVERIFY(!m.keyPressed(Qt::Key_Shift));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ QVERIFY(!m.keyPressed(Qt::Key_Control));
+ QCOMPARE(a->m_beginIndex, -1);
+
+ QVERIFY(!m.mouseMoved(&mouseEvent));
+ QCOMPARE(a->m_gotInput, false);
+
+ // Complete Ctrl+Shift+LB shortcut
+ QVERIFY(m.buttonPressed(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, 13);
+ QCOMPARE(a->m_ended, false);
+ QCOMPARE(a->m_gotInput, false);
+ a->reset();
+
+ QVERIFY(m.mouseMoved(&mouseEvent));
+ QCOMPARE(a->m_gotInput, true);
+ a->reset();
+
+ // Release Ctrl
+ QVERIFY(!m.keyReleased(Qt::Key_Control));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, false);
+ QCOMPARE(a->m_gotInput, false);
+
+ // Release Shift
+ QVERIFY(!m.keyReleased(Qt::Key_Shift));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, false);
+
+ // Release LB, now it should end
+ QVERIFY(m.buttonReleased(Qt::LeftButton, &mouseEvent));
+ QCOMPARE(a->m_beginIndex, -1);
+ QCOMPARE(a->m_ended, true);
+ a->reset();
+}
+
+QTEST_KDEMAIN(KisInputManagerTest, GUI)
diff --git a/krita/ui/input/kis_show_palette_action.h \
b/krita/ui/tests/kis_input_manager_test.h similarity index 53%
copy from krita/ui/input/kis_show_palette_action.h
copy to krita/ui/tests/kis_input_manager_test.h
index 2485883..1fb8eab 100644
--- a/krita/ui/input/kis_show_palette_action.h
+++ b/krita/ui/tests/kis_input_manager_test.h
@@ -1,5 +1,5 @@
-/* This file is part of the KDE project
- * Copyright (C) 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
+/*
+ * Copyright (c) 2012 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,25 +16,20 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef KIS_SHOW_PALETTE_ACTION_H
-#define KIS_SHOW_PALETTE_ACTION_H
+#ifndef __KIS_INPUT_MANAGER_TEST_H
+#define __KIS_INPUT_MANAGER_TEST_H
-#include "kis_abstract_input_action.h"
+#include <QtTest/QtTest>
-/**
- * \brief Show Palette implementation of KisAbstractInputAction.
- *
- * The Show Palette action shows the popup palette.
- */
-class KisShowPaletteAction : public KisAbstractInputAction
+class KisInputManagerTest : public QObject
{
-public:
- explicit KisShowPaletteAction(KisInputManager* manager);
- virtual ~KisShowPaletteAction();
-
- virtual void begin(int /*shortcut*/);
- virtual void end();
- virtual void inputEvent(QEvent* event);
+ Q_OBJECT
+private slots:
+ void testKeyShortcut();
+ void testStrokeShortcut();
+ void testKeyEvents();
+ void testReleaseUnnecessaryModifiers();
+ void testMouseMoves();
};
-#endif // KIS_SHOW_PALETTE_ACTION_H
+#endif /* __KIS_INPUT_MANAGER_TEST_H */
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic