diff --git a/po/POTFILES b/po/POTFILES index fef308f2..10bab163 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -14,6 +14,5 @@ src/Views/SystemView/SystemMemoryView.vala src/Views/SystemView/SystemNetworkView.vala src/Views/SystemView/SystemStorageView.vala src/Views/SystemView/SystemGPUView.vala -src/Widgets/Headerbar/Search.vala src/Widgets/Statusbar/Statusbar.vala src/Widgets/WidgetResource/WidgetResource.vala diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 8b0c00f5..fd1c4297 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -4,7 +4,6 @@ */ public class Monitor.MainWindow : Hdy.ApplicationWindow { - public Search search { get; private set; } public ProcessView process_view { get; private set; } public MainWindow (MonitorApp app) { @@ -45,12 +44,13 @@ public class Monitor.MainWindow : Hdy.ApplicationWindow { tooltip_text = (_("Settings")) }; - search = new Search (this) { + var search_entry = new Gtk.SearchEntry () { + placeholder_text = _("Search process name or PID"), valign = CENTER }; var search_revealer = new Gtk.Revealer () { - child = search, + child = search_entry, transition_type = SLIDE_LEFT }; @@ -106,7 +106,7 @@ public class Monitor.MainWindow : Hdy.ApplicationWindow { this.show_all (); }); - key_press_event.connect (search.handle_event); + key_press_event.connect (search_entry.handle_event); this.delete_event.connect (() => { int window_width, window_height; @@ -130,8 +130,32 @@ public class Monitor.MainWindow : Hdy.ApplicationWindow { dbusserver.indicator_state (MonitorApp.settings.get_boolean ("indicator-state")); stack.visible_child_name = MonitorApp.settings.get_string ("opened-view"); + search_entry.search_changed.connect (() => { + // collapse tree only when search is focused and changed + if (search_entry.is_focus) { + process_view.process_tree_view.collapse_all (); + } + + process_view.needle = search_entry.text; + + // focus on child row to avoid the app crashes by clicking "Kill/End Process" buttons in headerbar + process_view.process_tree_view.focus_on_child_row (); + search_entry.grab_focus (); + + if (search_entry.text != "") { + search_entry.insert_at_cursor (""); + } + }); + + search_entry.activate.connect (() => { + process_view.process_tree_view.focus_on_first_row (); + }); + var search_action = new GLib.SimpleAction ("search", null); - search_action.activate.connect (() => search.activate_entry ()); + search_action.activate.connect (() => { + search_entry.text = ""; + search_entry.search_changed (); + }); add_action (search_action); } @@ -145,5 +169,4 @@ public class Monitor.MainWindow : Hdy.ApplicationWindow { this.maximize (); } } - } diff --git a/src/Views/ProcessView/ProcessView.vala b/src/Views/ProcessView/ProcessView.vala index e93fa1bd..5ddf4ad9 100644 --- a/src/Views/ProcessView/ProcessView.vala +++ b/src/Views/ProcessView/ProcessView.vala @@ -4,16 +4,24 @@ */ public class Monitor.ProcessView : Gtk.Box { - public TreeViewModel treeview_model { get; private set; } + public string needle = ""; + public CPUProcessTreeView process_tree_view { get; private set; } private ProcessInfoView process_info_view; + private TreeViewModel treeview_model; construct { treeview_model = new TreeViewModel (); + var filter_model = new Gtk.TreeModelFilter (treeview_model, null); + filter_model.set_visible_func (filter_func); + + var sort_model = new Gtk.TreeModelSort.with_model (filter_model); + process_tree_view = new CPUProcessTreeView (treeview_model); process_tree_view.process_selected.connect ((process) => on_process_selected (process)); + process_tree_view.set_model (sort_model); var process_tree_view_scrolled = new Gtk.ScrolledWindow (null, null) { child = process_tree_view @@ -32,6 +40,8 @@ public class Monitor.ProcessView : Gtk.Box { paned.pack2 (process_info_view, false, false); add (paned); + + notify["needle"].connect (filter_model.refilter); } public void on_process_selected (Process process) { @@ -51,4 +61,42 @@ public class Monitor.ProcessView : Gtk.Box { }); } + + private bool filter_func (Gtk.TreeModel model, Gtk.TreeIter iter) { + string name_haystack; + int pid_haystack; + string cmd_haystack; + bool found = false; + + if (needle.length == 0) { + return true; + } + + model.get (iter, Column.NAME, out name_haystack, -1); + model.get (iter, Column.PID, out pid_haystack, -1); + model.get (iter, Column.CMD, out cmd_haystack, -1); + + // sometimes name_haystack is null + if (name_haystack != null) { + bool name_found = name_haystack.casefold ().contains (needle.casefold ()) || false; + bool pid_found = pid_haystack.to_string ().casefold ().contains (needle.casefold ()) || false; + bool cmd_found = cmd_haystack.casefold ().contains (needle.casefold ()) || false; + found = name_found || pid_found || cmd_found; + } + + Gtk.TreeIter child_iter; + bool child_found = false; + + if (model.iter_children (out child_iter, iter)) { + do { + child_found = filter_func (model, child_iter); + } while (model.iter_next (ref child_iter) && !child_found); + } + + if (child_found && needle.length > 0) { + process_tree_view.expand_all (); + } + + return found || child_found; + } } diff --git a/src/Widgets/Headerbar/Search.vala b/src/Widgets/Headerbar/Search.vala deleted file mode 100644 index b6b3316c..00000000 --- a/src/Widgets/Headerbar/Search.vala +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-or-later - * SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io) - */ - -public class Monitor.Search : Gtk.SearchEntry { - public MainWindow window { get; construct; } - private Gtk.TreeModelFilter filter_model; - private CPUProcessTreeView process_tree_view; - - public Search (MainWindow window) { - Object (window: window); - } - - construct { - this.process_tree_view = window.process_view.process_tree_view; - this.placeholder_text = _("Search Process"); - this.tooltip_markup = Granite.markup_accel_tooltip ({ "F" }, _("Type process name or PID to search")); - - filter_model = new Gtk.TreeModelFilter (window.process_view.treeview_model, null); - connect_signal (); - filter_model.set_visible_func (filter_func); - // process_tree_view.set_model (filter_model); - - var sort_model = new Gtk.TreeModelSort.with_model (filter_model); - process_tree_view.set_model (sort_model); - } - - private void connect_signal () { - this.search_changed.connect (() => { - // collapse tree only when search is focused and changed - if (this.is_focus) { - process_tree_view.collapse_all (); - } - - filter_model.refilter (); - - // focus on child row to avoid the app crashes by clicking "Kill/End Process" buttons in headerbar - process_tree_view.focus_on_child_row (); - this.grab_focus (); - - if (this.text != "") { - this.insert_at_cursor (""); - } - }); - - activate.connect (() => { - window.process_view.process_tree_view.focus_on_first_row (); - }); - } - - private bool filter_func (Gtk.TreeModel model, Gtk.TreeIter iter) { - string name_haystack; - int pid_haystack; - string cmd_haystack; - bool found = false; - var needle = this.text; - - // should help with assertion errors, donno - // if (needle == null) return true; - - if (needle.length == 0) { - return true; - } - - model.get (iter, Column.NAME, out name_haystack, -1); - model.get (iter, Column.PID, out pid_haystack, -1); - model.get (iter, Column.CMD, out cmd_haystack, -1); - - // sometimes name_haystack is null - if (name_haystack != null) { - bool name_found = name_haystack.casefold ().contains (needle.casefold ()) || false; - bool pid_found = pid_haystack.to_string ().casefold ().contains (needle.casefold ()) || false; - bool cmd_found = cmd_haystack.casefold ().contains (needle.casefold ()) || false; - found = name_found || pid_found || cmd_found; - } - - - Gtk.TreeIter child_iter; - bool child_found = false; - - if (model.iter_children (out child_iter, iter)) { - do { - child_found = filter_func (model, child_iter); - } while (model.iter_next (ref child_iter) && !child_found); - } - - if (child_found && needle.length > 0) { - process_tree_view.expand_all (); - } - - return found || child_found; - } - - // reset filter, grab focus and insert the character - public void activate_entry (string search_text = "") { - this.text = ""; - this.search_changed (); - this.insert_at_cursor (search_text); - } - -} diff --git a/src/meson.build b/src/meson.build index 492dd1ad..41ff3c6c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -26,7 +26,6 @@ source_app_files = [ 'Views/ProcessView/ProcessInfoView/OpenFilesTreeView.vala', # Widgets - 'Widgets/Headerbar/Search.vala', 'Widgets/Statusbar/Statusbar.vala', 'Widgets/Labels/LabelRoundy.vala', 'Widgets/Chart/Chart.vala',