Land Sysprof 2.x

This is a major redesign a modernization of Sysprof. The core data
structures and design are largely the same, but it has been ported to
Gtk3 and has lots of additions that should make your profiling experience
smoother. Especially for those that are new to profiling.

There are some very simple help docs added, but we really need the
experts to come in and write some documentation here.
This commit is contained in:
Christian Hergert
2016-04-13 05:24:03 -07:00
parent 34db28db32
commit 29c4ec495f
231 changed files with 35471 additions and 24788 deletions

38
src/Makefile.am Normal file
View File

@ -0,0 +1,38 @@
bin_PROGRAMS = sysprof
sysprof_CFLAGS = \
$(SYSPROF_CFLAGS) \
-I$(top_srcdir)/lib \
-I$(top_builddir)/lib
sysprof_SOURCES = \
sysprof.c \
sp-application.c \
sp-application.h \
sp-credits.h \
sp-window.c \
sp-window.h \
sp-window-settings.c \
sp-window-settings.h \
$(NULL)
nodist_sysprof_SOURCES = \
sp-resources.c \
sp-resources.h
sysprof_LDADD = \
$(SYSPROF_LIBS) \
$(top_builddir)/lib/libsysprof-@API_VERSION@.la
EXTRA_DIST =
CLEANFILES =
DISTCLEANFILES =
BUILT_SOURCES =
glib_resources_xml = resources/sysprof.gresource.xml
glib_resources_c = sp-resources.c
glib_resources_h = sp-resources.h
glib_resources_namespace = sysprof
include $(top_srcdir)/gresources.mk
-include $(top_srcdir)/git.mk

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<interface>
<menu id="app-menu">
<section id="app-menu-new-section">
<item>
<attribute name="label" translatable="yes">_New Window</attribute>
<attribute name="action">app.new-window</attribute>
</item>
</section>
<section id="app-menu-open-section">
<item>
<attribute name="label" translatable="yes">_Open Capture</attribute>
<attribute name="action">app.open-capture</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">About</attribute>
<attribute name="action">app.about</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Help</attribute>
<attribute name="action">app.help</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
<menu id="gear-menu">
<section id="gear-menu-open-section">
<item>
<attribute name="label" translatable="yes">Open</attribute>
<attribute name="action">win.open-capture</attribute>
</item>
</section>
<section id="gear-menu-save-section">
<item>
<attribute name="label" translatable="yes">Save As</attribute>
<attribute name="action">win.save-capture</attribute>
</item>
</section>
<section id="gear-menu-close-section">
<item>
<attribute name="label" translatable="yes">Close</attribute>
<attribute name="action">win.close-capture</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<gresources>
<gresource prefix="/org/gnome/sysprof">
<!-- Automatic GTK resources -->
<file>gtk/menus.ui</file>
<!-- Application icons -->
<file alias="icons/16x16/apps/sysprof.png">../../data/icons/16x16/apps/sysprof.png</file>
<file alias="icons/24x24/apps/sysprof.png">../../data/icons/24x24/apps/sysprof.png</file>
<file alias="icons/32x32/apps/sysprof.png">../../data/icons/32x32/apps/sysprof.png</file>
<file alias="icons/48x48/apps/sysprof.png">../../data/icons/48x48/apps/sysprof.png</file>
<file alias="icons/256x256/apps/sysprof.png">../../data/icons/256x256/apps/sysprof.png</file>
<file alias="icons/scalable/apps/sysprof-symbolic.svg">../../data/icons/scalable/apps/sysprof-symbolic.svg</file>
<!-- Theme overrides -->
<file compressed="true">theme/shared.css</file>
<!-- UI Files -->
<file compressed="true">ui/sp-window.ui</file>
</gresource>
</gresources>

View File

@ -0,0 +1,12 @@
popover list row {
padding: 6px 10px 6px 10px;
border-bottom: 1px solid alpha(@borders, 0.2);
}
popover list row:last-child {
border-bottom: none;
}
popover scrolledwindow {
border-top: 1px solid alpha(@borders, 0.75);
}

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<interface>
<template class="SpWindow" parent="GtkApplicationWindow">
<property name="default-height">700</property>
<property name="default-width">1200</property>
<property name="icon-name">sysprof</property>
<property name="show-menubar">false</property>
<property name="title" translatable="yes">Sysprof</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="show-close-button">true</property>
<property name="visible">true</property>
<child type="title">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="visible">true</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">true</property>
<property name="label" translatable="yes">Sysprof</property>
<attributes>
<attribute name="weight" value="bold"/>
<attribute name="scale" value="0.8"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel" id="subtitle">
<property name="visible">true</property>
<property name="label" translatable="yes">Not running</property>
<property name="ellipsize">start</property>
<style>
<class name="dim-label"/>
</style>
<attributes>
<attribute name="scale" value="0.8"/>
</attributes>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="record_button">
<property name="label" translatable="yes">_Record</property>
<property name="use-underline">true</property>
<property name="visible">true</property>
<property name="width-request">100</property>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
<child>
<object class="SpProfilerMenuButton" id="profiler_menu_button">
<property name="width-request">200</property>
<property name="visible">true</property>
</object>
</child>
<child>
<object class="GtkLabel" id="stat_label">
<property name="margin-end">12</property>
<property name="xalign">1</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="pack-type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkMenuButton" id="gear_menu_button">
<property name="visible">true</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="icon-name">open-menu-symbolic</property>
<property name="visible">true</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="visible">true</property>
<child>
<object class="GtkRevealer" id="info_bar_revealer">
<property name="visible">true</property>
<property name="reveal-child">false</property>
<child>
<object class="GtkInfoBar" id="info_bar">
<property name="visible">true</property>
<child internal-child="content_area">
<object class="GtkBox">
<child>
<object class="GtkLabel" id="info_bar_label">
<property name="hexpand">true</property>
<property name="label">Failure</property>
<property name="visible">true</property>
<property name="wrap">true</property>
<property name="xalign">0</property>
</object>
</child>
<child>
<object class="GtkButton" id="close_info_button">
<property name="label" translatable="yes">_Close</property>
<property name="use-underline">true</property>
<property name="visible">true</property>
<property name="width-request">100</property>
</object>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">close_info_button</action-widget>
</action-widgets>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="view_stack">
<property name="expand">true</property>
<property name="transition-duration">400</property>
<property name="transition-type">crossfade</property>
<property name="visible">true</property>
<child>
<object class="SpEmptyStateView" id="empty_view">
<property name="visible">true</property>
</object>
<packing>
<property name="name">empty</property>
</packing>
</child>
<child>
<object class="SpFailedStateView" id="failed_view">
<property name="visible">true</property>
</object>
<packing>
<property name="name">failed</property>
</packing>
</child>
<child>
<object class="SpRecordingStateView" id="recording_view">
<property name="visible">true</property>
</object>
<packing>
<property name="name">recording</property>
</packing>
</child>
<child>
<object class="SpCallgraphView" id="callgraph_view">
<property name="visible">true</property>
</object>
<packing>
<property name="name">browsing</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

