14 KiB
Comprehensive Plan: Port All egui Signals/Events to Qt GUI
Complete Event/Signal Map (50+ events from AppEvent)
Every event in event_bus.rs must have a Qt equivalent. Here is the full mapping:
1. Tool & Drawing Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
ToolChanged(Tool) |
ToolsPanel::toolChanged(int) → MainWindow::onToolChanged(int) |
Already wired |
LayerAdded |
LayersPanel button → MainWindow::onNewLayer() |
Already wired |
LayerDeleted(u64) |
LayersPanel delete button → MainWindow::onDeleteLayer() |
Already wired |
LayerSelected(u64) |
LayersPanel::itemClicked → engine->setActiveLayer(id) |
Already wired |
Undo |
actionUndo → MainWindow::onUndo() |
Already wired |
Redo |
actionRedo → MainWindow::onRedo() |
Already wired |
RenderRequested |
After every engine operation, call canvas->update() |
Needs wiring |
DrawingFinished |
After end_stroke, no-op in egui |
No-op in Qt too |
2. Document Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
DocSwitched(usize) |
QTabWidget::currentChanged → MainWindow::onTabChanged(int) |
Already wired |
DocClosed(usize) |
QTabWidget::tabCloseRequested → MainWindow::onTabCloseRequested(int) |
Already wired |
CloseAllDocs |
Menu action → iterate tabs, close all | Needs wiring |
DocCreated{name,w,h} |
NewImageDialog → MainWindow::createDocument() |
Already wired |
3. File Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
FileOpenRequested |
actionOpen → QFileDialog::getOpenFileName → engine->open_image() |
Stub exists |
FileSaveRequested |
actionSave → engine->save_as() |
Stub exists |
FileSaveAsRequested |
actionSaveAs → QFileDialog::getSaveFileName → engine->save_as() |
Stub exists |
FileOpened(path,data,w,h) |
After successful load, create document | Needs wiring |
ExportRequested |
actionExport → QFileDialog::getSaveFileName |
Stub exists |
ImportRequested |
actionImport → QFileDialog::getOpenFileName |
Stub exists |
ImportSvg(path) |
actionImportSvg → engine->import_svg() |
Stub exists |
ImportBrushesRequested |
actionImportBrushes → QFileDialog → ABR parser |
Stub exists |
4. Filter Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
ApplyFilter(id, params) |
FiltersPanel::itemClicked → engine->apply_filter() |
Already wired |
5. Selection Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
SelectionAll |
actionSelectAll → engine->selection_all() |
Already wired |
SelectionDeselect |
actionSelectDeselect → engine->selection_clear() |
Already wired |
SelectionInvert |
actionSelectInvert → engine->selection_invert() |
Already wired |
SelectionGrow(px) |
actionSelectGrow → dialog → engine->selection_grow() |
Stub exists |
SelectionShrink(px) |
actionSelectShrink → dialog → engine->selection_shrink() |
Stub exists |
SelectionFeather(r) |
actionSelectFeather → dialog → engine->selection_feather() |
Stub exists |
SelectionErode(px) |
actionSelectErode → dialog → engine->selection_shrink() |
Stub exists |
SelectionFade(px) |
actionSelectFade → dialog → engine->selection_feather() |
Stub exists |
6. Image Transform Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
RotateClockwise |
actionRotateCW → engine->rotate_layer(+90) |
Already wired |
RotateCounterClockwise |
actionRotateCCW → engine->rotate_layer(-90) |
Already wired |
Rotate180 |
actionRotate180 → engine->rotate_layer(180) |
Already wired |
FlipHorizontal |
actionFlipH → engine->flip_layer_horizontal() |
Already wired |
FlipVertical |
actionFlipV → engine->flip_layer_vertical() |
Already wired |
Crop |
actionCropImage → engine->crop(selection_rect) |
Stub exists |
ImageSize |
actionImageSize → dialog |
Stub exists |
CanvasSize |
actionCanvasSize → dialog |
Stub exists |
Invert |
actionInvert → engine->apply_filter("invert") |
Already wired |
7. Layer Operations
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
MergeDown |
actionMergeDown → engine->merge_down() |
Already wired |
FlattenImage |
actionFlattenImage → engine->flatten_image() |
Already wired |
LayerClear |
actionClearLayer → engine->clear_active_layer_pixels() |
Already wired |
TransformStart |
actionFreeTransform → enter transform mode |
Stub exists |
AlignLayer(axis) |
Layer > Align > [axis] → engine->align_active_layer() |
Stub exists |
8. Clipboard Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
ClipboardCopy |
actionCopy → QClipboard → copy layer pixels |
Stub exists |
ClipboardCut |
actionCut → copy + clear pixels |
Stub exists |
ClipboardPaste |
actionPaste → QClipboard → paste as new layer |
Stub exists |
ClipboardPasteSpecial |
actionPasteSpecial → paste with options |
Stub exists |
9. Zoom/Pan Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
ZoomIn |
actionZoomIn → canvas->zoomIn() |
Already wired |
ZoomOut |
actionZoomOut → canvas->zoomOut() |
Already wired |
ZoomReset |
actionZoomReset → canvas->setZoom(1.0) |
Already wired |
ZoomSet(f) |
zoomSlider valueChanged → canvas->setZoom() |
Already wired |
Pan(dx,dy) |
Middle-mouse drag → canvas->resetPan() |
Already wired |
PanReset |
actionPanReset → canvas->resetPan() |
Already wired |
10. AI/Vision Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
AiChatSubmit(text) |
AiChatPanel send button → AI engine call |
Stub exists |
AiChatStop |
AI panel stop button | Stub exists |
SmartSelectRun{x,y} |
Smart Select tool click → engine->vision_object_segment() |
Stub exists |
VisionRunTask |
Vision panel run button → engine->vision_*() |
Stub exists |
VisionSelectRun{x1,y1,x2,y2} |
Vision Select tool drag → engine->vision_object_segment() |
Stub exists |
VisionBackendChanged(backend) |
Vision panel CPU/GPU toggle | Stub exists |
11. Text Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
ToolTextStart{x,y} |
Text tool click → engine->add_text() |
Stub exists |
ToolTextAccepted |
Accept button → commit text layer | Stub exists |
ToolTextCancelled |
Cancel button → delete/revert text layer | Stub exists |
TextLayerSelected(id) |
Double-click text layer → enter edit mode | Stub exists |
12. Theme/Misc Events
| egui Event | Qt Signal/Slot | Implementation |
|---|---|---|
ThemeChanged(preset) |
Theme menu items → applyTheme() |
Already wired |
ResetLayout |
actionResetLayout → recreate dock layout |
Stub exists |
SaveSettings |
After settings change → save to file | Stub exists |
ShowStatusMessage(text) |
After operations → statusBar->showMessage() |
Needs wiring |
OpenLayerStyles(id) |
Layer Styles button → open panel | Stub exists |
13. Brush Editor Events (from brush_editor.rs)
| egui Feature | Qt Implementation |
|---|---|
| Brush Tip category (size, hardness, spacing, opacity) | BrushesPanel needs sliders |
| Dynamics category (pressure, velocity, tilt) | BrushesPanel needs sliders |
| Color category (cyclic color, variant) | BrushesPanel needs checkboxes |
| Texture category (brush texture overlays) | BrushesPanel needs texture picker |
| Live stroke preview (engine-rendered) | CanvasWidget render brush preview |
| Preset save/load | BrushesPanel save/load buttons |
14. Geometry Panel Events (from geometry_panel.rs)
| egui Feature | Qt Implementation |
|---|---|
| Vector shape list (per-shape selection) | PropertiesPanel or new GeometryPanel |
| Per-shape stroke/opacity/hardness sliders | PropertiesPanel dynamic controls |
| Per-shape color picker (stroke + fill) | PropertiesPanel color buttons |
| Per-shape bounds display | PropertiesPanel label |
| Per-shape delete button | PropertiesPanel delete button |
| Boolean operations (union, subtract, intersect) | PropertiesPanel or context menu |
15. Layer Styles Events (from layer_styles_panel.rs)
| egui Feature | Qt Implementation |
|---|---|
| Drop Shadow (enable, opacity, angle, distance, spread, size, color, blend) | LayerStylesPanel sliders |
| Inner Shadow (same params) | LayerStylesPanel sliders |
| Outer Glow (enable, opacity, spread, size, color, blend) | LayerStylesPanel sliders |
| Inner Glow (enable, opacity, choke, size, color, blend) | LayerStylesPanel sliders |
| Bevel & Emboss (enable, depth, size, angle, altitude, highlight/shadow) | LayerStylesPanel sliders |
| Satin (enable, opacity, angle, distance, size, color, invert) | LayerStylesPanel sliders |
| Color Overlay (enable, opacity, color, blend) | LayerStylesPanel controls |
| Gradient Overlay (enable, opacity, blend, angle, scale, gradient) | LayerStylesPanel controls |
| Pattern Overlay (enable, opacity, blend, scale, pattern) | LayerStylesPanel controls |
| Stroke (enable, size, position, opacity, color, blend) | LayerStylesPanel controls |
Tasks (Priority Order)
P0: Fix QSS Colors to Match egui Exactly
File: hcie-qt-app/resources/themes/photoshop_dark.qss
All 12+ color tokens must match ThemeColors::get(ThemePreset::Photoshop):
#1c1c1e(bg_app),#323236(bg_panel),#3e3e42(bg_hover),#242426(bg_dark_depth)#3a3a3e(bg_elevated),#161618(bg_recessed),#202022(title_bar_bg)#3878dc(accent),#404044(border_high),#28282a(border_low)#e0e0e0(text_primary),#949498(text_secondary)
P1: Wire All Menu Actions to Engine FFI
File: hcie-qt-app/src/mainwindow.cpp
Currently stub implementations exist for: Import, Export, ClipboardCopy/Cut/Paste, Crop, ImageSize, CanvasSize, SelectionGrow/Shrink/Feather/Erode/Fade, Align, Transform, LayerStyles, ImageSize, CanvasSize.
Each must call the corresponding m_engine->methodName() and then refresh() all panels + update canvas.
P2: Wire Panel Signals to Engine
Files: All panel .cpp files
Each panel's refresh() must read from engine and populate widgets. Each widget change must call engine method and emit renderRequested.
Key panels needing signal wiring:
- LayersPanel: visibility toggle, blend mode change, opacity change, layer reorder, add/delete/group/flatten buttons
- HistoryPanel: jump-to-step click →
engine->jumpToHistory() - PropertiesPanel: tool-specific sliders (size, opacity, hardness, flow, spacing per tool)
- BrushesPanel: preset selection →
engine->set_brush_tip() - FiltersPanel: filter click →
engine->apply_filter(name, params) - ColorsPanel: color selection →
engine->set_color(rgba) - AiChatPanel: send button →
engine->ai_chat_submit()
P3: Add Missing Panels
New files needed:
geometry_panel.h/cpp— vector shape list and per-shape editinglayer_styles_panel.cpp— flesh out with 10 style editors (currently stub)
P4: Canvas Rendering Loop
File: hcie-qt-app/src/canvas_widget.cpp
The paintGL() must call engine->get_composite_pixels() every frame (or on dirty). The current implementation does this but needs to handle the dirty flag properly — only re-upload when engine->isCompositeDirty().
P5: Properties Panel Tool-Specific Controls
File: hcie-qt-app/src/panels/properties_panel.cpp
Currently shows placeholder. Must rebuild tool settings based on active tool:
- Brush/Eraser: size, opacity, hardness, flow, spacing, color variant, cyclic color
- Pen: size, opacity, hardness, cyclic color
- Spray: radius, particle size, density, opacity, hardness
- Flood Fill: tolerance
- Magic Wand: tolerance
- Vector tools: stroke, opacity, fill toggle, round rect radius, star points
- Text: font, size, color, angle, alignment, orientation
- Gradient: type (linear/radial)
- VectorSelect: per-shape editing
P6: Color Panel with Standard Qt ColorPicker
File: hcie-qt-app/src/panels/colors_panel.cpp
Replace custom HSL wheel (broken rendering) with:
- Foreground/Background color swatches
- "Pick Color" button →
QColorDialog::getColor() - Palette grid (basic colors)
- Recent colors list
P7: Status Bar Message Expiry
File: hcie-qt-app/src/mainwindow.cpp
Implement ShowStatusMessage with 3-second timer expiry (matching egui).
Validation
After each task:
cmake --build build— must compile- Visual comparison with egui screenshots
- Functional test: each menu item, each panel interaction, each keyboard shortcut
Files Modified
| File | Changes |
|---|---|
hcie-qt-app/resources/themes/photoshop_dark.qss |
~30 color values, all widget styling |
hcie-qt-app/src/mainwindow.cpp |
Wire all menu actions to engine |
hcie-qt-app/src/mainwindow.h |
Add missing method declarations |
hcie-qt-app/src/panels/properties_panel.cpp |
Tool-specific settings |
hcie-qt-app/src/panels/colors_panel.cpp |
QColorDialog-based picker |
hcie-qt-app/src/panels/brushes_panel.cpp |
Preset selection, brush tip editing |
hcie-qt-app/src/panels/history_panel.cpp |
Jump-to-step |
hcie-qt-app/src/panels/layers_panel.cpp |
Visibility/blend/opacity signals |
hcie-qt-app/src/panels/filters_panel.cpp |
Filter param dialogs |
hcie-qt-app/src/panels/ai_chat_panel.cpp |
AI chat submit |
hcie-qt-app/src/panels/layer_styles_panel.cpp |
10 style editors |
hcie-qt-app/src/panels/layer_details_panel.cpp |
Read-only info display |
hcie-qt-app/src/canvas_widget.cpp |
Dirty flag, composite upload |
hcie-qt-app/src/hcie_engine_wrapper.h/cpp |
Missing FFI methods |
hcie-qt-app/src/dialogs/* |
Wire all dialog buttons |
hcie-engine-api/src/ffi.rs |
Add missing FFI functions |