\qt-creator-opensource-src-4.8.2\src\plugins\coreplugin\modemanager.h有C++类ModeManager的定义:
class CORE_EXPORT ModeManager : public QObject
{
Q_OBJECT
public:
static QObject *instance();
static IMode *currentMode();
static IMode *mode(Id id);
static void addAction(QAction *action, int priority);
Internal::FancyTabWidget *m_modeStack;//IDE左边整个竖条部分,包括左上方和左下方的工具栏
Internal::FancyActionBar *m_actionBar;//IDE左下方的工具栏
一、怎么添加左下方工具栏按钮?
构造函数初始化了m_actionBar,这个Bar就是指IDE左下方的工具栏。默认有运行,调试和构建三个按钮。
ModeManager::ModeManager(Internal::MainWindow *mainWindow,
Internal::FancyTabWidget *modeStack)
{
m_instance = this;
d = new ModeManagerPrivate();
d->m_mainWindow = mainWindow;
d->m_modeStack = modeStack;
d->m_oldCurrent = -1;
d->m_actionBar = new Internal::FancyActionBar(modeStack);
d->m_modeStack->addCornerWidget(d->m_actionBar);
那我们如何添加自定义按钮呢?ModeManager的addAction就是实现添加IDE左边工具栏的函数。
语句d->m_actionBar->insertAction(index, action);是关键。
void ModeManager::addAction(QAction *action, int priority)
{
d->m_actions.insert(action, priority);
// Count the number of commands with a higher priority
int index = 0;
foreach (int p, d->m_actions) {
if (p > priority)
++index;
}
d->m_actionBar->insertAction(index, action);
}
\src\plugins\coreplugin\fancyactionbar.cpp有函数实现:
void FancyActionBar::insertAction(int index, QAction *action)
{
auto *button = new FancyToolButton(action, this);
button->setIconsOnly(m_iconsOnly);
m_actionsLayout->insertWidget(index, button);
}
自定义工具栏时,就需要在外部调用Core::ModeManager::addAction(act, p);来添加按钮。如图所示:
二、那么,左上方的<欢迎,编辑,Debug,项目和帮助>这几个按钮又是怎么来的呢?
看源码:Internal::FancyTabWidget *m_modeStack;//IDE左边整个竖条部分,包括左上方和左下方的工具栏
函数void ModeManagerPrivate::appendMode(IMode *mode)里面的m_modeStack->insertTab负责添加tab选项;
void ModeManagerPrivate::appendMode(IMode *mode)
{
const int index = m_modeCommands.count();
m_mainWindow->addContextObject(mode);
m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(),
mode->menu() != nullptr);
m_modeStack->setTabEnabled(index, mode->isEnabled());
FancyTabWidget::insertTab再添加widget;
void FancyTabWidget::insertTab(int index, QWidget *tab, const QIcon &icon, const QString &label, bool hasMenu)
{
m_modesStack->insertWidget(index, tab);
m_tabBar->insertTab(index, icon, label, hasMenu);
}
我们看到,m_modeStack->insertTab(index, mode->widget(), mode->icon(), mode->displayName(), mode->menu() != nullptr);
这里的mode是什么东东?
\src\plugins\coreplugin\imode.h有定义
class CORE_EXPORT IMode : public IContext
以下是关联的调用关系,外部初始化IMode时,就会addMode:
IMode::IMode(QObject *parent) : IContext(parent)
{
ModeManager::instance()->addMode(this);
}
void ModeManager::addMode(IMode *mode)
{
QTC_ASSERT(d->m_startingUp, return);
d->m_modes.append(mode);
}
最后,我们再追溯一下前面提到的void ModeManagerPrivate::appendMode(IMode *mode)是哪里调用的?
我们挨个函数挨个函数的向源头追溯,得知:
void ModeManagerPrivate::extensionsInitializedHelper()
{
for (IMode *mode : m_modes)
appendMode(mode);
ModeManager::extensionsInitialized()
void ModeManager::extensionsInitialized()
{
d->extensionsInitializedHelper();
}
MainWindow::extensionsInitialized()
void MainWindow::extensionsInitialized()
{
ModeManager::extensionsInitialized();
void CorePlugin::extensionsInitialized()
void CorePlugin::extensionsInitialized()
{
m_mainWindow->extensionsInitialized();
最后的void CorePlugin::extensionsInitialized(),在
class EXTENSIONSYSTEM_EXPORT IPlugin类的定义是纯虚函数,需要用户在外部自己实现。
virtual void extensionsInitialized() = 0;
以上就是Qt Creator插件的实现原理。
三、早期的Qt Creator版本在插件接口定义上有不同之处,比如Qt Creator 3.2源码ModeManager有addWidget函数。
class CORE_EXPORT ModeManager : public QObject
{
static void addWidget(QWidget *widget);
通过addWidget函数可以实现如下效果:
以下源码从开源项目摘录 https://github.com/lexxmark/QtCreator-JsExtensions-Plugin
/jep_plugins/JepUtils.js
/jep_plugins/ModePanelButtons/ModePanelButtons.jep.js
function createActionToolButton(actionName) {
// look for an action
var cmd = actionManager.command(actionName);
if (cmd === null) {
jepAPI.debug("Cannot find such action: " + actionName);
return null;
}
// get action
var action = cmd.action();
// create button
var bttn = jepAPI.createQObject("QToolButton", null);
// tune button
bttn.toolButtonStyle = 2;
bttn.autoRaise = true;
bttn.styleSheet = "QToolButton {color: black; }";
// disable button's minimum width
bttn.sizePolicy = jepAPI.sizePolicy(13, 0, 1);
// assign action
bttn.setDefaultAction(action);
return bttn;
}
// add action buttons to mode panel
settings.actions.map(function (actionName) {
var bttn = createActionToolButton(actionName);
if (bttn)
modeManager.addWidget(bttn);
});
总之,Qt Creator 4.8.2版本没有ModeManager::addWidget函数,想添加自定义按钮只能通过ModeManager::addAction实现。