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