一. 前言
一直以來,筆者都在從事工控相關的行業,時至今日已有15年的職業歷程,為了更好的將自己的經驗應用于實踐,同時汲取各方力量助力這一開放式的開發框架,遂將其進行開源,
框架最初的版本是基于C#開發,應用于航空自動測驗系統,即View+TPS的結構,View即一個統一的UI界面,用于選擇不同的TPS測驗序列包,如此以來,開發人員只需要關注測驗序列邏輯及硬體設備的使用,而無需關注UI設計,因為在航空自動測驗系統中,被測件是成熟機載電子設備,只需要按照手冊中的測驗步驟,用程式呼叫系統中的硬體設備撰寫測驗序列,就可以被統一的UI呼叫,并對測驗進行控制,生成報表,
后來筆者又進入航天測控及軍工領域,這一行業有個特點就是需求不確定,甚至需要經常添加或修改UI及功能,專案周期短更迭快,需要一個可裁剪,可重用,松耦合,可高效同步的開發框架,因此筆者在原來框架的基礎上,設計了第二代基于插件的開發框架,在大中型專案開發中,的確提高了專案的開發效率,但問題也隨之而來,1.框架為應對技術上的需求,介面不得已進行升級,導致向下兼容性差,2.越來越多的跨平臺需求,而C#在Linux下的表現實在不咋地,因此框架仍需更新換代,
說起來慚愧,筆者除了是一個老程式員以外,也是一個原創音樂的愛好者,雖然音樂上并無建樹,但在進行音樂創作的時候,國外音頻宿主軟體倒是給了筆者很大的設計啟發,音頻宿主軟體,宿主毫無疑問就是一個框架,一個容器,用戶在使用的程序中,會安裝各種各樣的樂器音色庫插件,宿主根本不關心用戶會加載多少插件和什么插件,它只是負責管理好他們,提供各種供用戶操作的與插件的介面,宿主軟體就像一個舞臺,只是用于承載樂器插件完成一場美妙得音樂會,
二. QCPFrame 介紹
QCPFrame 全稱Qt-based Common Plugin Framework,它是一個開源的基于Qt的跨平臺插件開發框架,旨在提高基于PC及Linux平臺下工控軟體設計的通用性,重用性,高效性,可裁剪性,松耦合性,在QCPFrame中,您可以基于控制臺或者服務來運行最小插件系統,也可以通過view editor(也是一個插件)來編輯帶有UI的桌面程式,在QCPFrame中,一切皆插件,甚至一個函式功能,選單項,工具列,狀態欄,dock片都可以是一個插件,插件在編輯和配置插件,這一切就像是在搭積木,使得模塊開發而無需關注最終的集成,作為初版的QCPFrame,它具備以下特性:
1. 熱插拔
即支持軟體啟動后動態添加或替換新的插件進來,這有助于在線升級的功能實作,
2. 系統組件/非系統組件
由于框架采用了Model-ViewModel的架構,一切皆插件的設計思路,那么可執行程式對于系統而言,不過是一個啟動器而已,大部分功能是需要插件來實作,比如插件管理器,視圖編輯器,系統設定等等,這些從前是放在主程式中的功能模塊,如今也是作為一個插件被宿主統一管理,如此以來,系統的升級將意味著只需要升級插件,因為主程式基本沒有什么代碼,這些用于不斷擴充系統功能的組件,在系統中被稱之為系統組件,
非系統組件用于實作二次開發時,對于業務的實作,這樣把框架本身和業務分開的方式,不但提高了系統的靈活性,也可以將框架與業務解耦,
3. 組件克隆
在專案開發的程序中,我們經常會遇到需要很多組相同的界面及功能,可能只是這些界面及功能對應的硬體通道不同而已,之前很多人的做法就是復制代碼,或者寫一個類然后new出多個物件,有了組件克隆,你可以輕松通過組件管理器來克隆出一模一樣的組件,他們是深拷貝實作的,因此不必考慮指標的關聯性,出于安全考慮,只有非系統組件支持克隆,而系統組件的克隆不被允許,
4. 組件排序
組件排序功能,使開發者能夠調整組件在運行時被加載的順序,這在某些與硬體初始化相關的應用中至關重要,系統提供了"Model構造時",“View構造時”,“View第一次顯示時”,“View關閉時”這四個節點的信號,系統運行至這幾個節點時,會按照組件排序的順序,依次呼叫組件的這些介面函式,
5.共享記憶體
框架的介面提供了豐富的共享記憶體型別,供插件之間同步時使用,這包含C++基本型別,鏈表,佇列等等,
Github地址: https://github.com/Jamie-tong/QCPFrame.git
碼云地址:https://gitee.com/JamieT/QCPFrame.git
三. 系統結構

