閱讀Qt Creator-OutputPane相關

這裏主要分析QtCreator中OutputPane的相關內容,能夠看到QtCreator在狀態欄有四個Checkable按鈕,以下圖所示app

image

checkable按鈕的實現方式基本一致,這裏僅以其中一種General Message來講明問題。在插件源碼的coreplugin中,相關類有ModeManager,MessageManager,MessageOutputWindow,OutputPaneManager,OutputPaneToggleButton,OutputPaneManageButton,OutputPanePlaceHolder,MiniSplitterHandle,OutputWindow以及StatusBarManager和StatusBarWidget。這裏首先看一下他們之間的關係。ide

image

接下來詳細解釋與分析一下(高手勿噴,請多指教)。微笑函數

MainWindow的構造函數都作了些什麼?

MainWindow應該作的都只是各類管理器的初始化工做,如何佈局是由ModeManager來管理的,ModeManager經過各個不一樣的Mode來呈現不一樣的界面佈局。工具

IMode就是這些Mode的接口類,在後面會詳細介紹。先看MainWindow,初始化分爲了三個部分:構造函數、init()、extensionsInitialized()。在Qt Creator中,不少Manager使用單例模式,可是這些單例模式能夠說是一種不自動的,沒有根據成員m_instance的狀態來判斷是建立實例仍是直接返回,每個Manager都須要create一下(好處不詳,沒有分析出來悲傷,望高手賜教)。在構造函數中就是調用這些create(),合情合理,構造函數不就是建立嘛。先上段代碼看看:佈局

 

MainWindow::MainWindow() :
    Utils::AppMainWindow(),
    m_coreImpl(new ICore(this)),
    .....
    m_actionManager(new ActionManager(this)),
    m_editorManager(0),
    .....
    m_statusBarManager(0),
    m_modeManager(0),
    .....
    m_activeContext(0),
    m_generalSettings(new GeneralSettings),
    m_shortcutSettings(new ShortcutSettings),
    .....
    m_toggleSideBarAction(0),
	.....
    m_toggleSideBarButton(new QToolButton)
{
    (void) new DocumentManager(this);
    OutputPaneManager::create();

    setWindowTitle(tr("Qt Creator"));
	......
	......
    registerDefaultContainers();
    registerDefaultActions();

    ......

    m_modeStack = new FancyTabWidget(this);
    m_modeManager = new ModeManager(this, m_modeStack);
    m_modeManager->addWidget(m_progressManager->progressView());
    m_statusBarManager = new StatusBarManager(this);
    m_messageManager = new MessageManager;
    m_editorManager = new EditorManager(this);
    m_editorManager->hide();
    m_externalToolManager = new ExternalToolManager();
    setCentralWidget(m_modeStack);

    .......
    statusBar()->insertPermanentWidget(0, m_toggleSideBarButton);
	
	.......
}

撇掉與輸出窗口無關的東西,上面的代碼就是與Output相關的代碼。this

m_actionManager用於管理菜單,關於Output僅用於註冊快捷鍵。 .net

1. OutputPaneManager::create()

完成OutputPaneManager建立,在其構造函數中添加了「清除action」,「prevAction」,「nextAction」,」最大化最小化」,」關閉「等輸出窗口上toolbar的一些action。這幾個action是全部輸出類窗口的公共action,也就是說,全部的輸出類窗口都會有這幾個action。插件

2. registerDefaultContainers() 和 registerDefaultActions()

用於添加主窗口的菜單,具體添加方法參見http://www.devbean.info/2012/03/qtcreator-plugin-develop-catalog/設計

3.new FancyTabWidget 和 new ModeManager

FancyTabWidget是Qt Creator窗口最左邊的一列,包括歡迎、編輯、調試、設計、項目、分析、幫助,下邊還有一個你們都熟悉的cornerWidget(放着構建、構建運行等幾個按鈕)。ModeManager用於管理各類Mode,好比EditMode,WelcomeMode等等,每個FancyTabWidget中的Tab對應一個Mode,從這裏能夠看出,能夠經過添加IMode的子類以在FancyTabWidget中添加Tab。ModeManager的構造函數完成FancyTabWidget的Tab改變所引發的信號的槽,並添加cornerWidget(在FancyTabWidget中,並無添加,只是添加了一個佔位的佈局而已)。調試

4. new StatusBarManager(this) 和 new MessageManager

