這裏主要分析QtCreator中OutputPane的相關內容,能夠看到QtCreator在狀態欄有四個Checkable按鈕,以下圖所示app
checkable按鈕的實現方式基本一致,這裏僅以其中一種General Message來講明問題。在插件源碼的coreplugin中,相關類有ModeManager,MessageManager,MessageOutputWindow,OutputPaneManager,OutputPaneToggleButton,OutputPaneManageButton,OutputPanePlaceHolder,MiniSplitterHandle,OutputWindow以及StatusBarManager和StatusBarWidget。這裏首先看一下他們之間的關係。ide
接下來詳細解釋與分析一下(高手勿噴,請多指教)。函數
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
完成OutputPaneManager建立,在其構造函數中添加了「清除action」,「prevAction」,「nextAction」,」最大化最小化」,」關閉「等輸出窗口上toolbar的一些action。這幾個action是全部輸出類窗口的公共action,也就是說,全部的輸出類窗口都會有這幾個action。插件
用於添加主窗口的菜單,具體添加方法參見http://www.devbean.info/2012/03/qtcreator-plugin-develop-catalog/設計
FancyTabWidget是Qt Creator窗口最左邊的一列,包括歡迎、編輯、調試、設計、項目、分析、幫助,下邊還有一個你們都熟悉的cornerWidget(放着構建、構建運行等幾個按鈕)。ModeManager用於管理各類Mode,好比EditMode,WelcomeMode等等,每個FancyTabWidget中的Tab對應一個Mode,從這裏能夠看出,能夠經過添加IMode的子類以在FancyTabWidget中添加Tab。ModeManager的構造函數完成FancyTabWidget的Tab改變所引發的信號的槽,並添加cornerWidget(在FancyTabWidget中,並無添加,只是添加了一個佔位的佈局而已)。調試
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);在狀態欄的最左邊添加了一個按鈕用於顯示/隱藏邊欄。
先上代碼,已經去掉無關代碼。
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; }
僅將對象池的objectAdded() 和aboutToRemoveObject()兩個信號關聯到了相應的槽函數objectAdded(QObject*)和aboutToRemoveObject(QObject*)。當有對象添加到對象池當中時,就使用Aggregation來查詢是不是StatusBarWidget類型,若是是該類型,就將相對應的Widget添加到狀態欄的相應位置當中,並添加到窗口列表(QMap<QWidget *, IContext *> m_contextWidgets)當中。aboutToRemoveObject就是從窗口列表中刪除。
與StatusBarManager同樣,僅將對象池的objectAdded() 和aboutToRemoveObject()兩個信號關聯到了相應的槽函數objectAdded(QObject*)和aboutToRemoveObject(QObject*)。他查詢的是IMode類型,若是是IMode類型,就將其添加到FancyTabWidget當中,並連接相應的槽,註冊快捷鍵。
建立了一個Widget,這個Widget由OutputPaneManager來負責填充,並設置這個widget放在狀態欄的第2個位置上(有4個位置),添加這個StatusBarWidget到對象池,相應的槽函數完成真正的插入工做。
該函數中建立MessageOutputWindow,並將其添加到對象池中。
簡要代碼以下:
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(); ....... }
該函數爲空,能夠進行擴展。
首先在主窗口的menuBar中添加菜單,關聯」清空「,」最大化/最小化「操做。而後從對象池當中獲得全部的IOutputPane,並將它們根據在狀態欄中的位置進行排序。而後將每一個IOutputPane的輸出窗口outputWidget添加到QStackedWidget當中,將toolBarWidget添加到輸出窗口上邊的工具欄m_opToolBarWidgets(也是一個StackedWidget)中。
好,先寫這麼多,之後繼續補充。