Deepin Editor 1.0 開發總結

前段時間把編輯器這個項目給接了過來,鍛鍊一下自己、練練手,經歷了各種修修補補、增增刪刪的環節,剛看了一下 github,發現到如今我提交的 commit 也有 200+ 了...

介紹

Deepin 爲什麼喜歡造輪子?主要是爲了達到深度操作系統 用戶界面 / 用戶體驗 大統一的目標,今年的最主要目標不是造輪子,而是往系統穩定性的方向發展,所以造輪子是副業;雖然目前深度編輯器在技術方面還秒殺不了 KDE 家的 kate 編輯器,這個後面會講到,但是在 UI/UX 這方面我覺得可以秒殺它們。

深度編輯器定位就是簡單易用、輕量級的編輯器,目標就是要替換 gedit,保持深度編輯器的 UI/UX 和深度家族整體設計語言保持一致,比如我最近一直在寫博客,很多文章就是通過深度編輯器來寫的;論壇裏邊很多用戶說很少用到編輯器,也就偶爾修改配置文件和 TXT 文件的時候會用到,屬於輕度使用;在編程寫代碼這方面環境來看,都有專屬的 IDE (集成開發環境),所以用記事本來寫代碼的很少吧。

頂部採用類似 Chrome 的標籤欄設計,整體超窄邊框顯示,界面像深度終端那樣簡潔,不顯示多餘的東西,寫作的沉浸感,帶來了一種沉浸式的編輯體驗。

多標籤頁設計支持將標籤拖拽成窗口,或者將兩個窗口拖拽到一個窗口裏的另一個標籤頁。

右鍵智能菜單足以替換傳統編輯器的頂部菜單欄,右鍵菜單彈出時,如果文本已經有選擇的區域,針對用戶手動選擇的文字進行:剪切、複製、粘貼、刪除;如果沒有選中狀態,則臨時高亮鼠標下的單詞,針對光標下的單詞進行:剪切、複製、粘貼、刪除。

其他小功能

行號顯示、查找關鍵字、替換關鍵字、只讀模式下可以使用 Vim 快捷鍵進行字符移動操作,恩這些都是編輯器基本功能。

內置多套主題 UI,總有一款捕獲你的心,實現一秒快速切換,適合善變的你。

在平時使用文件選擇對話框來打開一些文件的時候,會出現一種重複選擇目錄的操作,這也是經常遇到的,因爲每次打開都是選擇 Home 目錄裏,這一個小細節我也是沒辦法忍的,所以實現了對上一次打開的目錄進行保存,當你打開文件選擇框的時候依舊是你上次打開文件夾目錄。

支持默認快捷鍵定製。

在 Windows、MacOS、Linux 這三個不同的操作系統中,它們的換行符是不同的,Windows 是 \r\n,Linux 是 \n,MacOS是 \r,據說 MacOS 10.0 以上的版本是以 \n 爲換行符,深度編輯器實現了在打開文件時候會自動偵測到文件的換行符,默認取第一行的換行符,當判斷是某個操作系統時,在保存的時候會使用該換行符作爲保存;保存對話框也提供了換行符的選項。

好了,非技術介紹就到這裏了,下面纔是主要內容。

架構設計

單進程多窗口設計理念

深度編輯器是一個單進程多窗口的應用程序,單進程多窗口就是無論打開多少個窗口,它只有一個獨立的進程,沒有因爲創建一個新窗口就會增加一個進程,實現多窗口單進程很簡單,也有很多種方式,比如深度文件管理器通過 QLocalSocket/QLocalServer 來實現;在這裏深度編輯器採用 DBus 來進行進程間的通信,通過 QDBusConnection 連接到 Session Bus,並提供一個服務,如果發現已經有程序註冊了該服務,那麼就說明已經啓動了一個進程不需要再單獨啓動一個進程,然後通過 QDBusInterface 訪問 Service 來達到進程通信的目的。

窗口管理

既然是單進程多窗口模式,就不能在 main.cpp 裏管理窗口創建/銷燬了,保持 main 文件的代碼簡潔,所以就誕生了 StartManager 類,所有窗口創建都在這個類裏邊進行管理,同時把創建過的窗口指針保存在一個 QList 裏。

窗口布局

