sysprof: start on new application design

This commit is contained in:
Christian Hergert
2023-07-07 13:01:15 -07:00
parent fc10c98e8d
commit d6539c1bdb
10 changed files with 383 additions and 595 deletions

View File

@ -5,99 +5,13 @@
<object class="GtkShortcutsSection">
<property name="section-name">shortcuts</property>
<property name="max-height">12</property>
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Files</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Save Recording</property>
<property name="subtitle" translatable="yes" context="shortcut window">Saves the current recording</property>
<property name="action-name">win.save-capture</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Open recording</property>
<property name="subtitle" translatable="yes" context="shortcut window">Opens a previously saved recording</property>
<property name="action-name">app.open-capture</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Recording</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Record again</property>
<property name="subtitle" translatable="yes" context="shortcut window">Starts a new recording</property>
<property name="action-name">win.replay-capture</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Stop recording</property>
<property name="accelerator">Escape</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Callgraph</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Expand function</property>
<property name="subtitle" translatable="yes" context="shortcut window">Shows the direct descendants of the callgraph function</property>
<property name="accelerator">Right</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Collapse function</property>
<property name="subtitle" translatable="yes" context="shortcut window">Hides all callgraph descendants below the selected function</property>
<property name="accelerator">Left</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Jump into function</property>
<property name="subtitle" translatable="yes" context="shortcut window">Selects the function or file as the top of the callgraph</property>
<property name="accelerator">Return</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Visualizers</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Zoom in</property>
<property name="accelerator">&lt;primary&gt;plus</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Zoom out</property>
<property name="accelerator">&lt;primary&gt;minus</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Reset zoom</property>
<property name="accelerator">&lt;primary&gt;0</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">General</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Show Help</property>
<property name="action-name">app.help</property>
<property name="action-name">win.help</property>
</object>
</child>
<child>
@ -106,28 +20,10 @@
<property name="action-name">win.show-help-overlay</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">New Tab</property>
<property name="action-name">win.new-tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Switch Tab</property>
<property name="accelerator">&lt;alt&gt;1...9</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">New Window</property>
<property name="action-name">app.new-window</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Close Window</property>
<property name="action-name">win.close-tab</property>
<property name="action-name">window.close</property>
</object>
</child>
<child>

View File

@ -1,50 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="win-menu">
<section id="win-menu-new">
<item>
<attribute name="label" translatable="yes">New Tab</attribute>
<attribute name="action">win.new-tab</attribute>
</item>
<item>
<attribute name="label" translatable="yes">New Window</attribute>
<attribute name="action">app.new-window</attribute>
</item>
</section>
<section id="win-menu-file">
<item>
<attribute name="label" translatable="yes">Open Recording…</attribute>
<attribute name="action">app.open-capture</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Save Recording…</attribute>
<attribute name="action">win.save-capture</attribute>
</item>
</section>
<section id="win-menu-replay">
<item>
<attribute name="label" translatable="yes">Record Again</attribute>
<attribute name="action">win.replay-capture</attribute>
</item>
</section>
<section id="win-menu-close">
<item>
<attribute name="label" translatable="yes">Close</attribute>
<attribute name="action">win.close-tab</attribute>
</item>
</section>
<section id="win-menu-misc">
<item>
<attribute name="label" translatable="yes">Keyboard Shortcuts</attribute>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">win.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Help</attribute>
<attribute name="action">app.help</attribute>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">win.help</attribute>
</item>
<item>
<attribute name="label" translatable="yes">About Sysprof</attribute>
<attribute name="action">app.about</attribute>
<attribute name="label" translatable="yes">_About Sysprof</attribute>
<attribute name="action">win.about</attribute>
</item>
</section>
</menu>

View File

