mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Merge branch 'gbsneto/filter-by-marks' into 'master'
Filter samples by marks See merge request GNOME/sysprof!129
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
subdir('eggbitset')
|
||||
subdir('elfparser')
|
||||
subdir('linereader')
|
||||
subdir('tree')
|
||||
|
||||
7
contrib/tree/meson.build
Normal file
7
contrib/tree/meson.build
Normal file
@ -0,0 +1,7 @@
|
||||
libtree_deps = [
|
||||
gio_dep,
|
||||
]
|
||||
|
||||
libtree_static_dep = declare_dependency(
|
||||
include_directories: include_directories('.'),
|
||||
)
|
||||
@ -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
|
||||
|
||||
@ -217,6 +217,7 @@ libsysprof_deps = [
|
||||
libeggbitset_static_dep,
|
||||
libelfparser_static_dep,
|
||||
liblinereader_static_dep,
|
||||
libtree_static_dep,
|
||||
libsysprof_capture_dep,
|
||||
]
|
||||
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><g fill="#222222"><path d="m 1.042969 0 c -0.8125 0 -1.285157 0.917969 -0.8125 1.582031 l 4.769531 6.738281 v 6.636719 c 0 0.742188 0.78125 1.226563 1.449219 0.894531 l 4 -2 c 0.335937 -0.171874 0.550781 -0.515624 0.550781 -0.894531 v -4.636719 l 4.8125 -6.738281 c 0.476562 -0.664062 0 -1.582031 -0.8125 -1.582031 z m 1.902343 2 h 10.109376 l -3.867188 5.417969 c -0.121094 0.167969 -0.1875 0.375 -0.1875 0.582031 v 4.339844 l -2 1 v -5.339844 c 0 -0.207031 -0.066406 -0.414062 -0.1875 -0.582031 z m 0 0"/><path d="m 3.859375 5 l 2.140625 3 v 7 l 4 -2 v -5 l 2.144531 -3 z m 0 0" fill-opacity="0.34902"/></g></svg>
|
||||
|
After Width: | Height: | Size: 742 B |
@ -31,6 +31,7 @@ sysprof_sources = [
|
||||
'sysprof-mark-chart-item.c',
|
||||
'sysprof-mark-chart-row.c',
|
||||
'sysprof-mark-chart.c',
|
||||
'sysprof-mark-filter.c',
|
||||
'sysprof-mark-table.c',
|
||||
'sysprof-marks-section.c',
|
||||
'sysprof-memory-callgraph-view.c',
|
||||
@ -51,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',
|
||||
@ -90,6 +92,7 @@ sysprof_deps = [
|
||||
dependency('libadwaita-1', version: '>= 1.6.0'),
|
||||
dependency('libpanel-1', version: '>= 1.4'),
|
||||
|
||||
libtree_static_dep,
|
||||
libsysprof_static_dep,
|
||||
]
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -31,6 +31,9 @@ struct _SysprofMarkChartRow
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GMenuModel *context_menu;
|
||||
GtkWidget *context_menu_popover;
|
||||
|
||||
SysprofMarkChartItem *item;
|
||||
|
||||
SysprofChart *chart;
|
||||
@ -47,6 +50,27 @@ G_DEFINE_FINAL_TYPE (SysprofMarkChartRow, sysprof_mark_chart_row, GTK_TYPE_WIDGE
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void
|
||||
filter_by_mark_action (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
SysprofMarkChartRow *self = (SysprofMarkChartRow *)widget;
|
||||
SysprofMarkCatalog *catalog;
|
||||
SysprofSession *session;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_CHART_ROW (self));
|
||||
|
||||
if (self->item == NULL ||
|
||||
!(session = sysprof_mark_chart_item_get_session (self->item)))
|
||||
return;
|
||||
|
||||
catalog = sysprof_mark_chart_item_get_catalog (self->item);
|
||||
g_assert (SYSPROF_IS_MARK_CATALOG (catalog));
|
||||
|
||||
sysprof_session_filter_by_mark (session, catalog);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_mark_chart_row_activate_layer_item_cb (SysprofMarkChartRow *self,
|
||||
SysprofChartLayer *layer,
|
||||
@ -79,6 +103,49 @@ sysprof_mark_chart_row_activate_layer_item_cb (SysprofMarkChartRow *self,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_chart_row_button_pressed_cb (SysprofMarkChartRow *self,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
GtkGestureClick *gesture)
|
||||
{
|
||||
GdkEventSequence *current;
|
||||
GdkEvent *event;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_CHART_ROW (self));
|
||||
g_assert (GTK_IS_GESTURE_CLICK (gesture));
|
||||
|
||||
current = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
||||
event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), current);
|
||||
|
||||
if (!gdk_event_triggers_context_menu (event))
|
||||
return;
|
||||
|
||||
if (!self->context_menu_popover)
|
||||
{
|
||||
self->context_menu_popover = gtk_popover_menu_new_from_model (self->context_menu);
|
||||
gtk_popover_set_position (GTK_POPOVER (self->context_menu_popover), GTK_POS_BOTTOM);
|
||||
gtk_popover_set_has_arrow (GTK_POPOVER (self->context_menu_popover), FALSE);
|
||||
gtk_widget_set_halign (self->context_menu_popover, GTK_ALIGN_START);
|
||||
gtk_widget_set_parent (GTK_WIDGET (self->context_menu_popover), GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
if (x != -1 && y != -1)
|
||||
{
|
||||
GdkRectangle rect = { x, y, 1, 1 };
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (self->context_menu_popover), &rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (self->context_menu_popover), NULL);
|
||||
}
|
||||
|
||||
gtk_popover_popup (GTK_POPOVER (self->context_menu_popover));
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_chart_row_dispose (GObject *object)
|
||||
{
|
||||
@ -154,8 +221,12 @@ sysprof_mark_chart_row_class_init (SysprofMarkChartRowClass *klass)
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-mark-chart-row.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofMarkChartRow, chart);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofMarkChartRow, context_menu);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofMarkChartRow, layer);
|
||||
gtk_widget_class_bind_template_callback (widget_class, sysprof_mark_chart_row_activate_layer_item_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, sysprof_mark_chart_row_button_pressed_cb);
|
||||
|
||||
gtk_widget_class_install_action (widget_class, "markchartrow.filter-by-mark", NULL, filter_by_mark_action);
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_CHART);
|
||||
g_type_ensure (SYSPROF_TYPE_TIME_SERIES_ITEM);
|
||||
|
||||
@ -1,6 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofMarkChartRow" parent="GtkWidget">
|
||||
|
||||
<menu id="context_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Set as Filter</attribute>
|
||||
<attribute name="action">markchartrow.filter-by-mark</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="button">0</property>
|
||||
<property name="exclusive">true</property>
|
||||
<signal name="pressed" handler="sysprof_mark_chart_row_button_pressed_cb" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
|
||||
<child>
|
||||
<object class="GtkInscription">
|
||||
<property name="xalign">1</property>
|
||||
<property name="nat-chars">30</property>
|
||||
<property name="min-chars">30</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="text-overflow">ellipsize-end</property>
|
||||
<binding name="text">
|
||||
<lookup name="name" type="SysprofMarkCatalog">
|
||||
<lookup name="catalog" type="SysprofMarkChartItem">
|
||||
<lookup name="item">SysprofMarkChartRow</lookup>
|
||||
</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="SysprofChart" id="chart">
|
||||
<signal name="activate-layer-item" handler="sysprof_mark_chart_row_activate_layer_item_cb" swapped="true"/>
|
||||
@ -24,5 +62,9 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</template>
|
||||
</interface>
|
||||
|
||||
@ -45,32 +45,12 @@
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkInscription">
|
||||
<property name="xalign">1</property>
|
||||
<property name="nat-chars">30</property>
|
||||
<property name="min-chars">30</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="text-overflow">ellipsize-end</property>
|
||||
<binding name="text">
|
||||
<lookup name="name" type="SysprofMarkCatalog">
|
||||
<lookup name="catalog" type="SysprofMarkChartItem">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofMarkChartRow">
|
||||
<property name="hexpand">true</property>
|
||||
<binding name="item">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
|
||||
331
src/sysprof/sysprof-mark-filter.c
Normal file
331
src/sysprof/sysprof-mark-filter.c
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* sysprof-mark-filter.c
|
||||
*
|
||||
* Copyright 2025 Georges Basile Stavracas Neto <feaneron@igalia.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "sysprof-mark-filter.h"
|
||||
|
||||
typedef struct _SysprofMarkFilterNode SysprofMarkFilterNode;
|
||||
static void sysprof_mark_filter_node_augment (SysprofMarkFilterNode *node);
|
||||
#define RB_AUGMENT(elem) (sysprof_mark_filter_node_augment (elem))
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
struct _SysprofMarkFilterNode
|
||||
{
|
||||
RB_ENTRY (_SysprofMarkFilterNode) link;
|
||||
SysprofTimeSpan time_span;
|
||||
gint64 max;
|
||||
};
|
||||
|
||||
struct _SysprofMarkFilter
|
||||
{
|
||||
GtkFilter parent_instance;
|
||||
|
||||
SysprofDocument *document;
|
||||
SysprofMarkCatalog *catalog;
|
||||
|
||||
RB_HEAD (sysprof_mark_filter, _SysprofMarkFilterNode) head;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (SysprofMarkFilter, sysprof_mark_filter, GTK_TYPE_FILTER)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DOCUMENT,
|
||||
PROP_CATALOG,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static inline int
|
||||
sysprof_mark_filter_node_compare (SysprofMarkFilterNode *a,
|
||||
SysprofMarkFilterNode *b)
|
||||
{
|
||||
if (a->time_span.begin_nsec < b->time_span.begin_nsec)
|
||||
return -1;
|
||||
else if (a->time_span.begin_nsec > b->time_span.begin_nsec)
|
||||
return 1;
|
||||
else if (a->time_span.end_nsec < b->time_span.end_nsec)
|
||||
return -1;
|
||||
else if (a->time_span.end_nsec > b->time_span.end_nsec)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
RB_GENERATE_STATIC (sysprof_mark_filter, _SysprofMarkFilterNode, link, sysprof_mark_filter_node_compare);
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_node_augment (SysprofMarkFilterNode *node)
|
||||
{
|
||||
node->max = node->time_span.end_nsec;
|
||||
|
||||
if (RB_LEFT (node, link) && RB_LEFT (node, link)->max > node->max)
|
||||
node->max = RB_LEFT (node, link)->max;
|
||||
|
||||
if (RB_RIGHT (node, link) && RB_RIGHT (node, link)->max > node->max)
|
||||
node->max = RB_RIGHT (node, link)->max;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_node_finalize (SysprofMarkFilterNode *node)
|
||||
{
|
||||
g_free (node);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_node_free (SysprofMarkFilterNode *node)
|
||||
{
|
||||
SysprofMarkFilterNode *right = RB_RIGHT (node, link);
|
||||
SysprofMarkFilterNode *left = RB_LEFT (node, link);
|
||||
|
||||
if (left != NULL)
|
||||
sysprof_mark_filter_node_free (left);
|
||||
|
||||
sysprof_mark_filter_node_finalize (node);
|
||||
|
||||
if (right != NULL)
|
||||
sysprof_mark_filter_node_free (right);
|
||||
}
|
||||
|
||||
static void
|
||||
populate_intervals (SysprofMarkFilter *self)
|
||||
{
|
||||
unsigned int n_marks;
|
||||
GListModel *model;
|
||||
int64_t begin_nsec;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_FILTER (self));
|
||||
g_assert (SYSPROF_IS_MARK_CATALOG (self->catalog));
|
||||
g_assert (SYSPROF_IS_DOCUMENT (self->document));
|
||||
|
||||
begin_nsec = sysprof_document_get_time_span (self->document)->begin_nsec;
|
||||
|
||||
model = G_LIST_MODEL (self->catalog);
|
||||
n_marks = g_list_model_get_n_items (model);
|
||||
|
||||
for (unsigned int i = 0; i < n_marks; i++)
|
||||
{
|
||||
g_autoptr(SysprofDocumentMark) mark = g_list_model_get_item (model, i);
|
||||
SysprofMarkFilterNode *parent;
|
||||
SysprofMarkFilterNode *node;
|
||||
SysprofMarkFilterNode *ret;
|
||||
SysprofTimeSpan time_span;
|
||||
|
||||
g_assert (SYSPROF_IS_DOCUMENT_MARK (mark));
|
||||
|
||||
time_span.begin_nsec = sysprof_document_frame_get_time (SYSPROF_DOCUMENT_FRAME (mark));
|
||||
time_span.end_nsec = sysprof_document_mark_get_end_time (mark);
|
||||
|
||||
if (sysprof_time_span_duration (time_span) == 0)
|
||||
continue;
|
||||
|
||||
time_span = sysprof_time_span_relative_to (time_span, begin_nsec);
|
||||
|
||||
node = g_new0 (SysprofMarkFilterNode, 1);
|
||||
node->time_span = time_span;
|
||||
node->max = time_span.end_nsec;
|
||||
|
||||
/* If there is a collision, then the node is returned. Otherwise
|
||||
* if the node was inserted, NULL is returned.
|
||||
*/
|
||||
if ((ret = RB_INSERT (sysprof_mark_filter, &self->head, node)))
|
||||
{
|
||||
sysprof_mark_filter_node_free (node);
|
||||
return;
|
||||
}
|
||||
|
||||
parent = RB_PARENT (node, link);
|
||||
while (parent != NULL)
|
||||
{
|
||||
if (node->max > parent->max)
|
||||
parent->max = node->max;
|
||||
node = parent;
|
||||
parent = RB_PARENT (parent, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_mark_filter_match (GtkFilter *filter,
|
||||
gpointer item)
|
||||
{
|
||||
SysprofDocumentFrame *frame = (SysprofDocumentFrame *) item;
|
||||
SysprofMarkFilter *self = (SysprofMarkFilter *)filter;
|
||||
SysprofMarkFilterNode *node;
|
||||
int64_t value;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_FILTER (self));
|
||||
g_assert (SYSPROF_IS_DOCUMENT_FRAME (item));
|
||||
|
||||
value = sysprof_document_frame_get_time_offset (frame);
|
||||
node = RB_ROOT (&self->head);
|
||||
|
||||
/* The root node contains our calculated max as augmented in RBTree.
|
||||
* Therefore, we can know if value falls beyond the upper bound
|
||||
* in O(1) without having to add a branch to the while loop below.
|
||||
*/
|
||||
if (node == NULL || node->max < value)
|
||||
return FALSE;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
g_assert (RB_LEFT (node, link) == NULL ||
|
||||
node->max >= RB_LEFT (node, link)->max);
|
||||
g_assert (RB_RIGHT (node, link) == NULL ||
|
||||
node->max >= RB_RIGHT (node, link)->max);
|
||||
|
||||
if (value >= node->time_span.begin_nsec && value <= node->time_span.end_nsec)
|
||||
return TRUE;
|
||||
|
||||
if (RB_LEFT (node, link) && RB_LEFT (node, link)->max >= value)
|
||||
node = RB_LEFT (node, link);
|
||||
else
|
||||
node = RB_RIGHT (node, link);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_finalize (GObject *object)
|
||||
{
|
||||
SysprofMarkFilter *self = (SysprofMarkFilter *)object;
|
||||
SysprofMarkFilterNode *node = RB_ROOT(&self->head);
|
||||
|
||||
g_clear_object (&self->catalog);
|
||||
|
||||
if (node != NULL)
|
||||
sysprof_mark_filter_node_free (node);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_mark_filter_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_constructed (GObject *object)
|
||||
{
|
||||
SysprofMarkFilter *self = (SysprofMarkFilter *)object;
|
||||
|
||||
G_OBJECT_CLASS (sysprof_mark_filter_parent_class)->constructed (object);
|
||||
|
||||
populate_intervals (self);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarkFilter *self = SYSPROF_MARK_FILTER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_value_set_object (value, self->document);
|
||||
break;
|
||||
|
||||
case PROP_CATALOG:
|
||||
g_value_set_object (value, self->catalog);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarkFilter *self = SYSPROF_MARK_FILTER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CATALOG:
|
||||
g_assert (self->catalog == NULL);
|
||||
self->catalog = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_DOCUMENT:
|
||||
g_assert (self->document == NULL);
|
||||
self->document = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_class_init (SysprofMarkFilterClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkFilterClass *filter_class = GTK_FILTER_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_mark_filter_finalize;
|
||||
object_class->constructed = sysprof_mark_filter_constructed;
|
||||
object_class->get_property = sysprof_mark_filter_get_property;
|
||||
object_class->set_property = sysprof_mark_filter_set_property;
|
||||
|
||||
filter_class->match = sysprof_mark_filter_match;
|
||||
|
||||
properties[PROP_CATALOG] =
|
||||
g_param_spec_object ("catalog", NULL, NULL,
|
||||
SYSPROF_TYPE_MARK_CATALOG,
|
||||
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties[PROP_DOCUMENT] =
|
||||
g_param_spec_object ("document", NULL, NULL,
|
||||
SYSPROF_TYPE_DOCUMENT,
|
||||
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_filter_init (SysprofMarkFilter *self)
|
||||
{
|
||||
RB_INIT (&self->head);
|
||||
}
|
||||
|
||||
SysprofMarkFilter *
|
||||
sysprof_mark_filter_new (SysprofDocument *document,
|
||||
SysprofMarkCatalog *catalog)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (document), NULL);
|
||||
g_return_val_if_fail (SYSPROF_IS_MARK_CATALOG (catalog), NULL);
|
||||
|
||||
return g_object_new (SYSPROF_TYPE_MARK_FILTER,
|
||||
"catalog", catalog,
|
||||
"document", document,
|
||||
NULL);
|
||||
}
|
||||
|
||||
SysprofMarkCatalog *
|
||||
sysprof_mark_filter_get_catalog (SysprofMarkFilter *self)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_MARK_FILTER (self), NULL);
|
||||
|
||||
return self->catalog;
|
||||
}
|
||||
38
src/sysprof/sysprof-mark-filter.h
Normal file
38
src/sysprof/sysprof-mark-filter.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* sysprof-mark-filter.h
|
||||
*
|
||||
* Copyright 2025 Georges Basile Stavracas Neto <feaneron@igalia.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "sysprof-session.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_MARK_FILTER (sysprof_mark_filter_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofMarkFilter, sysprof_mark_filter, SYSPROF, MARK_FILTER, GtkFilter)
|
||||
|
||||
SysprofMarkFilter *sysprof_mark_filter_new (SysprofDocument *document,
|
||||
SysprofMarkCatalog *catalog);
|
||||
SysprofMarkCatalog *sysprof_mark_filter_get_catalog (SysprofMarkFilter *self);
|
||||
|
||||
G_END_DECLS
|
||||
@ -43,6 +43,13 @@
|
||||
<property name="model">
|
||||
<object class="SysprofSampledModel">
|
||||
<property name="max-items">5000</property>
|
||||
<property name="model">
|
||||
<object class="GtkFilterListModel">
|
||||
<binding name="filter">
|
||||
<lookup name="filter">
|
||||
<lookup name="session">SysprofSamplesSection</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<property name="model">
|
||||
<object class="SysprofTimeFilterModel">
|
||||
<binding name="time-span">
|
||||
@ -61,6 +68,8 @@
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="x-expression">
|
||||
<lookup name="time" type="SysprofDocumentFrame"/>
|
||||
</property>
|
||||
|
||||
225
src/sysprof/sysprof-session-filters-widget.c
Normal file
225
src/sysprof/sysprof-session-filters-widget.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* sysprof-session-filters-widget.c
|
||||
*
|
||||
* Copyright 2025 Georges Basile Stavracas Neto <feaneron@igalia.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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));
|
||||
}
|
||||
32
src/sysprof/sysprof-session-filters-widget.h
Normal file
32
src/sysprof/sysprof-session-filters-widget.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* sysprof-session-filters-widget.c
|
||||
*
|
||||
* Copyright 2025 Georges Basile Stavracas Neto <feaneron@igalia.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
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
|
||||
112
src/sysprof/sysprof-session-filters-widget.ui
Normal file
112
src/sysprof/sysprof-session-filters-widget.ui
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofSessionFiltersWidget" parent="GtkWidget">
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="max-content-height">400</property>
|
||||
<property name="propagate-natural-height">true</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkListView">
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="model">
|
||||
<object class="GtkNoSelection">
|
||||
<binding name="model">
|
||||
<lookup name="filter">
|
||||
<lookup name="session">SysprofSessionFiltersWidget</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="activatable">false</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="pixel-size">12</property>
|
||||
<binding name="icon-name">
|
||||
<closure type="gchararray" function="filter_to_icon_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="hexpand">true</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filter_to_string">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">window-close-symbolic</property>
|
||||
<property name="action-name">sessionfilters.remove-filter</property>
|
||||
<binding name="action-target">
|
||||
<closure type="GVariant" function="item_to_action_target">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
<lookup name="position">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="flat" />
|
||||
<class name="circular" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkSeparator" />
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="label" translatable="yes">Clear All Filters</property>
|
||||
<signal name="clicked" handler="clear_all_filters" swapped="yes" />
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</template>
|
||||
</interface>
|
||||
@ -22,6 +22,7 @@
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-mark-filter.h"
|
||||
#include "sysprof-session-private.h"
|
||||
#include "sysprof-value-axis.h"
|
||||
|
||||
@ -488,6 +489,24 @@ sysprof_session_zoom_to_selection (SysprofSession *self)
|
||||
sysprof_session_update_axis (self);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_session_filter_by_mark (SysprofSession *self,
|
||||
SysprofMarkCatalog *catalog)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_SESSION (self));
|
||||
g_return_if_fail (catalog == NULL || SYSPROF_IS_MARK_CATALOG (catalog));
|
||||
|
||||
while (g_list_model_get_n_items (G_LIST_MODEL (self->filter)) > 0)
|
||||
gtk_multi_filter_remove (GTK_MULTI_FILTER (self->filter), 0);
|
||||
|
||||
if (catalog)
|
||||
{
|
||||
g_autoptr(SysprofMarkFilter) mark_filter = sysprof_mark_filter_new (self->document, catalog);
|
||||
|
||||
gtk_multi_filter_append (GTK_MULTI_FILTER (self->filter), GTK_FILTER (g_steal_pointer (&mark_filter)));
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
get_time_str (gint64 o)
|
||||
{
|
||||
|
||||
@ -44,5 +44,7 @@ SysprofAxis *sysprof_session_get_selected_time_axis (SysprofSession
|
||||
void sysprof_session_select_time (SysprofSession *self,
|
||||
const SysprofTimeSpan *time_span);
|
||||
void sysprof_session_zoom_to_selection (SysprofSession *self);
|
||||
void sysprof_session_filter_by_mark (SysprofSession *self,
|
||||
SysprofMarkCatalog *catalog);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -126,6 +126,36 @@
|
||||
<property name="tooltip-text" translatable="yes">Toggle Left Panel</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="start">
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">false</property>
|
||||
<property name="icon-name">funnel-outline-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">View Filters</property>
|
||||
<property name="popover">
|
||||
<object class="GtkPopover">
|
||||
<style>
|
||||
<class name="menu" />
|
||||
</style>
|
||||
<property name="child">
|
||||
<object class="SysprofSessionFiltersWidget">
|
||||
<binding name="session">
|
||||
<lookup name="session">SysprofWindow</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
<binding name="visible">
|
||||
<closure type="gboolean" function="n_filters_to_button_visibility">
|
||||
<lookup name="n-items" type="GtkMultiFilter">
|
||||
<lookup name="filter" type="SysprofSession">
|
||||
<lookup name="session">SysprofWindow</lookup>
|
||||
</lookup>
|
||||
</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child type="start">
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">6</property>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/empty-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/energy-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/flamegraph-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/funnel-outline-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/graphics-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/mark-chart-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks">icons/scalable/actions/mark-table-symbolic.svg</file>
|
||||
@ -50,6 +51,7 @@
|
||||
<file preprocess="xml-stripblanks">sysprof-processes-section.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-recording-pad.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-samples-section.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-session-filters-widget.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-sidebar.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-storage-section.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-task-row.ui</file>
|
||||
|
||||
Reference in New Issue
Block a user