1130 lines
39 KiB
C++

/**
* @file ac_manager.hpp
* @brief Reconstructed header for Toon Boom AC_Manager class hierarchy
*
* This header was reverse-engineered from ToonBoomActionManager.dll
* IDA Database: RE/ToonBoomActionManager.dll.i64
*
* AC_Manager is the central action/command management system for Toon Boom
* applications. It handles:
* - Responder chain management (first responder, selection responder)
* - Menu creation and management
* - Toolbar creation and registration
* - Shortcut/keyboard handling
* - Action triggering and validation
*
* @note All offsets and structures derived from decompilation analysis.
* This is NOT official Toon Boom code.
*/
#pragma once
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QList>
#include <QtCore/QVariant>
#include <QtGui/QIcon>
#include <QtGui/QKeySequence>
#include <QtWidgets/QWidget>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtXml/QDomElement>
#include <vector>
// Forward declarations
class AC_Manager;
class AC_ManagerImpl;
class AC_Responder;
class AC_Menu;
class AC_Toolbar;
class AC_ToolbarImpl;
class AC_ToolbarItemGenerator;
class AC_ShortcutManager;
class AC_ActionInfo;
class AC_Object;
class AC_Item;
class AC_Container;
class AC_ContainerImpl;
class AC_ToolbarMultiButton;
/**
* @brief Result code for action command handling
*
* Used as return value from perform(), trigger(), and validation methods.
*/
enum class AC_Result : int {
NotHandled = 0, ///< Action was not handled by any responder
Handled = 1, ///< Action was successfully handled
Error = 2 ///< An error occurred during handling
};
/**
* @brief Manager options for AC_Manager configuration
*/
enum class AC_ManagerOption : int {
TrimShortcuts = 0 ///< Whether to trim whitespace from shortcut strings
// Additional options may exist
};
/**
* @brief Action information passed to responders
*
* Contains information about the action being performed, including
* the slot name, parameters, and enabled/checked state.
*
* This is an opaque class - the actual implementation is in Toon Boom DLLs.
* The interface is provided for type safety in method signatures.
*/
class AC_ActionInfo : public QObject {
Q_OBJECT
public:
virtual ~AC_ActionInfo() = default;
// State accessors - implemented in Toon Boom DLLs
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual bool isChecked() const = 0;
virtual void setChecked(bool checked) = 0;
virtual bool isVisible() const = 0;
virtual void setVisible(bool visible) = 0;
// Action info
virtual const QString& slot() const = 0;
virtual const QString& text() const = 0;
virtual QVariant itemParameter() const = 0;
// Responder
virtual AC_Responder* responder() const = 0;
virtual void setResponder(AC_Responder* responder) = 0;
};
/**
* @brief Abstract interface for objects that can respond to actions
*
* AC_Responder defines the responder chain pattern used by Toon Boom.
* Responders receive actions from toolbar buttons, menus, and shortcuts,
* and can either handle them or pass them up the chain.
*
* To create a custom responder:
* 1. Inherit from AC_Responder (and QObject if you need Qt signals/slots)
* 2. Implement all pure virtual methods
* 3. Register with AC_Manager::registerResponder()
*
* Example:
* @code
* class MyResponder : public QObject, public AC_Responder {
* Q_OBJECT
* public:
* MyResponder(const QString& id, AC_Manager* mgr)
* : m_identity(id), m_manager(mgr) {
* mgr->registerResponder(this, nullptr);
* }
*
* // Implement AC_Responder interface...
* const QString& responderIdentity() const override { return m_identity; }
* AC_Manager* actionManager() const override { return m_manager; }
* // ... other methods
*
* public slots:
* void onActionMyAction() { // handle action }
* };
* @endcode
*/
class AC_Responder {
public:
virtual ~AC_Responder() = default;
// =========================================================================
// Identity
// =========================================================================
/**
* @brief Get the unique identity string for this responder
* @return Reference to identity QString (must remain valid)
*/
virtual const QString& responderIdentity() const = 0;
/**
* @brief Get the human-readable description
* @return Reference to description QString
*/
virtual const QString& responderDescription() const = 0;
/**
* @brief Set the description
* @param description New description
*/
virtual void setResponderDescription(const QString& description) = 0;
// =========================================================================
// Responder Chain Navigation
// =========================================================================
/**
* @brief Get the parent responder in the chain
* @return Parent responder or nullptr if this is the root
*/
virtual AC_Responder* parentResponder() = 0;
/**
* @brief Get proxy responder that should handle actions instead
* @return Proxy responder or nullptr
*/
virtual AC_Responder* proxyResponder() = 0;
// =========================================================================
// First Responder (Keyboard Focus)
// =========================================================================
/**
* @brief Check if this responder can become first responder
* @return true if this responder accepts first responder status
*/
virtual bool acceptsFirstResponder() = 0;
/**
* @brief Called when becoming first responder
* @return true if successfully became first responder
*/
virtual bool becomeFirstResponder() = 0;
/**
* @brief Called when resigning first responder status
* @return true if successfully resigned
*/
virtual bool resignFirstResponder() = 0;
// =========================================================================
// Selection Responder
// =========================================================================
/**
* @brief Check if this responder can become selection responder
* @return true if this responder accepts selection responder status
*/
virtual bool acceptsSelectionResponder() = 0;
/**
* @brief Called when becoming selection responder
* @return true if successfully became selection responder
*/
virtual bool becomeSelectionResponder() = 0;
/**
* @brief Called when resigning selection responder status
* @return true if successfully resigned
*/
virtual bool resignSelectionResponder() = 0;
// =========================================================================
// Action Handling
// =========================================================================
/**
* @brief Perform an action
*
* This is called when an action targets this responder. The implementation
* should invoke the appropriate slot based on AC_ActionInfo::slot().
*
* @param info Action information including slot name and parameters
* @return AC_Result::Handled if action was handled, NotHandled to pass up chain
*/
virtual AC_Result perform(AC_ActionInfo* info) = 0;
/**
* @brief Perform action on child responders
* @param info Action information
* @return Result from children
*/
virtual AC_Result performDownToChildren(AC_ActionInfo* info) = 0;
/**
* @brief Check if this responder should receive messages
* @return true if responder is active and should receive messages
*/
virtual bool shouldReceiveMessages() const = 0;
/**
* @brief Check if this responder handles keyboard shortcuts
* @return true if shortcuts should be processed by this responder
*/
virtual bool handleShortcuts() const = 0;
// =========================================================================
// Event Handling
// =========================================================================
/**
* @brief Handle a Qt event
* @param event Event to handle
* @return AC_Result indicating if event was handled
*/
virtual AC_Result handleEvent(QEvent* event) = 0;
// =========================================================================
// Manager Access
// =========================================================================
/**
* @brief Get the action manager
* @return AC_Manager instance or nullptr
*/
virtual AC_Manager* actionManager() const = 0;
};
/**
* @brief Simple base class for implementing AC_Responder
*
* Provides default implementations for most AC_Responder methods.
* Subclass this for simpler responder creation.
*
* @note This is a convenience class for users creating custom responders.
* It is NOT the same as Toon Boom's internal AC_ResponderTemplate.
*/
class AC_ResponderBase : public AC_Responder {
public:
AC_ResponderBase(const QString& identity, AC_Manager* manager = nullptr)
: m_identity(identity), m_manager(manager) {}
virtual ~AC_ResponderBase() = default;
// Identity
const QString& responderIdentity() const override { return m_identity; }
const QString& responderDescription() const override { return m_description; }
void setResponderDescription(const QString& desc) override { m_description = desc; }
// Chain - override in subclasses if needed
AC_Responder* parentResponder() override { return nullptr; }
AC_Responder* proxyResponder() override { return nullptr; }
// First responder - typically not needed for simple responders
bool acceptsFirstResponder() override { return false; }
bool becomeFirstResponder() override { return false; }
bool resignFirstResponder() override { return true; }
// Selection responder - typically not needed for simple responders
bool acceptsSelectionResponder() override { return false; }
bool becomeSelectionResponder() override { return false; }
bool resignSelectionResponder() override { return true; }
// Action handling - override perform() in subclasses
AC_Result perform(AC_ActionInfo* /*info*/) override { return AC_Result::NotHandled; }
AC_Result performDownToChildren(AC_ActionInfo* /*info*/) override { return AC_Result::NotHandled; }
// Messages
bool shouldReceiveMessages() const override { return true; }
bool handleShortcuts() const override { return true; }
// Events
AC_Result handleEvent(QEvent* /*event*/) override { return AC_Result::NotHandled; }
// Manager
AC_Manager* actionManager() const override { return m_manager; }
void setActionManager(AC_Manager* manager) { m_manager = manager; }
protected:
QString m_identity;
QString m_description;
AC_Manager* m_manager;
};
/**
* @brief Initialization parameters for AC_ManagerImpl constructor
*
* sizeof(AC_ManagerInitParams) = 0x20 (32 bytes) on x64
*/
struct AC_ManagerInitParams {
void* keywords; ///< +0x00: Pointer to keywords QList<QString>
void* keywordsEnd; ///< +0x08: End pointer for keywords
void* keywordsCapacity; ///< +0x10: Capacity pointer for keywords
bool trimShortcuts; ///< +0x18: Initial value for TrimShortcuts option
};
/**
* @brief Abstract base class for action/command management
*
* AC_Manager is a pure virtual interface that defines the contract for
* the action management system. The concrete implementation is AC_ManagerImpl.
*
* Key responsibilities:
* - Responder chain management for first responder and selection responder
* - Menu and toolbar creation from XML definitions
* - Action triggering and validation
* - Shortcut/keyboard event handling
* - Image/icon loading for UI elements
*
* vtable at 0x18004e508 (76 virtual methods)
*/
class AC_Manager {
public:
virtual ~AC_Manager() = 0;
// =========================================================================
// Image/Icon Management
// =========================================================================
/**
* @brief Add a directory to search for images
* @param dir Directory path to add
*/
virtual void addImageDir(const QString& dir) = 0;
/**
* @brief Add multiple image directories from a path string
* @param dirs Semicolon-separated directory paths
*/
virtual void addImageDirs(const QString& dirs) = 0;
/**
* @brief Find an image file by name
* @param name Image name to find
* @return Full path to the image, or empty string if not found
*/
virtual QString findImage(const QString& name) = 0;
/**
* @brief Load an icon with optional color blending
* @param name Icon name to load
* @param blendColor Color to blend with the icon
* @param useGeneric If true, fall back to generic image if not found
* @return Loaded QIcon
*/
virtual QIcon loadImage(const QString& name, const QColor& blendColor, bool useGeneric) = 0;
/**
* @brief Create a QAction-compatible icon
* @param icon Source icon
* @return Icon suitable for use with QAction
*/
virtual QIcon createQActionCompatibleIcon(const QIcon& icon) = 0;
/**
* @brief Set the generic/fallback image name
* @param name Name of the generic image
*/
virtual void setGenericImage(const QString& name) = 0;
// =========================================================================
// Identity and Options
// =========================================================================
/**
* @brief Generate a unique identity string
* @return Unique identifier in format "__uuid_%1_%2__"
*/
virtual QString generateIdentity() = 0;
/**
* @brief Get hover ID for current UI element
* @return Current hover identifier
*/
virtual QString hoverId() const = 0;
/**
* @brief Set hover ID
* @param id New hover identifier
*/
virtual void setHoverId(const QString& id) = 0;
/**
* @brief Get string option value
* @param name Option name
* @return Option value as string
*/
virtual QString option(const QString& name) const = 0;
/**
* @brief Get integer option value
* @param option Option enum value
* @return Option value as integer
*/
virtual int option(AC_ManagerOption option) const = 0;
/**
* @brief Set string option
* @param name Option name
* @param value Option value
* @return true if option was set successfully
*/
virtual bool setOption(const QString& name, const QString& value) = 0;
/**
* @brief Set integer option
* @param option Option enum value
* @param value Option value
* @return true if option was set successfully
*/
virtual bool setOption(AC_ManagerOption option, int value) = 0;
// =========================================================================
// Responder Management
// =========================================================================
/**
* @brief Get the application-level responder
* @return Application responder or nullptr
*/
virtual AC_Responder* applicationResponder() const = 0;
/**
* @brief Set the application-level responder
* @param responder New application responder
*/
virtual void setApplicationResponder(AC_Responder* responder) = 0;
/**
* @brief Get the current first responder
* @return First responder at top of stack, or nullptr
*/
virtual AC_Responder* firstResponder() const = 0;
/**
* @brief Set the first responder
* @param responder New first responder
* @return true if successfully set
*/
virtual bool setFirstResponder(AC_Responder* responder) = 0;
/**
* @brief Get the selection responder
* @return Current selection responder or nullptr
*/
virtual AC_Responder* selectionResponder() const = 0;
/**
* @brief Set the selection responder
* @param responder New selection responder
* @return true if successfully set
*/
virtual bool setSelectionResponder(AC_Responder* responder) = 0;
/**
* @brief Get the mouse responder (responder under mouse cursor)
* @return Mouse responder or nullptr
*/
virtual AC_Responder* mouseResponder() const = 0;
/**
* @brief Find responder by identity string
* @param identity Responder identity to find
* @return Responder or nullptr if not found
*/
virtual AC_Responder* responder(const QString& identity) const = 0;
/**
* @brief Find responder by C-string identity
* @param identity Responder identity to find
* @return Responder or nullptr if not found
*/
virtual AC_Responder* responder(const char* identity) const = 0;
/**
* @brief Find responder by identity list with fallback
* @param identities List of identities to try
* @param fallback Fallback responder if none found
* @return Found responder or fallback
*/
virtual AC_Responder* responder(const QList<QString>& identities, AC_Responder* fallback) const = 0;
/**
* @brief Get responder associated with a widget
* @param widget Widget to find responder for
* @return Associated responder or nullptr
*/
virtual AC_Responder* responderForWidget(QWidget* widget) const = 0;
/**
* @brief Register a responder
* @param responder Responder to register
* @param widget Associated widget (may be nullptr)
* @return true if successfully registered
*/
virtual bool registerResponder(AC_Responder* responder, QWidget* widget) = 0;
/**
* @brief Unregister a responder
* @param responder Responder to unregister
*/
virtual void unregisterResponder(AC_Responder* responder) = 0;
/**
* @brief Register a factory function to create responders for widgets
* @param widget Widget class to register factory for
* @param factory Function that creates AC_Responder for the widget
*/
virtual void registerResponderFactoryFnc(QWidget* widget,
AC_Responder* (*factory)(AC_Manager*, QWidget*)) = 0;
/**
* @brief Push a responder up the responder chain
* @param responder Responder to push
*/
virtual void pushUp(AC_Responder* responder) = 0;
/**
* @brief Push a responder out of the chain
* @param responder Responder to remove
*/
virtual void pushOut(AC_Responder* responder) = 0;
/**
* @brief Notify that selection was cleared on a responder
* @param responder Responder whose selection was cleared
*/
virtual void selectionCleared(AC_Responder* responder) = 0;
/**
* @brief Ignore a widget for responder purposes
* @param widget Widget to ignore
*/
virtual void ignoreWidget(QWidget* widget) = 0;
/**
* @brief Check if a widget is ignored
* @param widget Widget to check
* @param checkParents If true, also check parent widgets
* @return true if widget is ignored
*/
virtual bool isWidgetIgnored(QWidget* widget, bool checkParents) const = 0;
/**
* @brief Get all responder identities
* @return List of all registered responder identities
*/
virtual QList<QString> allResponderIdentities() const = 0;
/**
* @brief Get slot list for a responder
* @param identity Responder identity
* @param includeInherited Include inherited slots
* @return List of slot names
*/
virtual QList<QString> responderSlotList(const QString& identity, bool includeInherited) const = 0;
// =========================================================================
// Menu Management
// =========================================================================
/**
* @brief Get the main menu bar
* @return Main menu bar or nullptr
*/
virtual AC_Menu* menuBar() const = 0;
/**
* @brief Set the main menu bar
* @param menu New main menu bar
*/
virtual void setMenuBar(AC_Menu* menu) = 0;
/**
* @brief Create a menu bar from XML element
* @param element XML element defining the menu
* @param menuBar QMenuBar to populate
* @return Created AC_Menu
*/
virtual AC_Menu* createMenuBar(const QDomElement& element, QMenuBar* menuBar) = 0;
/**
* @brief Create a menu bar from XML element on a widget
* @param element XML element defining the menu
* @param parent Parent widget
* @return Created AC_Menu
*/
virtual AC_Menu* createMenuBar(const QDomElement& element, QWidget* parent) = 0;
/**
* @brief Create a menu bar from menu name
* @param name Menu name to load
* @param menuBar QMenuBar to populate
* @return Created AC_Menu
*/
virtual AC_Menu* createMenuBar(const QString& name, QMenuBar* menuBar) = 0;
/**
* @brief Create a menu bar from menu name on a widget
* @param name Menu name to load
* @param parent Parent widget
* @return Created AC_Menu
*/
virtual AC_Menu* createMenuBar(const QString& name, QWidget* parent) = 0;
/**
* @brief Create a popup menu from XML element
* @param element XML element defining the menu
* @param parent Parent widget
* @param owner Owner QObject for signal connections
* @return Created AC_Menu
*/
virtual AC_Menu* createPopupMenu(const QDomElement& element, QWidget* parent, QObject* owner) = 0;
/**
* @brief Create a popup menu from name
* @param name Menu name to load
* @param parent Parent widget
* @param owner Owner QObject
* @return Created AC_Menu
*/
virtual AC_Menu* createPopupMenu(const QString& name, QWidget* parent, QObject* owner) = 0;
/**
* @brief Create a popup menu with icons
* @param name Menu name to load
* @param parent Parent widget
* @param owner Owner QObject
* @return Created AC_Menu with icons
*/
virtual AC_Menu* createPopupMenuWithIcons(const QString& name, QWidget* parent, QObject* owner) = 0;
/**
* @brief Load menus from XML element
* @param element Root XML element containing menu definitions
*/
virtual void loadMenus(const QDomElement& element) = 0;
/**
* @brief Load menus from XML element with flags
* @param element Root XML element
* @param flags Loading flags
*/
virtual void loadMenus(const QDomElement& element, int flags) = 0;
/**
* @brief Load menus from file
* @param path Path to menu definition file
*/
virtual void loadMenus(const QString& path) = 0;
/**
* @brief Load plugin menus
* @param name Plugin name
* @param placeholders List of placeholder names
* @param element XML element with menu definitions
*/
virtual void loadPluginMenus(const QString& name, QList<QString>& placeholders,
const QDomElement& element) = 0;
/**
* @brief Get menu element by name
* @param name Menu name
* @return XML element for the menu
*/
virtual QDomElement menuElement(const QString& name) = 0;
// =========================================================================
// Toolbar Management
// =========================================================================
/**
* @brief Create a toolbar from XML element
* @param element XML element defining the toolbar
* @param ids Output list of item IDs (may be nullptr)
* @param mainWindow Main window to add toolbar to
* @param area Toolbar area (Qt::ToolBarArea)
* @param objectName Object name for the toolbar (may be nullptr)
* @param owner Owner QObject
* @return Created AC_Toolbar
*/
virtual AC_Toolbar* createToolbar(const QDomElement& element, QList<QString>* ids,
QMainWindow* mainWindow, int area,
const char* objectName, QObject* owner) = 0;
/**
* @brief Create a toolbar from name
* @param name Toolbar name to load
* @param ids Output list of item IDs
* @param mainWindow Main window
* @param area Toolbar area
* @param objectName Object name
* @param owner Owner QObject
* @return Created AC_Toolbar
*/
virtual AC_Toolbar* createToolbar(const QString& name, QList<QString>* ids,
QMainWindow* mainWindow, int area,
const char* objectName, QObject* owner) = 0;
/**
* @brief Create a multi-button toolbar item
* @param element XML element defining the multi-button
* @param container Container for the button
* @param parent Parent widget
* @return Created AC_ToolbarMultiButton
*/
virtual AC_ToolbarMultiButton* createToolbarMultiButton(const QDomElement& element,
AC_ContainerImpl* container,
QWidget* parent) = 0;
/**
* @brief Load toolbars from XML element
* @param element Root XML element
* @param ids Output list of loaded toolbar IDs
*/
virtual void loadToolbars(const QDomElement& element, QList<QString>& ids) = 0;
/**
* @brief Load toolbars from file
* @param path Path to toolbar definition file
* @param ids Output list of loaded toolbar IDs
*/
virtual void loadToolbars(const QString& path, QList<QString>& ids) = 0;
/**
* @brief Get toolbar element by name
* @param name Toolbar name
* @return XML element for the toolbar
*/
virtual QDomElement toolbarElement(const QString& name) = 0;
/**
* @brief Get toolbar item generator
* @return Current item generator or nullptr
*/
virtual AC_ToolbarItemGenerator* itemGenerator() const = 0;
/**
* @brief Set toolbar item generator
* @param generator New item generator
*/
virtual void setItemGenerator(AC_ToolbarItemGenerator* generator) = 0;
/**
* @brief Register a toolbar with the manager
* @param toolbar Toolbar to register
*/
virtual void registerToolbar(AC_ToolbarImpl* toolbar) = 0;
/**
* @brief Get toolbar customize button image name
* @return Image name for customize button
*/
virtual QString toolbarCustomizeImage() const = 0;
/**
* @brief Set toolbar customize button image
* @param name Image name
*/
virtual void setToolbarCustomizeImage(const QString& name) = 0;
/**
* @brief Update all toolbar states
*/
virtual void updateToolbars() = 0;
/**
* @brief Update toolbar tooltip text
*/
virtual void updateToolbarText() = 0;
// =========================================================================
// Shortcut/Keyboard Management
// =========================================================================
/**
* @brief Get the shortcut manager
* @return Shortcut manager or nullptr
*/
virtual AC_ShortcutManager* shortcutManager() const = 0;
/**
* @brief Set the shortcut manager
* @param manager New shortcut manager
*/
virtual void setShortcutManager(AC_ShortcutManager* manager) = 0;
/**
* @brief Load shortcuts from XML element
* @param element XML element with shortcut definitions
*/
virtual void loadShortcuts(const QDomElement& element) = 0;
/**
* @brief Load shortcuts from file
* @param path Path to shortcut definition file
*/
virtual void loadShortcuts(const QString& path) = 0;
/**
* @brief Get key code for a shortcut
* @param shortcut Shortcut name
* @return Qt key code
*/
virtual int keyCodeForShortcut(const QString& shortcut) const = 0;
/**
* @brief Get key sequence for a shortcut
* @param shortcut Shortcut name
* @return QKeySequence for the shortcut
*/
virtual QKeySequence keySequenceForShortcut(const QString& shortcut) const = 0;
/**
* @brief Check if a key event matches a shortcut
* @param shortcut Shortcut name
* @param event Key event to check
* @return true if event matches shortcut
*/
virtual bool isShortcut(const char* shortcut, QKeyEvent* event) const = 0;
/**
* @brief Handle a key event
* @param event Key event to handle
* @param isRelease true if this is a key release event
* @return Result indicating if event was handled
*/
virtual AC_Result handleKeyEvent(QKeyEvent* event, bool isRelease) = 0;
// =========================================================================
// Action Triggering and Validation
// =========================================================================
/**
* @brief Trigger an action by name
* @param responderIdentity Target responder identity
* @param actionName Action name to trigger
* @param forEachResponder If true, trigger on each matching responder
* @return Result of the action
*/
virtual AC_Result trigger(const QString& responderIdentity, const QString& actionName,
bool forEachResponder) = 0;
/**
* @brief Trigger an action with arguments
* @param responderIdentity Target responder identity
* @param actionName Action name to trigger
* @param args Action arguments
* @param forEachResponder If true, trigger on each matching responder
* @return Result of the action
*/
virtual AC_Result trigger(const QString& responderIdentity, const QString& actionName,
const std::vector<QVariant>& args, bool forEachResponder) = 0;
/**
* @brief Trigger an action on each matching responder
* @param responderIdentity Target responder identity
* @param actionName Action name to trigger
* @param forEachResponder Iteration flag
* @return Result of the action
*/
virtual AC_Result triggerForEach(const QString& responderIdentity, const QString& actionName,
bool forEachResponder) = 0;
/**
* @brief Trigger an action on each responder with arguments
* @param responderIdentity Target responder identity
* @param actionName Action name to trigger
* @param args Action arguments
* @param forEachResponder Iteration flag
* @return Result of the action
*/
virtual AC_Result triggerForEach(const QString& responderIdentity, const QString& actionName,
const std::vector<QVariant>& args, bool forEachResponder) = 0;
/**
* @brief Perform validation for an action
* @param responderIdentity Target responder identity
* @param actionName Action name to validate
* @param enabled Output: whether action is enabled
* @param checked Output: whether action is checked
* @return Result of validation
*/
virtual AC_Result performValidation(const QString& responderIdentity, const QString& actionName,
bool* enabled, bool* checked) = 0;
// =========================================================================
// Static Factory
// =========================================================================
/**
* @brief Create a responder for a widget
* @param manager AC_Manager instance
* @param widget Widget to create responder for
* @return Created responder or nullptr
*/
static AC_Responder* createResponderForWidget(AC_Manager* manager, QWidget* widget);
};
/**
* @brief Concrete implementation of AC_Manager
*
* AC_ManagerImpl inherits from QObject and AC_Manager, providing the
* actual implementation of the action management system.
*
* sizeof(AC_ManagerImpl) = 0x158 (344 bytes) on x64
*
* Memory layout:
* - +0x00: QObject (vptr + members)
* - +0x10: AC_Manager vptr
* - +0x18: QList<QString>* m_keywords (shared with init params)
* - +0x20: (keywords internal)
* - +0x28: (keywords internal)
* - +0x30: bool m_trimShortcuts
* - +0x38: Internal tree for responder name->list mapping
* - +0x48: Internal tree (continued)
* - +0x60: Internal tree for menus
* - +0x70: (menus continued)
* - +0x78: AC_ShortcutManager* m_shortcutManager
* - +0x80: (shortcut internal)
* - +0x88: QString m_hoverId
* - +0xA0: QString m_genericImage
* - +0xB8: QString m_toolbarCustomizeImage
* - +0xC8: Internal tree for toolbars
* - +0xD8: (toolbars continued)
* - +0xE0: std::vector<AC_Responder*> m_registeredResponders
* - +0xF8: std::vector<AC_Responder*> m_responderStack
* - +0x110: (responder stack continued)
* - +0x118: AC_Menu* m_menuBar
* - +0x120: AC_Responder* m_firstResponder (via stack)
* - +0x128: AC_Responder* m_applicationResponder
* - +0x130: AC_Responder* m_selectionResponder
* - +0x138: AC_ToolbarItemGenerator* m_itemGenerator
* - +0x140: int m_uniqueIdCounter
* - +0x144: int m_flags
* - +0x148: void* m_internalData
* - +0x150: bool m_option_trimShortcuts (at offset 304 from AC_Manager base)
*
* Signals:
* - firstResponderChanged()
* - selectionResponderChanged()
* - updateToolbarsSignal()
* - updateToolbarsText()
*/
class AC_ManagerImpl : public QObject, public AC_Manager {
Q_OBJECT
public:
/**
* @brief Construct AC_ManagerImpl with initialization parameters
* @param params Initialization parameters
*/
explicit AC_ManagerImpl(const AC_ManagerInitParams& params);
virtual ~AC_ManagerImpl() override;
// All AC_Manager virtual methods are implemented...
// See AC_Manager for documentation
// Additional non-virtual methods
/**
* @brief Get the keywords list
* @return Reference to keywords list
*/
const QList<QString>& keywords() const;
/**
* @brief Check if shortcuts should be trimmed
* @return true if trimming is enabled
*/
bool trimShortcuts() const;
/**
* @brief Check if a responder is registered
* @param responder Responder to check
* @return true if registered
*/
bool isRegistred(AC_Responder* responder) const;
/**
* @brief Get all responders matching identity list
* @param identities Identity list to match
* @param fallback Fallback responder
* @return Vector of matching responders
*/
std::vector<AC_Responder*> responders(const QList<QString>& identities,
AC_Responder* fallback) const;
/**
* @brief Get all responders matching single identity
* @param identity Identity to match
* @return Vector of matching responders
*/
std::vector<AC_Responder*> responders(const QString& identity) const;
/**
* @brief Normalize a string for comparison
* @param str String to normalize
* @return Normalized string
*/
static QString normalize(const QString& str);
signals:
/**
* @brief Emitted when the first responder changes
*/
void firstResponderChanged();
/**
* @brief Emitted when the selection responder changes
*/
void selectionResponderChanged();
/**
* @brief Emitted to signal toolbar update needed
*/
void updateToolbarsSignal();
/**
* @brief Emitted to signal toolbar text update needed
*/
void updateToolbarsText();
protected:
/**
* @brief Fire the first responder changed signal
*/
void fireFirstResponderChanged();
/**
* @brief Fire the selection responder changed signal
*/
void fireSelectionResponderChanged();
/**
* @brief Fire toolbar update signal
*/
void fireUpdateToolbars();
/**
* @brief Fire toolbar text update signal
*/
void fireUpdateToolbarText();
/**
* @brief Fire toolbar button clicked notification
* @param identity Button identity
*/
void fireToolbarButtonClicked(const QString& identity);
private slots:
/**
* @brief Handle ignored widget destruction
* @param object Destroyed object
*/
void ignoredWidgetDestroyed(QObject* object);
};
// ============================================================================
// Offset Constants (for reference/debugging)
// ============================================================================
namespace AC_ManagerImpl_Offsets {
// Offsets from AC_Manager base (this + 16 from QObject base)
constexpr size_t Keywords = 0x08; // 8 - QList<QString>* to keywords
constexpr size_t TrimShortcutsInit = 0x18; // 24 - Initial trimShortcuts value
constexpr size_t ResponderNameMap = 0x28; // 40 - Internal tree for name->responders
constexpr size_t MenuTree = 0x50; // 80 - Internal tree for menus
constexpr size_t ShortcutManager = 0x68; // 104 - AC_ShortcutManager*
constexpr size_t HoverId = 0x78; // 120 - QString m_hoverId
constexpr size_t GenericImage = 0x90; // 144 - QString m_genericImage
constexpr size_t ToolbarCustomizeImage = 0xA8; // 168 - QString m_toolbarCustomizeImage
constexpr size_t ToolbarTree = 0xB8; // 184 - Internal tree for toolbars
constexpr size_t RegisteredResponders = 0xD0; // 208 - std::vector<AC_Responder*>
constexpr size_t ResponderStack = 0xE8; // 232 - std::vector<AC_Responder*>
constexpr size_t MenuBar = 0x108; // 264 - AC_Menu*
constexpr size_t ApplicationResponder = 0x118; // 280 - AC_Responder*
constexpr size_t SelectionResponder = 0x120; // 288 - AC_Responder*
constexpr size_t ItemGenerator = 0x128; // 296 - AC_ToolbarItemGenerator*
constexpr size_t TrimShortcutsOption = 0x130; // 304 - bool (option value)
}