Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement simple search in playlist #765

Merged
merged 11 commits into from
Aug 6, 2024
10 changes: 9 additions & 1 deletion src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,6 +42,8 @@ public class Music.Application : Gtk.Application {

add_action_entries (ACTION_ENTRIES, this);

set_accels_for_action (ACTION_PREFIX + ACTION_FIND, {"<Ctrl>F"});

((SimpleAction) lookup_action (ACTION_PLAY_PAUSE)).set_enabled (false);
((SimpleAction) lookup_action (ACTION_PLAY_PAUSE)).set_state (false);
((SimpleAction) lookup_action (ACTION_NEXT)).set_enabled (false);
Expand Down Expand Up @@ -179,6 +183,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 ());
Expand Down
39 changes: 38 additions & 1 deletion src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
private Gtk.Button repeat_button;
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 ();
Expand All @@ -20,9 +22,20 @@ public class Music.MainWindow : Gtk.ApplicationWindow {

repeat_button = new Gtk.Button ();

search_entry = new Gtk.SearchEntry () {
placeholder_text = _("Search titles in playlist")
};

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_DEFAULT_DECORATION);
queue_header.pack_start (start_window_controls);
Expand Down Expand Up @@ -171,6 +184,30 @@ 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));
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;
}
});

search_entry.activate.connect (() => {
var selected = queue_listbox.get_selected_row ();
if (selected != null) {
selected.activate ();
}
});
}

public void start_search () {
if (search_revealer.child_revealed) {
search_entry.grab_focus ();
}
}

private void action_open () {
Expand Down
30 changes: 29 additions & 1 deletion src/PlaybackManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
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);

Expand Down Expand Up @@ -50,8 +56,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 ();
});

Expand Down Expand Up @@ -348,6 +354,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;
Expand Down