Skip to content
Merged
26 changes: 7 additions & 19 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +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;
private SearchBar search_bar;
private Gtk.Revealer search_revealer;

construct {
Expand All @@ -22,12 +22,11 @@ public class Music.MainWindow : Gtk.ApplicationWindow {

repeat_button = new Gtk.Button ();

search_entry = new Gtk.SearchEntry () {
placeholder_text = _("Search titles in playlist")
};
ListModel list_model;
search_bar = new SearchBar (playback_manager.queue_liststore, out list_model);

search_revealer = new Gtk.Revealer () {
child = search_entry
child = search_bar
};

playback_manager.bind_property (
Expand All @@ -51,7 +50,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
hexpand = true,
vexpand = true
};
queue_listbox.bind_model (playback_manager.queue_liststore, create_queue_row);
queue_listbox.bind_model (list_model, create_queue_row);
queue_listbox.set_placeholder (queue_placeholder);

var scrolled = new Gtk.ScrolledWindow () {
Expand Down Expand Up @@ -205,18 +204,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow {
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 (() => {
search_bar.activated.connect (() => {
var selected = queue_listbox.get_selected_row ();
if (selected != null) {
selected.activate ();
Expand All @@ -226,7 +214,7 @@ public class Music.MainWindow : Gtk.ApplicationWindow {

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

Expand Down
22 changes: 0 additions & 22 deletions src/PlaybackManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -371,28 +371,6 @@ 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
52 changes: 52 additions & 0 deletions src/Widgets/SearchBar.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* SPDX-License-Identifier: LGPL-3.0-or-later
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
*/

public class Music.SearchBar : Granite.Bin {
public signal void activated ();

public ListModel list_model { get; construct; }

private Gtk.StringFilter filter;
private Gtk.FilterListModel filter_model;
private Gtk.SearchEntry search_entry;

/**
* @param new_model the new model with the search applied. Make sure to use this one in further UI
* instead of the old given model.
*/
public SearchBar (ListModel list_model, out ListModel new_model) {
Object (list_model: list_model);

new_model = filter_model;
}

construct {
var expression = new Gtk.PropertyExpression (typeof (AudioObject), null, "title");

filter = new Gtk.StringFilter (expression) {
ignore_case = true,
match_mode = SUBSTRING
};

filter_model = new Gtk.FilterListModel (list_model, filter);

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

child = search_entry;

search_entry.search_changed.connect (on_search_changed);
search_entry.activate.connect (() => activated ());
}

private void on_search_changed () {
filter.search = search_entry.text;
}

public void start_search () {
search_entry.grab_focus ();
}
}
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ sources = [
'DBus/MprisRoot.vala',
'Views/NowPlayingView.vala',
'Widgets/AlbumImage.vala',
'Widgets/SearchBar.vala',
'Widgets/SeekBar.vala',
'Widgets/TrackRow.vala',
]
Expand Down