Add QtFrontend plans.

This commit is contained in:
2025-12-04 15:51:06 -08:00
parent 37472c71ec
commit f5a4625652

116
docs/plans/qt-frontend.md Normal file
View 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.