圖1. QCPFrame 系統結構圖
從系統結構圖來看,主要的功能在左半邊,對于一個控制臺程式來講,viewmodel已經不參與運行,QCPFrame+Console即為最小插件系統,可以當作一個控制臺或者服務來啟動最小插件系統,
Model由QCPFModel和Configure Model組成,QCPFModel用于掃描并連接Plugins,為Plugins提供系統級介面,而Configure Model用于存盤系統配置,包括系統功能設定,組件選擇與克隆,運行時排序等功能,通過序列化和反序列化可以將用戶的配置永久保留,在軟體啟動時再裝載進來,
ViewModel有著與Model類似的結構,但它已經與QCPFrame沒有直接關系,它的存在只是為了使View進行前后端分離,即當你不喜歡這個view時,可以通過ViewModel快速構建你喜歡的View,你可以使用ViewModel中的屬性或方法,也可以選擇不用,這取決于你自己,
四. View Editor插件
為了直觀的介紹QCPFrame,我們通過系統中一個重要的插件View Editor來介紹QCPFrame的便捷之處,

圖2. 帶UI界面的QCPFrame
如上圖所示,View界面主要由選單欄,工具列,dock視窗,狀態欄組成,而view editor插件要做的作業,就是幫我們添加以上各UI元素,并通過Model與特定的功能進行系結,這一切都是可視化的,你可以調整他們的位置,

圖3. View Editor 選單編輯功能
對于選單欄來說,其實可以認為每個頂級選單項即為一顆樹,view editor在設計時,允許用戶在隨意添加樹節點,除了頂級選單意外,可以任意添加分隔符,通過方向鍵調整層級關系,每個選單項可以設定查看權限,這在后面權限管理中會講到,添加好樹節點以后,就可以通過Map Function按鈕給該選單項掛載一個Function,你可以通過Function Viewer頁面來找到你要的Function,一旦完成Function掛載,該選單項再下一次啟動后,便可以通過信號槽與組件指定的功能掛接起來,通過Load Icon按鈕為該選單項設定一個圖示,該圖示將一直伴隨這個Action,值得一提的是這些可以掛載的Function是預先在插件工程中開發好的,隨著插件的增多,對于View Editor來說,可選可編輯的Function也將更豐富,

圖4. View Editor 工具列及狀態欄編輯功能
對于工具列來說,允許用戶添加多個工具列,并為指定工具列添加Action, Action下拉框的項來自選單編輯頁面所映射過的Action,也就是說你只能先在選單下加入該新Action,才能在工具列里添加它,多工具列,可以讓你實作類似Word一樣的復雜視圖,值得一提的是,工具列編輯模塊允許你指定插件里開發好的任意widget,也就是你可以將一個自定義的widget展示到工具列里去,Widget Viewer是一個插件widget串列查看器,你可以通過它找到你要的widget,
系統只提供了一個狀態欄,其編輯類似于工具列,只不過沒有分割符,因為Qt的狀態欄會自動為每個item添加分隔符,

圖5. View Editor 部件選擇功能
通過widiget選擇功能,你可以從已經開發好的widget串列中選擇你要的,在重新啟動以后,系統會將這些widget放入dockwidget容器中,系統做了Layout存盤,因此當你通過拖拽,調整好需要的UI并關閉系統時,該Layout將會被保存,包括工具列的位置及Dock,如圖1所示,
其實說到這里,本節內容不過是在講一個插件,它只是整個系統中一個小的模塊,我的意思是說,至此我們可以把任何功能與主程式剝離,而使其成為一個易于升級的熱插拔模塊,插件在編輯或配置自己,也可以編輯或配置其他組件,這一切,作為可執行程式的View全然不知,它只不過是一個容器罷了,
小結:
本篇文章簡單介紹了一下該開源專案的主旨,系統結構,設計理念及一些初步的概念,說的不對的望各位大神指點,下一篇,我會介紹框架的二次開發及介面,也會展望一下未來,指定進一步的設計目標,謝謝,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/1378.html
標籤:其他
