You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+21-1Lines changed: 21 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,7 +37,8 @@ The codebase is split into several Stack packages:
37
37
-**`ff-core`** — all business logic and CLI code
38
38
-**`ff-test`** — test suite (tasty + tasty-golden + tasty-hedgehog)
39
39
-**`ff-brick`** — experimental TUI frontend (included in stack.yaml)
40
-
-**`ff-gtk`**, **`ff-qtah`** — experimental GUI frontends (not in stack.yaml)
40
+
-**`ff-qtah`** — experimental Qt GUI frontend (included in stack.yaml)
41
+
-**`ff-gtk`** — experimental GTK GUI frontend (not in stack.yaml)
41
42
42
43
### Core modules (`ff-core/lib/`)
43
44
@@ -71,6 +72,25 @@ Main types: `Note` (tasks and wiki pages), `Contact`, `Tag`, `Track` (external i
71
72
72
73
Data is stored on the filesystem via `ron-storage` (from the `ff-notes/ron` repo, pinned by git commit in `stack.yaml`). Each collection (`note`, `contact`, `tag`) is a subdirectory under the data dir. Documents are identified by `DocId` (a RON UUID).
73
74
75
+
### ff-qtah: Qt GUI frontend
76
+
77
+
The Qt frontend uses [qtah](https://hackage.haskell.org/package/qtah) bindings. Key constraints:
78
+
79
+
**Thread safety**: All Qt UI operations must happen on the main (GUI) thread. Never call Qt functions from `forkIO` threads — this is UB and causes unpredictable behavior (e.g., sorting not applied). The correct pattern for background data loading:
80
+
81
+
```haskell
82
+
-- background thread: only pure IO, no Qt calls
83
+
void . forkIO $do
84
+
result <- loadData
85
+
putMVar resultVar result
86
+
-- main thread: receives result and updates UI
87
+
runInGuiThreadWhenReady resultVar $\result -> updateUI result
88
+
```
89
+
90
+
`runInGuiThreadWhenReady` (in `FF.Qt`) creates a 0ms repeating timer on the main thread, and when the `MVar` is filled it calls `QObject.deleteLater` to stop itself, then runs the action.
91
+
92
+
**qtah API gaps**: `QTimer` in qtah does not expose `stop` — use `QObject.deleteLater` to destroy the timer from within its own callback.
93
+
74
94
### External dependencies (extra-deps)
75
95
76
96
The RON libraries (`ron`, `ron-rdt`, `ron-schema`, `ron-storage`) are pulled directly from the `ff-notes/ron` GitHub repo at a specific commit, not from Hackage.
0 commit comments