From 294373eb6e3bb2ed76d6deb7aea8c0021b39cba3 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 14:30:12 +0000 Subject: [PATCH 1/6] Add search entry in revealer to queue header --- src/MainWindow.vala | 14 +++++++++++++- src/PlaybackManager.vala | 3 ++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 01a51903e..ddd2ede82 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -7,6 +7,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow { private Gtk.Button repeat_button; private Gtk.Button shuffle_button; private Settings settings; + private Gtk.SearchEntry search_entry; construct { var playback_manager = PlaybackManager.get_default (); @@ -20,9 +21,20 @@ public class Music.MainWindow : Gtk.ApplicationWindow { repeat_button = new Gtk.Button (); + search_entry = new Gtk.SearchEntry () { + placeholder_text = _("Search titles in playlist") + }; + + var search_revealer = new Gtk.Revealer () { + child = search_entry + }; + + playback_manager.bind_property ( + "has-items", search_revealer, "reveal-child", DEFAULT | SYNC_CREATE + ); var queue_header = new Gtk.HeaderBar () { show_title_buttons = false, - title_widget = new Gtk.Label ("") + title_widget = search_revealer }; queue_header.add_css_class (Granite.STYLE_CLASS_FLAT); queue_header.add_css_class (Granite.STYLE_CLASS_DEFAULT_DECORATION); diff --git a/src/PlaybackManager.vala b/src/PlaybackManager.vala index abdc6bdfc..d22a25784 100644 --- a/src/PlaybackManager.vala +++ b/src/PlaybackManager.vala @@ -6,6 +6,7 @@ public class Music.PlaybackManager : Object { public AudioObject? current_audio { get; set; default = null; } public ListStore queue_liststore { get; private set; } + public bool has_items { get; private set; } public int64 playback_position { get; private set; } public signal void invalids_found (int count); @@ -50,8 +51,8 @@ public class Music.PlaybackManager : Object { queue_liststore.items_changed.connect (() => { var shuffle_action_action = (SimpleAction) GLib.Application.get_default ().lookup_action (Application.ACTION_SHUFFLE); + has_items = queue_liststore.get_n_items () > 0; shuffle_action_action.set_enabled (queue_liststore.get_n_items () > 1); - update_next_previous_sensitivity (); }); From 2bf7883ba58ea6de82b451e80aafd91e91b542c6 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 15:19:29 +0000 Subject: [PATCH 2/6] Implement search and select --- src/MainWindow.vala | 7 +++++++ src/PlaybackManager.vala | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index ddd2ede82..86506f9f2 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -171,6 +171,13 @@ public class Music.MainWindow : Gtk.ApplicationWindow { queue_listbox.row_activated.connect ((row) => { playback_manager.current_audio = ((TrackRow) row).audio_object; }); + + search_entry.search_changed.connect (() => { + int pos = playback_manager.find_title (search_entry.text); + if (pos > 0) { + queue_listbox.select_row (queue_listbox.get_row_at_index (pos)); + } + }); } //Array concatenation not permitted for parameters so use a list instead diff --git a/src/PlaybackManager.vala b/src/PlaybackManager.vala index d22a25784..da96e82a6 100644 --- a/src/PlaybackManager.vala +++ b/src/PlaybackManager.vala @@ -349,6 +349,28 @@ public class Music.PlaybackManager : Object { } } + public int find_title (string term) { + var search_object = new AudioObject ("") { + title = term + }; + + int found_at = -1; + uint position; + if (queue_liststore.find_with_equal_func ( + search_object, + (a, b) => { + var term_a = ((AudioObject)a).title.down (); + var term_b = ((AudioObject)b).title.down (); + return term_a.contains (term_b); + }, + out position + )) { + found_at = (int)position; + } + + return found_at; + } + private void update_next_previous_sensitivity () { var next_sensitive = false; var previous_sensitive = false; From 141990854da3b8a4be798fc550db4393c30693aa Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 15:39:03 +0000 Subject: [PATCH 3/6] Scroll to selected item --- src/MainWindow.vala | 4 ++++ src/PlaybackManager.vala | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 86506f9f2..33e3aa3e3 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -176,6 +176,10 @@ public class Music.MainWindow : Gtk.ApplicationWindow { int pos = playback_manager.find_title (search_entry.text); if (pos > 0) { queue_listbox.select_row (queue_listbox.get_row_at_index (pos)); + var adj = scrolled.vadjustment; + // Search entry is hidden if n_items is zero so no need to check + var ratio = (double)pos / (double)playback_manager.n_items; + adj.@value = adj.upper * ratio; } }); } diff --git a/src/PlaybackManager.vala b/src/PlaybackManager.vala index da96e82a6..7147863b1 100644 --- a/src/PlaybackManager.vala +++ b/src/PlaybackManager.vala @@ -7,6 +7,11 @@ public class Music.PlaybackManager : Object { public AudioObject? current_audio { get; set; default = null; } public ListStore queue_liststore { get; private set; } public bool has_items { get; private set; } + public uint n_items { + get { + return queue_liststore != null ? queue_liststore.get_n_items () : 0; + } + } public int64 playback_position { get; private set; } public signal void invalids_found (int count); From e195220e40c45d9e50858b54e76ab3605bfc8946 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 15:48:10 +0000 Subject: [PATCH 4/6] Start playing selected track on search entry activate --- src/MainWindow.vala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 33e3aa3e3..d5e21b3e1 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -182,6 +182,13 @@ public class Music.MainWindow : Gtk.ApplicationWindow { adj.@value = adj.upper * ratio; } }); + + search_entry.activate.connect (() => { + var selected = queue_listbox.get_selected_row (); + if (selected != null) { + selected.activate (); + } + }); } //Array concatenation not permitted for parameters so use a list instead From 19ab8635916a42ecbedf64263d7e4f40e3e946a4 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 14 Dec 2023 16:11:31 +0000 Subject: [PATCH 5/6] Add action to focus search entry --- src/Application.vala | 10 +++++++++- src/MainWindow.vala | 9 ++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 1b3c4df39..57d65127c 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -9,12 +9,14 @@ public class Music.Application : Gtk.Application { public const string ACTION_PLAY_PAUSE = "action-play-pause"; public const string ACTION_PREVIOUS = "action-previous"; public const string ACTION_SHUFFLE = "action-shuffle"; + public const string ACTION_FIND = "action-find"; private const ActionEntry[] ACTION_ENTRIES = { { ACTION_PLAY_PAUSE, action_play_pause, null, "false" }, { ACTION_NEXT, action_next }, { ACTION_PREVIOUS, action_previous }, - { ACTION_SHUFFLE, action_shuffle } + { ACTION_SHUFFLE, action_shuffle }, + { ACTION_FIND, action_find } }; private PlaybackManager? playback_manager = null; @@ -47,6 +49,8 @@ public class Music.Application : Gtk.Application { ((SimpleAction) lookup_action (ACTION_PREVIOUS)).set_enabled (false); ((SimpleAction) lookup_action (ACTION_SHUFFLE)).set_enabled (false); + set_accels_for_action (ACTION_PREFIX + ACTION_FIND, {"F"}); + playback_manager = PlaybackManager.get_default (); var mpris_id = Bus.own_name ( @@ -175,6 +179,10 @@ public class Music.Application : Gtk.Application { playback_manager.shuffle (); } + private void action_find () { + ((MainWindow)active_window).start_search (); + } + private void on_bus_acquired (DBusConnection connection, string name) { try { connection.register_object ("/org/mpris/MediaPlayer2", new MprisRoot ()); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index d5e21b3e1..b2708b76c 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -8,6 +8,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow { private Gtk.Button shuffle_button; private Settings settings; private Gtk.SearchEntry search_entry; + private Gtk.Revealer search_revealer; construct { var playback_manager = PlaybackManager.get_default (); @@ -25,7 +26,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow { placeholder_text = _("Search titles in playlist") }; - var search_revealer = new Gtk.Revealer () { + search_revealer = new Gtk.Revealer () { child = search_entry }; @@ -191,6 +192,12 @@ public class Music.MainWindow : Gtk.ApplicationWindow { }); } + public void start_search () { + if (search_revealer.child_revealed) { + search_entry.grab_focus (); + } + } + //Array concatenation not permitted for parameters so use a list instead private void prepend_directory_files (GLib.File dir, ref SList file_list) { try { From 25bd01da85b6888c52154c112343577744977141 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Mon, 5 Aug 2024 18:40:43 +0100 Subject: [PATCH 6/6] Allow select first row --- src/MainWindow.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 3892f967b..4fcac567e 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -187,7 +187,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow { search_entry.search_changed.connect (() => { int pos = playback_manager.find_title (search_entry.text); - if (pos > 0) { + if (pos >= 0) { queue_listbox.select_row (queue_listbox.get_row_at_index (pos)); var adj = scrolled.vadjustment; // Search entry is hidden if n_items is zero so no need to check