Add QtFrontend plans.
This commit is contained in:
116
docs/plans/qt-frontend.md
Normal file
116
docs/plans/qt-frontend.md
Normal file
@@ -0,0 +1,116 @@
|
||||
Based on the project structure and the presence of files like
|
||||
`imgui.ini`, `GUIFrontend.h`, and `TerminalFrontend.h`, here is an
|
||||
analysis of the difficulty and challenges involved in adding a GTK or Qt
|
||||
version of the GUI.
|
||||
|
||||
### **Executive Summary: Difficulty Level - Moderate**
|
||||
|
||||
The project is well-architected for this task. It already supports
|
||||
multiple frontends (Terminal vs. GUI), meaning the "Core Logic" (
|
||||
Buffers, Syntax, Commands) is successfully decoupled from the "View" (
|
||||
Rendering/Input). However, the specific move from an **Immediate Mode**
|
||||
GUI (likely Dear ImGui, implied by `imgui.ini` and standard naming
|
||||
patterns) to a **Retained Mode** GUI (Qt/GTK) introduces specific
|
||||
architectural frictions regarding the event loop and state management.
|
||||
|
||||
---
|
||||
|
||||
### **1. Architectural Analysis**
|
||||
|
||||
The existence of abstract interfaces—likely `Frontend`, `Renderer`, and
|
||||
`InputHandler`—is the biggest asset here.
|
||||
|
||||
* **Current State:**
|
||||
* **Abstract Layer:** `Frontend.h`, `Renderer.h`, `InputHandler.h`
|
||||
likely define the contract.
|
||||
* **Implementations:**
|
||||
* `Terminal*` files implement the TUI (likely ncurses or VT100).
|
||||
* `GUI*` files (currently ImGui) implement the graphical
|
||||
version.
|
||||
* **The Path Forward:**
|
||||
* You would create `QtFrontend`, `QtRenderer`, `QtInputHandler` (or
|
||||
GTK equivalents).
|
||||
* Because the core logic (`Editor.cc`, `Buffer.cc`) calls these
|
||||
interfaces, you theoretically don't need to touch the core text
|
||||
manipulation code.
|
||||
|
||||
### **2. Key Challenges**
|
||||
|
||||
#### **A. The Event Loop Inversion (Main Challenge)**
|
||||
|
||||
* **Current (ImGui):** Typically, the application owns the loop:
|
||||
`while (running) { HandleInput(); Update(); Render(); }`. The
|
||||
application explicitly tells the GUI to draw every frame.
|
||||
* **Target (Qt/GTK):** The framework owns the loop: `app.exec()` or
|
||||
`gtk_main()`. The framework calls *you* when events happen.
|
||||
* **Difficulty:** You will need to refactor `main.cc` or the entry point
|
||||
to hand over control to the Qt/GTK application object. The Editor's "
|
||||
tick" function might need to be connected to a timer or an idle event
|
||||
in the new framework to ensure logic updates happen.
|
||||
|
||||
#### **B. Rendering Paradigm: Canvas vs. Widgets**
|
||||
|
||||
* **The "Easy" Way (Custom Canvas):**
|
||||
* Implement the `QtRenderer` by subclassing `QWidget` and overriding
|
||||
`paintEvent`.
|
||||
* Use `QPainter` (or Cairo in GTK) to draw text, cursors, and
|
||||
selections exactly where the `Renderer` interface says to.
|
||||
* **Pros:** Keeps the code similar to the current ImGui/Terminal
|
||||
renderers.
|
||||
* **Cons:** You lose native accessibility and some native "feel" (
|
||||
scrolling physics, native text context menus).
|
||||
* **The "Hard" Way (Native Widgets):**
|
||||
* Trying to map an internal `Buffer` directly to a `QTextEdit` or
|
||||
`GtkTextView`.
|
||||
* **Difficulty:** This is usually very hard because the Editor core
|
||||
likely manages its own cursor, selection, and syntax highlighting.
|
||||
Syncing that internal state with a complex native widget often
|
||||
leads to conflicts.
|
||||
* **Recommendation:** Stick to the "Custom Canvas" approach (drawing
|
||||
text manually on a surface) to preserve the custom editor
|
||||
behavior (vim-like modes, specific syntax highlighting).
|
||||
|
||||
#### **C. Input Handling**
|
||||
|
||||
* **Challenge:** Mapping Qt/GTK key events to the internal `Keymap`.
|
||||
* **Detail:** ImGui and Terminal libraries often provide raw scancodes
|
||||
or simple chars. Qt/GTK provide complex Event objects. You will need a
|
||||
translation layer in `QtInputHandler::keyPressEvent` that converts
|
||||
`Qt::Key_Escape` -> `KKey::Escape` (or your internal equivalent).
|
||||
|
||||
### **3. Portability of Assets**
|
||||
|
||||
#### **Themes (Colors)**
|
||||
|
||||
* **Feasibility:** High.
|
||||
* **Approach:** `GUITheme.h` likely contains structs with RGB/Hex
|
||||
values. Qt supports stylesheets (QSS) and GTK uses CSS. You can write
|
||||
a converter that reads your current theme configuration and generates
|
||||
a CSS string to apply to your window, or simply use the RGB values
|
||||
directly in your custom `QPainter`/Cairo drawing logic.
|
||||
|
||||
#### **Fonts**
|
||||
|
||||
* **Feasibility:** Moderate.
|
||||
* **Approach:**
|
||||
* **ImGui:** Usually loads a TTF into a texture atlas.
|
||||
* **Qt/GTK:** Uses the system font engine (Freetype/Pango).
|
||||
* **Challenge:** You won't use the texture atlas anymore. You will
|
||||
simply request a font family and size (e.g.,
|
||||
`QFont("JetBrains Mono", 12)`). You may need to ensure your custom
|
||||
renderer calculates character width/height metrics correctly using
|
||||
`QFontMetrics` (Qt) or `PangoLayout` (GTK) to align the grid
|
||||
correctly.
|
||||
|
||||
### **4. Summary Recommendation**
|
||||
|
||||
If you proceed, **Qt** is generally considered easier to integrate with
|
||||
C++ projects than GTK (which is C-based, though `gtkmm` exists).
|
||||
|
||||
1. **Create a `QtFrontend`** class inheriting from `Frontend`.
|
||||
2. **Create a `QtWindow`** class inheriting from `QWidget`.
|
||||
3. **Implement `QtRenderer`** that holds a pointer to the `QtWindow`.
|
||||
When the core calls `DrawText()`, `QtRenderer` should queue that
|
||||
command or draw directly to the widget's paint buffer.
|
||||
4. **Refactor `main.cc`** to instantiate `QApplication` instead of the
|
||||
current manual loop.
|
||||
Reference in New Issue
Block a user