#pragma once #include #include #include #include #include #include #include #include #include #include "uitypes.h" #define MENU_ORDER_FIRST 0 #define MENU_ORDER_EARLY 64 #define MENU_ORDER_NORMAL 128 #define MENU_ORDER_LATE 192 #define MENU_ORDER_LAST 255 class View; class UIContext; struct LinearViewCursorPosition; /*! \defgroup action Action \ingroup uiapi */ /*! \ingroup action */ struct BINARYNINJAUIAPI HighlightTokenState { bool valid; bool focused; bool secondaryHighlight; BNInstructionTextTokenType type; BinaryNinja::InstructionTextToken token; ArchitectureRef arch; bool addrValid, localVarValid, isDest; uint64_t addr; BinaryNinja::Variable localVar; size_t tokenIndex; size_t characterIndex; size_t indentGroup; HighlightTokenState(); Json::Value serialize() const; bool deserialize(const Json::Value& value); }; /*! \ingroup action */ struct BINARYNINJAUIAPI UIActionContext { UIContext* context; View* view; QWidget* widget; HighlightTokenState token; BinaryViewRef binaryView; uint64_t address, length; size_t instrIndex; FunctionRef function; LowLevelILFunctionRef lowLevelILFunction; MediumLevelILFunctionRef mediumLevelILFunction; HighLevelILFunctionRef highLevelILFunction; LinearViewCursorPosition* cursorPosition; UIActionContext(); UIActionContext(const BinaryNinja::PluginCommandContext& pluginContext); operator BinaryNinja::PluginCommandContext() const; }; /*! \ingroup action */ struct BINARYNINJAUIAPI UIAction { std::function activate; std::function isValid; UIAction(); UIAction(const std::function& activate); UIAction(const std::function& activate); UIAction(const std::function& activate, const std::function& isValid); UIAction(const std::function& activate, const std::function& isValid); UIAction(const std::function& activate, const std::function& isValid); UIAction(const std::function& activate, const std::function& isValid); UIAction(const UIAction& other); UIAction& operator=(const UIAction& other); static void registerAction(const QString& name, const QKeySequence& defaultKeyBinding = QKeySequence(), const QList& alias = QList()); static void registerAction(const QString& name, const QList& defaultKeyBinding, const QList& alias = QList()); static void unregisterAction(const QString& name); static void registerTransformActions(); static void registerPluginCommandActions(); static void registerPluginCommandActions(const QString& prefix); static void registerHighlightColorActions(const QString& prefix); static void registerBookmarkActions(const QString& prefix); static void setActionDisplayName(const QString& registeredName, const QString& displayName); static void setActionDisplayName(const QString& registeredName, const std::function& displayNameFunc); static void setActionDisplayName( const QString& registeredName, const std::function& displayNameFunc); static bool isActionRegistered(const QString& name); static std::set getAllRegisteredActions(); static QList getDefaultKeyBinding(const QString& name); static QList getKeyBinding(const QString& name); static QList getAliases(const QString& name); static QString getActionDisplayName(const QString& name, const UIActionContext& context); static int rawControl(); static int rawMeta(); static void setUserKeyBinding(const QString& name, const QList& keyBinding); static void resetKeyBindingToDefault(const QString& name); static void readKeyBindingsFile(); static void writeKeyBindingsFile(); }; /*! \ingroup action */ struct BINARYNINJAUIAPI UITransformAction { std::function activate; std::function isValid; UITransformAction(); UITransformAction(const std::function& activate); UITransformAction(const std::function& activate); UITransformAction(const std::function& activate, const std::function& isValid); UITransformAction(const std::function& activate, const std::function& isValid); UITransformAction(const std::function& activate, const std::function& isValid); UITransformAction(const std::function& activate, const std::function& isValid); UITransformAction(const UITransformAction& other); }; /*! \ingroup action */ struct BINARYNINJAUIAPI UIHighlightColorAction { std::function activate; std::function isValid; UIHighlightColorAction(); UIHighlightColorAction(const std::function& activate); UIHighlightColorAction(const std::function& activate); UIHighlightColorAction(const std::function& activate, const std::function& isValid); UIHighlightColorAction(const std::function& activate, const std::function& isValid); UIHighlightColorAction(const std::function& activate, const std::function& isValid); UIHighlightColorAction( const std::function& activate, const std::function& isValid); UIHighlightColorAction(const UIHighlightColorAction& other); }; /*! \ingroup action */ struct BINARYNINJAUIAPI UIBookmarkAction { std::function activate; std::function isValid; UIBookmarkAction(const std::function& activate, const std::function& isValid); }; /*! \ingroup action */ enum ActionPriority { LowActionPriority, NormalActionPriority, HighActionPriority }; class UIActionHandler; class BINARYNINJAUIAPI UIActionHandlerWidgetConnection : public QObject { Q_OBJECT UIActionHandler* m_handler; friend class UIActionHandler; public: UIActionHandlerWidgetConnection(QWidget* widget, UIActionHandler* handler); virtual ~UIActionHandlerWidgetConnection(); }; /*! \ingroup action */ class BINARYNINJAUIAPI UIActionHandler { std::map m_actions; std::map m_priority; std::map> m_actionDisplayNames; std::map> m_checked; QWidget* m_handlerWidget; UIActionHandlerWidgetConnection* m_handlerWidgetConnection = nullptr; std::map> m_handlerWidgetShortcuts; UIActionHandler* m_parent; std::set m_children; bool m_isGlobal, m_inheritParentBindings; std::function m_actionContextOverride; friend class UIActionHandlerWidgetConnection; static std::map> m_actionBindings; static std::set m_globalMenuActions; void bindActionShortcutToWidget(const QString& name); void unbindActionShortcut(const QString& name); void addActionToChildren(const QString& name); void removeActionFromChildren(const QString& name); public: UIActionHandler(bool isGlobal = false); virtual ~UIActionHandler(); void setupActionHandler(QWidget* obj, bool inheritParentBindings = true); static UIActionHandler* actionHandlerFromWidget(QWidget* widget); static UIActionHandler* globalActions(); void bindAction(const QString& name, const UIAction& action); void bindAction(const QString& name, const UIAction& action, ActionPriority priority); void unbindAction(const QString& name); void executeAction(const QString& name); void executeAction(const QString& name, const UIActionContext& context); bool isBoundAction(const QString& name); bool isValidAction(const QString& name); bool isValidAction(const QString& name, const UIActionContext& context); ActionPriority getPriority(const QString& name); void bindCopyAsActions(const UITransformAction& action); void bindCopyAsActions(const UITransformAction& action, const std::function& shouldShow); void bindPasteFromActions(const UITransformAction& action); void bindTransformActions(const UITransformAction& encode, const UITransformAction& decode); void bindTransformActions(const UITransformAction& encode, const UITransformAction& decode, const std::function& shouldShow); void unbindCopyAsActions(); void unbindPasteFromActions(); void unbindTransformActions(); void bindPluginCommandActions(); void bindPluginCommandActions(const QString& prefix, const std::function& context, const std::function& isValid); void unbindPluginCommandActions(); void unbindPluginCommandActions(const QString& prefix); void bindHighlightColorActions(const QString& prefix, const UIHighlightColorAction& action); void unbindHighlightColorActions(const QString& prefix); void bindBookmarkActions(const QString& prefix, const UIBookmarkAction& action); void unbindBookmarkActions(const QString& prefix); void setActionDisplayName(const QString& registeredName, const QString& displayName); void setActionDisplayName(const QString& registeredName, const std::function& displayNameFunc); void setActionDisplayName( const QString& registeredName, const std::function& displayNameFunc); QString getActionDisplayName(const QString& name); QString getActionDisplayName(const QString& name, const UIActionContext& context); void setChecked(const QString& name, bool checked); void setChecked(const QString& name, const std::function& checked); void setChecked(const QString& name, const std::function& checked); bool isChecked(const QString& name); bool isChecked(const QString& name, const UIActionContext& context); bool isCheckable(const QString& name); std::set getAllValidActions(); std::set getAllValidActions(const UIActionContext& context); UIActionContext defaultActionContext(); virtual UIActionContext actionContext(); void setActionContext(const std::function& contextFunc); QWidget* widget() { return m_handlerWidget; } static void updateActionBindings(const QString& name); static bool isActionBoundToAnyHandler(const QString& name); static void addGlobalMenuAction(const QString& name); static void removeGlobalMenuAction(const QString& name); static void reparentWidget(QWidget* widget); }; /*! \ingroup action */ enum MenuItemVisibility { DefaultMenuItemVisibility, ShowMenuItemOnlyWhenActive, AlwaysShowMenuItem, NeverShowMenuItem }; class MenuInstance; /*! \ingroup action */ class BINARYNINJAUIAPI Menu { std::map m_actions; std::map m_groups; std::map m_order, m_groupOrder; std::map m_visibility; std::map m_roles; std::map m_icons; uint64_t m_version; bool m_global; Menu(bool global); void setParentOrdering(const QString& path, const QString& group, uint8_t order); public: Menu(); Menu(const Menu& menu); void addAction(const QString& action, const QString& group, uint8_t order = MENU_ORDER_NORMAL); void addRelativeAction(const QString& base, const QString& action, const QString& group, uint8_t order = MENU_ORDER_NORMAL); void addAction( const QString& submenu, const QString& action, const QString& group, uint8_t order = MENU_ORDER_NORMAL); void addRelativeAction( const QString& submenu, const QString& base, const QString& action, const QString& group, uint8_t order = MENU_ORDER_NORMAL); void removeAction(const QString& action); void removeAction(const QString& submenu, const QString& action); void addCopyAsActions(const QString& group, uint8_t order = MENU_ORDER_NORMAL); void addPasteFromActions(const QString& group, uint8_t order = MENU_ORDER_NORMAL); void addTransformActions(const QString& group, uint8_t order = MENU_ORDER_NORMAL); void removeCopyAsActions(); void removePasteFromActions(); void removeTransformActions(); void addPluginCommandActions(const QString& group); void addPluginCommandActions(const QString& prefix, const QString& group, uint8_t order = MENU_ORDER_NORMAL, const std::vector& types = {}); void addPluginCommandSubmenuActions(const QString& submenu, const QString& group, const std::vector& types); void removePluginCommandActions(); void removePluginCommandSubmenuActions(const QString& submenu); void addHighlightColorActions(const QString& submenu, const QString& group, uint8_t order = MENU_ORDER_NORMAL); void removeHighlightColorActions(const QString& submenu); void setOrdering(const QString& path, const QString& group, uint8_t order = MENU_ORDER_NORMAL); void setGroupOrdering(const QString& group, uint8_t order); void setVisibility(const QString& path, MenuItemVisibility visibility); void setRole(const QString& path, QAction::MenuRole role); void setIcon(const QString& path, const QIcon& icon); MenuInstance* create(QWidget* owner, UIActionHandler* handler, bool showInactiveActions = false); MenuInstance* create( QWidget* owner, UIActionHandler* handler, const UIActionContext& context, bool showInactiveActions = false); uint64_t getVersion(); const std::map& getActions(); QString getGroupForAction(const QString& name); uint8_t getOrderForAction(const QString& name); uint8_t getOrderForGroup(const QString& name); MenuItemVisibility getVisibility(const QString& name); QAction::MenuRole getRole(const QString& name); QIcon getIcon(const QString& name); static Menu* mainMenu(const QString& name); static Menu* dockMenu(); static void setMainMenuOrder(const QString& name, uint8_t order); static std::vector getMainMenus(); }; class BINARYNINJAUIAPI OrderedMenuHelper { Menu* m_menu = nullptr; uint8_t m_groupOrder = MENU_ORDER_NORMAL; std::map m_orders; public: OrderedMenuHelper(Menu* menu) : m_menu(menu) { } Menu* getMenu() { return m_menu; } void addAction(const QString& action, const QString& group) { if (m_orders.find(group) == m_orders.end()) { m_menu->setGroupOrdering(group, m_groupOrder++); m_orders[group] = MENU_ORDER_NORMAL; } m_menu->addAction(action, group, m_orders[group]++); } }; /*! \ingroup action */ class BINARYNINJAUIAPI MenuInstance { Menu* m_menu; QMenu* m_instance; UIActionHandler* m_handler; UIActionContext m_context; uint64_t m_version; std::map> m_actions; struct Group; struct Item { QString name, action; uint8_t order; QAction::MenuRole role; QIcon icon; bool checkable; std::vector submenu; }; struct Group { QString name; std::vector items; uint8_t order; }; static std::map> m_actionBindings; std::vector layoutMenu( const std::map& actions, const QString& prefix, bool showInactiveActions); void addGroupsToMenu(QMenu* menu, const std::vector& groups); public: MenuInstance(Menu* menu, QMenu* instance); virtual ~MenuInstance(); void update(UIActionHandler* handler, bool showInactiveActions = false); void update(UIActionHandler* handler, const UIActionContext& context, bool showInactiveActions = false); Menu* source() const { return m_menu; } QMenu* instance() const { return m_instance; } static void updateActionBindings(const QString& name); }; /*! \ingroup action */ class BINARYNINJAUIAPI MainMenuInstance { QMenuBar* m_instance; std::map m_menus; MenuInstance* m_dockMenu; public: MainMenuInstance(QMenuBar* instance); ~MainMenuInstance(); void update(UIActionHandler* handler); void update(UIActionHandler* handler, const UIActionContext& context); }; Q_DECLARE_METATYPE(UIActionHandler*)