@ -1,6 +1,6 @@
/* main.c
*
* Copyright 2016 Christian Hergert <christian@hergert.me>
* Copyright 2016-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
@ -14,20 +14,24 @@
*
* 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 <locale.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <sysprof.h>
#include <sysprof-capture.h>
#include "sysprof-application.h"
gint
main (gint argc,
gchar *argv[])
int
main (int argc,
char *argv[])
{
g_autoptr(SysprofApplication) app = NULL;
gint ret;

View File

@ -1,5 +1,5 @@
sysprof_sources = [
'sysprof.c',
'main.c',
'sysprof-application.c',
'sysprof-window.c',
]
@ -11,11 +11,11 @@ sysprof_resources = gnome.compile_resources('sysprof-resources', 'sysprof.gresou
sysprof_deps = [
cc.find_library('m', required: false),
libsysprof_capture_dep,
libsysprof_dep,
libsysprof_ui_dep,
dependency('pangoft2', required: false),
dependency('libadwaita-1', version: '>= 1.2.alpha'),
dependency('libadwaita-1', version: '>= 1.4.alpha'),
dependency('libpanel-1', version: '>= 1.3.0'),
libsysprof_analyze_static_dep,
libsysprof_profile_static_dep,
libsysprof_gtk_static_dep,
]
sysprof = executable('sysprof', sysprof_resources + sysprof_sources,

View File

@ -32,100 +32,37 @@ struct _SysprofApplication
G_DEFINE_TYPE (SysprofApplication, sysprof_application, ADW_TYPE_APPLICATION)
struct {
const gchar *action_name;
const gchar *accels[12];
} default_accels[] = {
{ "app.help", { "F1", NULL } },
{ "app.quit", { "<Primary>q", NULL } },
{ "app.new-window", { "<Primary>n", NULL } },
{ "app.open-capture", { "<Primary>o", NULL } },
{ "zoom.zoom-in", { "<Primary>plus", "<Primary>KP_Add", "<Primary>equal", "ZoomIn", NULL } },
{ "zoom.zoom-out", { "<Primary>minus", "<Primary>KP_Subtract", "ZoomOut", NULL } },
{ "zoom.zoom-one", { "<Primary>0", "<Primary>KP_0", NULL } },
{ "win.new-tab", { "<Primary>t", NULL } },
{ "win.close-tab", { "<Primary>w", NULL } },
{ "win.replay-capture", { "<Primary>r", NULL } },
{ "win.save-capture", { "<Primary>s", NULL } },
{ "win.switch-tab(1)", { "<Alt>1", NULL } },
{ "win.switch-tab(2)", { "<Alt>2", NULL } },
{ "win.switch-tab(3)", { "<Alt>3", NULL } },
{ "win.switch-tab(4)", { "<Alt>4", NULL } },
{ "win.switch-tab(5)", { "<Alt>5", NULL } },
{ "win.switch-tab(6)", { "<Alt>6", NULL } },
{ "win.switch-tab(7)", { "<Alt>7", NULL } },
{ "win.switch-tab(8)", { "<Alt>8", NULL } },
{ "win.switch-tab(9)", { "<Alt>9", NULL } },
{ NULL }
};
static void
sysprof_application_activate (GApplication *app)
{
SysprofWindow *window;
GList *windows;
g_assert (GTK_IS_APPLICATION (app));
windows = gtk_application_get_windows (GTK_APPLICATION (app));
for (; windows != NULL; windows = windows->next)
for (const GList *iter = gtk_application_get_windows (GTK_APPLICATION (app));
iter != NULL;
iter = iter->next)
{
if (SYSPROF_IS_WINDOW (windows->data))
if (SYSPROF_IS_WINDOW (iter->data))
{
gtk_window_present (windows->data);
gtk_window_present (iter->data);
return;
}
}
window = SYSPROF_WINDOW (sysprof_window_new (SYSPROF_APPLICATION (app)));
gtk_window_present (GTK_WINDOW (window));
g_warning ("TODO: show greeter window");
}
static void
sysprof_application_open (GApplication *app,
GFile **files,
gint n_files,
const gchar *hint)
int n_files,
const char *hint)
{
GtkWidget *window;
g_assert (SYSPROF_IS_APPLICATION (app));
g_assert (files != NULL || n_files == 0);
window = sysprof_window_new (SYSPROF_APPLICATION (app));
/* Present window before opening files so that message dialogs
* always display above the window.
*/
gtk_window_present (GTK_WINDOW (window));
for (gint i = 0; i < n_files; i++)
sysprof_window_open (SYSPROF_WINDOW (window), files[i]);
if (n_files == 0)
sysprof_application_activate (app);
}
static void
sysprof_application_startup (GApplication *application)
{
g_autoptr(GtkCssProvider) provider = NULL;
g_assert (SYSPROF_IS_APPLICATION (application));
G_APPLICATION_CLASS (sysprof_application_parent_class)->startup (application);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gnome/sysprof/theme/shared.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_THEME+1);
for (guint i = 0; default_accels[i].action_name; i++)
gtk_application_set_accels_for_action (GTK_APPLICATION (application),
default_accels[i].action_name,
default_accels[i].accels);
for (guint i = 0; i < n_files; i++)
sysprof_window_open (SYSPROF_APPLICATION (app), files[i]);
}
static void
@ -149,7 +86,6 @@ sysprof_application_class_init (SysprofApplicationClass *klass)
GtkApplicationClass *gtk_app_class = GTK_APPLICATION_CLASS (klass);
app_class->open = sysprof_application_open;
app_class->startup = sysprof_application_startup;
app_class->activate = sysprof_application_activate;
gtk_app_class->window_added = sysprof_application_window_added;
@ -176,7 +112,7 @@ sysprof_about (GSimpleAction *action,
{
GtkApplication *app = user_data;
GtkWindow *best_toplevel = NULL;
GList *windows;
const GList *windows;
g_assert (G_IS_APPLICATION (app));
g_assert (G_IS_SIMPLE_ACTION (action));
@ -193,12 +129,12 @@ sysprof_about (GSimpleAction *action,
}
}
adw_show_about_window(best_toplevel,
adw_show_about_window (best_toplevel,
"application-name", _("Sysprof"),
"application-icon", APP_ID_S,
"version", "GNOME " SYMBOLIC_VERSION " (" PACKAGE_VERSION ")",
"copyright", "Copyright 2004-2009 Søren Sandmann Pedersen\n"
"Copyright 2016-2021 Christian Hergert",
"Copyright 2016-2023 Christian Hergert",
"issue-url", "https://gitlab.gnome.org/GNOME/sysprof/-/issues/new",
"license-type", GTK_LICENSE_GPL_3_0,
"developers", sysprof_authors,
@ -215,67 +151,24 @@ sysprof_help (GSimpleAction *action,
gpointer user_data)
{
SysprofApplication *self = user_data;
g_autoptr(GtkUriLauncher) launcher = NULL;
GtkWindow *window;
g_assert (SYSPROF_IS_APPLICATION (self));
g_assert (G_IS_SIMPLE_ACTION (action));
window = gtk_application_get_active_window (GTK_APPLICATION (self));
gtk_show_uri (window, "help:sysprof", GDK_CURRENT_TIME);
}
static void
sysprof_new_window (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
SysprofApplication *self = user_data;
SysprofWindow *window;
g_assert (SYSPROF_IS_APPLICATION (self));
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
window = SYSPROF_WINDOW (sysprof_window_new (self));
gtk_window_present (GTK_WINDOW (window));
}
static void
sysprof_open_capture (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
GtkApplication *app = user_data;
GList *list;
g_assert (G_IS_APPLICATION (app));
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
list = gtk_application_get_windows (app);
for (; list != NULL; list = list->next)
{
GtkWindow *window = list->data;
if (SYSPROF_IS_WINDOW (window))
{
sysprof_window_open_from_dialog (SYSPROF_WINDOW (window));
break;
}
}
launcher = gtk_uri_launcher_new ("help:sysprof");
gtk_uri_launcher_launch (launcher, window, NULL, NULL, NULL);
}
static void
sysprof_application_init (SysprofApplication *self)
{
static const GActionEntry actions[] = {
{ "about", sysprof_about },
{ "new-window", sysprof_new_window },
{ "open-capture", sysprof_open_capture },
{ "help", sysprof_help },
{ "quit", sysprof_quit },
{ "about", sysprof_about },
{ "help", sysprof_help },
{ "quit", sysprof_quit },
};
setlocale (LC_ALL, "");
@ -286,7 +179,10 @@ sysprof_application_init (SysprofApplication *self)
g_set_application_name (_("Sysprof"));
g_action_map_add_action_entries (G_ACTION_MAP (self), actions, G_N_ELEMENTS (actions), self);
g_action_map_add_action_entries (G_ACTION_MAP (self),
actions,
G_N_ELEMENTS (actions),
self);
g_application_set_default (G_APPLICATION (self));
}

View File

@ -1,6 +1,6 @@
/* sysprof-window.c
*
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
* 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
@ -18,167 +18,99 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "sysprof-window"
#include "config.h"
#include <glib/gi18n.h>
#include <sysprof-ui.h>
#include <sysprof-gtk.h>
#include "sysprof-window.h"
struct _SysprofWindow
{
AdwApplicationWindow parent_instance;
GBindingGroup *bindings;
SysprofNotebook *notebook;
GtkButton *open_button;
GtkMenuButton *menu_button;
SysprofDocument *document;
SysprofSession *session;
};
G_DEFINE_TYPE (SysprofWindow, sysprof_window, ADW_TYPE_APPLICATION_WINDOW)
enum {
PROP_0,
PROP_DOCUMENT,
PROP_SESSION,
N_PROPS
};
/**
* sysprof_window_new:
*
* Create a new #SysprofWindow.
*
* Returns: (transfer full): a newly created #SysprofWindow
*/
GtkWidget *
sysprof_window_new (SysprofApplication *application)
{
return g_object_new (SYSPROF_TYPE_WINDOW,
"application", application,
NULL);
}
G_DEFINE_FINAL_TYPE (SysprofWindow, sysprof_window, ADW_TYPE_APPLICATION_WINDOW)
static GParamSpec *properties [N_PROPS];
static void
sysprof_window_notify_can_replay_cb (SysprofWindow *self,
GParamSpec *pspec,
SysprofNotebook *notebook)
sysprof_window_set_document (SysprofWindow *self,
SysprofDocument *document)
{
g_assert (SYSPROF_IS_WINDOW (self));
g_assert (SYSPROF_IS_NOTEBOOK (notebook));
g_assert (SYSPROF_IS_DOCUMENT (document));
g_assert (self->document == NULL);
g_assert (self->session == NULL);
gtk_widget_action_set_enabled (GTK_WIDGET (self),
"win.replay-capture",
sysprof_notebook_get_can_replay (notebook));
g_set_object (&self->document, document);
self->session = sysprof_session_new (document);
}
static void
sysprof_window_notify_can_save_cb (SysprofWindow *self,
GParamSpec *pspec,
SysprofNotebook *notebook)
{
g_assert (SYSPROF_IS_WINDOW (self));
g_assert (SYSPROF_IS_NOTEBOOK (notebook));
gtk_widget_action_set_enabled (GTK_WIDGET (self),
"win.save-capture",
sysprof_notebook_get_can_save (notebook));
}
static void
new_tab_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofWindow *self = (SysprofWindow *)widget;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
sysprof_window_new_tab (self);
}
static void
switch_tab_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofWindow *self = (SysprofWindow *)widget;
int page;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
g_return_if_fail (g_variant_is_of_type (param, G_VARIANT_TYPE_INT32));
page = g_variant_get_int32 (param);
sysprof_notebook_set_current_page (self->notebook, page - 1);
}
static void
close_tab_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofWindow *self = (SysprofWindow *)widget;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
if (sysprof_notebook_get_n_pages (self->notebook) == 1)
{
SysprofDisplay *child = sysprof_notebook_get_nth_page (self->notebook, 0);
if (SYSPROF_IS_DISPLAY (child) &&
sysprof_display_is_empty (SYSPROF_DISPLAY (child)))
{
gtk_window_destroy (GTK_WINDOW (self));
return;
}
}
sysprof_notebook_close_current (self->notebook);
}
static void
replay_capture_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofWindow *self = (SysprofWindow *)widget;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
sysprof_notebook_replay (self->notebook);
}
static void
save_capture_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofWindow *self = (SysprofWindow *)widget;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
sysprof_notebook_save (self->notebook);
}
static void
stop_recording_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofWindow *self = (SysprofWindow *)widget;
SysprofDisplay *current;
g_assert (SYSPROF_IS_WINDOW (self));
if ((current = sysprof_notebook_get_current (self->notebook)))
sysprof_display_stop_recording (current);
}
static void
sysprof_window_finalize (GObject *object)
sysprof_window_dispose (GObject *object)
{
SysprofWindow *self = (SysprofWindow *)object;
g_binding_group_set_source (self->bindings, NULL);
g_clear_object (&self->bindings);
gtk_widget_dispose_template (GTK_WIDGET (self), SYSPROF_TYPE_WINDOW);
G_OBJECT_CLASS (sysprof_window_parent_class)->finalize (object);
g_clear_object (&self->document);
g_clear_object (&self->session);
G_OBJECT_CLASS (sysprof_window_parent_class)->dispose (object);
}
static void
sysprof_window_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SysprofWindow *self = SYSPROF_WINDOW (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_value_set_object (value, sysprof_window_get_document (self));
break;
case PROP_SESSION:
g_value_set_object (value, sysprof_window_get_session (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
sysprof_window_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SysprofWindow *self = SYSPROF_WINDOW (object);
switch (prop_id)
{
case PROP_DOCUMENT:
sysprof_window_set_document (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
@ -187,131 +119,138 @@ sysprof_window_class_init (SysprofWindowClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = sysprof_window_finalize;
object_class->dispose = sysprof_window_dispose;
object_class->get_property = sysprof_window_get_property;
object_class->set_property = sysprof_window_set_property;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-window.ui");
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, menu_button);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, open_button);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, notebook);
properties[PROP_DOCUMENT] =
g_param_spec_object ("document", NULL, NULL,
SYSPROF_TYPE_DOCUMENT,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
gtk_widget_class_install_action (widget_class, "win.close-tab", NULL, close_tab_cb);
gtk_widget_class_install_action (widget_class, "win.new-tab", NULL, new_tab_cb);
gtk_widget_class_install_action (widget_class, "win.switch-tab", "i", switch_tab_cb);
gtk_widget_class_install_action (widget_class, "win.replay-capture", NULL, replay_capture_cb);
gtk_widget_class_install_action (widget_class, "win.save-capture", NULL, save_capture_cb);
gtk_widget_class_install_action (widget_class, "win.stop-recording", NULL, stop_recording_cb);
properties[PROP_SESSION] =
g_param_spec_object ("session", NULL, NULL,
SYSPROF_TYPE_SESSION,
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "win.stop-recording", NULL);
g_object_class_install_properties (object_class, N_PROPS, properties);
g_type_ensure (SYSPROF_TYPE_NOTEBOOK);
g_type_ensure (SYSPROF_TYPE_DISPLAY);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-window.ui");
g_type_ensure (SYSPROF_TYPE_DOCUMENT);
g_type_ensure (SYSPROF_TYPE_SESSION);
}
static void
sysprof_window_init (SysprofWindow *self)
{
GMenu *menu;
gtk_widget_init_template (GTK_WIDGET (self));
menu = gtk_application_get_menu_by_id (GTK_APPLICATION (g_application_get_default ()), "win-menu");
gtk_menu_button_set_menu_model (self->menu_button, G_MENU_MODEL (menu));
g_signal_connect_object (self->notebook,
"notify::can-replay",
G_CALLBACK (sysprof_window_notify_can_replay_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->notebook,
"notify::can-save",
G_CALLBACK (sysprof_window_notify_can_save_cb),
self,
G_CONNECT_SWAPPED);
self->bindings = g_binding_group_new ();
g_binding_group_bind (self->bindings, "title", self, "title", G_BINDING_SYNC_CREATE);
g_object_bind_property (self->notebook, "current", self->bindings, "source",
G_BINDING_SYNC_CREATE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.save-capture", FALSE);
gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.replay-capture", FALSE);
}
void
sysprof_window_open (SysprofWindow *self,
GFile *file)
GtkWidget *
sysprof_window_new (SysprofApplication *app,
SysprofDocument *document)
{
g_return_if_fail (SYSPROF_IS_WINDOW (self));
g_return_if_fail (G_IS_FILE (file));
g_return_val_if_fail (SYSPROF_IS_APPLICATION (app), NULL);
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (document), NULL);
sysprof_notebook_open (self->notebook, file);
return g_object_new (SYSPROF_TYPE_WINDOW,
"application", app,
"document", document,
NULL);
}
/**
* sysprof_window_get_session:
* @self: a #SysprofWindow
*
* Gets the session for the window.
*
* Returns: (transfer none): a #SysprofSession
*/
SysprofSession *
sysprof_window_get_session (SysprofWindow *self)
{
g_return_val_if_fail (SYSPROF_IS_WINDOW (self), NULL);
return self->session;
}
/**
* sysprof_window_get_document:
* @self: a #SysprofWindow
*
* Gets the document for the window.
*
* Returns: (transfer none): a #SysprofDocument
*/
SysprofDocument *
sysprof_window_get_document (SysprofWindow *self)
{
g_return_val_if_fail (SYSPROF_IS_WINDOW (self), NULL);
return self->document;
}
static void
sysprof_window_open_from_dialog_cb (SysprofWindow *self,
int response,
GtkFileChooserNative *dialog)
sysprof_window_load_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
g_assert (SYSPROF_IS_WINDOW (self));
g_assert (GTK_IS_FILE_CHOOSER_NATIVE (dialog));
SysprofDocumentLoader *loader = (SysprofDocumentLoader *)object;
g_autoptr(SysprofApplication) app = user_data;
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GError) error = NULL;
if (response == GTK_RESPONSE_ACCEPT)
g_assert (SYSPROF_IS_DOCUMENT_LOADER (loader));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (SYSPROF_IS_APPLICATION (app));
g_application_release (G_APPLICATION (app));
if (!(document = sysprof_document_loader_load_finish (loader, result, &error)))
{
g_autoptr(GFile) file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
GtkWidget *dialog;
if (g_file_is_native (file))
sysprof_window_open (self, file);
dialog = adw_message_dialog_new (NULL, _("Invalid Document"), NULL);
adw_message_dialog_format_body (ADW_MESSAGE_DIALOG (dialog),
_("The document could not be loaded. Please check that you have the correct capture file.\n\n%s"),
error->message);
adw_message_dialog_add_response (ADW_MESSAGE_DIALOG (dialog), "close", _("Close"));
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (dialog));
gtk_window_present (GTK_WINDOW (dialog));
}
else
{
GtkWidget *window;
window = sysprof_window_new (app, document);
gtk_window_present (GTK_WINDOW (window));
}
}
void
sysprof_window_open (SysprofApplication *app,
GFile *file)
{
g_autoptr(SysprofDocumentLoader) loader = NULL;
g_return_if_fail (SYSPROF_IS_APPLICATION (app));
g_return_if_fail (G_IS_FILE (file));
if (!g_file_is_native (file))
{
g_autofree char *uri = g_file_get_uri (file);
g_warning ("Cannot open non-native file \"%s\"", uri);
return;
}
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (dialog));
}
void
sysprof_window_open_from_dialog (SysprofWindow *self)
{
GtkFileChooserNative *dialog;
GtkFileFilter *filter;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
/* Translators: This is a window title. */
dialog = gtk_file_chooser_native_new (_("Open Capture…"),
GTK_WINDOW (self),
GTK_FILE_CHOOSER_ACTION_OPEN,
/* Translators: This is a button. */
_("Open"),
/* Translators: This is a button. */
_("Cancel"));
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Sysprof Captures"));
gtk_file_filter_add_pattern (filter, "*.syscap");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("All Files"));
gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
g_signal_connect_object (dialog,
"response",
G_CALLBACK (sysprof_window_open_from_dialog_cb),
self,
G_CONNECT_SWAPPED);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
void
sysprof_window_new_tab (SysprofWindow *self)
{
GtkWidget *display;
gint page;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
display = sysprof_display_new ();
page = sysprof_notebook_append (self->notebook, SYSPROF_DISPLAY (display));
sysprof_notebook_set_current_page (self->notebook, page);
g_application_hold (G_APPLICATION (app));
loader = sysprof_document_loader_new (g_file_peek_path (file));
sysprof_document_loader_load_async (loader,
NULL,
sysprof_window_load_cb,
g_object_ref (app));
}