StatusBarManager的構造函數完成根據StatusBarWidget的個數(四個)向StatusBar添加Widget的功能(其實就至關於將狀態欄分紅了四個部分),並將他們存放在QList<QWidget*>中以便之後使用。來一段代碼

StatusBarManager::StatusBarManager(MainWindow *mainWnd)
  : QObject(mainWnd),
    m_mainWnd(mainWnd)
{
    for (int i = 0; i <= StatusBarWidget::Last; ++i) {
        QWidget *w = new QWidget();
        m_mainWnd->statusBar()->insertPermanentWidget(i, w);
        w->setLayout(new QHBoxLayout);
        w->setVisible(true);
        w->layout()->setMargin(0);
        m_statusBarWidgets.append(w);
    }
    m_mainWnd->statusBar()->insertPermanentWidget(StatusBarWidget::Last+1,
                                                  new QLabel(), 1);
}

我的認爲這裏使得狀態欄的分組個數固定,設計並非很好,插件但願添加按鈕到狀態欄時就遇到了困難,須要修改StatusBarWidget,並從新編譯Core插件,不知道是我理解的不夠深刻仍是怎麼轉動眼睛。MessageManager的構造函數並無作什麼實質性的東西。

statusBar()->insertPermanentWidget(0, m_toggleSideBarButton);在狀態欄的最左邊添加了一個按鈕用於顯示/隱藏邊欄。

MainWindow的init()作了些什麼?

先上代碼,已經去掉無關代碼。

bool MainWindow::init(QString *errorMessage)
{
    Q_UNUSED(errorMessage)

    .....

    ExtensionSystem::PluginManager::addObject(m_coreImpl);
    m_statusBarManager->init();
    m_modeManager->init();

    .......

    m_outputView = new Core::StatusBarWidget;
    m_outputView->setWidget(OutputPaneManager::instance()->buttonsWidget());
    m_outputView->setPosition(Core::StatusBarWidget::Second);
    ExtensionSystem::PluginManager::addObject(m_outputView);
    m_messageManager->init();
    return true;
}

1. m_statusBarManager->init()

僅將對象池的objectAdded() 和aboutToRemoveObject()兩個信號關聯到了相應的槽函數objectAdded(QObject*)和aboutToRemoveObject(QObject*)。當有對象添加到對象池當中時,就使用Aggregation來查詢是不是StatusBarWidget類型,若是是該類型,就將相對應的Widget添加到狀態欄的相應位置當中,並添加到窗口列表(QMap<QWidget *, IContext *> m_contextWidgets)當中。aboutToRemoveObject就是從窗口列表中刪除。

2. m_modeManager->init()

與StatusBarManager同樣,僅將對象池的objectAdded() 和aboutToRemoveObject()兩個信號關聯到了相應的槽函數objectAdded(QObject*)和aboutToRemoveObject(QObject*)。他查詢的是IMode類型,若是是IMode類型,就將其添加到FancyTabWidget當中,並連接相應的槽,註冊快捷鍵。

3.new Core::StatusBarWidget()以後的幾句代碼

建立了一個Widget,這個Widget由OutputPaneManager來負責填充,並設置這個widget放在狀態欄的第2個位置上(有4個位置),添加這個StatusBarWidget到對象池,相應的槽函數完成真正的插入工做。

4. MessageManager::init()

該函數中建立MessageOutputWindow,並將其添加到對象池中。

MainWindow的extensionsInitialized()都作了些什麼?

簡要代碼以下:

void MainWindow::extensionsInitialized()
{
    .......
    m_statusBarManager->extensionsInitalized();
    OutputPaneManager::instance()->init();
    .......
    // reading the shortcut settings must be done after all shortcuts have been registered
    m_actionManager->d->initialize();

    .......
}

1. m_statusBarManager->extensionsInitalized()

該函數爲空,能夠進行擴展。

2. OutputPaneManager::instance()->init()

首先在主窗口的menuBar中添加菜單,關聯」清空「,」最大化/最小化「操做。而後從對象池當中獲得全部的IOutputPane,並將它們根據在狀態欄中的位置進行排序。而後將每一個IOutputPane的輸出窗口outputWidget添加到QStackedWidget當中,將toolBarWidget添加到輸出窗口上邊的工具欄m_opToolBarWidgets(也是一個StackedWidget)中。

好,先寫這麼多,之後繼續補充。

相關文章
相關標籤/搜索