271
src/sp-application.c Normal file
View File

@ -0,0 +1,271 @@
/* sp-application.c
*
* Copyright (C) 2016 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/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib/gi18n.h>
#include "sp-application.h"
#include "sp-credits.h"
#include "sp-window.h"
struct _SpApplication
{
GtkApplication parent_instance;
};
G_DEFINE_TYPE (SpApplication, sp_application, GTK_TYPE_APPLICATION)
static void
sp_application_activate (GApplication *app)
{
SpWindow *window;
GList *windows;
g_assert (GTK_IS_APPLICATION (app));
windows = gtk_application_get_windows (GTK_APPLICATION (app));
for (; windows != NULL; windows = windows->next)
{
if (SP_IS_WINDOW (windows->data))
{
gtk_window_present (windows->data);
return;
}
}
window = g_object_new (SP_TYPE_WINDOW,
"application", app,
NULL);
gtk_window_present (GTK_WINDOW (window));
}
static void
sp_application_open (GApplication *app,
GFile **files,
gint n_files,
const gchar *hint)
{
guint opened = 0;
gint i;
g_assert (SP_IS_APPLICATION (app));
g_assert (files != NULL || n_files == 0);
for (i = 0; i < n_files; i++)
{
SpWindow *window;
window = g_object_new (SP_TYPE_WINDOW,
"application", app,
NULL);
sp_window_open (window, files [i]);
gtk_window_present (GTK_WINDOW (window));
opened++;
}
if (opened == 0)
sp_application_activate (app);
}
static void
sp_application_startup (GApplication *application)
{
GtkCssProvider *provider;
g_assert (SP_IS_APPLICATION (application));
G_APPLICATION_CLASS (sp_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_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_clear_object (&provider);
}
static void
sp_application_class_init (SpApplicationClass *klass)
{
GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
app_class->open = sp_application_open;
app_class->startup = sp_application_startup;
app_class->activate = sp_application_activate;
}
static void
sysprof_quit (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
GApplication *app = user_data;
g_assert (G_IS_APPLICATION (app));
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
g_application_quit (app);
}
static void
sysprof_about (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
GtkApplication *app = user_data;
GtkWindow *best_toplevel = NULL;
GtkWindow *dialog;
GList *windows;
g_assert (G_IS_APPLICATION (app));
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
windows = gtk_application_get_windows (app);
for (; windows != NULL; windows = windows->next)
{
if (SP_IS_WINDOW (windows->data))
{
best_toplevel = windows->data;
break;
}
}
dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG,
"application", app,
"authors", sysprof_authors,
"artists", sysprof_artists,
"comments", _("A system profiler"),
"copyright", "Copyright © 2004-2009 Søren Sandmann Pedersen\n"
"Copyright © 2016 Christian Hergert",
"transient-for", best_toplevel,
"translator-credits", _("translator-credits"),
"license-type", GTK_LICENSE_GPL_3_0,
"logo-icon-name", "sysprof",
"program-name", _("Sysprof"),
"version", PACKAGE_VERSION,
"website", "https://wiki.gnome.org/Apps/Sysprof",
"website-label", _("Learn more about Sysprof"),
NULL);
gtk_window_present (dialog);
}
static void
sysprof_help (GSimpleAction *action,
GVariant *param,
gpointer user_data)
{
gtk_show_uri (gdk_screen_get_default (),
"help:sysprof",
gtk_get_current_event_time (),
NULL);
}
static void
sysprof_new_window (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
SpApplication *self = user_data;
SpWindow *window;
g_assert (SP_IS_APPLICATION (self));
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
window = g_object_new (SP_TYPE_WINDOW,
"application", self,
NULL);
gtk_window_present (GTK_WINDOW (window));
}
static void
sysprof_open_capture (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
GtkApplication *app = user_data;
GtkWidget *window;
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)
{
window = list->data;
if (SP_IS_WINDOW (window))
{
SpWindowState state;
state = sp_window_get_state (SP_WINDOW (window));
if (state == SP_WINDOW_STATE_EMPTY)
{
sp_window_open_from_dialog (SP_WINDOW (window));
return;
}
}
}
window = g_object_new (SP_TYPE_WINDOW,
"application", app,
NULL);
gtk_window_present (GTK_WINDOW (window));
sp_window_open_from_dialog (SP_WINDOW (window));
}
static void
sp_application_init (SpApplication *self)
{
static const GActionEntry actions[] = {
{ "about", sysprof_about },
{ "new-window", sysprof_new_window },
{ "open-capture", sysprof_open_capture },
{ "help", sysprof_help },
{ "quit", sysprof_quit },
};
g_action_map_add_action_entries (G_ACTION_MAP (self), actions, G_N_ELEMENTS (actions), self);
g_application_set_default (G_APPLICATION (self));
}
SpApplication *
sp_application_new (void)
{
return g_object_new (SP_TYPE_APPLICATION,
"application-id", "org.gnome.Sysprof2",
"resource-base-path", "/org/gnome/sysprof",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}

34
src/sp-application.h Normal file
View File

@ -0,0 +1,34 @@
/* sp-application.h
*
* Copyright (C) 2016 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/>.
*/
#ifndef SP_APPLICATION_H
#define SP_APPLICATION_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define SP_TYPE_APPLICATION (sp_application_get_type())
G_DECLARE_FINAL_TYPE (SpApplication, sp_application, SP, APPLICATION, GtkApplication)
SpApplication *sp_application_new (void);
G_END_DECLS
#endif /* SP_APPLICATION_H */

