1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 FernTech
//! Shared capability types for the data-source drag-and-drop + lazy protocol.
//!
//! These types are the Teksilo-shaped equivalent of Qt's
//! `flags`/`canDropMimeData`/`dropMimeData` (DnD validation) and
//! `canFetchMore`/`fetchMore` (lazy loading), expressed as defaulted methods on
//! [`ListDataSource`](crate::ListDataSource) and
//! [`TreeDataSource`](crate::TreeDataSource). A source *owns* the answer to
//! "may this drop happen?" (`can_accept`) and "apply the move" (`accept_drop`);
//! the view merely renders the source's verdict and routes the commit. This is
//! what lets an external source of truth (e.g. a Qleany entity store) drive a
//! view without the view ever mutating a mirror model.
//!
//! ## Key types
//!
//! - [`ItemKey`] — blanket identity trait for any `Clone + Eq + Hash + Debug + 'static` type.
//! - [`RowState`] — whether a lazy row's data is resident (`Ready`) or still loading (`Loading`).
//! - [`DragEligibility`] — per-row drag gate returned by `ListDataSource::drag`.
//! - [`DropPosition`] — where a drop lands relative to the target row.
//! - [`DragSource`] — who is dragging: the same view (intra-view reorder) or a foreign view/OS drop.
//! - [`DropQuery`] / [`DropResponse`] — hover-time can-I-drop? query and verdict.
//! - [`DropCommit`] — the committed drop handed to `accept_drop`.
//!
//! ```ignore
//! // Example: implementing can_accept for a custom ListDataSource
//! fn can_accept(&self, query: &teksilo_data::DropQuery<'_, usize>) -> teksilo_data::DropResponse {
//! match &query.source {
//! teksilo_data::DragSource::SameView { .. } => teksilo_data::DropResponse::Accept,
//! teksilo_data::DragSource::Foreign { .. } => teksilo_data::DropResponse::Reject,
//! }
//! }
//! ```
use DragPayload;
/// A stable, hashable identity for a row/node. Blanket-implemented for every
/// `Clone + Eq + Hash + Debug + 'static` type, so `usize`, `NodeId`, `i64`,
/// `String`, `Uuid`, … all qualify with no extra work.
///
/// In-memory models use positional keys (`usize` for `ListModel`, `NodeId` for
/// `TreeModel`); external sources use their own domain key (an entity id), which
/// is exactly what removes the need to mirror them into a built-in model.
/// Whether a realized row's data is resident yet. A windowed/lazy source returns
/// `Loading` for indices outside its resident window; the view renders a
/// placeholder skeleton for those and calls `request_window` to pull them.
/// Where, relative to a target row, a drop lands. `Into` (reparent) is only
/// meaningful for trees; flat lists reject it.
/// Whether a row may begin a drag at all (the per-item transferable gate, Qt's
/// `Qt::ItemIsDragEnabled` / `TabBar`'s `with_transferable_predicate`).
/// Who is dragging, from the receiving source's point of view.
///
/// `SameView` is an intra-view reorder identified by the dragged row's key.
/// `Foreign` is everything else — an in-app drag from *another* view or an OS
/// drop — carried as a type-erased [`DragPayload`] the source downcasts itself
/// (e.g. a designer source downcasts to its palette-drop type, a list source to
/// its item type, an OS drop to files). This single distinction is exactly what
/// `TabBar` already encodes via its `source_bar_id`.
/// A hover-time question posed to a source: "may `source` drop at `position`
/// relative to `target`?" The source answers with a [`DropResponse`].
/// A source's verdict on a [`DropQuery`]. Drives the hover affordance and gates
/// the commit.
/// A drop the user actually committed, handed to `accept_drop` to apply.