用了差不多一年的 Qt GUI 庫,對 Qt 佈局也有大概的理解,其實 Qt 的佈局理解起來還挺簡單的,用起來確實比 Gtk+ 順手多了;深度編輯器窗口布局大概就如上圖所描述的,由於是多標籤設計,Qt 提供了多頁面切換佈局:QStackedLayout,也有建立在 QStackedLayout 上的的便利類 QStackedWidget,主要是爲了方便一些就用了 QStackedWidget,不用多 new 一個 QWidget,哈哈哈。

標籤欄控件是用了 dtkwidget 裏的 DTabBar,繼承了 QTabBar,是 @zccrs 大神寫的一個增強 QTabBar 功能的控件,所以基本用起來和 QTabBar 沒多大區別,在功能上當然要比 QTabBar 強大許多,主要是滿足深度編輯器的多標籤設計需求:

  • 支持左右拖動(這個原生的已經支持)
  • 標籤多的時候出現左右滾動箭頭按鈕
  • 可以支持向外 Drag and Drop 事件,以產生標籤拖拽出窗口的效果
  • 新建標籤欄按鈕

EditWrapper 其實主要就是封裝了左側的行號控件 + Qt 編輯框控件 QPlainTextEdit,在 EditWrapper 類裏做了 openFile()、saveFile() 相關操作,也就是在這個類做了打開文件、保存文件的代碼,Window 類會調用到此相關的函數。

主題模塊

把之前的 DSimpleListView 替換成了 QListView,使用 Qt 原生的 Model/View 架構,也就是模型、視圖和委託,MV 架構可以將數據和界面代碼分離,ThemeListModel 作爲數據層,ThemeItemDelegate 是繪畫代理層,ThemeListView 負責視圖顯示。

在創建 ThmeListModel 這個類的時候,它會自動加載所有主題資源文件,目錄在 /usr/share/deepin-editor/themes ,這個是寫死了路徑,通過 QFileInfoList 對該目錄進行遍歷,加載裏面所有主題文件進行數據存儲,然後用背景顏色亮度進行排序。

主題文件以 .theme 爲後綴,是一個以 json 爲格式的文件。

編輯控件

使用的是 Qt 官方清一色的編輯控件 QPlainTextEdit,主要用於純文本編輯和顯示,因爲天生缺陷,比如加載大文件的時候比較慢了,我也開始有點嫌棄它了,KDE 自己寫了一套組件,完全是根據自己的標準來寫的,界面顯示內容全都是在一個 QAbstractScrollArea 裏繪製,名叫 KTextEditor,其工程之大,真所謂鬼斧神工,是一個比 QPlainTextEdit 控件要厲害多了,大文件加載完全秒完成,而且高亮也不會卡 UI 線程。

研究了幾天時間,也想過要造這個輪子,但是目前還寫不出和 QPlainTextEdit 那種高度的水平,更不能說要秒殺 KTextEditor 了,那就先放一下了,這個時候想起了老王說的那句話:“很多時候技術上遇到瓶頸,千萬不要放棄,先暫時放一下,靈感會隨着你長時間的深入思考突然蹦出來的。”

至於爲什麼不用 KTextEditor ,這些依賴都不是蓋的,哈哈哈。

高亮實現

關於 Qt 語法高亮,Qt 官方文檔有個很好的例子:Syntax Highlighter Example,QSyntaxHighlighter 允許自定義高亮規則,但是需要配合 QPlainTextEdit 來使用,如果未來自己實現一個編輯器控件的話,這個也是個問題。

使用了 KDE 的 KSyntaxHighlighting,它是一個 Qt 的高亮引擎庫,在 QSyntaxHighlighter 類基礎上進行開發的,Qt Creator 也在用這個庫,目前支持 272 種語法高亮,也可以自己定製擴展:Working with Syntax Highlighting,這個項目幾乎是 KDE 依賴最小的吧,看了一下確實只依賴了 Extra CMake Modules (ecm) ...

Polkit 提權實現

待寫。

最後

之前一位社區開發者 @sonichy 問我:右鍵打開文件的時候是怎麼實現在標籤頁中打開呢?我大概知道是什麼意思了,最近沒有時間回覆,在這裏可以回答一下。雙擊打開文件的時候文件管理器會調用對應的軟件,並且會加上當前打開的文件地址字符串作爲參數傳進來編輯器,然後使用 QDBusInterface 作爲遠程對象接口代理,通過 callWithArgumentList() 調用遠程接口,這樣就實現了不打開新窗口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章