The grip used a bare MouseArea for the drag. Inside the ListView (a Flickable), once the pointer moved past the drag threshold the ListView stole the gesture for flicking, so the grip's positionChanged stopped firing: the drop target was never resolved and release did nothing. Replace the MouseArea with a DragHandler (target: null — it tracks, it doesn't move the item) whose grabPermissions take the pointer grab and refuse to yield it to the Flickable, so the drag is no longer stolen. It reports centroid.scenePosition continuously, mapped to ListView content coordinates via contentItem.mapFromScene, driving the same updateDrop/ commitDrop path. A HoverHandler keeps the hover affordance, and the grip gets a slightly larger hit target. QML compiles (AOT cache build of OutlineView). The drop resolution and refile commit paths were already verified; this restores the gesture that feeds them. |
||
|---|---|---|
| crates | ||
| doc | ||
| ui | ||
| .gitignore | ||
| .gitmodules | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| VISION.md | ||
| notes.org | ||
| test.org | ||
README.md
Orkmode
A standalone org-mode implementation for KDE, built with Rust (parser/core) and C++ (Qt UI).
Project Structure
orkmode/
├── Cargo.toml # Workspace root
├── crates/
│ ├── org-ast/ # AST type definitions
│ │ └── src/
│ │ ├── lib.rs # Module exports
│ │ ├── document.rs # Document, settings
│ │ ├── headline.rs # Section, Headline, Planning
│ │ ├── elements.rs # Block elements (paragraph, list, table, etc.)
│ │ ├── objects.rs # Inline objects (markup, links, etc.)
│ │ ├── timestamp.rs # Timestamp types
│ │ └── span.rs # Source location tracking
│ ├── org-parser/ # Tree-sitter based parser
│ │ ├── build.rs # Compiles tree-sitter-org grammar
│ │ ├── tree-sitter-org/ # Git submodule: nvim-orgmode/tree-sitter-org
│ │ └── src/
│ │ ├── lib.rs # Parser API
│ │ ├── convert.rs # Tree-sitter → AST conversion
│ │ ├── ts.rs # Tree-sitter language bindings
│ │ └── error.rs # Error types
│ ├── ork-cli/ # Command-line interface (9P client)
│ │ └── src/
│ │ ├── main.rs # CLI commands (base + friendly verbs)
│ │ └── client.rs # 9P2000 client
│ └── ork-server/ # 9P server exposing org files
│ └── src/
│ ├── bin/ork-server.rs # Server entry point
│ ├── state.rs # Document state, section ops, ctl verbs
│ ├── namespace.rs # 9P namespace (docs, sections, agenda, query)
│ ├── p9.rs # 9P protocol handling
│ └── virtfs.rs # Virtual filesystem tree
└── ui/ # Qt6/QML GUI (9P client, no FFI)
├── CMakeLists.txt # Qt6 build (Core/Gui/Qml/Quick/Network)
├── src/
│ ├── main.cpp # Entry point; --addr, --selftest
│ ├── p9client.{h,cpp} # Minimal synchronous 9P2000 client
│ ├── orkclient.{h,cpp} # QML-facing façade over the 9P client
│ └── documentmodel.{h,cpp} # Lazy QAbstractItemModel section tree
└── qml/
├── Main.qml # Window, document sidebar, outline
└── OutlineView.qml # Folding TreeView with structural styling
Features
Supported Org Syntax
- Headlines with nesting levels
- TODO keywords (customizable via #+TODO:)
- Priority cookies ([#A], [#B], [#C])
- Tags
- Property drawers
- Planning lines (SCHEDULED, DEADLINE, CLOSED)
- Timestamps (active, inactive, ranges, repeaters)
- Paragraphs
- Plain lists (unordered, ordered, checkboxes)
- Source blocks
- Tables
- Drawers
- Keywords/directives
- Comments
- LaTeX environments
- Inline markup (bold, italic, etc.) - AST types ready, parsing TODO
- Links - AST types ready, parsing TODO
- Footnotes
- Citations
Document Settings
Parses common #+KEYWORD directives:
- TITLE, AUTHOR, EMAIL, DATE
- TODO, SEQ_TODO, TYP_TODO
- PROPERTY, STARTUP, OPTIONS
- FILETAGS, CATEGORY, ARCHIVE
Building
Prerequisites
- Rust 1.70+
- C compiler (for tree-sitter grammar)
- Qt 6.3+ and CMake 3.21+ (for the GUI)
Build
# Build all crates
cargo build
# Run tests
cargo test
# Build release
cargo build --release
GUI
The GUI is a separate Qt6/CMake project that talks to ork-server over 9P.
cmake -S ui -B ui/build -DCMAKE_BUILD_TYPE=Release
cmake --build ui/build -j
# Run against a running ork-server (see below)
./ui/build/bin/orkmode -a unix:///tmp/ork.sock
Usage
Server
Start the 9P server to expose an org directory:
# Unix socket (preferred for local use)
ork-server -a unix:///tmp/ork.sock -d ~/org
# TCP socket
ork-server -a tcp://localhost:5640 -d ~/org
CLI (ork)
ork is a 9P client that talks to ork-server. All org-mode intelligence lives in the server.
# Set the server address (or use -a on each call)
export ORK_ADDR=unix:///tmp/ork.sock
# Base 9P operations
ork ls / # List root namespace
ork read /idx # Read a file
ork write /work/task/keyword DONE # Write a value
# Friendly verbs (compositions of 9P ops)
ork docs # List documents (name + title)
ork sections work # Top-level sections in work.org
ork tree work # Full section outline
ork todos # All TODO items across docs
ork todos work # TODOs in work.org only
# Section details
ork get work my-task # Show section fields
ork set work my-task keyword DONE # Set a field
ork set work my-task tags work:urgent # Set tags (colon-separated)
# Create sections
ork mkdoc notes # Create notes.org
ork add work "* TODO New task :work:" # Add top-level section
ork add work "* Subtask" -p parent-id # Add child section
# TODO management
ork todo work my-task # Cycle to next state
ork todo work my-task DONE # Set explicit state
ork tag work my-task urgent # Add tag
ork tag work my-task urgent -r # Remove tag
# Structural operations
ork mv work my-task up # Reorder among siblings
ork promote work my-task # Decrease level
ork demote work my-task # Increase level
ork rm work my-task # Delete section and subtree
ork refile work my-task archive # Move to another doc
ork refile work my-task archive -p done # As child of 'done' section
ork archive work my-task # Move to work.org_archive
# Properties
ork prop work my-task CUSTOM_ID # Get property
ork prop work my-task EFFORT 2h # Set property
ork prop work my-task EFFORT -d # Delete property
# Agenda views
ork agenda todos # All TODOs
ork agenda today # Items scheduled/due today
ork agenda week # Next 7 days
# Query
ork query 'tag:work' # Match sections by tag
ork query 'tag:work+todo:TODO' # Compound query
ork query 'priority:A' # By priority
# Maintenance
ork reload # Rescan files from disk
ork lint # Validate all documents
ork lint work # Validate one document
Any 9P client works (e.g., plan9port 9p):
9p -a 'unix!/tmp/ork.sock' ls /
9p -a 'unix!/tmp/ork.sock' read /idx
9p -a 'unix!/tmp/ork.sock' write /work/task/keyword DONE
Architecture
Parser Design
The parser uses tree-sitter with the nvim-orgmode/tree-sitter-org grammar.
Benefits:
- Incremental parsing: Only re-parses changed regions
- Error recovery: Produces partial AST even with syntax errors
- Performance: O(n) parsing, minimal memory allocation
- Battle-tested: Used by Neovim's org-mode plugin
AST Design
The AST follows the org-element specification:
- Document: Root node with settings and sections
- Section: Headline + content + children
- Elements: Block-level constructs (paragraphs, lists, blocks)
- Objects: Inline constructs (markup, links, timestamps)
All nodes include source span information for editor integration.
Roadmap
Phase 1: Parser ✓
- Tree-sitter integration
- Core AST types
- Headline/section parsing
- Block element parsing
- Complete inline object parsing
Phase 2: 9P Server ✓
- Document state with locking
- Read/write section fields (keyword, priority, title, tags, timestamps, body)
- Create documents and sections
- Structural ops (delete, move, promote, demote, refile, archive)
- Agenda views (todos, today, week)
- Query interface (tag, todo, priority)
- ctl verbs (reload, lint)
Phase 3: Qt UI (Current)
- Document rendering (read-only)
- Structural styling (keywords, priorities, tags, timestamps)
- Folding/cycling (TreeView)
- Navigation
- Inline editing
- TODO state cycling (click to toggle)
- Tag/property editing
- Syntax highlighting for bodies
Phase 4: Agenda
- Dedicated agenda view panel
- Day/week/month views
- Filtering and sorting
- Custom views
Phase 5: Advanced Features
- Code block execution
- Diagram rendering (mermaid, plantuml)
- Capture templates
- Clock/time tracking
License
GPL-3.0-or-later