diff --git a/src/audrey.gresource.xml b/src/audrey.gresource.xml
index de54e33..9fd414e 100644
--- a/src/audrey.gresource.xml
+++ b/src/audrey.gresource.xml
@@ -4,6 +4,7 @@
style.css
gtk/help-overlay.ui
ui/play_queue.ui
+ ui/play_queue_song.ui
ui/setup.ui
ui/window.ui
diff --git a/src/ui/meson.build b/src/ui/meson.build
index b168e86..a0ba2ba 100644
--- a/src/ui/meson.build
+++ b/src/ui/meson.build
@@ -1,7 +1,7 @@
blueprints = custom_target(
'blueprints',
- input: files('play_queue.blp', 'setup.blp', 'window.blp'),
- output: ['play_queue.ui', 'setup.ui', 'window.ui'],
+ input: files('play_queue.blp', 'play_queue_song.blp', 'setup.blp', 'window.blp'),
+ output: ['play_queue.ui', 'play_queue_song.ui', 'setup.ui', 'window.ui'],
command: [
find_program('blueprint-compiler'),
'batch-compile',
diff --git a/src/ui/play_queue.blp b/src/ui/play_queue.blp
index b19271e..862453d 100644
--- a/src/ui/play_queue.blp
+++ b/src/ui/play_queue.blp
@@ -15,48 +15,13 @@ template $UiPlayQueue: Adw.NavigationPage {
}
ScrolledWindow {
- ColumnView view {
- styles [ "data-table" ]
-
+ ListView view {
model: bind template.selection;
- //ColumnViewColumn {
- // factory: SignalListItemFactory {
- // setup => $on_delete_cell_setup ();
- // };
- //}
-
- ColumnViewColumn {
- title: _("Title");
- expand: true;
-
- factory: BuilderListItemFactory {
- template ColumnViewCell {
- child: Label {
- halign: start;
- label: bind template.item as <$SubsonicSong>.title;
- tooltip-text: bind template.item as <$SubsonicSong>.title;
- ellipsize: end;
- };
- }
- };
- }
-
- ColumnViewColumn {
- title: _("Artist");
- fixed-width: 200;
-
- factory: BuilderListItemFactory {
- template ColumnViewCell {
- child: Label {
- halign: start;
- label: bind template.item as <$SubsonicSong>.artist;
- tooltip-text: bind template.item as <$SubsonicSong>.artist;
- ellipsize: end;
- };
- }
- };
- }
+ factory: SignalListItemFactory {
+ setup => $on_song_list_setup ();
+ bind => $on_song_list_bind ();
+ };
}
}
}
diff --git a/src/ui/play_queue.vala b/src/ui/play_queue.vala
index a9a64b3..9e06c2c 100644
--- a/src/ui/play_queue.vala
+++ b/src/ui/play_queue.vala
@@ -1,3 +1,17 @@
+[GtkTemplate (ui = "/eu/callcc/audrey/ui/play_queue_song.ui")]
+class Ui.PlayQueueSong : Gtk.ListBoxRow {
+ public uint position { get; set; }
+ public Subsonic.Song song { get; set; }
+
+ [GtkCallback] private string format_duration (int duration) {
+ return "%02d:%02d".printf(duration/60, duration%60);
+ }
+
+ [GtkCallback] private string star_button_icon_name (DateTime? starred) {
+ return starred == null ? "non-starred" : "starred";
+ }
+}
+
[GtkTemplate (ui = "/eu/callcc/audrey/ui/play_queue.ui")]
public class Ui.PlayQueue : Adw.NavigationPage {
public PlayQueueSelection selection { get; default = new PlayQueueSelection (); }
@@ -24,6 +38,19 @@ public class Ui.PlayQueue : Adw.NavigationPage {
private void on_store_items_changed (GLib.ListModel store, uint position, uint removed, uint added) {
this.can_clear_all = store.get_n_items () > 0;
}
+
+ [GtkCallback] private void on_song_list_setup (Gtk.SignalListItemFactory factory, Object object) {
+ var item = object as Gtk.ListItem;
+ item.child = new PlayQueueSong ();
+ }
+
+ [GtkCallback] private void on_song_list_bind (Gtk.SignalListItemFactory factory, Object object) {
+ var item = object as Gtk.ListItem;
+ var child = item.child as PlayQueueSong;
+
+ child.position = item.position+1;
+ child.song = item.item as Subsonic.Song;
+ }
}
// this is a custom SelectionModel that lets us only signal the
diff --git a/src/ui/play_queue_song.blp b/src/ui/play_queue_song.blp
new file mode 100644
index 0000000..9a78050
--- /dev/null
+++ b/src/ui/play_queue_song.blp
@@ -0,0 +1,121 @@
+using Gtk 4.0;
+
+template $UiPlayQueueSong: ListBoxRow {
+ selectable: false;
+
+ Box {
+ focusable: false;
+ spacing: 6;
+
+ Image {
+ visible: false;
+ icon-name: "list-drag-handle";
+ styles [ "drag-handle" ]
+ }
+
+ Box {
+ width-request: 48;
+ focusable: false;
+ homogeneous: true;
+
+ Image {
+ focusable: false;
+ icon-size: normal;
+ //icon-name: "media-playback-start";
+ }
+
+ Label {
+ focusable: false;
+ halign: end;
+ justify: right;
+ styles [ "dim-label", "numeric" ]
+
+ label: bind template.position;
+ }
+ }
+
+ Box title_box {
+ focusable: false;
+ hexpand: true;
+
+ Label {
+ focusable: false;
+ xalign: 0;
+ halign: start;
+ hexpand: true;
+ ellipsize: end;
+ max-width-chars: 90;
+ justify: fill;
+ margin-start: 9;
+
+ label: bind template.song as <$SubsonicSong>.title;
+ }
+ }
+
+ Box artist_box {
+ //visible: false;
+ focusable: false;
+ hexpand: true;
+
+ Label {
+ focusable: false;
+ xalign: 0;
+ halign: start;
+ hexpand: true;
+ ellipsize: end;
+ max-width-chars: 90;
+ justify: fill;
+ margin-start: 9;
+
+ label: bind template.song as <$SubsonicSong>.artist;
+ }
+ }
+
+ Box album_duration_box {
+ focusable: false;
+ hexpand: true;
+ spacing: 6;
+
+ Label {
+ //visible: false;
+ focusable: false;
+ xalign: 0;
+ halign: start;
+ hexpand: true;
+ ellipsize: end;
+ max-width-chars: 90;
+ justify: fill;
+
+ label: bind template.song as <$SubsonicSong>.album;
+ }
+
+ Label {
+ focusable: false;
+ halign: end;
+ hexpand: true;
+ single-line-mode: true;
+ styles [ "numeric" ]
+
+ label: bind $format_duration (template.song as <$SubsonicSong>.duration) as ;
+ }
+ }
+
+ Button {
+ focusable: true;
+ icon-name: bind $star_button_icon_name (template.song as <$SubsonicSong>.starred) as ;
+ styles [ "flat" ]
+ }
+
+ MenuButton {
+ //visible: false;
+ focusable: true;
+ icon-name: "view-more";
+ styles [ "flat" ]
+ }
+ }
+}
+
+SizeGroup {
+ mode: horizontal;
+ widgets [title_box, artist_box, album_duration_box]
+}