Skip to content

Port ProcessTreeView to GTK4#525

Open
stsdc wants to merge 38 commits into
mainfrom
stsdc/gtk4-treeview
Open

Port ProcessTreeView to GTK4#525
stsdc wants to merge 38 commits into
mainfrom
stsdc/gtk4-treeview

Conversation

@stsdc
Copy link
Copy Markdown
Member

@stsdc stsdc commented Feb 26, 2026

The intend is to future proof the process list and lay some ground for a tree view reintroduction.

@stsdc stsdc linked an issue Feb 26, 2026 that may be closed by this pull request
@stsdc stsdc requested a review from a team March 5, 2026 12:27
@stsdc stsdc marked this pull request as ready for review March 5, 2026 13:11
@stsdc stsdc added this to OS 9 Mar 5, 2026
@stsdc stsdc moved this to Needs Review in OS 9 Mar 5, 2026
Comment thread src/meson.build Outdated
Comment thread src/Views/ProcessView/ProcessTreeView/ProcessTreeView.vala Outdated
public class Monitor.ProcessTreeView : Granite.Bin {
private Gtk.ColumnView list;

public ProcessTreeView (TreeViewModel model) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this gobject style?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is it necessary in this case? Model is used only in this constructor.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's maybe not "necessary" but it's best practice for classes to use gobject style construction

Copy link
Copy Markdown
Member

@danirabbit danirabbit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a few comments about code style etc

Comment thread src/Views/ProcessView/ProcessTreeView/ProcessTreeView.vala
Comment thread src/Views/ProcessView/ProcessTreeView/ProcessTreeView.vala Outdated
Comment thread src/Views/ProcessView/ProcessTreeView/ProcessTreeView.vala Outdated
Comment thread src/Views/ProcessView/ProcessTreeView/ProcessTreeView.vala Outdated
Comment thread src/Views/ProcessView/ProcessTreeView/ProcessTreeView.vala Outdated
@danirabbit danirabbit requested a review from a team March 5, 2026 17:20
Comment thread src/Models/TreeViewModel.vala Outdated
Comment thread src/Models/TreeViewModel.vala Outdated
Comment thread src/Models/TreeViewModel.vala Outdated
@stsdc stsdc requested a review from danirabbit May 10, 2026 15:33
@stsdc
Copy link
Copy Markdown
Member Author

stsdc commented May 10, 2026

I have binded all the values from a ProcessRowData to the rows in the ColumnView. This fixed unnecessary list jumps on every update. Thanks to @alice-mkh and sadlyascii for the help!

@stsdc stsdc requested a review from a team May 10, 2026 16:14
Copy link
Copy Markdown
Member

@ryonakano ryonakano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just take a glance at the changes, but leaving some comments that I noticed or concerned.

@@ -0,0 +1,11 @@

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our source code in the elementary Organization usually have a copyright header here, so we should add it here. The same comment goes to the other new files added in this PR.

pid_item_factory.unbind.connect (pid_item_unbind_factory);


var name_column = new Gtk.ColumnViewColumn (_("Process Name"), name_item_factory) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add this file to POTFILES because it have translatable strings like here.

_needle = value;
}
}
public Gtk.FilterListModel model_out;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be { get; private set; } for lesser scope?

private Gtk.AnyFilter any_filter;
private Gtk.StringFilter name_filter;
private Gtk.StringFilter cmd_filter;
private Gtk.CustomFilter pid_filter;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason this is a instance variable instead of a local variable in the constructor? It's not used out of the constructor.

Comment on lines +8 to +9
name_filter.search = value;
cmd_filter.search = value;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using GLib.Object.bind_property() instead of making these variables as instance variables? I'm suggesting this in favor of lesser scope and also because substituting these variables in the setter feels like out of scope of an setter for me.

Something like this (note that I've neither compiled nor tested this):

public class Monitor.TreeViewFilter : GLib.Object {
    public string needle { get; set; }
    public Gtk.FilterListModel model_out;
    private Gtk.AnyFilter any_filter;
    private Gtk.CustomFilter pid_filter;

    public TreeViewFilter (GLib.ListModel? model) {
        var name_filter = build_str_filter ("name");
        var cmd_filter = build_str_filter ("cmd");

        // since the pid property is an int, we need to use a custom filter to convert it to a string
        pid_filter = new Gtk.CustomFilter ((obj) => {
            var item = (ProcessRowData) obj;
            bool pid_found = item.pid.to_string ().contains (needle.casefold ()) || false;
            return pid_found;
        });

        any_filter = new Gtk.AnyFilter ();
        any_filter.append (name_filter);
        any_filter.append (cmd_filter);
        any_filter.append (pid_filter);

        model_out = new Gtk.FilterListModel (model, any_filter);

        bind_property ("needle", name_filter, "search", SYNC_CREATE);
        bind_property ("needle", cmd_filter, "search", SYNC_CREATE);
    }

    private Gtk.StringFilter build_str_filter (string column_name) {
        var expression = new Gtk.PropertyExpression (typeof (ProcessRowData), null, column_name);
        return new Gtk.StringFilter (expression) {
            ignore_case = true,
            match_mode = SUBSTRING,
            search = needle
        };
    }
}

Comment on lines +93 to +94
var label = (Gtk.Label) box.get_last_child ();
var icon = (Gtk.Image) box.get_first_child ();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this heavily depends on implementation of name_item_setup_factory(), which makes difficult for future changes. I think we should create a new widget class that based on Gtk.Box and contains label and icon.

public ProcessManager process_manager;
private Gee.Map<int, Gtk.TreeIter ? > process_rows;

public TreeViewFilter filtered;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if Vala allows this, but can't we make this { get; private set; } while keeping access to its needle property?

private Gee.Map<int, Gtk.TreeIter ? > process_rows;

public TreeViewFilter filtered;
public Gtk.SingleSelection selection_model;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be { get; private set; }?

item.memory = process.mem_usage;
sorter.changed (DIFFERENT);
} else {
debug ("Failed to find process row for pid %d", pid);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason this is debug(), which means the message is not shown by default without G_MESSAGES_DEBUG environment variable is set?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I recommend to use the early return pattern so that the expected route doesn't get too nested. Something like this:

            uint pos;
            if (!store.find (process_row, out pos)) {
                debug ("Failed to find process row for pid %d", pid); 
                return;
            }

            var item = (ProcessRowData) store.get_item (pos);
            item.cpu = (int) process.cpu_percentage;
            item.memory = process.mem_usage;
            sorter.changed (DIFFERENT);

Comment on lines -75 to +99
private void update_model () {
public void update_model () {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this now a public method?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs Review

Development

Successfully merging this pull request may close these issues.

Rewrite process tree view

4 participants