Qt Creator plugin动手实践(3)C++ 类ModeManager源码分析

\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实现。

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值