Radium Engine  1.5.20
Loading...
Searching...
No Matches
KeyMappingManager.hpp
1#pragma once
2
3#include <QXmlStreamWriter>
4#include <QtGui/QKeyEvent>
5#include <QtGui/QMouseEvent>
6#include <QtXml/QtXml>
7
8#include <Gui/RaGui.hpp>
9
10#include <Core/Utils/Index.hpp>
11#include <Core/Utils/Log.hpp>
12#include <Core/Utils/Observable.hpp>
13#include <Core/Utils/Singleton.hpp>
14#include <Core/Utils/StdOptional.hpp>
15
16namespace Ra {
17namespace Gui {
22class RA_GUI_API KeyMappingManager : public Ra::Core::Utils::ObservableVoid
23{
24 RA_SINGLETON_INTERFACE( KeyMappingManager );
25
26 public:
29 {
30 public:
34 EventBinding() = default;
35
40 EventBinding( Qt::MouseButtons buttons,
41 Qt::KeyboardModifiers modifiers,
42 int key,
43 bool wheel = false ) :
44 m_buttons { buttons }, m_modifiers { modifiers }, m_key { key }, m_wheel { wheel } {}
45
49 explicit EventBinding( Qt::MouseButtons buttons,
50 Qt::KeyboardModifiers modifiers = Qt::NoModifier ) :
51 m_buttons { buttons }, m_modifiers { modifiers } {}
52
56 explicit EventBinding( int key, Qt::KeyboardModifiers modifiers = Qt::NoModifier ) :
57 m_modifiers { modifiers }, m_key { key } {}
58
62 explicit EventBinding( bool wheel, Qt::KeyboardModifiers modifiers = Qt::NoModifier ) :
63 m_modifiers { modifiers }, m_wheel { wheel } {}
64
65 bool isMouseEvent() { return m_buttons != Qt::NoButton; }
66 bool isWheelEvent() { return m_wheel; }
67 bool isKeyEvent() { return !isMouseEvent() && !isWheelEvent(); }
68 bool operator<( const EventBinding& b ) const;
69
70 // public data member, since there isn't any write access getter from KeyMappingManager
71 Qt::MouseButtons m_buttons { Qt::NoButton };
72 Qt::KeyboardModifiers m_modifiers { Qt::NoModifier };
73 // only one key
74 int m_key { -1 };
75 bool m_wheel { false };
76 };
77
78 using KeyMappingAction = Ra::Core::Utils::Index;
79 using Context = Ra::Core::Utils::Index;
80
83 void loadConfiguration( const std::string& filename = {} );
84
88 bool saveConfiguration( const std::string& filename = {} );
89
91 void reloadConfiguration();
92
93 std::string getLoadedFilename() { return m_file->fileName().toStdString(); }
94
101 KeyMappingAction getAction( const Context& context,
102 const Qt::MouseButtons& buttons,
103 const Qt::KeyboardModifiers& modifiers,
104 int key,
105 bool wheel = false );
106 KeyMappingAction
107 getAction( const Context& context, const QEvent* event, int key, bool wheel = false );
108 KeyMappingAction getAction( const Context& context, const EventBinding& binding );
109
112 std::optional<EventBinding> getBinding( const Context& context, KeyMappingAction action );
113
116 KeyMappingAction addAction( const Context& context, const std::string& actionName );
117
120 KeyMappingAction
121 addAction( const Context& context, const EventBinding& binding, const std::string& actionName );
122
126 void setActionBinding( const Context& context,
127 const EventBinding& binding,
128 const KeyMappingAction& action );
129
136 Context addContext( const std::string& contextName );
137
141 Context getContext( const std::string& contextName );
142
148 KeyMappingAction getAction( const Context& context, const std::string& actionName );
149
151 std::string getActionName( const Context& context, const KeyMappingAction& action );
152
154 std::string getContextName( const Context& context );
155
157 int addListener( Observable::Observer callback );
158
161 void removeListener( int callbackId );
162
164 std::string getHelpText();
165
168 static std::string enumNamesFromMouseButtons( const Qt::MouseButtons& buttons );
169
172 static std::string enumNamesFromKeyboardModifiers( const Qt::KeyboardModifiers& modifiers );
173
177 static EventBinding createEventBindingFromStrings( const std::string& buttonsString = "",
178 const std::string& modifiersString = "",
179 const std::string& keyString = "",
180 const std::string& wheelString = "" );
181
182 private:
183 KeyMappingManager();
184 ~KeyMappingManager();
185
187 void saveNode( QXmlStreamWriter& stream, const QDomNode& domNode );
188 void saveKeymap( QXmlStreamWriter& stream );
189
190 void loadConfigurationInternal( const QDomDocument& domDocument );
191 void loadConfigurationTagsInternal( QDomElement& node );
192 KeyMappingAction loadConfigurationMappingInternal( const std::string& context,
193 const std::string& keyString,
194 const std::string& modifiersString,
195 const std::string& buttonsString,
196 const std::string& wheelString,
197 const std::string& actionName );
198
202 static Qt::KeyboardModifiers getQtModifiersValue( const std::string& modifierString );
203
207 static Qt::MouseButtons getQtMouseButtonsValue( const std::string& buttonsString );
208 static int getKeyCode( const std::string& keyString );
209
210 std::string m_defaultConfigFile;
211 QFile* m_file;
212
213 using EventBindingMap = std::map<EventBinding, KeyMappingAction>;
214 using ContextNameMap = std::map<std::string, Context>;
216
217 ContextNameMap m_contextNameToIndex;
218 std::vector<ActionNameMap> m_actionNameToIndex;
219 std::vector<EventBindingMap> m_bindingToAction;
220};
221
238template <typename T>
240{
241 public:
242 static inline KeyMappingManager::Context getContext() { return m_keyMappingContext; }
243
247 static inline void configureKeyMapping() { T::configureKeyMapping_impl(); }
248
249 protected:
250 T& self() { return static_cast<T&>( *this ); }
251 static inline void setContext( const KeyMappingManager::Context& c ) {
252 m_keyMappingContext = c;
253 }
254
255 private:
256 static KeyMappingManager::Context m_keyMappingContext;
257};
258
260template <typename T>
261KeyMappingManager::Context KeyMappingManageable<T>::m_keyMappingContext;
262
270{
271 public:
272 using Context = KeyMappingManager::Context;
273 using KeyMappingAction = KeyMappingManager::KeyMappingAction;
274 using Callback = std::function<void( QEvent* )>;
275
279 inline explicit KeyMappingCallbackManager( Context context );
280
284 inline void addEventCallback( KeyMappingAction action, Callback callback );
285
291 addActionAndCallback( const std::string& actionName,
292 const KeyMappingManager::EventBinding& binding,
293 Callback callback );
294
298 inline bool triggerEventCallback( QEvent* event, int key, bool wheel = false );
299
303 inline bool triggerEventCallback( KeyMappingAction action, QEvent* event );
304
305 private:
306 std::map<KeyMappingAction, Callback> m_keymappingCallbacks;
307 Context m_context;
308};
309
310/******************************************************************************/
311/* inlines ********************************************************************/
312/******************************************************************************/
313
314inline bool KeyMappingManager::EventBinding::operator<( const EventBinding& b ) const {
315 return ( m_buttons < b.m_buttons ) ||
316 ( ( m_buttons == b.m_buttons ) && ( m_modifiers < b.m_modifiers ) ) ||
317 ( ( m_buttons == b.m_buttons ) && ( m_modifiers == b.m_modifiers ) &&
318 ( m_key < b.m_key ) ) ||
319 ( ( m_buttons == b.m_buttons ) && ( m_modifiers == b.m_modifiers ) &&
320 ( m_key == b.m_key ) && ( m_wheel < b.m_wheel ) );
321}
322
324 m_context { context } {}
325
326inline void KeyMappingCallbackManager::addEventCallback( KeyMappingAction action,
327 Callback callback ) {
328 m_keymappingCallbacks[action] = callback;
329}
330
333 const KeyMappingManager::EventBinding& binding,
334 Callback callback ) {
335
336 auto mgr = KeyMappingManager::getInstance();
337 auto action = mgr->addAction( m_context, binding, actionName );
338 addEventCallback( action, callback );
339 return action;
340}
341
342inline bool KeyMappingCallbackManager::triggerEventCallback( KeyMappingAction actionIndex,
343 QEvent* event ) {
344 auto itr = m_keymappingCallbacks.find( actionIndex );
345 if ( itr == m_keymappingCallbacks.end() ) return false;
346 itr->second( event );
347 return true;
348}
349
350inline bool KeyMappingCallbackManager::triggerEventCallback( QEvent* event, int key, bool wheel ) {
351 auto mgr = KeyMappingManager::getInstance();
352 auto actionIndex = mgr->getAction( m_context, event, key, wheel );
353 return triggerEventCallback( actionIndex, event );
354}
355
356} // namespace Gui
357} // namespace Ra
This class manage a collection of binding/callback associated with a context.
bool triggerEventCallback(QEvent *event, int key, bool wheel=false)
void addEventCallback(KeyMappingAction action, Callback callback)
KeyMappingManager::KeyMappingAction addActionAndCallback(const std::string &actionName, const KeyMappingManager::EventBinding &binding, Callback callback)
KeyMappingManageable decorator to use as CRTP.
Inner class to store event binding.
EventBinding(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, int key, bool wheel=false)
EventBinding(bool wheel, Qt::KeyboardModifiers modifiers=Qt::NoModifier)
EventBinding(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers=Qt::NoModifier)
EventBinding(int key, Qt::KeyboardModifiers modifiers=Qt::NoModifier)
An utility class used to map a (combination of) key / modifiers / mouse buttons to a specific action....
Ra::Core::Utils::Index KeyMappingAction
handle to an action
Ra::Core::Utils::Index Context
handle to a Context
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3