#ifndef MENUBAR_COMMAND_H
#define MENUBAR_COMMAND_H
#include <vector>
#include <map>
#include <string>
#include "tcommon.h"
#include <QAction>
#include <QMenu>
#undef DVAPI
#undef DVVAR
#ifdef TOONZQT_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif
//
// forward declaration
//
class QAction;
//
// base class
//
class DVAPI CommandHandlerInterface
{
public:
virtual ~CommandHandlerInterface() {}
virtual void execute() = 0;
};
//-----------------------------------------------------------------------------
//
// command identifier (e.g. "copy"). They are NOT command names (e.g. "&Copy")
//
typedef const char *CommandId;
enum CommandType {
UndefinedCommandType = 0,
RightClickMenuCommandType,
MenuFileCommandType,
MenuEditCommandType,
MenuScanCleanupCommandType,
MenuLevelCommandType,
MenuXsheetCommandType,
MenuCellsCommandType,
MenuViewCommandType,
MenuWindowsCommandType,
PlaybackCommandType,
RGBACommandType,
FillCommandType,
ToolCommandType,
ToolModifierCommandType,
ZoomCommandType,
MiscCommandType,
MenuCommandType
};
//-----------------------------------------------------------------------------
class AuxActionsCreator
{
public:
AuxActionsCreator();
virtual ~AuxActionsCreator(){};
virtual void createActions(QObject *parent) = 0;
};
//-----------------------------------------------------------------------------
class AuxActionsCreatorManager
{
bool m_auxActionsCreated;
std::vector<AuxActionsCreator *> m_auxActionsCreators;
AuxActionsCreatorManager();
public:
static AuxActionsCreatorManager *instance();
void addAuxActionsCreator(AuxActionsCreator *auxActionsCreator);
void createAuxActions(QObject *parent);
};
//-----------------------------------------------------------------------------
//
// command manager:
// setExecutor(id, executor)
// setAction(id, qaction)
// execute(qaction)/
//
class DVAPI CommandManager
{ // singleton
class Node
{
public:
std::string m_id;
CommandType m_type;
QAction *m_qaction;
CommandHandlerInterface *m_handler;
bool m_enabled;
QString m_onText, m_offText; // for toggle commands. e.g. show/hide something
Node(CommandId id)
: m_id(id), m_type(UndefinedCommandType), m_qaction(0), m_handler(0), m_enabled(true) {}
~Node()
{
if (m_handler)
delete m_handler;
}
};
std::map<std::string, Node *> m_idTable;
std::map<QAction *, Node *> m_qactionTable;
std::map<std::string, Node *> m_shortcutTable;
CommandManager();
Node *getNode(CommandId id, bool createIfNeeded = true);
void setShortcut(CommandId id, QAction *action, std::string shortcutString);
void createAuxActions();
public:
static CommandManager *instance();
~CommandManager();
void setHandler(CommandId id, CommandHandlerInterface *handler);
void define(
CommandId id,
CommandType type,
std::string defaultShortcutString,
QAction *action);
QAction *createAction(const char *id, const char *name, const char *defaultShortcut);
void getActions(CommandType type, std::vector<QAction *> &actions);
QAction *getActionFromShortcut(std::string shortcutString);
std::string getShortcutFromAction(QAction *action);
std::string getShortcutFromId(CommandId id);
int getKeyFromShortcut(const std::string &shortcut);
int getKeyFromId(CommandId id);
void setShortcut(QAction *action, std::string shortcutString);
QAction *getAction(CommandId id, bool createIfNeeded = false);
// createAction creates a new indepenent QAction with text and shortcut
// if the action is a toggle action (e.g. show/hide something) the text is controlled by state
// you can use createAction() for context menu
QAction *createAction(CommandId id, QObject *parent = 0, bool state = true);
void execute(QAction *action);
/*! If action is defined in m_qactionTable recall \b execute(action), otherwise recall execute(menuAction).*/
void execute(QAction *action, QAction *menuAction);
void execute(CommandId id);
void enable(CommandId id, bool enabled);
// if id is a toggle (e.g. a checkable menu item) then set its status;
// note: this will trigger any associated handler
void setChecked(CommandId id, bool checked);
// use setToggleTexts for toggle commands that have two names according to the current status. e.g. show/hide something
void setToggleTexts(CommandId id, const QString &onText, const QString &offText);
std::string getIdFromAction(QAction* action);
};
//-----------------------------------------------------------------------------
//
// CommandHandlerHelper = target + method
//
template <class T>
class CommandHandlerHelper : public CommandHandlerInterface
{
T *m_target;
void (T::*m_method)();
public:
CommandHandlerHelper(T *target, void (T::*method)())
: m_target(target), m_method(method)
{
}
void execute() { (m_target->*m_method)(); }
};
template <class T, typename R>
class CommandHandlerHelper2 : public CommandHandlerInterface
{
T *m_target;
void (T::*m_method)(R value);
R m_value;
public:
CommandHandlerHelper2(T *target, void (T::*method)(R), R value)
: m_target(target), m_method(method), m_value(value)
{
}
void execute() { (m_target->*m_method)(m_value); }
};
//-----------------------------------------------------------------------------
template <class T>
inline void setCommandHandler(CommandId id, T *target, void (T::*method)())
{
CommandManager::instance()->setHandler(id, new CommandHandlerHelper<T>(target, method));
}
//-----------------------------------------------------------------------------
class DVAPI MenuItemHandler : public QObject
{
Q_OBJECT
public:
MenuItemHandler(CommandId cmdId);
virtual ~MenuItemHandler(){};
virtual void execute() = 0;
};
template <class T>
class OpenPopupCommandHandler : public MenuItemHandler
{
T *m_popup;
CommandId m_id;
public:
OpenPopupCommandHandler(CommandId cmdId)
: MenuItemHandler(cmdId), m_popup(0)
{
}
void execute()
{
if (!m_popup)
m_popup = new T();
m_popup->show();
m_popup->raise();
m_popup->activateWindow();
}
};
//-----------------------------------------------------------------------------
class DVAPI DVAction : public QAction
{
Q_OBJECT
public:
DVAction(const QString &text, QObject *parent);
DVAction(const QIcon &icon, const QString &text, QObject *parent);
public slots:
void onTriggered();
};
//-----------------------------------------------------------------------------
class DVAPI DVMenuAction : public QMenu
{
Q_OBJECT
int m_triggeredActionIndex;
public:
DVMenuAction(const QString &text, QWidget *parent, QList<QString> actions);
void setActions(QList<QString> actions);
int getTriggeredActionIndex() { return m_triggeredActionIndex; }
public slots:
void onTriggered(QAction *action);
};
//-----------------------------------------------------------------------------
#endif // MENUBAR_COMMAND_H