View File

@ -1,6 +1,6 @@
/* sysprof-window.h
*
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
* 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
@ -22,6 +22,9 @@
#include <adwaita.h>
#include <sysprof-analyze.h>
#include <sysprof-gtk.h>
#include "sysprof-application.h"
G_BEGIN_DECLS
@ -30,10 +33,11 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (SysprofWindow, sysprof_window, SYSPROF, WINDOW, AdwApplicationWindow)
GtkWidget *sysprof_window_new (SysprofApplication *application);
void sysprof_window_new_tab (SysprofWindow *self);
void sysprof_window_open (SysprofWindow *self,
GFile *file);
void sysprof_window_open_from_dialog (SysprofWindow *self);
GtkWidget *sysprof_window_new (SysprofApplication *app,
SysprofDocument *document);
void sysprof_window_open (SysprofApplication *app,
GFile *file);
SysprofDocument *sysprof_window_get_document (SysprofWindow *self);
SysprofSession *sysprof_window_get_session (SysprofWindow *self);
G_END_DECLS

View File

@ -1,59 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<requires lib="Adw" version="1.0"/>
<requires lib="Panel" version="1.0"/>
<template class="SysprofWindow" parent="AdwApplicationWindow">
<style>
<class name="org-gnome-Sysprof"/>
</style>
<property name="default-width">1200</property>
<property name="default-height">750</property>
<property name="default-width">700</property>
<property name="icon-name">org.gnome.Sysprof-symbolic</property>
<property name="title" translatable="yes">Sysprof</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar">
<property name="show-title-buttons">true</property>
<child type="end">
<object class="GtkMenuButton" id="menu_button">
<property name="tooltip-text" translatable="yes">Main Menu</property>
<property name="primary">true</property>
<property name="icon-name">open-menu-symbolic</property>
<style>
<class name="image-button"/>
</style>
<property name="content">
<object class="AdwOverlaySplitView">
<property name="show-sidebar" bind-source="show_left_sidebar" bind-property="active" bind-flags="bidirectional|sync-create"/>
<property name="sidebar">
<object class="AdwNavigationPage">
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-end-title-buttons">false</property>
<property name="title-widget">
<object class="AdwWindowTitle">
<property name="title">Sysprof</property>
</object>
</property>
<child type="end">
<object class="GtkMenuButton">
<property name="icon-name">open-menu-symbolic</property>
<property name="menu-model">primary_menu</property>
</object>
</child>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vexpand">true</property>
<child>
<object class="GtkListBox" id="list_box">
<style>
<class name="navigation-sidebar"/>
</style>
</object>
</child>
</object>
</property>
</object>
</child>
<child type="start">
<object class="GtkButton" id="open_button">
<property name="label" translatable="yes">_Open</property>
<property name="action-name">app.open-capture</property>
<property name="use-underline">true</property>
<property name="tooltip-text" translatable="yes">Open Recording… (Ctrl+O)</property>
</object>
</child>
<child type="end">
<object class="GtkLabel" id="stat_label">
<property name="margin-end">12</property>
<property name="xalign">1</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</property>
</object>
</child>
<child>
<object class="SysprofNotebook" id="notebook">
<property name="vexpand">true</property>
<child>
<object class="SysprofDisplay">
<property name="visible">true</property>
</property>
<property name="content">
<object class="AdwNavigationPage">
<property name="child">
<object class="AdwOverlaySplitView">
<property name="sidebar-position">end</property>
<property name="show-sidebar" bind-source="show_right_sidebar" bind-property="active" bind-flags="bidirectional|sync-create"/>
<property name="content">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="title-widget">
<object class="AdwWindowTitle">
<binding name="title">
<lookup name="title" type="SysprofDocument">
<lookup name="document">SysprofWindow</lookup>
</lookup>
</binding>
</object>
</property>
<child type="start">
<object class="GtkToggleButton" id="show_left_sidebar">
<property name="icon-name">dock-left-symbolic</property>
<property name="active">true</property>
</object>
</child>
<child type="end">
<object class="GtkToggleButton" id="show_right_sidebar">
<property name="icon-name">dock-right-symbolic</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton">
<property name="icon-name">document-properties-symbolic</property>
</object>
</child>
</object>
</child>
<property name="content">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="vexpand">true</property>
</object>
</property>
</object>
</property>
<property name="sidebar">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="title-widget">
<object class="AdwWindowTitle">
</object>
</property>
</object>
</child>
</object>
</property>
</object>
</child>
</property>
</object>
</child>
</property>
</object>
</child>
</property>
</template>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">Open Recording…</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Save As…</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Record Again…</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Show Embedded Files…</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Show Embedded Metadata…</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Preferences</attribute>
<attribute name="action-name">app.preferences</attribute>
<attribute name="accel">&lt;ctrl&gt;comma</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Help</attribute>
<attribute name="accel">F1</attribute>
<attribute name="action">app.help</attribute>
</item>
<item>
<attribute name="label" translatable="yes">About Sysprof</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -1,15 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<gresources>
<gresource prefix="/org/gnome/sysprof">
<!-- Automatic GTK resources -->
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
<!-- Theme overrides -->
<file compressed="true">theme/shared.css</file>
</gresource>
<gresource prefix="/org/gnome/sysprof/ui">
<gresource prefix="/org/gnome/sysprof">
<file preprocess="xml-stripblanks">sysprof-window.ui</file>
</gresource>
</gresources>

View File

@ -1,12 +0,0 @@
visualizers list {
background: @theme_bg_color;
}
visualizers list row:backdrop,
visualizers list row:last-child {
border-bottom: none;
}
ticks {
color: alpha(@theme_fg_color, 0.4);
}