v0.1.6: highlight the folder a dragged playlist would drop into
This commit is contained in:
+39
-12
@@ -157,6 +157,9 @@ class PlaylistTree(QTreeWidget):
|
||||
super().__init__(parent)
|
||||
self._manager = manager
|
||||
self._drop_target: QTreeWidgetItem | None = None
|
||||
# KIND_ROLE value a drop during the active drag would land on
|
||||
# ("folder" for internal playlist moves, "playlist" for track drops).
|
||||
self._drag_target_kind: str | None = None
|
||||
|
||||
self.setHeaderHidden(True)
|
||||
self.setIndentation(14)
|
||||
@@ -396,13 +399,14 @@ class PlaylistTree(QTreeWidget):
|
||||
# so edge auto-scroll stays live even over non-folder rows —
|
||||
# otherwise scrolling down to a distant folder would be nearly
|
||||
# impossible past the playlists in between.
|
||||
self._clear_drop_target()
|
||||
self._drag_target_kind = "folder"
|
||||
target = self.itemAt(pos)
|
||||
kind = target.data(0, KIND_ROLE) if target else ""
|
||||
if kind in ("folder", "") or target is None:
|
||||
event.acceptProposedAction()
|
||||
else:
|
||||
event.ignore()
|
||||
self._highlight_drop_target(pos, "folder")
|
||||
self._update_autoscroll(pos, accepted=True)
|
||||
return
|
||||
if not event.mimeData().hasFormat(TRACKS_MIME):
|
||||
@@ -410,23 +414,48 @@ class PlaylistTree(QTreeWidget):
|
||||
self._update_autoscroll(pos, accepted=False)
|
||||
event.ignore()
|
||||
return
|
||||
self._drag_target_kind = "playlist"
|
||||
target = self.itemAt(pos)
|
||||
if target and target.data(0, KIND_ROLE) == "playlist":
|
||||
self._set_drop_target(target)
|
||||
event.acceptProposedAction()
|
||||
self._update_autoscroll(pos, accepted=True)
|
||||
else:
|
||||
self._clear_drop_target()
|
||||
event.ignore()
|
||||
self._update_autoscroll(pos, accepted=False)
|
||||
self._highlight_drop_target(pos, "playlist")
|
||||
|
||||
def dragLeaveEvent(self, event):
|
||||
self._clear_drop_target()
|
||||
self._stop_autoscroll()
|
||||
super().dragLeaveEvent(event)
|
||||
|
||||
def _highlight_drop_target(self, pos: QPoint, kind: str):
|
||||
"""Highlight the row at ``pos`` if it's a valid target for the active
|
||||
drag — a folder for internal playlist moves, a playlist for track
|
||||
drops — so the user can see where the drop would land. Clears any
|
||||
stale highlight otherwise. A folder inside the dragged row's own
|
||||
branch is never highlighted: the manager would reject that drop as a
|
||||
cycle, so lighting it up would lie."""
|
||||
target = self.itemAt(pos)
|
||||
ok = target is not None and target.data(0, KIND_ROLE) == kind
|
||||
if ok and kind == "folder":
|
||||
ok = not self._is_own_branch(self.currentItem(), target)
|
||||
if ok:
|
||||
self._set_drop_target(target)
|
||||
else:
|
||||
self._clear_drop_target()
|
||||
|
||||
@staticmethod
|
||||
def _is_own_branch(dragged, item) -> bool:
|
||||
"""True if ``item`` is the dragged row or inside its subtree."""
|
||||
while item is not None:
|
||||
if item is dragged:
|
||||
return True
|
||||
item = item.parent()
|
||||
return False
|
||||
|
||||
def _set_drop_target(self, item):
|
||||
"""Highlight the playlist row a drop would land on (cleared on the way
|
||||
"""Highlight the row a drop would land on (cleared on the way
|
||||
out). Foreground is set too so the name stays legible on the highlight."""
|
||||
if item is self._drop_target:
|
||||
return
|
||||
@@ -463,18 +492,16 @@ class PlaylistTree(QTreeWidget):
|
||||
self._autoscroll_timer.stop()
|
||||
return
|
||||
# The cursor may be held still while rows scroll under it, so keep the
|
||||
# drop-target highlight on the row now beneath it (track drags only;
|
||||
# internal playlist moves never set a drop target).
|
||||
if self._autoscroll_pos is not None and self._drop_target is not None:
|
||||
target = self.itemAt(self._autoscroll_pos)
|
||||
if target and target.data(0, KIND_ROLE) == "playlist":
|
||||
self._set_drop_target(target)
|
||||
else:
|
||||
self._clear_drop_target()
|
||||
# drop-target highlight on the row now beneath it.
|
||||
if (self._autoscroll_pos is not None
|
||||
and self._drag_target_kind is not None):
|
||||
self._highlight_drop_target(self._autoscroll_pos,
|
||||
self._drag_target_kind)
|
||||
|
||||
def _stop_autoscroll(self):
|
||||
self._autoscroll_dir = 0
|
||||
self._autoscroll_pos = None
|
||||
self._drag_target_kind = None
|
||||
self._autoscroll_timer.stop()
|
||||
|
||||
def dropEvent(self, event):
|
||||
|
||||
Reference in New Issue
Block a user