fix drag and drop

This commit is contained in:
Erica Z 2024-11-05 16:25:17 +01:00
parent 930430d5ec
commit b5fadce142
4 changed files with 71 additions and 23 deletions

View file

@ -3,10 +3,10 @@ using Gtk 4.0;
template $AudreyUiPlayQueueSong: Box { template $AudreyUiPlayQueueSong: Box {
height-request: 48; height-request: 48;
spacing: 12; spacing: 12;
margin-start: 6;
margin-end: 6;
Box { Box {
margin-start: 6;
width-request: 36; width-request: 36;
focusable: false; focusable: false;
homogeneous: true; homogeneous: true;
@ -116,20 +116,24 @@ template $AudreyUiPlayQueueSong: Box {
valign: center; valign: center;
} }
MenuButton { Box {
// visible: false; MenuButton {
focusable: true; // visible: false;
icon-name: "view-more"; focusable: true;
icon-name: "view-more";
styles [ styles [
"flat" "flat"
] ]
valign: center; valign: center;
popover: PopoverMenu { popover: PopoverMenu {
menu-model: song-menu; menu-model: song-menu;
}; };
}
margin-end: 6;
} }
DragSource { DragSource {

View file

@ -19,6 +19,11 @@
min-height: 15px; min-height: 15px;
} }
/* make drag and drop indicator take up entire perimeter */
#play-queue listview row {
padding: 0;
}
#play-queue .playing label.title { #play-queue .playing label.title {
font-weight: bold; font-weight: bold;
} }

View file

@ -112,8 +112,7 @@ mod imp {
fn on_drag_prepare(&self, x: f64, y: f64) -> Option<gdk::ContentProvider> { fn on_drag_prepare(&self, x: f64, y: f64) -> Option<gdk::ContentProvider> {
if self.draggable.get() { if self.draggable.get() {
self.drag_pos.replace((x as i32, y as i32)); self.drag_pos.replace((x as i32, y as i32));
let value = self.obj().to_value(); Some(gdk::ContentProvider::for_value(&self.obj().to_value()))
Some(gdk::ContentProvider::for_value(&value))
} else { } else {
None None
} }
@ -122,6 +121,7 @@ mod imp {
#[template_callback] #[template_callback]
fn on_drag_begin(&self, drag: &gdk::Drag) { fn on_drag_begin(&self, drag: &gdk::Drag) {
let drag_widget = gtk::ListBox::new(); let drag_widget = gtk::ListBox::new();
drag_widget.add_css_class("boxed-list");
let drag_row: super::Song = glib::Object::new(); let drag_row: super::Song = glib::Object::new();
drag_row.set_draggable(false); drag_row.set_draggable(false);
@ -148,19 +148,23 @@ mod imp {
} }
#[template_callback] #[template_callback]
fn on_drop(&self, _value: glib::Value, _x: f64, _y: f64) -> bool { // why BoxedValue? see https://discourse.gnome.org/t/gtk-rs-passing-widget-as-gvalue-through-drag-and-drop-with-composite-template/16449/2
/* FIXME: WrongValueType(ValueTypeMismatchError { actual: GValue, requested: AudreyUiPlayQueueSong }) fn on_drop(&self, value: glib::BoxedValue, _x: f64, _y: f64) -> bool {
let source: super::Song = value.get().unwrap(); let source: super::Song = value.get().unwrap();
source.imp().drag_widget.set(None); source.imp().drag_widget.set(None);
self.obj().playbin().move_track( let from = source.position();
source.displayed_position() - 1, let to = self.obj().position();
self.obj().displayed_position() - 1,
);
true */ // see playlist_move for justification
false if from < to {
self.obj().window().playlist_move(from, to + 1);
} else {
self.obj().window().playlist_move(from, to);
}
true
} }
fn set_playlist_pos(&self, playlist_pos: i32) { fn set_playlist_pos(&self, playlist_pos: i32) {

View file

@ -627,4 +627,39 @@ impl Window {
} }
} }
} }
pub fn playlist_move(&self, from: u32, to: u32) {
// NOTE: for mpv, to refers to the "gap" right before i
// so playlist-move i 0 makes a track the first
// playlist-move i 1 makes a track the second
// and playlist-move i playlist-count makes a track the last
// (so if to is the position of another track, from is left behind to)
self.imp()
.mpv
.command(["playlist-move", &from.to_string(), &to.to_string()])
.unwrap();
if from < to {
// F1234T -> 1234FT
let mut spliced = Vec::with_capacity((to - from) as usize);
for i in from + 1..to {
spliced.push(self.playlist_model().item(i).unwrap());
}
spliced.push(self.playlist_model().item(from).unwrap());
self.playlist_model()
.splice(from, spliced.len() as u32, &spliced);
} else if to < from {
// T1234F -> FT1234
let mut spliced = Vec::with_capacity((from - to + 1) as usize);
spliced.push(self.playlist_model().item(from).unwrap());
spliced.push(self.playlist_model().item(to).unwrap());
for i in to + 1..from {
spliced.push(self.playlist_model().item(i).unwrap());
}
self.playlist_model()
.splice(to, spliced.len() as u32, &spliced);
}
}
} }