38
src/sp-credits.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef SP_CREDITS_H
#define SP_CREDITS_H
#include <glib.h>
G_BEGIN_DECLS
static gchar *sysprof_authors[] = {
"Bastien Nocera",
"Behdad Esfahbod",
"Christian Hergert",
"Damien Lespiau",
"Geoffrey Keating",
"Javier Jardón",
"Jeffrey Stedfast",
"Kristian Høgsberg",
"Kristian Rietvel",
"M Joonas Pihlaja",
"Matthias Clasen",
"Michel Dänzer",
"Nix",
"Owen Taylor",
"Paolo Borelli",
"Pascal Terjan",
"Pauli Nieminen",
"Robert Love",
"Søren Sandmann Pedersen",
NULL
};
static gchar *sysprof_artists[] = {
"Jakub Steiner",
NULL
};
G_END_DECLS
#endif /* SP_CREDITS_H */

175
src/sp-window-settings.c Normal file
View File

@ -0,0 +1,175 @@
/* sp-window-settings.c
*
* Copyright (C) 2016 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/>.
*/
#include "sp-window.h"
#include "sp-window-settings.h"
#define WINDOW_MIN_WIDTH 1200
#define WINDOW_MIN_HEIGHT 700
#define SAVE_TIMEOUT_SECS 1
static GSettings *settings;
static gboolean
sp_window_settings__window_save_settings_cb (gpointer data)
{
GtkWindow *window = data;
GdkRectangle geom;
gboolean maximized;
g_assert (GTK_IS_WINDOW (window));
g_assert (G_IS_SETTINGS (settings));
g_object_set_data (G_OBJECT (window), "SETTINGS_HANDLER_ID", NULL);
gtk_window_get_size (window, &geom.width, &geom.height);
gtk_window_get_position (window, &geom.x, &geom.y);
maximized = gtk_window_is_maximized (window);
g_settings_set (settings, "window-size", "(ii)", geom.width, geom.height);
g_settings_set (settings, "window-position", "(ii)", geom.x, geom.y);
g_settings_set_boolean (settings, "window-maximized", maximized);
return G_SOURCE_REMOVE;
}
static gboolean
sp_window_settings__window_configure_event (GtkWindow *window,
GdkEventConfigure *event)
{
guint handler;
g_assert (GTK_IS_WINDOW (window));
g_assert (event != NULL);
g_assert (G_IS_SETTINGS (settings));
handler = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "SETTINGS_HANDLER_ID"));
if (handler == 0)
{
handler = g_timeout_add_seconds (SAVE_TIMEOUT_SECS,
sp_window_settings__window_save_settings_cb,
window);
g_object_set_data (G_OBJECT (window), "SETTINGS_HANDLER_ID", GINT_TO_POINTER (handler));
}
return GDK_EVENT_PROPAGATE;
}
static void
sp_window_settings__window_realize (GtkWindow *window)
{
GtkApplication *app;
GdkRectangle geom = { 0 };
gboolean maximized = FALSE;
GList *list;
guint count = 0;
g_assert (GTK_IS_WINDOW (window));
g_assert (G_IS_SETTINGS (settings));
g_settings_get (settings, "window-position", "(ii)", &geom.x, &geom.y);
g_settings_get (settings, "window-size", "(ii)", &geom.width, &geom.height);
g_settings_get (settings, "window-maximized", "b", &maximized);
geom.width = MAX (geom.width, WINDOW_MIN_WIDTH);
geom.height = MAX (geom.height, WINDOW_MIN_HEIGHT);
gtk_window_set_default_size (window, geom.width, geom.height);
/*
* If there are other windows currently visible other than this one,
* then ignore positioning and let the window manager decide.
*/
count = 0;
app = GTK_APPLICATION (g_application_get_default ());
list = gtk_application_get_windows (app);
for (; list != NULL; list = list->next)
{
GtkWindow *ele = list->data;
if (SP_IS_WINDOW (ele) && (ele != window) &&
gtk_widget_get_visible (GTK_WIDGET (window)))
count++;
}
if (count == 0)
gtk_window_move (window, geom.x, geom.y);
if (maximized)
gtk_window_maximize (window);
}
static void
sp_window_settings__window_destroy (GtkWindow *window)
{
guint handler;
g_assert (GTK_IS_WINDOW (window));
g_assert (G_IS_SETTINGS (settings));
handler = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window), "SETTINGS_HANDLER_ID"));
if (handler != 0)
{
g_source_remove (handler);
g_object_set_data (G_OBJECT (window), "SETTINGS_HANDLER_ID", NULL);
}
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (sp_window_settings__window_configure_event),
NULL);
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (sp_window_settings__window_destroy),
NULL);
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (sp_window_settings__window_realize),
NULL);
g_object_unref (settings);
}
void
sp_window_settings_register (GtkWindow *window)
{
if (settings == NULL)
{
settings = g_settings_new ("org.gnome.sysprof2");
g_object_add_weak_pointer (G_OBJECT (settings), (gpointer *)&settings);
}
else
{
g_object_ref (settings);
}
g_signal_connect (window,
"configure-event",
G_CALLBACK (sp_window_settings__window_configure_event),
NULL);
g_signal_connect (window,
"destroy",
G_CALLBACK (sp_window_settings__window_destroy),
NULL);
g_signal_connect (window,
"realize",
G_CALLBACK (sp_window_settings__window_realize),
NULL);
}

