From d72e796c91f07efb5f052b8c44e08f0c04d873e3 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 29 Jun 2023 16:24:33 -0700 Subject: [PATCH] libsysprof-gtk: use signals to create charts This allows us to keep the final type for tracks like I want and instead move various logic into signal handlers which are kept within the same source file for discovery. --- src/libsysprof-gtk/meson.build | 1 - .../sysprof-counter-track-private.h | 35 ---- src/libsysprof-gtk/sysprof-counter-track.c | 120 ------------- src/libsysprof-gtk/sysprof-session-discover.c | 158 +++++++++++++----- src/libsysprof-gtk/sysprof-track.c | 70 ++++---- src/libsysprof-gtk/sysprof-track.h | 12 +- 6 files changed, 159 insertions(+), 237 deletions(-) delete mode 100644 src/libsysprof-gtk/sysprof-counter-track-private.h delete mode 100644 src/libsysprof-gtk/sysprof-counter-track.c diff --git a/src/libsysprof-gtk/meson.build b/src/libsysprof-gtk/meson.build index 19bb812b..bb6b2dc3 100644 --- a/src/libsysprof-gtk/meson.build +++ b/src/libsysprof-gtk/meson.build @@ -63,7 +63,6 @@ libsysprof_gtk_public_headers = [ ] libsysprof_gtk_private_sources = [ - 'sysprof-counter-track.c', 'sysprof-css.c', 'sysprof-mark-chart-item.c', 'sysprof-mark-chart-row.c', diff --git a/src/libsysprof-gtk/sysprof-counter-track-private.h b/src/libsysprof-gtk/sysprof-counter-track-private.h deleted file mode 100644 index 8f45686b..00000000 --- a/src/libsysprof-gtk/sysprof-counter-track-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* sysprof-counter-track-private.h - * - * Copyright 2023 Christian Hergert - * - * 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 "sysprof-track.h" - -G_BEGIN_DECLS - -#define SYSPROF_TYPE_COUNTER_TRACK (sysprof_counter_track_get_type()) - -G_DECLARE_FINAL_TYPE (SysprofCounterTrack, sysprof_counter_track, SYSPROF, COUNTER_TRACK, SysprofTrack) - -SysprofTrack *sysprof_counter_track_new (SysprofSession *session, - const char *title, - SysprofDocumentCounter *counter); - -G_END_DECLS diff --git a/src/libsysprof-gtk/sysprof-counter-track.c b/src/libsysprof-gtk/sysprof-counter-track.c deleted file mode 100644 index 77e96591..00000000 --- a/src/libsysprof-gtk/sysprof-counter-track.c +++ /dev/null @@ -1,120 +0,0 @@ -/* sysprof-counter-track.c - * - * Copyright 2023 Christian Hergert - * - * 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 "config.h" - -#include "sysprof-counter-track-private.h" -#include "sysprof-chart.h" -#include "sysprof-line-layer.h" -#include "sysprof-value-axis.h" -#include "sysprof-xy-series.h" - -struct _SysprofCounterTrack -{ - SysprofTrack parent_instance; - SysprofDocumentCounter *counter; -}; - -G_DEFINE_FINAL_TYPE (SysprofCounterTrack, sysprof_counter_track, SYSPROF_TYPE_TRACK) - -static GtkWidget * -sysprof_counter_track_create_chart (SysprofTrack *track) -{ - SysprofCounterTrack *self = (SysprofCounterTrack *)track; - SysprofSession *session = NULL; - g_autoptr(SysprofSeries) xy_series = NULL; - g_autoptr(SysprofAxis) y_axis = NULL; - SysprofChartLayer *layer; - SysprofChart *chart; - SysprofAxis *x_axis; - - g_assert (SYSPROF_IS_COUNTER_TRACK (self)); - - if (!(session = sysprof_track_get_session (track))) - return NULL; - - x_axis = sysprof_session_get_visible_time_axis (session); - y_axis = sysprof_value_axis_new (sysprof_document_counter_get_min_value (self->counter), - sysprof_document_counter_get_max_value (self->counter)); - xy_series = sysprof_xy_series_new (sysprof_track_get_title (track), - g_object_ref (G_LIST_MODEL (self->counter)), - gtk_property_expression_new (SYSPROF_TYPE_DOCUMENT_COUNTER_VALUE, NULL, "time"), - gtk_property_expression_new (SYSPROF_TYPE_DOCUMENT_COUNTER_VALUE, NULL, "value-double")); - - chart = g_object_new (SYSPROF_TYPE_CHART, NULL); - layer = g_object_new (SYSPROF_TYPE_LINE_LAYER, - "fill", TRUE, - "spline", TRUE, - "series", xy_series, - "x-axis", x_axis, - "y-axis", y_axis, - NULL); - sysprof_chart_add_layer (chart, layer); - - return GTK_WIDGET (chart); -} - -static void -sysprof_counter_track_dispose (GObject *object) -{ - SysprofCounterTrack *self = (SysprofCounterTrack *)object; - - g_clear_object (&self->counter); - - G_OBJECT_CLASS (sysprof_counter_track_parent_class)->dispose (object); -} - -static void -sysprof_counter_track_class_init (SysprofCounterTrackClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - SysprofTrackClass *track_class = SYSPROF_TRACK_CLASS (klass); - - object_class->dispose = sysprof_counter_track_dispose; - - track_class->create_chart = sysprof_counter_track_create_chart; -} - -static void -sysprof_counter_track_init (SysprofCounterTrack *self) -{ -} - -SysprofTrack * -sysprof_counter_track_new (SysprofSession *session, - const char *title, - SysprofDocumentCounter *counter) -{ - SysprofCounterTrack *self; - - g_return_val_if_fail (SYSPROF_IS_DOCUMENT_COUNTER (counter), NULL); - - if (title == NULL) - title = sysprof_document_counter_get_name (counter); - - self = g_object_new (SYSPROF_TYPE_COUNTER_TRACK, - "session", session, - "title", title, - NULL); - - self->counter = g_object_ref (counter); - - return SYSPROF_TRACK (self); -} diff --git a/src/libsysprof-gtk/sysprof-session-discover.c b/src/libsysprof-gtk/sysprof-session-discover.c index bc29869d..862d1d6e 100644 --- a/src/libsysprof-gtk/sysprof-session-discover.c +++ b/src/libsysprof-gtk/sysprof-session-discover.c @@ -22,37 +22,63 @@ #include -#include "sysprof-counter-track-private.h" +#include "sysprof-chart.h" +#include "sysprof-chart-layer.h" +#include "sysprof-column-layer.h" #include "sysprof-session-private.h" #include "sysprof-track-private.h" +#include "sysprof-value-axis.h" typedef struct _SysprofTrackCounter { + const char *track_name; + + /* Used to layer values into main view */ const char *category; const char *name; - const char *subtracks_name_glob; - const char *track_name; + + /* Used to split out sub views */ + const char *subtracks_category; + const char *subtracks_name; } SysprofTrackCounter; static const SysprofTrackCounter discovery_counters[] = { - { "CPU Percent", "Combined", "Total CPU *", N_("CPU Usage") }, + { + N_("CPU"), + "CPU Percent", "Combined", + "CPU Percent", "*", + }, + + { N_("Memory"), "Memory", "Used", NULL, NULL }, + + { + N_("Energy"), + "RAPL", "*", + "RAPL *", "*", + }, + }; static GListModel * filter_counters (GListModel *model, - const char *category, + const char *category_glob, const char *name_glob) { g_autoptr(GListStore) store = NULL; - g_autoptr(GPatternSpec) spec = NULL; + g_autoptr(GPatternSpec) cat_spec = NULL; + g_autoptr(GPatternSpec) name_spec = NULL; guint n_items; g_assert (G_IS_LIST_MODEL (model)); - g_assert (category != NULL); - g_assert (name_glob != NULL); + + if (category_glob == NULL || name_glob == NULL) + return NULL; store = g_list_store_new (SYSPROF_TYPE_DOCUMENT_COUNTER); - spec = g_pattern_spec_new (name_glob); + + cat_spec = g_pattern_spec_new (category_glob); + name_spec = g_pattern_spec_new (name_glob); + n_items = g_list_model_get_n_items (model); for (guint i = 0; i < n_items; i++) @@ -61,8 +87,8 @@ filter_counters (GListModel *model, const char *ctrcat = sysprof_document_counter_get_category (counter); const char *ctrname = sysprof_document_counter_get_name (counter); - if (g_strcmp0 (category, ctrcat) == 0 && - g_pattern_spec_match (spec, strlen (ctrname), ctrname, NULL)) + if (g_pattern_spec_match (cat_spec, strlen (ctrcat), ctrcat, NULL) || + g_pattern_spec_match (name_spec, strlen (ctrname), ctrname, NULL)) g_list_store_append (store, counter); } @@ -72,10 +98,75 @@ filter_counters (GListModel *model, return G_LIST_MODEL (g_steal_pointer (&store)); } -void -_sysprof_session_discover_tracks (SysprofSession *self, +static GtkWidget * +create_chart_for_samples (SysprofSession *session, + SysprofTrack *track) +{ + g_autoptr(SysprofSeries) xy_series = NULL; + g_autoptr(SysprofAxis) y_axis = NULL; + g_autoptr(GListModel) samples = NULL; + SysprofChartLayer *layer; + SysprofDocument *document; + SysprofChart *chart; + SysprofAxis *x_axis = NULL; + + g_assert (SYSPROF_IS_SESSION (session)); + g_assert (SYSPROF_IS_TRACK (track)); + + document = sysprof_session_get_document (session); + x_axis = sysprof_session_get_visible_time_axis (session); + y_axis = sysprof_value_axis_new (0, 128); + xy_series = sysprof_xy_series_new (_("Stack Depth"), + sysprof_document_list_samples (document), + gtk_property_expression_new (SYSPROF_TYPE_DOCUMENT_SAMPLE, NULL, "time"), + gtk_property_expression_new (SYSPROF_TYPE_DOCUMENT_SAMPLE, NULL, "stack-depth")); + + chart = g_object_new (SYSPROF_TYPE_CHART, + "height-request", 48, + NULL); + layer = g_object_new (SYSPROF_TYPE_COLUMN_LAYER, + "series", xy_series, + "x-axis", x_axis, + "y-axis", y_axis, + NULL); + sysprof_chart_add_layer (chart, layer); + + return GTK_WIDGET (chart); +} + +static void +sysprof_session_discover_sampler (SysprofSession *self, SysprofDocument *document, GListStore *tracks) +{ + g_autoptr(GListModel) samples = NULL; + + g_assert (SYSPROF_IS_SESSION (self)); + g_assert (SYSPROF_IS_DOCUMENT (document)); + g_assert (G_IS_LIST_STORE (tracks)); + + samples = sysprof_document_list_samples (document); + + if (g_list_model_get_n_items (samples) > 0) + { + g_autoptr(SysprofTrack) track = NULL; + + track = g_object_new (SYSPROF_TYPE_TRACK, + "title", _("Profiler"), + NULL); + g_signal_connect_object (track, + "create-chart", + G_CALLBACK (create_chart_for_samples), + self, + G_CONNECT_SWAPPED); + g_list_store_append (tracks, track); + } +} + +static void +sysprof_session_discover_counters (SysprofSession *self, + SysprofDocument *document, + GListStore *tracks) { g_autoptr(GListModel) counters = NULL; @@ -88,34 +179,25 @@ _sysprof_session_discover_tracks (SysprofSession *self, for (guint i = 0; i < G_N_ELEMENTS (discovery_counters); i++) { const SysprofTrackCounter *info = &discovery_counters[i]; - g_autoptr(SysprofDocumentCounter) counter = NULL; + g_autoptr(GListModel) track_counters = filter_counters (counters, info->category, info->name); - if ((counter = sysprof_document_find_counter (document, info->category, info->name))) + if (track_counters != NULL) { - g_autoptr(SysprofTrack) track = NULL; - g_autoptr(GListModel) subcounters = NULL; + g_autoptr(GListModel) subtrack_counters = filter_counters (counters, info->subtracks_category, info->subtracks_name); - track = sysprof_counter_track_new (self, - g_dgettext (GETTEXT_PACKAGE, info->track_name), - counter); - - if ((subcounters = filter_counters (counters, info->category, info->subtracks_name_glob))) - { - guint n_items = g_list_model_get_n_items (subcounters); - - for (guint j = 0; j < n_items; j++) - { - g_autoptr(SysprofDocumentCounter) subcounter = g_list_model_get_item (subcounters, j); - g_autoptr(SysprofTrack) subtrack = NULL; - - subtrack = sysprof_counter_track_new (self, - sysprof_document_counter_get_name (subcounter), - subcounter); - _sysprof_track_add_subtrack (track, subtrack); - } - } - - g_list_store_append (tracks, track); } } } + +void +_sysprof_session_discover_tracks (SysprofSession *self, + SysprofDocument *document, + GListStore *tracks) +{ + g_assert (SYSPROF_IS_SESSION (self)); + g_assert (SYSPROF_IS_DOCUMENT (document)); + g_assert (G_IS_LIST_STORE (tracks)); + + sysprof_session_discover_sampler (self, document, tracks); + sysprof_session_discover_counters (self, document, tracks); +} diff --git a/src/libsysprof-gtk/sysprof-track.c b/src/libsysprof-gtk/sysprof-track.c index 7776585e..9e902008 100644 --- a/src/libsysprof-gtk/sysprof-track.c +++ b/src/libsysprof-gtk/sysprof-track.c @@ -22,13 +22,14 @@ #include "sysprof-track-private.h" -typedef struct _SysprofTrackPrivate +struct _SysprofTrack { + GObject parent_instance; SysprofSession *session; char *title; GListStore *subtracks; GMenuModel *menu_model; -} SysprofTrackPrivate; +}; enum { PROP_0, @@ -39,20 +40,25 @@ enum { N_PROPS }; -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SysprofTrack, sysprof_track, G_TYPE_OBJECT) +enum { + CREATE_CHART, + N_SIGNALS +}; + +G_DEFINE_FINAL_TYPE (SysprofTrack, sysprof_track, G_TYPE_OBJECT) static GParamSpec *properties [N_PROPS]; +static guint signals[N_SIGNALS]; static void sysprof_track_dispose (GObject *object) { SysprofTrack *self = (SysprofTrack *)object; - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - g_clear_object (&priv->menu_model); - g_clear_object (&priv->subtracks); - g_clear_pointer (&priv->title, g_free); - g_clear_weak_pointer (&priv->session); + g_clear_object (&self->menu_model); + g_clear_object (&self->subtracks); + g_clear_pointer (&self->title, g_free); + g_clear_weak_pointer (&self->session); G_OBJECT_CLASS (sysprof_track_parent_class)->dispose (object); } @@ -95,20 +101,19 @@ sysprof_track_set_property (GObject *object, GParamSpec *pspec) { SysprofTrack *self = SYSPROF_TRACK (object); - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); switch (prop_id) { case PROP_MENU_MODEL: - priv->menu_model = g_value_dup_object (value); + self->menu_model = g_value_dup_object (value); break; case PROP_SESSION: - g_set_weak_pointer (&priv->session, g_value_get_object (value)); + g_set_weak_pointer (&self->session, g_value_get_object (value)); break; case PROP_TITLE: - priv->title = g_value_dup_string (value); + self->title = g_value_dup_string (value); break; default: @@ -146,37 +151,40 @@ sysprof_track_class_init (SysprofTrackClass *klass) (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); g_object_class_install_properties (object_class, N_PROPS, properties); + + signals[CREATE_CHART] = + g_signal_new ("create-chart", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_first_wins, NULL, + NULL, + GTK_TYPE_WIDGET, 0); } static void sysprof_track_init (SysprofTrack *self) { - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - - priv->subtracks = g_list_store_new (SYSPROF_TYPE_TRACK); + self->subtracks = g_list_store_new (SYSPROF_TYPE_TRACK); } const char * sysprof_track_get_title (SysprofTrack *self) { - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - g_return_val_if_fail (SYSPROF_IS_TRACK (self), NULL); - return priv->title; + return self->title; } void _sysprof_track_add_subtrack (SysprofTrack *self, SysprofTrack *subtrack) { - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - g_return_if_fail (SYSPROF_IS_TRACK (self)); g_return_if_fail (SYSPROF_IS_TRACK (subtrack)); g_return_if_fail (subtrack != self); - g_list_store_append (priv->subtracks, subtrack); + g_list_store_append (self->subtracks, subtrack); } /** @@ -188,14 +196,12 @@ _sysprof_track_add_subtrack (SysprofTrack *self, GListModel * sysprof_track_list_subtracks (SysprofTrack *self) { - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - g_return_val_if_fail (SYSPROF_IS_TRACK (self), NULL); - if (g_list_model_get_n_items (G_LIST_MODEL (priv->subtracks)) == 0) + if (g_list_model_get_n_items (G_LIST_MODEL (self->subtracks)) == 0) return NULL; - return g_object_ref (G_LIST_MODEL (priv->subtracks)); + return g_object_ref (G_LIST_MODEL (self->subtracks)); } /** @@ -207,11 +213,9 @@ sysprof_track_list_subtracks (SysprofTrack *self) SysprofSession * sysprof_track_get_session (SysprofTrack *self) { - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - g_return_val_if_fail (SYSPROF_IS_TRACK (self), NULL); - return priv->session; + return self->session; } /** @@ -225,17 +229,19 @@ sysprof_track_get_session (SysprofTrack *self) GMenuModel * sysprof_track_get_menu_model (SysprofTrack *self) { - SysprofTrackPrivate *priv = sysprof_track_get_instance_private (self); - g_return_val_if_fail (SYSPROF_IS_TRACK (self), NULL); - return priv->menu_model; + return self->menu_model; } GtkWidget * _sysprof_track_create_chart (SysprofTrack *self) { + GtkWidget *ret = NULL; + g_return_val_if_fail (SYSPROF_IS_TRACK (self), NULL); - return SYSPROF_TRACK_GET_CLASS (self)->create_chart (self); + g_signal_emit (self, signals[CREATE_CHART], 0, &ret); + + return ret; } diff --git a/src/libsysprof-gtk/sysprof-track.h b/src/libsysprof-gtk/sysprof-track.h index 9c83ca20..1a1ae002 100644 --- a/src/libsysprof-gtk/sysprof-track.h +++ b/src/libsysprof-gtk/sysprof-track.h @@ -31,17 +31,7 @@ G_BEGIN_DECLS #define SYSPROF_TYPE_TRACK (sysprof_track_get_type()) SYSPROF_AVAILABLE_IN_ALL -G_DECLARE_DERIVABLE_TYPE (SysprofTrack, sysprof_track, SYSPROF, TRACK, GObject) - -struct _SysprofTrackClass -{ - GObjectClass parent_class; - - GtkWidget *(*create_chart) (SysprofTrack *self); - - /*< private >*/ - gpointer _reserved[16]; -}; +G_DECLARE_FINAL_TYPE (SysprofTrack, sysprof_track, SYSPROF, TRACK, GObject) SYSPROF_AVAILABLE_IN_ALL SysprofSession *sysprof_track_get_session (SysprofTrack *self);