1 #pragma once
2
3 #ifndef MENUBAR_COMMAND_H
4 #define MENUBAR_COMMAND_H
5
6 #include <vector>
7 #include <map>
8 #include <string>
9 #include "tcommon.h"
10
11 #include <QAction>
12 #include <QMenu>
13
14 #undef DVAPI
15 #undef DVVAR
16 #ifdef TOONZQT_EXPORTS
17 #define DVAPI DV_EXPORT_API
18 #define DVVAR DV_EXPORT_VAR
19 #else
20 #define DVAPI DV_IMPORT_API
21 #define DVVAR DV_IMPORT_VAR
22 #endif
23
24 //
25 // forward declaration
26 //
27 class QAction;
28
29 //
30 // base class
31 //
32 class DVAPI CommandHandlerInterface {
33 public:
~CommandHandlerInterface()34 virtual ~CommandHandlerInterface() {}
35 virtual void execute() = 0;
36 };
37
38 //-----------------------------------------------------------------------------
39
40 //
41 // command identifier (e.g. "copy"). They are NOT command names (e.g. "&Copy")
42 //
43 typedef const char *CommandId;
44
45 enum CommandType {
46 UndefinedCommandType = 0,
47 RightClickMenuCommandType,
48 MenuFileCommandType,
49 MenuEditCommandType,
50 MenuScanCleanupCommandType,
51 MenuLevelCommandType,
52 MenuXsheetCommandType,
53 MenuCellsCommandType,
54 MenuPlayCommandType,
55 MenuRenderCommandType,
56 MenuViewCommandType,
57 MenuWindowsCommandType,
58 MenuHelpCommandType,
59 PlaybackCommandType,
60 RGBACommandType,
61 FillCommandType,
62 ToolCommandType,
63 ToolModifierCommandType,
64 ZoomCommandType,
65 MiscCommandType,
66 MenuCommandType,
67 VisualizationButtonCommandType,
68 StopMotionCommandType
69 };
70
71 //-----------------------------------------------------------------------------
72
73 class AuxActionsCreator {
74 public:
75 AuxActionsCreator();
~AuxActionsCreator()76 virtual ~AuxActionsCreator(){};
77 virtual void createActions(QObject *parent) = 0;
78 };
79
80 //-----------------------------------------------------------------------------
81
82 class AuxActionsCreatorManager {
83 bool m_auxActionsCreated;
84 std::vector<AuxActionsCreator *> m_auxActionsCreators;
85 AuxActionsCreatorManager();
86
87 public:
88 static AuxActionsCreatorManager *instance();
89 void addAuxActionsCreator(AuxActionsCreator *auxActionsCreator);
90 void createAuxActions(QObject *parent);
91 };
92
93 //-----------------------------------------------------------------------------
94
95 //
96 // command manager:
97 // setExecutor(id, executor)
98 // setAction(id, qaction)
99 // execute(qaction)/
100 //
101 class DVAPI CommandManager { // singleton
102
103 class Node {
104 public:
105 std::string m_id;
106 CommandType m_type;
107 QAction *m_qaction;
108 CommandHandlerInterface *m_handler;
109 bool m_enabled;
110 QString m_onText,
111 m_offText; // for toggle commands. e.g. show/hide something
112
Node(CommandId id)113 Node(CommandId id)
114 : m_id(id)
115 , m_type(UndefinedCommandType)
116 , m_qaction(0)
117 , m_handler(0)
118 , m_enabled(true) {}
119
~Node()120 ~Node() {
121 if (m_handler) delete m_handler;
122 }
123 };
124
125 std::map<std::string, Node *> m_idTable;
126 std::map<QAction *, Node *> m_qactionTable;
127 std::map<std::string, Node *> m_shortcutTable;
128
129 CommandManager();
130
131 Node *getNode(CommandId id, bool createIfNeeded = true);
132 void setShortcut(CommandId id, QAction *action, std::string shortcutString);
133 void createAuxActions();
134
135 public:
136 static CommandManager *instance();
137 ~CommandManager();
138
139 void setHandler(CommandId id, CommandHandlerInterface *handler);
140
141 void define(CommandId id, CommandType type, std::string defaultShortcutString,
142 QAction *action);
143
144 QAction *createAction(const char *id, const char *name,
145 const char *defaultShortcut);
146
147 void getActions(CommandType type, std::vector<QAction *> &actions);
148 QAction *getActionFromShortcut(std::string shortcutString);
149 std::string getShortcutFromAction(QAction *action);
150 std::string getShortcutFromId(CommandId id);
151 int getKeyFromShortcut(const std::string &shortcut);
152 int getKeyFromId(CommandId id);
153 void setShortcut(QAction *action, std::string shortcutString,
154 bool keepDefault = true);
155
156 QAction *getAction(CommandId id, bool createIfNeeded = false);
157
158 // createAction creates a new indepenent QAction with text and shortcut
159 // if the action is a toggle action (e.g. show/hide something) the text is
160 // controlled by state
161 // you can use createAction() for context menu
162 QAction *createAction(CommandId id, QObject *parent = 0, bool state = true);
163
164 void execute(QAction *action);
165 /*! If action is defined in m_qactionTable recall \b execute(action),
166 * otherwise recall execute(menuAction).*/
167 void execute(QAction *action, QAction *menuAction);
168 void execute(CommandId id);
169 void enable(CommandId id, bool enabled);
170
171 // if id is a toggle (e.g. a checkable menu item) then set its status;
172 // note: this will trigger any associated handler
173 void setChecked(CommandId id, bool checked);
174
175 // use setToggleTexts for toggle commands that have two names according to the
176 // current status. e.g. show/hide something
177 void setToggleTexts(CommandId id, const QString &onText,
178 const QString &offText);
179
180 std::string getIdFromAction(QAction *action);
181
182 // load user defined shortcuts
183 void loadShortcuts();
184 };
185
186 //-----------------------------------------------------------------------------
187
188 //
189 // CommandHandlerHelper = target + method
190 //
191
192 template <class T>
193 class CommandHandlerHelper final : public CommandHandlerInterface {
194 T *m_target;
195 void (T::*m_method)();
196
197 public:
CommandHandlerHelper(T * target,void (T::* method)())198 CommandHandlerHelper(T *target, void (T::*method)())
199 : m_target(target), m_method(method) {}
execute()200 void execute() override { (m_target->*m_method)(); }
201 };
202
203 template <class T, typename R>
204 class CommandHandlerHelper2 final : public CommandHandlerInterface {
205 T *m_target;
206 void (T::*m_method)(R value);
207 R m_value;
208
209 public:
CommandHandlerHelper2(T * target,void (T::* method)(R),R value)210 CommandHandlerHelper2(T *target, void (T::*method)(R), R value)
211 : m_target(target), m_method(method), m_value(value) {}
execute()212 void execute() override { (m_target->*m_method)(m_value); }
213 };
214
215 //-----------------------------------------------------------------------------
216
217 template <class T>
setCommandHandler(CommandId id,T * target,void (T::* method)())218 inline void setCommandHandler(CommandId id, T *target, void (T::*method)()) {
219 CommandManager::instance()->setHandler(
220 id, new CommandHandlerHelper<T>(target, method));
221 }
222
223 //-----------------------------------------------------------------------------
224
225 class DVAPI MenuItemHandler : public QObject {
226 Q_OBJECT
227 public:
228 MenuItemHandler(CommandId cmdId);
~MenuItemHandler()229 virtual ~MenuItemHandler(){};
230 virtual void execute() = 0;
231 };
232
233 template <class T>
234 class OpenPopupCommandHandler final : public MenuItemHandler {
235 T *m_popup;
236 CommandId m_id;
237
238 public:
OpenPopupCommandHandler(CommandId cmdId)239 OpenPopupCommandHandler(CommandId cmdId)
240 : MenuItemHandler(cmdId), m_popup(0) {}
241
execute()242 void execute() override {
243 if (!m_popup) m_popup = new T();
244 m_popup->show();
245 m_popup->raise();
246 m_popup->activateWindow();
247 }
248 };
249
250 //-----------------------------------------------------------------------------
251
252 class DVAPI DVAction final : public QAction {
253 Q_OBJECT
254 public:
255 DVAction(const QString &text, QObject *parent);
256 DVAction(const QIcon &icon, const QString &text, QObject *parent);
257
258 public slots:
259 void onTriggered();
260 };
261
262 //-----------------------------------------------------------------------------
263
264 class DVAPI DVMenuAction final : public QMenu {
265 Q_OBJECT
266
267 int m_triggeredActionIndex;
268
269 public:
270 DVMenuAction(const QString &text, QWidget *parent, QList<QString> actions);
271 void setActions(QList<QString> actions);
272
getTriggeredActionIndex()273 int getTriggeredActionIndex() { return m_triggeredActionIndex; }
274
275 public slots:
276 void onTriggered(QAction *action);
277 };
278
279 //-----------------------------------------------------------------------------
280
281 #endif // MENUBAR_COMMAND_H
282