30
src/sp-window-settings.h Normal file
View File

@ -0,0 +1,30 @@
/* sp-window-settings.h
*
* Copyright (C) 2016 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/>.
*/
#ifndef SP_WINDOW_SETTINGS_H
#define SP_WINDOW_SETTINGS_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
void sp_window_settings_register (GtkWindow *window);
G_END_DECLS
#endif /* SP_WINDOW_SETTINGS_H */

853
src/sp-window.c Normal file
View File

@ -0,0 +1,853 @@
/* sp-window.c
*
* Copyright (C) 2016 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/>.
*/
#include <errno.h>
#include <glib/gi18n.h>
#include <sysprof.h>
#include "sp-application.h"
#include "sp-window.h"
#include "sp-window-settings.h"
struct _SpWindow
{
GtkApplicationWindow parent_instance;
SpWindowState state;
SpProfiler *profiler;
SpCaptureReader *reader;
/* Gtk widget template children */
SpCallgraphView *callgraph_view;
SpEmptyStateView *empty_view;
GtkMenuButton *gear_menu_button;
GtkInfoBar *info_bar;
GtkLabel *info_bar_label;
GtkRevealer *info_bar_revealer;
SpProfilerMenuButton *profiler_menu_button;
SpRecordingStateView *recording_view;
GtkButton *record_button;
GtkLabel *subtitle;
GtkLabel *stat_label;
GtkLabel *title;
GtkStack *view_stack;
guint stats_handler;
};
G_DEFINE_TYPE (SpWindow, sp_window, GTK_TYPE_APPLICATION_WINDOW)
static void sp_window_set_state (SpWindow *self,
SpWindowState state);
enum {
START_RECORDING,
STOP_RECORDING,
N_SIGNALS
};
static guint signals [N_SIGNALS];
static void sp_window_set_profiler (SpWindow *self,
SpProfiler *profiler);
static void
sp_window_notify_user (SpWindow *self,
GtkMessageType message_type,
const gchar *format,
...)
{
g_autofree gchar *str = NULL;
va_list args;
g_assert (SP_IS_WINDOW (self));
g_assert (format != NULL);
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
gtk_info_bar_set_message_type (self->info_bar, message_type);
gtk_label_set_label (self->info_bar_label, str);
gtk_revealer_set_reveal_child (self->info_bar_revealer, TRUE);
}
static void
sp_window_action_set (SpWindow *self,
const gchar *action_name,
const gchar *first_property,
...)
{
gpointer action;
va_list args;
g_assert (SP_IS_WINDOW (self));
g_assert (action_name != NULL);
action = g_action_map_lookup_action (G_ACTION_MAP (self), action_name);
if (action == NULL)
{
g_warning ("Failed to locate action \"%s\"", action_name);
return;
}
va_start (args, first_property);
g_object_set_valist (action, first_property, args);
va_end (args);
}
static gboolean
sp_window_update_stats (gpointer data)
{
SpWindow *self = data;
g_assert (SP_IS_WINDOW (self));
if (self->profiler != NULL)
{
SpCaptureWriter *writer;
if (NULL != (writer = sp_profiler_get_writer (self->profiler)))
{
g_autofree gchar *str = NULL;
SpCaptureStat stbuf;
guint count;
sp_capture_writer_stat (writer, &stbuf);
count = stbuf.frame_count[SP_CAPTURE_FRAME_SAMPLE];
str = g_strdup_printf (_("Samples: %u"), count);
gtk_label_set_label (self->stat_label, str);
}
}
return G_SOURCE_CONTINUE;
}
static void
sp_window_update_subtitle (SpWindow *self)
{
g_autofree gchar *relative = NULL;
const gchar *filename;
const gchar *date;
GTimeVal tv;
g_assert (SP_IS_WINDOW (self));
g_assert (self->reader != NULL);
if (NULL != (filename = sp_capture_reader_get_filename (self->reader)))
{
g_autoptr(GFile) home = NULL;
g_autoptr(GFile) file = NULL;
file = g_file_new_for_path (filename);
home = g_file_new_for_path (g_get_home_dir ());
if (g_file_has_prefix (file, home))
filename = relative = g_file_get_relative_path (home, file);
}
if (filename == NULL)
filename = _("[Memory Capture]");
date = sp_capture_reader_get_time (self->reader);
if (g_time_val_from_iso8601 (date, &tv))
{
g_autoptr(GDateTime) dt = NULL;
g_autofree gchar *str = NULL;
g_autofree gchar *label = NULL;
dt = g_date_time_new_from_timeval_local (&tv);
str = g_date_time_format (dt, "%x %X");
label = g_strdup_printf (_("%s - %s"), filename, str);
gtk_label_set_label (self->subtitle, label);
}
else
gtk_label_set_label (self->subtitle, filename);
}
static void
sp_window_build_profile_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
SpProfile *profile = (SpProfile *)object;
g_autoptr(SpWindow) self = user_data;
g_autoptr(GError) error = NULL;
g_assert (SP_IS_CALLGRAPH_PROFILE (profile));
g_assert (SP_IS_WINDOW (self));
g_assert (G_IS_ASYNC_RESULT (result));
if (!sp_profile_generate_finish (profile, result, &error))
{
sp_window_notify_user (self, GTK_MESSAGE_ERROR, "%s", error->message);
sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
return;
}
sp_callgraph_view_set_profile (self->callgraph_view, SP_CALLGRAPH_PROFILE (profile));
sp_window_set_state (self, SP_WINDOW_STATE_BROWSING);
}
static void
sp_window_build_profile (SpWindow *self)
{
g_autoptr(SpProfile) profile = NULL;
g_assert (SP_IS_WINDOW (self));
g_assert (self->reader != NULL);
profile = sp_callgraph_profile_new ();
sp_profile_set_reader (profile, self->reader);
sp_profile_generate (profile,
NULL,
sp_window_build_profile_cb,
g_object_ref (self));
}
static void
add_class (gpointer widget,
const gchar *name)
{
g_assert (GTK_IS_WIDGET (widget));
gtk_style_context_add_class (gtk_widget_get_style_context (widget), name);
}
static void
remove_class (gpointer widget,
const gchar *name)
{
g_assert (GTK_IS_WIDGET (widget));
gtk_style_context_remove_class (gtk_widget_get_style_context (widget), name);
}
static void
sp_window_set_state (SpWindow *self,
SpWindowState state)
{
g_autoptr(SpProfiler) profiler = NULL;
g_assert (SP_IS_WINDOW (self));
if (self->state == state)
return;
self->state = state;
switch (state)
{
case SP_WINDOW_STATE_EMPTY:
case SP_WINDOW_STATE_FAILED:
profiler = sp_profiler_new ();
gtk_button_set_label (self->record_button, _("Record"));
gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), TRUE);
add_class (self->record_button, "suggsted-action");
remove_class (self->record_button, "destructive-action");
if (state == SP_WINDOW_STATE_FAILED)
gtk_stack_set_visible_child_name (self->view_stack, "failed");
else
gtk_stack_set_visible_child_name (self->view_stack, "empty");
gtk_label_set_label (self->subtitle, _("Not running"));
sp_callgraph_view_set_profile (self->callgraph_view, NULL);
gtk_widget_set_visible (GTK_WIDGET (self->stat_label), FALSE);
g_clear_pointer (&self->reader, sp_capture_reader_unref);
sp_window_set_profiler (self, profiler);
sp_window_action_set (self, "close-capture", "enabled", FALSE, NULL);
sp_window_action_set (self, "save-capture", "enabled", FALSE, NULL);
break;
case SP_WINDOW_STATE_RECORDING:
gtk_button_set_label (self->record_button, _("Stop"));
gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), TRUE);
remove_class (self->record_button, "suggsted-action");
add_class (self->record_button, "destructive-action");
gtk_stack_set_visible_child_name (self->view_stack, "recording");
gtk_label_set_label (self->subtitle, _("Recording…"));
gtk_widget_set_visible (GTK_WIDGET (self->stat_label), TRUE);
g_clear_pointer (&self->reader, sp_capture_reader_unref);
sp_callgraph_view_set_profile (self->callgraph_view, NULL);
sp_window_action_set (self, "close-capture", "enabled", FALSE, NULL);
sp_window_action_set (self, "save-capture", "enabled", FALSE, NULL);
break;
case SP_WINDOW_STATE_PROCESSING:
gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), FALSE);
gtk_label_set_label (self->subtitle, _("Building profile…"));
sp_window_action_set (self, "close-capture", "enabled", FALSE, NULL);
sp_window_action_set (self, "save-capture", "enabled", FALSE, NULL);
sp_window_build_profile (self);
break;
case SP_WINDOW_STATE_BROWSING:
gtk_button_set_label (self->record_button, _("Record"));
gtk_widget_set_sensitive (GTK_WIDGET (self->record_button), TRUE);
add_class (self->record_button, "suggsted-action");
remove_class (self->record_button, "destructive-action");
gtk_widget_set_visible (GTK_WIDGET (self->stat_label), TRUE);
gtk_stack_set_visible_child_name (self->view_stack, "browsing");
sp_window_update_stats (self);
sp_window_update_subtitle (self);
sp_window_action_set (self, "close-capture", "enabled", TRUE, NULL);
sp_window_action_set (self, "save-capture", "enabled", TRUE, NULL);
break;
default:
g_warning ("Unknown state: %0d", state);
break;
}
}
static void
sp_window_enable_stats (SpWindow *self)
{
g_assert (SP_IS_WINDOW (self));
if (self->stats_handler == 0)
self->stats_handler =
g_timeout_add_seconds (1, sp_window_update_stats, self);
}
static void
sp_window_disable_stats (SpWindow *self)
{
g_assert (SP_IS_WINDOW (self));
if (self->stats_handler != 0)
{
g_source_remove (self->stats_handler);
self->stats_handler = 0;
}
}
static void
sp_window_add_sources (SpWindow *window,
SpProfiler *profiler)
{
g_autoptr(SpSource) proc_source = NULL;
g_autoptr(SpSource) perf_source = NULL;
g_assert (SP_IS_WINDOW (window));
g_assert (SP_IS_PROFILER (profiler));
proc_source = sp_proc_source_new ();
sp_profiler_add_source (profiler, proc_source);
perf_source = sp_perf_source_new ();
sp_profiler_add_source (profiler, perf_source);
}
static void
sp_window_start_recording (SpWindow *self)
{
g_assert (SP_IS_WINDOW (self));
if (self->state == SP_WINDOW_STATE_RECORDING)
{
/* SpProfiler::stopped will move us to generating */
gtk_label_set_label (self->subtitle, _("Stopping…"));
sp_profiler_stop (self->profiler);
return;
}
if ((self->state == SP_WINDOW_STATE_EMPTY) ||
(self->state == SP_WINDOW_STATE_FAILED) ||
(self->state == SP_WINDOW_STATE_BROWSING))
{
sp_window_add_sources (self, self->profiler);
sp_window_set_state (self, SP_WINDOW_STATE_RECORDING);
sp_window_enable_stats (self);
sp_profiler_start (self->profiler);
return;
}
}
static void
sp_window_stop_recording (SpWindow *self)
{
g_assert (SP_IS_WINDOW (self));
if (self->state == SP_WINDOW_STATE_RECORDING)
{
if (self->profiler != NULL)
sp_profiler_stop (self->profiler);
}
}
static void
sp_window_hide_info_bar_revealer (SpWindow *self)
{
g_assert (SP_IS_WINDOW (self));
gtk_revealer_set_reveal_child (self->info_bar_revealer, FALSE);
}
static void
sp_window_profiler_stopped (SpWindow *self,
SpProfiler *profiler)
{
g_autoptr(SpCaptureReader) reader = NULL;
g_autoptr(GError) error = NULL;
SpCaptureWriter *writer;
g_assert (SP_IS_WINDOW (self));
g_assert (SP_IS_PROFILER (profiler));
sp_window_disable_stats (self);
if (self->state == SP_WINDOW_STATE_FAILED)
return;
writer = sp_profiler_get_writer (profiler);
reader = sp_capture_writer_create_reader (writer, &error);
if (reader == NULL)
{
sp_window_notify_user (self, GTK_MESSAGE_ERROR, "%s", error->message);
sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
return;
}
g_clear_pointer (&self->reader, sp_capture_reader_unref);
self->reader = g_steal_pointer (&reader);
sp_window_build_profile (self);
}
static void
sp_window_profiler_failed (SpWindow *self,
const GError *reason,
SpProfiler *profiler)
{
g_assert (SP_IS_WINDOW (self));
g_assert (reason != NULL);
g_assert (SP_IS_PROFILER (profiler));
sp_window_notify_user (self, GTK_MESSAGE_ERROR, "%s", reason->message);
sp_window_set_state (self, SP_WINDOW_STATE_FAILED);
}
static void
sp_window_set_profiler (SpWindow *self,
SpProfiler *profiler)
{
g_assert (SP_IS_WINDOW (self));
g_assert (SP_IS_PROFILER (profiler));
if (self->profiler != profiler)
{
if (self->profiler != NULL)
{
if (sp_profiler_get_is_running (self->profiler))
sp_profiler_stop (self->profiler);
sp_profiler_menu_button_set_profiler (self->profiler_menu_button, NULL);
sp_recording_state_view_set_profiler (self->recording_view, NULL);
g_clear_object (&self->profiler);
}
if (profiler != NULL)
{
if (!sp_profiler_get_is_mutable (profiler))
{
g_warning ("Ignoring attempt to set profiler to an already running session!");
return;
}
self->profiler = g_object_ref (profiler);
g_signal_connect_object (profiler,
"stopped",
G_CALLBACK (sp_window_profiler_stopped),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (profiler,
"failed",
G_CALLBACK (sp_window_profiler_failed),
self,
G_CONNECT_SWAPPED);
sp_profiler_menu_button_set_profiler (self->profiler_menu_button, profiler);
sp_recording_state_view_set_profiler (self->recording_view, profiler);
}
}
}
static void
sp_window_open_capture (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
SpWindow *self = user_data;
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
g_assert (SP_IS_WINDOW (self));
sp_window_open_from_dialog (self);
}
static void
sp_window_save_capture (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
g_autoptr(SpCaptureReader) reader = NULL;
SpWindow *self = user_data;
GtkWidget *dialog;
GtkResponseType response;
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
g_assert (SP_IS_WINDOW (self));
if (self->reader == NULL)
return;
reader = sp_capture_reader_ref (self->reader);
dialog = gtk_file_chooser_dialog_new (_("Save Capture As"),
GTK_WINDOW (self),
GTK_FILE_CHOOSER_ACTION_SAVE,
_("Cancel"), GTK_RESPONSE_CANCEL,
_("Save"), GTK_RESPONSE_OK,
NULL);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if (response == GTK_RESPONSE_OK)
{
g_autofree gchar *filename = NULL;
g_autoptr(GError) error = NULL;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
/* this should really be done outside the main loop. */
if (!sp_capture_reader_save_as (reader, filename, &error))
{
sp_window_notify_user (self,
GTK_MESSAGE_ERROR,
_("An error occurred while attempting to save your capture: %s"),
error->message);
goto failure;
}
}
failure:
gtk_widget_destroy (dialog);
}
static void
sp_window_close_capture (GSimpleAction *action,
GVariant *variant,
gpointer user_data)
{
SpWindow *self = user_data;
g_assert (G_IS_SIMPLE_ACTION (action));
g_assert (variant == NULL);
g_assert (SP_IS_WINDOW (self));
sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
}
static void
sp_window_record_button_clicked (SpWindow *self,
GtkButton *button)
{
g_assert (SP_IS_WINDOW (self));
g_assert (GTK_IS_BUTTON (button));
sp_window_start_recording (self);
}
static void
sp_window_destroy (GtkWidget *widget)
{
SpWindow *self = (SpWindow *)widget;
g_clear_object (&self->profiler);
g_clear_pointer (&self->reader, sp_capture_reader_unref);
sp_window_disable_stats (self);
GTK_WIDGET_CLASS (sp_window_parent_class)->destroy (widget);
}
static void
sp_window_constructed (GObject *object)
{
SpWindow *self = (SpWindow *)object;
g_autoptr(SpProfiler) profiler = NULL;
G_OBJECT_CLASS (sp_window_parent_class)->constructed (object);
profiler = sp_profiler_new ();
sp_window_set_profiler (self, profiler);
sp_window_set_state (self, SP_WINDOW_STATE_EMPTY);
}
static void
sp_window_class_init (SpWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkBindingSet *binding_set;
object_class->constructed = sp_window_constructed;
widget_class->destroy = sp_window_destroy;
signals [START_RECORDING] =
g_signal_new_class_handler ("start-recording",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_CALLBACK (sp_window_start_recording),
NULL, NULL, NULL, G_TYPE_NONE, 0);
signals [STOP_RECORDING] =
g_signal_new_class_handler ("stop-recording",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_CALLBACK (sp_window_stop_recording),
NULL, NULL, NULL, G_TYPE_NONE, 0);
binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "stop-recording", 0);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sp-window.ui");
gtk_widget_class_bind_template_child (widget_class, SpWindow, callgraph_view);
gtk_widget_class_bind_template_child (widget_class, SpWindow, empty_view);
gtk_widget_class_bind_template_child (widget_class, SpWindow, gear_menu_button);
gtk_widget_class_bind_template_child (widget_class, SpWindow, info_bar);
gtk_widget_class_bind_template_child (widget_class, SpWindow, info_bar_label);
gtk_widget_class_bind_template_child (widget_class, SpWindow, info_bar_revealer);
gtk_widget_class_bind_template_child (widget_class, SpWindow, profiler_menu_button);
gtk_widget_class_bind_template_child (widget_class, SpWindow, record_button);
gtk_widget_class_bind_template_child (widget_class, SpWindow, recording_view);
gtk_widget_class_bind_template_child (widget_class, SpWindow, stat_label);
gtk_widget_class_bind_template_child (widget_class, SpWindow, subtitle);
gtk_widget_class_bind_template_child (widget_class, SpWindow, title);
gtk_widget_class_bind_template_child (widget_class, SpWindow, view_stack);
}
static void
sp_window_init (SpWindow *self)
{
GAction *action;
static GActionEntry action_entries[] = {
{ "close-capture", sp_window_close_capture },
{ "open-capture", sp_window_open_capture },
{ "save-capture", sp_window_save_capture },
};
GtkApplication *app;
GMenu *menu;
gtk_widget_init_template (GTK_WIDGET (self));
/*
* Hookup widget signals.
*/
g_signal_connect_object (self->info_bar,
"response",
G_CALLBACK (sp_window_hide_info_bar_revealer),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->info_bar,
"close",
G_CALLBACK (sp_window_hide_info_bar_revealer),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->record_button,
"clicked",
G_CALLBACK (sp_window_record_button_clicked),
self,
G_CONNECT_SWAPPED);
/*
* Setup actions for the window.
*/
g_action_map_add_action_entries (G_ACTION_MAP (self),
action_entries,
G_N_ELEMENTS (action_entries),
self);
/*
* Setup our gear (hamburger) menu.
*/
app = GTK_APPLICATION (g_application_get_default ());
menu = gtk_application_get_menu_by_id (app, "gear-menu");
gtk_menu_button_set_menu_model (self->gear_menu_button, G_MENU_MODEL (menu));
/*
* Restore previous window settings.
*/
sp_window_settings_register (GTK_WINDOW (self));
/*
* Set default focus to the record button for quick workflow of
* launch, enter, escape, view.
*/
gtk_window_set_focus (GTK_WINDOW (self), GTK_WIDGET (self->record_button));
}
static void
sp_window_open_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
SpWindow *self = (SpWindow *)object;
g_autoptr(SpCaptureReader) reader = NULL;
g_autoptr(GError) error = NULL;
g_assert (SP_IS_WINDOW (self));
g_assert (G_IS_TASK (result));
reader = g_task_propagate_pointer (G_TASK (result), &error);
if (reader == NULL)
{
sp_window_notify_user (self,
GTK_MESSAGE_ERROR,
"%s", error->message);
return;
}
g_clear_pointer (&self->reader, sp_capture_reader_unref);
self->reader = g_steal_pointer (&reader);
sp_window_set_state (self, SP_WINDOW_STATE_PROCESSING);
}
static void
sp_window_open_worker (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
g_autofree gchar *path = NULL;
SpCaptureReader *reader;
GFile *file = task_data;
GError *error = NULL;
g_assert (G_IS_TASK (task));
g_assert (SP_IS_WINDOW (source_object));
g_assert (G_IS_FILE (file));
path = g_file_get_path (file);
if (NULL == (reader = sp_capture_reader_new (path, &error)))
{
g_task_return_error (task, error);
return;
}
g_task_return_pointer (task, reader, (GDestroyNotify)sp_capture_reader_unref);
}
void
sp_window_open (SpWindow *self,
GFile *file)
{
g_autoptr(GTask) task = NULL;
g_return_if_fail (SP_IS_WINDOW (self));
g_return_if_fail (G_IS_FILE (file));
if (!g_file_is_native (file))
{
sp_window_notify_user (self,
GTK_MESSAGE_ERROR,
_("The file \"%s\" could not be opened. Only local files are supported."),
g_file_get_uri (file));
return;
}
task = g_task_new (self, NULL, sp_window_open_cb, NULL);
g_task_set_task_data (task, g_object_ref (file), g_object_unref);
g_task_run_in_thread (task, sp_window_open_worker);
}
SpWindowState
sp_window_get_state (SpWindow *self)
{
g_return_val_if_fail (SP_IS_WINDOW (self), SP_WINDOW_STATE_0);
return self->state;
}
void
sp_window_open_from_dialog (SpWindow *self)
{
GtkFileFilter *filter;
GtkDialog *dialog;
g_assert (SP_IS_WINDOW (self));
dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
"action", GTK_FILE_CHOOSER_ACTION_OPEN,
"title", _("Open Capture"),
"transient-for", self,
NULL);
gtk_dialog_add_buttons (dialog,
_("Cancel"), GTK_RESPONSE_CANCEL,
_("Open"), GTK_RESPONSE_OK,
NULL);
gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
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);
if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK)
{
g_autoptr(GFile) file = NULL;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
sp_window_open (self, file);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
}

