1 /*
2     Copyright (C) 2005-2008 Remon Sijrier
3 
4     This file is part of Traverso
5 
6     Traverso is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
19 
20 */
21 
22 #ifndef INPUTENGINE_H
23 #define INPUTENGINE_H
24 
25 
26 #include <QKeyEvent>
27 #include <QWheelEvent>
28 #include <QString>
29 #include <QObject>
30 #include <QTimer>
31 #include <QHash>
32 #include <QStringList>
33 
34 
35 class ContextItem;
36 class Command;
37 class CommandPlugin;
38 
39 static const int FKEY = 0;                 // <K>    - press one key fast
40 static const int FKEY2 = 1;                // <KK>   - press two keys fast, together
41 static const int HOLDKEY = 2;                 // [K]    - Hold one key
42 static const int HKEY2 = 3;                // [KK]   - Hold two keys, together
43 static const int D_FKEY = 4;               // <<K>>  - double press one key fast
44 static const int D_FKEY2 = 5;              // <<KK>> - double press two keys fast, together
45 static const int FHKEY = 6;                // <[K]>  - press fast and then hold one key
46 static const int FHKEY2 = 7;               // <[KK]> - press fast and then hold two keys together
47 static const int S_FKEY_FKEY = 8;          // >K>K   - press one key and then other key fast and sequentially
48 static const int S_FKEY_FKEY2 = 9;         // >K>KK  - press one key and then two other keys fast and sequentially
49 static const int S_FKEY2_FKEY = 10;        // >KK>K  - press two keys and then another one fast and sequentially
50 static const int S_FKEY2_FKEY2 = 11;       // >KK>KK  - press two keys and then another one fast and sequentially
51 static const int S_FKEY_HKEY = 12;         // >K[K]  - press fastly one key and then hold another key, sequentially
52 static const int S_FKEY_HKEY2 = 13;        // >K[KK] - press fastly one key and then hold two ther ones, sequentially
53 static const int S_FKEY2_HKEY = 14;        // >KK[K] - press two keys together fastly and then hold a third one, sequentially
54 static const int S_FKEY2_HKEY2 = 15;       // >KK[KK] - press two keys together fastly and then hold a third one, sequentially
55 
56 // internal class used for qt event catching
57 class EventCatcher : public QObject
58 {
59         Q_OBJECT
60 public:
61         EventCatcher();
62 
63         QTimer holdTimer;
64         QTimer clearOutputTimer;
65         QTimer secondChanceTimer;
66 
67 public slots:
68         void assume_hold();
69         void quit_second_chance();
70         void clear_output();
71 };
72 
73 
74 
75 struct IEAction
76 {
77         void render_key_sequence(const QString& key1, const QString& key2);
78 	~IEAction();
79         struct Data {
80         	QStringList modes;
81 		QVariantList arguments;
82 		QList<int > modifierkeys;
83         	QString slotsignature;
84 		QString pluginname;
85 		QString commandname;
86 		QString submenu;
87 		bool useX;
88 		bool useY;
89 		int sortorder;
90 	};
91 
92         QHash<QString, Data*> objects;
93 	QHash<QString, Data*> objectUsingModifierKeys;
94 
95         int type;
96         int fact1_key1;
97         int fact1_key2;
98         int fact2_key1;
99         int fact2_key2;
100         bool isInstantaneous;
101         QByteArray keySequence;
102 };
103 
104 
105 struct MenuData {
smallerMenuData106         static bool smaller(const MenuData left, const MenuData right )
107         {
108                 return left.sortorder < right.sortorder;
109         }
greaterMenuData110         static bool greater(const MenuData* left, const MenuData* right )
111         {
112                 return left->sortorder > right->sortorder;
113         }
114 	QString 	keysequence;
115 	QString		iedata;
116         QString		description;
117 	QString		submenu;
118         int		sortorder;
119 	QList<int > 	modifierkeys;
120 };
121 
122 class InputEngine : public QObject
123 {
124 	Q_OBJECT
125 public:
126 
127         void catch_key_press(QKeyEvent *);
128         void catch_key_release(QKeyEvent *);
129         void catch_mousebutton_press( QMouseEvent * e );
130         void catch_mousebutton_release( QMouseEvent * e );
131         void catch_mousebutton_doubleclick( QMouseEvent * e );
132         void catch_scroll(QWheelEvent * e );
133 
134         int collected_number();
135 
136 	bool is_jogging();
137 	bool is_holding();
138 
139 	QList<MenuData > create_menudata_for(QObject* item);
140 	Command* get_holding_command() const;
141 	void create_menudata_for_metaobject(const QMetaObject* mo, QList<MenuData >& list) const;
142 
143         int broadcast_action_from_contextmenu(const QString& name);
144 
145         void jog();
146 	void bypass_jog_until_mouse_movements_exceeded_manhattenlength(int length=35);
147 
148         void activate();
149         void suspend();
150 	void clear_modifier_keys();
151 
152 	Command* succes();
153 	Command* failure();
154 	Command* did_not_implement();
155 
156 
157         int init_map(const QString& mapFilename);
158 
159         void set_clear_time(int time);
160         void set_hold_sensitiveness(int factor);
161         void set_double_fact_interval(int time);
162 
163         void register_command_plugin(CommandPlugin* plugin, const QString& pluginName);
164 
165 
166 private:
167         InputEngine();
InputEngine(const InputEngine &)168         InputEngine(const InputEngine&) : QObject() {}
169         ~InputEngine();
170 
171         static const int 	STACK_SIZE = 4;
172         static const int 	MAX_ACTIONS = 300;
173         static const int 	PRESS_EVENT = 1;
174         static const int 	RELEASE_EVENT = 2;
175 
176 	enum BroadcastResult {
177 		SUCCES=1,
178 		FAILURE=2,
179 		DIDNOTIMPLEMENT=3
180 	};
181 
182 
183         QList<IEAction* >	m_ieActions;
184 	QList<int>		m_modifierKeys;
185 	QList<int>		m_activeModifierKeys;
186 	QHash<QString, CommandPlugin*> m_commandplugins;
187 	QHash<QString, int>	m_modes;
188         EventCatcher 		catcher;
189         Command* 		holdingCommand;
190         QString			sCollectedNumber;
191 	QPoint			m_jogBypassPos;
192 
193 
194         bool 			active;
195         bool 			isHolding;
196         bool 			isPressEventLocked;
197         bool 			isHoldingOutput;
198         bool 			isFirstFact;
199         bool 			isDoubleKey;
200         bool 			isJogging;
201 	bool			m_cancelHold;
202 	bool			m_bypassJog;
203 
204         int 			fact1_k1;
205         int 			fact1_k2;
206         int 			fact2_k1;
207         int 			fact2_k2;
208         int 			fact1Type;
209         int 			wholeMapIndex;
210         int 			wholeActionType;
211         int 			collectedNumber;
212         int 			stackIndex;
213         int 			eventType[STACK_SIZE];
214         int 			eventStack[STACK_SIZE];
215         int 			pressEventCounter; // that avoid more than 2 press events in a same fact
216         int 			pairOf2;
217         int 			pairOf3;
218         int 			clearTime;
219         int 			assumeHoldTime;
220         int 			doubleFactWaitTime;
221         long 			eventTime[STACK_SIZE];
222 	int			m_broadcastResult;
223 	int			m_unbypassJogDistance;
224 
225         bool 			is_fake( int keyval);
226         int 			identify_first_fact();
227         int 			identify_first_and_second_facts_together();
228         void 			push_event(int pType,  int pKey);
229         void 			press_checker();
230         void 			release_checker();
231         void 			push_fact( int k1 ,  int k2);
232         void 			give_a_chance_for_second_fact();
233         void 			dispatch_action(int mapIndex);
234         void 			dispatch_hold();
235         void 			finish_hold();
236         void 			conclusion();
237         void 			hold_output();
238         void 			stop_collecting();
239         bool 			check_number_collection(int eventcode);
240 
241         //! call the slot that handler a given action
242         int broadcast_action(IEAction* action, bool autorepeat=false, bool fromContextMenu=false);
243 
244         void set_jogging(bool jog);
245 	void reset();
246 	void process_press_event(int eventcode, bool isAutoRepeat=false);
247         void process_release_event(int eventcode);
248 	int find_index_for_instant_fkey( int key );
249 	int find_index_for_instant_fkey2( int key1, int key2 );
250         int find_index_for_single_fact(int type, int key1, int key2);
251 	bool is_modifier_keyfact(int eventcode);
252 
253 	int holdEventCode;
254 
255         friend class EventCatcher;
256 
257         // allow this function to create one instance
258         friend InputEngine& ie();
259 };
260 
261 // use this function to get the InputEngine object
262 InputEngine& ie();
263 
264 
265 #endif
266 
267 //eof
268