forked from qt-creator/qt-creator
Core: Introduce Menu and Action classes
Idea is to have a bit more "object { propertySetter }" kind of pattern for common cases and to couple actions and menus only via Ids, not real objects. In a LayoutBuilder context this might later look like Menu { id(BOOKMARKS_MENU), title(Tr::tr("&Bookmarks")), container(Core::Constants::M_TOOLS) } in the end. Overall line count increases but I claim it reduces complexity on the user code side. Change-Id: I166e0c8c6b3036430dc464fd652fb37ded21c09a Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -66,6 +66,165 @@ void PresentationModeHandler::showShortcutPopup(const QString &shortcut)
|
|||||||
Utils::FadingIndicator::showText(window, shortcut);
|
Utils::FadingIndicator::showText(window, shortcut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Core::Internal
|
||||||
|
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
class ActionPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void ensureCommand()
|
||||||
|
{
|
||||||
|
if (!command) {
|
||||||
|
QTC_ASSERT(actionId.isValid(), return);
|
||||||
|
QTC_ASSERT(!context.isEmpty(), return);
|
||||||
|
command = ActionManager::registerAction(&action, actionId, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction action;
|
||||||
|
Id actionId;
|
||||||
|
Context context;
|
||||||
|
Command *command = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
Action::Action()
|
||||||
|
: d(new ActionPrivate)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::~Action()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setText(const QString &text)
|
||||||
|
{
|
||||||
|
d->action.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setCommandAttribute(Command::CommandAttribute attr)
|
||||||
|
{
|
||||||
|
d->ensureCommand();
|
||||||
|
QTC_ASSERT(d->command, return);
|
||||||
|
d->command->setAttribute(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setContainer(Utils::Id containerId, Utils::Id groupId)
|
||||||
|
{
|
||||||
|
d->ensureCommand();
|
||||||
|
QTC_ASSERT(d->command, return);
|
||||||
|
if (containerId.isValid()) {
|
||||||
|
ActionContainer *container = ActionManager::actionContainer(containerId);
|
||||||
|
container->addAction(d->command, groupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setOnTriggered(const std::function<void ()> &func)
|
||||||
|
{
|
||||||
|
QObject::connect(&d->action, &QAction::triggered, &d->action, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setOnTriggered(QObject *guard, const std::function<void ()> &func)
|
||||||
|
{
|
||||||
|
QObject::connect(&d->action, &QAction::triggered, guard, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setDefaultKeySequence(const QKeySequence &seq)
|
||||||
|
{
|
||||||
|
d->ensureCommand();
|
||||||
|
QTC_ASSERT(d->command, return);
|
||||||
|
d->command->setDefaultKeySequence(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setDefaultKeySequence(const QString &mac, const QString &nonMac)
|
||||||
|
{
|
||||||
|
d->ensureCommand();
|
||||||
|
QTC_ASSERT(d->command, return);
|
||||||
|
d->command->setDefaultKeySequence(QKeySequence(useMacShortcuts ? mac : nonMac));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setIcon(const QIcon &icon)
|
||||||
|
{
|
||||||
|
d->action.setIcon(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setIconVisibleInMenu(bool on)
|
||||||
|
{
|
||||||
|
d->action.setIconVisibleInMenu(on);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setTouchBarIcon(const QIcon &icon)
|
||||||
|
{
|
||||||
|
d->ensureCommand();
|
||||||
|
QTC_ASSERT(d->command, return);
|
||||||
|
d->command->setTouchBarIcon(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setEnabled(bool on)
|
||||||
|
{
|
||||||
|
d->action.setEnabled(on);
|
||||||
|
}
|
||||||
|
|
||||||
|
Command *Action::command() const
|
||||||
|
{
|
||||||
|
d->ensureCommand();
|
||||||
|
QTC_CHECK(d->command);
|
||||||
|
return d->command;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setId(Id id)
|
||||||
|
{
|
||||||
|
d->actionId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setContext(Id id)
|
||||||
|
{
|
||||||
|
d->context = Context(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Action::setContext(const Context &context)
|
||||||
|
{
|
||||||
|
d->context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
|
||||||
|
ActionSeparator::ActionSeparator(Id id)
|
||||||
|
{
|
||||||
|
ActionContainer *container = ActionManager::actionContainer(id);
|
||||||
|
QTC_ASSERT(container, return);
|
||||||
|
container->addSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
|
||||||
|
Menu::Menu() = default;
|
||||||
|
|
||||||
|
void Menu::setId(Id id)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(!m_menu, return);
|
||||||
|
m_menu = ActionManager::createMenu(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::setTitle(const QString &title)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_menu, return);
|
||||||
|
m_menu->menu()->setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::setContainer(Id containerId, Id groupId)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_menu, return);
|
||||||
|
ActionContainer *container = ActionManager::actionContainer(containerId);
|
||||||
|
container->addMenu(m_menu, groupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::addSeparator()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_menu, return);
|
||||||
|
m_menu->addSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -536,3 +695,5 @@ void ActionManagerPrivate::saveSettings()
|
|||||||
saveSettings(j.value());
|
saveSettings(j.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Core
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAction;
|
class QAction;
|
||||||
class QString;
|
class QString;
|
||||||
@@ -29,6 +31,53 @@ class ICorePrivate;
|
|||||||
class MainWindow;
|
class MainWindow;
|
||||||
} // Internal
|
} // Internal
|
||||||
|
|
||||||
|
class CORE_EXPORT Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Action();
|
||||||
|
~Action();
|
||||||
|
|
||||||
|
void setId(Utils::Id id);
|
||||||
|
void setContext(const Utils::Id id);
|
||||||
|
void setContext(const Core::Context &context);
|
||||||
|
void setText(const QString &text);
|
||||||
|
void setCommandAttribute(Core::Command::CommandAttribute attr);
|
||||||
|
void setContainer(Utils::Id containerId, Utils::Id groupId = {});
|
||||||
|
void setOnTriggered(const std::function<void()> &func);
|
||||||
|
void setOnTriggered(QObject *guard, const std::function<void()> &func);
|
||||||
|
void setDefaultKeySequence(const QKeySequence &seq);
|
||||||
|
void setDefaultKeySequence(const QString &mac, const QString &nonMac);
|
||||||
|
void setIcon(const QIcon &icon);
|
||||||
|
void setIconVisibleInMenu(bool on);
|
||||||
|
void setTouchBarIcon(const QIcon &icon);
|
||||||
|
void setEnabled(bool on);
|
||||||
|
|
||||||
|
Command *command() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ActionPrivate *d = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CORE_EXPORT Menu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Menu();
|
||||||
|
|
||||||
|
void setId(Utils::Id id);
|
||||||
|
void setTitle(const QString &title);
|
||||||
|
void setContainer(Utils::Id containerId, Utils::Id groupId = {});
|
||||||
|
void addSeparator();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActionContainer *m_menu = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CORE_EXPORT ActionSeparator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActionSeparator(Utils::Id id);
|
||||||
|
};
|
||||||
|
|
||||||
class CORE_EXPORT ActionManager : public QObject
|
class CORE_EXPORT ActionManager : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@@ -86,12 +86,14 @@ public:
|
|||||||
BookmarkFilter m_bookmarkFilter{&m_bookmarkManager};
|
BookmarkFilter m_bookmarkFilter{&m_bookmarkManager};
|
||||||
BookmarkViewFactory m_bookmarkViewFactory{&m_bookmarkManager};
|
BookmarkViewFactory m_bookmarkViewFactory{&m_bookmarkManager};
|
||||||
|
|
||||||
QAction m_toggleAction{Tr::tr("Toggle Bookmark")};
|
Menu m_bookmarkMenu;
|
||||||
QAction m_editAction{Tr::tr("Edit Bookmark")};
|
Action m_toggleAction;
|
||||||
QAction m_prevAction{Tr::tr("Previous Bookmark")};
|
Action m_editAction;
|
||||||
QAction m_nextAction{Tr::tr("Next Bookmark")};
|
Action m_prevAction;
|
||||||
QAction m_docPrevAction{Tr::tr("Previous Bookmark in Document")};
|
Action m_nextAction;
|
||||||
QAction m_docNextAction{Tr::tr("Next Bookmark in Document")};
|
Action m_docPrevAction;
|
||||||
|
Action m_docNextAction;
|
||||||
|
|
||||||
QAction m_editBookmarkAction{Tr::tr("Edit Bookmark")};
|
QAction m_editBookmarkAction{Tr::tr("Edit Bookmark")};
|
||||||
QAction m_bookmarkMarginAction{Tr::tr("Toggle Bookmark")};
|
QAction m_bookmarkMarginAction{Tr::tr("Toggle Bookmark")};
|
||||||
|
|
||||||
@@ -113,66 +115,32 @@ public:
|
|||||||
|
|
||||||
TextEditorPluginPrivate::TextEditorPluginPrivate()
|
TextEditorPluginPrivate::TextEditorPluginPrivate()
|
||||||
{
|
{
|
||||||
ActionContainer *mtools = ActionManager::actionContainer(Core::Constants::M_TOOLS);
|
const Id bookmarkMenuId = "Bookmarks.Menu";
|
||||||
ActionContainer *touchBar = ActionManager::actionContainer(Core::Constants::TOUCH_BAR);
|
|
||||||
ActionContainer *mbm = ActionManager::createMenu(Id("Bookmarks.Menu"));
|
|
||||||
|
|
||||||
mbm->menu()->setTitle(Tr::tr("&Bookmarks"));
|
|
||||||
mtools->addMenu(mbm);
|
|
||||||
|
|
||||||
const Context editorManagerContext(Core::Constants::C_EDITORMANAGER);
|
const Context editorManagerContext(Core::Constants::C_EDITORMANAGER);
|
||||||
|
|
||||||
// Toggle
|
m_bookmarkMenu.setId(bookmarkMenuId);
|
||||||
Command *cmd = ActionManager::registerAction(&m_toggleAction, "Bookmarks.Toggle",
|
m_bookmarkMenu.setTitle(Tr::tr("&Bookmarks"));
|
||||||
editorManagerContext);
|
m_bookmarkMenu.setContainer(Core::Constants::M_TOOLS);
|
||||||
cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? Tr::tr("Meta+M") : Tr::tr("Ctrl+M")));
|
|
||||||
cmd->setTouchBarIcon(Icons::MACOS_TOUCHBAR_BOOKMARK.icon());
|
|
||||||
mbm->addAction(cmd);
|
|
||||||
touchBar->addAction(cmd, Core::Constants::G_TOUCHBAR_EDITOR);
|
|
||||||
|
|
||||||
cmd = ActionManager::registerAction(&m_editAction, "Bookmarks.Edit", editorManagerContext);
|
m_toggleAction.setId("Bookmarks.Toggle");
|
||||||
cmd->setDefaultKeySequence(
|
m_toggleAction.setContext(editorManagerContext);
|
||||||
QKeySequence(useMacShortcuts ? Tr::tr("Meta+Shift+M") : Tr::tr("Ctrl+Shift+M")));
|
m_toggleAction.setText(Tr::tr("Toggle Bookmark"));
|
||||||
mbm->addAction(cmd);
|
m_toggleAction.setDefaultKeySequence(Tr::tr("Meta+M"), Tr::tr("Ctrl+M"));
|
||||||
|
m_toggleAction.setTouchBarIcon(Icons::MACOS_TOUCHBAR_BOOKMARK.icon());
|
||||||
mbm->addSeparator();
|
m_toggleAction.setContainer(bookmarkMenuId);
|
||||||
|
m_toggleAction.setOnTriggered(this, [this] {
|
||||||
// Previous
|
|
||||||
m_prevAction.setIcon(Icons::PREV_TOOLBAR.icon());
|
|
||||||
m_prevAction.setIconVisibleInMenu(false);
|
|
||||||
cmd = ActionManager::registerAction(&m_prevAction, BOOKMARKS_PREV_ACTION, editorManagerContext);
|
|
||||||
cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? Tr::tr("Meta+,")
|
|
||||||
: Tr::tr("Ctrl+,")));
|
|
||||||
mbm->addAction(cmd);
|
|
||||||
|
|
||||||
// Next
|
|
||||||
m_nextAction.setIcon(Icons::NEXT_TOOLBAR.icon());
|
|
||||||
m_nextAction.setIconVisibleInMenu(false);
|
|
||||||
cmd = ActionManager::registerAction(&m_nextAction, BOOKMARKS_NEXT_ACTION, editorManagerContext);
|
|
||||||
cmd->setDefaultKeySequence(QKeySequence(useMacShortcuts ? Tr::tr("Meta+.")
|
|
||||||
: Tr::tr("Ctrl+.")));
|
|
||||||
mbm->addAction(cmd);
|
|
||||||
|
|
||||||
mbm->addSeparator();
|
|
||||||
|
|
||||||
// Previous Doc
|
|
||||||
cmd = ActionManager::registerAction(&m_docPrevAction, "Bookmarks.PreviousDocument",
|
|
||||||
editorManagerContext);
|
|
||||||
mbm->addAction(cmd);
|
|
||||||
|
|
||||||
// Next Doc
|
|
||||||
cmd = ActionManager::registerAction(&m_docNextAction, "Bookmarks.NextDocument",
|
|
||||||
editorManagerContext);
|
|
||||||
mbm->addAction(cmd);
|
|
||||||
|
|
||||||
connect(&m_toggleAction, &QAction::triggered, this, [this] {
|
|
||||||
IEditor *editor = EditorManager::currentEditor();
|
IEditor *editor = EditorManager::currentEditor();
|
||||||
auto widget = TextEditorWidget::fromEditor(editor);
|
auto widget = TextEditorWidget::fromEditor(editor);
|
||||||
if (widget && editor && !editor->document()->isTemporary())
|
if (widget && editor && !editor->document()->isTemporary())
|
||||||
m_bookmarkManager.toggleBookmark(editor->document()->filePath(), editor->currentLine());
|
m_bookmarkManager.toggleBookmark(editor->document()->filePath(), editor->currentLine());
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&m_editAction, &QAction::triggered, this, [this] {
|
m_editAction.setId("Bookmarks.Edit");
|
||||||
|
m_editAction.setContext(editorManagerContext);
|
||||||
|
m_editAction.setText(Tr::tr("Edit Bookmark"));
|
||||||
|
m_editAction.setDefaultKeySequence(Tr::tr("Meta+Shift+M"), Tr::tr("Ctrl+Shift+M"));
|
||||||
|
m_editAction.setContainer(bookmarkMenuId);
|
||||||
|
m_editAction.setOnTriggered(this, [this] {
|
||||||
IEditor *editor = EditorManager::currentEditor();
|
IEditor *editor = EditorManager::currentEditor();
|
||||||
auto widget = TextEditorWidget::fromEditor(editor);
|
auto widget = TextEditorWidget::fromEditor(editor);
|
||||||
if (widget && editor && !editor->document()->isTemporary()) {
|
if (widget && editor && !editor->document()->isTemporary()) {
|
||||||
@@ -184,12 +152,39 @@ TextEditorPluginPrivate::TextEditorPluginPrivate()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&m_prevAction, &QAction::triggered, &m_bookmarkManager, &BookmarkManager::prev);
|
m_bookmarkMenu.addSeparator();
|
||||||
connect(&m_nextAction, &QAction::triggered, &m_bookmarkManager, &BookmarkManager::next);
|
|
||||||
connect(&m_docPrevAction, &QAction::triggered,
|
m_prevAction.setId(BOOKMARKS_PREV_ACTION);
|
||||||
&m_bookmarkManager, &BookmarkManager::prevInDocument);
|
m_prevAction.setContext(editorManagerContext);
|
||||||
connect(&m_docNextAction, &QAction::triggered,
|
m_prevAction.setText(Tr::tr("Previous Bookmark"));
|
||||||
&m_bookmarkManager, &BookmarkManager::nextInDocument);
|
m_prevAction.setDefaultKeySequence(Tr::tr("Meta+,"), Tr::tr("Ctrl+,"));
|
||||||
|
m_prevAction.setContainer(bookmarkMenuId);
|
||||||
|
m_prevAction.setIcon(Icons::PREV_TOOLBAR.icon());
|
||||||
|
m_prevAction.setIconVisibleInMenu(false);
|
||||||
|
m_prevAction.setOnTriggered(this, [this] { m_bookmarkManager.prev(); });
|
||||||
|
|
||||||
|
m_nextAction.setId(BOOKMARKS_NEXT_ACTION);
|
||||||
|
m_nextAction.setContext(editorManagerContext);
|
||||||
|
m_nextAction.setText(Tr::tr("Next Bookmark"));
|
||||||
|
m_nextAction.setIcon(Icons::NEXT_TOOLBAR.icon());
|
||||||
|
m_nextAction.setIconVisibleInMenu(false);
|
||||||
|
m_nextAction.setDefaultKeySequence(Tr::tr("Meta+."), Tr::tr("Ctrl+."));
|
||||||
|
m_nextAction.setContainer(bookmarkMenuId);
|
||||||
|
m_nextAction.setOnTriggered(this, [this] { m_bookmarkManager.next(); });
|
||||||
|
|
||||||
|
m_bookmarkMenu.addSeparator();
|
||||||
|
|
||||||
|
m_docPrevAction.setId("Bookmarks.PreviousDocument");
|
||||||
|
m_docPrevAction.setContext(editorManagerContext);
|
||||||
|
m_docPrevAction.setText(Tr::tr("Previous Bookmark in Document"));
|
||||||
|
m_docPrevAction.setContainer(bookmarkMenuId);
|
||||||
|
m_docPrevAction.setOnTriggered(this, [this] { m_bookmarkManager.prevInDocument(); });
|
||||||
|
|
||||||
|
m_docNextAction.setId("Bookmarks.NextDocument");
|
||||||
|
m_docNextAction.setContext(Core::Constants::C_EDITORMANAGER);
|
||||||
|
m_docNextAction.setText(Tr::tr("Next Bookmark in Document"));
|
||||||
|
m_docNextAction.setContainer(bookmarkMenuId);
|
||||||
|
m_docNextAction.setOnTriggered(this, [this] { m_bookmarkManager.nextInDocument(); });
|
||||||
|
|
||||||
connect(&m_editBookmarkAction, &QAction::triggered, this, [this] {
|
connect(&m_editBookmarkAction, &QAction::triggered, this, [this] {
|
||||||
m_bookmarkManager.editByFileAndLine(m_marginActionFileName, m_marginActionLineNumber);
|
m_bookmarkManager.editByFileAndLine(m_marginActionFileName, m_marginActionLineNumber);
|
||||||
@@ -203,11 +198,14 @@ TextEditorPluginPrivate::TextEditorPluginPrivate()
|
|||||||
m_bookmarkManager.toggleBookmark(m_marginActionFileName, m_marginActionLineNumber);
|
m_bookmarkManager.toggleBookmark(m_marginActionFileName, m_marginActionLineNumber);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ActionContainer *touchBar = ActionManager::actionContainer(Core::Constants::TOUCH_BAR);
|
||||||
|
touchBar->addAction(m_toggleAction.command(), Core::Constants::G_TOUCHBAR_EDITOR);
|
||||||
|
|
||||||
// EditorManager
|
// EditorManager
|
||||||
connect(EditorManager::instance(), &EditorManager::editorAboutToClose,
|
connect(EditorManager::instance(), &EditorManager::editorAboutToClose,
|
||||||
this, &TextEditorPluginPrivate::editorAboutToClose);
|
this, &TextEditorPluginPrivate::editorAboutToClose);
|
||||||
connect(EditorManager::instance(), &EditorManager::editorOpened,
|
connect(EditorManager::instance(), &EditorManager::editorOpened,
|
||||||
this, &TextEditorPluginPrivate::editorOpened);
|
this, &TextEditorPluginPrivate::editorOpened);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorPluginPrivate::updateActions(bool enableToggle, int state)
|
void TextEditorPluginPrivate::updateActions(bool enableToggle, int state)
|
||||||
|
Reference in New Issue
Block a user