sysprof: add progressbar while loading

And try to keep some of the window disabled during the loading process.
This commit is contained in:
Christian Hergert
2023-08-07 14:32:49 -07:00
parent 170122abc8
commit 65515cfe64
5 changed files with 283 additions and 125 deletions

View File

@ -64,6 +64,7 @@ sysprof_sources = [
'sysprof-time-span-layer.c', 'sysprof-time-span-layer.c',
'sysprof-traceables-utility.c', 'sysprof-traceables-utility.c',
'sysprof-tree-expander.c', 'sysprof-tree-expander.c',
'sysprof-util.c',
'sysprof-value-axis.c', 'sysprof-value-axis.c',
'sysprof-weighted-callgraph-view.c', 'sysprof-weighted-callgraph-view.c',
'sysprof-window.c', 'sysprof-window.c',

View File

@ -0,0 +1,68 @@
/* sysprof-util.c
*
* Copyright 2023 Christian Hergert <chergert@redhat.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 "config.h"
#include "sysprof-util.h"
static gboolean
hide_callback (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
gint64 *begin_time = user_data;
double fraction;
g_assert (GTK_IS_WIDGET (widget));
g_assert (begin_time != NULL);
fraction = (g_get_monotonic_time () - *begin_time) / (double)G_USEC_PER_SEC;
if (fraction > 1)
{
gtk_widget_set_visible (widget, FALSE);
gtk_widget_set_opacity (widget, 1);
return G_SOURCE_REMOVE;
}
if (fraction < 0)
fraction = 0;
gtk_widget_set_opacity (widget, 1.-fraction);
return G_SOURCE_CONTINUE;
}
void
_gtk_widget_hide_with_fade (GtkWidget *widget)
{
gint64 begin_time;
g_return_if_fail (GTK_IS_WIDGET (widget));
if (!gtk_widget_get_visible (widget))
return;
begin_time = g_get_monotonic_time ();
gtk_widget_add_tick_callback (widget,
hide_callback,
g_memdup2 (&begin_time, sizeof begin_time),
g_free);
}

View File

@ -0,0 +1,29 @@
/* sysprof-util.h
*
* Copyright 2023 Christian Hergert <chergert@redhat.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
void _gtk_widget_hide_with_fade (GtkWidget *widget);
G_END_DECLS

View File

@ -38,6 +38,7 @@
#include "sysprof-samples-section.h" #include "sysprof-samples-section.h"
#include "sysprof-sidebar.h" #include "sysprof-sidebar.h"
#include "sysprof-storage-section.h" #include "sysprof-storage-section.h"
#include "sysprof-util.h"
#include "sysprof-window.h" #include "sysprof-window.h"
struct _SysprofWindow struct _SysprofWindow
@ -50,6 +51,7 @@ struct _SysprofWindow
GtkToggleButton *show_right_sidebar; GtkToggleButton *show_right_sidebar;
GtkWidget *left_split_overlay; GtkWidget *left_split_overlay;
GtkWidget *right_split_overlay; GtkWidget *right_split_overlay;
GtkProgressBar *progress_bar;
guint disposed : 1; guint disposed : 1;
}; };
@ -57,6 +59,7 @@ struct _SysprofWindow
enum { enum {
PROP_0, PROP_0,
PROP_DOCUMENT, PROP_DOCUMENT,
PROP_IS_LOADED,
PROP_SESSION, PROP_SESSION,
N_PROPS N_PROPS
}; };
@ -93,6 +96,33 @@ sysprof_window_update_zoom_actions (SysprofWindow *self)
visible_time->end_nsec < document_time->end_nsec); visible_time->end_nsec < document_time->end_nsec);
} }
static void
sysprof_window_update_action_state (SysprofWindow *self)
{
g_assert (SYSPROF_IS_WINDOW (self));
if (self->session == NULL)
{
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.open-capture", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.record-capture", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "session.zoom-one", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "session.zoom-out", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "session.zoom-in", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "session.seek-forward", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "session.seek-backward", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.save-capture", FALSE);
}
else
{
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.open-capture", TRUE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.record-capture", TRUE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.save-capture", TRUE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "session.zoom-in", TRUE);
sysprof_window_update_zoom_actions (self);
}
}
static void static void
sysprof_window_open_file_cb (GObject *object, sysprof_window_open_file_cb (GObject *object,
GAsyncResult *result, GAsyncResult *result,
@ -223,9 +253,10 @@ sysprof_window_set_document (SysprofWindow *self,
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (action)); g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (action));
} }
sysprof_window_update_zoom_actions (self); sysprof_window_update_action_state (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DOCUMENT]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DOCUMENT]);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IS_LOADED]);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]);
} }
@ -464,6 +495,10 @@ sysprof_window_get_property (GObject *object,
g_value_set_object (value, sysprof_window_get_document (self)); g_value_set_object (value, sysprof_window_get_document (self));
break; break;
case PROP_IS_LOADED:
g_value_set_boolean (value, !!sysprof_window_get_document (self));
break;
case PROP_SESSION: case PROP_SESSION:
g_value_set_object (value, sysprof_window_get_session (self)); g_value_set_object (value, sysprof_window_get_session (self));
break; break;
@ -507,6 +542,11 @@ sysprof_window_class_init (SysprofWindowClass *klass)
SYSPROF_TYPE_DOCUMENT, SYSPROF_TYPE_DOCUMENT,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
properties [PROP_IS_LOADED] =
g_param_spec_boolean ("is-loaded", NULL, NULL,
FALSE,
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
properties[PROP_SESSION] = properties[PROP_SESSION] =
g_param_spec_object ("session", NULL, NULL, g_param_spec_object ("session", NULL, NULL,
SYSPROF_TYPE_SESSION, SYSPROF_TYPE_SESSION,
@ -516,9 +556,10 @@ sysprof_window_class_init (SysprofWindowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-window.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-window.ui");
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, show_right_sidebar);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, left_split_overlay); gtk_widget_class_bind_template_child (widget_class, SysprofWindow, left_split_overlay);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, progress_bar);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, right_split_overlay); gtk_widget_class_bind_template_child (widget_class, SysprofWindow, right_split_overlay);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, show_right_sidebar);
gtk_widget_class_bind_template_callback (widget_class, main_view_notify_sidebar); gtk_widget_class_bind_template_callback (widget_class, main_view_notify_sidebar);
@ -567,6 +608,8 @@ sysprof_window_init (SysprofWindow *self)
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
sysprof_window_update_action_state (self);
show_left_sidebar = g_property_action_new ("show-left-sidebar", show_left_sidebar = g_property_action_new ("show-left-sidebar",
self->left_split_overlay, self->left_split_overlay,
"show-sidebar"); "show-sidebar");
@ -642,6 +685,8 @@ sysprof_window_load_cb (GObject *object,
g_application_release (G_APPLICATION (app)); g_application_release (G_APPLICATION (app));
_gtk_widget_hide_with_fade (GTK_WIDGET (self->progress_bar));
if (!(document = sysprof_document_loader_load_finish (loader, result, &error))) if (!(document = sysprof_document_loader_load_finish (loader, result, &error)))
{ {
GtkWidget *dialog; GtkWidget *dialog;
@ -658,8 +703,6 @@ sysprof_window_load_cb (GObject *object,
} }
sysprof_window_set_document (self, document); sysprof_window_set_document (self, document);
gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
} }
static void static void
@ -692,8 +735,10 @@ sysprof_window_open (SysprofApplication *app,
self = g_object_new (SYSPROF_TYPE_WINDOW, self = g_object_new (SYSPROF_TYPE_WINDOW,
"application", app, "application", app,
"sensitive", FALSE,
NULL); NULL);
g_object_bind_property (loader, "fraction",
self->progress_bar, "fraction",
G_BINDING_SYNC_CREATE);
sysprof_document_loader_load_async (loader, sysprof_document_loader_load_async (loader,
NULL, NULL,
sysprof_window_load_cb, sysprof_window_load_cb,

View File

@ -46,6 +46,9 @@
<property name="max-sidebar-width">200</property> <property name="max-sidebar-width">200</property>
<property name="sidebar"> <property name="sidebar">
<object class="AdwNavigationPage"> <object class="AdwNavigationPage">
<binding name="sensitive">
<lookup name="is-loaded">SysprofWindow</lookup>
</binding>
<property name="child"> <property name="child">
<object class="AdwToolbarView"> <object class="AdwToolbarView">
<child type="top"> <child type="top">
@ -165,129 +168,141 @@
</object> </object>
</child> </child>
<property name="content"> <property name="content">
<object class="GtkStack" id="section_stack"> <object class="GtkOverlay">
<property name="vexpand">true</property> <child type="overlay">
<child> <object class="GtkProgressBar" id="progress_bar">
<object class="SysprofSamplesSection"> <property name="hexpand">true</property>
<property name="category">callgraph</property> <style>
<property name="icon-name">org.gnome.Sysprof-symbolic</property> <class name="osd"/>
<binding name="session"> </style>
<lookup name="session">SysprofWindow</lookup>
</binding>
</object> </object>
</child> </child>
<child> <child>
<object class="SysprofMemorySection"> <object class="GtkStack" id="section_stack">
<property name="category">callgraph</property> <property name="vexpand">true</property>
<property name="icon-name">memory-allocations-symbolic</property> <child>
<binding name="session"> <object class="SysprofSamplesSection">
<lookup name="session">SysprofWindow</lookup> <property name="category">callgraph</property>
</binding> <property name="icon-name">org.gnome.Sysprof-symbolic</property>
</object> <binding name="session">
</child> <lookup name="session">SysprofWindow</lookup>
<child> </binding>
<object class="SysprofLogsSection"> </object>
<property name="category">processes</property> </child>
<property name="icon-name">system-log-symbolic</property> <child>
<binding name="session"> <object class="SysprofMemorySection">
<lookup name="session">SysprofWindow</lookup> <property name="category">callgraph</property>
</binding> <property name="icon-name">memory-allocations-symbolic</property>
</object> <binding name="session">
</child> <lookup name="session">SysprofWindow</lookup>
<child> </binding>
<object class="SysprofMarksSection"> </object>
<property name="category">processes</property> </child>
<property name="icon-name">mark-chart-symbolic</property> <child>
<binding name="session"> <object class="SysprofLogsSection">
<lookup name="session">SysprofWindow</lookup> <property name="category">processes</property>
</binding> <property name="icon-name">system-log-symbolic</property>
</object> <binding name="session">
</child> <lookup name="session">SysprofWindow</lookup>
<child> </binding>
<object class="SysprofProcessesSection"> </object>
<property name="category">processes</property> </child>
<property name="icon-name">application-x-executable-symbolic</property> <child>
<binding name="session"> <object class="SysprofMarksSection">
<lookup name="session">SysprofWindow</lookup> <property name="category">processes</property>
</binding> <property name="icon-name">mark-chart-symbolic</property>
</object> <binding name="session">
</child> <lookup name="session">SysprofWindow</lookup>
<child> </binding>
<object class="SysprofDBusSection"> </object>
<property name="title" translatable="yes">D-Bus</property> </child>
<property name="category">processes</property> <child>
<property name="icon-name">dbus-symbolic</property> <object class="SysprofProcessesSection">
<binding name="session"> <property name="category">processes</property>
<lookup name="session">SysprofWindow</lookup> <property name="icon-name">application-x-executable-symbolic</property>
</binding> <binding name="session">
</object> <lookup name="session">SysprofWindow</lookup>
</child> </binding>
<child> </object>
<object class="SysprofCpuSection"> </child>
<property name="title" translatable="yes">CPU</property> <child>
<property name="category">counters</property> <object class="SysprofDBusSection">
<property name="icon-name">system-run-symbolic</property> <property name="title" translatable="yes">D-Bus</property>
<binding name="session"> <property name="category">processes</property>
<lookup name="session">SysprofWindow</lookup> <property name="icon-name">dbus-symbolic</property>
</binding> <binding name="session">
</object> <lookup name="session">SysprofWindow</lookup>
</child> </binding>
<child> </object>
<object class="SysprofEnergySection"> </child>
<property name="title" translatable="yes">Energy</property> <child>
<property name="category">counters</property> <object class="SysprofCpuSection">
<property name="icon-name">energy-symbolic</property> <property name="title" translatable="yes">CPU</property>
<binding name="session"> <property name="category">counters</property>
<lookup name="session">SysprofWindow</lookup> <property name="icon-name">system-run-symbolic</property>
</binding> <binding name="session">
</object> <lookup name="session">SysprofWindow</lookup>
</child> </binding>
<child> </object>
<object class="SysprofGraphicsSection"> </child>
<property name="title" translatable="yes">Graphics</property> <child>
<property name="category">counters</property> <object class="SysprofEnergySection">
<property name="icon-name">graphics-symbolic</property> <property name="title" translatable="yes">Energy</property>
<binding name="session"> <property name="category">counters</property>
<lookup name="session">SysprofWindow</lookup> <property name="icon-name">energy-symbolic</property>
</binding> <binding name="session">
</object> <lookup name="session">SysprofWindow</lookup>
</child> </binding>
<child> </object>
<object class="SysprofNetworkSection"> </child>
<property name="title" translatable="yes">Network</property> <child>
<property name="category">counters</property> <object class="SysprofGraphicsSection">
<property name="icon-name">network-transmit-receive-symbolic</property> <property name="title" translatable="yes">Graphics</property>
<binding name="session"> <property name="category">counters</property>
<lookup name="session">SysprofWindow</lookup> <property name="icon-name">graphics-symbolic</property>
</binding> <binding name="session">
</object> <lookup name="session">SysprofWindow</lookup>
</child> </binding>
<child> </object>
<object class="SysprofStorageSection"> </child>
<property name="title" translatable="yes">Storage</property> <child>
<property name="category">counters</property> <object class="SysprofNetworkSection">
<property name="icon-name">storage-symbolic</property> <property name="title" translatable="yes">Network</property>
<binding name="session"> <property name="category">counters</property>
<lookup name="session">SysprofWindow</lookup> <property name="icon-name">network-transmit-receive-symbolic</property>
</binding> <binding name="session">
</object> <lookup name="session">SysprofWindow</lookup>
</child> </binding>
<child> </object>
<object class="SysprofFilesSection"> </child>
<property name="category">auxiliary</property> <child>
<property name="icon-name">folder-symbolic</property> <object class="SysprofStorageSection">
<binding name="session"> <property name="title" translatable="yes">Storage</property>
<lookup name="session">SysprofWindow</lookup> <property name="category">counters</property>
</binding> <property name="icon-name">storage-symbolic</property>
</object> <binding name="session">
</child> <lookup name="session">SysprofWindow</lookup>
<child> </binding>
<object class="SysprofMetadataSection"> </object>
<property name="category">auxiliary</property> </child>
<property name="icon-name">metadata-symbolic</property> <child>
<binding name="session"> <object class="SysprofFilesSection">
<lookup name="session">SysprofWindow</lookup> <property name="category">auxiliary</property>
</binding> <property name="icon-name">folder-symbolic</property>
<binding name="session">
<lookup name="session">SysprofWindow</lookup>
</binding>
</object>
</child>
<child>
<object class="SysprofMetadataSection">
<property name="category">auxiliary</property>
<property name="icon-name">metadata-symbolic</property>
<binding name="session">
<lookup name="session">SysprofWindow</lookup>
</binding>
</object>
</child>
</object> </object>
</child> </child>
</object> </object>