52
src/sp-window.h Normal file
View File

@ -0,0 +1,52 @@
/* sp-window.h
*
* Copyright (C) 2016 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/>.
*/
#ifndef SP_WINDOW_H
#define SP_WINDOW_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define SP_TYPE_WINDOW (sp_window_get_type())
G_DECLARE_FINAL_TYPE (SpWindow, sp_window, SP, WINDOW, GtkApplicationWindow)
typedef enum
{
SP_WINDOW_STATE_0,
SP_WINDOW_STATE_EMPTY,
SP_WINDOW_STATE_FAILED,
SP_WINDOW_STATE_RECORDING,
SP_WINDOW_STATE_PROCESSING,
SP_WINDOW_STATE_BROWSING,
} SpWindowState;
SpWindowState sp_window_get_state (SpWindow *self);
gboolean sp_window_get_recording (SpWindow *self);
GFile *sp_window_get_capture_file (SpWindow *self);
void sp_window_set_capture_file (SpWindow *self,
GFile *capture_file);
void sp_window_open (SpWindow *self,
GFile *file);
void sp_window_open_from_dialog (SpWindow *self);
G_END_DECLS
#endif /* SP_WINDOW_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,926 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="main_window">
<property name="title" translatable="yes">System Profiler</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="default_width">700</property>
<property name="default_height">500</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkVBox" id="main_vbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkMenuBar" id="menubar">
<property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Profiler</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem1_menu">
<child>
<widget class="GtkImageMenuItem" id="start_item">
<property name="visible">True</property>
<property name="label" translatable="yes">_Start</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_start1_activate" last_modification_time="Thu, 04 Nov 2004 18:51:54 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image128">
<property name="visible">True</property>
<property name="stock">gtk-media-play</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="profile_item">
<property name="visible">True</property>
<property name="label" translatable="yes">_Profile</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_profile1_activate" last_modification_time="Thu, 04 Nov 2004 18:51:54 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image129">
<property name="visible">True</property>
<property name="stock">gtk-justify-left</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="reset_item">
<property name="visible">True</property>
<property name="label" translatable="yes">_Reset</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_reset_item_activate" last_modification_time="Fri, 05 Nov 2004 15:34:30 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image130">
<property name="visible">True</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="open_item">
<property name="visible">True</property>
<property name="label" translatable="yes">_Open...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_open_item_activate" last_modification_time="Thu, 04 Nov 2004 21:01:03 GMT"/>
<accelerator key="o" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image131">
<property name="visible">True</property>
<property name="stock">gtk-open</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as_item">
<property name="visible">True</property>
<property name="label" translatable="yes">Save _As...</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_Save _As..._activate" last_modification_time="Wed, 31 Dec 2003 20:44:40 GMT"/>
<accelerator key="s" modifiers="GDK_CONTROL_MASK | GDK_SHIFT_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image132">
<property name="visible">True</property>
<property name="stock">gtk-save-as</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit">
<property name="visible">True</property>
<property name="label" translatable="yes">_Quit</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_quit_activate" last_modification_time="Wed, 31 Dec 2003 20:44:40 GMT"/>
<accelerator key="q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image133">
<property name="visible">True</property>
<property name="stock">gtk-quit</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="view1">
<property name="visible">True</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_view1_activate" last_modification_time="Tue, 08 Nov 2005 04:06:22 GMT"/>
<child>
<widget class="GtkMenu" id="view1_menu">
<child>
<widget class="GtkCheckMenuItem" id="screenshot_item">
<property name="visible">True</property>
<property name="label" translatable="yes">_Screenshot Window</property>
<property name="use_underline">True</property>
<property name="active">False</property>
<signal name="activate" handler="on_screenshot_item_activate" last_modification_time="Tue, 08 Nov 2005 00:40:14 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem4_menu">
<child>
<widget class="GtkImageMenuItem" id="about">
<property name="visible">True</property>
<property name="label" translatable="yes">_About</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_about_activate" last_modification_time="Wed, 31 Dec 2003 20:44:40 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image134">
<property name="visible">True</property>
<property name="stock">gtk-about</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">3</property>
<property name="left_padding">3</property>
<property name="right_padding">3</property>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkToolbar" id="toolbar">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="tooltips">True</property>
<property name="show_arrow">True</property>
<child>
<widget class="GtkRadioToolButton" id="start_button">
<property name="visible">True</property>
<property name="label" translatable="yes">S_tart</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-media-play</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">True</property>
<property name="active">False</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkRadioToolButton" id="profile_button">
<property name="visible">True</property>
<property name="label" translatable="yes">_Profile</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-justify-left</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">True</property>
<property name="active">False</property>
<property name="group">start_button</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="reset_button">
<property name="visible">True</property>
<property name="label" translatable="yes">_Reset</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-clear</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkToolItem" id="toolitem1">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
<widget class="GtkSeparatorToolItem" id="separatortoolitem1">
<property name="visible">True</property>
<property name="draw">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<widget class="GtkToolButton" id="save_as_button">
<property name="visible">True</property>
<property name="stock_id">gtk-save-as</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<widget class="GtkRadioToolButton" id="dummy_button">
<property name="visible">True</property>
<property name="label" translatable="yes">dummy</property>
<property name="use_underline">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<property name="active">False</property>
<property name="group">start_button</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">3</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="samples-toolbar">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
<property name="tooltips">True</property>
<property name="show_arrow">False</property>
<child>
<widget class="GtkToolItem" id="toolitem2">
<property name="visible">True</property>
<property name="visible_horizontal">True</property>
<property name="visible_vertical">True</property>
<property name="is_important">False</property>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="show_tabs">False</property>
<property name="show_border">False</property>
<property name="tab_pos">GTK_POS_TOP</property>
<property name="scrollable">False</property>
<property name="enable_popup">False</property>
<child>
<widget class="GtkHBox" id="samples_hbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="label" translatable="yes">Samples: </property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="show_tabs">False</property>
<property name="show_border">False</property>
<property name="tab_pos">GTK_POS_TOP</property>
<property name="scrollable">False</property>
<property name="enable_popup">False</property>
<child>
<widget class="GtkLabel" id="samples_label">
<property name="visible">True</property>
<property name="label" translatable="yes">0</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1.0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">label6</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="label" translatable="yes">888888</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="label" translatable="yes">label7</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">label2</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="sizer_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Samples: 8888888</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">label3</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">3</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHPaned" id="hpaned">
<property name="border_width">3</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkVPaned" id="vpaned">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="object_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="callers_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="descendants_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkWindow" id="screenshot_window">
<property name="title" translatable="yes">Screenshot</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_UTILITY</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="border_width">12</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">3</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="screenshot_textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_NONE</property>
<property name="cursor_visible">False</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Screenshot&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="screenshot_close_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>