Files
kte/docs/plans/qt-frontend.md
Kyle Isom ee2c9939d7 Introduce QtFrontend with renderer, input handler, and theming support.
- Added `QtFrontend`, `QtRenderer`, and `QtInputHandler` for Qt-based UI rendering and input handling.
- Implemented support for theming, font customization, and palette overrides in GUITheme.
- Renamed and refactored ImGui-specific components (e.g., `GUIRenderer` -> `ImGuiRenderer`).
- Added cross-frontend integration for commands and visual font picker.
2025-12-04 21:33:55 -08:00

5.4 KiB

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.

Note (2025-12): The Qt frontend defers all key processing to the existing command subsystem and keymaps, mirroring the ImGui path. There are no Qt-only keybindings; QtInputHandler translates Qt key events into the shared keymap flow (C-k prefix, Ctrl chords, ESC/Meta, universal-argument digits, printable insertion).