Commit Graph

10 Commits

Author SHA1 Message Date
Levi Neely 3d46936613 Hide outline until a document is selected
When no document was selected, the OutlineView's own "No sections"
empty-state label (count === 0 with an empty model) rendered centered
in the same pane as the "Select a document" placeholder. Both used
anchors.centerIn: parent, so the two messages overlapped and read as
crunched text. Hide the OutlineView until currentDoc is set so only the
"Select a document" placeholder shows.
2026-10-06 12:54:26 +02:00
Levi Neely 42f8aaa62c Wrap and space the empty-state placeholder in main pane
The centered placeholder ("Select a document" / "Not connected: ...")
had no width constraint, so long text rendered as a single over-wide,
cramped line. Constrain its width, center-align, enable word wrap, and
set lineHeight 1.3 so the message breathes.
2026-10-06 12:52:59 +02:00
Levi Neely e418177bad Give sidebar document entries more breathing room 2026-10-06 11:31:37 +02:00
Levi Neely b329bcebd0 Support cross-file refile via spring-loaded drag
Dragging a section's grip can now drop it into another file: hover the
drag over a document in the sidebar for ~450ms and the view springs to
that file, after which the normal in-file drop chooses the exact
position. The subtree is removed from the source file and inserted in the
target (reparented, re-leveled, and placed before the chosen sibling).

The key change is making the drag scene-level so it survives the view
switching files mid-drag:

Model (decouple source from view):
- beginDrag(row) captures (sourceDoc, sourceId) by value; dragSourceDoc()/
  dragSourceId() expose them for the drag payload.
- resolveDrop(gapAboveRow, desiredLevel) resolves against the current view
  and excludes the dragged subtree only when it lives in the current file
  (so cross-file drags, whose source isn't present, exclude nothing).
- commitDrag(parentId, beforeId) issues refile <sourceDoc> <id> <curDoc>
  … so it targets whatever file is now shown; endDrag() clears state.
- Drops the old row-indexed refileSection/resolveDrop.

GUI:
- OutlineView: the grip starts a Qt Automatic (scene) drag on an invisible
  proxy carrying the section payload (keys ["ork-section"]); a DropArea
  over the outline resolves the live position and commits on drop. Because
  the drag is scene-level, springing the view no longer cancels it.
- Main.qml: each sidebar document is a DropArea with a 450ms spring Timer
  that selects that document when a section is held over it; it highlights
  while a drag hovers.

Verified: cross-file refile over 9P (refile src mover tgt two child) moves
the subtree between files, re-levels it, inserts before the sibling, and
carries its body. Server tests still green. GUI builds clean.

The scene-drag gesture and spring timing can't be verified headlessly;
the data path (begin/resolve/commit + cross-doc refile) is confirmed.
2026-10-05 09:35:34 +02:00
Levi Neely c4dc18cbfc Add an org path setting with a directory picker to Settings
Let the user change the server's scanned org directory from the GUI,
backed by the server's /cfg file. The server expands a leading ~ and
rescans, so the client only sends a path.

OrkClient:
- orgPath() reads /cfg and extracts the org_path value (basic TOML
  string, with escapes).
- setOrgPath() writes org_path to /cfg with proper TOML escaping, and
  emits orgPathChanged() on success. On failure the server's message is
  left in error().

SettingsDialog:
- New "Org Path" group: a text field prefilled from orgPath() when the
  dialog opens, a Browse… button opening a FolderDialog (QtQuick.Dialogs),
  and an Apply button. The folder picker's file:// URL is converted to a
  local path. A status line shows success or the server error. The field
  accepts a raw path too, so ~ and typed paths work.

Main.qml:
- On orgPathChanged, clear the selection and refresh the document list so
  the sidebar reflects the newly scanned directory.

Verified over 9P against a live server using the exact TOML setApply
writes: empty initial config, ~/org expanded to $HOME/org, and an
absolute Browse-style path each switch the served documents. GUI builds
clean (QML cache compiles SettingsDialog).
2026-10-02 12:11:19 +02:00
Levi Neely b2953a7caf Fix font and scaling in Main.qml
Replace all pixelSize with pointSize using baseFontSize:
- Sidebar width: 16em (was 220px)
- Header margins: 1em (was 12px)
- Document title: baseFontSize (was 13px)
- Document name: baseFontSize-2 (was 10px)
- Section header: baseFontSize-1 (was 11px)
- Delegate padding: 0.8em / 0.4em
- All spacing font-relative
2026-10-01 10:25:03 +02:00
Levi Neely 3d2edf1807 Fix system theme consistency
- In system mode, read palette from QGuiApplication::palette() rather
  than parsing kdeglobals (platform plugin already handles this)
- Don't call setPalette() in system mode — let Qt handle it
- Add isOverriding property for QML to check mode
- Use Fusion style by default for consistent palette respect
- Improved fallback logic in systemSchemePath() for dark/light detection
- Added /etc/xdg/kdeglobals as fallback for system-wide defaults
2026-10-01 09:15:31 +02:00
Levi Neely 5677be6236 Add font customization and UI scaling
ThemeManager now supports:
  - fontFamily, fontSize, fontStyle with full QFontDatabase access
  - uiScale (0.5x to 4.0x) saved to theme.conf
  - resetFont() to return to system defaults

SettingsDialog provides UI for:
  - Color scheme selection (all installed KDE schemes)
  - Font family/style/size with live preview
  - UI scale slider with percentage display

OutlineView uses pointSize (scalable) instead of pixelSize (fixed).
All font sizes derived from theme.fontSize or baseFontSize.
2026-10-01 09:11:45 +02:00
Levi Neely 64c7272f70 Add KDE color scheme support
ThemeManager reads .colors files from /usr/share/color-schemes and
~/.local/share/color-schemes (KDE standard locations). Supports:
  - 'system' mode: follows kdeglobals ColorScheme setting
  - explicit scheme name: forces specific scheme (BreezeDark, etc.)

QML now uses theme.* colors throughout instead of hardcoded Nord values.
Org-mode semantic colors (todoColor, doneColor, priorityAColor, etc.)
adjust automatically for dark/light themes.

Settings saved to ~/.config/orkmode/theme.conf
2026-10-01 09:08:15 +02:00
Levi Neely 71a89943ae Add v0.3 read-only Qt6/QML GUI (9P client)
A standalone Qt6/QML app in ui/ that speaks 9P to ork-server; no FFI,
no privileged path. All org logic stays in the server.

- p9client: minimal synchronous 9P2000 client over QTcp/QLocalSocket
- orkclient: QML-facing facade (read/list/listDirs/write/rdwr/docs)
- documentmodel: lazy QAbstractItemModel of the section tree, with a
  BodyRole that reads /<doc>/<id>/body (planning line + :PROPERTIES:
  drawer stripped, since those are shown as structural objects)
- Main.qml: document sidebar + outline; OutlineView.qml: folding
  TreeView rendering keyword/priority/title/tags/timestamps as distinct
  objects, with section body shown inline beneath each headline
- main.cpp: --addr/$ORK_ADDR, --selftest (headless outline dump),
  --shot (headless window grab for debugging)
- CMake build; binary emitted to bin/ to avoid the QML-module-URI vs
  target-name directory clash

Known issue: inline body layout still needs work (row sizing/overlap
when bodies wrap); to be iterated.
2026-10-01 02:02:53 +02:00