Для подготовки этого поста я, как и раньше, использовал доку от VCreate Logic, только в этот раз материал переработан в гораздо большей степени.
Работа с меню
Нам нужно уметь делать несколько вещей:
Работа с меню
Нам нужно уметь делать несколько вещей:
- добавлять пункт меню в сушествующее меню Qt Creator (например, Help)
- добавлять меню в менюбар Qt Creator
- добавлять пункт меню в новое меню
- регистрировать новые меню и пункты меню
- обрабатывать вызов меню и пункта меню
Для демонстрации возьмем плагин DoNothing, который мы начали создавать в части 1 этой серии. Меню и пункты меню будем создавать в методе DoNothing::initialize(), поскольку это часть инициализации плагина. Сначала создадим пункт меню About DoNothing в меню Help, перед пунктом About Plugins, затем создадим новое меню DoNothing c единственным пунктом About DoNothing:
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
// The initialize() method is called when Qt Creator wants the plugin to initialize itself. This function is ideally used to initialize the internal state of the plugin and register actions/objects with Qt Creator.
// The function is called after all the dependencies of this plugin have been loaded.
Q_UNUSED(args);
Q_UNUSED(errMsg);
createMenuItems();
createMenus();
// Return true signifying that the initialization was successful.
// If the initialization was unsuccessful (for some wired reason); the errMsg string should be set to a human readable error message.
return true;
}
{
// The initialize() method is called when Qt Creator wants the plugin to initialize itself. This function is ideally used to initialize the internal state of the plugin and register actions/objects with Qt Creator.
// The function is called after all the dependencies of this plugin have been loaded.
Q_UNUSED(args);
Q_UNUSED(errMsg);
createMenuItems();
createMenus();
// Return true signifying that the initialization was successful.
// If the initialization was unsuccessful (for some wired reason); the errMsg string should be set to a human readable error message.
return true;
}
Вся работа с меню строится на использовании классов QMenu, QMenuBar, QAction, и нескольких классов Core:
- Core::ActionManager
- Core::ActionContainer
- Core::Command
ActionManager отвечает за регистрацию меню, пунктов меню и горячих клавиш.
ActionContainer представляет собой меню или менюбар. Экземпляры ActionContainer никогда не создаются напрямую, только с помощью ActionManager::createMenu(), ActionManager::createMenuBar(). Получить существующее меню можно через ActionManger, используя константы Core::Constants (M_FILE, M_FILE_NEW,... M_HELP).
Core::Command представляет такие действия как выбор пункта меню, нажатие кнопки или горячей клавиши. Экземпляры Core::Command также не создаются напрямую, вместо этого используются вызовы ActionManager::registerAction() для регистрации действия и получения команды. Объект Command представляет видимое для пользователя действие и его свойства.
Еще два слова об ActionManager::registerAction(). Этот метод регистрирует наши новые меню и пункты меню в ActionManager. Что, помимо прочих вещей, позволяет определять горячие клавиши на них (см. Tools->Options->Environment->Keyboard).
Поскольку все пункты меню являются QAction, их сигналы triggered(bool) или toggled(bool) связываются с нашим обработчиком посредством connect(). Подробности см. в коде.
Далее мы рассмотрим два метода- CreateMenuItems() и CreateMenus(). Полностью код плагина приведен в конце поста.
Добавляем пункт меню в сушествующее меню Qt Creator
Добавить пункт меню можно как в начало меню, так и в середину. Добиться первого можно с помощью вызова метода Core::ActionContainer::addAction(), а второго- с помощью вызова метода QMenu::insertAction().
insertAction() в качестве первого параметра получает пункт уже существующего меню (указатель на QAction), перед которым надо добавить новый пункт меню. Ну а новый пункт меню (опять же указатель на QAction) передается во втором параметре.
Приведенный внизу код содержит оба метода. Мы добавим два новых пункта в меню Help- About DoNothing и About DoNothing 2:
void DoNothingPlugin::createMenuItems()
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a command for "About DoNothing"
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothingItem", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd->action()->setText("About DoNothing");
// Add the command "Do Nothing" in the beginning of Help menu
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);
// Since menu-items are QActions, we can connect to their triggered(bool) or
// toggled(bool) signal and respond to trigger/toggled events
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a command for "About DoNothing 2"
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2Item", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing 2" item before "About Plugins..."
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QAction* aboutPluginsAction = am->command(Core::Constants::ABOUT_PLUGINS)->action();
helpMenu->insertAction(aboutPluginsAction, cmd2->action());
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a command for "About DoNothing"
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothingItem", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd->action()->setText("About DoNothing");
// Add the command "Do Nothing" in the beginning of Help menu
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);
// Since menu-items are QActions, we can connect to their triggered(bool) or
// toggled(bool) signal and respond to trigger/toggled events
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a command for "About DoNothing 2"
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2Item", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing 2" item before "About Plugins..."
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QAction* aboutPluginsAction = am->command(Core::Constants::ABOUT_PLUGINS)->action();
helpMenu->insertAction(aboutPluginsAction, cmd2->action());
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
Добавляем новое меню в Qt Creator
Новое меню можно добававить либо в начало менюбара, либо где-нибудь в середину. Аналогично с пунктом меню, существуют методы Core::ActionContainer::addMenu() и QMenuBar::insertMenu().
isertMenu(), как и insertAction(), в качестве первого параметра получает указатель на QActon, который является меню, перед которым надо добавить наше новое меню. Как и раньше, указатель на новое передается во втором параметре.
Мы создадим два меню- в самом начале менюбара и перед меню Help:
void DoNothingPlugin::createMenus()
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle(tr("DoNothing"));
// Create a command for "About DoNothing".
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing", QList<int>() << 0);
cmd->action()->setText("About DoNothing");
// Add DoNothing menu to the beginning of the menu bar
am->actionContainer(Core::Constants::MENU_BAR)->addMenu(ac);
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
// Connect the action
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a DoNothing2 menu
Core::ActionContainer* ac2 = am->createMenu("DoNothingPlugin.DoNothing2Menu");
ac2->menu()->setTitle(tr("DoNothing2"));
// Create a command for "About DoNothing 2".
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2", QList<int>() << 0);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing" menu between "Window" and "Help".
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QMenuBar* menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(helpMenu->menuAction(), ac2->menu());
// Add the "About DoNothing 2" action to the DoNothing2 menu
ac2->addAction(cmd2);
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle(tr("DoNothing"));
// Create a command for "About DoNothing".
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing", QList<int>() << 0);
cmd->action()->setText("About DoNothing");
// Add DoNothing menu to the beginning of the menu bar
am->actionContainer(Core::Constants::MENU_BAR)->addMenu(ac);
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
// Connect the action
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a DoNothing2 menu
Core::ActionContainer* ac2 = am->createMenu("DoNothingPlugin.DoNothing2Menu");
ac2->menu()->setTitle(tr("DoNothing2"));
// Create a command for "About DoNothing 2".
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2", QList<int>() << 0);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing" menu between "Window" and "Help".
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QMenuBar* menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(helpMenu->menuAction(), ac2->menu());
// Add the "About DoNothing 2" action to the DoNothing2 menu
ac2->addAction(cmd2);
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
Код плагина
donothingplugin.h:
#ifndef DONOTHINGPLUGIN_H
#define DONOTHINGPLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private:
void createMenus();
void createMenuItems();
private slots:
void about();
};
#endif // DONOTHINGPLUGIN_H
#define DONOTHINGPLUGIN_H
#include <extensionsystem/iplugin.h>
class DoNothingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
DoNothingPlugin();
~DoNothingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
private:
void createMenus();
void createMenuItems();
private slots:
void about();
};
#endif // DONOTHINGPLUGIN_H
donothingplugin.cpp
#include "donothingplugin.h"
#include <QtPlugin>
#include <QStringList>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <QtGui/QMessageBox>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
// The initialize() method is called when Qt Creator wants the plugin to initialize itself. This function is ideally used to initialize the internal state of the plugin and register actions/objects with Qt Creator.
// The function is called after all the dependencies of this plugin have been loaded.
Q_UNUSED(args);
Q_UNUSED(errMsg);
createMenuItems();
createMenus();
// Return true signifying that the initialization was successful.
// If the initialization was unsuccessful (for some wired reason); the errMsg string should be set to a human readable error message.
return true;
}
void DoNothingPlugin::extensionsInitialized()
{
// The extensionsInitialized() method is called after this plugin has been initialized (ie. after initialize() method has been called). This method is called on plugins that depend on this plugin first.
// Do nothing
}
void DoNothingPlugin::shutdown()
{
//The shutdown() method is called when the plugin is about to be unloaded.
// Do nothing
}
void DoNothingPlugin::createMenuItems()
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a command for "About DoNothing"
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothingItem", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd->action()->setText("About DoNothing");
// Add the command "Do Nothing" in the beginning of Help menu
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);
// Since menu-items are QActions, we can connect to their triggered(bool) or
// toggled(bool) signal and respond to trigger/toggled events
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a command for "About DoNothing 2"
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2Item", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing 2" item before "About Plugins..."
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QAction* aboutPluginsAction = am->command(Core::Constants::ABOUT_PLUGINS)->action();
helpMenu->insertAction(aboutPluginsAction, cmd2->action());
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
void DoNothingPlugin::createMenus()
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle(tr("DoNothing"));
// Create a command for "About DoNothing".
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing", QList<int>() << 0);
cmd->action()->setText("About DoNothing");
// Add DoNothing menu to the beginning of the menu bar
am->actionContainer(Core::Constants::MENU_BAR)->addMenu(ac);
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
// Connect the action
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a DoNothing2 menu
Core::ActionContainer* ac2 = am->createMenu("DoNothingPlugin.DoNothing2Menu");
ac2->menu()->setTitle(tr("DoNothing2"));
// Create a command for "About DoNothing 2".
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2", QList<int>() << 0);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing" menu between "Window" and "Help".
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QMenuBar* menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(helpMenu->menuAction(), ac2->menu());
// Add the "About DoNothing 2" action to the DoNothing2 menu
ac2->addAction(cmd2);
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
void DoNothingPlugin::about()
{
QMessageBox::information(0, "About DoNothing Plugin", "Seriously dude, this plugin does nothing", QMessageBox::Ok);
}
// export the plugin class
Q_EXPORT_PLUGIN(DoNothingPlugin)
#include <QtPlugin>
#include <QStringList>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
#include <QtGui/QMessageBox>
DoNothingPlugin::DoNothingPlugin()
{
// Do nothing
}
DoNothingPlugin::~DoNothingPlugin()
{
// Do notning
}
bool DoNothingPlugin::initialize(const QStringList& args, QString *errMsg)
{
// The initialize() method is called when Qt Creator wants the plugin to initialize itself. This function is ideally used to initialize the internal state of the plugin and register actions/objects with Qt Creator.
// The function is called after all the dependencies of this plugin have been loaded.
Q_UNUSED(args);
Q_UNUSED(errMsg);
createMenuItems();
createMenus();
// Return true signifying that the initialization was successful.
// If the initialization was unsuccessful (for some wired reason); the errMsg string should be set to a human readable error message.
return true;
}
void DoNothingPlugin::extensionsInitialized()
{
// The extensionsInitialized() method is called after this plugin has been initialized (ie. after initialize() method has been called). This method is called on plugins that depend on this plugin first.
// Do nothing
}
void DoNothingPlugin::shutdown()
{
//The shutdown() method is called when the plugin is about to be unloaded.
// Do nothing
}
void DoNothingPlugin::createMenuItems()
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a command for "About DoNothing"
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothingItem", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd->action()->setText("About DoNothing");
// Add the command "Do Nothing" in the beginning of Help menu
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);
// Since menu-items are QActions, we can connect to their triggered(bool) or
// toggled(bool) signal and respond to trigger/toggled events
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a command for "About DoNothing 2"
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2Item", QList<int>() << Core::Constants::C_GLOBAL_ID);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing 2" item before "About Plugins..."
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QAction* aboutPluginsAction = am->command(Core::Constants::ABOUT_PLUGINS)->action();
helpMenu->insertAction(aboutPluginsAction, cmd2->action());
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
void DoNothingPlugin::createMenus()
{
// Fetch the action manager
Core::ActionManager* am = Core::ICore::instance()->actionManager();
// Create a DoNothing menu
Core::ActionContainer* ac = am->createMenu("DoNothingPlugin.DoNothingMenu");
ac->menu()->setTitle(tr("DoNothing"));
// Create a command for "About DoNothing".
Core::Command* cmd = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing", QList<int>() << 0);
cmd->action()->setText("About DoNothing");
// Add DoNothing menu to the beginning of the menu bar
am->actionContainer(Core::Constants::MENU_BAR)->addMenu(ac);
// Add the "About DoNothing" action to the DoNothing menu
ac->addAction(cmd);
// Connect the action
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
// Create a DoNothing2 menu
Core::ActionContainer* ac2 = am->createMenu("DoNothingPlugin.DoNothing2Menu");
ac2->menu()->setTitle(tr("DoNothing2"));
// Create a command for "About DoNothing 2".
Core::Command* cmd2 = am->registerAction(new QAction(this), "DoNothingPlugin.AboutDoNothing2", QList<int>() << 0);
cmd2->action()->setText("About DoNothing 2");
// Insert the "DoNothing" menu between "Window" and "Help".
QMenu* helpMenu = am->actionContainer(Core::Constants::M_HELP)->menu();
QMenuBar* menuBar = am->actionContainer(Core::Constants::MENU_BAR)->menuBar();
menuBar->insertMenu(helpMenu->menuAction(), ac2->menu());
// Add the "About DoNothing 2" action to the DoNothing2 menu
ac2->addAction(cmd2);
// Connect the action
connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(about()));
}
void DoNothingPlugin::about()
{
QMessageBox::information(0, "About DoNothing Plugin", "Seriously dude, this plugin does nothing", QMessageBox::Ok);
}
// export the plugin class
Q_EXPORT_PLUGIN(DoNothingPlugin)
А как заставить записываться например в плагине редактора кода без диалогового окна ?
ОтветитьУдалитьКак горячие клавиши сразу устанавливать при регистрации действия в registerAction()? Не знаю пока. Нужно сырцы других плагинов посмотреть. Как найду, проапдейчу.
ОтветитьУдалитьВ нужной команде определяем последовательность по умолчанию перед тем как добавить/вставить команду. Т.е. вот так:
ОтветитьУдалитьcmd->setDefaultKeySequence(QKeySequence(tr("Alt+N")));
am->actionContainer(Core::Constants::M_HELP)->addAction(cmd);