diff --git a/po/POTFILES.in b/po/POTFILES.in index 0cb3fa09..fdae6bda 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -46,6 +46,7 @@ src/sysprof/sysprof-processes-section.ui src/sysprof/sysprof-recording-pad.c src/sysprof/sysprof-recording-pad.ui src/sysprof/sysprof-samples-section.ui +src/sysprof/sysprof-session-filters-widget.ui src/sysprof/sysprof-sidebar.ui src/sysprof/sysprof-storage-section.ui src/sysprof/sysprof-traceables-utility.ui diff --git a/src/sysprof/icons/scalable/actions/funnel-outline-symbolic.svg b/src/sysprof/icons/scalable/actions/funnel-outline-symbolic.svg new file mode 100644 index 00000000..10b32288 --- /dev/null +++ b/src/sysprof/icons/scalable/actions/funnel-outline-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/sysprof/meson.build b/src/sysprof/meson.build index 6a7ccf77..038f58f9 100644 --- a/src/sysprof/meson.build +++ b/src/sysprof/meson.build @@ -52,6 +52,7 @@ sysprof_sources = [ 'sysprof-scheduler.c', 'sysprof-section.c', 'sysprof-series.c', + 'sysprof-session-filters-widget.c', 'sysprof-session-model-item.c', 'sysprof-session-model.c', 'sysprof-session.c', diff --git a/src/sysprof/style.css b/src/sysprof/style.css index d5d7b5e2..750ffdf0 100644 --- a/src/sysprof/style.css +++ b/src/sysprof/style.css @@ -96,3 +96,17 @@ popover.tasks listview row { popover.tasks listview row label.heading { padding-bottom: 3px; } + +sessionfilters row { + padding: 3px 0; +} + +sessionfilters row:hover { + background: none; +} + +sessionfilters row button { + min-width: 0; + min-height: 0; + padding: 3px; +} diff --git a/src/sysprof/sysprof-session-filters-widget.c b/src/sysprof/sysprof-session-filters-widget.c new file mode 100644 index 00000000..96b2cb2e --- /dev/null +++ b/src/sysprof/sysprof-session-filters-widget.c @@ -0,0 +1,225 @@ +/* + * sysprof-session-filters-widget.c + * + * Copyright 2025 Georges Basile Stavracas Neto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "sysprof-mark-filter.h" +#include "sysprof-session-filters-widget.h" +#include "sysprof-session.h" + +struct _SysprofSessionFiltersWidget +{ + GtkWidget parent_instance; + + SysprofSession *session; +}; + +G_DEFINE_FINAL_TYPE (SysprofSessionFiltersWidget, sysprof_session_filters_widget, GTK_TYPE_WIDGET) + +enum { + PROP_0, + PROP_SESSION, + N_PROPS, +}; + +static GParamSpec *properties [N_PROPS]; + +static void +sysprof_session_filters_widget_remove_filter (GtkWidget *widget, + const char *action_name, + GVariant *param) +{ + SysprofSessionFiltersWidget *self = (SysprofSessionFiltersWidget *) widget; + GtkFilter *filter; + unsigned int position; + + g_assert (SYSPROF_IS_SESSION_FILTERS_WIDGET (widget)); + g_assert (SYSPROF_IS_SESSION (self->session)); + + filter = sysprof_session_get_filter (self->session); + g_assert (GTK_IS_MULTI_FILTER (filter)); + + position = g_variant_get_uint32 (param); + + gtk_multi_filter_remove (GTK_MULTI_FILTER (filter), position); +} + +static GVariant * +item_to_action_target (gpointer unused, + GtkFilter *filter, + unsigned int position) +{ + if (filter) + return g_variant_new_uint32 (position); + + return NULL; +} + +static char * +filter_to_icon_name (gpointer unused, + GtkFilter *filter) +{ + if (!filter) + return g_strdup (""); + + if (SYSPROF_IS_MARK_FILTER (filter)) + return g_strdup ("mark-chart-symbolic"); + + return g_strdup ("funnel-outline-symbolic"); +} + +static char * +filter_to_string (gpointer unused, + GtkFilter *filter) +{ + if (!filter) + return g_strdup (""); + + if (SYSPROF_IS_MARK_FILTER (filter)) + { + SysprofMarkFilter *mark_filter = (SysprofMarkFilter *) filter; + SysprofMarkCatalog *catalog = sysprof_mark_filter_get_catalog (mark_filter); + + return g_strdup_printf ("%s / %s", + sysprof_mark_catalog_get_group (catalog), + sysprof_mark_catalog_get_name (catalog)); + } + + return g_strdup (G_OBJECT_TYPE_NAME (filter)); +} + +static void +clear_all_filters (SysprofSessionFiltersWidget *self, + GtkButton *button) +{ + GtkFilter *filter; + + g_assert (SYSPROF_IS_SESSION_FILTERS_WIDGET (self)); + g_assert (SYSPROF_IS_SESSION (self->session)); + g_assert (GTK_IS_BUTTON (button)); + + filter = sysprof_session_get_filter (self->session); + g_assert (GTK_IS_MULTI_FILTER (filter)); + + while (g_list_model_get_n_items (G_LIST_MODEL (filter)) > 0) + gtk_multi_filter_remove (GTK_MULTI_FILTER (filter), 0); +} + +static void +sysprof_session_filters_widget_set_session (SysprofSessionFiltersWidget *self, + SysprofSession *session) +{ + if (g_set_object (&self->session, session)) + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]); +} + +static void +sysprof_session_filters_widget_finalize (GObject *object) +{ + SysprofSessionFiltersWidget *self = (SysprofSessionFiltersWidget *)object; + + g_clear_object (&self->session); + + G_OBJECT_CLASS (sysprof_session_filters_widget_parent_class)->finalize (object); +} + +static void +sysprof_session_filters_widget_dispose (GObject *object) +{ + SysprofSessionFiltersWidget *self = (SysprofSessionFiltersWidget *)object; + + gtk_widget_dispose_template (GTK_WIDGET (self), SYSPROF_TYPE_SESSION_FILTERS_WIDGET); + + G_OBJECT_CLASS (sysprof_session_filters_widget_parent_class)->dispose (object); +} + +static void +sysprof_session_filters_widget_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SysprofSessionFiltersWidget *self = SYSPROF_SESSION_FILTERS_WIDGET (object); + + switch (prop_id) + { + case PROP_SESSION: + g_value_set_object (value, self->session); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_session_filters_widget_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SysprofSessionFiltersWidget *self = SYSPROF_SESSION_FILTERS_WIDGET (object); + + switch (prop_id) + { + case PROP_SESSION: + sysprof_session_filters_widget_set_session (self, g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_session_filters_widget_class_init (SysprofSessionFiltersWidgetClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = sysprof_session_filters_widget_finalize; + object_class->dispose = sysprof_session_filters_widget_dispose; + object_class->get_property = sysprof_session_filters_widget_get_property; + object_class->set_property = sysprof_session_filters_widget_set_property; + + properties[PROP_SESSION] = + g_param_spec_object ("session", NULL, NULL, + SYSPROF_TYPE_SESSION, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, N_PROPS, properties); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-session-filters-widget.ui"); + + gtk_widget_class_set_css_name (widget_class, "sessionfilters"); + gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); + + gtk_widget_class_bind_template_callback (widget_class, clear_all_filters); + gtk_widget_class_bind_template_callback (widget_class, filter_to_icon_name); + gtk_widget_class_bind_template_callback (widget_class, filter_to_string); + gtk_widget_class_bind_template_callback (widget_class, item_to_action_target); + + gtk_widget_class_install_action (widget_class, "sessionfilters.remove-filter", "u", sysprof_session_filters_widget_remove_filter); +} + +static void +sysprof_session_filters_widget_init (SysprofSessionFiltersWidget *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} diff --git a/src/sysprof/sysprof-session-filters-widget.h b/src/sysprof/sysprof-session-filters-widget.h new file mode 100644 index 00000000..22a2c892 --- /dev/null +++ b/src/sysprof/sysprof-session-filters-widget.h @@ -0,0 +1,32 @@ +/* + * sysprof-session-filters-widget.c + * + * Copyright 2025 Georges Basile Stavracas Neto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define SYSPROF_TYPE_SESSION_FILTERS_WIDGET (sysprof_session_filters_widget_get_type()) + +G_DECLARE_FINAL_TYPE (SysprofSessionFiltersWidget, sysprof_session_filters_widget, SYSPROF, SESSION_FILTERS_WIDGET, GtkWidget) + +G_END_DECLS diff --git a/src/sysprof/sysprof-session-filters-widget.ui b/src/sysprof/sysprof-session-filters-widget.ui new file mode 100644 index 00000000..ebad1025 --- /dev/null +++ b/src/sysprof/sysprof-session-filters-widget.ui @@ -0,0 +1,112 @@ + + + + diff --git a/src/sysprof/sysprof-window.c b/src/sysprof/sysprof-window.c index e81e264b..cc351836 100644 --- a/src/sysprof/sysprof-window.c +++ b/src/sysprof/sysprof-window.c @@ -41,6 +41,7 @@ #include "sysprof-pair.h" #include "sysprof-processes-section.h" #include "sysprof-samples-section.h" +#include "sysprof-session-filters-widget.h" #include "sysprof-sidebar.h" #include "sysprof-storage-section.h" #include "sysprof-task-row.h" @@ -328,6 +329,13 @@ main_view_notify_sidebar (SysprofWindow *self, gtk_widget_set_sensitive (GTK_WIDGET (self->show_right_sidebar), sidebar != NULL); } +static gboolean +n_filters_to_button_visibility (SysprofWindow *self, + unsigned int n_filters) +{ + return n_filters > 0; +} + static void sysprof_window_session_seek_backward (GtkWidget *widget, const char *action_name, @@ -617,6 +625,7 @@ sysprof_window_class_init (SysprofWindowClass *klass) gtk_widget_class_bind_template_child (widget_class, SysprofWindow, stack_title); gtk_widget_class_bind_template_callback (widget_class, main_view_notify_sidebar); + gtk_widget_class_bind_template_callback (widget_class, n_filters_to_button_visibility); gtk_widget_class_install_action (widget_class, "win.open-capture", NULL, sysprof_window_open_capture_action); gtk_widget_class_install_action (widget_class, "win.record-capture", NULL, sysprof_window_record_capture_action); @@ -649,6 +658,7 @@ sysprof_window_class_init (SysprofWindowClass *klass) g_type_ensure (SYSPROF_TYPE_NETWORK_SECTION); g_type_ensure (SYSPROF_TYPE_PROCESSES_SECTION); g_type_ensure (SYSPROF_TYPE_SAMPLES_SECTION); + g_type_ensure (SYSPROF_TYPE_SESSION_FILTERS_WIDGET); g_type_ensure (SYSPROF_TYPE_STORAGE_SECTION); g_type_ensure (SYSPROF_TYPE_SESSION); g_type_ensure (SYSPROF_TYPE_SYMBOL); diff --git a/src/sysprof/sysprof-window.ui b/src/sysprof/sysprof-window.ui index f4e1e7cb..c18b4a47 100644 --- a/src/sysprof/sysprof-window.ui +++ b/src/sysprof/sysprof-window.ui @@ -126,6 +126,36 @@ Toggle Left Panel + + + false + funnel-outline-symbolic + View Filters + + + + + + + SysprofWindow + + + + + + + + + + SysprofWindow + + + + + + 6 diff --git a/src/sysprof/sysprof.gresource.xml b/src/sysprof/sysprof.gresource.xml index 3903b5a5..eb5d9307 100644 --- a/src/sysprof/sysprof.gresource.xml +++ b/src/sysprof/sysprof.gresource.xml @@ -8,6 +8,7 @@ icons/scalable/actions/empty-symbolic.svg icons/scalable/actions/energy-symbolic.svg icons/scalable/actions/flamegraph-symbolic.svg + icons/scalable/actions/funnel-outline-symbolic.svg icons/scalable/actions/graphics-symbolic.svg icons/scalable/actions/mark-chart-symbolic.svg icons/scalable/actions/mark-table-symbolic.svg @@ -50,6 +51,7 @@ sysprof-processes-section.ui sysprof-recording-pad.ui sysprof-samples-section.ui + sysprof-session-filters-widget.ui sysprof-sidebar.ui sysprof-storage-section.ui sysprof-task-row.ui