Merge branch 'wip/gtk4-port' into 'master'

Port sysprof to GTK 4

See merge request GNOME/sysprof!49
This commit is contained in:
Christian Hergert
2022-04-01 23:51:04 +00:00
100 changed files with 5620 additions and 2175 deletions

View File

@ -97,21 +97,6 @@
} }
] ]
}, },
{
"name" : "libdazzle",
"config-opts" : [
"--libdir=/app/lib",
"--buildtype=debugoptimized"
],
"buildsystem" : "meson",
"builddir" : true,
"sources" : [
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libdazzle.git"
}
]
},
{ {
"name" : "sysprof", "name" : "sysprof",
"config-opts" : [ "config-opts" : [

View File

@ -1,20 +1,5 @@
<schemalist> <schemalist>
<schema id="org.gnome.sysprof3" path="/org/gnome/sysprof/" gettext-domain="sysprof"> <schema id="org.gnome.sysprof3" path="/org/gnome/sysprof/" gettext-domain="sysprof">
<key name="window-size" type="(ii)">
<default>(-1, -1)</default>
<summary>Window size</summary>
<description>Window size (width and height).</description>
</key>
<key name="window-position" type="(ii)">
<default>(-1,-1)</default>
<summary>Window position</summary>
<description>Window position (x and y).</description>
</key>
<key name="window-maximized" type="b">
<default>true</default>
<summary>Window maximized</summary>
<description>Window maximized state</description>
</key>
<key name="last-spawn-argv" type="s"> <key name="last-spawn-argv" type="s">
<default>''</default> <default>''</default>
<summary>Last Spawn Program</summary> <summary>Last Spawn Program</summary>

View File

@ -8,22 +8,23 @@ project('sysprof', 'c',
] ]
) )
symbolic_version = '42.0' symbolic_version = '43.alpha0'
gnome = import('gnome') gnome = import('gnome')
pkgconfig = import('pkgconfig') pkgconfig = import('pkgconfig')
i18n = import('i18n') i18n = import('i18n')
libsysprof_api_version = 4 libsysprof_api_version = 4
libsysprof_ui_api_version = 5
version_split = meson.project_version().split('.') version_split = meson.project_version().split('.')
datadir = get_option('datadir') datadir = get_option('datadir')
datadir_for_pc_file = join_paths('${prefix}', datadir) datadir_for_pc_file = join_paths('${prefix}', datadir)
podir = join_paths(meson.current_source_dir(), 'po') podir = join_paths(meson.current_source_dir(), 'po')
glib_req_version = '>= 2.67.4' glib_req_version = '>= 2.68.0'
gtk_req_version = '>= 3.22' gtk_req_version = '>= 4.4'
polkit_req_version = '>= 0.105' polkit_req_version = '>= 0.105'
dazzle_req_version = '>= 3.30.0'
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
@ -45,6 +46,7 @@ config_h.set('PACKAGE_TARNAME', 'PACKAGE_STRING')
config_h.set('PACKAGE', 'PACKAGE_NAME') config_h.set('PACKAGE', 'PACKAGE_NAME')
config_h.set('VERSION', 'PACKAGE_VERSION') config_h.set('VERSION', 'PACKAGE_VERSION')
# Detect and set symbol visibility # Detect and set symbol visibility
if get_option('default_library') != 'static' if get_option('default_library') != 'static'
if host_machine.system() == 'windows' if host_machine.system() == 'windows'

View File

@ -1,7 +1,3 @@
SysprofDisplay dzlmultipaned {
-DzlMultiPaned-handle-size: 0;
}
SysprofVisualizer { SysprofVisualizer {
background: @content_view_bg; background: @content_view_bg;
} }
@ -34,11 +30,11 @@ SysprofVisualizersFrame scrollbar.horizontal {
background: transparent; background: transparent;
} }
SysprofVisualizersFrame scrollbar.horizontal contents trough { SysprofVisualizersFrame scrollbar.horizontal range trough {
background: transparent; background: transparent;
} }
SysprofVisualizersFrame scrollbar.horizontal contents trough slider { SysprofVisualizersFrame scrollbar.horizontal range trough slider {
margin-left: 1px; margin-left: 1px;
margin-right: 1px; margin-right: 1px;
padding: 6px; padding: 6px;
@ -81,10 +77,6 @@ SysprofVisualizersFrame .left-column .small-button.flat:hover {
border-color: @borders; border-color: @borders;
} }
SysprofDisplay > dzlmultipaned > :nth-child(2) {
border-top: 1px solid @borders;
}
SysprofVisualizersFrame .selection { SysprofVisualizersFrame .selection {
border-radius: 3px; border-radius: 3px;
background-color: alpha(@theme_selected_bg_color, 0.35); background-color: alpha(@theme_selected_bg_color, 0.35);

View File

@ -0,0 +1,35 @@
/* egg-handle.h
*
* Copyright 2021 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define EGG_TYPE_HANDLE (egg_handle_get_type())
G_DECLARE_FINAL_TYPE (EggHandle, egg_handle, EGG, HANDLE, GtkWidget)
GtkWidget *egg_handle_new (GtkPositionType position);
void egg_handle_set_position (EggHandle *self,
GtkPositionType position);
G_END_DECLS

View File

@ -0,0 +1,145 @@
/* egg-handle.c
*
* Copyright 2021 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "config.h"
#include "egg-handle-private.h"
#define EXTRA_SIZE 8
struct _EggHandle
{
GtkWidget parent_instance;
GtkWidget *separator;
GtkPositionType position : 3;
};
G_DEFINE_TYPE (EggHandle, egg_handle, GTK_TYPE_WIDGET)
static gboolean
egg_handle_contains (GtkWidget *widget,
double x,
double y)
{
EggHandle *self = (EggHandle *)widget;
graphene_rect_t area;
g_assert (EGG_IS_HANDLE (self));
if (!gtk_widget_compute_bounds (GTK_WIDGET (self->separator),
GTK_WIDGET (self),
&area))
return FALSE;
switch (self->position)
{
case GTK_POS_LEFT:
area.origin.x -= EXTRA_SIZE;
area.size.width = EXTRA_SIZE;
break;
case GTK_POS_RIGHT:
area.size.width = EXTRA_SIZE;
break;
case GTK_POS_TOP:
area.origin.y -= EXTRA_SIZE;
area.size.height = EXTRA_SIZE;
break;
case GTK_POS_BOTTOM:
area.size.height = EXTRA_SIZE;
break;
default:
g_assert_not_reached ();
break;
}
return graphene_rect_contains_point (&area, &GRAPHENE_POINT_INIT (x, y));
}
static void
egg_handle_dispose (GObject *object)
{
EggHandle *self = (EggHandle *)object;
g_clear_pointer (&self->separator, gtk_widget_unparent);
G_OBJECT_CLASS (egg_handle_parent_class)->dispose (object);
}
static void
egg_handle_class_init (EggHandleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = egg_handle_dispose;
widget_class->contains = egg_handle_contains;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
static void
egg_handle_init (EggHandle *self)
{
self->separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_widget_set_parent (GTK_WIDGET (self->separator), GTK_WIDGET (self));
}
void
egg_handle_set_position (EggHandle *self,
GtkPositionType position)
{
g_return_if_fail (EGG_IS_HANDLE (self));
self->position = position;
switch (position)
{
case GTK_POS_LEFT:
case GTK_POS_RIGHT:
gtk_widget_set_cursor_from_name (GTK_WIDGET (self), "col-resize");
gtk_orientable_set_orientation (GTK_ORIENTABLE (self->separator), GTK_ORIENTATION_VERTICAL);
break;
case GTK_POS_TOP:
case GTK_POS_BOTTOM:
gtk_widget_set_cursor_from_name (GTK_WIDGET (self), "row-resize");
gtk_orientable_set_orientation (GTK_ORIENTABLE (self->separator), GTK_ORIENTATION_HORIZONTAL);
break;
default:
g_assert_not_reached ();
}
}
GtkWidget *
egg_handle_new (GtkPositionType position)
{
EggHandle *self;
self = g_object_new (EGG_TYPE_HANDLE, NULL);
egg_handle_set_position (self, position);
return GTK_WIDGET (self);
}

View File

@ -0,0 +1,48 @@
/* egg-paned.h
*
* Copyright 2021 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define EGG_TYPE_PANED (egg_paned_get_type())
G_DECLARE_FINAL_TYPE (EggPaned, egg_paned, EGG, PANED, GtkWidget)
GtkWidget *egg_paned_new (void);
void egg_paned_append (EggPaned *self,
GtkWidget *child);
void egg_paned_prepend (EggPaned *self,
GtkWidget *child);
void egg_paned_insert (EggPaned *self,
int position,
GtkWidget *child);
void egg_paned_insert_after (EggPaned *self,
GtkWidget *child,
GtkWidget *sibling);
void egg_paned_remove (EggPaned *self,
GtkWidget *child);
guint egg_paned_get_n_children (EggPaned *self);
GtkWidget *egg_paned_get_nth_child (EggPaned *self,
guint nth);
G_END_DECLS

View File

@ -0,0 +1,593 @@
/* egg-paned.c
*
* Copyright 2021 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "config.h"
#include <string.h>
#include "egg-paned-private.h"
#include "egg-resizer-private.h"
struct _EggPaned
{
GtkWidget parent_instance;
GtkOrientation orientation;
};
static void buildable_iface_init (GtkBuildableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EggPaned, egg_paned, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
enum {
PROP_0,
N_PROPS,
PROP_ORIENTATION,
};
static void
update_orientation (GtkWidget *widget,
GtkOrientation orientation)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_widget_remove_css_class (widget, "vertical");
gtk_widget_add_css_class (widget, "horizontal");
}
else
{
gtk_widget_remove_css_class (widget, "horizontal");
gtk_widget_add_css_class (widget, "vertical");
}
gtk_accessible_update_property (GTK_ACCESSIBLE (widget),
GTK_ACCESSIBLE_PROPERTY_ORIENTATION, orientation,
-1);
}
/**
* egg_paned_new:
*
* Create a new #EggPaned.
*
* Returns: (transfer full): a newly created #EggPaned
*/
GtkWidget *
egg_paned_new (void)
{
return g_object_new (EGG_TYPE_PANED, NULL);
}
static void
egg_paned_set_orientation (EggPaned *self,
GtkOrientation orientation)
{
GtkPositionType pos;
g_assert (EGG_IS_PANED (self));
g_assert (orientation == GTK_ORIENTATION_HORIZONTAL ||
orientation == GTK_ORIENTATION_VERTICAL);
if (self->orientation == orientation)
return;
self->orientation = orientation;
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
pos = GTK_POS_LEFT;
else
pos = GTK_POS_TOP;
for (GtkWidget *child = gtk_widget_get_last_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_prev_sibling (child))
{
g_assert (EGG_IS_RESIZER (child));
egg_resizer_set_position (EGG_RESIZER (child), pos);
}
update_orientation (GTK_WIDGET (self), self->orientation);
gtk_widget_queue_resize (GTK_WIDGET (self));
g_object_notify (G_OBJECT (self), "orientation");
}
static void
egg_paned_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
EggPaned *self = (EggPaned *)widget;
g_assert (EGG_IS_PANED (self));
*minimum = 0;
*natural = 0;
*minimum_baseline = -1;
*natural_baseline = -1;
for (GtkWidget *child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
int child_min, child_nat;
gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, NULL, NULL);
if (orientation == self->orientation)
{
*minimum += child_min;
*natural += child_nat;
}
else
{
*minimum = MAX (*minimum, child_min);
*natural = MAX (*natural, child_nat);
}
}
}
typedef struct
{
GtkWidget *widget;
GtkRequisition min_request;
GtkRequisition nat_request;
GtkAllocation alloc;
} ChildAllocation;
static void
egg_paned_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
EggPaned *self = (EggPaned *)widget;
ChildAllocation *allocs;
ChildAllocation *last_alloc = NULL;
GtkOrientation orientation;
guint n_children = 0;
guint n_expand = 0;
guint i;
int extra_width = width;
int extra_height = height;
int expand_width;
int expand_height;
int x, y;
g_assert (EGG_IS_PANED (self));
GTK_WIDGET_CLASS (egg_paned_parent_class)->size_allocate (widget, width, height, baseline);
n_children = egg_paned_get_n_children (self);
if (n_children == 1)
{
GtkWidget *child = gtk_widget_get_first_child (widget);
GtkAllocation alloc = { 0, 0, width, height };
if (gtk_widget_get_visible (child))
{
gtk_widget_size_allocate (child, &alloc, -1);
return;
}
}
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (self));
allocs = g_newa (ChildAllocation, n_children);
memset (allocs, 0, sizeof *allocs * n_children);
/* Give min size to each of the children */
i = 0;
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child), i++)
{
ChildAllocation *child_alloc = &allocs[i];
if (!gtk_widget_get_visible (child))
continue;
gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, height,
&child_alloc->min_request.width,
&child_alloc->nat_request.width,
NULL, NULL);
gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, width,
&child_alloc->min_request.height,
&child_alloc->nat_request.height,
NULL, NULL);
child_alloc->alloc.width = child_alloc->min_request.width;
child_alloc->alloc.height = child_alloc->min_request.height;
n_expand += gtk_widget_compute_expand (child, orientation);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
extra_width -= child_alloc->alloc.width;
child_alloc->alloc.height = height;
}
else
{
extra_height -= child_alloc->alloc.height;
child_alloc->alloc.width = width;
}
}
/* Now try to distribute extra space for natural size */
i = 0;
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child), i++)
{
ChildAllocation *child_alloc = &allocs[i];
if (!gtk_widget_get_visible (child))
continue;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
int taken = MIN (extra_width, child_alloc->nat_request.width - child_alloc->alloc.width);
if (taken > 0)
{
child_alloc->alloc.width += taken;
extra_width -= taken;
}
}
else
{
int taken = MIN (extra_height, child_alloc->nat_request.height - child_alloc->alloc.height);
if (taken > 0)
{
child_alloc->alloc.height += taken;
extra_height -= taken;
}
}
last_alloc = child_alloc;
}
/* Now give extra space for those that expand */
expand_width = n_expand ? extra_width / n_expand : 0;
expand_height = n_expand ? extra_height / n_expand : 0;
i = n_children;
for (GtkWidget *child = gtk_widget_get_last_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_prev_sibling (child), i--)
{
ChildAllocation *child_alloc = &allocs[i-1];
if (!gtk_widget_get_visible (child))
continue;
if (!gtk_widget_compute_expand (child, orientation))
continue;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
child_alloc->alloc.width += expand_width;
extra_width -= expand_width;
}
else
{
child_alloc->alloc.height += expand_height;
extra_height -= expand_height;
}
}
/* Give any leftover to the last visible child */
if (last_alloc)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
last_alloc->alloc.width += extra_width;
else
last_alloc->alloc.height += extra_height;
}
i = 0;
x = 0;
y = 0;
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child), i++)
{
ChildAllocation *child_alloc = &allocs[i];
child_alloc->alloc.x = x;
child_alloc->alloc.y = y;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
x += child_alloc->alloc.width;
else
y += child_alloc->alloc.height;
gtk_widget_size_allocate (child, &child_alloc->alloc, -1);
}
}
static void
egg_paned_dispose (GObject *object)
{
EggPaned *self = (EggPaned *)object;
GtkWidget *child;
child = gtk_widget_get_first_child (GTK_WIDGET (self));
while (child)
{
GtkWidget *next = gtk_widget_get_next_sibling (child);
gtk_widget_unparent (child);
child = next;
}
G_OBJECT_CLASS (egg_paned_parent_class)->dispose (object);
}
static void
egg_paned_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EggPaned *self = EGG_PANED (object);
switch (prop_id)
{
case PROP_ORIENTATION:
g_value_set_enum (value, self->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_paned_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EggPaned *self = EGG_PANED (object);
switch (prop_id)
{
case PROP_ORIENTATION:
egg_paned_set_orientation (self, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_paned_class_init (EggPanedClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = egg_paned_dispose;
object_class->get_property = egg_paned_get_property;
object_class->set_property = egg_paned_set_property;
widget_class->measure = egg_paned_measure;
widget_class->size_allocate = egg_paned_size_allocate;
g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
gtk_widget_class_set_css_name (widget_class, "eggpaned");
}
static void
egg_paned_init (EggPaned *self)
{
self->orientation = GTK_ORIENTATION_HORIZONTAL;
update_orientation (GTK_WIDGET (self), self->orientation);
}
static void
egg_paned_update_handles (EggPaned *self)
{
GtkWidget *child;
g_assert (EGG_IS_PANED (self));
for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
GtkWidget *handle;
g_assert (EGG_IS_RESIZER (child));
if ((handle = egg_resizer_get_handle (EGG_RESIZER (child))))
gtk_widget_show (handle);
}
if ((child = gtk_widget_get_last_child (GTK_WIDGET (self))))
{
GtkWidget *handle = egg_resizer_get_handle (EGG_RESIZER (child));
gtk_widget_hide (handle);
}
}
void
egg_paned_remove (EggPaned *self,
GtkWidget *child)
{
GtkWidget *resizer;
g_return_if_fail (EGG_IS_PANED (self));
g_return_if_fail (GTK_IS_WIDGET (child));
resizer = gtk_widget_get_ancestor (child, EGG_TYPE_RESIZER);
g_return_if_fail (resizer != NULL &&
gtk_widget_get_parent (resizer) == GTK_WIDGET (self));
gtk_widget_unparent (resizer);
egg_paned_update_handles (self);
gtk_widget_queue_resize (GTK_WIDGET (self));
}
void
egg_paned_insert (EggPaned *self,
int position,
GtkWidget *child)
{
GtkPositionType pos;
GtkWidget *resizer;
g_return_if_fail (EGG_IS_PANED (self));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (gtk_widget_get_parent (child) == NULL);
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
pos = GTK_POS_LEFT;
else
pos = GTK_POS_TOP;
resizer = egg_resizer_new (pos);
egg_resizer_set_child (EGG_RESIZER (resizer), child);
if (position < 0)
gtk_widget_insert_before (GTK_WIDGET (resizer), GTK_WIDGET (self), NULL);
else if (position == 0)
gtk_widget_insert_after (GTK_WIDGET (resizer), GTK_WIDGET (self), NULL);
else
{
GtkWidget *sibling = gtk_widget_get_first_child (GTK_WIDGET (self));
for (int i = position; i > 0 && sibling != NULL; i--)
sibling = gtk_widget_get_next_sibling (sibling);
gtk_widget_insert_before (GTK_WIDGET (resizer), GTK_WIDGET (self), sibling);
}
egg_paned_update_handles (self);
gtk_widget_queue_resize (GTK_WIDGET (self));
}
void
egg_paned_append (EggPaned *self,
GtkWidget *child)
{
egg_paned_insert (self, -1, child);
}
void
egg_paned_prepend (EggPaned *self,
GtkWidget *child)
{
egg_paned_insert (self, 0, child);
}
void
egg_paned_insert_after (EggPaned *self,
GtkWidget *child,
GtkWidget *sibling)
{
int position = 0;
g_return_if_fail (EGG_IS_PANED (self));
g_return_if_fail (GTK_IS_WIDGET (child));
g_return_if_fail (!sibling || GTK_IS_WIDGET (sibling));
if (sibling == NULL)
{
egg_paned_prepend (self, child);
return;
}
/* TODO: We should reverse insert() to call this */
for (GtkWidget *ancestor = gtk_widget_get_first_child (GTK_WIDGET (self));
ancestor != NULL;
ancestor = gtk_widget_get_next_sibling (ancestor))
{
position++;
if (sibling == ancestor || gtk_widget_is_ancestor (sibling, ancestor))
break;
}
egg_paned_insert (self, position, child);
}
guint
egg_paned_get_n_children (EggPaned *self)
{
guint count = 0;
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child))
count++;
return count;
}
GtkWidget *
egg_paned_get_nth_child (EggPaned *self,
guint nth)
{
g_return_val_if_fail (EGG_IS_PANED (self), NULL);
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self));
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
g_assert (EGG_IS_RESIZER (child));
if (nth == 0)
return egg_resizer_get_child (EGG_RESIZER (child));
nth--;
}
return NULL;
}
static void
egg_paned_add_child (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const char *type)
{
if (GTK_IS_WIDGET (child))
egg_paned_append (EGG_PANED (buildable), GTK_WIDGET (child));
else
g_warning ("Cannot add child of type %s to %s",
G_OBJECT_TYPE_NAME (child),
G_OBJECT_TYPE_NAME (buildable));
}
static void
buildable_iface_init (GtkBuildableIface *iface)
{
iface->add_child = egg_paned_add_child;
}

View File

@ -0,0 +1,40 @@
/* egg-resizer.h
*
* Copyright 2021 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define EGG_TYPE_RESIZER (egg_resizer_get_type())
G_DECLARE_FINAL_TYPE (EggResizer, egg_resizer, EGG, RESIZER, GtkWidget)
GtkWidget *egg_resizer_new (GtkPositionType position);
GtkPositionType egg_resizer_get_position (EggResizer *self);
void egg_resizer_set_position (EggResizer *self,
GtkPositionType position);
GtkWidget *egg_resizer_get_child (EggResizer *self);
void egg_resizer_set_child (EggResizer *self,
GtkWidget *child);
GtkWidget *egg_resizer_get_handle (EggResizer *self);
G_END_DECLS

View File

@ -0,0 +1,495 @@
/* egg-resizer.c
*
* Copyright 2021 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "config.h"
#include "egg-handle-private.h"
#include "egg-resizer-private.h"
#define HANDLE_SIZE 8
struct _EggResizer
{
GtkWidget parent_instance;
EggHandle *handle;
GtkWidget *child;
double drag_orig_size;
double drag_position;
GtkPositionType position : 3;
};
G_DEFINE_TYPE (EggResizer, egg_resizer, GTK_TYPE_WIDGET)
enum {
PROP_0,
PROP_CHILD,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
static void
egg_resizer_drag_begin_cb (EggResizer *self,
double start_x,
double start_y,
GtkGestureDrag *drag)
{
GtkAllocation child_alloc;
GtkAllocation handle_alloc;
g_assert (EGG_IS_RESIZER (self));
g_assert (GTK_IS_GESTURE_DRAG (drag));
if (self->child == NULL)
return;
switch (self->position)
{
case GTK_POS_LEFT:
if (start_x > gtk_widget_get_width (GTK_WIDGET (self)) - HANDLE_SIZE)
goto start_drag;
break;
case GTK_POS_RIGHT:
if (start_x <= HANDLE_SIZE)
goto start_drag;
break;
case GTK_POS_TOP:
if (start_y > gtk_widget_get_height (GTK_WIDGET (self)) - HANDLE_SIZE)
goto start_drag;
break;
case GTK_POS_BOTTOM:
if (start_y <= HANDLE_SIZE)
goto start_drag;
break;
default:
g_assert_not_reached ();
break;
}
gtk_gesture_set_state (GTK_GESTURE (drag),
GTK_EVENT_SEQUENCE_DENIED);
return;
start_drag:
gtk_widget_get_allocation (self->child, &child_alloc);
gtk_widget_get_allocation (GTK_WIDGET (self->handle), &handle_alloc);
if (self->position == GTK_POS_LEFT ||
self->position == GTK_POS_RIGHT)
{
self->drag_orig_size = child_alloc.width + handle_alloc.width;
gtk_widget_set_hexpand (self->child, FALSE);
}
else
{
self->drag_orig_size = child_alloc.height + handle_alloc.height;
gtk_widget_set_vexpand (self->child, FALSE);
}
self->drag_position = self->drag_orig_size;
gtk_widget_queue_resize (GTK_WIDGET (self));
}
static void
egg_resizer_drag_update_cb (EggResizer *self,
double offset_x,
double offset_y,
GtkGestureDrag *drag)
{
g_assert (EGG_IS_RESIZER (self));
g_assert (GTK_IS_GESTURE_DRAG (drag));
if (self->position == GTK_POS_LEFT)
self->drag_position = self->drag_orig_size + offset_x;
else if (self->position == GTK_POS_RIGHT)
self->drag_position = gtk_widget_get_width (GTK_WIDGET (self)) - offset_x;
else if (self->position == GTK_POS_TOP)
self->drag_position = self->drag_orig_size + offset_y;
else if (self->position == GTK_POS_BOTTOM)
self->drag_position = gtk_widget_get_height (GTK_WIDGET (self)) - offset_y;
gtk_widget_queue_resize (GTK_WIDGET (self));
}
static void
egg_resizer_drag_end_cb (EggResizer *self,
double offset_x,
double offset_y,
GtkGestureDrag *drag)
{
g_assert (EGG_IS_RESIZER (self));
g_assert (GTK_IS_GESTURE_DRAG (drag));
}
GtkWidget *
egg_resizer_new (GtkPositionType position)
{
EggResizer *self;
self = g_object_new (EGG_TYPE_RESIZER, NULL);
self->position = position;
self->handle = EGG_HANDLE (egg_handle_new (position));
gtk_widget_set_parent (GTK_WIDGET (self->handle), GTK_WIDGET (self));
return GTK_WIDGET (self);
}
static void
egg_resizer_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
EggResizer *self = (EggResizer *)widget;
g_assert (EGG_IS_RESIZER (self));
*minimum = 0;
*natural = 0;
*minimum_baseline = -1;
*natural_baseline = -1;
if (self->child != NULL)
gtk_widget_measure (self->child,
orientation,
for_size,
minimum, natural,
NULL, NULL);
if ((orientation == GTK_ORIENTATION_HORIZONTAL &&
(self->position == GTK_POS_LEFT ||
self->position == GTK_POS_RIGHT)) ||
(orientation == GTK_ORIENTATION_VERTICAL &&
(self->position == GTK_POS_TOP ||
self->position == GTK_POS_BOTTOM)))
{
int handle_min, handle_nat;
if (self->drag_position != 0)
{
if (self->drag_position > *minimum)
*natural = self->drag_position;
else if (self->drag_position < *minimum)
*natural = *minimum;
}
if (gtk_widget_get_visible (GTK_WIDGET (self->handle)))
{
gtk_widget_measure (GTK_WIDGET (self->handle),
orientation, for_size,
&handle_min, &handle_nat,
NULL, NULL);
*minimum += handle_min;
*natural += handle_nat;
}
}
}
static void
egg_resizer_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
EggResizer *self = (EggResizer *)widget;
GtkOrientation orientation;
GtkAllocation child_alloc;
GtkAllocation handle_alloc;
int handle_min = 0, handle_nat = 0;
g_assert (EGG_IS_RESIZER (self));
if (self->position == GTK_POS_LEFT ||
self->position == GTK_POS_RIGHT)
orientation = GTK_ORIENTATION_HORIZONTAL;
else
orientation = GTK_ORIENTATION_VERTICAL;
if (gtk_widget_get_visible (GTK_WIDGET (self->handle)))
gtk_widget_measure (GTK_WIDGET (self->handle),
orientation,
-1,
&handle_min, &handle_nat,
NULL, NULL);
switch (self->position)
{
case GTK_POS_LEFT:
handle_alloc.x = width - handle_min;
handle_alloc.width = handle_min;
handle_alloc.y = 0;
handle_alloc.height = height;
child_alloc.x = 0;
child_alloc.y = 0;
child_alloc.width = width - handle_min;
child_alloc.height = height;
break;
case GTK_POS_RIGHT:
handle_alloc.x = 0;
handle_alloc.width = handle_min;
handle_alloc.y = 0;
handle_alloc.height = height;
child_alloc.x = handle_min;
child_alloc.y = 0;
child_alloc.width = width - handle_min;
child_alloc.height = height;
break;
case GTK_POS_TOP:
handle_alloc.x = 0;
handle_alloc.width = width;
handle_alloc.y = height - handle_min;
handle_alloc.height = handle_min;
child_alloc.x = 0;
child_alloc.y = 0;
child_alloc.width = width;
child_alloc.height = height - handle_min;
break;
case GTK_POS_BOTTOM:
handle_alloc.x = 0;
handle_alloc.width = width;
handle_alloc.y = 0;
handle_alloc.height = handle_min;
child_alloc.x = 0;
child_alloc.y = handle_min;
child_alloc.width = width;
child_alloc.height = height - handle_min;
break;
default:
g_assert_not_reached ();
}
if (gtk_widget_get_mapped (GTK_WIDGET (self->handle)))
gtk_widget_size_allocate (GTK_WIDGET (self->handle), &handle_alloc, -1);
if (self->child != NULL &&
gtk_widget_get_mapped (self->child))
gtk_widget_size_allocate (self->child, &child_alloc, -1);
}
static void
egg_resizer_compute_expand (GtkWidget *widget,
gboolean *hexpand,
gboolean *vexpand)
{
EggResizer *self = EGG_RESIZER (widget);
if (self->child != NULL)
{
*hexpand = gtk_widget_compute_expand (self->child, GTK_ORIENTATION_HORIZONTAL);
*vexpand = gtk_widget_compute_expand (self->child, GTK_ORIENTATION_VERTICAL);
}
else
{
*hexpand = FALSE;
*vexpand = FALSE;
}
}
static void
egg_resizer_dispose (GObject *object)
{
EggResizer *self = (EggResizer *)object;
if (self->handle)
gtk_widget_unparent (GTK_WIDGET (self->handle));
self->handle = NULL;
if (self->child)
gtk_widget_unparent (self->child);
self->child = NULL;
G_OBJECT_CLASS (egg_resizer_parent_class)->dispose (object);
}
static void
egg_resizer_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EggResizer *self = EGG_RESIZER (object);
switch (prop_id)
{
case PROP_CHILD:
g_value_set_object (value, egg_resizer_get_child (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_resizer_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EggResizer *self = EGG_RESIZER (object);
switch (prop_id)
{
case PROP_CHILD:
egg_resizer_set_child (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_resizer_class_init (EggResizerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = egg_resizer_dispose;
object_class->get_property = egg_resizer_get_property;
object_class->set_property = egg_resizer_set_property;
widget_class->compute_expand = egg_resizer_compute_expand;
widget_class->measure = egg_resizer_measure;
widget_class->size_allocate = egg_resizer_size_allocate;
properties [PROP_CHILD] =
g_param_spec_object ("child",
"Child",
"Child",
GTK_TYPE_WIDGET,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_css_name (widget_class, "eggresizer");
}
static void
egg_resizer_init (EggResizer *self)
{
GtkGesture *gesture;
gesture = gtk_gesture_drag_new ();
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), GTK_PHASE_CAPTURE);
g_signal_connect_object (gesture,
"drag-begin",
G_CALLBACK (egg_resizer_drag_begin_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (gesture,
"drag-update",
G_CALLBACK (egg_resizer_drag_update_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (gesture,
"drag-end",
G_CALLBACK (egg_resizer_drag_end_cb),
self,
G_CONNECT_SWAPPED);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
}
/**
* egg_resizer_get_child:
* @self: a #EggResizer
*
* Gets the child widget of the resizer.
*
* Returns: (transfer none) (nullable): A #GtkWidget or %NULL
*/
GtkWidget *
egg_resizer_get_child (EggResizer *self)
{
g_return_val_if_fail (EGG_IS_RESIZER (self), NULL);
return self->child;
}
void
egg_resizer_set_child (EggResizer *self,
GtkWidget *child)
{
g_return_if_fail (EGG_IS_RESIZER (self));
g_return_if_fail (!child || GTK_IS_WIDGET (child));
if (child == self->child)
return;
g_clear_pointer (&self->child, gtk_widget_unparent);
self->child = child;
if (self->child != NULL)
gtk_widget_insert_before (self->child,
GTK_WIDGET (self),
GTK_WIDGET (self->handle));
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CHILD]);
}
GtkPositionType
egg_resizer_get_position (EggResizer *self)
{
g_return_val_if_fail (EGG_IS_RESIZER (self), 0);
return self->position;
}
void
egg_resizer_set_position (EggResizer *self,
GtkPositionType position)
{
g_return_if_fail (EGG_IS_RESIZER (self));
if (position != self->position)
{
self->position = position;
egg_handle_set_position (self->handle, position);
gtk_widget_queue_resize (GTK_WIDGET (self));
}
}
GtkWidget *
egg_resizer_get_handle (EggResizer *self)
{
g_return_val_if_fail (EGG_IS_RESIZER (self), NULL);
return GTK_WIDGET (self->handle);
}

View File

@ -0,0 +1,781 @@
/* egg-three-grid.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/>.
*/
#define G_LOG_DOMAIN "egg-three-grid"
#include "config.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include "egg-three-grid.h"
struct _EggThreeGridChild
{
GtkLayoutChild parent_instance;
EggThreeGridColumn column;
int row;
int min_height;
int nat_height;
int min_baseline;
int nat_baseline;
};
#define EGG_TYPE_THREE_GRID_CHILD (egg_three_grid_child_get_type())
G_DECLARE_FINAL_TYPE (EggThreeGridChild, egg_three_grid_child, EGG, THREE_GRID_CHILD, GtkLayoutChild)
G_DEFINE_FINAL_TYPE (EggThreeGridChild, egg_three_grid_child, GTK_TYPE_LAYOUT_CHILD)
enum {
CHILD_PROP_0,
CHILD_PROP_COLUMN,
CHILD_PROP_ROW,
LAST_CHILD_PROP
};
static GParamSpec *child_properties [LAST_CHILD_PROP];
static void
egg_three_grid_child_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EggThreeGridChild *self = EGG_THREE_GRID_CHILD (object);
switch (prop_id)
{
case CHILD_PROP_ROW:
g_value_set_uint (value, self->row);
break;
case CHILD_PROP_COLUMN:
g_value_set_enum (value, self->column);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_three_grid_child_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EggThreeGridChild *self = EGG_THREE_GRID_CHILD (object);
switch (prop_id)
{
case CHILD_PROP_ROW:
self->row = g_value_get_uint (value);
break;
case CHILD_PROP_COLUMN:
self->column = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_three_grid_child_class_init (EggThreeGridChildClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = egg_three_grid_child_get_property;
object_class->set_property = egg_three_grid_child_set_property;
child_properties [CHILD_PROP_COLUMN] =
g_param_spec_enum ("column",
"Column",
"The column for the child",
EGG_TYPE_THREE_GRID_COLUMN,
EGG_THREE_GRID_COLUMN_LEFT,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
child_properties [CHILD_PROP_ROW] =
g_param_spec_uint ("row",
"Row",
"The row for the child",
0, G_MAXUINT, 0,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, LAST_CHILD_PROP, child_properties);
}
static void
egg_three_grid_child_init (EggThreeGridChild *self)
{
}
typedef struct
{
int row;
int min_above_baseline;
int min_below_baseline;
int nat_above_baseline;
int nat_below_baseline;
} EggThreeGridRowInfo;
struct _EggThreeGridLayout
{
GtkLayoutManager parent_instance;
GHashTable *row_infos;
int row_spacing;
int column_spacing;
};
#define EGG_TYPE_THREE_GRID_LAYOUT (egg_three_grid_layout_get_type())
G_DECLARE_FINAL_TYPE (EggThreeGridLayout, egg_three_grid_layout, EGG, THREE_GRID_LAYOUT, GtkLayoutManager)
G_DEFINE_FINAL_TYPE (EggThreeGridLayout, egg_three_grid_layout, GTK_TYPE_LAYOUT_MANAGER)
static GtkSizeRequestMode
egg_three_grid_layout_get_request_mode (GtkLayoutManager *manager,
GtkWidget *widget)
{
return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
}
static void
get_column_width (EggThreeGridLayout *self,
GtkWidget *widget,
EggThreeGridColumn column,
int *min_width,
int *nat_width)
{
int real_min_width = 0;
int real_nat_width = 0;
g_assert (EGG_IS_THREE_GRID_LAYOUT (self));
g_assert (column >= EGG_THREE_GRID_COLUMN_LEFT);
g_assert (column <= EGG_THREE_GRID_COLUMN_RIGHT);
g_assert (min_width != NULL);
g_assert (nat_width != NULL);
for (GtkWidget *iter = gtk_widget_get_first_child (widget);
iter;
iter = gtk_widget_get_next_sibling (iter))
{
EggThreeGridChild *child = EGG_THREE_GRID_CHILD (gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), iter));
if (child->column == column)
{
int child_min_width;
int child_nat_width;
gtk_widget_measure (iter, GTK_ORIENTATION_HORIZONTAL, 0, &child_min_width, &child_nat_width, NULL, NULL);
real_min_width = MAX (real_min_width, child_min_width);
real_nat_width = MAX (real_nat_width, child_nat_width);
}
}
*min_width = real_min_width;
*nat_width = real_nat_width;
}
static void
get_preferred_width (EggThreeGridLayout *self,
GtkWidget *widget,
int *min_width,
int *nat_width)
{
int min_widths[3];
int nat_widths[3];
g_assert (EGG_IS_THREE_GRID_LAYOUT (self));
g_assert (min_width != NULL);
g_assert (nat_width != NULL);
for (guint i = 0; i < 3; i++)
get_column_width (self, widget, i, &min_widths[i], &nat_widths[i]);
*min_width = MAX (min_widths[0], min_widths[2]) * 2 + min_widths[1] + (self->column_spacing * 2);
*nat_width = MAX (nat_widths[0], nat_widths[2]) * 2 + nat_widths[1] + (self->column_spacing * 2);
}
static void
row_info_merge (EggThreeGridRowInfo *row_info,
const EggThreeGridRowInfo *other)
{
g_assert (row_info);
g_assert (other);
row_info->min_above_baseline = MAX (row_info->min_above_baseline, other->min_above_baseline);
row_info->min_below_baseline = MAX (row_info->min_below_baseline, other->min_below_baseline);
row_info->nat_above_baseline = MAX (row_info->nat_above_baseline, other->nat_above_baseline);
row_info->nat_below_baseline = MAX (row_info->nat_below_baseline, other->nat_below_baseline);
}
static void
update_row_info (GHashTable *hashtable,
EggThreeGridChild *child)
{
GtkBaselinePosition baseline_position = GTK_BASELINE_POSITION_CENTER;
EggThreeGridRowInfo *row_info;
EggThreeGridRowInfo current = { 0 };
g_assert (hashtable);
g_assert (child);
row_info = g_hash_table_lookup (hashtable, GINT_TO_POINTER (child->row));
if (row_info == NULL)
{
row_info = g_new0 (EggThreeGridRowInfo, 1);
row_info->row = child->row;
g_hash_table_insert (hashtable, GINT_TO_POINTER (child->row), row_info);
}
/*
* TODO:
*
* Allow setting baseline position per row. Right now we only support center
* because that is the easiest thing to start with.
*/
if (child->min_baseline == -1)
{
if (baseline_position == GTK_BASELINE_POSITION_CENTER)
{
current.min_above_baseline = current.min_below_baseline = ceil (child->min_height / 2.0);
current.nat_above_baseline = current.nat_below_baseline = ceil (child->min_height / 2.0);
}
else if (baseline_position == GTK_BASELINE_POSITION_TOP)
{
g_assert_not_reached ();
}
else if (baseline_position == GTK_BASELINE_POSITION_BOTTOM)
{
g_assert_not_reached ();
}
}
else
{
current.min_above_baseline = child->min_baseline;
current.min_below_baseline = child->min_height - child->min_baseline;
current.nat_above_baseline = child->nat_baseline;
current.nat_below_baseline = child->nat_height - child->nat_baseline;
}
row_info_merge (row_info, &current);
}
static void
get_preferred_height_for_width (EggThreeGridLayout *self,
GtkWidget *widget,
int width,
int *min_height,
int *nat_height)
{
g_autoptr(GHashTable) row_infos = NULL;
EggThreeGridRowInfo *row_info;
GHashTableIter hiter;
int real_min_height = 0;
int real_nat_height = 0;
int column_min_widths[3];
int column_nat_widths[3];
int widths[3];
int n_rows;
g_assert (EGG_IS_THREE_GRID_LAYOUT (self));
g_assert (min_height != NULL);
g_assert (nat_height != NULL);
width -= self->column_spacing * 2;
get_column_width (self, widget, EGG_THREE_GRID_COLUMN_LEFT, &column_min_widths[0], &column_nat_widths[0]);
get_column_width (self, widget, EGG_THREE_GRID_COLUMN_CENTER, &column_min_widths[1], &column_nat_widths[1]);
get_column_width (self, widget, EGG_THREE_GRID_COLUMN_RIGHT, &column_min_widths[2], &column_nat_widths[2]);
if ((MAX (column_min_widths[0], column_min_widths[2]) * 2 + column_nat_widths[1]) > width)
{
widths[0] = column_min_widths[0];
widths[2] = column_min_widths[2];
widths[1] = width - widths[0] - widths[2];
}
else
{
/* Handle #1 and #2 */
widths[1] = column_nat_widths[1];
widths[0] = (width - widths[1]) / 2;
widths[2] = width - widths[1] - widths[0];
}
row_infos = g_hash_table_new_full (NULL, NULL, NULL, g_free);
for (GtkWidget *iter = gtk_widget_get_first_child (widget);
iter;
iter = gtk_widget_get_next_sibling (iter))
{
EggThreeGridChild *child = EGG_THREE_GRID_CHILD (gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), iter));
if (!gtk_widget_get_visible (iter) || !gtk_widget_get_child_visible (iter))
continue;
gtk_widget_measure (iter, GTK_ORIENTATION_VERTICAL, MAX (0, widths[child->column]),
&child->min_height, &child->nat_height,
&child->min_baseline, &child->nat_baseline);
update_row_info (row_infos, child);
}
g_hash_table_iter_init (&hiter, row_infos);
while (g_hash_table_iter_next (&hiter, NULL, (gpointer *)&row_info))
{
real_min_height += row_info->min_above_baseline + row_info->min_below_baseline;
real_nat_height += row_info->nat_above_baseline + row_info->nat_below_baseline;
}
n_rows = g_hash_table_size (row_infos);
if (n_rows > 1)
{
real_min_height += (n_rows - 1) * self->row_spacing;
real_nat_height += (n_rows - 1) * self->row_spacing;
}
*min_height = real_min_height;
*nat_height = real_nat_height;
g_clear_pointer (&self->row_infos, g_hash_table_unref);
self->row_infos = g_steal_pointer (&row_infos);
}
static int
sort_by_row (gconstpointer a,
gconstpointer b)
{
const EggThreeGridRowInfo *info_a = a;
const EggThreeGridRowInfo *info_b = b;
return info_a->row - info_b->row;
}
static void
size_allocate_children (EggThreeGridLayout *self,
GtkWidget *widget,
EggThreeGridColumn column,
int row,
GtkAllocation *allocation,
int baseline)
{
g_assert (EGG_IS_THREE_GRID_LAYOUT (self));
g_assert (allocation != NULL);
for (GtkWidget *iter = gtk_widget_get_first_child (widget);
iter;
iter = gtk_widget_get_next_sibling (iter))
{
EggThreeGridChild *child = EGG_THREE_GRID_CHILD (gtk_layout_manager_get_layout_child (GTK_LAYOUT_MANAGER (self), iter));
if (child->row == row && child->column == column)
{
GtkAllocation copy = *allocation;
gtk_widget_size_allocate (iter, &copy, baseline);
}
}
}
static void
egg_three_grid_layout_allocate (GtkLayoutManager *manager,
GtkWidget *widget,
int width,
int height,
int baseline)
{
EggThreeGridLayout *self = (EggThreeGridLayout *)manager;
g_autofree GtkRequestedSize *rows = NULL;
const GList *iter;
GtkAllocation area;
GtkTextDirection dir;
GList *values;
guint i;
guint n_rows;
int min_height;
int nat_height;
int left_min_width;
int left_nat_width;
int center_min_width;
int center_nat_width;
int right_min_width;
int right_nat_width;
int left;
int center;
int right;
g_assert (EGG_IS_THREE_GRID_LAYOUT (self));
area.x = 0;
area.y = 0;
area.width = width;
area.height = height;
dir = gtk_widget_get_direction (widget);
get_preferred_height_for_width (self, widget, width, &min_height, &nat_height);
if (min_height > height)
g_warning ("%s requested a minimum height of %d and got %d",
G_OBJECT_TYPE_NAME (widget), min_height, height);
if (self->row_infos == NULL)
return;
values = g_hash_table_get_values (self->row_infos);
values = g_list_sort (values, sort_by_row);
get_column_width (self, widget, EGG_THREE_GRID_COLUMN_LEFT, &left_min_width, &left_nat_width);
get_column_width (self, widget, EGG_THREE_GRID_COLUMN_CENTER, &center_min_width, &center_nat_width);
get_column_width (self, widget, EGG_THREE_GRID_COLUMN_RIGHT, &right_min_width, &right_nat_width);
/*
* Determine how much to give to the center widget first. This is because we will
* just give the rest of the space on the sides to left/right columns and they
* can deal with alignment by using halign.
*
* We can be in one of a couple states:
*
* 1) There is enough room for all columns natural size.
* (We allocate the same to the left and the right).
* 2) There is enough for the natural size of the center
* but for some amount between natural and min sizing
* of the left/right columns.
* 3) There is only minimum size for columns and some
* amount between natural/minimum of the center.
*
* We can handle #1 and #2 with the same logic though.
*/
if ((MAX (left_min_width, right_min_width) * 2 + center_nat_width + 2 * self->column_spacing) > area.width)
{
/* Handle #3 */
left = right = MAX (left_min_width, right_min_width);
center = area.width - left - right - 2 * self->column_spacing;
}
else
{
/* Handle #1 and #2 */
center = center_nat_width;
right = left = (area.width - center) / 2 - self->column_spacing;
}
n_rows = g_list_length (values);
rows = g_new0 (GtkRequestedSize, n_rows);
for (iter = values, i = 0; iter != NULL; iter = iter->next, i++)
{
EggThreeGridRowInfo *row_info = iter->data;
rows[i].data = row_info;
rows[i].minimum_size = row_info->min_above_baseline + row_info->min_below_baseline;
rows[i].natural_size = row_info->nat_above_baseline + row_info->nat_below_baseline;
}
gtk_distribute_natural_allocation (area.height, n_rows, rows);
for (i = 0; i < n_rows; i++)
{
GtkRequestedSize *size = &rows[i];
EggThreeGridRowInfo *row_info = size->data;
GtkAllocation child_alloc;
int child_baseline;
if (row_info->nat_above_baseline + row_info->nat_below_baseline < size->minimum_size)
child_baseline = row_info->nat_above_baseline;
else
child_baseline = row_info->min_above_baseline;
child_alloc.x = area.x;
child_alloc.width = left;
child_alloc.y = area.y;
child_alloc.height = size->minimum_size;
if (dir == GTK_TEXT_DIR_LTR)
size_allocate_children (self, widget, EGG_THREE_GRID_COLUMN_LEFT, row_info->row, &child_alloc, child_baseline);
else
size_allocate_children (self, widget, EGG_THREE_GRID_COLUMN_RIGHT, row_info->row, &child_alloc, child_baseline);
child_alloc.x = area.x + left + self->column_spacing;
child_alloc.width = center;
child_alloc.y = area.y;
child_alloc.height = size->minimum_size;
size_allocate_children (self, widget, EGG_THREE_GRID_COLUMN_CENTER, row_info->row, &child_alloc, child_baseline);
child_alloc.x = area.x + area.width - right;
child_alloc.width = right;
child_alloc.y = area.y;
child_alloc.height = size->minimum_size;
if (dir == GTK_TEXT_DIR_LTR)
size_allocate_children (self, widget, EGG_THREE_GRID_COLUMN_RIGHT, row_info->row, &child_alloc, child_baseline);
else
size_allocate_children (self, widget, EGG_THREE_GRID_COLUMN_LEFT, row_info->row, &child_alloc, child_baseline);
area.y += child_alloc.height + self->row_spacing;
area.height -= child_alloc.height + self->row_spacing;
}
g_list_free (values);
}
static void
egg_three_grid_layout_measure (GtkLayoutManager *manager,
GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
EggThreeGridLayout *self = (EggThreeGridLayout *)manager;
g_assert (EGG_IS_THREE_GRID_LAYOUT (self));
*minimum_baseline = -1;
*natural_baseline = -1;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
get_preferred_width (self, widget, minimum, natural);
else
get_preferred_height_for_width (self, widget, for_size, minimum, natural);
}
static void
egg_three_grid_layout_dispose (GObject *object)
{
EggThreeGridLayout *self = (EggThreeGridLayout *)object;
g_clear_pointer (&self->row_infos, g_hash_table_unref);
G_OBJECT_CLASS (egg_three_grid_layout_parent_class)->dispose (object);
}
static void
egg_three_grid_layout_class_init (EggThreeGridLayoutClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (klass);
object_class->dispose = egg_three_grid_layout_dispose;
layout_class->get_request_mode = egg_three_grid_layout_get_request_mode;
layout_class->measure = egg_three_grid_layout_measure;
layout_class->allocate = egg_three_grid_layout_allocate;
layout_class->layout_child_type = EGG_TYPE_THREE_GRID_CHILD;
}
static void
egg_three_grid_layout_init (EggThreeGridLayout *self)
{
}
typedef struct
{
guint column_spacing;
guint row_spacing;
} EggThreeGridPrivate;
static void buildable_iface_init (GtkBuildableIface *iface);
G_DEFINE_TYPE_WITH_CODE (EggThreeGrid, egg_three_grid, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (EggThreeGrid)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init))
enum {
PROP_0,
PROP_COLUMN_SPACING,
PROP_ROW_SPACING,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
void
egg_three_grid_add (EggThreeGrid *self,
GtkWidget *widget,
guint row,
EggThreeGridColumn column)
{
g_assert (EGG_IS_THREE_GRID (self));
g_assert (GTK_IS_WIDGET (widget));
gtk_widget_set_parent (widget, GTK_WIDGET (self));
}
void
egg_three_grid_remove (EggThreeGrid *self,
GtkWidget *widget)
{
g_assert (EGG_IS_THREE_GRID (self));
g_assert (GTK_IS_WIDGET (widget));
gtk_widget_unparent (widget);
gtk_widget_queue_resize (GTK_WIDGET (self));
}
static void
egg_three_grid_dispose (GObject *object)
{
EggThreeGrid *self = (EggThreeGrid *)object;
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
egg_three_grid_remove (self, child);
G_OBJECT_CLASS (egg_three_grid_parent_class)->dispose (object);
}
static void
egg_three_grid_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EggThreeGrid *self = EGG_THREE_GRID (object);
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
switch (prop_id)
{
case PROP_COLUMN_SPACING:
g_value_set_uint (value, EGG_THREE_GRID_LAYOUT (manager)->column_spacing);
break;
case PROP_ROW_SPACING:
g_value_set_uint (value, EGG_THREE_GRID_LAYOUT (manager)->row_spacing);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_three_grid_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EggThreeGrid *self = EGG_THREE_GRID (object);
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
switch (prop_id)
{
case PROP_COLUMN_SPACING:
EGG_THREE_GRID_LAYOUT (manager)->column_spacing = g_value_get_uint (value);
gtk_widget_queue_resize (GTK_WIDGET (self));
break;
case PROP_ROW_SPACING:
EGG_THREE_GRID_LAYOUT (manager)->row_spacing = g_value_get_uint (value);
gtk_widget_queue_resize (GTK_WIDGET (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_three_grid_class_init (EggThreeGridClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = egg_three_grid_dispose;
object_class->get_property = egg_three_grid_get_property;
object_class->set_property = egg_three_grid_set_property;
properties [PROP_COLUMN_SPACING] =
g_param_spec_uint ("column-spacing",
"Column Spacing",
"The amount of spacing to add between columns",
0,
G_MAXUINT,
0,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties [PROP_ROW_SPACING] =
g_param_spec_uint ("row-spacing",
"Row Spacing",
"The amount of spacing to add between rows",
0,
G_MAXUINT,
0,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_css_name (widget_class, "threegrid");
gtk_widget_class_set_layout_manager_type (widget_class, EGG_TYPE_THREE_GRID_LAYOUT);
}
static void
egg_three_grid_init (EggThreeGrid *self)
{
}
GtkWidget *
egg_three_grid_new (void)
{
return g_object_new (EGG_TYPE_THREE_GRID, NULL);
}
GType
egg_three_grid_column_get_type (void)
{
static GType type_id;
if (g_once_init_enter (&type_id))
{
GType _type_id;
static const GEnumValue values[] = {
{ EGG_THREE_GRID_COLUMN_LEFT, "EGG_THREE_GRID_COLUMN_LEFT", "left" },
{ EGG_THREE_GRID_COLUMN_CENTER, "EGG_THREE_GRID_COLUMN_CENTER", "center" },
{ EGG_THREE_GRID_COLUMN_RIGHT, "EGG_THREE_GRID_COLUMN_RIGHT", "right" },
{ 0 }
};
_type_id = g_enum_register_static ("EggThreeGridColumn", values);
g_once_init_leave (&type_id, _type_id);
}
return type_id;
}
static void
egg_three_grid_add_child (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const char *type)
{
if (GTK_IS_WIDGET (child))
egg_three_grid_add (EGG_THREE_GRID (buildable), GTK_WIDGET (child), 0, EGG_THREE_GRID_COLUMN_LEFT);
else
g_warning ("%s cannot be added to %s", G_OBJECT_TYPE_NAME (child), G_OBJECT_TYPE_NAME (buildable));
}
static void
buildable_iface_init (GtkBuildableIface *iface)
{
iface->add_child = egg_three_grid_add_child;
}

View File

@ -0,0 +1,51 @@
/* egg-three-grid.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/>.
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define EGG_TYPE_THREE_GRID (egg_three_grid_get_type())
#define EGG_TYPE_THREE_GRID_COLUMN (egg_three_grid_column_get_type())
G_DECLARE_DERIVABLE_TYPE (EggThreeGrid, egg_three_grid, EGG, THREE_GRID, GtkWidget)
struct _EggThreeGridClass
{
GtkWidgetClass parent_class;
};
typedef enum
{
EGG_THREE_GRID_COLUMN_LEFT,
EGG_THREE_GRID_COLUMN_CENTER,
EGG_THREE_GRID_COLUMN_RIGHT
} EggThreeGridColumn;
GType egg_three_grid_column_get_type (void);
GtkWidget *egg_three_grid_new (void);
void egg_three_grid_add (EggThreeGrid *self,
GtkWidget *child,
guint row,
EggThreeGridColumn column);
void egg_three_grid_remove (EggThreeGrid *self,
GtkWidget *child);
G_END_DECLS

View File

@ -24,7 +24,6 @@
<file preprocess="xml-stripblanks">sysprof-profiler-assistant.ui</file> <file preprocess="xml-stripblanks">sysprof-profiler-assistant.ui</file>
<file preprocess="xml-stripblanks">sysprof-recording-state-view.ui</file> <file preprocess="xml-stripblanks">sysprof-recording-state-view.ui</file>
<file preprocess="xml-stripblanks">sysprof-tab.ui</file> <file preprocess="xml-stripblanks">sysprof-tab.ui</file>
<file preprocess="xml-stripblanks">sysprof-time-label.ui</file>
<file preprocess="xml-stripblanks">sysprof-visualizers-frame.ui</file> <file preprocess="xml-stripblanks">sysprof-visualizers-frame.ui</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@ -13,6 +13,11 @@ libsysprof_ui_public_sources = [
] ]
libsysprof_ui_private_sources = [ libsysprof_ui_private_sources = [
'egg-handle.c',
'egg-paned.c',
'egg-resizer.c',
'egg-three-grid.c',
'pointcache.c', 'pointcache.c',
'rectangles.c', 'rectangles.c',
'sysprof-aid.c', 'sysprof-aid.c',
@ -23,6 +28,7 @@ libsysprof_ui_private_sources = [
'sysprof-callgraph-page.c', 'sysprof-callgraph-page.c',
'sysprof-cell-renderer-duration.c', 'sysprof-cell-renderer-duration.c',
'sysprof-cell-renderer-percent.c', 'sysprof-cell-renderer-percent.c',
'sysprof-cell-renderer-progress.c',
'sysprof-color-cycle.c', 'sysprof-color-cycle.c',
'sysprof-counters-aid.c', 'sysprof-counters-aid.c',
'sysprof-cpu-aid.c', 'sysprof-cpu-aid.c',
@ -87,7 +93,8 @@ libsysprof_ui_resources = gnome.compile_resources(
# Subset of dependencies used in generating the pkg-config file # Subset of dependencies used in generating the pkg-config file
libsysprof_ui_pkg_deps = [ libsysprof_ui_pkg_deps = [
dependency('gio-2.0', version: glib_req_version), dependency('gio-2.0', version: glib_req_version),
dependency('gtk+-3.0', version: gtk_req_version), dependency('gtk4', version: gtk_req_version),
dependency('libadwaita-1'),
] ]
libsysprof_ui_deps = libsysprof_ui_pkg_deps + [ libsysprof_ui_deps = libsysprof_ui_pkg_deps + [
@ -98,15 +105,8 @@ libsysprof_ui_deps = libsysprof_ui_pkg_deps + [
# dependency object # dependency object
libsysprof_ui_pkg_deps += libsysprof libsysprof_ui_pkg_deps += libsysprof
dazzle_dep = dependency('libdazzle-1.0', version: dazzle_req_version, fallback: ['libdazzle', 'libdazzle_dep'])
libsysprof_ui_deps += dazzle_dep
if dazzle_dep.type_name() == 'pkgconfig'
libsysprof_ui_pkg_deps += dazzle_dep
endif
libsysprof_ui = shared_library( libsysprof_ui = shared_library(
'sysprof-ui-@0@'.format(libsysprof_api_version), 'sysprof-ui-@0@'.format(libsysprof_ui_api_version),
libsysprof_ui_public_sources + libsysprof_ui_private_sources + libsysprof_ui_resources, libsysprof_ui_public_sources + libsysprof_ui_private_sources + libsysprof_ui_resources,
dependencies: libsysprof_ui_deps + [librax_dep], dependencies: libsysprof_ui_deps + [librax_dep],
@ -124,16 +124,16 @@ libsysprof_ui_dep = declare_dependency(
pkgconfig.generate( pkgconfig.generate(
libsysprof_ui, libsysprof_ui,
subdirs: [ sysprof_header_subdir ], subdirs: [ sysprof_ui_header_subdir ],
description: 'The UI library for GTK applications embedding sysprof', description: 'The UI library for GTK applications embedding sysprof',
install_dir: join_paths(get_option('libdir'), 'pkgconfig'), install_dir: join_paths(get_option('libdir'), 'pkgconfig'),
requires: [ 'gio-2.0', 'gtk+-3.0' ], requires: [ 'gio-2.0', 'gtk4' ],
libraries_private: libsysprof_ui_pkg_deps, libraries_private: libsysprof_ui_pkg_deps,
variables: [ variables: [
'datadir=' + datadir_for_pc_file, 'datadir=' + datadir_for_pc_file,
], ],
) )
install_headers(libsysprof_ui_public_headers, subdir: sysprof_header_subdir) install_headers(libsysprof_ui_public_headers, subdir: sysprof_ui_header_subdir)
endif endif

View File

@ -1,32 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface> <interface>
<requires lib="gtk+" version="3.12"/> <requires lib="gtk" version="4.0"/>
<template class="SysprofAidIcon" parent="GtkFlowBoxChild"> <template class="SysprofAidIcon" parent="GtkFlowBoxChild">
<property name="can_focus">False</property> <property name="child">
<child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">6</property> <property name="spacing">6</property>
<child> <child>
<object class="GtkOverlay"> <object class="GtkOverlay">
<property name="halign">center</property> <property name="halign">center</property>
<property name="visible">true</property> <property name="child">
<child>
<object class="GtkImage" id="image"> <object class="GtkImage" id="image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">64</property> <property name="pixel_size">64</property>
<property name="width-request">92</property> <property name="width-request">92</property>
<property name="icon_name">org.gnome.Sysprof-symbolic</property> <property name="icon_name">org.gnome.Sysprof-symbolic</property>
</object> </object>
</child> </property>
<child type="overlay"> <child type="overlay">
<object class="GtkImage" id="check"> <object class="GtkImage" id="check">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">16</property> <property name="pixel_size">16</property>
<property name="icon_name">object-select-symbolic</property> <property name="icon_name">object-select-symbolic</property>
<property name="halign">end</property> <property name="halign">end</property>
@ -34,29 +25,17 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label"> <object class="GtkLabel" id="label">
<property name="visible">True</property> <property name="use_underline">1</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
<property name="justify">center</property> <property name="justify">center</property>
<property name="wrap">True</property> <property name="wrap">1</property>
<property name="mnemonic_widget">SysprofAidIcon</property> <property name="mnemonic_widget">SysprofAidIcon</property>
<property name="max_width_chars">12</property> <property name="max_width_chars">12</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
</object> </object>
</child> </property>
</template> </template>
</interface> </interface>

View File

@ -218,7 +218,7 @@ sysprof_battery_aid_present_finish (SysprofAid *aid,
if (found > 0) if (found > 0)
sysprof_display_add_group (present->display, group); sysprof_display_add_group (present->display, group);
else else
gtk_widget_destroy (GTK_WIDGET (group)); g_object_unref (g_object_ref_sink (group));
} }
return counters != NULL; return counters != NULL;

View File

@ -39,11 +39,12 @@
#include "config.h" #include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "../stackstash.h" #include "../stackstash.h"
#include "egg-paned-private.h"
#include "sysprof-callgraph-page.h" #include "sysprof-callgraph-page.h"
#include "sysprof-cell-renderer-percent.h" #include "sysprof-cell-renderer-percent.h"
@ -56,6 +57,9 @@ typedef struct
GtkTreeView *descendants_view; GtkTreeView *descendants_view;
GtkTreeViewColumn *descendants_name_column; GtkTreeViewColumn *descendants_name_column;
GtkStack *stack; GtkStack *stack;
GtkWidget *empty_state;
GtkWidget *loading_state;
GtkWidget *callgraph;
GQueue *history; GQueue *history;
@ -208,7 +212,7 @@ sysprof_callgraph_page_load (SysprofCallgraphPage *self,
gtk_tree_selection_select_iter (selection, &iter); gtk_tree_selection_select_iter (selection, &iter);
} }
gtk_stack_set_visible_child_name (priv->stack, "callgraph"); gtk_stack_set_visible_child (priv->stack, priv->callgraph);
g_clear_object (&functions); g_clear_object (&functions);
} }
@ -220,7 +224,7 @@ _sysprof_callgraph_page_set_failed (SysprofCallgraphPage *self)
g_return_if_fail (SYSPROF_IS_CALLGRAPH_PAGE (self)); g_return_if_fail (SYSPROF_IS_CALLGRAPH_PAGE (self));
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, priv->empty_state);
} }
static void static void
@ -239,7 +243,7 @@ sysprof_callgraph_page_unload (SysprofCallgraphPage *self)
gtk_tree_view_set_model (priv->functions_view, NULL); gtk_tree_view_set_model (priv->functions_view, NULL);
gtk_tree_view_set_model (priv->descendants_view, NULL); gtk_tree_view_set_model (priv->descendants_view, NULL);
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, priv->empty_state);
} }
/** /**
@ -664,10 +668,12 @@ sysprof_callgraph_page_real_go_previous (SysprofCallgraphPage *self)
sysprof_callgraph_page_set_node (self, node); sysprof_callgraph_page_set_node (self, node);
} }
static void static gboolean
descendants_view_move_cursor_cb (GtkTreeView *descendants_view, descendants_view_move_cursor_cb (GtkTreeView *descendants_view,
GtkMovementStep step, GtkMovementStep step,
int direction, int direction,
gboolean extend,
gboolean modify,
gpointer user_data) gpointer user_data)
{ {
if (step == GTK_MOVEMENT_VISUAL_POSITIONS) if (step == GTK_MOVEMENT_VISUAL_POSITIONS)
@ -680,15 +686,19 @@ descendants_view_move_cursor_cb (GtkTreeView *descendants_view,
{ {
gtk_tree_view_expand_row (descendants_view, path, FALSE); gtk_tree_view_expand_row (descendants_view, path, FALSE);
g_signal_stop_emission_by_name (descendants_view, "move-cursor"); g_signal_stop_emission_by_name (descendants_view, "move-cursor");
return FALSE;
} }
else if (direction == -1) else if (direction == -1)
{ {
gtk_tree_view_collapse_row (descendants_view, path); gtk_tree_view_collapse_row (descendants_view, path);
g_signal_stop_emission_by_name (descendants_view, "move-cursor"); g_signal_stop_emission_by_name (descendants_view, "move-cursor");
return FALSE;
} }
gtk_tree_path_free (path); gtk_tree_path_free (path);
} }
return TRUE;
} }
static void static void
@ -732,7 +742,7 @@ static void
copy_tree_view_selection (GtkTreeView *tree_view) copy_tree_view_selection (GtkTreeView *tree_view)
{ {
g_autoptr(GString) str = NULL; g_autoptr(GString) str = NULL;
GtkClipboard *clipboard; GdkClipboard *clipboard;
g_assert (GTK_IS_TREE_VIEW (tree_view)); g_assert (GTK_IS_TREE_VIEW (tree_view));
@ -741,24 +751,26 @@ copy_tree_view_selection (GtkTreeView *tree_view)
copy_tree_view_selection_cb, copy_tree_view_selection_cb,
str); str);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view), GDK_SELECTION_CLIPBOARD); clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view));
gtk_clipboard_set_text (clipboard, str->str, str->len); gdk_clipboard_set_text (clipboard, str->str);
} }
static void static void
sysprof_callgraph_page_copy_cb (GtkWidget *widget, sysprof_callgraph_page_copy_cb (GtkWidget *widget,
SysprofCallgraphPage *self) const char *action_name,
GVariant *param)
{ {
SysprofCallgraphPage *self = (SysprofCallgraphPage *)widget;
SysprofCallgraphPagePrivate *priv = sysprof_callgraph_page_get_instance_private (self); SysprofCallgraphPagePrivate *priv = sysprof_callgraph_page_get_instance_private (self);
GtkWidget *toplevel; GtkRoot *toplevel;
GtkWidget *focus; GtkWidget *focus;
g_assert (GTK_IS_WIDGET (widget)); g_assert (GTK_IS_WIDGET (widget));
g_assert (SYSPROF_IS_CALLGRAPH_PAGE (self)); g_assert (SYSPROF_IS_CALLGRAPH_PAGE (self));
if (!(toplevel = gtk_widget_get_toplevel (widget)) || if (!(toplevel = gtk_widget_get_root (widget)) ||
!GTK_IS_WINDOW (toplevel) || !GTK_IS_ROOT (toplevel) ||
!(focus = gtk_window_get_focus (GTK_WINDOW (toplevel)))) !(focus = gtk_root_get_focus (toplevel)))
return; return;
if (focus == GTK_WIDGET (priv->descendants_view)) if (focus == GTK_WIDGET (priv->descendants_view))
@ -891,7 +903,6 @@ sysprof_callgraph_page_class_init (SysprofCallgraphPageClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass); SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass);
GtkBindingSet *bindings;
object_class->finalize = sysprof_callgraph_page_finalize; object_class->finalize = sysprof_callgraph_page_finalize;
object_class->get_property = sysprof_callgraph_page_get_property; object_class->get_property = sysprof_callgraph_page_get_property;
@ -926,10 +937,16 @@ sysprof_callgraph_page_class_init (SysprofCallgraphPageClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, descendants_view); gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, descendants_view);
gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, descendants_name_column); gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, descendants_name_column);
gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, stack); gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, stack);
gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, callgraph);
gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, empty_state);
gtk_widget_class_bind_template_child_private (widget_class, SysprofCallgraphPage, loading_state);
bindings = gtk_binding_set_by_class (klass); gtk_widget_class_install_action (widget_class, "page.copy", NULL, sysprof_callgraph_page_copy_cb);
gtk_binding_entry_add_signal (bindings, GDK_KEY_Left, GDK_MOD1_MASK, "go-previous", 0);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_c, GDK_CONTROL_MASK, "page.copy", NULL);
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Left, GDK_ALT_MASK, "go-previous", NULL);
g_type_ensure (EGG_TYPE_PANED);
g_type_ensure (SYSPROF_TYPE_CELL_RENDERER_PERCENT); g_type_ensure (SYSPROF_TYPE_CELL_RENDERER_PERCENT);
} }
@ -937,7 +954,6 @@ static void
sysprof_callgraph_page_init (SysprofCallgraphPage *self) sysprof_callgraph_page_init (SysprofCallgraphPage *self)
{ {
SysprofCallgraphPagePrivate *priv = sysprof_callgraph_page_get_instance_private (self); SysprofCallgraphPagePrivate *priv = sysprof_callgraph_page_get_instance_private (self);
DzlShortcutController *controller;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkCellRenderer *cell; GtkCellRenderer *cell;
@ -945,7 +961,7 @@ sysprof_callgraph_page_init (SysprofCallgraphPage *self)
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, priv->loading_state);
selection = gtk_tree_view_get_selection (priv->functions_view); selection = gtk_tree_view_get_selection (priv->functions_view);
@ -991,16 +1007,6 @@ sysprof_callgraph_page_init (SysprofCallgraphPage *self)
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->descendants_view), gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->descendants_view),
GTK_SELECTION_MULTIPLE); GTK_SELECTION_MULTIPLE);
controller = dzl_shortcut_controller_find (GTK_WIDGET (self));
dzl_shortcut_controller_add_command_callback (controller,
"org.gnome.sysprof3.capture.copy",
"<Control>c",
DZL_SHORTCUT_PHASE_BUBBLE,
(GtkCallback) sysprof_callgraph_page_copy_cb,
self,
NULL);
} }
typedef struct _Descendant Descendant; typedef struct _Descendant Descendant;
@ -1287,7 +1293,7 @@ _sysprof_callgraph_page_set_loading (SysprofCallgraphPage *self,
priv->loading--; priv->loading--;
if (priv->loading) if (priv->loading)
gtk_stack_set_visible_child_name (priv->stack, "loading"); gtk_stack_set_visible_child (priv->stack, priv->loading_state);
else else
gtk_stack_set_visible_child_name (priv->stack, "callgraph"); gtk_stack_set_visible_child (priv->stack, priv->callgraph);
} }

View File

@ -2,23 +2,19 @@
<template class="SysprofCallgraphPage" parent="SysprofPage"> <template class="SysprofCallgraphPage" parent="SysprofPage">
<child> <child>
<object class="GtkStack" id="stack"> <object class="GtkStack" id="stack">
<property name="visible">true</property>
<child> <child>
<object class="GtkPaned"> <object class="EggPaned" id="callgraph">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="position">450</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkPaned"> <object class="EggPaned">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property> <property name="width-request">400</property>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">true</property> <property name="vexpand">true</property>
<child> <child>
<object class="GtkTreeView" id="functions_view"> <object class="GtkTreeView" id="functions_view">
<property name="fixed-height-mode">true</property> <property name="fixed-height-mode">true</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="function_name_column"> <object class="GtkTreeViewColumn" id="function_name_column">
<property name="expand">true</property> <property name="expand">true</property>
@ -70,16 +66,12 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="resize">true</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">true</property> <property name="vexpand">true</property>
<child> <child>
<object class="GtkTreeView" id="callers_view"> <object class="GtkTreeView" id="callers_view">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="callers_name_column"> <object class="GtkTreeViewColumn" id="callers_name_column">
<property name="expand">true</property> <property name="expand">true</property>
@ -131,18 +123,14 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="resize">true</property>
</packing>
</child> </child>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">true</property> <property name="hexpand">true</property>
<child> <child>
<object class="GtkTreeView" id="descendants_view"> <object class="GtkTreeView" id="descendants_view">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="descendants_name_column"> <object class="GtkTreeViewColumn" id="descendants_name_column">
<property name="expand">true</property> <property name="expand">true</property>
@ -203,31 +191,20 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="name">callgraph</property>
</packing>
</child> </child>
<child> <child>
<object class="DzlEmptyState"> <object class="AdwStatusPage" id="loading_state">
<property name="icon-name">content-loading-symbolic</property> <property name="icon-name">content-loading-symbolic</property>
<property name="title" translatable="yes">Generating Callgraph</property> <property name="title" translatable="yes">Generating Callgraph</property>
<property name="subtitle" translatable="yes">Sysprof is busy creating the selected callgraph.</property> <property name="description" translatable="yes">Sysprof is busy creating the selected callgraph.</property>
<property name="visible">true</property>
</object> </object>
<packing>
<property name="name">loading</property>
</packing>
</child> </child>
<child> <child>
<object class="DzlEmptyState"> <object class="AdwStatusPage" id="empty_state">
<property name="icon-name">computer-fail-symbolic</property> <property name="icon-name">computer-fail-symbolic</property>
<property name="title" translatable="yes">Not Enough Samples</property> <property name="title" translatable="yes">Not Enough Samples</property>
<property name="subtitle" translatable="yes">More samples are necessary to display a callgraph.</property> <property name="description" translatable="yes">More samples are necessary to display a callgraph.</property>
<property name="visible">false</property>
</object> </object>
<packing>
<property name="name">empty-state</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -55,38 +55,87 @@ G_DEFINE_TYPE_WITH_PRIVATE (SysprofCellRendererDuration, sysprof_cell_renderer_d
static GParamSpec *properties [N_PROPS]; static GParamSpec *properties [N_PROPS];
static inline void
rounded_rectangle (cairo_t *cr,
const GdkRectangle *rect,
int x_radius,
int y_radius)
{
int x;
int y;
int width;
int height;
int x1, x2;
int y1, y2;
int xr1, xr2;
int yr1, yr2;
g_assert (cr);
g_assert (rect);
x = rect->x;
y = rect->y;
width = rect->width;
height = rect->height;
x1 = x;
x2 = x1 + width;
y1 = y;
y2 = y1 + height;
x_radius = MIN (x_radius, width / 2.0);
y_radius = MIN (y_radius, width / 2.0);
xr1 = x_radius;
xr2 = x_radius / 2.0;
yr1 = y_radius;
yr2 = y_radius / 2.0;
cairo_move_to (cr, x1 + xr1, y1);
cairo_line_to (cr, x2 - xr1, y1);
cairo_curve_to (cr, x2 - xr2, y1, x2, y1 + yr2, x2, y1 + yr1);
cairo_line_to (cr, x2, y2 - yr1);
cairo_curve_to (cr, x2, y2 - yr2, x2 - xr2, y2, x2 - xr1, y2);
cairo_line_to (cr, x1 + xr1, y2);
cairo_curve_to (cr, x1 + xr2, y2, x1, y2 - yr2, x1, y2 - yr1);
cairo_line_to (cr, x1, y1 + yr1);
cairo_curve_to (cr, x1, y1 + yr2, x1 + xr2, y1, x1 + xr1, y1);
cairo_close_path (cr);
}
static void static void
sysprof_cell_renderer_duration_render (GtkCellRenderer *renderer, sysprof_cell_renderer_duration_snapshot (GtkCellRenderer *renderer,
cairo_t *cr, GtkSnapshot *snapshot,
GtkWidget *widget, GtkWidget *widget,
const GdkRectangle *bg_area, const GdkRectangle *bg_area,
const GdkRectangle *cell_area, const GdkRectangle *cell_area,
GtkCellRendererState state) GtkCellRendererState state)
{ {
SysprofCellRendererDuration *self = (SysprofCellRendererDuration *)renderer; SysprofCellRendererDuration *self = (SysprofCellRendererDuration *)renderer;
SysprofCellRendererDurationPrivate *priv = sysprof_cell_renderer_duration_get_instance_private (self); SysprofCellRendererDurationPrivate *priv = sysprof_cell_renderer_duration_get_instance_private (self);
g_autoptr(GString) str = NULL; g_autoptr(GString) str = NULL;
GtkStyleContext *style_context; GtkStyleContext *style_context;
cairo_t *cr;
gdouble x1, x2; gdouble x1, x2;
GdkRGBA rgba; GdkRGBA rgba;
GdkRectangle r; GdkRectangle r;
gint64 duration; gint64 duration;
g_assert (SYSPROF_IS_CELL_RENDERER_DURATION (self)); g_assert (SYSPROF_IS_CELL_RENDERER_DURATION (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
g_assert (GTK_IS_WIDGET (widget)); g_assert (GTK_IS_WIDGET (widget));
if (priv->zoom_manager == NULL) if (priv->zoom_manager == NULL)
return; return;
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (cell_area->x, cell_area->y, cell_area->width, cell_area->height));
style_context = gtk_widget_get_style_context (widget); style_context = gtk_widget_get_style_context (widget);
if (priv->color_set) if (priv->color_set)
rgba = priv->color; rgba = priv->color;
else else
gtk_style_context_get_color (style_context, gtk_style_context_get_color (style_context, &rgba);
gtk_style_context_get_state (style_context),
&rgba);
duration = sysprof_zoom_manager_get_duration_for_width (priv->zoom_manager, bg_area->width); duration = sysprof_zoom_manager_get_duration_for_width (priv->zoom_manager, bg_area->width);
@ -108,7 +157,7 @@ sysprof_cell_renderer_duration_render (GtkCellRenderer *renderer,
if (r.width > 3) if (r.width > 3)
{ {
dzl_cairo_rounded_rectangle (cr, &r, 2, 2); rounded_rectangle (cr, &r, 2, 2);
cairo_fill (cr); cairo_fill (cr);
} }
else if (r.width > 1) else if (r.width > 1)
@ -166,6 +215,8 @@ sysprof_cell_renderer_duration_render (GtkCellRenderer *renderer,
g_object_unref (layout); g_object_unref (layout);
} }
cairo_destroy (cr);
} }
static GtkSizeRequestMode static GtkSizeRequestMode
@ -342,7 +393,7 @@ sysprof_cell_renderer_duration_class_init (SysprofCellRendererDurationClass *kla
cell_class->get_preferred_height_for_width = sysprof_cell_renderer_duration_get_preferred_height_for_width; cell_class->get_preferred_height_for_width = sysprof_cell_renderer_duration_get_preferred_height_for_width;
cell_class->get_preferred_width = sysprof_cell_renderer_duration_get_preferred_width; cell_class->get_preferred_width = sysprof_cell_renderer_duration_get_preferred_width;
cell_class->get_request_mode = sysprof_cell_renderer_duration_get_request_mode; cell_class->get_request_mode = sysprof_cell_renderer_duration_get_request_mode;
cell_class->render = sysprof_cell_renderer_duration_render; cell_class->snapshot = sysprof_cell_renderer_duration_snapshot;
/* Note we do not emit ::notify() for these properties */ /* Note we do not emit ::notify() for these properties */

View File

@ -37,7 +37,7 @@ enum {
N_PROPS N_PROPS
}; };
G_DEFINE_TYPE_WITH_PRIVATE (SysprofCellRendererPercent, sysprof_cell_renderer_percent, GTK_TYPE_CELL_RENDERER_PROGRESS) G_DEFINE_TYPE_WITH_PRIVATE (SysprofCellRendererPercent, sysprof_cell_renderer_percent, SYSPROF_TYPE_CELL_RENDERER_PROGRESS)
static GParamSpec *properties [N_PROPS]; static GParamSpec *properties [N_PROPS];

View File

@ -20,7 +20,7 @@
#pragma once #pragma once
#include <gtk/gtk.h> #include "sysprof-cell-renderer-progress.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -37,12 +37,12 @@ typedef struct _SysprofCellRendererPercentClass SysprofCellRendererPercentClass;
struct _SysprofCellRendererPercent struct _SysprofCellRendererPercent
{ {
GtkCellRendererProgress parent; SysprofCellRendererProgress parent;
}; };
struct _SysprofCellRendererPercentClass struct _SysprofCellRendererPercentClass
{ {
GtkCellRendererProgressClass parent_class; SysprofCellRendererProgressClass parent_class;
/*< private >*/ /*< private >*/
gpointer _reserved[4]; gpointer _reserved[4];

View File

@ -0,0 +1,712 @@
/* gtkcellrendererprogress.c
* Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
* heavily modified by Jörgen Scheibengruber <mfcn@gmx.de>
* heavily modified by Marco Pesenti Gritti <marco@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2007. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <stdlib.h>
#include "sysprof-cell-renderer-progress.h"
enum
{
PROP_0,
PROP_VALUE,
PROP_TEXT,
PROP_PULSE,
PROP_TEXT_XALIGN,
PROP_TEXT_YALIGN,
PROP_ORIENTATION,
PROP_INVERTED
};
struct _SysprofCellRendererProgressPrivate
{
int value;
char *text;
char *label;
int min_h;
int min_w;
int pulse;
int offset;
float text_xalign;
float text_yalign;
GtkOrientation orientation;
gboolean inverted;
};
static void sysprof_cell_renderer_progress_finalize (GObject *object);
static void sysprof_cell_renderer_progress_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec);
static void sysprof_cell_renderer_progress_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec);
static void sysprof_cell_renderer_progress_set_value (SysprofCellRendererProgress *cellprogress,
int value);
static void sysprof_cell_renderer_progress_set_text (SysprofCellRendererProgress *cellprogress,
const char *text);
static void sysprof_cell_renderer_progress_set_pulse (SysprofCellRendererProgress *cellprogress,
int pulse);
static void compute_dimensions (GtkCellRenderer *cell,
GtkWidget *widget,
const char *text,
int *width,
int *height);
static void sysprof_cell_renderer_progress_snapshot (GtkCellRenderer *cell,
GtkSnapshot *snapshot,
GtkWidget *widget,
const GdkRectangle *background_area,
const GdkRectangle *cell_area,
GtkCellRendererState flags);
G_DEFINE_TYPE_WITH_CODE (SysprofCellRendererProgress, sysprof_cell_renderer_progress, GTK_TYPE_CELL_RENDERER,
G_ADD_PRIVATE (SysprofCellRendererProgress)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
static void
recompute_label (SysprofCellRendererProgress *cellprogress)
{
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
char *label;
if (priv->text)
label = g_strdup (priv->text);
else if (priv->pulse < 0)
label = g_strdup_printf (C_("progress bar label", "%d%%"), priv->value);
else
label = NULL;
g_free (priv->label);
priv->label = label;
}
static void
sysprof_cell_renderer_progress_set_value (SysprofCellRendererProgress *cellprogress,
int value)
{
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
if (priv->value != value)
{
priv->value = value;
recompute_label (cellprogress);
g_object_notify (G_OBJECT (cellprogress), "value");
}
}
static void
sysprof_cell_renderer_progress_set_text (SysprofCellRendererProgress *cellprogress,
const char *text)
{
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
char *new_text;
new_text = g_strdup (text);
g_free (priv->text);
priv->text = new_text;
recompute_label (cellprogress);
g_object_notify (G_OBJECT (cellprogress), "text");
}
static void
sysprof_cell_renderer_progress_set_pulse (SysprofCellRendererProgress *cellprogress,
int pulse)
{
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
if (pulse != priv->pulse)
{
if (pulse <= 0)
priv->offset = 0;
else
priv->offset = pulse;
g_object_notify (G_OBJECT (cellprogress), "pulse");
}
priv->pulse = pulse;
recompute_label (cellprogress);
}
static void
sysprof_cell_renderer_progress_finalize (GObject *object)
{
SysprofCellRendererProgress *cellprogress = SYSPROF_CELL_RENDERER_PROGRESS (object);
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
g_free (priv->text);
g_free (priv->label);
G_OBJECT_CLASS (sysprof_cell_renderer_progress_parent_class)->finalize (object);
}
static void
sysprof_cell_renderer_progress_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
SysprofCellRendererProgress *cellprogress = SYSPROF_CELL_RENDERER_PROGRESS (object);
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
switch (param_id)
{
case PROP_VALUE:
g_value_set_int (value, priv->value);
break;
case PROP_TEXT:
g_value_set_string (value, priv->text);
break;
case PROP_PULSE:
g_value_set_int (value, priv->pulse);
break;
case PROP_TEXT_XALIGN:
g_value_set_float (value, priv->text_xalign);
break;
case PROP_TEXT_YALIGN:
g_value_set_float (value, priv->text_yalign);
break;
case PROP_ORIENTATION:
g_value_set_enum (value, priv->orientation);
break;
case PROP_INVERTED:
g_value_set_boolean (value, priv->inverted);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
sysprof_cell_renderer_progress_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
SysprofCellRendererProgress *cellprogress = SYSPROF_CELL_RENDERER_PROGRESS (object);
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
switch (param_id)
{
case PROP_VALUE:
sysprof_cell_renderer_progress_set_value (cellprogress,
g_value_get_int (value));
break;
case PROP_TEXT:
sysprof_cell_renderer_progress_set_text (cellprogress,
g_value_get_string (value));
break;
case PROP_PULSE:
sysprof_cell_renderer_progress_set_pulse (cellprogress,
g_value_get_int (value));
break;
case PROP_TEXT_XALIGN:
priv->text_xalign = g_value_get_float (value);
break;
case PROP_TEXT_YALIGN:
priv->text_yalign = g_value_get_float (value);
break;
case PROP_ORIENTATION:
if (priv->orientation != g_value_get_enum (value))
{
priv->orientation = g_value_get_enum (value);
g_object_notify_by_pspec (object, pspec);
}
break;
case PROP_INVERTED:
if (priv->inverted != g_value_get_boolean (value))
{
priv->inverted = g_value_get_boolean (value);
g_object_notify_by_pspec (object, pspec);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
compute_dimensions (GtkCellRenderer *cell,
GtkWidget *widget,
const char *text,
int *width,
int *height)
{
PangoRectangle logical_rect;
PangoLayout *layout;
int xpad, ypad;
layout = gtk_widget_create_pango_layout (widget, text);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
if (width)
*width = logical_rect.width + xpad * 2;
if (height)
*height = logical_rect.height + ypad * 2;
g_object_unref (layout);
}
static void
sysprof_cell_renderer_progress_get_preferred_width (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
SysprofCellRendererProgress *self = SYSPROF_CELL_RENDERER_PROGRESS (cell);
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (self);
int w, h;
int size;
if (priv->min_w < 0)
{
char *text = g_strdup_printf (C_("progress bar label", "%d%%"), 100);
compute_dimensions (cell, widget, text,
&priv->min_w,
&priv->min_h);
g_free (text);
}
compute_dimensions (cell, widget, priv->label, &w, &h);
size = MAX (priv->min_w, w);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static void
sysprof_cell_renderer_progress_get_preferred_height (GtkCellRenderer *cell,
GtkWidget *widget,
int *minimum,
int *natural)
{
SysprofCellRendererProgress *self = SYSPROF_CELL_RENDERER_PROGRESS (cell);
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (self);
int w, h;
int size;
if (priv->min_w < 0)
{
char *text = g_strdup_printf (C_("progress bar label", "%d%%"), 100);
compute_dimensions (cell, widget, text,
&priv->min_w,
&priv->min_h);
g_free (text);
}
compute_dimensions (cell, widget, priv->label, &w, &h);
size = MIN (priv->min_h, h);
if (minimum != NULL)
*minimum = size;
if (natural != NULL)
*natural = size;
}
static inline int
get_bar_size (int pulse,
int value,
int full_size)
{
int bar_size;
if (pulse < 0)
bar_size = full_size * MAX (0, value) / 100;
else if (pulse == 0)
bar_size = 0;
else if (pulse == G_MAXINT)
bar_size = full_size;
else
bar_size = MAX (2, full_size / 5);
return bar_size;
}
static inline int
get_bar_position (int start,
int full_size,
int bar_size,
int pulse,
int offset,
gboolean is_rtl)
{
int position;
if (pulse < 0 || pulse == 0 || pulse == G_MAXINT)
{
position = is_rtl ? (start + full_size - bar_size) : start;
}
else
{
position = (is_rtl ? offset + 12 : offset) % 24;
if (position > 12)
position = 24 - position;
position = start + full_size * position / 15;
}
return position;
}
static void
sysprof_cell_renderer_progress_snapshot (GtkCellRenderer *cell,
GtkSnapshot *snapshot,
GtkWidget *widget,
const GdkRectangle *background_area,
const GdkRectangle *cell_area,
GtkCellRendererState flags)
{
SysprofCellRendererProgress *cellprogress = SYSPROF_CELL_RENDERER_PROGRESS (cell);
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
GtkStyleContext *context;
GtkBorder padding;
PangoLayout *layout;
PangoRectangle logical_rect;
int x, y, w, h, x_pos, y_pos, bar_position, bar_size, start, full_size;
int xpad, ypad;
GdkRectangle clip;
gboolean is_rtl;
context = gtk_widget_get_style_context (widget);
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
x = cell_area->x + xpad;
y = cell_area->y + ypad;
w = cell_area->width - xpad * 2;
h = cell_area->height - ypad * 2;
gtk_style_context_save (context);
gtk_style_context_add_class (context, "trough");
gtk_snapshot_render_background (snapshot, context, x, y, w, h);
gtk_snapshot_render_frame (snapshot, context, x, y, w, h);
gtk_style_context_get_padding (context, &padding);
x += padding.left;
y += padding.top;
w -= padding.left + padding.right;
h -= padding.top + padding.bottom;
gtk_style_context_restore (context);
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
clip.y = y;
clip.height = h;
start = x;
full_size = w;
bar_size = get_bar_size (priv->pulse, priv->value, full_size);
if (!priv->inverted)
bar_position = get_bar_position (start, full_size, bar_size,
priv->pulse, priv->offset, is_rtl);
else
bar_position = get_bar_position (start, full_size, bar_size,
priv->pulse, priv->offset, !is_rtl);
clip.width = bar_size;
clip.x = bar_position;
}
else
{
clip.x = x;
clip.width = w;
start = y;
full_size = h;
bar_size = get_bar_size (priv->pulse, priv->value, full_size);
if (priv->inverted)
bar_position = get_bar_position (start, full_size, bar_size,
priv->pulse, priv->offset, TRUE);
else
bar_position = get_bar_position (start, full_size, bar_size,
priv->pulse, priv->offset, FALSE);
clip.height = bar_size;
clip.y = bar_position;
}
if (bar_size > 0)
{
gtk_style_context_save (context);
gtk_style_context_add_class (context, "progressbar");
gtk_snapshot_render_background (snapshot, context, clip.x, clip.y, clip.width, clip.height);
gtk_snapshot_render_frame (snapshot, context, clip.x, clip.y, clip.width, clip.height);
gtk_style_context_restore (context);
}
if (priv->label)
{
float text_xalign;
layout = gtk_widget_create_pango_layout (widget, priv->label);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
text_xalign = 1.0 - priv->text_xalign;
else
text_xalign = priv->text_xalign;
x_pos = x + padding.left + text_xalign *
(w - padding.left - padding.right - logical_rect.width);
y_pos = y + padding.top + priv->text_yalign *
(h - padding.top - padding.bottom - logical_rect.height);
gtk_snapshot_push_clip (snapshot,
&GRAPHENE_RECT_INIT(
clip.x, clip.y,
clip.width, clip.height
));
gtk_style_context_save (context);
gtk_style_context_add_class (context, "progressbar");
gtk_snapshot_render_layout (snapshot, context,
x_pos, y_pos,
layout);
gtk_style_context_restore (context);
gtk_snapshot_pop (snapshot);
gtk_style_context_save (context);
gtk_style_context_add_class (context, "trough");
if (bar_position > start)
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
clip.x = x;
clip.width = bar_position - x;
}
else
{
clip.y = y;
clip.height = bar_position - y;
}
gtk_snapshot_push_clip (snapshot,
&GRAPHENE_RECT_INIT(
clip.x, clip.y,
clip.width, clip.height
));
gtk_snapshot_render_layout (snapshot, context,
x_pos, y_pos,
layout);
gtk_snapshot_pop (snapshot);
}
if (bar_position + bar_size < start + full_size)
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
clip.x = bar_position + bar_size;
clip.width = x + w - (bar_position + bar_size);
}
else
{
clip.y = bar_position + bar_size;
clip.height = y + h - (bar_position + bar_size);
}
gtk_snapshot_push_clip (snapshot,
&GRAPHENE_RECT_INIT(
clip.x, clip.y,
clip.width, clip.height
));
gtk_snapshot_render_layout (snapshot, context,
x_pos, y_pos,
layout);
gtk_snapshot_pop (snapshot);
}
gtk_style_context_restore (context);
g_object_unref (layout);
}
}
static void
sysprof_cell_renderer_progress_class_init (SysprofCellRendererProgressClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
object_class->finalize = sysprof_cell_renderer_progress_finalize;
object_class->get_property = sysprof_cell_renderer_progress_get_property;
object_class->set_property = sysprof_cell_renderer_progress_set_property;
cell_class->get_preferred_width = sysprof_cell_renderer_progress_get_preferred_width;
cell_class->get_preferred_height = sysprof_cell_renderer_progress_get_preferred_height;
cell_class->snapshot = sysprof_cell_renderer_progress_snapshot;
/**
* SysprofCellRendererProgress:value:
*
* The "value" property determines the percentage to which the
* progress bar will be "filled in".
**/
g_object_class_install_property (object_class,
PROP_VALUE,
g_param_spec_int ("value",
"Value",
"Value of the progress bar",
0, 100, 0,
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
/**
* SysprofCellRendererProgress:text:
*
* The "text" property determines the label which will be drawn
* over the progress bar. Setting this property to %NULL causes the default
* label to be displayed. Setting this property to an empty string causes
* no label to be displayed.
**/
g_object_class_install_property (object_class,
PROP_TEXT,
g_param_spec_string ("text",
"Text",
"Text on the progress bar",
NULL,
G_PARAM_READWRITE));
/**
* SysprofCellRendererProgress:pulse:
*
* Setting this to a non-negative value causes the cell renderer to
* enter "activity mode", where a block bounces back and forth to
* indicate that some progress is made, without specifying exactly how
* much.
*
* Each increment of the property causes the block to move by a little
* bit.
*
* To indicate that the activity has not started yet, set the property
* to zero. To indicate completion, set the property to %G_MAXINT.
*/
g_object_class_install_property (object_class,
PROP_PULSE,
g_param_spec_int ("pulse",
"Pulse",
"Set this to positive values to indicate that some progress is made, but you dont know how much.",
-1, G_MAXINT, -1,
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
/**
* SysprofCellRendererProgress:text-xalign:
*
* The "text-xalign" property controls the horizontal alignment of the
* text in the progress bar. Valid values range from 0 (left) to 1
* (right). Reserved for RTL layouts.
*/
g_object_class_install_property (object_class,
PROP_TEXT_XALIGN,
g_param_spec_float ("text-xalign",
"Text x alignment",
"The horizontal text alignment, from 0 (left) to 1 (right). Reversed for RTL layouts.",
0.0, 1.0, 0.5,
G_PARAM_READWRITE));
/**
* SysprofCellRendererProgress:text-yalign:
*
* The "text-yalign" property controls the vertical alignment of the
* text in the progress bar. Valid values range from 0 (top) to 1
* (bottom).
*/
g_object_class_install_property (object_class,
PROP_TEXT_YALIGN,
g_param_spec_float ("text-yalign",
"Text y alignment",
"The vertical text alignment, from 0 (top) to 1 (bottom).",
0.0, 1.0, 0.5,
G_PARAM_READWRITE));
g_object_class_override_property (object_class,
PROP_ORIENTATION,
"orientation");
g_object_class_install_property (object_class,
PROP_INVERTED,
g_param_spec_boolean ("inverted",
"Inverted",
"Invert the direction in which the progress bar grows",
FALSE,
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
}
static void
sysprof_cell_renderer_progress_init (SysprofCellRendererProgress *cellprogress)
{
SysprofCellRendererProgressPrivate *priv = sysprof_cell_renderer_progress_get_instance_private (cellprogress);
priv->value = 0;
priv->text = NULL;
priv->label = NULL;
priv->min_w = -1;
priv->min_h = -1;
priv->pulse = -1;
priv->offset = 0;
priv->text_xalign = 0.5;
priv->text_yalign = 0.5;
priv->orientation = GTK_ORIENTATION_HORIZONTAL,
priv->inverted = FALSE;
}
/**
* sysprof_cell_renderer_progress_new:
*
* Creates a new `SysprofCellRendererProgress`.
*
* Returns: the new cell renderer
**/
GtkCellRenderer*
sysprof_cell_renderer_progress_new (void)
{
return g_object_new (SYSPROF_TYPE_CELL_RENDERER_PROGRESS, NULL);
}

View File

@ -0,0 +1,53 @@
/* gtkcellrendererprogress.h
* Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
* modified by Jörgen Scheibengruber <mfcn@gmx.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Modified by the GTK+ Team and others 1997-2004. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define SYSPROF_TYPE_CELL_RENDERER_PROGRESS (sysprof_cell_renderer_progress_get_type ())
#define SYSPROF_CELL_RENDERER_PROGRESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SYSPROF_TYPE_CELL_RENDERER_PROGRESS, SysprofCellRendererProgress))
#define SYSPROF_IS_CELL_RENDERER_PROGRESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SYSPROF_TYPE_CELL_RENDERER_PROGRESS))
typedef struct _SysprofCellRendererProgress SysprofCellRendererProgress;
typedef struct _SysprofCellRendererProgressClass SysprofCellRendererProgressClass;
typedef struct _SysprofCellRendererProgressPrivate SysprofCellRendererProgressPrivate;
struct _SysprofCellRendererProgress
{
GtkCellRenderer parent_instance;
};
struct _SysprofCellRendererProgressClass
{
GtkCellRendererClass parent_class;
};
GType sysprof_cell_renderer_progress_get_type (void) G_GNUC_CONST;
GtkCellRenderer *sysprof_cell_renderer_progress_new (void);
G_END_DECLS

View File

@ -221,7 +221,7 @@ sysprof_cpu_aid_present_finish (SysprofAid *aid,
"y-lower", 0.0, "y-lower", 0.0,
"y-upper", 100.0, "y-upper", 100.0,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (freq), GTK_WIDGET (freq_row)); sysprof_visualizer_group_insert (freq, freq_row, -1, FALSE);
over_row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER, over_row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
"title", _("CPU Usage (All)"), "title", _("CPU Usage (All)"),
@ -323,17 +323,17 @@ sysprof_cpu_aid_present_finish (SysprofAid *aid,
if (has_usage && !found_combined) if (has_usage && !found_combined)
sysprof_visualizer_group_insert (usage, over_row, 0, FALSE); sysprof_visualizer_group_insert (usage, over_row, 0, FALSE);
else else
gtk_widget_destroy (GTK_WIDGET (over_row)); g_object_unref (g_object_ref_sink (over_row));
if (has_usage) if (has_usage)
sysprof_display_add_group (present->display, usage); sysprof_display_add_group (present->display, usage);
else else
gtk_widget_destroy (GTK_WIDGET (usage)); g_object_unref (g_object_ref_sink (usage));
if (has_freq) if (has_freq)
sysprof_display_add_group (present->display, freq); sysprof_display_add_group (present->display, freq);
else else
gtk_widget_destroy (GTK_WIDGET (freq)); g_object_unref (g_object_ref_sink (freq));
} }
return counters != NULL; return counters != NULL;

View File

@ -34,7 +34,8 @@ struct _SysprofDepthVisualizer
PointCache *points; PointCache *points;
guint reload_source; guint reload_source;
guint mode; guint mode;
GtkAllocation last_alloc; int last_width;
int last_height;
guint reloading : 1; guint reloading : 1;
guint needs_reload : 1; guint needs_reload : 1;
}; };
@ -238,34 +239,46 @@ sysprof_depth_visualizer_set_reader (SysprofVisualizer *row,
} }
} }
static gboolean static void
sysprof_depth_visualizer_draw (GtkWidget *widget, sysprof_depth_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget; SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget;
GtkAllocation alloc; GtkAllocation alloc;
GdkRectangle clip; GdkRectangle clip;
const Point *points; const Point *points;
gboolean ret; cairo_t *cr;
guint n_points = 0; guint n_points = 0;
GdkRGBA user; GdkRGBA user;
GdkRGBA system; GdkRGBA system;
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self)); g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
ret = GTK_WIDGET_CLASS (sysprof_depth_visualizer_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_depth_visualizer_parent_class)->snapshot (widget, snapshot);
if (self->points == NULL) if (self->points == NULL)
return ret; return;
gdk_rgba_parse (&user, "#1a5fb4"); gdk_rgba_parse (&user, "#1a5fb4");
gdk_rgba_parse (&system, "#3584e4"); gdk_rgba_parse (&system, "#3584e4");
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, alloc.width, alloc.height));
/* FIXME: we should abstract visualizer drawing into regions so that we
* can still know the region we're drawing.
*/
#if 0
if (!gdk_cairo_get_clip_rectangle (cr, &clip)) if (!gdk_cairo_get_clip_rectangle (cr, &clip))
return ret; return;
#else
clip.x = alloc.x = 0;
clip.y = alloc.y = 0;
clip.width = alloc.width;
clip.height = alloc.height;
#endif
/* Draw user-space stacks */ /* Draw user-space stacks */
if (self->mode != SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY && if (self->mode != SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY &&
@ -355,7 +368,7 @@ sysprof_depth_visualizer_draw (GtkWidget *widget,
cairo_stroke (cr); cairo_stroke (cr);
} }
return ret; cairo_destroy (cr);
} }
static gboolean static gboolean
@ -372,25 +385,23 @@ sysprof_depth_visualizer_queue_reload (SysprofDepthVisualizer *self)
{ {
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self)); g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
if (self->reload_source) g_clear_handle_id (&self->reload_source, g_source_remove);
g_source_remove (self->reload_source); self->reload_source = g_idle_add (sysprof_depth_visualizer_do_reload, self);
self->reload_source = gdk_threads_add_idle (sysprof_depth_visualizer_do_reload, self);
} }
static void static void
sysprof_depth_visualizer_size_allocate (GtkWidget *widget, sysprof_depth_visualizer_size_allocate (GtkWidget *widget,
GtkAllocation *alloc) int width,
int height,
int baseline)
{ {
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget; SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget;
GTK_WIDGET_CLASS (sysprof_depth_visualizer_parent_class)->size_allocate (widget, alloc); if (width != self->last_width || height != self->last_height)
if (alloc->width != self->last_alloc.x ||
alloc->height != self->last_alloc.height)
{ {
sysprof_depth_visualizer_queue_reload (SYSPROF_DEPTH_VISUALIZER (widget)); sysprof_depth_visualizer_queue_reload (SYSPROF_DEPTH_VISUALIZER (widget));
self->last_alloc = *alloc; self->last_width = width;
self->last_height = height;
} }
} }
@ -400,12 +411,7 @@ sysprof_depth_visualizer_finalize (GObject *object)
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)object; SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)object;
g_clear_pointer (&self->reader, sysprof_capture_reader_unref); g_clear_pointer (&self->reader, sysprof_capture_reader_unref);
g_clear_handle_id (&self->reload_source, g_source_remove);
if (self->reload_source)
{
g_source_remove (self->reload_source);
self->reload_source = 0;
}
G_OBJECT_CLASS (sysprof_depth_visualizer_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_depth_visualizer_parent_class)->finalize (object);
} }
@ -419,7 +425,7 @@ sysprof_depth_visualizer_class_init (SysprofDepthVisualizerClass *klass)
object_class->finalize = sysprof_depth_visualizer_finalize; object_class->finalize = sysprof_depth_visualizer_finalize;
widget_class->draw = sysprof_depth_visualizer_draw; widget_class->snapshot = sysprof_depth_visualizer_snapshot;
widget_class->size_allocate = sysprof_depth_visualizer_size_allocate; widget_class->size_allocate = sysprof_depth_visualizer_size_allocate;
row_class->set_reader = sysprof_depth_visualizer_set_reader; row_class->set_reader = sysprof_depth_visualizer_set_reader;

View File

@ -22,19 +22,20 @@
#include "config.h" #include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <string.h> #include <string.h>
#include "sysprof-details-page.h" #include "sysprof-details-page.h"
#include "sysprof-ui-private.h" #include "sysprof-ui-private.h"
#include "egg-three-grid.h"
struct _SysprofDetailsPage struct _SysprofDetailsPage
{ {
SysprofPage parent_instance; GtkWidget parent_instance;
/* Template Objects */ /* Template Objects */
DzlThreeGrid *three_grid; EggThreeGrid *three_grid;
GtkListStore *marks_store; GtkListStore *marks_store;
GtkTreeView *marks_view; GtkTreeView *marks_view;
GtkLabel *counters; GtkLabel *counters;
@ -51,7 +52,7 @@ struct _SysprofDetailsPage
guint next_row; guint next_row;
}; };
G_DEFINE_TYPE (SysprofDetailsPage, sysprof_details_page, GTK_TYPE_BIN) G_DEFINE_TYPE (SysprofDetailsPage, sysprof_details_page, GTK_TYPE_WIDGET)
#if GLIB_CHECK_VERSION(2, 56, 0) #if GLIB_CHECK_VERSION(2, 56, 0)
# define _g_date_time_new_from_iso8601 g_date_time_new_from_iso8601 # define _g_date_time_new_from_iso8601 g_date_time_new_from_iso8601
@ -76,12 +77,28 @@ _g_date_time_new_from_iso8601 (const gchar *str,
} }
#endif #endif
static void
sysprof_details_page_dispose (GObject *object)
{
SysprofDetailsPage *self = (SysprofDetailsPage *)object;
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (sysprof_details_page_parent_class)->dispose (object);
}
static void static void
sysprof_details_page_class_init (SysprofDetailsPageClass *klass) sysprof_details_page_class_init (SysprofDetailsPageClass *klass)
{ {
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = sysprof_details_page_dispose;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-details-page.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-details-page.ui");
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, allocations); gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, allocations);
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, counters); gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, counters);
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, cpu_label); gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, cpu_label);
@ -96,7 +113,7 @@ sysprof_details_page_class_init (SysprofDetailsPageClass *klass)
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, start_time); gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, start_time);
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, three_grid); gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, three_grid);
g_type_ensure (DZL_TYPE_THREE_GRID); g_type_ensure (EGG_TYPE_THREE_GRID);
} }
static void static void
@ -264,16 +281,10 @@ sysprof_details_page_add_item (SysprofDetailsPage *self,
g_return_if_fail (!center || GTK_IS_WIDGET (center)); g_return_if_fail (!center || GTK_IS_WIDGET (center));
if (left) if (left)
gtk_container_add_with_properties (GTK_CONTAINER (self->three_grid), left, egg_three_grid_add (self->three_grid, left, self->next_row, EGG_THREE_GRID_COLUMN_LEFT);
"row", self->next_row,
"column", DZL_THREE_GRID_COLUMN_LEFT,
NULL);
if (center) if (center)
gtk_container_add_with_properties (GTK_CONTAINER (self->three_grid), center, egg_three_grid_add (self->three_grid, center, self->next_row, EGG_THREE_GRID_COLUMN_CENTER);
"row", self->next_row,
"column", DZL_THREE_GRID_COLUMN_CENTER,
NULL);
self->next_row++; self->next_row++;
} }

View File

@ -39,7 +39,7 @@ SYSPROF_ALIGNED_END (8);
#define SYSPROF_TYPE_DETAILS_PAGE (sysprof_details_page_get_type()) #define SYSPROF_TYPE_DETAILS_PAGE (sysprof_details_page_get_type())
G_DECLARE_FINAL_TYPE (SysprofDetailsPage, sysprof_details_page, SYSPROF, DETAILS_PAGE, GtkBin) G_DECLARE_FINAL_TYPE (SysprofDetailsPage, sysprof_details_page, SYSPROF, DETAILS_PAGE, GtkWidget)
GtkWidget *sysprof_details_page_new (void); GtkWidget *sysprof_details_page_new (void);
void sysprof_details_page_set_reader (SysprofDetailsPage *self, void sysprof_details_page_set_reader (SysprofDetailsPage *self,

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface> <interface>
<requires lib="gtk+" version="3.22"/> <template class="SysprofDetailsPage" parent="GtkWidget">
<template class="SysprofDetailsPage" parent="GtkBin">
<property name="can_focus">False</property>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property> <property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">true</property> <property name="propagate-natural-height">true</property>
<property name="visible">true</property> <property name="visible">true</property>
<child> <child>
<object class="DzlThreeGrid" id="three_grid"> <object class="EggThreeGrid" id="three_grid">
<property name="margin">36</property> <property name="margin-start">36</property>
<property name="margin-end">36</property>
<property name="margin-top">36</property>
<property name="margin-bottom">36</property>
<property name="column-spacing">12</property> <property name="column-spacing">12</property>
<property name="row-spacing">6</property> <property name="row-spacing">6</property>
<property name="visible">true</property> <property name="visible">true</property>
@ -23,11 +23,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">0</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -37,41 +37,39 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">1</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Duration</property> <property name="label" translatable="yes">Duration</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">2</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">CPU Model</property> <property name="label" translatable="yes">CPU Model</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">3</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">3</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -82,11 +80,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">4</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">4</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -96,11 +94,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">5</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">5</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -110,11 +108,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">6</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">6</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -124,11 +122,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">7</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">7</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -138,11 +136,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">8</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">8</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -153,148 +151,137 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">9</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">9</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="filename"> <object class="GtkLabel" id="filename">
<property name="width-chars">35</property> <property name="width-chars">35</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">1</property>
<property name="row">0</property>
</layout>
</object> </object>
<packing>
<property name="column">1</property>
<property name="row">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="start_time"> <object class="GtkLabel" id="start_time">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">1</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="duration"> <object class="GtkLabel" id="duration">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">2</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="cpu_label"> <object class="GtkLabel" id="cpu_label">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">end</property> <property name="ellipsize">end</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">3</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">3</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="samples"> <object class="GtkLabel" id="samples">
<property name="margin-top">12</property> <property name="margin-top">12</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">4</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">4</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="marks"> <object class="GtkLabel" id="marks">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">5</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">5</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="processes"> <object class="GtkLabel" id="processes">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">6</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">6</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="forks"> <object class="GtkLabel" id="forks">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">7</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">7</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="counters"> <object class="GtkLabel" id="counters">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">8</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">8</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="allocations"> <object class="GtkLabel" id="allocations">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ellipsize">start</property> <property name="ellipsize">start</property>
<property name="margin-bottom">12</property> <property name="margin-bottom">12</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">True</property> <property name="selectable">True</property>
<layout>
<property name="column">center</property>
<property name="row">9</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">9</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkFrame"> <object class="GtkFrame">
<property name="visible">True</property> <property name="visible">True</property>
<property name="shadow-type">in</property>
<property name="margin-bottom">12</property> <property name="margin-bottom">12</property>
<child> <child>
<object class="GtkTreeView" id="marks_view"> <object class="GtkTreeView" id="marks_view">
@ -371,11 +358,11 @@
</child> </child>
</object> </object>
</child> </child>
<layout>
<property name="column">center</property>
<property name="row">10</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">10</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -245,7 +245,7 @@ sysprof_diskstat_aid_present_finish (SysprofAid *aid,
if (counters->len > 0) if (counters->len > 0)
sysprof_display_add_group (present->display, group); sysprof_display_add_group (present->display, group);
else else
gtk_widget_destroy (GTK_WIDGET (group)); g_object_unref (g_object_ref_sink (group));
} }
return counters != NULL; return counters != NULL;

View File

@ -1,6 +1,6 @@
/* sysprof-window-settings.h /* sysprof-display-private.h
* *
* Copyright 2016 Christian Hergert <chergert@redhat.com> * Copyright 2021 Christian Hergert <chergert@redhat.com>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,17 +14,16 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#ifndef SYSPROF_WINDOW_SETTINGS_H #pragma once
#define SYSPROF_WINDOW_SETTINGS_H
#include <gtk/gtk.h> #include "sysprof-display.h"
G_BEGIN_DECLS G_BEGIN_DECLS
void sysprof_window_settings_register (GtkWindow *window); void _sysprof_display_destroy (SysprofDisplay *self);
G_END_DECLS G_END_DECLS
#endif /* SYSPROF_WINDOW_SETTINGS_H */

View File

@ -22,11 +22,12 @@
#include "config.h" #include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "egg-paned-private.h"
#include "sysprof-details-page.h" #include "sysprof-details-page.h"
#include "sysprof-display.h" #include "sysprof-display-private.h"
#include "sysprof-profiler-assistant.h" #include "sysprof-profiler-assistant.h"
#include "sysprof-failed-state-view.h" #include "sysprof-failed-state-view.h"
#include "sysprof-recording-state-view.h" #include "sysprof-recording-state-view.h"
@ -72,7 +73,7 @@ typedef struct
SysprofCaptureFlags flags; SysprofCaptureFlags flags;
} SysprofDisplayPrivate; } SysprofDisplayPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofDisplay, sysprof_display, GTK_TYPE_BIN) G_DEFINE_TYPE_WITH_PRIVATE (SysprofDisplay, sysprof_display, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -96,10 +97,7 @@ update_title_child_property (SysprofDisplay *self)
if ((parent = gtk_widget_get_parent (GTK_WIDGET (self))) && GTK_IS_NOTEBOOK (parent)) if ((parent = gtk_widget_get_parent (GTK_WIDGET (self))) && GTK_IS_NOTEBOOK (parent))
{ {
g_autofree gchar *title = sysprof_display_dup_title (self); g_autofree gchar *title = sysprof_display_dup_title (self);
gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (parent), GTK_WIDGET (self), title);
gtk_container_child_set (GTK_CONTAINER (parent), GTK_WIDGET (self),
"menu-label", title,
NULL);
} }
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
@ -319,19 +317,17 @@ sysprof_display_notify_selection_cb (SysprofDisplay *self,
/* Opportunistically load pages */ /* Opportunistically load pages */
if (priv->reader != NULL) if (priv->reader != NULL)
{ {
GList *pages = gtk_container_get_children (GTK_CONTAINER (priv->pages)); for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->pages));
child;
for (const GList *iter = pages; iter; iter = iter->next) child = gtk_widget_get_next_sibling (child))
{ {
if (SYSPROF_IS_PAGE (iter->data)) if (SYSPROF_IS_PAGE (child))
sysprof_page_load_async (iter->data, sysprof_page_load_async (SYSPROF_PAGE (child),
priv->reader, priv->reader,
selection, selection,
priv->filter, priv->filter,
NULL, NULL, NULL); NULL, NULL, NULL);
} }
g_list_free (pages);
} }
} }
} }
@ -372,15 +368,21 @@ stop_recording_cb (GSimpleAction *action,
} }
static void static void
sysprof_display_finalize (GObject *object) sysprof_display_dispose (GObject *object)
{ {
SysprofDisplay *self = (SysprofDisplay *)object; SysprofDisplay *self = (SysprofDisplay *)object;
SysprofDisplayPrivate *priv = sysprof_display_get_instance_private (self); SysprofDisplayPrivate *priv = sysprof_display_get_instance_private (self);
if (priv->stack)
{
gtk_widget_unparent (GTK_WIDGET (priv->stack));
priv->stack = NULL;
}
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref); g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
g_clear_pointer (&priv->filter, sysprof_capture_condition_unref); g_clear_pointer (&priv->filter, sysprof_capture_condition_unref);
G_OBJECT_CLASS (sysprof_display_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_display_parent_class)->dispose (object);
} }
static void static void
@ -443,7 +445,7 @@ sysprof_display_class_init (SysprofDisplayClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = sysprof_display_finalize; object_class->dispose = sysprof_display_dispose;
object_class->get_property = sysprof_display_get_property; object_class->get_property = sysprof_display_get_property;
object_class->set_property = sysprof_display_set_property; object_class->set_property = sysprof_display_set_property;
@ -453,6 +455,7 @@ sysprof_display_class_init (SysprofDisplayClass *klass)
"/org/gnome/sysprof/css/SysprofDisplay-shared.css"); "/org/gnome/sysprof/css/SysprofDisplay-shared.css");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-display.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-display.ui");
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, "SysprofDisplay"); gtk_widget_class_set_css_name (widget_class, "SysprofDisplay");
gtk_widget_class_bind_template_child_private (widget_class, SysprofDisplay, assistant); gtk_widget_class_bind_template_child_private (widget_class, SysprofDisplay, assistant);
gtk_widget_class_bind_template_child_private (widget_class, SysprofDisplay, details); gtk_widget_class_bind_template_child_private (widget_class, SysprofDisplay, details);
@ -499,7 +502,7 @@ sysprof_display_class_init (SysprofDisplayClass *klass)
g_object_class_install_properties (object_class, N_PROPS, properties); g_object_class_install_properties (object_class, N_PROPS, properties);
g_type_ensure (DZL_TYPE_MULTI_PANED); g_type_ensure (EGG_TYPE_PANED);
g_type_ensure (SYSPROF_TYPE_DETAILS_PAGE); g_type_ensure (SYSPROF_TYPE_DETAILS_PAGE);
g_type_ensure (SYSPROF_TYPE_FAILED_STATE_VIEW); g_type_ensure (SYSPROF_TYPE_FAILED_STATE_VIEW);
g_type_ensure (SYSPROF_TYPE_PROFILER_ASSISTANT); g_type_ensure (SYSPROF_TYPE_PROFILER_ASSISTANT);
@ -552,7 +555,7 @@ sysprof_display_add_group (SysprofDisplay *self,
if (priv->reader != NULL) if (priv->reader != NULL)
_sysprof_visualizer_group_set_reader (group, priv->reader); _sysprof_visualizer_group_set_reader (group, priv->reader);
gtk_container_add (GTK_CONTAINER (priv->visualizers), GTK_WIDGET (group)); sysprof_visualizers_frame_add_group (priv->visualizers, group);
} }
void void
@ -567,10 +570,7 @@ sysprof_display_add_page (SysprofDisplay *self,
g_return_if_fail (SYSPROF_IS_PAGE (page)); g_return_if_fail (SYSPROF_IS_PAGE (page));
title = sysprof_page_get_title (page); title = sysprof_page_get_title (page);
gtk_stack_add_titled (priv->pages, GTK_WIDGET (page), NULL, title);
gtk_container_add_with_properties (GTK_CONTAINER (priv->pages), GTK_WIDGET (page),
"title", title,
NULL);
selection = sysprof_visualizers_frame_get_selection (priv->visualizers); selection = sysprof_visualizers_frame_get_selection (priv->visualizers);
@ -933,7 +933,6 @@ sysprof_display_load_scan_cb (GObject *object,
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
SysprofSelection *selection; SysprofSelection *selection;
GCancellable *cancellable; GCancellable *cancellable;
GList *pages;
g_assert (SYSPROF_IS_DISPLAY (self)); g_assert (SYSPROF_IS_DISPLAY (self));
g_assert (G_IS_ASYNC_RESULT (result)); g_assert (G_IS_ASYNC_RESULT (result));
@ -956,17 +955,17 @@ sysprof_display_load_scan_cb (GObject *object,
sysprof_details_page_set_reader (priv->details, reader); sysprof_details_page_set_reader (priv->details, reader);
/* Opportunistically load pages */ /* Opportunistically load pages */
pages = gtk_container_get_children (GTK_CONTAINER (priv->pages)); for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->pages));
for (const GList *iter = pages; iter; iter = iter->next) child;
child = gtk_widget_get_next_sibling (child))
{ {
if (SYSPROF_IS_PAGE (iter->data)) if (SYSPROF_IS_PAGE (child))
sysprof_page_load_async (iter->data, sysprof_page_load_async (SYSPROF_PAGE (child),
reader, reader,
selection, selection,
priv->filter, priv->filter,
NULL, NULL, NULL); NULL, NULL, NULL);
} }
g_list_free (pages);
gtk_stack_set_visible_child_name (priv->stack, "view"); gtk_stack_set_visible_child_name (priv->stack, "view");
} }
@ -1097,12 +1096,13 @@ sysprof_display_open (SysprofDisplay *self,
error->message); error->message);
g_signal_connect (dialog, g_signal_connect (dialog,
"response", "response",
G_CALLBACK (gtk_widget_destroy), G_CALLBACK (gtk_window_destroy),
NULL); NULL);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window)); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
gtk_window_present (GTK_WINDOW (dialog)); gtk_window_present (GTK_WINDOW (dialog));
gtk_widget_destroy (GTK_WIDGET (self));
_sysprof_display_destroy (self);
return; return;
} }
@ -1200,36 +1200,21 @@ sysprof_display_new_for_profiler (SysprofProfiler *profiler)
return GTK_WIDGET (g_steal_pointer (&self)); return GTK_WIDGET (g_steal_pointer (&self));
} }
void static void
sysprof_display_save (SysprofDisplay *self) on_save_response_cb (SysprofDisplay *self,
int res,
GtkFileChooserNative *chooser)
{ {
SysprofDisplayPrivate *priv = sysprof_display_get_instance_private (self); SysprofDisplayPrivate *priv = sysprof_display_get_instance_private (self);
g_autoptr(GFile) file = NULL; g_autoptr(GFile) file = NULL;
GtkFileChooserNative *native;
GtkWindow *parent;
gint res;
g_return_if_fail (SYSPROF_IS_DISPLAY (self)); g_assert (SYSPROF_IS_DISPLAY (self));
g_return_if_fail (priv->reader != NULL); g_assert (GTK_IS_FILE_CHOOSER_NATIVE (chooser));
parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
native = gtk_file_chooser_native_new (_("Save Recording"),
parent,
GTK_FILE_CHOOSER_ACTION_SAVE,
_("Save"),
_("Cancel"));
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (native), TRUE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (native), TRUE);
gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER (native), TRUE);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (native), "capture.syscap");
res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native));
switch (res) switch (res)
{ {
case GTK_RESPONSE_ACCEPT: case GTK_RESPONSE_ACCEPT:
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native)); file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (chooser));
if (g_file_is_native (file)) if (g_file_is_native (file))
{ {
@ -1239,17 +1224,24 @@ sysprof_display_save (SysprofDisplay *self)
if (!sysprof_capture_reader_save_as_with_error (priv->reader, path, &error)) if (!sysprof_capture_reader_save_as_with_error (priv->reader, path, &error))
{ {
GtkWidget *msg; GtkWidget *msg;
GtkNative *root;
msg = gtk_message_dialog_new (parent, root = gtk_widget_get_native (GTK_WIDGET (self));
msg = gtk_message_dialog_new (GTK_WINDOW (root),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR,
GTK_MESSAGE_ERROR, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE, GTK_BUTTONS_CLOSE,
_("Failed to save recording: %s"), _("Failed to save recording: %s"),
error->message); error->message);
gtk_window_present (GTK_WINDOW (msg)); gtk_window_present (GTK_WINDOW (msg));
g_signal_connect (msg, "response", G_CALLBACK (gtk_widget_destroy), NULL); g_signal_connect (msg, "response", G_CALLBACK (gtk_window_destroy), NULL);
} }
} }
else
{
g_autofree char *uri = g_file_get_uri (file);
g_warning ("%s is not native, cannot open", uri);
}
break; break;
@ -1258,7 +1250,35 @@ sysprof_display_save (SysprofDisplay *self)
} }
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native)); gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (chooser));
}
void
sysprof_display_save (SysprofDisplay *self)
{
SysprofDisplayPrivate *priv = sysprof_display_get_instance_private (self);
GtkFileChooserNative *native;
GtkNative *root;
g_return_if_fail (SYSPROF_IS_DISPLAY (self));
g_return_if_fail (priv->reader != NULL);
root = gtk_widget_get_native (GTK_WIDGET (self));
native = gtk_file_chooser_native_new (_("Save Recording"),
GTK_WINDOW (root),
GTK_FILE_CHOOSER_ACTION_SAVE,
_("Save"),
_("Cancel"));
gtk_file_chooser_set_create_folders (GTK_FILE_CHOOSER (native), TRUE);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (native), "capture.syscap");
g_signal_connect_object (native,
"response",
G_CALLBACK (on_save_response_cb),
self,
G_CONNECT_SWAPPED);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (native));
} }
void void
@ -1294,3 +1314,15 @@ sysprof_display_add_to_selection (SysprofDisplay *self,
selection = sysprof_visualizers_frame_get_selection (priv->visualizers); selection = sysprof_visualizers_frame_get_selection (priv->visualizers);
sysprof_selection_select_range (selection, begin_time, end_time); sysprof_selection_select_range (selection, begin_time, end_time);
} }
void
_sysprof_display_destroy (SysprofDisplay *self)
{
GtkWidget *parent;
g_return_if_fail (SYSPROF_IS_DISPLAY (self));
if ((parent = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_NOTEBOOK)))
gtk_notebook_remove_page (GTK_NOTEBOOK (parent),
gtk_notebook_page_num (GTK_NOTEBOOK (parent), GTK_WIDGET (self)));
}

View File

@ -32,11 +32,11 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_DISPLAY (sysprof_display_get_type()) #define SYSPROF_TYPE_DISPLAY (sysprof_display_get_type())
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (SysprofDisplay, sysprof_display, SYSPROF, DISPLAY, GtkBin) G_DECLARE_DERIVABLE_TYPE (SysprofDisplay, sysprof_display, SYSPROF, DISPLAY, GtkWidget)
struct _SysprofDisplayClass struct _SysprofDisplayClass
{ {
GtkBinClass parent_class; GtkWidgetClass parent_class;
/*< private >*/ /*< private >*/
gpointer _reserved[16]; gpointer _reserved[16];

View File

@ -1,77 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<template class="SysprofDisplay" parent="GtkBin"> <requires lib="gtk" version="4.0"/>
<template class="SysprofDisplay" parent="GtkWidget">
<child> <child>
<object class="GtkStack" id="stack"> <object class="GtkStack" id="stack">
<property name="homogeneous">false</property> <property name="hhomogeneous">0</property>
<property name="visible">true</property> <property name="vhomogeneous">0</property>
<child> <child>
<object class="SysprofProfilerAssistant" id="assistant"> <object class="GtkStackPage">
<property name="visible">true</property>
</object>
<packing>
<property name="name">assistant</property> <property name="name">assistant</property>
</packing> <property name="child">
<object class="SysprofProfilerAssistant" id="assistant">
</object>
</property>
</object>
</child> </child>
<child> <child>
<object class="DzlMultiPaned"> <object class="GtkStackPage">
<property name="orientation">vertical</property> <property name="name">view</property>
<property name="visible">true</property> <property name="child">
<child> <object class="EggPaned">
<object class="GtkBox">
<property name="vexpand">false</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property>
<child> <child>
<object class="SysprofVisualizersFrame" id="visualizers"> <object class="SysprofVisualizersFrame" id="visualizers">
<property name="vexpand">false</property>
</object>
</child>
<child>
<object class="GtkStack" id="pages">
<property name="hhomogeneous">0</property>
<property name="vhomogeneous">0</property>
<property name="vexpand">true</property> <property name="vexpand">true</property>
<property name="visible">true</property> <child>
</object> <object class="GtkStackPage">
</child> <property name="title" translatable="yes">Details</property>
<child> <property name="name">details</property>
<object class="GtkSeparator"> <property name="child">
<property name="orientation">horizontal</property> <object class="SysprofDetailsPage" id="details">
<property name="visible">true</property> </object>
</property>
</object>
</child>
</object> </object>
</child> </child>
</object> </object>
</child> </property>
<child>
<object class="GtkStack" id="pages">
<property name="homogeneous">false</property>
<property name="vexpand">true</property>
<property name="visible">true</property>
<child>
<object class="SysprofDetailsPage" id="details">
<property name="visible">true</property>
</object>
<packing>
<property name="title" translatable="yes">Details</property>
<property name="name">details</property>
</packing>
</child>
</object>
</child>
</object> </object>
<packing>
<property name="name">view</property>
</packing>
</child> </child>
<child> <child>
<object class="SysprofRecordingStateView" id="recording_view"> <object class="GtkStackPage">
<property name="visible">true</property>
</object>
<packing>
<property name="name">record</property> <property name="name">record</property>
</packing> <property name="child">
<object class="SysprofRecordingStateView" id="recording_view">
</object>
</property>
</object>
</child> </child>
<child> <child>
<object class="SysprofFailedStateView" id="failed_view"> <object class="GtkStackPage">
<property name="visible">true</property>
</object>
<packing>
<property name="name">failed</property> <property name="name">failed</property>
</packing> <property name="child">
<object class="SysprofFailedStateView" id="failed_view">
</object>
</property>
</object>
</child> </child>
</object> </object>
</child> </child>

View File

@ -296,35 +296,37 @@ sysprof_duplex_visualizer_set_reader (SysprofVisualizer *visualizer,
g_task_run_in_thread (task, sysprof_duplex_visualizer_worker); g_task_run_in_thread (task, sysprof_duplex_visualizer_worker);
} }
static gboolean static void
sysprof_duplex_visualizer_draw (GtkWidget *widget, sysprof_duplex_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
static const gdouble dashes[] = { 1.0, 2.0 }; static const gdouble dashes[] = { 1.0, 2.0 };
SysprofDuplexVisualizer *self = (SysprofDuplexVisualizer *)widget; SysprofDuplexVisualizer *self = (SysprofDuplexVisualizer *)widget;
PangoFontDescription *font_desc; PangoFontDescription *font_desc;
GtkStyleContext *style_context; GtkStyleContext *style_context;
PangoLayout *layout; PangoLayout *layout;
cairo_t *cr;
GtkAllocation alloc; GtkAllocation alloc;
GdkRectangle clip;
gboolean ret;
GdkRGBA fg; GdkRGBA fg;
guint mid; guint mid;
g_assert (SYSPROF_IS_DUPLEX_VISUALIZER (self)); g_assert (SYSPROF_IS_DUPLEX_VISUALIZER (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
/* FIXME: This should all be drawn offscreen and then drawn to the snapshot
* using GdkMemoryTexture so that we can avoid extra GPU uploads.
*/
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
gdk_cairo_get_clip_rectangle (cr, &clip);
mid = alloc.height / 2; mid = alloc.height / 2;
ret = GTK_WIDGET_CLASS (sysprof_duplex_visualizer_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_duplex_visualizer_parent_class)->snapshot (widget, snapshot);
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, alloc.width, alloc.height));
style_context = gtk_widget_get_style_context (widget); style_context = gtk_widget_get_style_context (widget);
gtk_style_context_get_color (style_context, gtk_style_context_get_color (style_context, &fg);
gtk_style_context_get_state (style_context),
&fg);
fg.alpha *= 0.4; fg.alpha *= 0.4;
/* Draw our center line */ /* Draw our center line */
@ -366,6 +368,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
n_fpoints); n_fpoints);
/* Skip past data that we won't see anyway */ /* Skip past data that we won't see anyway */
#if 0
for (p = 0; p < n_fpoints; p++) for (p = 0; p < n_fpoints; p++)
{ {
if (points[p].x >= clip.x) if (points[p].x >= clip.x)
@ -373,7 +376,8 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
} }
if (p >= n_fpoints) if (p >= n_fpoints)
return ret; return;
#endif
/* But get at least one data point to anchor out of view */ /* But get at least one data point to anchor out of view */
if (p > 0) if (p > 0)
@ -398,8 +402,10 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
last_x = points[i].x; last_x = points[i].x;
last_y = points[i].y; last_y = points[i].y;
#if 0
if (points[i].x > clip.x + clip.width) if (points[i].x > clip.x + clip.width)
break; break;
#endif
} }
cairo_line_to (cr, last_x, mid); cairo_line_to (cr, last_x, mid);
@ -436,6 +442,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
points, points,
n_fpoints); n_fpoints);
#if 0
/* Skip past data that we won't see anyway */ /* Skip past data that we won't see anyway */
for (p = 0; p < n_fpoints; p++) for (p = 0; p < n_fpoints; p++)
{ {
@ -445,6 +452,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
if (p >= n_fpoints) if (p >= n_fpoints)
return ret; return ret;
#endif
/* But get at least one data point to anchor out of view */ /* But get at least one data point to anchor out of view */
if (p > 0) if (p > 0)
@ -469,8 +477,10 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
last_x = points[i].x; last_x = points[i].x;
last_y = points[i].y; last_y = points[i].y;
#if 0
if (points[i].x > clip.x + clip.width) if (points[i].x > clip.x + clip.width)
break; break;
#endif
} }
cairo_line_to (cr, last_x, mid); cairo_line_to (cr, last_x, mid);
@ -510,7 +520,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
pango_font_description_free (font_desc); pango_font_description_free (font_desc);
g_object_unref (layout); g_object_unref (layout);
return ret; cairo_destroy (cr);
} }
static void static void
@ -534,7 +544,7 @@ sysprof_duplex_visualizer_class_init (SysprofDuplexVisualizerClass *klass)
object_class->finalize = sysprof_duplex_visualizer_finalize; object_class->finalize = sysprof_duplex_visualizer_finalize;
widget_class->draw = sysprof_duplex_visualizer_draw; widget_class->snapshot = sysprof_duplex_visualizer_snapshot;
visualizer_class->set_reader = sysprof_duplex_visualizer_set_reader; visualizer_class->set_reader = sysprof_duplex_visualizer_set_reader;
} }

View File

@ -127,9 +127,9 @@ value_entry_activate (GtkWidget *entry,
} }
static void static void
sysprof_environ_editor_row_destroy (GtkWidget *widget) sysprof_environ_editor_row_dispose (GObject *object)
{ {
SysprofEnvironEditorRow *self = (SysprofEnvironEditorRow *)widget; SysprofEnvironEditorRow *self = (SysprofEnvironEditorRow *)object;
if (self->variable != NULL) if (self->variable != NULL)
{ {
@ -137,7 +137,7 @@ sysprof_environ_editor_row_destroy (GtkWidget *widget)
g_clear_object (&self->variable); g_clear_object (&self->variable);
} }
GTK_WIDGET_CLASS (sysprof_environ_editor_row_parent_class)->destroy (widget); G_OBJECT_CLASS (sysprof_environ_editor_row_parent_class)->dispose (object);
} }
static void static void
@ -184,11 +184,10 @@ sysprof_environ_editor_row_class_init (SysprofEnvironEditorRowClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = sysprof_environ_editor_row_dispose;
object_class->get_property = sysprof_environ_editor_row_get_property; object_class->get_property = sysprof_environ_editor_row_get_property;
object_class->set_property = sysprof_environ_editor_row_set_property; object_class->set_property = sysprof_environ_editor_row_set_property;
widget_class->destroy = sysprof_environ_editor_row_destroy;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-environ-editor-row.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-environ-editor-row.ui");
gtk_widget_class_bind_template_child (widget_class, SysprofEnvironEditorRow, delete_button); gtk_widget_class_bind_template_child (widget_class, SysprofEnvironEditorRow, delete_button);
gtk_widget_class_bind_template_child (widget_class, SysprofEnvironEditorRow, key_entry); gtk_widget_class_bind_template_child (widget_class, SysprofEnvironEditorRow, key_entry);

View File

@ -1,78 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface> <interface>
<requires lib="gtk+" version="3.10"/>
<template class="SysprofEnvironEditorRow" parent="GtkListBoxRow"> <template class="SysprofEnvironEditorRow" parent="GtkListBoxRow">
<property name="can_focus">False</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property> <property name="spacing">12</property>
<child> <child>
<object class="GtkEntry" id="key_entry"> <object class="GtkEntry" id="key_entry">
<property name="visible">True</property> <property name="margin-start">3</property>
<property name="can_focus">True</property> <property name="has-frame">False</property>
<property name="margin_start">3</property>
<property name="has_frame">False</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="eq_label"> <object class="GtkLabel" id="eq_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">=</property> <property name="label">=</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="value_entry"> <object class="GtkEntry" id="value_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property> <property name="hexpand">True</property>
<property name="has_frame">False</property> <property name="has-frame">False</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="delete_button"> <object class="GtkButton" id="delete_button">
<property name="visible">True</property> <property name="tooltip-text" translatable="yes">Remove environment variable</property>
<property name="can_focus">False</property> <property name="icon-name">list-remove-symbolic</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Remove environment variable</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">list-remove-symbolic</property>
</object>
</child>
<style> <style>
<class name="image-button"/> <class name="image-button"/>
<class name="flat"/> <class name="flat"/>
</style> </style>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -30,13 +30,14 @@
struct _SysprofEnvironEditor struct _SysprofEnvironEditor
{ {
GtkListBox parent_instance; GtkWidget parent_instance;
GtkListBox *list_box;
SysprofEnviron *environ; SysprofEnviron *environ;
GtkWidget *dummy_row; GtkWidget *dummy_row;
SysprofEnvironVariable *dummy; SysprofEnvironVariable *dummy;
}; };
G_DEFINE_TYPE (SysprofEnvironEditor, sysprof_environ_editor, GTK_TYPE_LIST_BOX) G_DEFINE_TYPE (SysprofEnvironEditor, sysprof_environ_editor, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -69,7 +70,10 @@ sysprof_environ_editor_create_dummy_row (SysprofEnvironEditor *self)
label = g_object_new (GTK_TYPE_LABEL, label = g_object_new (GTK_TYPE_LABEL,
"label", _("New variable…"), "label", _("New variable…"),
"margin", 6, "margin-start", 6,
"margin-end", 6,
"margin-top", 6,
"margin-bottom", 6,
"visible", TRUE, "visible", TRUE,
"xalign", 0.0f, "xalign", 0.0f,
NULL); NULL);
@ -114,8 +118,7 @@ sysprof_environ_editor_disconnect (SysprofEnvironEditor *self)
g_assert (SYSPROF_IS_ENVIRON_EDITOR (self)); g_assert (SYSPROF_IS_ENVIRON_EDITOR (self));
g_assert (SYSPROF_IS_ENVIRON (self->environ)); g_assert (SYSPROF_IS_ENVIRON (self->environ));
gtk_list_box_bind_model (GTK_LIST_BOX (self), NULL, NULL, NULL, NULL); gtk_list_box_bind_model (self->list_box, NULL, NULL, NULL, NULL);
g_clear_object (&self->dummy); g_clear_object (&self->dummy);
} }
@ -125,12 +128,12 @@ sysprof_environ_editor_connect (SysprofEnvironEditor *self)
g_assert (SYSPROF_IS_ENVIRON_EDITOR (self)); g_assert (SYSPROF_IS_ENVIRON_EDITOR (self));
g_assert (SYSPROF_IS_ENVIRON (self->environ)); g_assert (SYSPROF_IS_ENVIRON (self->environ));
gtk_list_box_bind_model (GTK_LIST_BOX (self), gtk_list_box_bind_model (self->list_box,
G_LIST_MODEL (self->environ), G_LIST_MODEL (self->environ),
sysprof_environ_editor_create_row, self, NULL); sysprof_environ_editor_create_row, self, NULL);
self->dummy_row = sysprof_environ_editor_create_dummy_row (self); self->dummy_row = sysprof_environ_editor_create_dummy_row (self);
gtk_container_add (GTK_CONTAINER (self), self->dummy_row); gtk_list_box_append (self->list_box, self->dummy_row);
} }
static void static void
@ -168,17 +171,19 @@ find_row (SysprofEnvironEditor *self,
g_assert (SYSPROF_IS_ENVIRON_EDITOR (self)); g_assert (SYSPROF_IS_ENVIRON_EDITOR (self));
g_assert (SYSPROF_IS_ENVIRON_VARIABLE (variable)); g_assert (SYSPROF_IS_ENVIRON_VARIABLE (variable));
gtk_container_foreach (GTK_CONTAINER (self), find_row_cb, &lookup); for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->list_box));
child;
child = gtk_widget_get_next_sibling (child))
find_row_cb (child, &lookup);
return lookup.row; return lookup.row;
} }
static void static void
sysprof_environ_editor_row_activated (GtkListBox *list_box, sysprof_environ_editor_row_activated (SysprofEnvironEditor *self,
GtkListBoxRow *row) GtkListBoxRow *row,
GtkListBox *list_box)
{ {
SysprofEnvironEditor *self = (SysprofEnvironEditor *)list_box;
g_assert (GTK_IS_LIST_BOX (list_box)); g_assert (GTK_IS_LIST_BOX (list_box));
g_assert (GTK_IS_LIST_BOX_ROW (row)); g_assert (GTK_IS_LIST_BOX_ROW (row));
@ -196,13 +201,19 @@ sysprof_environ_editor_row_activated (GtkListBox *list_box,
} }
static void static void
sysprof_environ_editor_destroy (GtkWidget *widget) sysprof_environ_editor_dispose (GObject *object)
{ {
SysprofEnvironEditor *self = (SysprofEnvironEditor *)widget; SysprofEnvironEditor *self = (SysprofEnvironEditor *)object;
GTK_WIDGET_CLASS (sysprof_environ_editor_parent_class)->destroy (widget); if (self->list_box)
{
gtk_widget_unparent (GTK_WIDGET (self->list_box));
self->list_box = NULL;
}
g_clear_object (&self->environ); g_clear_object (&self->environ);
G_OBJECT_CLASS (sysprof_environ_editor_parent_class)->dispose (object);
} }
static void static void
@ -248,16 +259,12 @@ sysprof_environ_editor_class_init (SysprofEnvironEditorClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkListBoxClass *list_box_class = GTK_LIST_BOX_CLASS (klass);
SysprofThemeManager *theme_manager = sysprof_theme_manager_get_default (); SysprofThemeManager *theme_manager = sysprof_theme_manager_get_default ();
object_class->dispose = sysprof_environ_editor_dispose;
object_class->get_property = sysprof_environ_editor_get_property; object_class->get_property = sysprof_environ_editor_get_property;
object_class->set_property = sysprof_environ_editor_set_property; object_class->set_property = sysprof_environ_editor_set_property;
widget_class->destroy = sysprof_environ_editor_destroy;
list_box_class->row_activated = sysprof_environ_editor_row_activated;
properties [PROP_ENVIRON] = properties [PROP_ENVIRON] =
g_param_spec_object ("environ", g_param_spec_object ("environ",
"Environment", "Environment",
@ -267,16 +274,26 @@ sysprof_environ_editor_class_init (SysprofEnvironEditorClass *klass)
g_object_class_install_properties (object_class, N_PROPS, properties); g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
sysprof_theme_manager_register_resource (theme_manager, NULL, NULL, "/org/gnome/sysprof/css/SysprofEnvironEditor-shared.css"); sysprof_theme_manager_register_resource (theme_manager, NULL, NULL, "/org/gnome/sysprof/css/SysprofEnvironEditor-shared.css");
} }
static void static void
sysprof_environ_editor_init (SysprofEnvironEditor *self) sysprof_environ_editor_init (SysprofEnvironEditor *self)
{ {
gtk_list_box_set_selection_mode (GTK_LIST_BOX (self), GTK_SELECTION_NONE); self->list_box = GTK_LIST_BOX (gtk_list_box_new ());
gtk_widget_set_parent (GTK_WIDGET (self->list_box), GTK_WIDGET (self));
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), gtk_list_box_set_selection_mode (self->list_box, GTK_SELECTION_NONE);
"environ-editor");
gtk_widget_add_css_class (GTK_WIDGET (self), "environ-editor");
g_signal_connect_object (self->list_box,
"row-activated",
G_CALLBACK (sysprof_environ_editor_row_activated),
self,
G_CONNECT_SWAPPED);
} }
GtkWidget * GtkWidget *

View File

@ -28,11 +28,11 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_ENVIRON_EDITOR (sysprof_environ_editor_get_type()) #define SYSPROF_TYPE_ENVIRON_EDITOR (sysprof_environ_editor_get_type())
G_DECLARE_FINAL_TYPE (SysprofEnvironEditor, sysprof_environ_editor, SYSPROF, ENVIRON_EDITOR, GtkListBox) G_DECLARE_FINAL_TYPE (SysprofEnvironEditor, sysprof_environ_editor, SYSPROF, ENVIRON_EDITOR, GtkWidget)
GtkWidget *sysprof_environ_editor_new (void); GtkWidget *sysprof_environ_editor_new (void);
SysprofEnviron *sysprof_environ_editor_get_environ (SysprofEnvironEditor *self); SysprofEnviron *sysprof_environ_editor_get_environ (SysprofEnvironEditor *self);
void sysprof_environ_editor_set_environ (SysprofEnvironEditor *self, void sysprof_environ_editor_set_environ (SysprofEnvironEditor *self,
SysprofEnviron *environ); SysprofEnviron *environ);
G_END_DECLS G_END_DECLS

View File

@ -22,7 +22,7 @@
#include "sysprof-failed-state-view.h" #include "sysprof-failed-state-view.h"
G_DEFINE_TYPE (SysprofFailedStateView, sysprof_failed_state_view, GTK_TYPE_BIN) G_DEFINE_TYPE (SysprofFailedStateView, sysprof_failed_state_view, GTK_TYPE_WIDGET)
GtkWidget * GtkWidget *
sysprof_failed_state_view_new (void) sysprof_failed_state_view_new (void)
@ -30,11 +30,27 @@ sysprof_failed_state_view_new (void)
return g_object_new (SYSPROF_TYPE_FAILED_STATE_VIEW, NULL); return g_object_new (SYSPROF_TYPE_FAILED_STATE_VIEW, NULL);
} }
static void
sysprof_failed_state_view_dispose (GObject *object)
{
SysprofFailedStateView *self = (SysprofFailedStateView *)object;
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (sysprof_failed_state_view_parent_class)->dispose (object);
}
static void static void
sysprof_failed_state_view_class_init (SysprofFailedStateViewClass *klass) sysprof_failed_state_view_class_init (SysprofFailedStateViewClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = sysprof_failed_state_view_dispose;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class, gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/sysprof/ui/sysprof-failed-state-view.ui"); "/org/gnome/sysprof/ui/sysprof-failed-state-view.ui");
} }

View File

@ -27,13 +27,11 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_FAILED_STATE_VIEW (sysprof_failed_state_view_get_type()) #define SYSPROF_TYPE_FAILED_STATE_VIEW (sysprof_failed_state_view_get_type())
G_DECLARE_DERIVABLE_TYPE (SysprofFailedStateView, sysprof_failed_state_view, SYSPROF, FAILED_STATE_VIEW, GtkBin) G_DECLARE_DERIVABLE_TYPE (SysprofFailedStateView, sysprof_failed_state_view, SYSPROF, FAILED_STATE_VIEW, GtkWidget)
struct _SysprofFailedStateViewClass struct _SysprofFailedStateViewClass
{ {
GtkBinClass parent; GtkWidgetClass parent;
gpointer padding[4];
}; };
GtkWidget *sysprof_failed_state_view_new (void); GtkWidget *sysprof_failed_state_view_new (void);

View File

@ -1,9 +1,12 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<interface> <interface>
<template class="SysprofFailedStateView" parent="GtkBin"> <template class="SysprofFailedStateView" parent="GtkWidget">
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="border-width">36</property> <property name="margin-top">36</property>
<property name="margin-bottom">36</property>
<property name="margin-start">36</property>
<property name="margin-end">36</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">12</property> <property name="spacing">12</property>
<property name="visible">true</property> <property name="visible">true</property>
@ -17,7 +20,23 @@
</style> </style>
</object> </object>
</child> </child>
<child> <child type="end">
<object class="GtkLabel">
<property name="vexpand">true</property>
<property name="visible">true</property>
</object>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label" translatable="yes">Something unexpectedly went wrong while trying to profile your system.</property>
<property name="use-markup">true</property>
<property name="visible">true</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child type="end">
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Ouch, that hurt!</property> <property name="label" translatable="yes">Ouch, that hurt!</property>
<property name="visible">true</property> <property name="visible">true</property>
@ -29,34 +48,6 @@
<attribute name="weight" value="bold"/> <attribute name="weight" value="bold"/>
</attributes> </attributes>
</object> </object>
<packing>
<property name="pack-type">end</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Something unexpectedly went wrong while trying to profile your system.</property>
<property name="use-markup">true</property>
<property name="visible">true</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="GtkLabel">
<property name="vexpand">true</property>
<property name="visible">true</property>
</object>
<packing>
<property name="position">0</property>
<property name="pack-type">end</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -141,9 +141,9 @@ copy_array (GArray *ar)
return ret; return ret;
} }
static gboolean static void
sysprof_line_visualizer_draw (GtkWidget *widget, sysprof_line_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
static PangoAttrList *attrs = NULL; static PangoAttrList *attrs = NULL;
SysprofLineVisualizer *self = (SysprofLineVisualizer *)widget; SysprofLineVisualizer *self = (SysprofLineVisualizer *)widget;
@ -151,28 +151,35 @@ sysprof_line_visualizer_draw (GtkWidget *widget,
g_autofree gchar *upper = NULL; g_autofree gchar *upper = NULL;
GtkStyleContext *style_context; GtkStyleContext *style_context;
PangoLayout *layout; PangoLayout *layout;
GtkStateFlags flags; cairo_t *cr;
GtkAllocation alloc; GtkAllocation alloc;
GdkRectangle clip; GdkRectangle clip;
GdkRGBA foreground; GdkRGBA foreground;
gboolean ret;
g_assert (SYSPROF_IS_LINE_VISUALIZER (widget)); g_assert (SYSPROF_IS_LINE_VISUALIZER (widget));
g_assert (cr != NULL); g_assert (snapshot != NULL);
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
ret = GTK_WIDGET_CLASS (sysprof_line_visualizer_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_line_visualizer_parent_class)->snapshot (widget, snapshot);
if (priv->cache == NULL) if (priv->cache == NULL)
return ret; return;
#if 0
if (!gdk_cairo_get_clip_rectangle (cr, &clip)) if (!gdk_cairo_get_clip_rectangle (cr, &clip))
return ret; return ret;
#else
clip.x = 0;
clip.y = 0;
clip.width = alloc.width;
clip.height = alloc.height;
#endif
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, alloc.width, alloc.height));
style_context = gtk_widget_get_style_context (widget); style_context = gtk_widget_get_style_context (widget);
flags = gtk_widget_get_state_flags (widget); gtk_style_context_get_color (style_context, &foreground);
gtk_style_context_get_color (style_context, flags, &foreground);
for (guint line = 0; line < priv->lines->len; line++) for (guint line = 0; line < priv->lines->len; line++)
{ {
@ -205,7 +212,7 @@ sysprof_line_visualizer_draw (GtkWidget *widget,
} }
if (p >= n_fpoints) if (p >= n_fpoints)
return ret; goto cleanup;
if (p > 0) if (p > 0)
p--; p--;
@ -289,7 +296,8 @@ sysprof_line_visualizer_draw (GtkWidget *widget,
g_clear_object (&layout); g_clear_object (&layout);
} }
return ret; cleanup:
cairo_destroy (cr);
} }
static void static void
@ -347,12 +355,10 @@ sysprof_line_visualizer_queue_reload (SysprofLineVisualizer *self)
g_assert (SYSPROF_IS_LINE_VISUALIZER (self)); g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
if (priv->queued_load == 0) if (priv->queued_load == 0)
{ priv->queued_load = g_idle_add_full (G_PRIORITY_LOW,
priv->queued_load = gdk_threads_add_idle_full (G_PRIORITY_LOW, sysprof_line_visualizer_do_reload,
sysprof_line_visualizer_do_reload, self,
self, NULL);
NULL);
}
} }
static void static void
@ -390,11 +396,7 @@ sysprof_line_visualizer_finalize (GObject *object)
g_clear_pointer (&priv->cache, point_cache_unref); g_clear_pointer (&priv->cache, point_cache_unref);
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref); g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
if (priv->queued_load != 0) g_clear_handle_id (&priv->queued_load, g_source_remove);
{
g_source_remove (priv->queued_load);
priv->queued_load = 0;
}
G_OBJECT_CLASS (sysprof_line_visualizer_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_line_visualizer_parent_class)->finalize (object);
} }
@ -472,7 +474,7 @@ sysprof_line_visualizer_class_init (SysprofLineVisualizerClass *klass)
object_class->get_property = sysprof_line_visualizer_get_property; object_class->get_property = sysprof_line_visualizer_get_property;
object_class->set_property = sysprof_line_visualizer_set_property; object_class->set_property = sysprof_line_visualizer_set_property;
widget_class->draw = sysprof_line_visualizer_draw; widget_class->snapshot = sysprof_line_visualizer_snapshot;
visualizer_class->set_reader = sysprof_line_visualizer_set_reader; visualizer_class->set_reader = sysprof_line_visualizer_set_reader;

View File

@ -70,25 +70,27 @@ sysprof_mark_visualizer_new (GHashTable *groups)
return SYSPROF_VISUALIZER (g_steal_pointer (&self)); return SYSPROF_VISUALIZER (g_steal_pointer (&self));
} }
static gboolean static void
sysprof_mark_visualizer_draw (GtkWidget *widget, sysprof_mark_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofMarkVisualizer *self = (SysprofMarkVisualizer *)widget; SysprofMarkVisualizer *self = (SysprofMarkVisualizer *)widget;
SysprofVisualizer *vis = (SysprofVisualizer *)widget; SysprofVisualizer *vis = (SysprofVisualizer *)widget;
static const GdkRGBA black = {0,0,0,1};
const GdkRGBA *rgba = &black;
GHashTableIter iter; GHashTableIter iter;
GtkAllocation alloc; GtkAllocation alloc;
gpointer k, v; gpointer k, v;
gboolean ret; int n_groups = 0;
gint n_groups = 0; int y = 0;
gint y = 0;
g_assert (SYSPROF_IS_MARK_VISUALIZER (self)); g_assert (SYSPROF_IS_MARK_VISUALIZER (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
GTK_WIDGET_CLASS (sysprof_mark_visualizer_parent_class)->snapshot (widget, snapshot);
ret = GTK_WIDGET_CLASS (sysprof_mark_visualizer_parent_class)->draw (widget, cr);
if (self->spans_by_group == NULL) if (self->spans_by_group == NULL)
return ret; return;
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
@ -117,19 +119,14 @@ sysprof_mark_visualizer_draw (GtkWidget *widget,
g_hash_table_iter_init (&iter, self->spans_by_group); g_hash_table_iter_init (&iter, self->spans_by_group);
while (g_hash_table_iter_next (&iter, &k, &v)) while (g_hash_table_iter_next (&iter, &k, &v))
{ {
static const GdkRGBA black = {0, 0, 0, 1};
SysprofMarkTimeSpan *span; SysprofMarkTimeSpan *span;
const gchar *group = k; const gchar *group = k;
const GArray *spans = v; const GArray *spans = v;
const GdkRGBA *rgba;
const GdkRGBA *kindrgba; const GdkRGBA *kindrgba;
const GdkRGBA *grouprgba; const GdkRGBA *grouprgba;
if ((grouprgba = g_hash_table_lookup (self->rgba_by_group, group))) if ((grouprgba = g_hash_table_lookup (self->rgba_by_group, group)))
{ rgba = grouprgba;
rgba = grouprgba;
gdk_cairo_set_source_rgba (cr, rgba);
}
for (guint i = 0; i < spans->len; i++) for (guint i = 0; i < spans->len; i++)
{ {
@ -144,7 +141,6 @@ sysprof_mark_visualizer_draw (GtkWidget *widget,
rgba = kindrgba; rgba = kindrgba;
else if ((grouprgba = g_hash_table_lookup (self->rgba_by_group, group))) else if ((grouprgba = g_hash_table_lookup (self->rgba_by_group, group)))
rgba = grouprgba; rgba = grouprgba;
gdk_cairo_set_source_rgba (cr, rgba);
} }
x1 = span->x; x1 = span->x;
@ -180,31 +176,24 @@ sysprof_mark_visualizer_draw (GtkWidget *widget,
break; break;
} }
cairo_rectangle (cr, x1, y, x2 - x1, RECT_HEIGHT); gtk_snapshot_append_color (snapshot, rgba, &GRAPHENE_RECT_INIT (x1, y, x2 - x1, RECT_HEIGHT));
if (n_groups == 1)
cairo_fill (cr);
} }
if (n_groups > 1)
cairo_fill (cr);
y += RECT_HEIGHT + RECT_OVERLAP; y += RECT_HEIGHT + RECT_OVERLAP;
} }
return ret;
} }
static void static void
sysprof_mark_visualizer_size_allocate (GtkWidget *widget, sysprof_mark_visualizer_size_allocate (GtkWidget *widget,
GtkAllocation *alloc) int width,
int height,
int baseline)
{ {
SysprofMarkVisualizer *self = (SysprofMarkVisualizer *)widget; SysprofMarkVisualizer *self = (SysprofMarkVisualizer *)widget;
g_assert (SYSPROF_IS_MARK_VISUALIZER (self)); g_assert (SYSPROF_IS_MARK_VISUALIZER (self));
g_assert (alloc != NULL);
GTK_WIDGET_CLASS (sysprof_mark_visualizer_parent_class)->size_allocate (widget, alloc); GTK_WIDGET_CLASS (sysprof_mark_visualizer_parent_class)->size_allocate (widget, width, height, baseline);
reset_positions (self); reset_positions (self);
} }
@ -230,7 +219,7 @@ sysprof_mark_visualizer_class_init (SysprofMarkVisualizerClass *klass)
object_class->finalize = sysprof_mark_visualizer_finalize; object_class->finalize = sysprof_mark_visualizer_finalize;
widget_class->draw = sysprof_mark_visualizer_draw; widget_class->snapshot = sysprof_mark_visualizer_snapshot;
widget_class->size_allocate = sysprof_mark_visualizer_size_allocate; widget_class->size_allocate = sysprof_mark_visualizer_size_allocate;
} }

View File

@ -46,6 +46,177 @@ typedef struct
G_DEFINE_TYPE (SysprofMarksAid, sysprof_marks_aid, SYSPROF_TYPE_AID) G_DEFINE_TYPE (SysprofMarksAid, sysprof_marks_aid, SYSPROF_TYPE_AID)
static void
rgb_to_hls (gdouble *r,
gdouble *g,
gdouble *b)
{
gdouble min;
gdouble max;
gdouble red;
gdouble green;
gdouble blue;
gdouble h, l, s;
gdouble delta;
red = *r;
green = *g;
blue = *b;
if (red > green)
{
if (red > blue)
max = red;
else
max = blue;
if (green < blue)
min = green;
else
min = blue;
}
else
{
if (green > blue)
max = green;
else
max = blue;
if (red < blue)
min = red;
else
min = blue;
}
l = (max + min) / 2;
s = 0;
h = 0;
if (max != min)
{
if (l <= 0.5)
s = (max - min) / (max + min);
else
s = (max - min) / (2 - max - min);
delta = max - min;
if (red == max)
h = (green - blue) / delta;
else if (green == max)
h = 2 + (blue - red) / delta;
else if (blue == max)
h = 4 + (red - green) / delta;
h *= 60;
if (h < 0.0)
h += 360;
}
*r = h;
*g = l;
*b = s;
}
static void
hls_to_rgb (gdouble *h,
gdouble *l,
gdouble *s)
{
gdouble hue;
gdouble lightness;
gdouble saturation;
gdouble m1, m2;
gdouble r, g, b;
lightness = *l;
saturation = *s;
if (lightness <= 0.5)
m2 = lightness * (1 + saturation);
else
m2 = lightness + saturation - lightness * saturation;
m1 = 2 * lightness - m2;
if (saturation == 0)
{
*h = lightness;
*l = lightness;
*s = lightness;
}
else
{
hue = *h + 120;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
if (hue < 60)
r = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
r = m2;
else if (hue < 240)
r = m1 + (m2 - m1) * (240 - hue) / 60;
else
r = m1;
hue = *h;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
if (hue < 60)
g = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
g = m2;
else if (hue < 240)
g = m1 + (m2 - m1) * (240 - hue) / 60;
else
g = m1;
hue = *h - 120;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
if (hue < 60)
b = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
b = m2;
else if (hue < 240)
b = m1 + (m2 - m1) * (240 - hue) / 60;
else
b = m1;
*h = r;
*l = g;
*s = b;
}
}
static void
rgba_shade (const GdkRGBA *rgba,
GdkRGBA *dst,
gdouble k)
{
gdouble red;
gdouble green;
gdouble blue;
red = rgba->red;
green = rgba->green;
blue = rgba->blue;
rgb_to_hls (&red, &green, &blue);
green *= k;
if (green > 1.0)
green = 1.0;
else if (green < 0.0)
green = 0.0;
blue *= k;
if (blue > 1.0)
blue = 1.0;
else if (blue < 0.0)
blue = 0.0;
hls_to_rgb (&red, &green, &blue);
dst->red = red;
dst->green = green;
dst->blue = blue;
dst->alpha = rgba->alpha;
}
static void static void
present_free (gpointer data) present_free (gpointer data)
{ {
@ -275,7 +446,7 @@ sysprof_marks_aid_present_finish (SysprofAid *aid,
if (!g_hash_table_contains (seen, GUINT_TO_POINTER (span->kind))) if (!g_hash_table_contains (seen, GUINT_TO_POINTER (span->kind)))
{ {
dzl_rgba_shade (&rgba, &kind_rgba, 1 + (ratio * span->kind)); rgba_shade (&rgba, &kind_rgba, 1 + (ratio * span->kind));
g_hash_table_insert (seen, g_hash_table_insert (seen,
GUINT_TO_POINTER (span->kind), GUINT_TO_POINTER (span->kind),
g_memdup2 (&kind_rgba, sizeof kind_rgba)); g_memdup2 (&kind_rgba, sizeof kind_rgba));

View File

@ -50,6 +50,8 @@ typedef struct
GtkLabel *end; GtkLabel *end;
GtkLabel *duration; GtkLabel *duration;
GtkTextView *message; GtkTextView *message;
GtkWidget *failed;
GtkWidget *marks;
} SysprofMarksPagePrivate; } SysprofMarksPagePrivate;
enum { enum {
@ -64,19 +66,21 @@ static GParamSpec *properties [N_PROPS];
G_DEFINE_TYPE_WITH_PRIVATE (SysprofMarksPage, sysprof_marks_page, SYSPROF_TYPE_PAGE) G_DEFINE_TYPE_WITH_PRIVATE (SysprofMarksPage, sysprof_marks_page, SYSPROF_TYPE_PAGE)
static gboolean static gboolean
sysprof_marks_page_tree_view_key_press_event_cb (SysprofMarksPage *self, sysprof_marks_page_tree_view_key_press_event_cb (SysprofMarksPage *self,
const GdkEventKey *key, guint keyval,
GtkTreeView *tree_view) guint keycode,
GdkModifierType state,
GtkEventControllerKey *controller)
{ {
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self); SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
gint dir = 0; gint dir = 0;
g_assert (SYSPROF_MARKS_PAGE (self)); g_assert (SYSPROF_MARKS_PAGE (self));
g_assert (key != NULL); g_assert (GTK_IS_EVENT_CONTROLLER_KEY (controller));
if (key->state == 0) if ((state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_ALT_MASK)) == 0)
{ {
switch (key->keyval) switch (keyval)
{ {
case GDK_KEY_Left: case GDK_KEY_Left:
dir = -1; dir = -1;
@ -308,9 +312,9 @@ sysprof_marks_page_load_cb (GObject *object,
gtk_tree_view_set_model (priv->tree_view, GTK_TREE_MODEL (model)); gtk_tree_view_set_model (priv->tree_view, GTK_TREE_MODEL (model));
if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL) == 0) if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (model), NULL) == 0)
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, GTK_WIDGET (priv->failed));
else else
gtk_stack_set_visible_child_name (priv->stack, "marks"); gtk_stack_set_visible_child (priv->stack, GTK_WIDGET (priv->marks));
g_task_return_boolean (task, TRUE); g_task_return_boolean (task, TRUE);
} }
@ -515,6 +519,8 @@ sysprof_marks_page_class_init (SysprofMarksPageClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, duration); gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, duration);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, time); gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, time);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, message); gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, message);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, marks);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, failed);
properties [PROP_KIND] = properties [PROP_KIND] =
g_param_spec_enum ("kind", NULL, NULL, g_param_spec_enum ("kind", NULL, NULL,
@ -536,6 +542,7 @@ static void
sysprof_marks_page_init (SysprofMarksPage *self) sysprof_marks_page_init (SysprofMarksPage *self)
{ {
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self); SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
GtkEventController *controller;
priv->kind = SYSPROF_MARKS_MODEL_MARKS; priv->kind = SYSPROF_MARKS_MODEL_MARKS;
@ -544,11 +551,14 @@ sysprof_marks_page_init (SysprofMarksPage *self)
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->tree_view), gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->tree_view),
GTK_SELECTION_MULTIPLE); GTK_SELECTION_MULTIPLE);
g_signal_connect_object (priv->tree_view, controller = gtk_event_controller_key_new ();
"key-press-event", gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
g_signal_connect_object (controller,
"key-pressed",
G_CALLBACK (sysprof_marks_page_tree_view_key_press_event_cb), G_CALLBACK (sysprof_marks_page_tree_view_key_press_event_cb),
self, self,
G_CONNECT_SWAPPED); G_CONNECT_SWAPPED);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
g_signal_connect_object (priv->tree_view, g_signal_connect_object (priv->tree_view,
"row-activated", "row-activated",

View File

@ -3,22 +3,21 @@
<template class="SysprofMarksPage" parent="SysprofPage"> <template class="SysprofMarksPage" parent="SysprofPage">
<child> <child>
<object class="GtkStack" id="stack"> <object class="GtkStack" id="stack">
<property name="homogeneous">false</property> <property name="hhomogeneous">false</property>
<property name="visible">true</property> <property name="vhomogeneous">false</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox" id="marks">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkBox" id="details_box"> <object class="GtkBox" id="details_box">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="margin">6</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Details</property> <property name="label" translatable="yes">Details</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="visible">true</property> <property name="margin-top">6</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-bottom">6</property> <property name="margin-bottom">6</property>
<attributes> <attributes>
<attribute name="weight" value="bold"/> <attribute name="weight" value="bold"/>
@ -30,164 +29,150 @@
<property name="hexpand">false</property> <property name="hexpand">false</property>
<property name="vexpand">true</property> <property name="vexpand">true</property>
<property name="margin-start">6</property> <property name="margin-start">6</property>
<property name="visible">true</property> <property name="margin-end">6</property>
<property name="column-spacing">6</property> <property name="column-spacing">6</property>
<property name="row-spacing">3</property> <property name="row-spacing">3</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Group</property> <property name="label" translatable="yes">Group</property>
<property name="visible">true</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="row">0</property>
<property name="column">0</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">0</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Mark</property> <property name="label" translatable="yes">Mark</property>
<property name="visible">true</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="yalign">0</property> <property name="yalign">0</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="row">1</property>
<property name="column">0</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">1</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Time</property> <property name="label" translatable="yes">Time</property>
<property name="visible">true</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="row">2</property>
<property name="column">0</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">2</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">End</property> <property name="label" translatable="yes">End</property>
<property name="visible">true</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="row">3</property>
<property name="column">0</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">3</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Duration</property> <property name="label" translatable="yes">Duration</property>
<property name="visible">true</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="row">4</property>
<property name="column">0</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">4</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Message</property> <property name="label" translatable="yes">Message</property>
<property name="visible">true</property>
<property name="xalign">1</property> <property name="xalign">1</property>
<property name="yalign">0</property> <property name="yalign">0</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="row">5</property>
<property name="column">0</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">5</property>
<property name="left-attach">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="group"> <object class="GtkLabel" id="group">
<property name="visible">true</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="wrap">true</property> <property name="wrap">true</property>
<layout>
<property name="row">0</property>
<property name="column">1</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">0</property>
<property name="left-attach">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="mark"> <object class="GtkLabel" id="mark">
<property name="visible">true</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="max-width-chars">5</property> <property name="max-width-chars">5</property>
<property name="ellipsize">end</property> <property name="ellipsize">end</property>
<layout>
<property name="row">1</property>
<property name="column">1</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">1</property>
<property name="left-attach">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="time"> <object class="GtkLabel" id="time">
<property name="visible">true</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<layout>
<property name="row">2</property>
<property name="column">1</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">2</property>
<property name="left-attach">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="end"> <object class="GtkLabel" id="end">
<property name="visible">true</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<layout>
<property name="row">3</property>
<property name="column">1</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">3</property>
<property name="left-attach">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="duration"> <object class="GtkLabel" id="duration">
<property name="visible">true</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<layout>
<property name="row">4</property>
<property name="column">1</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">4</property>
<property name="left-attach">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="hexpand">true</property> <property name="hexpand">true</property>
<property name="shadow-type">in</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkTextView" id="message"> <object class="GtkTextView" id="message">
<property name="editable">false</property> <property name="editable">false</property>
<property name="visible">true</property>
</object> </object>
</child> </child>
<layout>
<property name="row">5</property>
<property name="column">1</property>
</layout>
</object> </object>
<packing>
<property name="top-attach">5</property>
<property name="left-attach">1</property>
</packing>
</child> </child>
</object> </object>
</child> </child>
@ -196,20 +181,16 @@
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow" id="scroller"> <object class="GtkScrolledWindow" id="scroller">
<property name="hscrollbar-policy">external</property> <property name="hscrollbar-policy">external</property>
<property name="hexpand">true</property> <property name="hexpand">true</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeView" id="tree_view"> <object class="GtkTreeView" id="tree_view">
<property name="headers-visible">false</property>
<property name="enable-grid-lines">horizontal</property> <property name="enable-grid-lines">horizontal</property>
<property name="has-tooltip">true</property> <property name="has-tooltip">true</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="duration_column"> <object class="GtkTreeViewColumn" id="duration_column">
<property name="title" translatable="yes">Duration</property> <property name="title" translatable="yes">Duration</property>
@ -235,20 +216,42 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="name">marks</property>
</packing>
</child> </child>
<child> <child>
<object class="DzlEmptyState"> <object class="GtkBox" id="failed">
<property name="icon-name">computer-fail-symbolic</property> <property name="halign">center</property>
<property name="title" translatable="yes">No Timings Available</property> <property name="orientation">vertical</property>
<property name="subtitle" translatable="yes">No timing data was found for the current selection</property> <property name="spacing">12</property>
<property name="visible">true</property> <property name="valign">center</property>
<child>
<object class="GtkImage">
<property name="icon-name">computer-fail-symbolic</property>
<property name="pixel-size">128</property>
</object>
</child>
<child>
<object class="GtkLabel" id="title">
<property name="label" translatable="yes">No Timings Available</property>
<style>
<class name="dim-label"/>
</style>
<attributes>
<attribute name="scale" value="2.0"/>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
<child>
<object class="GtkLabel" id="subtitle">
<property name="label" translatable="yes">No timing data was found for the current selection</property>
<property name="use-markup">true</property>
<property name="wrap">true</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object> </object>
<packing>
<property name="name">empty-state</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -39,11 +39,13 @@
#include "config.h" #include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "../stackstash.h" #include "../stackstash.h"
#include "egg-paned-private.h"
#include "egg-three-grid.h"
#include "sysprof-cell-renderer-percent.h" #include "sysprof-cell-renderer-percent.h"
#include "sysprof-memprof-page.h" #include "sysprof-memprof-page.h"
#include "sysprof-profile.h" #include "sysprof-profile.h"
@ -59,15 +61,19 @@ typedef struct
GtkTreeViewColumn *function_size_column; GtkTreeViewColumn *function_size_column;
GtkCellRendererText *function_size_cell; GtkCellRendererText *function_size_cell;
GtkStack *stack; GtkStack *stack;
GtkRadioButton *summary; GtkToggleButton *summary;
GtkRadioButton *all_allocs; GtkToggleButton *all_allocs;
GtkRadioButton *temp_allocs; GtkToggleButton *temp_allocs;
GtkRadioButton *leaked_allocs_button; GtkToggleButton *leaked_allocs_button;
GtkLabel *temp_allocs_count; GtkLabel *temp_allocs_count;
GtkLabel *num_allocs; GtkLabel *num_allocs;
GtkLabel *leaked_allocs; GtkLabel *leaked_allocs;
GtkLabel *peak_allocs; GtkLabel *peak_allocs;
GtkListBox *by_size; GtkListBox *by_size;
GtkWidget *callgraph;
GtkWidget *summary_page;
GtkWidget *loading_state;
GtkWidget *empty_state;
GCancellable *cancellable; GCancellable *cancellable;
@ -174,6 +180,7 @@ update_summary (SysprofMemprofPage *self,
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self); SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
SysprofMemprofStats stats; SysprofMemprofStats stats;
g_autoptr(GString) str = NULL; g_autoptr(GString) str = NULL;
GtkWidget *child;
g_assert (SYSPROF_IS_MEMPROF_PAGE (self)); g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
g_assert (SYSPROF_IS_MEMPROF_PROFILE (profile)); g_assert (SYSPROF_IS_MEMPROF_PROFILE (profile));
@ -194,9 +201,8 @@ update_summary (SysprofMemprofPage *self,
gtk_label_set_label (priv->temp_allocs_count, str->str); gtk_label_set_label (priv->temp_allocs_count, str->str);
g_string_truncate (str, 0); g_string_truncate (str, 0);
gtk_container_foreach (GTK_CONTAINER (priv->by_size), while ((child = gtk_widget_get_first_child (GTK_WIDGET (priv->by_size))))
(GtkCallback)gtk_widget_destroy, gtk_list_box_remove (priv->by_size, child);
NULL);
for (guint i = 0; i < G_N_ELEMENTS (stats.by_size); i++) for (guint i = 0; i < G_N_ELEMENTS (stats.by_size); i++)
{ {
@ -237,7 +243,7 @@ update_summary (SysprofMemprofPage *self,
gtk_label_set_label (GTK_LABEL (title), title_str); gtk_label_set_label (GTK_LABEL (title), title_str);
gtk_label_set_xalign (GTK_LABEL (title), 0); gtk_label_set_xalign (GTK_LABEL (title), 0);
dzl_gtk_widget_add_style_class (title, "dim-label"); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (title)), "dim-label");
gtk_widget_set_margin_start (box, 6); gtk_widget_set_margin_start (box, 6);
gtk_widget_set_margin_end (box, 6); gtk_widget_set_margin_end (box, 6);
@ -267,13 +273,11 @@ update_summary (SysprofMemprofPage *self,
gtk_level_bar_set_value (GTK_LEVEL_BAR (prog), gtk_level_bar_set_value (GTK_LEVEL_BAR (prog),
stats.by_size[i].n_allocs); stats.by_size[i].n_allocs);
gtk_container_add (GTK_CONTAINER (row), box); gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_container_add (GTK_CONTAINER (box), title); gtk_box_append (GTK_BOX (box), title);
gtk_container_add (GTK_CONTAINER (box), prog); gtk_box_append (GTK_BOX (box), prog);
gtk_container_add (GTK_CONTAINER (box), subtitle); gtk_box_append (GTK_BOX (box), subtitle);
gtk_container_add (GTK_CONTAINER (priv->by_size), row); gtk_list_box_append (priv->by_size, row);
gtk_widget_show_all (row);
} }
} }
@ -310,7 +314,7 @@ sysprof_memprof_page_load (SysprofMemprofPage *self,
if (sysprof_memprof_profile_is_empty (profile)) if (sysprof_memprof_profile_is_empty (profile))
{ {
gtk_stack_set_visible_child_name (priv->stack, "summary"); gtk_stack_set_visible_child (priv->stack, priv->summary_page);
return; return;
} }
@ -345,7 +349,7 @@ sysprof_memprof_page_load (SysprofMemprofPage *self,
gtk_tree_selection_select_iter (selection, &iter); gtk_tree_selection_select_iter (selection, &iter);
} }
gtk_stack_set_visible_child_name (priv->stack, "callgraph"); gtk_stack_set_visible_child (priv->stack, priv->callgraph);
g_clear_object (&functions); g_clear_object (&functions);
} }
@ -357,7 +361,7 @@ _sysprof_memprof_page_set_failed (SysprofMemprofPage *self)
g_return_if_fail (SYSPROF_IS_MEMPROF_PAGE (self)); g_return_if_fail (SYSPROF_IS_MEMPROF_PAGE (self));
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, priv->empty_state);
} }
static void static void
@ -376,7 +380,7 @@ sysprof_memprof_page_unload (SysprofMemprofPage *self)
gtk_tree_view_set_model (priv->functions_view, NULL); gtk_tree_view_set_model (priv->functions_view, NULL);
gtk_tree_view_set_model (priv->descendants_view, NULL); gtk_tree_view_set_model (priv->descendants_view, NULL);
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, priv->empty_state);
} }
/** /**
@ -887,7 +891,7 @@ static void
copy_tree_view_selection (GtkTreeView *tree_view) copy_tree_view_selection (GtkTreeView *tree_view)
{ {
g_autoptr(GString) str = NULL; g_autoptr(GString) str = NULL;
GtkClipboard *clipboard; GdkClipboard *clipboard;
g_assert (GTK_IS_TREE_VIEW (tree_view)); g_assert (GTK_IS_TREE_VIEW (tree_view));
@ -896,24 +900,25 @@ copy_tree_view_selection (GtkTreeView *tree_view)
copy_tree_view_selection_cb, copy_tree_view_selection_cb,
str); str);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view), GDK_SELECTION_CLIPBOARD); clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view));
gtk_clipboard_set_text (clipboard, str->str, str->len); gdk_clipboard_set_text (clipboard, str->str);
} }
static void static void
sysprof_memprof_page_copy_cb (GtkWidget *widget, sysprof_memprof_page_copy_cb (GtkWidget *widget,
SysprofMemprofPage *self) const char *action_name,
GVariant *param)
{ {
SysprofMemprofPage *self = (SysprofMemprofPage *)widget;
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self); SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
GtkWidget *toplevel;
GtkWidget *focus; GtkWidget *focus;
GtkRoot *toplevel;
g_assert (GTK_IS_WIDGET (widget));
g_assert (SYSPROF_IS_MEMPROF_PAGE (self)); g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
if (!(toplevel = gtk_widget_get_toplevel (widget)) || if (!(toplevel = gtk_widget_get_root (widget)) ||
!GTK_IS_WINDOW (toplevel) || !GTK_IS_ROOT (toplevel) ||
!(focus = gtk_window_get_focus (GTK_WINDOW (toplevel)))) !(focus = gtk_root_get_focus (toplevel)))
return; return;
if (focus == GTK_WIDGET (priv->descendants_view)) if (focus == GTK_WIDGET (priv->descendants_view))
@ -973,7 +978,7 @@ sysprof_memprof_page_load_async (SysprofPage *page,
else else
g_set_object (&priv->cancellable, cancellable); g_set_object (&priv->cancellable, cancellable);
gtk_stack_set_visible_child_name (priv->stack, "loading"); gtk_stack_set_visible_child (priv->stack, priv->loading_state);
task = g_task_new (self, cancellable, callback, user_data); task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, sysprof_memprof_page_load_async); g_task_set_source_tag (task, sysprof_memprof_page_load_async);
@ -1015,12 +1020,12 @@ do_allocs (SysprofMemprofPage *self,
static void static void
mode_notify_active (SysprofMemprofPage *self, mode_notify_active (SysprofMemprofPage *self,
GParamSpec *pspec, GParamSpec *pspec,
GtkRadioButton *button) GtkToggleButton *button)
{ {
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self); SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
g_assert (SYSPROF_IS_MEMPROF_PAGE (self)); g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
g_assert (GTK_IS_RADIO_BUTTON (button)); g_assert (GTK_IS_TOGGLE_BUTTON (button));
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
{ {
@ -1106,7 +1111,6 @@ sysprof_memprof_page_class_init (SysprofMemprofPageClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass); SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass);
GtkBindingSet *bindings;
object_class->finalize = sysprof_memprof_page_finalize; object_class->finalize = sysprof_memprof_page_finalize;
object_class->get_property = sysprof_memprof_page_get_property; object_class->get_property = sysprof_memprof_page_get_property;
@ -1152,10 +1156,18 @@ sysprof_memprof_page_class_init (SysprofMemprofPageClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, leaked_allocs); gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, leaked_allocs);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, leaked_allocs_button); gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, leaked_allocs_button);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, peak_allocs); gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, peak_allocs);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, loading_state);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, empty_state);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, summary_page);
gtk_widget_class_bind_template_child_private (widget_class, SysprofMemprofPage, callgraph);
bindings = gtk_binding_set_by_class (klass); gtk_widget_class_install_action (widget_class, "page.copy", NULL, sysprof_memprof_page_copy_cb);
gtk_binding_entry_add_signal (bindings, GDK_KEY_Left, GDK_MOD1_MASK, "go-previous", 0);
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_c, GDK_CONTROL_MASK, "page.copy", NULL);
gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Left, GDK_ALT_MASK, "go-previous", NULL);
g_type_ensure (EGG_TYPE_PANED);
g_type_ensure (EGG_TYPE_THREE_GRID);
g_type_ensure (SYSPROF_TYPE_CELL_RENDERER_PERCENT); g_type_ensure (SYSPROF_TYPE_CELL_RENDERER_PERCENT);
} }
@ -1163,7 +1175,6 @@ static void
sysprof_memprof_page_init (SysprofMemprofPage *self) sysprof_memprof_page_init (SysprofMemprofPage *self)
{ {
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self); SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
DzlShortcutController *controller;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkCellRenderer *cell; GtkCellRenderer *cell;
@ -1172,7 +1183,7 @@ sysprof_memprof_page_init (SysprofMemprofPage *self)
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
gtk_stack_set_visible_child_name (priv->stack, "empty-state"); gtk_stack_set_visible_child (priv->stack, priv->empty_state);
gtk_list_box_set_header_func (priv->by_size, sep_header_func, NULL, NULL); gtk_list_box_set_header_func (priv->by_size, sep_header_func, NULL, NULL);
@ -1246,16 +1257,6 @@ sysprof_memprof_page_init (SysprofMemprofPage *self)
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->descendants_view), gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->descendants_view),
GTK_SELECTION_MULTIPLE); GTK_SELECTION_MULTIPLE);
controller = dzl_shortcut_controller_find (GTK_WIDGET (self));
dzl_shortcut_controller_add_command_callback (controller,
"org.gnome.sysprof3.capture.copy",
"<Control>c",
DZL_SHORTCUT_PHASE_BUBBLE,
(GtkCallback) sysprof_memprof_page_copy_cb,
self,
NULL);
} }
typedef struct _Descendant Descendant; typedef struct _Descendant Descendant;
@ -1542,7 +1543,7 @@ _sysprof_memprof_page_set_loading (SysprofMemprofPage *self,
priv->loading--; priv->loading--;
if (priv->loading) if (priv->loading)
gtk_stack_set_visible_child_name (priv->stack, "loading"); gtk_stack_set_visible_child (priv->stack, priv->loading_state);
else else
gtk_stack_set_visible_child_name (priv->stack, "callgraph"); gtk_stack_set_visible_child (priv->stack, priv->callgraph);
} }

View File

@ -1,45 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<template class="SysprofMemprofPage" parent="SysprofPage"> <template class="SysprofMemprofPage" parent="SysprofPage">
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkBox"> <object class="GtkCenterBox">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="visible">true</property>
<child type="center"> <child type="center">
<object class="GtkBox"> <object class="GtkBox">
<property name="margin-top">6</property> <property name="margin-top">6</property>
<property name="margin-bottom">6</property> <property name="margin-bottom">6</property>
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="homogeneous">true</property> <property name="homogeneous">true</property>
<property name="visible">true</property>
<style> <style>
<class name="linked"/> <class name="linked"/>
</style> </style>
<child> <child>
<object class="GtkRadioButton" id="summary"> <object class="GtkToggleButton" id="summary">
<property name="label" translatable="yes">Summary</property> <property name="label" translatable="yes">Summary</property>
<property name="draw-indicator">false</property>
<property name="visible">true</property>
<property name="active">false</property> <property name="active">false</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="all_allocs"> <object class="GtkToggleButton" id="all_allocs">
<property name="label" translatable="yes">All Allocations</property> <property name="label" translatable="yes">All Allocations</property>
<property name="draw-indicator">false</property>
<property name="visible">true</property>
<property name="group">summary</property> <property name="group">summary</property>
<property name="active">true</property> <property name="active">true</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkRadioButton" id="temp_allocs"> <object class="GtkToggleButton" id="temp_allocs">
<property name="label" translatable="yes">Temporary Allocations</property> <property name="label" translatable="yes">Temporary Allocations</property>
<property name="draw-indicator">false</property>
<property name="visible">true</property>
<property name="active">false</property> <property name="active">false</property>
<property name="group">summary</property> <property name="group">summary</property>
</object> </object>
@ -48,7 +40,6 @@
<object class="GtkRadioButton" id="leaked_allocs_button"> <object class="GtkRadioButton" id="leaked_allocs_button">
<property name="label" translatable="yes">Leaked Allocations</property> <property name="label" translatable="yes">Leaked Allocations</property>
<property name="draw-indicator">false</property> <property name="draw-indicator">false</property>
<property name="visible">true</property>
<property name="active">false</property> <property name="active">false</property>
<property name="group">summary</property> <property name="group">summary</property>
</object> </object>
@ -60,27 +51,25 @@
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="visible">true</property>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkStack" id="stack"> <object class="GtkStack" id="stack">
<property name="visible">true</property>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow" id="summary_page">
<property name="hscrollbar-policy">never</property> <property name="hscrollbar-policy">never</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="margin">16</property> <property name="margin-top">16</property>
<property name="margin-bottom">16</property>
<property name="margin-start">16</property>
<property name="margin-end">16</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property>
<child> <child>
<object class="DzlThreeGrid"> <object class="EggThreeGrid">
<property name="expand">true</property> <property name="hexpand">true</property>
<property name="row-spacing">6</property> <property name="row-spacing">6</property>
<property name="column-spacing">18</property> <property name="column-spacing">18</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label">Peak Allocation</property> <property name="label">Peak Allocation</property>
@ -89,47 +78,45 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">0</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="peak_allocs"> <object class="GtkLabel" id="peak_allocs">
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">true</property> <property name="selectable">true</property>
<property name="visible">false</property> <property name="visible">false</property>
<layout>
<property name="column">center</property>
<property name="row">0</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label">Number of Allocations</property> <property name="label">Number of Allocations</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="visible">true</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">1</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="num_allocs"> <object class="GtkLabel" id="num_allocs">
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">true</property> <property name="selectable">true</property>
<property name="visible">true</property> <layout>
<property name="column">center</property>
<property name="row">1</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
@ -139,104 +126,92 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">2</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="leaked_allocs"> <object class="GtkLabel" id="leaked_allocs">
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">true</property> <property name="selectable">true</property>
<property name="visible">false</property> <property name="visible">false</property>
<layout>
<property name="column">center</property>
<property name="row">2</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label">Temporary Allocations</property> <property name="label">Temporary Allocations</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="visible">true</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">3</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">3</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="temp_allocs_count"> <object class="GtkLabel" id="temp_allocs_count">
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="selectable">true</property> <property name="selectable">true</property>
<property name="width-chars">50</property> <property name="width-chars">50</property>
<property name="visible">true</property> <layout>
<property name="column">center</property>
<property name="row">3</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">3</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label">Allocations by Size</property> <property name="label">Allocations by Size</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="valign">start</property> <property name="valign">start</property>
<property name="visible">true</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">4</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">4</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkFrame"> <object class="GtkFrame">
<property name="visible">true</property>
<child> <child>
<object class="GtkListBox" id="by_size"> <object class="GtkListBox" id="by_size">
<property name="visible">true</property>
</object> </object>
</child> </child>
<layout>
<property name="column">center</property>
<property name="row">4</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">4</property>
</packing>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="name">summary</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkPaned"> <object class="EggPaned" id="callgraph">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="position">450</property> <property name="vexpand">true</property>
<property name="expand">true</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkPaned"> <object class="EggPaned">
<property name="width-request">400</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeView" id="functions_view"> <object class="GtkTreeView" id="functions_view">
<property name="fixed-height-mode">true</property> <property name="fixed-height-mode">true</property>
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="function_name_column"> <object class="GtkTreeViewColumn" id="function_name_column">
<property name="expand">true</property> <property name="expand">true</property>
@ -289,16 +264,11 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="resize">true</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeView" id="callers_view"> <object class="GtkTreeView" id="callers_view">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="callers_name_column"> <object class="GtkTreeViewColumn" id="callers_name_column">
<property name="expand">true</property> <property name="expand">true</property>
@ -351,18 +321,13 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="resize">true</property>
</packing>
</child> </child>
</object> </object>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeView" id="descendants_view"> <object class="GtkTreeView" id="descendants_view">
<property name="visible">true</property>
<child> <child>
<object class="GtkTreeViewColumn" id="descendants_name_column"> <object class="GtkTreeViewColumn" id="descendants_name_column">
<property name="expand">true</property> <property name="expand">true</property>
@ -421,31 +386,20 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="name">callgraph</property>
</packing>
</child> </child>
<child> <child>
<object class="DzlEmptyState"> <object class="AdwStatusPage" id="loading_state">
<property name="icon-name">content-loading-symbolic</property> <property name="icon-name">content-loading-symbolic</property>
<property name="title" translatable="yes">Analyzing Memory Allocations</property> <property name="title" translatable="yes">Analyzing Memory Allocations</property>
<property name="subtitle" translatable="yes">Sysprof is busy analyzing memory allocations.</property> <property name="description" translatable="yes">Sysprof is busy analyzing memory allocations.</property>
<property name="visible">true</property>
</object> </object>
<packing>
<property name="name">loading</property>
</packing>
</child> </child>
<child> <child>
<object class="DzlEmptyState"> <object class="AdwStatusPage" id="empty_state">
<property name="icon-name">computer-fail-symbolic</property> <property name="icon-name">computer-fail-symbolic</property>
<property name="title" translatable="yes">Not Enough Samples</property> <property name="title" translatable="yes">Not Enough Samples</property>
<property name="subtitle" translatable="yes">More samples are necessary to display a callgraph.</property> <property name="description" translatable="yes">More samples are necessary to display a callgraph.</property>
<property name="visible">false</property>
</object> </object>
<packing>
<property name="name">empty-state</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -528,49 +528,46 @@ sysprof_memprof_visualizer_queue_redraw (SysprofMemprofVisualizer *self)
} }
static void static void
sysprof_memprof_visualizer_size_allocate (GtkWidget *widget, sysprof_memprof_visualizer_size_allocate (GtkWidget *widget,
GtkAllocation *alloc) int width,
int height,
int baseline)
{ {
SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)widget; sysprof_memprof_visualizer_queue_redraw (SYSPROF_MEMPROF_VISUALIZER (widget));
g_assert (GTK_IS_WIDGET (widget));
g_assert (alloc != NULL);
GTK_WIDGET_CLASS (sysprof_memprof_visualizer_parent_class)->size_allocate (widget, alloc);
sysprof_memprof_visualizer_queue_redraw (self);
} }
static void static void
sysprof_memprof_visualizer_destroy (GtkWidget *widget) sysprof_memprof_visualizer_dispose (GObject *object)
{ {
SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)widget; SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)object;
g_clear_pointer (&self->reader, sysprof_capture_reader_unref); g_clear_pointer (&self->reader, sysprof_capture_reader_unref);
g_clear_pointer (&self->surface, cairo_surface_destroy); g_clear_pointer (&self->surface, cairo_surface_destroy);
g_clear_handle_id (&self->queued_draw, g_source_remove); g_clear_handle_id (&self->queued_draw, g_source_remove);
GTK_WIDGET_CLASS (sysprof_memprof_visualizer_parent_class)->destroy (widget); G_OBJECT_CLASS (sysprof_memprof_visualizer_parent_class)->dispose (object);
} }
static gboolean static void
sysprof_memprof_visualizer_draw (GtkWidget *widget, sysprof_memprof_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)widget; SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)widget;
gboolean ret;
g_assert (SYSPROF_IS_MEMPROF_VISUALIZER (self)); g_assert (SYSPROF_IS_MEMPROF_VISUALIZER (self));
g_assert (cr != NULL); g_assert (GTK_IS_SNAPSHOT (snapshot));
ret = GTK_WIDGET_CLASS (sysprof_memprof_visualizer_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_memprof_visualizer_parent_class)->snapshot (widget, snapshot);
if (self->surface != NULL) if (self->surface != NULL)
{ {
cairo_t *cr;
GtkAllocation alloc; GtkAllocation alloc;
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, alloc.width, alloc.height));
cairo_save (cr); cairo_save (cr);
cairo_rectangle (cr, 0, 0, alloc.width, alloc.height); cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
@ -590,19 +587,21 @@ sysprof_memprof_visualizer_draw (GtkWidget *widget,
cairo_set_source_surface (cr, self->surface, 0, 0); cairo_set_source_surface (cr, self->surface, 0, 0);
cairo_paint (cr); cairo_paint (cr);
cairo_restore (cr); cairo_restore (cr);
}
return ret; cairo_destroy (cr);
}
} }
static void static void
sysprof_memprof_visualizer_class_init (SysprofMemprofVisualizerClass *klass) sysprof_memprof_visualizer_class_init (SysprofMemprofVisualizerClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofVisualizerClass *visualizer_class = SYSPROF_VISUALIZER_CLASS (klass); SysprofVisualizerClass *visualizer_class = SYSPROF_VISUALIZER_CLASS (klass);
widget_class->destroy = sysprof_memprof_visualizer_destroy; object_class->dispose = sysprof_memprof_visualizer_dispose;
widget_class->draw = sysprof_memprof_visualizer_draw;
widget_class->snapshot = sysprof_memprof_visualizer_snapshot;
widget_class->size_allocate = sysprof_memprof_visualizer_size_allocate; widget_class->size_allocate = sysprof_memprof_visualizer_size_allocate;
visualizer_class->set_reader = sysprof_memprof_visualizer_set_reader; visualizer_class->set_reader = sysprof_memprof_visualizer_set_reader;

View File

@ -242,7 +242,7 @@ sysprof_netdev_aid_present_finish (SysprofAid *aid,
if (counters->len > 0) if (counters->len > 0)
sysprof_display_add_group (present->display, group); sysprof_display_add_group (present->display, group);
else else
gtk_widget_destroy (GTK_WIDGET (group)); g_object_unref (g_object_ref_sink (group));
} }
return counters != NULL; return counters != NULL;

View File

@ -29,10 +29,15 @@
typedef struct typedef struct
{ {
GtkNotebook *notebook;
guint always_show_tabs : 1; guint always_show_tabs : 1;
} SysprofNotebookPrivate; } SysprofNotebookPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofNotebook, sysprof_notebook, GTK_TYPE_NOTEBOOK) static void buildable_iface_init (GtkBuildableIface *iface);
G_DEFINE_TYPE_WITH_CODE (SysprofNotebook, sysprof_notebook, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (SysprofNotebook)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init))
enum { enum {
PROP_0, PROP_0,
@ -83,15 +88,16 @@ sysprof_notebook_notify_can_replay_cb (SysprofNotebook *self,
} }
static void static void
sysprof_notebook_page_added (GtkNotebook *notebook, sysprof_notebook_page_added (SysprofNotebook *self,
GtkWidget *child, GtkWidget *child,
guint page_num) guint page_num,
GtkNotebook *notebook)
{ {
SysprofNotebook *self = (SysprofNotebook *)notebook;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self); SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_assert (SYSPROF_IS_NOTEBOOK (self)); g_assert (SYSPROF_IS_NOTEBOOK (self));
g_assert (GTK_IS_WIDGET (child)); g_assert (GTK_IS_WIDGET (child));
g_assert (GTK_IS_NOTEBOOK (notebook));
gtk_notebook_set_show_tabs (notebook, gtk_notebook_set_show_tabs (notebook,
(priv->always_show_tabs || (priv->always_show_tabs ||
@ -107,13 +113,13 @@ sysprof_notebook_page_added (GtkNotebook *notebook,
g_signal_connect_object (child, g_signal_connect_object (child,
"notify::can-replay", "notify::can-replay",
G_CALLBACK (sysprof_notebook_notify_can_replay_cb), G_CALLBACK (sysprof_notebook_notify_can_replay_cb),
notebook, self,
G_CONNECT_SWAPPED); G_CONNECT_SWAPPED);
g_signal_connect_object (child, g_signal_connect_object (child,
"notify::can-save", "notify::can-save",
G_CALLBACK (sysprof_notebook_notify_can_save_cb), G_CALLBACK (sysprof_notebook_notify_can_save_cb),
notebook, self,
G_CONNECT_SWAPPED); G_CONNECT_SWAPPED);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_REPLAY]); g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_REPLAY]);
@ -125,15 +131,16 @@ sysprof_notebook_page_added (GtkNotebook *notebook,
} }
static void static void
sysprof_notebook_page_removed (GtkNotebook *notebook, sysprof_notebook_page_removed (SysprofNotebook *self,
GtkWidget *child, GtkWidget *child,
guint page_num) guint page_num,
GtkNotebook *notebook)
{ {
SysprofNotebook *self = (SysprofNotebook *)notebook;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self); SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_assert (SYSPROF_IS_NOTEBOOK (self)); g_assert (SYSPROF_IS_NOTEBOOK (self));
g_assert (GTK_IS_WIDGET (child)); g_assert (GTK_IS_WIDGET (child));
g_assert (GTK_IS_NOTEBOOK (notebook));
if (gtk_widget_in_destruction (GTK_WIDGET (notebook))) if (gtk_widget_in_destruction (GTK_WIDGET (notebook)))
return; return;
@ -141,16 +148,16 @@ sysprof_notebook_page_removed (GtkNotebook *notebook,
if (gtk_notebook_get_n_pages (notebook) == 0) if (gtk_notebook_get_n_pages (notebook) == 0)
{ {
child = sysprof_display_new (); child = sysprof_display_new ();
gtk_container_add (GTK_CONTAINER (notebook), child); gtk_notebook_append_page (notebook, child, NULL);
gtk_widget_show (child); gtk_widget_show (child);
g_signal_handlers_disconnect_by_func (child, g_signal_handlers_disconnect_by_func (child,
G_CALLBACK (sysprof_notebook_notify_can_save_cb), G_CALLBACK (sysprof_notebook_notify_can_save_cb),
notebook); notebook);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_REPLAY]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CAN_REPLAY]);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_SAVE]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CAN_SAVE]);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CURRENT]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CURRENT]);
} }
gtk_notebook_set_show_tabs (notebook, gtk_notebook_set_show_tabs (notebook,
@ -159,18 +166,33 @@ sysprof_notebook_page_removed (GtkNotebook *notebook,
} }
static void static void
sysprof_notebook_switch_page (GtkNotebook *notebook, sysprof_notebook_switch_page (SysprofNotebook *self,
GtkWidget *widget, GtkWidget *widget,
guint page) guint page,
GtkNotebook *notebook)
{ {
g_assert (SYSPROF_IS_NOTEBOOK (self));
g_assert (GTK_IS_NOTEBOOK (notebook)); g_assert (GTK_IS_NOTEBOOK (notebook));
g_assert (GTK_IS_WIDGET (widget)); g_assert (GTK_IS_WIDGET (widget));
GTK_NOTEBOOK_CLASS (sysprof_notebook_parent_class)->switch_page (notebook, widget, page); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CAN_REPLAY]);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CAN_SAVE]);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CURRENT]);
}
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_REPLAY]); static void
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_SAVE]); sysprof_notebook_dispose (GObject *object)
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CURRENT]); {
SysprofNotebook *self = (SysprofNotebook *)object;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
if (priv->notebook)
{
gtk_widget_unparent (GTK_WIDGET (priv->notebook));
priv->notebook = NULL;
}
G_OBJECT_CLASS (sysprof_notebook_parent_class)->dispose (object);
} }
static void static void
@ -227,15 +249,12 @@ static void
sysprof_notebook_class_init (SysprofNotebookClass *klass) sysprof_notebook_class_init (SysprofNotebookClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = sysprof_notebook_dispose;
object_class->get_property = sysprof_notebook_get_property; object_class->get_property = sysprof_notebook_get_property;
object_class->set_property = sysprof_notebook_set_property; object_class->set_property = sysprof_notebook_set_property;
notebook_class->page_added = sysprof_notebook_page_added;
notebook_class->page_removed = sysprof_notebook_page_removed;
notebook_class->switch_page = sysprof_notebook_switch_page;
properties [PROP_ALWAYS_SHOW_TABS] = properties [PROP_ALWAYS_SHOW_TABS] =
g_param_spec_boolean ("always-show-tabs", g_param_spec_boolean ("always-show-tabs",
"Always Show Tabs", "Always Show Tabs",
@ -265,71 +284,86 @@ sysprof_notebook_class_init (SysprofNotebookClass *klass)
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties); g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
} }
static void static void
sysprof_notebook_init (SysprofNotebook *self) sysprof_notebook_init (SysprofNotebook *self)
{ {
gtk_notebook_set_show_border (GTK_NOTEBOOK (self), FALSE); SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
gtk_notebook_set_scrollable (GTK_NOTEBOOK (self), TRUE);
gtk_notebook_popup_enable (GTK_NOTEBOOK (self)); priv->notebook = GTK_NOTEBOOK (gtk_notebook_new ());
gtk_widget_set_parent (GTK_WIDGET (priv->notebook), GTK_WIDGET (self));
gtk_notebook_set_show_border (priv->notebook, FALSE);
gtk_notebook_set_scrollable (priv->notebook, TRUE);
gtk_notebook_popup_enable (priv->notebook);
g_signal_connect_object (priv->notebook,
"page-added",
G_CALLBACK (sysprof_notebook_page_added),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (priv->notebook,
"page-removed",
G_CALLBACK (sysprof_notebook_page_removed),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (priv->notebook,
"switch-page",
G_CALLBACK (sysprof_notebook_switch_page),
self,
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
} }
void void
sysprof_notebook_close_current (SysprofNotebook *self) sysprof_notebook_close_current (SysprofNotebook *self)
{ {
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
gint page; gint page;
g_return_if_fail (SYSPROF_IS_NOTEBOOK (self)); g_return_if_fail (SYSPROF_IS_NOTEBOOK (self));
if ((page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self))) >= 0) if ((page = gtk_notebook_get_current_page (priv->notebook)) >= 0)
gtk_widget_destroy (gtk_notebook_get_nth_page (GTK_NOTEBOOK (self), page)); gtk_notebook_remove_page (priv->notebook, page);
}
static void
find_empty_display_cb (GtkWidget *widget,
gpointer user_data)
{
GtkWidget **display = user_data;
g_assert (GTK_IS_WIDGET (widget));
g_assert (display != NULL);
if (*display != NULL)
return;
if (SYSPROF_IS_DISPLAY (widget) &&
sysprof_display_is_empty (SYSPROF_DISPLAY (widget)))
*display = widget;
} }
void void
sysprof_notebook_open (SysprofNotebook *self, sysprof_notebook_open (SysprofNotebook *self,
GFile *file) GFile *file)
{ {
GtkWidget *display = NULL; SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
gint page; SysprofDisplay *display = NULL;
int page;
g_return_if_fail (SYSPROF_IS_NOTEBOOK (self)); g_return_if_fail (SYSPROF_IS_NOTEBOOK (self));
g_return_if_fail (g_file_is_native (file)); g_return_if_fail (g_file_is_native (file));
gtk_container_foreach (GTK_CONTAINER (self), for (page = 0; page < sysprof_notebook_get_n_pages (self); page++)
find_empty_display_cb, {
&display); SysprofDisplay *child = sysprof_notebook_get_nth_page (self, page);
if (sysprof_display_is_empty (child))
{
display = child;
break;
}
}
if (display == NULL) if (display == NULL)
{ {
display = SYSPROF_DISPLAY (sysprof_display_new ());
display = sysprof_display_new (); page = sysprof_notebook_append (self, display);
page = gtk_notebook_insert_page (GTK_NOTEBOOK (self), display, NULL, -1);
gtk_widget_show (display);
} }
else else
{ {
page = gtk_notebook_page_num (GTK_NOTEBOOK (self), display); page = gtk_notebook_page_num (priv->notebook, GTK_WIDGET (display));
} }
gtk_notebook_set_current_page (GTK_NOTEBOOK (self), page); sysprof_notebook_set_current_page (self, page);
sysprof_display_open (SYSPROF_DISPLAY (display), file); sysprof_display_open (SYSPROF_DISPLAY (display), file);
} }
@ -337,12 +371,13 @@ sysprof_notebook_open (SysprofNotebook *self,
SysprofDisplay * SysprofDisplay *
sysprof_notebook_get_current (SysprofNotebook *self) sysprof_notebook_get_current (SysprofNotebook *self)
{ {
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
gint page; gint page;
g_assert (SYSPROF_IS_NOTEBOOK (self)); g_assert (SYSPROF_IS_NOTEBOOK (self));
if ((page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self))) >= 0) if ((page = gtk_notebook_get_current_page (priv->notebook)) >= 0)
return SYSPROF_DISPLAY (gtk_notebook_get_nth_page (GTK_NOTEBOOK (self), page)); return SYSPROF_DISPLAY (gtk_notebook_get_nth_page (priv->notebook, page));
return NULL; return NULL;
} }
@ -387,6 +422,7 @@ sysprof_notebook_get_can_replay (SysprofNotebook *self)
void void
sysprof_notebook_replay (SysprofNotebook *self) sysprof_notebook_replay (SysprofNotebook *self)
{ {
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
SysprofDisplay *display; SysprofDisplay *display;
SysprofDisplay *replay; SysprofDisplay *replay;
gint page; gint page;
@ -401,15 +437,16 @@ sysprof_notebook_replay (SysprofNotebook *self)
g_return_if_fail (SYSPROF_IS_DISPLAY (replay)); g_return_if_fail (SYSPROF_IS_DISPLAY (replay));
gtk_widget_show (GTK_WIDGET (replay)); gtk_widget_show (GTK_WIDGET (replay));
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (replay)); gtk_notebook_append_page (priv->notebook, GTK_WIDGET (replay), NULL);
page = gtk_notebook_page_num (GTK_NOTEBOOK (self), GTK_WIDGET (replay)); page = gtk_notebook_page_num (priv->notebook, GTK_WIDGET (replay));
gtk_notebook_set_current_page (GTK_NOTEBOOK (self), page); gtk_notebook_set_current_page (priv->notebook, page);
} }
void void
sysprof_notebook_add_profiler (SysprofNotebook *self, sysprof_notebook_add_profiler (SysprofNotebook *self,
SysprofProfiler *profiler) SysprofProfiler *profiler)
{ {
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
GtkWidget *display; GtkWidget *display;
gint page; gint page;
@ -419,9 +456,9 @@ sysprof_notebook_add_profiler (SysprofNotebook *self,
display = sysprof_display_new_for_profiler (profiler); display = sysprof_display_new_for_profiler (profiler);
gtk_widget_show (display); gtk_widget_show (display);
gtk_container_add (GTK_CONTAINER (self), display); gtk_notebook_append_page (priv->notebook, GTK_WIDGET (display), NULL);
page = gtk_notebook_page_num (GTK_NOTEBOOK (self), display); page = gtk_notebook_page_num (priv->notebook, display);
gtk_notebook_set_current_page (GTK_NOTEBOOK (self), page); gtk_notebook_set_current_page (priv->notebook, page);
} }
gboolean gboolean
@ -447,9 +484,78 @@ sysprof_notebook_set_always_show_tabs (SysprofNotebook *self,
if (always_show_tabs != priv->always_show_tabs) if (always_show_tabs != priv->always_show_tabs)
{ {
priv->always_show_tabs = always_show_tabs; priv->always_show_tabs = always_show_tabs;
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self), gtk_notebook_set_show_tabs (priv->notebook,
(priv->always_show_tabs || (priv->always_show_tabs ||
gtk_notebook_get_n_pages (GTK_NOTEBOOK (self)) > 1)); gtk_notebook_get_n_pages (priv->notebook) > 1));
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ALWAYS_SHOW_TABS]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ALWAYS_SHOW_TABS]);
} }
} }
static void
sysprof_notebook_add_child (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const char *type)
{
SysprofNotebook *self = (SysprofNotebook *)buildable;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_assert (SYSPROF_IS_NOTEBOOK (self));
if (SYSPROF_IS_DISPLAY (child))
gtk_notebook_append_page (priv->notebook, GTK_WIDGET (child), NULL);
else
g_warning ("Cannot add child of type %s to %s",
G_OBJECT_TYPE_NAME (child),
G_OBJECT_TYPE_NAME (self));
}
static void
buildable_iface_init (GtkBuildableIface *iface)
{
iface->add_child = sysprof_notebook_add_child;
}
guint
sysprof_notebook_get_n_pages (SysprofNotebook *self)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_return_val_if_fail (SYSPROF_IS_NOTEBOOK (self), 0);
return gtk_notebook_get_n_pages (priv->notebook);
}
SysprofDisplay *
sysprof_notebook_get_nth_page (SysprofNotebook *self,
guint nth)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_return_val_if_fail (SYSPROF_IS_NOTEBOOK (self), NULL);
return SYSPROF_DISPLAY (gtk_notebook_get_nth_page (priv->notebook, nth));
}
void
sysprof_notebook_set_current_page (SysprofNotebook *self,
int nth)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_return_if_fail (SYSPROF_IS_NOTEBOOK (self));
gtk_notebook_set_current_page (priv->notebook, nth);
}
int
sysprof_notebook_append (SysprofNotebook *self,
SysprofDisplay *display)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_return_val_if_fail (SYSPROF_IS_NOTEBOOK (self), -1);
g_return_val_if_fail (SYSPROF_IS_DISPLAY (display), -1);
return gtk_notebook_append_page (priv->notebook, GTK_WIDGET (display), NULL);
}

View File

@ -35,11 +35,11 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_NOTEBOOK (sysprof_notebook_get_type()) #define SYSPROF_TYPE_NOTEBOOK (sysprof_notebook_get_type())
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (SysprofNotebook, sysprof_notebook, SYSPROF, NOTEBOOK, GtkNotebook) G_DECLARE_DERIVABLE_TYPE (SysprofNotebook, sysprof_notebook, SYSPROF, NOTEBOOK, GtkWidget)
struct _SysprofNotebookClass struct _SysprofNotebookClass
{ {
GtkNotebookClass parent_class; GtkWidgetClass parent_class;
/*< private >*/ /*< private >*/
gpointer _reserved[16]; gpointer _reserved[16];
@ -70,5 +70,16 @@ gboolean sysprof_notebook_get_always_show_tabs (SysprofNotebook *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_notebook_set_always_show_tabs (SysprofNotebook *self, void sysprof_notebook_set_always_show_tabs (SysprofNotebook *self,
gboolean always_show_tabs); gboolean always_show_tabs);
SYSPROF_AVAILABLE_IN_ALL
guint sysprof_notebook_get_n_pages (SysprofNotebook *self);
SYSPROF_AVAILABLE_IN_ALL
SysprofDisplay *sysprof_notebook_get_nth_page (SysprofNotebook *self,
guint nth);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_notebook_set_current_page (SysprofNotebook *self,
int page);
SYSPROF_AVAILABLE_IN_ALL
int sysprof_notebook_append (SysprofNotebook *self,
SysprofDisplay *display);
G_END_DECLS G_END_DECLS

View File

@ -31,7 +31,7 @@ typedef struct
gchar *title; gchar *title;
} SysprofPagePrivate; } SysprofPagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofPage, sysprof_page, GTK_TYPE_BIN) G_DEFINE_TYPE_WITH_PRIVATE (SysprofPage, sysprof_page, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -105,14 +105,18 @@ sysprof_page_real_load_finish (SysprofPage *self,
} }
static void static void
sysprof_page_finalize (GObject *object) sysprof_page_dispose (GObject *object)
{ {
SysprofPage *self = (SysprofPage *)object; SysprofPage *self = (SysprofPage *)object;
SysprofPagePrivate *priv = sysprof_page_get_instance_private (self); SysprofPagePrivate *priv = sysprof_page_get_instance_private (self);
GtkWidget *child;
g_clear_pointer (&priv->title, g_free); g_clear_pointer (&priv->title, g_free);
G_OBJECT_CLASS (sysprof_page_parent_class)->finalize (object); while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (sysprof_page_parent_class)->dispose (object);
} }
static void static void
@ -157,8 +161,9 @@ static void
sysprof_page_class_init (SysprofPageClass *klass) sysprof_page_class_init (SysprofPageClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = sysprof_page_finalize; object_class->dispose = sysprof_page_dispose;
object_class->get_property = sysprof_page_get_property; object_class->get_property = sysprof_page_get_property;
object_class->set_property = sysprof_page_set_property; object_class->set_property = sysprof_page_set_property;
@ -173,11 +178,14 @@ sysprof_page_class_init (SysprofPageClass *klass)
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties); g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
} }
static void static void
sysprof_page_init (SysprofPage *self) sysprof_page_init (SysprofPage *self)
{ {
gtk_widget_set_vexpand (GTK_WIDGET (self), TRUE);
} }
/** /**

View File

@ -32,11 +32,11 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_PAGE (sysprof_page_get_type()) #define SYSPROF_TYPE_PAGE (sysprof_page_get_type())
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (SysprofPage, sysprof_page, SYSPROF, PAGE, GtkBin) G_DECLARE_DERIVABLE_TYPE (SysprofPage, sysprof_page, SYSPROF, PAGE, GtkWidget)
struct _SysprofPageClass struct _SysprofPageClass
{ {
GtkBinClass parent_class; GtkWidgetClass parent_class;
void (*load_async) (SysprofPage *self, void (*load_async) (SysprofPage *self,
SysprofCaptureReader *reader, SysprofCaptureReader *reader,

View File

@ -4,7 +4,10 @@
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">true</property> <property name="visible">true</property>
<property name="margin">6</property> <property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="spacing">6</property> <property name="spacing">6</property>
<child> <child>
<object class="GtkImage" id="image"> <object class="GtkImage" id="image">

View File

@ -183,24 +183,24 @@ sysprof_procs_visualizer_set_reader (SysprofVisualizer *visualizer,
g_task_run_in_thread (task, discovery_worker); g_task_run_in_thread (task, discovery_worker);
} }
static gboolean static void
sysprof_procs_visualizer_draw (GtkWidget *widget, sysprof_procs_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofProcsVisualizer *self = (SysprofProcsVisualizer *)widget; SysprofProcsVisualizer *self = (SysprofProcsVisualizer *)widget;
g_autofree SysprofVisualizerAbsolutePoint *points = NULL; g_autofree SysprofVisualizerAbsolutePoint *points = NULL;
gboolean ret = GDK_EVENT_PROPAGATE;
GtkAllocation alloc; GtkAllocation alloc;
GdkRGBA background; GdkRGBA background;
GdkRGBA foreground; GdkRGBA foreground;
const Point *fpoints; const Point *fpoints;
guint n_fpoints = 0; guint n_fpoints = 0;
Discovery *d; Discovery *d;
cairo_t *cr;
gdouble last_x = 0; gdouble last_x = 0;
gdouble last_y = 0; gdouble last_y = 0;
g_assert (SYSPROF_IS_PROCS_VISUALIZER (self)); g_assert (SYSPROF_IS_PROCS_VISUALIZER (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
@ -208,14 +208,17 @@ sysprof_procs_visualizer_draw (GtkWidget *widget,
background = foreground; background = foreground;
background.alpha *= .5; background.alpha *= .5;
ret = GTK_WIDGET_CLASS (sysprof_procs_visualizer_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_procs_visualizer_parent_class)->snapshot (widget, snapshot);
if (!(d = self->discovery) || d->cache == NULL) if (!(d = self->discovery) || d->cache == NULL)
return ret; return;
if (!(fpoints = point_cache_get_points (d->cache, 1, &n_fpoints))) if (!(fpoints = point_cache_get_points (d->cache, 1, &n_fpoints)))
return ret; return;
/* This is all going to need offscreen drawing instead of new cairo every frame */
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, alloc.width, alloc.height));
points = g_new0 (SysprofVisualizerAbsolutePoint, n_fpoints); points = g_new0 (SysprofVisualizerAbsolutePoint, n_fpoints);
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (self), sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (self),
@ -254,7 +257,7 @@ sysprof_procs_visualizer_draw (GtkWidget *widget,
gdk_cairo_set_source_rgba (cr, &foreground); gdk_cairo_set_source_rgba (cr, &foreground);
cairo_stroke (cr); cairo_stroke (cr);
return ret; cairo_destroy (cr);
} }
static void static void
@ -276,7 +279,7 @@ sysprof_procs_visualizer_class_init (SysprofProcsVisualizerClass *klass)
object_class->finalize = sysprof_procs_visualizer_finalize; object_class->finalize = sysprof_procs_visualizer_finalize;
widget_class->draw = sysprof_procs_visualizer_draw; widget_class->snapshot = sysprof_procs_visualizer_snapshot;
visualizer_class->set_reader = sysprof_procs_visualizer_set_reader; visualizer_class->set_reader = sysprof_procs_visualizer_set_reader;
} }

View File

@ -24,6 +24,8 @@
#include <sysprof.h> #include <sysprof.h>
#include "egg-three-grid.h"
#include "sysprof-platform.h" #include "sysprof-platform.h"
#include "sysprof-aid-icon.h" #include "sysprof-aid-icon.h"
@ -45,7 +47,7 @@
struct _SysprofProfilerAssistant struct _SysprofProfilerAssistant
{ {
GtkBin parent_instance; GtkWidget parent_instance;
SysprofProcessModel *process_model; SysprofProcessModel *process_model;
@ -61,6 +63,7 @@ struct _SysprofProfilerAssistant
GtkSwitch *whole_system_switch; GtkSwitch *whole_system_switch;
GtkSwitch *launch_switch; GtkSwitch *launch_switch;
GtkSwitch *inherit_switch; GtkSwitch *inherit_switch;
GtkWidget *scroller;
}; };
enum { enum {
@ -70,7 +73,7 @@ enum {
static guint signals [N_SIGNALS]; static guint signals [N_SIGNALS];
G_DEFINE_TYPE (SysprofProfilerAssistant, sysprof_profiler_assistant, GTK_TYPE_BIN) G_DEFINE_TYPE (SysprofProfilerAssistant, sysprof_profiler_assistant, GTK_TYPE_WIDGET)
/** /**
* sysprof_profiler_assistant_new: * sysprof_profiler_assistant_new:
@ -155,12 +158,12 @@ sysprof_profiler_assistant_command_line_changed_cb (SysprofProfilerAssistant *se
g_assert (GTK_IS_ENTRY (entry)); g_assert (GTK_IS_ENTRY (entry));
style_context = gtk_widget_get_style_context (GTK_WIDGET (entry)); style_context = gtk_widget_get_style_context (GTK_WIDGET (entry));
text = gtk_entry_get_text (entry); text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (text == NULL || text[0] == 0 || g_shell_parse_argv (text, &argc, &argv, NULL)) if (text == NULL || text[0] == 0 || g_shell_parse_argv (text, &argc, &argv, NULL))
gtk_style_context_remove_class (style_context, GTK_STYLE_CLASS_ERROR); gtk_style_context_remove_class (style_context, "error");
else else
gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_ERROR); gtk_style_context_add_class (style_context, "error");
} }
static void static void
@ -222,9 +225,10 @@ sysprof_profiler_assistant_record_clicked_cb (SysprofProfilerAssistant *self,
sysprof_profiler_set_writer (profiler, writer); sysprof_profiler_set_writer (profiler, writer);
/* Add pids to profiler */ /* Add pids to profiler */
gtk_container_foreach (GTK_CONTAINER (self->process_list_box), for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->process_list_box));
(GtkCallback) sysprof_profiler_assistant_foreach_cb, child;
profiler); child = gtk_widget_get_next_sibling (child))
sysprof_profiler_assistant_foreach_cb (child, profiler);
/* Setup whole system profiling */ /* Setup whole system profiling */
sysprof_profiler_set_whole_system (profiler, gtk_switch_get_active (self->whole_system_switch)); sysprof_profiler_set_whole_system (profiler, gtk_switch_get_active (self->whole_system_switch));
@ -237,7 +241,7 @@ sysprof_profiler_assistant_record_clicked_cb (SysprofProfilerAssistant *self,
const gchar *command; const gchar *command;
gint argc; gint argc;
command = gtk_entry_get_text (self->command_line); command = gtk_editable_get_text (GTK_EDITABLE (self->command_line));
g_shell_parse_argv (command, &argc, &argv, NULL); g_shell_parse_argv (command, &argc, &argv, NULL);
sysprof_profiler_set_spawn (profiler, TRUE); sysprof_profiler_set_spawn (profiler, TRUE);
@ -269,9 +273,10 @@ sysprof_profiler_assistant_record_clicked_cb (SysprofProfilerAssistant *self,
sysprof_profiler_add_source (profiler, symbols_source); sysprof_profiler_add_source (profiler, symbols_source);
/* Now allow the aids to add their sources */ /* Now allow the aids to add their sources */
gtk_container_foreach (GTK_CONTAINER (self->aid_flow_box), for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->aid_flow_box));
(GtkCallback) sysprof_profiler_assistant_foreach_cb, child;
profiler); child = gtk_widget_get_next_sibling (child))
sysprof_profiler_assistant_foreach_cb (child, profiler);
g_signal_emit (self, signals [START_RECORDING], 0, profiler); g_signal_emit (self, signals [START_RECORDING], 0, profiler);
} }
@ -322,7 +327,7 @@ sysprof_profiler_assistant_search_changed_cb (SysprofProfilerAssistant *self,
sysprof_process_model_queue_reload (self->process_model); sysprof_process_model_queue_reload (self->process_model);
text = gtk_entry_get_text (GTK_ENTRY (search_entry)); text = gtk_editable_get_text (GTK_EDITABLE (search_entry));
if (text[0] == 0) if (text[0] == 0)
{ {
@ -345,21 +350,23 @@ sysprof_profiler_assistant_search_changed_cb (SysprofProfilerAssistant *self,
} }
static void static void
sysprof_profiler_assistant_destroy (GtkWidget *widget) sysprof_profiler_assistant_dispose (GObject *object)
{ {
SysprofProfilerAssistant *self = (SysprofProfilerAssistant *)widget; SysprofProfilerAssistant *self = (SysprofProfilerAssistant *)object;
g_clear_object (&self->process_model); g_clear_object (&self->process_model);
g_clear_pointer (&self->scroller, gtk_widget_unparent);
GTK_WIDGET_CLASS (sysprof_profiler_assistant_parent_class)->destroy (widget); G_OBJECT_CLASS (sysprof_profiler_assistant_parent_class)->dispose (object);
} }
static void static void
sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass) sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->destroy = sysprof_profiler_assistant_destroy; object_class->dispose = sysprof_profiler_assistant_dispose;
/** /**
* SysprofProfilerAssistant::start-recording: * SysprofProfilerAssistant::start-recording:
@ -377,6 +384,7 @@ sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass)
G_TYPE_NONE, 1, SYSPROF_TYPE_PROFILER); G_TYPE_NONE, 1, SYSPROF_TYPE_PROFILER);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-profiler-assistant.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-profiler-assistant.ui");
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, allow_throttling); gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, allow_throttling);
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, aid_flow_box); gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, aid_flow_box);
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, command_line); gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, command_line);
@ -388,6 +396,9 @@ sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass)
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, launch_switch); gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, launch_switch);
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, inherit_switch); gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, inherit_switch);
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, search_entry); gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, search_entry);
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, scroller);
g_type_ensure (EGG_TYPE_THREE_GRID);
g_type_ensure (SYSPROF_TYPE_AID_ICON); g_type_ensure (SYSPROF_TYPE_AID_ICON);
g_type_ensure (SYSPROF_TYPE_BATTERY_AID); g_type_ensure (SYSPROF_TYPE_BATTERY_AID);
@ -465,12 +476,12 @@ sysprof_profiler_assistant_set_executable (SysprofProfilerAssistant *self,
if (path == NULL || path[0] == 0) if (path == NULL || path[0] == 0)
{ {
gtk_entry_set_text (GTK_ENTRY (self->command_line), ""); gtk_editable_set_text (GTK_EDITABLE (self->command_line), "");
gtk_switch_set_active (self->launch_switch, FALSE); gtk_switch_set_active (self->launch_switch, FALSE);
} }
else else
{ {
gtk_entry_set_text (GTK_ENTRY (self->command_line), path); gtk_editable_set_text (GTK_EDITABLE (self->command_line), path);
gtk_switch_set_active (self->launch_switch, TRUE); gtk_switch_set_active (self->launch_switch, TRUE);
gtk_widget_grab_focus (GTK_WIDGET (self->command_line)); gtk_widget_grab_focus (GTK_WIDGET (self->command_line));
} }

View File

@ -28,7 +28,7 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_PROFILER_ASSISTANT (sysprof_profiler_assistant_get_type()) #define SYSPROF_TYPE_PROFILER_ASSISTANT (sysprof_profiler_assistant_get_type())
G_DECLARE_FINAL_TYPE (SysprofProfilerAssistant, sysprof_profiler_assistant, SYSPROF, PROFILER_ASSISTANT, GtkBin) G_DECLARE_FINAL_TYPE (SysprofProfilerAssistant, sysprof_profiler_assistant, SYSPROF, PROFILER_ASSISTANT, GtkWidget)
GtkWidget *sysprof_profiler_assistant_new (void); GtkWidget *sysprof_profiler_assistant_new (void);
void sysprof_profiler_assistant_set_executable (SysprofProfilerAssistant *self, void sysprof_profiler_assistant_set_executable (SysprofProfilerAssistant *self,

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<requires lib="gtk+" version="3.22"/>
<object class="SysprofCpuAid" id="cpu_aid"> <object class="SysprofCpuAid" id="cpu_aid">
<property name="icon-name">sysprof-cpu</property> <property name="icon-name">sysprof-cpu</property>
</object> </object>
@ -62,21 +61,24 @@
<object class="SysprofDiskstatSource"/> <object class="SysprofDiskstatSource"/>
</child> </child>
</object> </object>
<template class="SysprofProfilerAssistant" parent="GtkBin"> <template class="SysprofProfilerAssistant" parent="GtkWidget">
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow" id="scroller">
<property name="propagate-natural-width">true</property> <property name="propagate-natural-width">true</property>
<property name="propagate-natural-height">true</property> <property name="propagate-natural-height">true</property>
<property name="hscrollbar-policy">never</property> <property name="hscrollbar-policy">never</property>
<property name="visible">true</property> <property name="visible">true</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="margin">36</property> <property name="margin-top">36</property>
<property name="margin-bottom">36</property>
<property name="margin-start">36</property>
<property name="margin-end">36</property>
<property name="spacing">12</property> <property name="spacing">12</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="visible">true</property> <property name="visible">true</property>
<child> <child>
<object class="DzlThreeGrid" id="three_grid"> <object class="EggThreeGrid" id="three_grid">
<property name="column-spacing">12</property> <property name="column-spacing">12</property>
<property name="row-spacing">6</property> <property name="row-spacing">6</property>
<property name="visible">true</property> <property name="visible">true</property>
@ -199,11 +201,11 @@
</child> </child>
</object> </object>
</child> </child>
<layout>
<property name="column">center</property>
<property name="row">5</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">5</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label1"> <object class="GtkLabel" id="label1">
@ -213,11 +215,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">0</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSwitch" id="whole_system_switch"> <object class="GtkSwitch" id="whole_system_switch">
@ -225,11 +227,11 @@
<property name="halign">start</property> <property name="halign">start</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="visible">true</property> <property name="visible">true</property>
<layout>
<property name="column">center</property>
<property name="row">0</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
@ -271,7 +273,6 @@
</child> </child>
<child> <child>
<object class="GtkScrolledWindow"> <object class="GtkScrolledWindow">
<property name="shadow-type">in</property>
<property name="hscrollbar-policy">never</property> <property name="hscrollbar-policy">never</property>
<property name="min-content-height">175</property> <property name="min-content-height">175</property>
<property name="max-content-height">175</property> <property name="max-content-height">175</property>
@ -282,8 +283,8 @@
<property name="visible">true</property> <property name="visible">true</property>
<child type="placeholder"> <child type="placeholder">
<object class="GtkLabel"> <object class="GtkLabel">
<property name="margin-left">12</property> <property name="margin-start">12</property>
<property name="margin-right">12</property> <property name="margin-end">12</property>
<property name="label" translatable="yes">Loading Processes…</property> <property name="label" translatable="yes">Loading Processes…</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="visible">true</property> <property name="visible">true</property>
@ -300,11 +301,11 @@
</child> </child>
</object> </object>
</child> </child>
<layout>
<property name="column">center</property>
<property name="row">1</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label2"> <object class="GtkLabel" id="label2">
@ -315,11 +316,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">2</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
@ -399,7 +400,6 @@
</child> </child>
<child> <child>
<object class="GtkFrame"> <object class="GtkFrame">
<property name="shadow-type">in</property>
<property name="visible">true</property> <property name="visible">true</property>
<child> <child>
<object class="SysprofEnvironEditor" id="environ_editor"> <object class="SysprofEnvironEditor" id="environ_editor">
@ -452,11 +452,11 @@
</child> </child>
</object> </object>
</child> </child>
<layout>
<property name="column">center</property>
<property name="row">2</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkLabel" id="label3"> <object class="GtkLabel" id="label3">
@ -467,11 +467,11 @@
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
<layout>
<property name="column">left</property>
<property name="row">3</property>
</layout>
</object> </object>
<packing>
<property name="column">left</property>
<property name="row">3</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
@ -501,11 +501,11 @@
</style> </style>
</object> </object>
</child> </child>
<layout>
<property name="column">center</property>
<property name="row">3</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">3</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="record_button"> <object class="GtkButton" id="record_button">
@ -519,17 +519,13 @@
<style> <style>
<class name="suggested-action"/> <class name="suggested-action"/>
</style> </style>
<layout>
<property name="column">center</property>
<property name="row">4</property>
</layout>
</object> </object>
<packing>
<property name="column">center</property>
<property name="row">4</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="pack-type">start</property>
<property name="position">2</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -227,7 +227,7 @@ sysprof_rapl_aid_present_finish (SysprofAid *aid,
if (found > 0) if (found > 0)
sysprof_display_add_group (present->display, energy); sysprof_display_add_group (present->display, energy);
else else
gtk_widget_destroy (GTK_WIDGET (energy)); g_object_unref (g_object_ref_sink (energy));
} }
return counters != NULL; return counters != NULL;

View File

@ -31,7 +31,7 @@ typedef struct
gulong notify_elapsed_handler; gulong notify_elapsed_handler;
} SysprofRecordingStateViewPrivate; } SysprofRecordingStateViewPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofRecordingStateView, sysprof_recording_state_view, GTK_TYPE_BIN) G_DEFINE_TYPE_WITH_PRIVATE (SysprofRecordingStateView, sysprof_recording_state_view, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -79,18 +79,22 @@ sysprof_recording_state_view_notify_elapsed (SysprofRecordingStateView *self,
} }
static void static void
sysprof_recording_state_view_destroy (GtkWidget *widget) sysprof_recording_state_view_dispose (GObject *object)
{ {
SysprofRecordingStateView *self = (SysprofRecordingStateView *)widget; SysprofRecordingStateView *self = (SysprofRecordingStateView *)object;
SysprofRecordingStateViewPrivate *priv = sysprof_recording_state_view_get_instance_private (self); SysprofRecordingStateViewPrivate *priv = sysprof_recording_state_view_get_instance_private (self);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
if (priv->profiler != NULL) if (priv->profiler != NULL)
{ {
g_signal_handler_disconnect (priv->profiler, priv->notify_elapsed_handler); g_clear_signal_handler (&priv->notify_elapsed_handler, priv->profiler);
g_clear_object (&priv->profiler); g_clear_object (&priv->profiler);
} }
GTK_WIDGET_CLASS (sysprof_recording_state_view_parent_class)->destroy (widget); G_OBJECT_CLASS (sysprof_recording_state_view_parent_class)->dispose (object);
} }
static void static void
@ -138,11 +142,10 @@ sysprof_recording_state_view_class_init (SysprofRecordingStateViewClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = sysprof_recording_state_view_dispose;
object_class->get_property = sysprof_recording_state_view_get_property; object_class->get_property = sysprof_recording_state_view_get_property;
object_class->set_property = sysprof_recording_state_view_set_property; object_class->set_property = sysprof_recording_state_view_set_property;
widget_class->destroy = sysprof_recording_state_view_destroy;
properties [PROP_PROFILER] = properties [PROP_PROFILER] =
g_param_spec_object ("profiler", g_param_spec_object ("profiler",
"Profiler", "Profiler",
@ -153,6 +156,7 @@ sysprof_recording_state_view_class_init (SysprofRecordingStateViewClass *klass)
g_object_class_install_properties (object_class, N_PROPS, properties); g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-recording-state-view.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-recording-state-view.ui");
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_bind_template_child_private (widget_class, SysprofRecordingStateView, elapsed); gtk_widget_class_bind_template_child_private (widget_class, SysprofRecordingStateView, elapsed);
gtk_widget_class_bind_template_child_private (widget_class, SysprofRecordingStateView, samples); gtk_widget_class_bind_template_child_private (widget_class, SysprofRecordingStateView, samples);

View File

@ -27,13 +27,11 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_RECORDING_STATE_VIEW (sysprof_recording_state_view_get_type()) #define SYSPROF_TYPE_RECORDING_STATE_VIEW (sysprof_recording_state_view_get_type())
G_DECLARE_DERIVABLE_TYPE (SysprofRecordingStateView, sysprof_recording_state_view, SYSPROF, RECORDING_STATE_VIEW, GtkBin) G_DECLARE_DERIVABLE_TYPE (SysprofRecordingStateView, sysprof_recording_state_view, SYSPROF, RECORDING_STATE_VIEW, GtkWidget)
struct _SysprofRecordingStateViewClass struct _SysprofRecordingStateViewClass
{ {
GtkBinClass parent; GtkWidgetClass parent;
gpointer padding[4];
}; };
GtkWidget *sysprof_recording_state_view_new (void); GtkWidget *sysprof_recording_state_view_new (void);

View File

@ -1,11 +1,14 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<interface> <interface>
<template class="SysprofRecordingStateView" parent="GtkBin"> <template class="SysprofRecordingStateView" parent="GtkWidget">
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="width-request">500</property> <property name="width-request">500</property>
<property name="halign">center</property> <property name="halign">center</property>
<property name="border-width">36</property> <property name="margin-start">36</property>
<property name="margin-end">36</property>
<property name="margin-top">36</property>
<property name="margin-bottom">36</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">12</property> <property name="spacing">12</property>
<property name="visible">true</property> <property name="visible">true</property>

View File

@ -28,7 +28,9 @@
struct _SysprofScrollmap struct _SysprofScrollmap
{ {
GtkScrollbar parent_instance; GtkWidget parent_instance;
GtkWidget *scrollbar;
gint64 begin_time; gint64 begin_time;
gint64 end_time; gint64 end_time;
@ -49,7 +51,7 @@ typedef struct
gint height; gint height;
} Recalculate; } Recalculate;
G_DEFINE_TYPE (SysprofScrollmap, sysprof_scrollmap, GTK_TYPE_SCROLLBAR) G_DEFINE_TYPE (SysprofScrollmap, sysprof_scrollmap, GTK_TYPE_WIDGET)
static void static void
recalculate_free (gpointer data) recalculate_free (gpointer data)
@ -152,68 +154,62 @@ sysprof_scrollmap_recalculate_finish (SysprofScrollmap *self,
return g_task_propagate_pointer (G_TASK (result), error); return g_task_propagate_pointer (G_TASK (result), error);
} }
static void static inline void
draw_boxes (const GtkAllocation *alloc, draw_boxes (const GtkAllocation *alloc,
cairo_t *cr, GtkSnapshot *snapshot,
gint x, int x,
gint n_boxes) int n_boxes,
const GdkRGBA *color)
{ {
gint y; int y = alloc->y + alloc->height - BOX_SIZE;
g_assert (cr != NULL); for (int i = 0; i < n_boxes; i++)
y = alloc->height - BOX_SIZE;
for (gint i = 0; i < n_boxes; i++)
{ {
cairo_rectangle (cr, x, y, BOX_SIZE, -BOX_SIZE); gtk_snapshot_append_color (snapshot, color, &GRAPHENE_RECT_INIT (x, y, BOX_SIZE, -BOX_SIZE));
y -= (BOX_SIZE + 1); y -= (BOX_SIZE + 1);
} }
cairo_fill (cr);
} }
static gboolean static void
sysprof_scrollmap_draw (GtkWidget *widget, sysprof_scrollmap_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofScrollmap *self = (SysprofScrollmap *)widget; SysprofScrollmap *self = (SysprofScrollmap *)widget;
GtkStyleContext *style_context; GtkStyleContext *style_context;
GtkAllocation alloc; GtkAllocation alloc;
GdkRGBA color; GdkRGBA color;
gint max_boxes; int max_boxes;
g_assert (SYSPROF_IS_SCROLLMAP (self)); g_assert (SYSPROF_IS_SCROLLMAP (self));
g_assert (cr != NULL); g_assert (GTK_IS_SNAPSHOT (snapshot));
if (self->buckets == NULL) if (self->buckets == NULL)
goto chainup; goto chainup;
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
alloc.y += 3;
alloc.height -= 6;
max_boxes = alloc.height / (BOX_SIZE + 1) - 1; max_boxes = alloc.height / (BOX_SIZE + 1) - 1;
style_context = gtk_widget_get_style_context (widget); style_context = gtk_widget_get_style_context (widget);
gtk_style_context_get_color (style_context, gtk_style_context_get_color (style_context, &color);
gtk_style_context_get_state (style_context),
&color);
gdk_cairo_set_source_rgba (cr, &color);
for (guint i = 0; i < self->buckets->len; i++) for (guint i = 0; i < self->buckets->len; i++)
{ {
gint n = g_array_index (self->buckets, gint, i); int n = g_array_index (self->buckets, gint, i);
gint x = 1 + i * (BOX_SIZE + 1); int x = 1 + i * (BOX_SIZE + 1);
gint b = max_boxes * (n / (gdouble)self->most); int b = max_boxes * (n / (gdouble)self->most);
#if 1
if (n > 0) if (n > 0)
b = MAX (b, 1); b = MAX (b, 1);
#endif
draw_boxes (&alloc, cr, x, b); draw_boxes (&alloc, snapshot, x, b, &color);
} }
chainup: chainup:
return GTK_WIDGET_CLASS (sysprof_scrollmap_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_scrollmap_parent_class)->snapshot (widget, snapshot);
} }
static void static void
@ -246,14 +242,20 @@ sysprof_scrollmap_recalculate_cb (GObject *object,
} }
static void static void
sysprof_scrollmap_finalize (GObject *object) sysprof_scrollmap_dispose (GObject *object)
{ {
SysprofScrollmap *self = (SysprofScrollmap *)object; SysprofScrollmap *self = (SysprofScrollmap *)object;
if (self->scrollbar)
{
gtk_widget_unparent (GTK_WIDGET (self->scrollbar));
self->scrollbar = NULL;
}
g_clear_pointer (&self->buckets, g_array_unref); g_clear_pointer (&self->buckets, g_array_unref);
g_clear_pointer (&self->timings, g_array_unref); g_clear_pointer (&self->timings, g_array_unref);
G_OBJECT_CLASS (sysprof_scrollmap_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_scrollmap_parent_class)->dispose (object);
} }
static void static void
@ -262,14 +264,21 @@ sysprof_scrollmap_class_init (SysprofScrollmapClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = sysprof_scrollmap_finalize; object_class->dispose = sysprof_scrollmap_dispose;
widget_class->draw = sysprof_scrollmap_draw; widget_class->snapshot = sysprof_scrollmap_snapshot;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, "scrollmap");
} }
static void static void
sysprof_scrollmap_init (SysprofScrollmap *self) sysprof_scrollmap_init (SysprofScrollmap *self)
{ {
self->scrollbar = g_object_new (GTK_TYPE_SCROLLBAR,
"orientation", GTK_ORIENTATION_HORIZONTAL,
NULL);
gtk_widget_set_parent (GTK_WIDGET (self->scrollbar), GTK_WIDGET (self));
} }
void void
@ -304,3 +313,21 @@ sysprof_scrollmap_set_time_range (SysprofScrollmap *self,
sysprof_scrollmap_recalculate_cb, sysprof_scrollmap_recalculate_cb,
NULL); NULL);
} }
void
sysprof_scrollmap_set_adjustment (SysprofScrollmap *self,
GtkAdjustment *adjustment)
{
g_return_if_fail (SYSPROF_IS_SCROLLMAP (self));
g_return_if_fail (!adjustment || GTK_IS_ADJUSTMENT (adjustment));
gtk_scrollbar_set_adjustment (GTK_SCROLLBAR (self->scrollbar), adjustment);
}
GtkAdjustment *
sysprof_scrollmap_get_adjustment (SysprofScrollmap *self)
{
g_return_val_if_fail (SYSPROF_IS_SCROLLMAP (self), NULL);
return gtk_scrollbar_get_adjustment (GTK_SCROLLBAR (self->scrollbar));
}

View File

@ -26,12 +26,15 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_SCROLLMAP (sysprof_scrollmap_get_type()) #define SYSPROF_TYPE_SCROLLMAP (sysprof_scrollmap_get_type())
G_DECLARE_FINAL_TYPE (SysprofScrollmap, sysprof_scrollmap, SYSPROF, SCROLLMAP, GtkScrollbar) G_DECLARE_FINAL_TYPE (SysprofScrollmap, sysprof_scrollmap, SYSPROF, SCROLLMAP, GtkWidget)
void sysprof_scrollmap_set_timings (SysprofScrollmap *self, GtkAdjustment *sysprof_scrollmap_get_adjustment (SysprofScrollmap *self);
GArray *timings); void sysprof_scrollmap_set_adjustment (SysprofScrollmap *self,
void sysprof_scrollmap_set_time_range (SysprofScrollmap *self, GtkAdjustment *adjustment);
gint64 begin_time, void sysprof_scrollmap_set_timings (SysprofScrollmap *self,
gint64 end_time); GArray *timings);
void sysprof_scrollmap_set_time_range (SysprofScrollmap *self,
gint64 begin_time,
gint64 end_time);
G_END_DECLS G_END_DECLS

View File

@ -22,14 +22,15 @@
#include "config.h" #include "config.h"
#include "sysprof-display.h" #include "sysprof-display-private.h"
#include "sysprof-tab.h" #include "sysprof-tab.h"
#include "sysprof-ui-private.h" #include "sysprof-ui-private.h"
struct _SysprofTab struct _SysprofTab
{ {
GtkBox parent_instance; GtkWidget parent_instance;
GtkWidget *center_box;
GtkButton *close_button; GtkButton *close_button;
GtkLabel *title; GtkLabel *title;
GtkImage *recording; GtkImage *recording;
@ -37,7 +38,7 @@ struct _SysprofTab
SysprofDisplay *display; SysprofDisplay *display;
}; };
G_DEFINE_TYPE (SysprofTab, sysprof_tab, GTK_TYPE_BOX) G_DEFINE_TYPE (SysprofTab, sysprof_tab, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -62,18 +63,19 @@ sysprof_tab_close_clicked (SysprofTab *self,
g_assert (SYSPROF_IS_TAB (self)); g_assert (SYSPROF_IS_TAB (self));
g_assert (GTK_IS_BUTTON (button)); g_assert (GTK_IS_BUTTON (button));
if (self->display != NULL) if (self->display)
gtk_widget_destroy (GTK_WIDGET (self->display)); _sysprof_display_destroy (self->display);
} }
static void static void
sysprof_tab_finalize (GObject *object) sysprof_tab_dispose (GObject *object)
{ {
SysprofTab *self = (SysprofTab *)object; SysprofTab *self = (SysprofTab *)object;
g_clear_pointer (&self->center_box, gtk_widget_unparent);
g_clear_weak_pointer (&self->display); g_clear_weak_pointer (&self->display);
G_OBJECT_CLASS (sysprof_tab_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_tab_parent_class)->dispose (object);
} }
static void static void
@ -122,11 +124,13 @@ sysprof_tab_class_init (SysprofTabClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = sysprof_tab_finalize; object_class->dispose = sysprof_tab_dispose;
object_class->get_property = sysprof_tab_get_property; object_class->get_property = sysprof_tab_get_property;
object_class->set_property = sysprof_tab_set_property; object_class->set_property = sysprof_tab_set_property;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-tab.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-tab.ui");
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_bind_template_child (widget_class, SysprofTab, center_box);
gtk_widget_class_bind_template_child (widget_class, SysprofTab, close_button); gtk_widget_class_bind_template_child (widget_class, SysprofTab, close_button);
gtk_widget_class_bind_template_child (widget_class, SysprofTab, recording); gtk_widget_class_bind_template_child (widget_class, SysprofTab, recording);
gtk_widget_class_bind_template_child (widget_class, SysprofTab, title); gtk_widget_class_bind_template_child (widget_class, SysprofTab, title);

View File

@ -28,7 +28,7 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_TAB (sysprof_tab_get_type()) #define SYSPROF_TYPE_TAB (sysprof_tab_get_type())
G_DECLARE_FINAL_TYPE (SysprofTab, sysprof_tab, SYSPROF, TAB, GtkBox) G_DECLARE_FINAL_TYPE (SysprofTab, sysprof_tab, SYSPROF, TAB, GtkWidget)
GtkWidget *sysprof_tab_new (SysprofDisplay *display); GtkWidget *sysprof_tab_new (SysprofDisplay *display);

View File

@ -1,60 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface> <interface>
<requires lib="gtk+" version="3.0"/> <template class="SysprofTab" parent="GtkWidget">
<template class="SysprofTab" parent="GtkBox"> <property name="hexpand">true</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="spacing">6</property>
<child> <child>
<object class="GtkImage" id="recording"> <object class="GtkCenterBox" id="center_box">
<property name="visible">false</property> <child type="start">
<property name="icon-name">media-record-symbolic</property> <object class="GtkImage" id="recording">
<property name="pixel-size">16</property> <property name="visible">false</property>
<property name="hexpand">true</property> <property name="icon-name">media-record-symbolic</property>
<property name="halign">end</property> <property name="pixel-size">16</property>
</object> <property name="hexpand">true</property>
<packing> <property name="halign">end</property>
<property name="expand">True</property> </object>
<property name="fill">True</property> </child>
<property name="position">0</property> <child type="center">
<property name="pack-type">start</property> <object class="GtkLabel" id="title">
</packing> <property name="margin-start">6</property>
</child> <property name="margin-end">6</property>
<child type="center"> </object>
<object class="GtkLabel" id="title"> </child>
<property name="visible">True</property> <child type="end">
<property name="can_focus">False</property> <object class="GtkButton" id="close_button">
</object> <property name="receives_default">False</property>
<packing> <property name="icon_name">window-close-symbolic</property>
<property name="expand">False</property> <style>
<property name="fill">True</property> <class name="flat"/>
<property name="position">0</property> <class name="small-button"/>
</packing> <class name="image-button"/>
</child> </style>
<child>
<object class="GtkButton" id="close_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">window-close-symbolic</property>
</object> </object>
</child> </child>
<style>
<class name="flat"/>
<class name="small-button"/>
</style>
</object> </object>
<packing>
<property name="pack-type">end</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
</template> </template>
</interface> </interface>

View File

@ -58,8 +58,8 @@ theme_resource_free (gpointer data)
if (theme_resource->provider != NULL) if (theme_resource->provider != NULL)
{ {
gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (), gtk_style_context_remove_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (theme_resource->provider)); GTK_STYLE_PROVIDER (theme_resource->provider));
g_clear_object (&theme_resource->provider); g_clear_object (&theme_resource->provider);
} }
@ -121,17 +121,17 @@ sysprof_theme_manager_do_reload (gpointer data)
{ {
theme_resource->provider = gtk_css_provider_new (); theme_resource->provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (theme_resource->provider, theme_resource->resource); gtk_css_provider_load_from_resource (theme_resource->provider, theme_resource->resource);
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (theme_resource->provider), GTK_STYLE_PROVIDER (theme_resource->provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1); GTK_STYLE_PROVIDER_PRIORITY_THEME+1);
} }
} }
else else
{ {
if (theme_resource->provider != NULL) if (theme_resource->provider != NULL)
{ {
gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (), gtk_style_context_remove_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (theme_resource->provider)); GTK_STYLE_PROVIDER (theme_resource->provider));
g_clear_object (&theme_resource->provider); g_clear_object (&theme_resource->provider);
} }
} }
@ -146,10 +146,10 @@ sysprof_theme_manager_queue_reload (SysprofThemeManager *self)
g_assert (SYSPROF_IS_THEME_MANAGER (self)); g_assert (SYSPROF_IS_THEME_MANAGER (self));
if (self->reload_source == 0) if (self->reload_source == 0)
self->reload_source = gdk_threads_add_idle_full (G_PRIORITY_LOW, self->reload_source = g_idle_add_full (G_PRIORITY_LOW,
sysprof_theme_manager_do_reload, sysprof_theme_manager_do_reload,
self, self,
NULL); NULL);
} }
static void static void
@ -181,7 +181,8 @@ sysprof_theme_manager_init (SysprofThemeManager *self)
{ {
self->theme_resources = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, theme_resource_free); self->theme_resources = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, theme_resource_free);
gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (), "/org/gnome/sysprof/icons"); gtk_icon_theme_add_resource_path (gtk_icon_theme_get_for_display (gdk_display_get_default ()),
"/org/gnome/sysprof/icons");
} }
/** /**

View File

@ -26,17 +26,37 @@
struct _SysprofTimeLabel struct _SysprofTimeLabel
{ {
GtkBox parent; GtkWidget parent_instance;
GtkCenterBox *box;
GtkLabel *minutes; GtkLabel *minutes;
GtkLabel *seconds; GtkLabel *seconds;
}; };
G_DEFINE_TYPE (SysprofTimeLabel, sysprof_time_label, GTK_TYPE_BOX) G_DEFINE_TYPE (SysprofTimeLabel, sysprof_time_label, GTK_TYPE_WIDGET)
static void
sysprof_time_label_dispose (GObject *object)
{
SysprofTimeLabel *self = (SysprofTimeLabel *)object;
if (self->box)
{
gtk_widget_unparent (GTK_WIDGET (self->box));
self->box = NULL;
}
G_OBJECT_CLASS (sysprof_time_label_parent_class)->dispose (object);
}
static void static void
sysprof_time_label_class_init (SysprofTimeLabelClass *klass) sysprof_time_label_class_init (SysprofTimeLabelClass *klass)
{ {
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = sysprof_time_label_dispose;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
} }
static void static void
@ -48,36 +68,32 @@ sysprof_time_label_init (SysprofTimeLabel *self)
pango_attr_list_insert (attrs, pango_attr_scale_new (4)); pango_attr_list_insert (attrs, pango_attr_scale_new (4));
pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
gtk_box_set_spacing (GTK_BOX (self), 3); self->box = GTK_CENTER_BOX (gtk_center_box_new ());
gtk_widget_set_parent (GTK_WIDGET (self->box), GTK_WIDGET (self));
self->minutes = g_object_new (GTK_TYPE_LABEL, self->minutes = g_object_new (GTK_TYPE_LABEL,
"attributes", attrs, "attributes", attrs,
"visible", TRUE,
"xalign", 1.0f, "xalign", 1.0f,
"hexpand", TRUE,
NULL); NULL);
gtk_container_add_with_properties (GTK_CONTAINER (self), GTK_WIDGET (self->minutes), gtk_center_box_set_start_widget (self->box, GTK_WIDGET (self->minutes));
"pack-type", GTK_PACK_START,
"expand", TRUE,
"fill", TRUE,
NULL);
sep = g_object_new (GTK_TYPE_LABEL, sep = g_object_new (GTK_TYPE_LABEL,
"margin-start", 3,
"margin-end", 3,
"attributes", attrs, "attributes", attrs,
"visible", TRUE, "visible", TRUE,
"label", ":", "label", ":",
NULL); NULL);
gtk_box_set_center_widget (GTK_BOX (self), sep); gtk_center_box_set_center_widget (self->box, sep);
self->seconds = g_object_new (GTK_TYPE_LABEL, self->seconds = g_object_new (GTK_TYPE_LABEL,
"attributes", attrs, "attributes", attrs,
"visible", TRUE, "visible", TRUE,
"xalign", 0.0f, "xalign", 0.0f,
"hexpand", TRUE,
NULL); NULL);
gtk_container_add_with_properties (GTK_CONTAINER (self), GTK_WIDGET (self->seconds), gtk_center_box_set_end_widget (self->box, GTK_WIDGET (self->seconds));
"pack-type", GTK_PACK_END,
"expand", TRUE,
"fill", TRUE,
NULL);
} }
void void

View File

@ -26,7 +26,7 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_TIME_LABEL (sysprof_time_label_get_type()) #define SYSPROF_TYPE_TIME_LABEL (sysprof_time_label_get_type())
G_DECLARE_FINAL_TYPE (SysprofTimeLabel, sysprof_time_label, SYSPROF, TIME_LABEL, GtkBox) G_DECLARE_FINAL_TYPE (SysprofTimeLabel, sysprof_time_label, SYSPROF, TIME_LABEL, GtkWidget)
void sysprof_time_label_set_duration (SysprofTimeLabel *self, void sysprof_time_label_set_duration (SysprofTimeLabel *self,
guint duration); guint duration);

View File

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<template class="SysprofTimeLabel" parent="GtkBox">
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child type="center">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="minute">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">00</property>
<property name="width_chars">2</property>
<property name="xalign">1</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="second">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">00</property>
<property name="width_chars">2</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">4</property>
</packing>
</child>
</template>
</interface>

View File

@ -114,35 +114,39 @@ copy_array (GArray *ar)
return ret; return ret;
} }
static gboolean static void
sysprof_time_visualizer_draw (GtkWidget *widget, sysprof_time_visualizer_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofTimeVisualizer *self = (SysprofTimeVisualizer *)widget; SysprofTimeVisualizer *self = (SysprofTimeVisualizer *)widget;
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self); SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
GtkStyleContext *style_context; GtkStyleContext *style_context;
GtkStateFlags flags; cairo_t *cr;
GtkAllocation alloc; GtkAllocation alloc;
GdkRectangle clip;
GdkRGBA foreground; GdkRGBA foreground;
gboolean ret;
g_assert (SYSPROF_IS_TIME_VISUALIZER (widget)); g_assert (SYSPROF_IS_TIME_VISUALIZER (widget));
g_assert (cr != NULL); g_assert (snapshot != NULL);
gtk_widget_get_allocation (widget, &alloc); gtk_widget_get_allocation (widget, &alloc);
ret = GTK_WIDGET_CLASS (sysprof_time_visualizer_parent_class)->draw (widget, cr); GTK_WIDGET_CLASS (sysprof_time_visualizer_parent_class)->snapshot (widget, snapshot);
if (priv->cache == NULL) if (priv->cache == NULL)
return ret; return;
#if 0
if (!gdk_cairo_get_clip_rectangle (cr, &clip)) if (!gdk_cairo_get_clip_rectangle (cr, &clip))
return ret; return ret;
#else
alloc.x = 0;
alloc.y = 0;
#endif
style_context = gtk_widget_get_style_context (widget); style_context = gtk_widget_get_style_context (widget);
flags = gtk_widget_get_state_flags (widget); gtk_style_context_get_color (style_context, &foreground);
gtk_style_context_get_color (style_context, flags, &foreground);
cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, alloc.width, alloc.height));
gdk_cairo_set_source_rgba (cr, &foreground); gdk_cairo_set_source_rgba (cr, &foreground);
@ -187,7 +191,7 @@ sysprof_time_visualizer_draw (GtkWidget *widget,
} }
} }
return ret; cairo_destroy (cr);
} }
static void static void
@ -243,10 +247,10 @@ sysprof_time_visualizer_queue_reload (SysprofTimeVisualizer *self)
if (priv->queued_load == 0) if (priv->queued_load == 0)
priv->queued_load = priv->queued_load =
gdk_threads_add_idle_full (G_PRIORITY_LOW, g_idle_add_full (G_PRIORITY_LOW,
sysprof_time_visualizer_do_reload, sysprof_time_visualizer_do_reload,
self, self,
NULL); NULL);
} }
static void static void
@ -283,11 +287,7 @@ sysprof_time_visualizer_finalize (GObject *object)
g_clear_pointer (&priv->cache, point_cache_unref); g_clear_pointer (&priv->cache, point_cache_unref);
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref); g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
if (priv->queued_load != 0) g_clear_handle_id (&priv->queued_load, g_source_remove);
{
g_source_remove (priv->queued_load);
priv->queued_load = 0;
}
G_OBJECT_CLASS (sysprof_time_visualizer_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_time_visualizer_parent_class)->finalize (object);
} }
@ -301,7 +301,7 @@ sysprof_time_visualizer_class_init (SysprofTimeVisualizerClass *klass)
object_class->finalize = sysprof_time_visualizer_finalize; object_class->finalize = sysprof_time_visualizer_finalize;
widget_class->draw = sysprof_time_visualizer_draw; widget_class->snapshot = sysprof_time_visualizer_snapshot;
visualizer_class->set_reader = sysprof_time_visualizer_set_reader; visualizer_class->set_reader = sysprof_time_visualizer_set_reader;
} }

View File

@ -20,7 +20,7 @@
#pragma once #pragma once
#include <dazzle.h> #include <gtk/gtk.h>
#include <sysprof.h> #include <sysprof.h>
G_BEGIN_DECLS G_BEGIN_DECLS

View File

@ -38,17 +38,28 @@ struct _SysprofVisualizerGroupHeader
G_DEFINE_TYPE (SysprofVisualizerGroupHeader, sysprof_visualizer_group_header, GTK_TYPE_LIST_BOX_ROW) G_DEFINE_TYPE (SysprofVisualizerGroupHeader, sysprof_visualizer_group_header, GTK_TYPE_LIST_BOX_ROW)
static void static void
sysprof_visualizer_group_header_finalize (GObject *object) sysprof_visualizer_group_header_dispose (GObject *object)
{ {
G_OBJECT_CLASS (sysprof_visualizer_group_header_parent_class)->finalize (object); SysprofVisualizerGroupHeader *self = (SysprofVisualizerGroupHeader *)object;
if (self->box)
{
gtk_widget_unparent (GTK_WIDGET (self->box));
self->box = NULL;
}
G_OBJECT_CLASS (sysprof_visualizer_group_header_parent_class)->dispose (object);
} }
static void static void
sysprof_visualizer_group_header_class_init (SysprofVisualizerGroupHeaderClass *klass) sysprof_visualizer_group_header_class_init (SysprofVisualizerGroupHeaderClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = sysprof_visualizer_group_header_finalize; object_class->dispose = sysprof_visualizer_group_header_dispose;
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
} }
static void static void
@ -58,7 +69,7 @@ sysprof_visualizer_group_header_init (SysprofVisualizerGroupHeader *self)
"orientation", GTK_ORIENTATION_VERTICAL, "orientation", GTK_ORIENTATION_VERTICAL,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->box)); gtk_widget_set_parent (GTK_WIDGET (self->box), GTK_WIDGET (self));
} }
void void
@ -68,8 +79,9 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
GMenuModel *menu, GMenuModel *menu,
GtkWidget *widget) GtkWidget *widget)
{ {
GtkBox *box;
GtkWidget *group; GtkWidget *group;
GtkWidget *sibling;
GtkBox *box;
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP_HEADER (self)); g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP_HEADER (self));
g_return_if_fail (SYSPROF_IS_VISUALIZER (widget)); g_return_if_fail (SYSPROF_IS_VISUALIZER (widget));
@ -81,9 +93,11 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
g_object_bind_property (widget, "visible", box, "visible", G_BINDING_SYNC_CREATE); g_object_bind_property (widget, "visible", box, "visible", G_BINDING_SYNC_CREATE);
gtk_container_add_with_properties (GTK_CONTAINER (self->box), GTK_WIDGET (box),
"position", position, sibling = gtk_widget_get_first_child (GTK_WIDGET (self->box));
NULL); for (; position > 1 && sibling; position--)
sibling = gtk_widget_get_next_sibling (sibling);
gtk_box_insert_child_after (self->box, GTK_WIDGET (box), sibling);
if (title != NULL) if (title != NULL)
{ {
@ -95,13 +109,16 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
label = g_object_new (GTK_TYPE_LABEL, label = g_object_new (GTK_TYPE_LABEL,
"attributes", attrs, "attributes", attrs,
"ellipsize", PANGO_ELLIPSIZE_MIDDLE, "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
"margin", 6, "margin-top", 6,
"margin-bottom", 6,
"margin-start", 6,
"margin-end", 6,
"hexpand", TRUE, "hexpand", TRUE,
"label", title, "label", title,
"visible", TRUE, "visible", TRUE,
"xalign", 0.0f, "xalign", 0.0f,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (label)); gtk_box_append (box, GTK_WIDGET (label));
pango_attr_list_unref (attrs); pango_attr_list_unref (attrs);
gtk_size_group_add_widget (size_group, widget); gtk_size_group_add_widget (size_group, widget);
@ -120,8 +137,8 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
"pixel-size", 16, "pixel-size", 16,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
dzl_gtk_widget_add_style_class (GTK_WIDGET (image), "dim-label"); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (image)), "dim-label");
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (image)); gtk_box_append (box, GTK_WIDGET (image));
} }
if (menu != NULL) if (menu != NULL)
@ -134,12 +151,11 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
"icon-name", "view-more-symbolic", "icon-name", "view-more-symbolic",
"visible", TRUE, "visible", TRUE,
NULL), NULL),
"margin-right", 6, "margin-end", 6,
"direction", GTK_ARROW_RIGHT, "direction", GTK_ARROW_RIGHT,
"halign", GTK_ALIGN_CENTER, "halign", GTK_ALIGN_CENTER,
"menu-model", menu, "menu-model", menu,
"tooltip-text", _("Display supplemental graphs"), "tooltip-text", _("Display supplemental graphs"),
"use-popover", FALSE,
"valign", GTK_ALIGN_CENTER, "valign", GTK_ALIGN_CENTER,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
@ -148,7 +164,7 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
gtk_style_context_add_class (style_context, "small-button"); gtk_style_context_add_class (style_context, "small-button");
gtk_style_context_add_class (style_context, "flat"); gtk_style_context_add_class (style_context, "flat");
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (button)); gtk_box_append (box, GTK_WIDGET (button));
} }
} }

View File

@ -22,7 +22,6 @@
#include "config.h" #include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "sysprof-visualizer.h" #include "sysprof-visualizer.h"
@ -158,21 +157,6 @@ create_action_name (const gchar *str)
return g_string_free (ret, FALSE); return g_string_free (ret, FALSE);
} }
static void
sysprof_visualizer_group_add (GtkContainer *container,
GtkWidget *child)
{
SysprofVisualizerGroup *self = (SysprofVisualizerGroup *)container;
g_assert (SYSPROF_IS_VISUALIZER_GROUP (self));
g_assert (GTK_IS_WIDGET (child));
if (SYSPROF_IS_VISUALIZER (child))
sysprof_visualizer_group_insert (self, SYSPROF_VISUALIZER (child), -1, FALSE);
else
GTK_CONTAINER_CLASS (sysprof_visualizer_group_parent_class)->add (container, child);
}
static void static void
sysprof_visualizer_group_finalize (GObject *object) sysprof_visualizer_group_finalize (GObject *object)
{ {
@ -186,7 +170,7 @@ sysprof_visualizer_group_finalize (GObject *object)
g_clear_object (&priv->rows_menu); g_clear_object (&priv->rows_menu);
g_clear_object (&priv->actions); g_clear_object (&priv->actions);
dzl_clear_weak_pointer (&priv->header); g_clear_weak_pointer (&priv->header);
G_OBJECT_CLASS (sysprof_visualizer_group_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_visualizer_group_parent_class)->finalize (object);
} }
@ -258,14 +242,11 @@ sysprof_visualizer_group_class_init (SysprofVisualizerGroupClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->finalize = sysprof_visualizer_group_finalize; object_class->finalize = sysprof_visualizer_group_finalize;
object_class->get_property = sysprof_visualizer_group_get_property; object_class->get_property = sysprof_visualizer_group_get_property;
object_class->set_property = sysprof_visualizer_group_set_property; object_class->set_property = sysprof_visualizer_group_set_property;
container_class->add = sysprof_visualizer_group_add;
properties [PROP_HAS_PAGE] = properties [PROP_HAS_PAGE] =
g_param_spec_boolean ("has-page", g_param_spec_boolean ("has-page",
"Has Page", "Has Page",
@ -331,7 +312,7 @@ sysprof_visualizer_group_init (SysprofVisualizerGroup *self)
"orientation", GTK_ORIENTATION_VERTICAL, "orientation", GTK_ORIENTATION_VERTICAL,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (priv->visualizers)); gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (self), GTK_WIDGET (priv->visualizers));
} }
void void
@ -343,11 +324,10 @@ _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self)); g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
g_return_if_fail (!header || SYSPROF_IS_VISUALIZER_GROUP_HEADER (header)); g_return_if_fail (!header || SYSPROF_IS_VISUALIZER_GROUP_HEADER (header));
if (dzl_set_weak_pointer (&priv->header, header)) if (g_set_weak_pointer (&priv->header, header))
{ {
if (header != NULL) if (header != NULL)
{ {
GList *children;
guint position = 0; guint position = 0;
gtk_widget_insert_action_group (GTK_WIDGET (header), gtk_widget_insert_action_group (GTK_WIDGET (header),
@ -355,11 +335,11 @@ _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
G_ACTION_GROUP (priv->actions)); G_ACTION_GROUP (priv->actions));
gtk_size_group_add_widget (priv->size_group, GTK_WIDGET (header)); gtk_size_group_add_widget (priv->size_group, GTK_WIDGET (header));
children = gtk_container_get_children (GTK_CONTAINER (priv->visualizers)); for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->visualizers));
child;
for (const GList *iter = children; iter; iter = iter->next) child = gtk_widget_get_next_sibling (child))
{ {
SysprofVisualizer *vis = iter->data; SysprofVisualizer *vis = SYSPROF_VISUALIZER (child);
const gchar *title; const gchar *title;
GMenuModel *menu = NULL; GMenuModel *menu = NULL;
@ -381,19 +361,10 @@ _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
position++; position++;
} }
g_list_free (children);
} }
} }
} }
static void
sysprof_visualizer_group_set_reader_cb (SysprofVisualizer *visualizer,
SysprofCaptureReader *reader)
{
sysprof_visualizer_set_reader (visualizer, reader);
}
void void
_sysprof_visualizer_group_set_reader (SysprofVisualizerGroup *self, _sysprof_visualizer_group_set_reader (SysprofVisualizerGroup *self,
SysprofCaptureReader *reader) SysprofCaptureReader *reader)
@ -403,9 +374,10 @@ _sysprof_visualizer_group_set_reader (SysprofVisualizerGroup *self,
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self)); g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
g_return_if_fail (reader != NULL); g_return_if_fail (reader != NULL);
gtk_container_foreach (GTK_CONTAINER (priv->visualizers), for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->visualizers));
(GtkCallback) sysprof_visualizer_group_set_reader_cb, child;
reader); child = gtk_widget_get_next_sibling (child))
sysprof_visualizer_set_reader (SYSPROF_VISUALIZER (child), reader);
} }
void void
@ -415,13 +387,18 @@ sysprof_visualizer_group_insert (SysprofVisualizerGroup *self,
gboolean can_toggle) gboolean can_toggle)
{ {
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self); SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
GtkWidget *sibling = NULL;
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self)); g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
g_return_if_fail (SYSPROF_IS_VISUALIZER (visualizer)); g_return_if_fail (SYSPROF_IS_VISUALIZER (visualizer));
gtk_container_add_with_properties (GTK_CONTAINER (priv->visualizers), GTK_WIDGET (visualizer), sibling = gtk_widget_get_first_child (GTK_WIDGET (priv->visualizers));
"position", position, while (position > 1 && sibling)
NULL); {
sibling = gtk_widget_get_next_sibling (sibling);
position--;
}
gtk_box_insert_child_after (priv->visualizers, GTK_WIDGET (visualizer), sibling);
if (can_toggle) if (can_toggle)
{ {

View File

@ -135,10 +135,11 @@ update_label_text (PangoLayout *layout,
static gboolean static gboolean
draw_ticks (SysprofVisualizerTicks *self, draw_ticks (SysprofVisualizerTicks *self,
cairo_t *cr, GtkSnapshot *snapshot,
GtkAllocation *area, GtkAllocation *area,
gint ticks, gint ticks,
gboolean label_mode) gboolean label_mode,
const GdkRGBA *color)
{ {
GtkAllocation alloc; GtkAllocation alloc;
gint64 begin_time, end_time; gint64 begin_time, end_time;
@ -146,7 +147,7 @@ draw_ticks (SysprofVisualizerTicks *self,
gint count = 0; gint count = 0;
g_assert (SYSPROF_IS_VISUALIZER_TICKS (self)); g_assert (SYSPROF_IS_VISUALIZER_TICKS (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
g_assert (area != NULL); g_assert (area != NULL);
g_assert (ticks >= 0); g_assert (ticks >= 0);
g_assert (ticks < N_TICKS); g_assert (ticks < N_TICKS);
@ -195,12 +196,16 @@ draw_ticks (SysprofVisualizerTicks *self,
if (x < (last_x2 + MIN_TICK_DISTANCE)) if (x < (last_x2 + MIN_TICK_DISTANCE))
continue; continue;
cairo_move_to (cr, (gint)x + 2.5 - (gint)half, 2);
update_label_text (layout, t - begin_time, want_msec); update_label_text (layout, t - begin_time, want_msec);
pango_layout_get_pixel_size (layout, &w, &h); pango_layout_get_pixel_size (layout, &w, &h);
if (x + w <= alloc.width) if (x + w <= alloc.width)
pango_cairo_show_layout (cr, layout); {
gtk_snapshot_save (snapshot);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT ((int)x + 2.5 - (int)half, 2));
gtk_snapshot_append_layout (snapshot, layout, color);
gtk_snapshot_restore (snapshot);
}
last_x2 = x + w; last_x2 = x + w;
} }
@ -212,48 +217,44 @@ draw_ticks (SysprofVisualizerTicks *self,
for (gint64 t = begin_time; t <= end_time; t += tick_sizing[ticks].span) for (gint64 t = begin_time; t <= end_time; t += tick_sizing[ticks].span)
{ {
gdouble x = sysprof_visualizer_get_x_for_time (SYSPROF_VISUALIZER (self), t); gdouble x = sysprof_visualizer_get_x_for_time (SYSPROF_VISUALIZER (self), t);
cairo_move_to (cr, (gint)x - .5 - (gint)half, alloc.height);
cairo_line_to (cr, (gint)x - .5 - (gint)half, alloc.height - tick_sizing[ticks].height); gtk_snapshot_append_color (snapshot, color,
&GRAPHENE_RECT_INIT ((int)x - .5 - (int)half,
alloc.height,
(int)x - .5 - (int)half + tick_sizing[ticks].width,
alloc.height - tick_sizing[ticks].height));
count++; count++;
} }
cairo_set_line_width (cr, tick_sizing[ticks].width);
cairo_stroke (cr);
} }
return count > 2; return count > 2;
} }
static gboolean static void
sysprof_visualizer_ticks_draw (GtkWidget *widget, sysprof_visualizer_ticks_snapshot (GtkWidget *widget,
cairo_t *cr) GtkSnapshot *snapshot)
{ {
SysprofVisualizerTicks *self = SYSPROF_VISUALIZER_TICKS (widget); SysprofVisualizerTicks *self = SYSPROF_VISUALIZER_TICKS (widget);
GtkStyleContext *style; GtkStyleContext *style;
GtkAllocation alloc; GtkAllocation alloc;
GtkStateFlags state;
gint64 timespan; gint64 timespan;
GdkRGBA color; GdkRGBA color;
g_assert (SYSPROF_IS_VISUALIZER_TICKS (self)); g_assert (SYSPROF_IS_VISUALIZER_TICKS (self));
g_assert (cr != NULL); g_assert (snapshot != NULL);
timespan = sysprof_visualizer_get_duration (SYSPROF_VISUALIZER (self)); timespan = sysprof_visualizer_get_duration (SYSPROF_VISUALIZER (self));
if (timespan == 0) if (timespan == 0)
return GDK_EVENT_PROPAGATE; return;
style = gtk_widget_get_style_context (widget);
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc); gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
alloc.x = 0; alloc.x = 0;
alloc.y = 0; alloc.y = 0;
gtk_render_background (style, cr, 0, 0, alloc.width, alloc.height); style = gtk_widget_get_style_context (widget);
gtk_style_context_get_color (style, &color);
state = gtk_widget_get_state_flags (widget); gtk_snapshot_render_background (snapshot, style, 0, 0, alloc.width, alloc.height);
gtk_style_context_get_color (style, state, &color);
gdk_cairo_set_source_rgba (cr, &color);
/* /*
* We need to discover up to what level we will draw tick marks. * We need to discover up to what level we will draw tick marks.
@ -272,27 +273,32 @@ sysprof_visualizer_ticks_draw (GtkWidget *widget,
for (guint j = i; j > 0; j--) for (guint j = i; j > 0; j--)
{ {
if (draw_ticks (self, cr, &alloc, j - 1, FALSE)) if (draw_ticks (self, snapshot, &alloc, j - 1, FALSE, &color))
largest_match = j - 1; largest_match = j - 1;
} }
if (largest_match != -1) if (largest_match != -1)
draw_ticks (self, cr, &alloc, largest_match, TRUE); draw_ticks (self, snapshot, &alloc, largest_match, TRUE, &color);
break; break;
} }
return GDK_EVENT_PROPAGATE;
} }
static void static void
sysprof_visualizer_ticks_get_preferred_height (GtkWidget *widget, sysprof_visualizer_ticks_measure (GtkWidget *widget,
gint *min_height, GtkOrientation orientation,
gint *nat_height) int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{ {
g_assert (SYSPROF_IS_VISUALIZER_TICKS (widget)); g_assert (SYSPROF_IS_VISUALIZER_TICKS (widget));
*min_height = *nat_height = tick_sizing[0].height + LABEL_HEIGHT_PX; if (orientation == GTK_ORIENTATION_VERTICAL)
*minimum = *natural = tick_sizing[0].height + LABEL_HEIGHT_PX;
else
*minimum = *natural = 0;
} }
static void static void
@ -300,8 +306,8 @@ sysprof_visualizer_ticks_class_init (SysprofVisualizerTicksClass *klass)
{ {
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->draw = sysprof_visualizer_ticks_draw; widget_class->snapshot = sysprof_visualizer_ticks_snapshot;
widget_class->get_preferred_height = sysprof_visualizer_ticks_get_preferred_height; widget_class->measure = sysprof_visualizer_ticks_measure;
gtk_widget_class_set_css_name (widget_class, "SysprofVisualizerTicks"); gtk_widget_class_set_css_name (widget_class, "SysprofVisualizerTicks");
} }

View File

@ -31,14 +31,9 @@ typedef struct
gint64 begin_time; gint64 begin_time;
gint64 end_time; gint64 end_time;
gint64 duration; gint64 duration;
/* A cached allocation that has the borders subtracted so that
* we place the content within the expected area.
*/
GtkAllocation cache_alloc;
} SysprofVisualizerPrivate; } SysprofVisualizerPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizer, sysprof_visualizer, DZL_TYPE_BIN) G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizer, sysprof_visualizer, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -50,53 +45,6 @@ enum {
static GParamSpec *properties [N_PROPS]; static GParamSpec *properties [N_PROPS];
static inline void
subtract_border (GtkAllocation *alloc,
GtkBorder *border)
{
#if 0
g_print ("Border; %d %d %d %d\n", border->top, border->left, border->bottom, border->right);
#endif
alloc->x += border->left;
alloc->y += border->top;
alloc->width -= border->left + border->right;
alloc->height -= border->top + border->bottom;
}
static void
adjust_alloc_for_borders (SysprofVisualizer *self,
GtkAllocation *alloc)
{
GtkStyleContext *style_context;
GtkBorder border;
GtkStateFlags state;
g_assert (SYSPROF_IS_VISUALIZER (self));
g_assert (alloc != NULL);
state = gtk_widget_get_state_flags (GTK_WIDGET (self));
style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
gtk_style_context_get_border (style_context, state, &border);
subtract_border (alloc, &border);
}
static void
sysprof_visualizer_size_allocate (GtkWidget *widget,
GtkAllocation *alloc)
{
SysprofVisualizer *self = (SysprofVisualizer *)widget;
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
g_assert (SYSPROF_IS_VISUALIZER (self));
GTK_WIDGET_CLASS (sysprof_visualizer_parent_class)->size_allocate (widget, alloc);
priv->cache_alloc = *alloc;
adjust_alloc_for_borders (self, &priv->cache_alloc);
}
static void static void
sysprof_visualizer_finalize (GObject *object) sysprof_visualizer_finalize (GObject *object)
{ {
@ -175,8 +123,6 @@ sysprof_visualizer_class_init (SysprofVisualizerClass *klass)
object_class->get_property = sysprof_visualizer_get_property; object_class->get_property = sysprof_visualizer_get_property;
object_class->set_property = sysprof_visualizer_set_property; object_class->set_property = sysprof_visualizer_set_property;
widget_class->size_allocate = sysprof_visualizer_size_allocate;
properties [PROP_BEGIN_TIME] = properties [PROP_BEGIN_TIME] =
g_param_spec_int64 ("begin-time", g_param_spec_int64 ("begin-time",
"Begin Time", "Begin Time",
@ -296,20 +242,21 @@ sysprof_visualizer_translate_points (SysprofVisualizer *self,
SysprofVisualizerAbsolutePoint *out_points, SysprofVisualizerAbsolutePoint *out_points,
guint n_out_points) guint n_out_points)
{ {
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self); int width;
const GtkAllocation *a; int height;
g_return_if_fail (SYSPROF_IS_VISUALIZER (self)); g_return_if_fail (SYSPROF_IS_VISUALIZER (self));
g_return_if_fail (in_points != NULL); g_return_if_fail (in_points != NULL);
g_return_if_fail (out_points != NULL); g_return_if_fail (out_points != NULL);
g_return_if_fail (n_in_points == n_out_points); g_return_if_fail (n_in_points == n_out_points);
a = &priv->cache_alloc; width = gtk_widget_get_width (GTK_WIDGET (self));
height = gtk_widget_get_height (GTK_WIDGET (self));
for (guint i = 0; i < n_in_points; i++) for (guint i = 0; i < n_in_points; i++)
{ {
out_points[i].x = (in_points[i].x * a->width); out_points[i].x = (in_points[i].x * width);
out_points[i].y = a->height - (ABS (in_points[i].y) * a->height); out_points[i].y = height - (ABS (in_points[i].y) * height);
} }
} }
@ -319,7 +266,7 @@ sysprof_visualizer_get_x_for_time (SysprofVisualizer *self,
{ {
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self); SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
return ((time - priv->begin_time) / (gdouble)priv->duration) * priv->cache_alloc.width; return ((time - priv->begin_time) / (gdouble)priv->duration) * gtk_widget_get_width (GTK_WIDGET (self));
} }
void void

View File

@ -24,7 +24,7 @@
# error "Only <sysprof-ui.h> can be included directly." # error "Only <sysprof-ui.h> can be included directly."
#endif #endif
#include <dazzle.h> #include <gtk/gtk.h>
#include <sysprof.h> #include <sysprof.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -44,11 +44,11 @@ typedef struct
#define SYSPROF_TYPE_VISUALIZER (sysprof_visualizer_get_type()) #define SYSPROF_TYPE_VISUALIZER (sysprof_visualizer_get_type())
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (SysprofVisualizer, sysprof_visualizer, SYSPROF, VISUALIZER, DzlBin) G_DECLARE_DERIVABLE_TYPE (SysprofVisualizer, sysprof_visualizer, SYSPROF, VISUALIZER, GtkWidget)
struct _SysprofVisualizerClass struct _SysprofVisualizerClass
{ {
DzlBinClass parent_class; GtkWidgetClass parent_class;
void (*set_reader) (SysprofVisualizer *self, void (*set_reader) (SysprofVisualizer *self,
SysprofCaptureReader *reader); SysprofCaptureReader *reader);

View File

@ -30,7 +30,7 @@
struct _SysprofVisualizersFrame struct _SysprofVisualizersFrame
{ {
GtkBin parent_instance; GtkWidget parent_instance;
/* Drag selection tracking */ /* Drag selection tracking */
SysprofSelection *selection; SysprofSelection *selection;
@ -65,13 +65,14 @@ typedef struct
{ {
GtkListBox *list; GtkListBox *list;
GtkStyleContext *style_context; GtkStyleContext *style_context;
cairo_t *cr; GtkSnapshot *snapshot;
GtkAllocation alloc; int width;
int height;
gint64 begin_time; gint64 begin_time;
gint64 duration; gint64 duration;
} SelectionDraw; } SelectionDraw;
G_DEFINE_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, GTK_TYPE_BIN) G_DEFINE_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, GTK_TYPE_WIDGET)
enum { enum {
PROP_0, PROP_0,
@ -115,16 +116,16 @@ draw_selection_cb (SysprofSelection *selection,
g_assert (SYSPROF_IS_SELECTION (selection)); g_assert (SYSPROF_IS_SELECTION (selection));
g_assert (draw != NULL); g_assert (draw != NULL);
g_assert (draw->cr != NULL); g_assert (draw->snapshot != NULL);
g_assert (GTK_IS_LIST_BOX (draw->list)); g_assert (GTK_IS_LIST_BOX (draw->list));
x = (range_begin - draw->begin_time) / (gdouble)draw->duration; x = (range_begin - draw->begin_time) / (gdouble)draw->duration;
x2 = (range_end - draw->begin_time) / (gdouble)draw->duration; x2 = (range_end - draw->begin_time) / (gdouble)draw->duration;
area.x = x * draw->alloc.width; area.x = x * draw->width;
area.width = (x2 * draw->alloc.width) - area.x; area.width = (x2 * draw->width) - area.x;
area.y = 0; area.y = 0;
area.height = draw->alloc.height; area.height = draw->height;
if (area.width < 0) if (area.width < 0)
{ {
@ -132,104 +133,106 @@ draw_selection_cb (SysprofSelection *selection,
area.x -= area.width; area.x -= area.width;
} }
gtk_render_background (draw->style_context, draw->cr, area.x + 2, area.y + 2, area.width - 4, area.height - 4); gtk_snapshot_render_background (draw->snapshot, draw->style_context, area.x + 2, area.y + 2, area.width - 4, area.height - 4);
} }
static gboolean static void
visualizers_draw_after_cb (SysprofVisualizersFrame *self, sysprof_visualizers_frame_snapshot (GtkWidget *widget,
cairo_t *cr, GtkSnapshot *snapshot)
GtkListBox *list)
{ {
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)widget;
SelectionDraw draw; SelectionDraw draw;
GtkAllocation alloc;
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self)); g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (GTK_IS_LIST_BOX (list)); g_assert (GTK_IS_SNAPSHOT (snapshot));
GTK_WIDGET_CLASS (sysprof_visualizers_frame_parent_class)->snapshot (widget, snapshot);
draw.style_context = gtk_widget_get_style_context (GTK_WIDGET (list));
draw.list = list;
draw.cr = cr;
draw.begin_time = self->begin_time;
draw.duration = sysprof_visualizer_get_duration (SYSPROF_VISUALIZER (self->ticks)); draw.duration = sysprof_visualizer_get_duration (SYSPROF_VISUALIZER (self->ticks));
if (draw.duration == 0) if (draw.duration == 0)
return GDK_EVENT_PROPAGATE; return;
gtk_widget_get_allocation (GTK_WIDGET (list), &draw.alloc); draw.style_context = gtk_widget_get_style_context (GTK_WIDGET (self->visualizers));
draw.list = self->visualizers;
draw.snapshot = snapshot;
draw.begin_time = self->begin_time;
gtk_widget_get_allocation (GTK_WIDGET (self->visualizers), &alloc);
draw.width = alloc.width;
draw.height = alloc.height;
if (sysprof_selection_get_has_selection (self->selection) || self->button_pressed) if (sysprof_selection_get_has_selection (self->selection) || self->button_pressed)
{ {
double x, y;
gtk_snapshot_save (snapshot);
gtk_widget_translate_coordinates (GTK_WIDGET (self->visualizers),
GTK_WIDGET (self),
0, 0, &x, &y);
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
gtk_style_context_add_class (draw.style_context, "selection"); gtk_style_context_add_class (draw.style_context, "selection");
sysprof_selection_foreach (self->selection, draw_selection_cb, &draw); sysprof_selection_foreach (self->selection, draw_selection_cb, &draw);
if (self->button_pressed) if (self->button_pressed)
draw_selection_cb (self->selection, self->drag_begin_at, self->drag_selection_at, &draw); draw_selection_cb (self->selection, self->drag_begin_at, self->drag_selection_at, &draw);
gtk_style_context_remove_class (draw.style_context, "selection"); gtk_style_context_remove_class (draw.style_context, "selection");
}
return GDK_EVENT_PROPAGATE; gtk_snapshot_restore (snapshot);
}
} }
static void static void
visualizers_realize_after_cb (SysprofVisualizersFrame *self,
GtkListBox *list)
{
GdkDisplay *display;
GdkWindow *window;
GdkCursor *cursor;
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (GTK_IS_LIST_BOX (list));
window = gtk_widget_get_window (GTK_WIDGET (list));
display = gdk_window_get_display (window);
cursor = gdk_cursor_new_from_name (display, "text");
gdk_window_set_cursor (window, cursor);
g_clear_object (&cursor);
}
static gboolean
visualizers_button_press_event_cb (SysprofVisualizersFrame *self, visualizers_button_press_event_cb (SysprofVisualizersFrame *self,
GdkEventButton *ev, int n_presses,
GtkListBox *visualizers) double x,
double y,
GtkGestureClick *gesture)
{ {
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self)); GdkModifierType state;
g_assert (ev != NULL); guint button;
g_assert (GTK_IS_LIST_BOX (visualizers));
if (ev->button != GDK_BUTTON_PRIMARY) g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (GTK_IS_GESTURE_CLICK (gesture));
button = gtk_gesture_single_get_button (GTK_GESTURE_SINGLE (gesture));
if (button != GDK_BUTTON_PRIMARY)
{ {
if (sysprof_selection_get_has_selection (self->selection)) if (sysprof_selection_get_has_selection (self->selection))
{ sysprof_selection_unselect_all (self->selection);
sysprof_selection_unselect_all (self->selection); return;
return GDK_EVENT_STOP;
}
return GDK_EVENT_PROPAGATE;
} }
if ((ev->state & GDK_SHIFT_MASK) == 0) state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (gesture));
if ((state & GDK_SHIFT_MASK) == 0)
sysprof_selection_unselect_all (self->selection); sysprof_selection_unselect_all (self->selection);
self->button_pressed = TRUE; self->button_pressed = TRUE;
self->drag_begin_at = get_time_from_x (self, ev->x); self->drag_begin_at = get_time_from_x (self, x);
self->drag_selection_at = self->drag_begin_at; self->drag_selection_at = self->drag_begin_at;
gtk_widget_queue_draw (GTK_WIDGET (visualizers)); gtk_widget_queue_draw (GTK_WIDGET (self));
return GDK_EVENT_PROPAGATE;
} }
static gboolean static void
visualizers_button_release_event_cb (SysprofVisualizersFrame *self, visualizers_button_release_event_cb (SysprofVisualizersFrame *self,
GdkEventButton *ev, int n_release,
GtkListBox *list) double x,
double y,
GtkGestureClick *gesture)
{ {
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self)); guint button;
g_assert (ev != NULL);
g_assert (GTK_IS_LIST_BOX (list));
if (!self->button_pressed || ev->button != GDK_BUTTON_PRIMARY) g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
return GDK_EVENT_PROPAGATE; g_assert (GTK_IS_GESTURE_CLICK (gesture));
button = gtk_gesture_single_get_button (GTK_GESTURE_SINGLE (gesture));
if (!self->button_pressed || button != GDK_BUTTON_PRIMARY)
return;
self->button_pressed = FALSE; self->button_pressed = FALSE;
@ -242,46 +245,33 @@ visualizers_button_release_event_cb (SysprofVisualizersFrame *self,
self->drag_selection_at = -1; self->drag_selection_at = -1;
} }
gtk_widget_queue_draw (GTK_WIDGET (list)); gtk_widget_queue_draw (GTK_WIDGET (self));
return GDK_EVENT_STOP;
} }
static gboolean static void
visualizers_motion_notify_event_cb (SysprofVisualizersFrame *self, visualizers_motion_notify_event_cb (SysprofVisualizersFrame *self,
GdkEventMotion *ev, double x,
GtkListBox *list) double y,
GtkEventControllerMotion *motion)
{ {
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self)); g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (ev != NULL); g_assert (GTK_IS_EVENT_CONTROLLER_MOTION (motion));
g_assert (GTK_IS_LIST_BOX (list));
if (!self->button_pressed) if (self->button_pressed)
return GDK_EVENT_PROPAGATE; {
self->drag_selection_at = get_time_from_x (self, x);
self->drag_selection_at = get_time_from_x (self, ev->x); gtk_widget_queue_draw (GTK_WIDGET (self));
}
gtk_widget_queue_draw (GTK_WIDGET (list));
return GDK_EVENT_PROPAGATE;
} }
static void static void
set_children_width_request_cb (GtkWidget *widget, set_children_width_request (GtkWidget *widget,
gpointer data) int width)
{ {
gtk_widget_set_size_request (widget, GPOINTER_TO_INT (data), -1); for (GtkWidget *child = gtk_widget_get_first_child (widget);
} child;
child = gtk_widget_get_next_sibling (child))
static void gtk_widget_set_size_request (child, width, -1);
set_children_width_request (GtkContainer *container,
gint width)
{
g_assert (GTK_IS_CONTAINER (container));
gtk_container_foreach (container,
set_children_width_request_cb,
GINT_TO_POINTER (width));
} }
static void static void
@ -297,8 +287,8 @@ sysprof_visualizers_frame_notify_zoom (SysprofVisualizersFrame *self,
duration = self->end_time - self->begin_time; duration = self->end_time - self->begin_time;
data_width = sysprof_zoom_manager_get_width_for_duration (self->zoom_manager, duration); data_width = sysprof_zoom_manager_get_width_for_duration (self->zoom_manager, duration);
set_children_width_request (GTK_CONTAINER (self->ticks_viewport), data_width); set_children_width_request (GTK_WIDGET (self->ticks_viewport), data_width);
set_children_width_request (GTK_CONTAINER (self->visualizers_viewport), data_width); set_children_width_request (GTK_WIDGET (self->visualizers_viewport), data_width);
} }
static gint static gint
@ -306,17 +296,16 @@ find_pos (SysprofVisualizersFrame *self,
const gchar *title, const gchar *title,
gint priority) gint priority)
{ {
GList *list;
gint pos = 0; gint pos = 0;
if (title == NULL) if (title == NULL)
return -1; return -1;
list = gtk_container_get_children (GTK_CONTAINER (self->visualizers)); for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->visualizers));
child;
for (const GList *iter = list; iter; iter = iter->next) child = gtk_widget_get_next_sibling (child))
{ {
SysprofVisualizerGroup *group = iter->data; SysprofVisualizerGroup *group = SYSPROF_VISUALIZER_GROUP (child);
gint prio = sysprof_visualizer_group_get_priority (group); gint prio = sysprof_visualizer_group_get_priority (group);
const gchar *item = sysprof_visualizer_group_get_title (group); const gchar *item = sysprof_visualizer_group_get_title (group);
@ -327,41 +316,34 @@ find_pos (SysprofVisualizersFrame *self,
pos++; pos++;
} }
g_list_free (list);
return pos; return pos;
} }
static void void
sysprof_visualizers_frame_add (GtkContainer *container, sysprof_visualizers_frame_add_group (SysprofVisualizersFrame *self,
GtkWidget *child) SysprofVisualizerGroup *group)
{ {
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)container; SysprofVisualizerGroupHeader *header;
const char *title;
int priority;
int pos;
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self)); g_return_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (GTK_IS_WIDGET (child)); g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (group));
if (SYSPROF_IS_VISUALIZER_GROUP (child)) title = sysprof_visualizer_group_get_title (group);
{ priority = sysprof_visualizer_group_get_priority (group);
SysprofVisualizerGroupHeader *header; pos = find_pos (self, title, priority);
const gchar *title = sysprof_visualizer_group_get_title (SYSPROF_VISUALIZER_GROUP (child));
gint priority = sysprof_visualizer_group_get_priority (SYSPROF_VISUALIZER_GROUP (child));
gint pos = find_pos (self, title, priority);
gtk_list_box_insert (self->visualizers, child, pos); gtk_list_box_insert (self->visualizers, GTK_WIDGET (group), pos);
header = _sysprof_visualizer_group_header_new (); header = _sysprof_visualizer_group_header_new ();
g_object_set_data (G_OBJECT (header), "VISUALIZER_GROUP", child); g_object_set_data (G_OBJECT (header), "VISUALIZER_GROUP", group);
gtk_list_box_insert (self->groups, GTK_WIDGET (header), pos); gtk_list_box_insert (self->groups, GTK_WIDGET (header), pos);
_sysprof_visualizer_group_set_header (SYSPROF_VISUALIZER_GROUP (child), header); _sysprof_visualizer_group_set_header (group, header);
gtk_widget_show (GTK_WIDGET (header)); gtk_widget_show (GTK_WIDGET (header));
sysprof_visualizers_frame_notify_zoom (self, NULL, self->zoom_manager); sysprof_visualizers_frame_notify_zoom (self, NULL, self->zoom_manager);
return;
}
GTK_CONTAINER_CLASS (sysprof_visualizers_frame_parent_class)->add (container, child);
} }
static void static void
@ -392,27 +374,17 @@ sysprof_visualizers_frame_group_activated_cb (SysprofVisualizersFrame *self
} }
static void static void
sysprof_visualizers_frame_size_allocate (GtkWidget *widget, sysprof_visualizers_frame_dispose (GObject *object)
GtkAllocation *alloc)
{
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)widget;
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (alloc != NULL);
sysprof_scrollmap_set_time_range (self->hscrollbar, self->begin_time, self->end_time);
GTK_WIDGET_CLASS (sysprof_visualizers_frame_parent_class)->size_allocate (widget, alloc);
}
static void
sysprof_visualizers_frame_finalize (GObject *object)
{ {
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)object; SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)object;
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
g_clear_object (&self->selection); g_clear_object (&self->selection);
G_OBJECT_CLASS (sysprof_visualizers_frame_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_visualizers_frame_parent_class)->dispose (object);
} }
static void static void
@ -443,16 +415,14 @@ sysprof_visualizers_frame_class_init (SysprofVisualizersFrameClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->finalize = sysprof_visualizers_frame_finalize; object_class->dispose = sysprof_visualizers_frame_dispose;
object_class->get_property = sysprof_visualizers_frame_get_property; object_class->get_property = sysprof_visualizers_frame_get_property;
widget_class->size_allocate = sysprof_visualizers_frame_size_allocate; widget_class->snapshot = sysprof_visualizers_frame_snapshot;
container_class->add = sysprof_visualizers_frame_add;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-visualizers-frame.ui"); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-visualizers-frame.ui");
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_css_name (widget_class, "SysprofVisualizersFrame"); gtk_widget_class_set_css_name (widget_class, "SysprofVisualizersFrame");
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, groups); gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, groups);
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, hscrollbar); gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, hscrollbar);
@ -491,18 +461,43 @@ sysprof_visualizers_frame_class_init (SysprofVisualizersFrameClass *klass)
static void static void
sysprof_visualizers_frame_init (SysprofVisualizersFrame *self) sysprof_visualizers_frame_init (SysprofVisualizersFrame *self)
{ {
GtkEventController *controller;
GtkAdjustment *hadj; GtkAdjustment *hadj;
GtkAdjustment *zadj; GtkAdjustment *zadj;
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
gtk_widget_set_cursor_from_name (GTK_WIDGET (self->visualizers), "text");
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
g_signal_connect_object (controller,
"pressed",
G_CALLBACK (visualizers_button_press_event_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (controller,
"released",
G_CALLBACK (visualizers_button_release_event_cb),
self,
G_CONNECT_SWAPPED);
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
gtk_widget_add_controller (GTK_WIDGET (self->visualizers), controller);
controller = gtk_event_controller_motion_new ();
g_signal_connect_object (controller,
"motion",
G_CALLBACK (visualizers_motion_notify_event_cb),
self,
G_CONNECT_SWAPPED);
gtk_widget_add_controller (GTK_WIDGET (self->visualizers), controller);
self->selection = g_object_new (SYSPROF_TYPE_SELECTION, NULL); self->selection = g_object_new (SYSPROF_TYPE_SELECTION, NULL);
zadj = sysprof_zoom_manager_get_adjustment (self->zoom_manager); zadj = sysprof_zoom_manager_get_adjustment (self->zoom_manager);
hadj = gtk_scrolled_window_get_hadjustment (self->hscroller); hadj = gtk_scrolled_window_get_hadjustment (self->hscroller);
gtk_scrolled_window_set_hadjustment (self->ticks_scroller, hadj); gtk_scrolled_window_set_hadjustment (self->ticks_scroller, hadj);
gtk_range_set_adjustment (GTK_RANGE (self->hscrollbar), hadj); sysprof_scrollmap_set_adjustment (self->hscrollbar, hadj);
gtk_range_set_adjustment (GTK_RANGE (self->zoom_scale), zadj); gtk_range_set_adjustment (GTK_RANGE (self->zoom_scale), zadj);
gtk_widget_insert_action_group (GTK_WIDGET (self), gtk_widget_insert_action_group (GTK_WIDGET (self),
@ -521,36 +516,6 @@ sysprof_visualizers_frame_init (SysprofVisualizersFrame *self)
self, self,
G_CONNECT_SWAPPED); G_CONNECT_SWAPPED);
g_signal_connect_object (self->visualizers,
"draw",
G_CALLBACK (visualizers_draw_after_cb),
self,
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
g_signal_connect_object (self->visualizers,
"realize",
G_CALLBACK (visualizers_realize_after_cb),
self,
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
g_signal_connect_object (self->visualizers,
"button-press-event",
G_CALLBACK (visualizers_button_press_event_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->visualizers,
"button-release-event",
G_CALLBACK (visualizers_button_release_event_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->visualizers,
"motion-notify-event",
G_CALLBACK (visualizers_motion_notify_event_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->zoom_manager, g_signal_connect_object (self->zoom_manager,
"notify::zoom", "notify::zoom",
G_CALLBACK (sysprof_visualizers_frame_notify_zoom), G_CALLBACK (sysprof_visualizers_frame_notify_zoom),
@ -745,7 +710,7 @@ sysprof_visualizers_frame_get_hadjustment (SysprofVisualizersFrame *self)
{ {
g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), NULL); g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), NULL);
return gtk_range_get_adjustment (GTK_RANGE (self->hscrollbar)); return sysprof_scrollmap_get_adjustment (self->hscrollbar);
} }
void void

View File

@ -30,8 +30,10 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_VISUALIZERS_FRAME (sysprof_visualizers_frame_get_type()) #define SYSPROF_TYPE_VISUALIZERS_FRAME (sysprof_visualizers_frame_get_type())
G_DECLARE_FINAL_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, SYSPROF, VISUALIZERS_FRAME, GtkBin) G_DECLARE_FINAL_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, SYSPROF, VISUALIZERS_FRAME, GtkWidget)
void sysprof_visualizers_frame_add_group (SysprofVisualizersFrame *self,
SysprofVisualizerGroup *group);
SysprofSelection *sysprof_visualizers_frame_get_selection (SysprofVisualizersFrame *self); SysprofSelection *sysprof_visualizers_frame_get_selection (SysprofVisualizersFrame *self);
SysprofVisualizerGroup *sysprof_visualizers_frame_get_selected_group (SysprofVisualizersFrame *self); SysprofVisualizerGroup *sysprof_visualizers_frame_get_selected_group (SysprofVisualizersFrame *self);
SysprofZoomManager *sysprof_visualizers_frame_get_zoom_manager (SysprofVisualizersFrame *self); SysprofZoomManager *sysprof_visualizers_frame_get_zoom_manager (SysprofVisualizersFrame *self);

View File

@ -1,44 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface> <interface>
<requires lib="gtk+" version="3.22"/> <template class="SysprofVisualizersFrame" parent="GtkWidget">
<template class="SysprofVisualizersFrame" parent="GtkBin">
<property name="can_focus">False</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkBox" id="box1"> <object class="GtkBox" id="box1">
<property name="width_request">125</property> <property name="width_request">125</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkBox"> <object class="GtkCenterBox">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="visible">true</property> <property name="visible">true</property>
<property name="margin-top">3</property> <property name="margin-top">3</property>
<property name="margin-bottom">3</property> <property name="margin-bottom">3</property>
<property name="margin-start">7</property> <property name="margin-start">7</property>
<property name="margin-end">7</property> <property name="margin-end">7</property>
<property name="hexpand">false</property>
<style> <style>
<class name="left-column"/> <class name="left-column"/>
</style> </style>
<child type="center"> <child type="center">
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">6</property>
<property name="margin_end">6</property>
<property name="margin_top">3</property>
<property name="margin_bottom">3</property>
<property name="label" translatable="yes">Instruments</property> <property name="label" translatable="yes">Instruments</property>
<property name="hexpand">true</property>
<style> <style>
<class name="dim-label"/> <class name="dim-label"/>
</style> </style>
@ -47,12 +34,11 @@
</attributes> </attributes>
</object> </object>
</child> </child>
<child> <child type="end">
<object class="GtkButton"> <object class="GtkButton">
<property name="action-name">display.page</property> <property name="action-name">display.page</property>
<property name="action-target">'details'</property> <property name="action-target">'details'</property>
<property name="tooltip-text" translatable="yes">Select for more details</property> <property name="tooltip-text" translatable="yes">Select for more details</property>
<property name="visible">true</property>
<style> <style>
<class name="image-button"/> <class name="image-button"/>
<class name="small-button"/> <class name="small-button"/>
@ -66,339 +52,170 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="pack-type">end</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox" id="ticks_box"> <object class="GtkBox" id="ticks_box">
<property name="visible">True</property> <property name="vexpand">false</property>
<property name="can_focus">False</property>
<property name="vexpand">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkScrolledWindow" id="ticks_scroller"> <object class="GtkScrolledWindow" id="ticks_scroller">
<property name="visible">True</property> <property name="hexpand">true</property>
<property name="can_focus">True</property> <property name="vexpand">true</property>
<property name="hexpand">True</property> <property name="hscrollbar-policy">external</property>
<property name="vexpand">True</property> <property name="vscrollbar-policy">never</property>
<property name="hscrollbar_policy">external</property>
<property name="vscrollbar_policy">never</property>
<child> <child>
<object class="GtkViewport" id="ticks_viewport"> <object class="GtkViewport" id="ticks_viewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property> <property name="halign">start</property>
<property name="shadow_type">none</property>
<style> <style>
<class name="visualizers"/> <class name="visualizers"/>
</style> </style>
<child> <child>
<object class="SysprofVisualizerTicks" id="ticks"> <object class="SysprofVisualizerTicks" id="ticks">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow" id="vscroller"> <object class="GtkScrolledWindow" id="vscroller">
<property name="visible">True</property> <property name="vexpand">true</property>
<property name="can_focus">True</property> <property name="hscrollbar-policy">never</property>
<property name="vexpand">True</property> <property name="propagate-natural-height">true</property>
<property name="hscrollbar_policy">never</property>
<property name="propagate_natural_height">True</property>
<child> <child>
<object class="GtkViewport"> <object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="shadow_type">none</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="orientation">horizontal</property> <property name="orientation">horizontal</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkListBox" id="groups"> <object class="GtkListBox" id="groups">
<property name="width_request">125</property> <property name="width_request">125</property>
<property name="visible">True</property> <property name="hexpand">false</property>
<property name="can_focus">False</property> <property name="selection-mode">single</property>
<property name="hexpand">False</property>
<property name="selection_mode">single</property>
<style> <style>
<class name="left-column"/> <class name="left-column"/>
<class name="visualizer-groups"/> <class name="visualizer-groups"/>
</style> </style>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScrolledWindow" id="hscroller"> <object class="GtkScrolledWindow" id="hscroller">
<property name="visible">True</property> <property name="hexpand">true</property>
<property name="can_focus">True</property> <property name="hscrollbar-policy">external</property>
<property name="hexpand">True</property> <property name="vscrollbar-policy">never</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">external</property>
<property name="vscrollbar_policy">never</property>
<property name="propagate_natural_height">True</property>
<child> <child>
<object class="GtkViewport" id="visualizers_viewport"> <object class="GtkViewport" id="visualizers_viewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="shadow_type">none</property>
<property name="halign">start</property> <property name="halign">start</property>
<style> <style>
<class name="visualizers"/> <class name="visualizers"/>
</style> </style>
<child> <child>
<object class="GtkListBox" id="visualizers"> <object class="GtkListBox" id="visualizers">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property> <property name="selection_mode">none</property>
<property name="activate_on_single_click">False</property> <property name="activate_on_single_click">false</property>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style> <style>
<class name="inline-toolbar"/> <class name="inline-toolbar"/>
</style> </style>
<child> <child>
<object class="GtkBox" id="box2"> <object class="GtkBox" id="box2">
<property name="width_request">125</property> <property name="width_request">125</property>
<property name="visible">True</property>
<property name="margin-start">6</property> <property name="margin-start">6</property>
<property name="margin-end">6</property> <property name="margin-end">6</property>
<property name="can_focus">False</property> <property name="hexpand">false</property>
<property name="hexpand">False</property>
<style> <style>
<class name="left-column"/> <class name="left-column"/>
</style> </style>
<child> <child>
<object class="GtkButton" id="zoom_out"> <object class="GtkButton" id="zoom_out">
<property name="action-name">zoom.zoom-out</property> <property name="action-name">zoom.zoom-out</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="valign">center</property> <property name="valign">center</property>
<child> <property name="icon_name">zoom-out-symbolic</property>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">zoom-out-symbolic</property>
</object>
</child>
<style> <style>
<class name="image-button"/> <class name="image-button"/>
<class name="small-button"/> <class name="small-button"/>
<class name="flat"/> <class name="flat"/>
</style> </style>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkScale" id="zoom_scale"> <object class="GtkScale" id="zoom_scale">
<property name="width_request">175</property> <property name="width_request">175</property>
<property name="visible">True</property> <property name="hexpand">true</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="round_digits">1</property> <property name="round_digits">1</property>
<property name="draw_value">False</property> <property name="draw_value">false</property>
<marks> <marks>
<mark value="0.0" position="bottom"/> <mark value="0.0" position="bottom"/>
</marks> </marks>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="zoom_in"> <object class="GtkButton" id="zoom_in">
<property name="action-name">zoom.zoom-in</property> <property name="action-name">zoom.zoom-in</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
<property name="valign">center</property> <property name="valign">center</property>
<child> <property name="icon-name">zoom-in-symbolic</property>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">zoom-in-symbolic</property>
</object>
</child>
<style> <style>
<class name="image-button"/> <class name="image-button"/>
<class name="small-button"/> <class name="small-button"/>
<class name="flat"/> <class name="flat"/>
</style> </style>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkSeparator"> <object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child> </child>
<child> <child>
<object class="SysprofScrollmap" id="hscrollbar"> <object class="SysprofScrollmap" id="hscrollbar">
<property name="visible">True</property> <property name="hexpand">true</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child> </child>
</object> </object>
</child> </child>

View File

@ -1,4 +1,5 @@
sysprof_header_subdir = 'sysprof-@0@'.format(libsysprof_api_version) sysprof_header_subdir = 'sysprof-@0@'.format(libsysprof_api_version)
sysprof_ui_header_subdir = 'sysprof-ui-@0@'.format(libsysprof_ui_api_version)
sysprof_version_conf = configuration_data() sysprof_version_conf = configuration_data()
sysprof_version = meson.project_version().split('.') sysprof_version = meson.project_version().split('.')

View File

@ -0,0 +1,639 @@
/* egg-binding-group.c
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
* Copyright (C) 2015 Garrett Regier <garrettregier@gmail.com>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This file 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
* Lesser 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 "config.h"
#include <glib/gi18n.h>
#include "egg-binding-group.h"
/**
* SECTION:eggbindinggroup
* @title: EggBindingGroup
* @short_description: Manage a collection of #GBindings on
* a #GObject as a group.
*
* #EggBindingGroup manages to simplify the process of binding
* many properties from a #GObject as a group. As such there is no API
* to unbind a property from the group.
*
* In particular, this allows you to change the source instance for the
* bindings. This automatically causes the unbinding of the properties
* from the old instance and binding to the new instance.
*
* This should not be confused with #GtkBindingGroup.
*/
struct _EggBindingGroup
{
GObject parent_instance;
GObject *source;
GPtrArray *lazy_bindings;
};
typedef struct
{
EggBindingGroup *group;
const gchar *source_property;
const gchar *target_property;
GObject *target;
GBinding *binding;
gpointer user_data;
GDestroyNotify user_data_destroy;
gpointer transform_to;
gpointer transform_from;
GBindingFlags binding_flags;
guint using_closures : 1;
} LazyBinding;
G_DEFINE_TYPE (EggBindingGroup, egg_binding_group, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_SOURCE,
LAST_PROP
};
static GParamSpec *properties [LAST_PROP];
/*#define DEBUG_BINDINGS 1*/
#ifdef DEBUG_BINDINGS
static gchar *
_g_flags_to_string (GFlagsClass *flags_class,
guint value)
{
GString *str;
GFlagsValue *flags_value;
gboolean first = TRUE;
str = g_string_new (NULL);
while ((first || value != 0) &&
(flags_value = g_flags_get_first_value (flags_class, value)) != NULL)
{
if (!first)
g_string_append (str, " | ");
g_string_append (str, flags_value->value_name);
first = FALSE;
value &= ~(flags_value->value);
}
return g_string_free (str, FALSE);
}
#endif
static void
egg_binding_group_connect (EggBindingGroup *self,
LazyBinding *lazy_binding)
{
GBinding *binding;
g_assert (EGG_IS_BINDING_GROUP (self));
g_assert (self->source != NULL);
g_assert (lazy_binding != NULL);
g_assert (lazy_binding->binding == NULL);
g_assert (lazy_binding->target != NULL);
g_assert (lazy_binding->target_property != NULL);
g_assert (lazy_binding->source_property != NULL);
#ifdef DEBUG_BINDINGS
{
GFlagsClass *flags_class;
g_autofree gchar *flags_str = NULL;
flags_class = g_type_class_ref (G_TYPE_BINDING_FLAGS);
flags_str = _g_flags_to_string (flags_class,
lazy_binding->binding_flags);
g_print ("Binding %s(%p):%s to %s(%p):%s (flags=%s)\n",
G_OBJECT_TYPE_NAME (self->source),
self->source,
lazy_binding->source_property,
G_OBJECT_TYPE_NAME (lazy_binding->target),
lazy_binding->target,
lazy_binding->target_property,
flags_str);
g_type_class_unref (flags_class);
}
#endif
if (!lazy_binding->using_closures)
{
binding = g_object_bind_property_full (self->source,
lazy_binding->source_property,
lazy_binding->target,
lazy_binding->target_property,
lazy_binding->binding_flags,
lazy_binding->transform_to,
lazy_binding->transform_from,
lazy_binding->user_data,
NULL);
}
else
{
binding = g_object_bind_property_with_closures (self->source,
lazy_binding->source_property,
lazy_binding->target,
lazy_binding->target_property,
lazy_binding->binding_flags,
lazy_binding->transform_to,
lazy_binding->transform_from);
}
lazy_binding->binding = binding;
}
static void
egg_binding_group_disconnect (LazyBinding *lazy_binding)
{
g_assert (lazy_binding != NULL);
if (lazy_binding->binding != NULL)
{
g_binding_unbind (lazy_binding->binding);
lazy_binding->binding = NULL;
}
}
static void
egg_binding_group__source_weak_notify (gpointer data,
GObject *where_object_was)
{
EggBindingGroup *self = data;
gsize i;
g_assert (EGG_IS_BINDING_GROUP (self));
self->source = NULL;
for (i = 0; i < self->lazy_bindings->len; i++)
{
LazyBinding *lazy_binding;
lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
lazy_binding->binding = NULL;
}
}
static void
egg_binding_group__target_weak_notify (gpointer data,
GObject *where_object_was)
{
EggBindingGroup *self = data;
gsize i;
g_assert (EGG_IS_BINDING_GROUP (self));
for (i = 0; i < self->lazy_bindings->len; i++)
{
LazyBinding *lazy_binding;
lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
if (lazy_binding->target == where_object_was)
{
lazy_binding->target = NULL;
lazy_binding->binding = NULL;
g_ptr_array_remove_index_fast (self->lazy_bindings, i);
break;
}
}
}
static void
lazy_binding_free (gpointer data)
{
LazyBinding *lazy_binding = data;
if (lazy_binding->target != NULL)
{
g_object_weak_unref (lazy_binding->target,
egg_binding_group__target_weak_notify,
lazy_binding->group);
lazy_binding->target = NULL;
}
egg_binding_group_disconnect (lazy_binding);
lazy_binding->group = NULL;
lazy_binding->source_property = NULL;
lazy_binding->target_property = NULL;
if (lazy_binding->user_data_destroy)
lazy_binding->user_data_destroy (lazy_binding->user_data);
if (lazy_binding->using_closures)
{
g_clear_pointer (&lazy_binding->transform_to, g_closure_unref);
g_clear_pointer (&lazy_binding->transform_from, g_closure_unref);
}
g_slice_free (LazyBinding, lazy_binding);
}
static void
egg_binding_group_dispose (GObject *object)
{
EggBindingGroup *self = (EggBindingGroup *)object;
g_assert (EGG_IS_BINDING_GROUP (self));
if (self->source != NULL)
{
g_object_weak_unref (self->source,
egg_binding_group__source_weak_notify,
self);
self->source = NULL;
}
if (self->lazy_bindings->len != 0)
g_ptr_array_remove_range (self->lazy_bindings, 0, self->lazy_bindings->len);
G_OBJECT_CLASS (egg_binding_group_parent_class)->dispose (object);
}
static void
egg_binding_group_finalize (GObject *object)
{
EggBindingGroup *self = (EggBindingGroup *)object;
g_assert (self->lazy_bindings != NULL);
g_assert (self->lazy_bindings->len == 0);
g_clear_pointer (&self->lazy_bindings, g_ptr_array_unref);
G_OBJECT_CLASS (egg_binding_group_parent_class)->finalize (object);
}
static void
egg_binding_group_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EggBindingGroup *self = EGG_BINDING_GROUP (object);
switch (prop_id)
{
case PROP_SOURCE:
g_value_set_object (value, egg_binding_group_get_source (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_binding_group_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EggBindingGroup *self = EGG_BINDING_GROUP (object);
switch (prop_id)
{
case PROP_SOURCE:
egg_binding_group_set_source (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
egg_binding_group_class_init (EggBindingGroupClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = egg_binding_group_dispose;
object_class->finalize = egg_binding_group_finalize;
object_class->get_property = egg_binding_group_get_property;
object_class->set_property = egg_binding_group_set_property;
/**
* EggBindingGroup:source
*
* The source object used for binding properties.
*/
properties [PROP_SOURCE] =
g_param_spec_object ("source",
"Source",
"The source GObject used for binding properties.",
G_TYPE_OBJECT,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, LAST_PROP, properties);
}
static void
egg_binding_group_init (EggBindingGroup *self)
{
self->lazy_bindings = g_ptr_array_new_with_free_func (lazy_binding_free);
}
/**
* egg_binding_group_new:
*
* Creates a new #EggBindingGroup.
*
* Returns: a new #EggBindingGroup
*/
EggBindingGroup *
egg_binding_group_new (void)
{
return g_object_new (EGG_TYPE_BINDING_GROUP, NULL);
}
/**
* egg_binding_group_get_source:
* @self: the #EggBindingGroup
*
* Gets the source object used for binding properties.
*
* Returns: (transfer none) (nullable): the source object.
*/
GObject *
egg_binding_group_get_source (EggBindingGroup *self)
{
g_return_val_if_fail (EGG_IS_BINDING_GROUP (self), NULL);
return self->source;
}
static gboolean
egg_binding_group_check_source (EggBindingGroup *self,
gpointer source)
{
gsize i;
for (i = 0; i < self->lazy_bindings->len; i++)
{
LazyBinding *lazy_binding;
lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
g_return_val_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
lazy_binding->source_property) != NULL,
FALSE);
}
return TRUE;
}
/**
* egg_binding_group_set_source:
* @self: the #EggBindingGroup
* @source: (type GObject) (nullable): the source #GObject
*
* Sets @source as the source object used for creating property
* bindings. If there is already a source object all bindings from it
* will be removed.
*
* Note: All properties that have been bound must exist on @source.
*/
void
egg_binding_group_set_source (EggBindingGroup *self,
gpointer source)
{
g_return_if_fail (EGG_IS_BINDING_GROUP (self));
g_return_if_fail (!source || G_IS_OBJECT (source));
g_return_if_fail (source != (gpointer)self);
if (source == (gpointer)self->source)
return;
if (self->source != NULL)
{
gsize i;
g_object_weak_unref (self->source,
egg_binding_group__source_weak_notify,
self);
self->source = NULL;
for (i = 0; i < self->lazy_bindings->len; i++)
{
LazyBinding *lazy_binding;
lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
egg_binding_group_disconnect (lazy_binding);
}
}
if (source != NULL && egg_binding_group_check_source (self, source))
{
gsize i;
self->source = source;
g_object_weak_ref (self->source,
egg_binding_group__source_weak_notify,
self);
for (i = 0; i < self->lazy_bindings->len; i++)
{
LazyBinding *lazy_binding;
lazy_binding = g_ptr_array_index (self->lazy_bindings, i);
egg_binding_group_connect (self, lazy_binding);
}
}
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SOURCE]);
}
static void
egg_binding_group_bind_helper (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags,
gpointer transform_to,
gpointer transform_from,
gpointer user_data,
GDestroyNotify user_data_destroy,
gboolean using_closures)
{
LazyBinding *lazy_binding;
g_return_if_fail (EGG_IS_BINDING_GROUP (self));
g_return_if_fail (source_property != NULL);
g_return_if_fail (self->source == NULL ||
g_object_class_find_property (G_OBJECT_GET_CLASS (self->source),
source_property) != NULL);
g_return_if_fail (G_IS_OBJECT (target));
g_return_if_fail (target_property != NULL);
g_return_if_fail (g_object_class_find_property (G_OBJECT_GET_CLASS (target),
target_property) != NULL);
g_return_if_fail (target != (gpointer)self ||
strcmp (source_property, target_property) != 0);
lazy_binding = g_slice_new0 (LazyBinding);
lazy_binding->group = self;
lazy_binding->source_property = g_intern_string (source_property);
lazy_binding->target_property = g_intern_string (target_property);
lazy_binding->target = target;
lazy_binding->binding_flags = flags | G_BINDING_SYNC_CREATE;
lazy_binding->user_data = user_data;
lazy_binding->user_data_destroy = user_data_destroy;
lazy_binding->transform_to = transform_to;
lazy_binding->transform_from = transform_from;
if (using_closures)
{
lazy_binding->using_closures = TRUE;
if (transform_to != NULL)
g_closure_sink (g_closure_ref (transform_to));
if (transform_from != NULL)
g_closure_sink (g_closure_ref (transform_from));
}
g_object_weak_ref (target,
egg_binding_group__target_weak_notify,
self);
g_ptr_array_add (self->lazy_bindings, lazy_binding);
if (self->source != NULL)
egg_binding_group_connect (self, lazy_binding);
}
/**
* egg_binding_group_bind:
* @self: the #EggBindingGroup
* @source_property: the property on the source to bind
* @target: (type GObject): the target #GObject
* @target_property: the property on @target to bind
* @flags: the flags used to create the #GBinding
*
* Creates a binding between @source_property on the source object
* and @target_property on @target. Whenever the @source_property
* is changed the @target_property is updated using the same value.
* The binding flags #G_BINDING_SYNC_CREATE is automatically specified.
*
* See: g_object_bind_property().
*/
void
egg_binding_group_bind (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags)
{
egg_binding_group_bind_full (self, source_property,
target, target_property,
flags,
NULL, NULL,
NULL, NULL);
}
/**
* egg_binding_group_bind_full:
* @self: the #EggBindingGroup
* @source_property: the property on the source to bind
* @target: (type GObject): the target #GObject
* @target_property: the property on @target to bind
* @flags: the flags used to create the #GBinding
* @transform_to: (scope notified) (nullable): the transformation function
* from the source object to the @target, or %NULL to use the default
* @transform_from: (scope notified) (nullable): the transformation function
* from the @target to the source object, or %NULL to use the default
* @user_data: custom data to be passed to the transformation
* functions, or %NULL
* @user_data_destroy: function to be called when disposing the binding,
* to free the resources used by the transformation functions
*
* Creates a binding between @source_property on the source object and
* @target_property on @target, allowing you to set the transformation
* functions to be used by the binding. The binding flags
* #G_BINDING_SYNC_CREATE is automatically specified.
*
* See: g_object_bind_property_full().
*/
void
egg_binding_group_bind_full (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags,
GBindingTransformFunc transform_to,
GBindingTransformFunc transform_from,
gpointer user_data,
GDestroyNotify user_data_destroy)
{
egg_binding_group_bind_helper (self, source_property,
target, target_property,
flags,
transform_to, transform_from,
user_data, user_data_destroy,
FALSE);
}
/**
* egg_binding_group_bind_with_closures: (rename-to egg_binding_group_bind_full)
* @self: the #EggBindingGroup
* @source_property: the property on the source to bind
* @target: (type GObject): the target #GObject
* @target_property: the property on @target to bind
* @flags: the flags used to create the #GBinding
* @transform_to: (nullable): a #GClosure wrapping the
* transformation function from the source object to the @target,
* or %NULL to use the default
* @transform_from: (nullable): a #GClosure wrapping the
* transformation function from the @target to the source object,
* or %NULL to use the default
*
* Creates a binding between @source_property on the source object and
* @target_property on @target, allowing you to set the transformation
* functions to be used by the binding. The binding flags
* #G_BINDING_SYNC_CREATE is automatically specified.
*
* This function is the language bindings friendly version of
* egg_binding_group_bind_property_full(), using #GClosures
* instead of function pointers.
*
* See: g_object_bind_property_with_closures().
*/
void
egg_binding_group_bind_with_closures (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags,
GClosure *transform_to,
GClosure *transform_from)
{
egg_binding_group_bind_helper (self, source_property,
target, target_property,
flags,
transform_to, transform_from,
NULL, NULL,
TRUE);
}

View File

@ -0,0 +1,57 @@
/* egg-binding-group.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
* Copyright (C) 2015 Garrett Regier <garrettregier@gmail.com>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This file 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
* Lesser 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/>.
*/
#pragma once
#include <gio/gio.h>
G_BEGIN_DECLS
#define EGG_TYPE_BINDING_GROUP (egg_binding_group_get_type())
G_DECLARE_FINAL_TYPE (EggBindingGroup, egg_binding_group, EGG, BINDING_GROUP, GObject)
EggBindingGroup *egg_binding_group_new (void);
GObject *egg_binding_group_get_source (EggBindingGroup *self);
void egg_binding_group_set_source (EggBindingGroup *self,
gpointer source);
void egg_binding_group_bind (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags);
void egg_binding_group_bind_full (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags,
GBindingTransformFunc transform_to,
GBindingTransformFunc transform_from,
gpointer user_data,
GDestroyNotify user_data_destroy);
void egg_binding_group_bind_with_closures (EggBindingGroup *self,
const gchar *source_property,
gpointer target,
const gchar *target_property,
GBindingFlags flags,
GClosure *transform_to,
GClosure *transform_from);
G_END_DECLS

View File

@ -1,10 +1,10 @@
if get_option('enable_gtk') and get_option('libsysprof') if get_option('enable_gtk') and get_option('libsysprof')
sysprof_sources = [ sysprof_sources = [
'egg-binding-group.c',
'sysprof.c', 'sysprof.c',
'sysprof-application.c', 'sysprof-application.c',
'sysprof-window.c', 'sysprof-window.c',
'sysprof-window-settings.c',
] ]
sysprof_resources = gnome.compile_resources('sysprof-resources', 'sysprof.gresource.xml', sysprof_resources = gnome.compile_resources('sysprof-resources', 'sysprof.gresource.xml',
@ -18,6 +18,7 @@ sysprof_deps = [
libsysprof_dep, libsysprof_dep,
libsysprof_ui_dep, libsysprof_ui_dep,
dependency('pangoft2', required: false), dependency('pangoft2', required: false),
dependency('libadwaita-1'),
] ]
sysprof = executable('sysprof', sysprof_resources + sysprof_sources, sysprof = executable('sysprof', sysprof_resources + sysprof_sources,

View File

@ -27,10 +27,10 @@
struct _SysprofApplication struct _SysprofApplication
{ {
DzlApplication parent_instance; AdwApplication parent_instance;
}; };
G_DEFINE_TYPE (SysprofApplication, sysprof_application, DZL_TYPE_APPLICATION) G_DEFINE_TYPE (SysprofApplication, sysprof_application, ADW_TYPE_APPLICATION)
struct { struct {
const gchar *action_name; const gchar *action_name;
@ -110,9 +110,6 @@ static void
sysprof_application_startup (GApplication *application) sysprof_application_startup (GApplication *application)
{ {
g_autoptr(GtkCssProvider) provider = NULL; g_autoptr(GtkCssProvider) provider = NULL;
#ifdef DEVELOPMENT_BUILD
g_autoptr(GtkCssProvider) adwaita = NULL;
#endif
g_assert (SYSPROF_IS_APPLICATION (application)); g_assert (SYSPROF_IS_APPLICATION (application));
@ -120,17 +117,9 @@ sysprof_application_startup (GApplication *application)
provider = gtk_css_provider_new (); provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gnome/sysprof/theme/shared.css"); 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_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); GTK_STYLE_PROVIDER_PRIORITY_THEME+1);
#ifdef DEVELOPMENT_BUILD
adwaita = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (adwaita, "/org/gnome/sysprof/theme/Adwaita-shared.css");
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (adwaita),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
#endif
for (guint i = 0; default_accels[i].action_name; i++) for (guint i = 0; default_accels[i].action_name; i++)
gtk_application_set_accels_for_action (GTK_APPLICATION (application), gtk_application_set_accels_for_action (GTK_APPLICATION (application),
@ -138,14 +127,31 @@ sysprof_application_startup (GApplication *application)
default_accels[i].accels); default_accels[i].accels);
} }
static void
sysprof_application_window_added (GtkApplication *application,
GtkWindow *window)
{
g_assert (SYSPROF_IS_APPLICATION (application));
g_assert (GTK_IS_WINDOW (window));
#ifdef DEVELOPMENT_BUILD
gtk_widget_add_css_class (GTK_WIDGET (window), "devel");
#endif
GTK_APPLICATION_CLASS (sysprof_application_parent_class)->window_added (application, window);
}
static void static void
sysprof_application_class_init (SysprofApplicationClass *klass) sysprof_application_class_init (SysprofApplicationClass *klass)
{ {
GApplicationClass *app_class = G_APPLICATION_CLASS (klass); GApplicationClass *app_class = G_APPLICATION_CLASS (klass);
GtkApplicationClass *gtk_app_class = GTK_APPLICATION_CLASS (klass);
app_class->open = sysprof_application_open; app_class->open = sysprof_application_open;
app_class->startup = sysprof_application_startup; app_class->startup = sysprof_application_startup;
app_class->activate = sysprof_application_activate; app_class->activate = sysprof_application_activate;
gtk_app_class->window_added = sysprof_application_window_added;
} }
static void static void
@ -206,8 +212,8 @@ sysprof_about (GSimpleAction *action,
NULL); NULL);
g_signal_connect (dialog, g_signal_connect (dialog,
"response", "close-request",
G_CALLBACK (gtk_widget_destroy), G_CALLBACK (gtk_window_destroy),
NULL); NULL);
gtk_window_present (dialog); gtk_window_present (dialog);
@ -226,10 +232,7 @@ sysprof_help (GSimpleAction *action,
window = gtk_application_get_active_window (GTK_APPLICATION (self)); window = gtk_application_get_active_window (GTK_APPLICATION (self));
gtk_show_uri_on_window (window, gtk_show_uri (window, "help:sysprof", GDK_CURRENT_TIME);
"help:sysprof",
gtk_get_current_event_time (),
NULL);
} }
static void static void

View File

@ -18,13 +18,13 @@
#pragma once #pragma once
#include <dazzle.h> #include <adwaita.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define SYSPROF_TYPE_APPLICATION (sysprof_application_get_type()) #define SYSPROF_TYPE_APPLICATION (sysprof_application_get_type())
G_DECLARE_FINAL_TYPE (SysprofApplication, sysprof_application, SYSPROF, APPLICATION, DzlApplication) G_DECLARE_FINAL_TYPE (SysprofApplication, sysprof_application, SYSPROF, APPLICATION, AdwApplication)
SysprofApplication *sysprof_application_new (void); SysprofApplication *sysprof_application_new (void);

View File

@ -1,175 +0,0 @@
/* sysprof-window-settings.c
*
* Copyright 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 "sysprof-window.h"
#include "sysprof-window-settings.h"
#define WINDOW_MIN_WIDTH 1200
#define WINDOW_MIN_HEIGHT 700
#define SAVE_TIMEOUT_SECS 1
static GSettings *settings;
static gboolean
sysprof_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
sysprof_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,
sysprof_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
sysprof_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 (SYSPROF_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
sysprof_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 (sysprof_window_settings__window_configure_event),
NULL);
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (sysprof_window_settings__window_destroy),
NULL);
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (sysprof_window_settings__window_realize),
NULL);
g_object_unref (settings);
}
void
sysprof_window_settings_register (GtkWindow *window)
{
if (settings == NULL)
{
settings = g_settings_new ("org.gnome.sysprof3");
g_object_add_weak_pointer (G_OBJECT (settings), (gpointer *)&settings);
}
else
{
g_object_ref (settings);
}
g_signal_connect (window,
"configure-event",
G_CALLBACK (sysprof_window_settings__window_configure_event),
NULL);
g_signal_connect (window,
"destroy",
G_CALLBACK (sysprof_window_settings__window_destroy),
NULL);
g_signal_connect (window,
"realize",
G_CALLBACK (sysprof_window_settings__window_realize),
NULL);
}

View File

@ -25,20 +25,22 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <sysprof-ui.h> #include <sysprof-ui.h>
#include "egg-binding-group.h"
#include "sysprof-window.h" #include "sysprof-window.h"
struct _SysprofWindow struct _SysprofWindow
{ {
DzlApplicationWindow parent_instance; AdwApplicationWindow parent_instance;
DzlBindingGroup *bindings; EggBindingGroup *bindings;
SysprofNotebook *notebook; SysprofNotebook *notebook;
GtkButton *open_button; GtkButton *open_button;
GtkMenuButton *menu_button; GtkMenuButton *menu_button;
}; };
G_DEFINE_TYPE (SysprofWindow, sysprof_window, DZL_TYPE_APPLICATION_WINDOW) G_DEFINE_TYPE (SysprofWindow, sysprof_window, ADW_TYPE_APPLICATION_WINDOW)
/** /**
* sysprof_window_new: * sysprof_window_new:
@ -63,9 +65,11 @@ sysprof_window_notify_can_replay_cb (SysprofWindow *self,
g_assert (SYSPROF_IS_WINDOW (self)); g_assert (SYSPROF_IS_WINDOW (self));
g_assert (SYSPROF_IS_NOTEBOOK (notebook)); g_assert (SYSPROF_IS_NOTEBOOK (notebook));
#if 0
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "replay-capture", dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "replay-capture",
"enabled", sysprof_notebook_get_can_replay (notebook), "enabled", sysprof_notebook_get_can_replay (notebook),
NULL); NULL);
#endif
} }
static void static void
@ -76,9 +80,11 @@ sysprof_window_notify_can_save_cb (SysprofWindow *self,
g_assert (SYSPROF_IS_WINDOW (self)); g_assert (SYSPROF_IS_WINDOW (self));
g_assert (SYSPROF_IS_NOTEBOOK (notebook)); g_assert (SYSPROF_IS_NOTEBOOK (notebook));
#if 0
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "save-capture", dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "save-capture",
"enabled", sysprof_notebook_get_can_save (notebook), "enabled", sysprof_notebook_get_can_save (notebook),
NULL); NULL);
#endif
} }
static void static void
@ -105,7 +111,7 @@ switch_tab_cb (GSimpleAction *action,
g_return_if_fail (g_variant_is_of_type (param, G_VARIANT_TYPE_INT32)); g_return_if_fail (g_variant_is_of_type (param, G_VARIANT_TYPE_INT32));
page = g_variant_get_int32 (param); page = g_variant_get_int32 (param);
gtk_notebook_set_current_page (GTK_NOTEBOOK (self->notebook), page - 1); sysprof_notebook_set_current_page (self->notebook, page - 1);
} }
static void static void
@ -114,20 +120,17 @@ close_tab_cb (GSimpleAction *action,
gpointer user_data) gpointer user_data)
{ {
SysprofWindow *self = user_data; SysprofWindow *self = user_data;
GtkNotebook *notebook;
g_return_if_fail (SYSPROF_IS_WINDOW (self)); g_return_if_fail (SYSPROF_IS_WINDOW (self));
notebook = GTK_NOTEBOOK (self->notebook); if (sysprof_notebook_get_n_pages (self->notebook) == 1)
if (gtk_notebook_get_n_pages (notebook) == 1)
{ {
GtkWidget *child = gtk_notebook_get_nth_page (notebook, 0); SysprofDisplay *child = sysprof_notebook_get_nth_page (self->notebook, 0);
if (SYSPROF_IS_DISPLAY (child) && if (SYSPROF_IS_DISPLAY (child) &&
sysprof_display_is_empty (SYSPROF_DISPLAY (child))) sysprof_display_is_empty (SYSPROF_DISPLAY (child)))
{ {
gtk_widget_destroy (GTK_WIDGET (self)); gtk_window_destroy (GTK_WINDOW (self));
return; return;
} }
} }
@ -175,7 +178,7 @@ sysprof_window_finalize (GObject *object)
{ {
SysprofWindow *self = (SysprofWindow *)object; SysprofWindow *self = (SysprofWindow *)object;
dzl_binding_group_set_source (self->bindings, NULL); egg_binding_group_set_source (self->bindings, NULL);
g_clear_object (&self->bindings); g_clear_object (&self->bindings);
G_OBJECT_CLASS (sysprof_window_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_window_parent_class)->finalize (object);
@ -194,6 +197,17 @@ sysprof_window_class_init (SysprofWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, open_button); gtk_widget_class_bind_template_child (widget_class, SysprofWindow, open_button);
gtk_widget_class_bind_template_child (widget_class, SysprofWindow, notebook); gtk_widget_class_bind_template_child (widget_class, SysprofWindow, notebook);
#if 0
/* Switch to GtkShortcutController class bindings */
DzlShortcutController *controller;
controller = dzl_shortcut_controller_find (GTK_WIDGET (self));
dzl_shortcut_controller_add_command_action (controller,
"org.gnome.sysprof3.stop-recording",
"Escape",
DZL_SHORTCUT_PHASE_BUBBLE,
"win.stop-recording");
#endif
g_type_ensure (SYSPROF_TYPE_NOTEBOOK); g_type_ensure (SYSPROF_TYPE_NOTEBOOK);
g_type_ensure (SYSPROF_TYPE_DISPLAY); g_type_ensure (SYSPROF_TYPE_DISPLAY);
} }
@ -201,7 +215,6 @@ sysprof_window_class_init (SysprofWindowClass *klass)
static void static void
sysprof_window_init (SysprofWindow *self) sysprof_window_init (SysprofWindow *self)
{ {
DzlShortcutController *controller;
static GActionEntry actions[] = { static GActionEntry actions[] = {
{ "close-tab", close_tab_cb }, { "close-tab", close_tab_cb },
{ "new-tab", new_tab_cb }, { "new-tab", new_tab_cb },
@ -210,9 +223,13 @@ sysprof_window_init (SysprofWindow *self)
{ "save-capture", save_capture_cb }, { "save-capture", save_capture_cb },
{ "stop-recording", stop_recording_cb }, { "stop-recording", stop_recording_cb },
}; };
GMenu *menu;
gtk_widget_init_template (GTK_WIDGET (self)); 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_action_map_add_action_entries (G_ACTION_MAP (self), g_action_map_add_action_entries (G_ACTION_MAP (self),
actions, actions,
G_N_ELEMENTS (actions), G_N_ELEMENTS (actions),
@ -230,24 +247,20 @@ sysprof_window_init (SysprofWindow *self)
self, self,
G_CONNECT_SWAPPED); G_CONNECT_SWAPPED);
self->bindings = dzl_binding_group_new (); self->bindings = egg_binding_group_new ();
dzl_binding_group_bind (self->bindings, "title", self, "title", G_BINDING_SYNC_CREATE); egg_binding_group_bind (self->bindings, "title", self, "title", G_BINDING_SYNC_CREATE);
g_object_bind_property (self->notebook, "current", self->bindings, "source", g_object_bind_property (self->notebook, "current", self->bindings, "source",
G_BINDING_SYNC_CREATE); G_BINDING_SYNC_CREATE);
controller = dzl_shortcut_controller_find (GTK_WIDGET (self)); #if 0
dzl_shortcut_controller_add_command_action (controller, /* Switch to using gtk_widget_action_set_enabled() */
"org.gnome.sysprof3.stop-recording",
"Escape",
DZL_SHORTCUT_PHASE_BUBBLE,
"win.stop-recording");
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "save-capture", dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "save-capture",
"enabled", FALSE, "enabled", FALSE,
NULL); NULL);
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "replay-capture", dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "replay-capture",
"enabled", FALSE, "enabled", FALSE,
NULL); NULL);
#endif
} }
void void
@ -260,12 +273,30 @@ sysprof_window_open (SysprofWindow *self,
sysprof_notebook_open (self->notebook, file); sysprof_notebook_open (self->notebook, file);
} }
static void
sysprof_window_open_from_dialog_cb (SysprofWindow *self,
int response,
GtkFileChooserNative *dialog)
{
g_assert (SYSPROF_IS_WINDOW (self));
g_assert (GTK_IS_FILE_CHOOSER_NATIVE (dialog));
if (response == GTK_RESPONSE_ACCEPT)
{
g_autoptr(GFile) file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
if (g_file_is_native (file))
sysprof_window_open (self, file);
}
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (dialog));
}
void void
sysprof_window_open_from_dialog (SysprofWindow *self) sysprof_window_open_from_dialog (SysprofWindow *self)
{ {
GtkFileChooserNative *dialog; GtkFileChooserNative *dialog;
GtkFileFilter *filter; GtkFileFilter *filter;
gint response;
g_return_if_fail (SYSPROF_IS_WINDOW (self)); g_return_if_fail (SYSPROF_IS_WINDOW (self));
@ -278,8 +309,6 @@ sysprof_window_open_from_dialog (SysprofWindow *self)
/* Translators: This is a button. */ /* Translators: This is a button. */
_("Cancel")); _("Cancel"));
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
filter = gtk_file_filter_new (); filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Sysprof Captures")); gtk_file_filter_set_name (filter, _("Sysprof Captures"));
gtk_file_filter_add_pattern (filter, "*.syscap"); gtk_file_filter_add_pattern (filter, "*.syscap");
@ -290,17 +319,13 @@ sysprof_window_open_from_dialog (SysprofWindow *self)
gtk_file_filter_add_pattern (filter, "*"); gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
response = gtk_native_dialog_run (GTK_NATIVE_DIALOG (dialog)); g_signal_connect_object (dialog,
"response",
G_CALLBACK (sysprof_window_open_from_dialog_cb),
self,
G_CONNECT_SWAPPED);
if (response == GTK_RESPONSE_ACCEPT) gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
{
g_autoptr(GFile) file = NULL;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
sysprof_window_open (self, file);
}
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (dialog));
} }
void void
@ -312,8 +337,6 @@ sysprof_window_new_tab (SysprofWindow *self)
g_return_if_fail (SYSPROF_IS_WINDOW (self)); g_return_if_fail (SYSPROF_IS_WINDOW (self));
display = sysprof_display_new (); display = sysprof_display_new ();
page = gtk_notebook_insert_page (GTK_NOTEBOOK (self->notebook), display, NULL, -1); page = sysprof_notebook_append (self->notebook, SYSPROF_DISPLAY (display));
gtk_widget_show (display); sysprof_notebook_set_current_page (self->notebook, page);
gtk_notebook_set_current_page (GTK_NOTEBOOK (self->notebook), page);
} }

View File

@ -20,7 +20,7 @@
#pragma once #pragma once
#include <dazzle.h> #include <adwaita.h>
#include "sysprof-application.h" #include "sysprof-application.h"
@ -28,7 +28,7 @@ G_BEGIN_DECLS
#define SYSPROF_TYPE_WINDOW (sysprof_window_get_type()) #define SYSPROF_TYPE_WINDOW (sysprof_window_get_type())
G_DECLARE_FINAL_TYPE (SysprofWindow, sysprof_window, SYSPROF, WINDOW, DzlApplicationWindow) G_DECLARE_FINAL_TYPE (SysprofWindow, sysprof_window, SYSPROF, WINDOW, AdwApplicationWindow)
GtkWidget *sysprof_window_new (SysprofApplication *application); GtkWidget *sysprof_window_new (SysprofApplication *application);
void sysprof_window_new_tab (SysprofWindow *self); void sysprof_window_new_tab (SysprofWindow *self);

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<interface>
<template class="SysprofWindow" parent="AdwApplicationWindow">
<style>
<class name="org-gnome-Sysprof"/>
</style>
<property name="default-height">750</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>
<property name="visible">true</property>
<child type="end">
<object class="GtkMenuButton" id="menu_button">
<property name="visible">true</property>
<child>
<object class="GtkImage">
<property name="icon-name">open-menu-symbolic</property>
<property name="visible">true</property>
</object>
</child>
<style>
<class name="image-button"/>
</style>
</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>
<property name="visible">true</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>
</object>
</child>
<child>
<object class="SysprofNotebook" id="notebook">
<property name="vexpand">true</property>
<child>
<object class="SysprofDisplay">
<property name="visible">true</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@ -7,9 +7,9 @@
<!-- Theme overrides --> <!-- Theme overrides -->
<file compressed="true">theme/shared.css</file> <file compressed="true">theme/shared.css</file>
<file compressed="true">theme/Adwaita-shared.css</file> </gresource>
<!-- UI Files --> <gresource prefix="/org/gnome/sysprof/ui">
<file preprocess="xml-stripblanks">ui/sysprof-window.ui</file> <file preprocess="xml-stripblanks">sysprof-window.ui</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@ -1,18 +0,0 @@
/* development styles */
window.development-version headerbar {
background: transparent -gtk-icontheme("system-run-symbolic") 80% 0/128px 128px no-repeat,
linear-gradient(to left,
mix(@theme_fg_color, @theme_bg_color, 0.5) 0%,
@theme_bg_color 25%);
color: alpha(@theme_fg_color, 0.2);
}
window.development-version headerbar box label {
color: @theme_fg_color;
}
button.sysprofprofilermenubutton.popup.suggested-action:checked {
background: shade(@theme_selected_bg_color,0.9);
border: 1px solid shade(@theme_selected_bg_color, 0.8);
color: alpha(@theme_selected_fg_color,0.9);
}

View File

@ -1,16 +1,3 @@
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);
}
visualizers list { visualizers list {
background: @theme_bg_color; background: @theme_bg_color;
} }

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<interface>
<template class="SysprofWindow" parent="DzlApplicationWindow">
<property name="default-height">750</property>
<property name="icon-name">org.gnome.Sysprof-symbolic</property>
<property name="show-menubar">false</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="show-close-button">true</property>
<property name="visible">true</property>
<property name="title" translatable="yes">Sysprof</property>
<child>
<object class="DzlMenuButton" id="menu_button">
<property name="icon-name">open-menu-symbolic</property>
<property name="show-accels">true</property>
<property name="menu-id">win-menu</property>
<property name="visible">true</property>
<style>
<class name="image-button"/>
</style>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
<child>
<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>
<property name="visible">true</property>
</object>
<packing>
<property name="pack-type">start</property>
</packing>
</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>
</object>
</child>
<child>
<object class="SysprofNotebook" id="notebook">
<property name="visible">true</property>
<child>
<object class="SysprofDisplay">
<property name="visible">true</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@ -122,8 +122,7 @@ if get_option('enable_gtk')
test_ui_deps = [ test_ui_deps = [
libsysprof_dep, libsysprof_dep,
libsysprof_ui_dep, libsysprof_ui_dep,
dependency('gtk+-3.0', version: gtk_req_version), dependency('gtk4', version: gtk_req_version),
dependency('libdazzle-1.0', version: dazzle_req_version, fallback: ['libdazzle', 'libdazzle_dep']),
dependency('pangoft2', required: false), dependency('pangoft2', required: false),
] ]

View File

@ -28,8 +28,9 @@ main (gint argc,
SysprofDisplay *view; SysprofDisplay *view;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
GMainLoop *main_loop;
gtk_init (&argc, &argv); gtk_init ();
if (argc != 2) if (argc != 2)
{ {
@ -43,6 +44,8 @@ main (gint argc,
return 1; return 1;
} }
main_loop = g_main_loop_new (NULL, FALSE);
window = g_object_new (GTK_TYPE_WINDOW, window = g_object_new (GTK_TYPE_WINDOW,
"title", "SysprofDisplay", "title", "SysprofDisplay",
"default-width", 800, "default-width", 800,
@ -51,13 +54,13 @@ main (gint argc,
view = g_object_new (SYSPROF_TYPE_DISPLAY, view = g_object_new (SYSPROF_TYPE_DISPLAY,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (view)); gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (view));
sysprof_display_load_async (view, reader, NULL, NULL, NULL); sysprof_display_load_async (view, reader, NULL, NULL, NULL);
g_signal_connect (window, "delete-event", gtk_main_quit, NULL); g_signal_connect_swapped (window, "close-request", G_CALLBACK (g_main_loop_quit), main_loop);
gtk_window_present (GTK_WINDOW (window)); gtk_window_present (GTK_WINDOW (window));
gtk_main (); g_main_loop_run (main_loop);
return 0; return 0;
} }

View File

@ -18,11 +18,11 @@ filter_cb (GObject *object,
const gchar *needle = user_data; const gchar *needle = user_data;
const gchar *command = sysprof_process_model_item_get_command_line (SYSPROF_PROCESS_MODEL_ITEM (object)); const gchar *command = sysprof_process_model_item_get_command_line (SYSPROF_PROCESS_MODEL_ITEM (object));
return !!strstr (command, needle); return needle == NULL || needle[0] == 0 || strstr (command, needle) != NULL;
} }
static void static void
on_entry_changed (GtkEntry *entry, on_entry_changed (GtkEntry *entry,
SysprofModelFilter *filter) SysprofModelFilter *filter)
{ {
const gchar *text; const gchar *text;
@ -30,10 +30,10 @@ on_entry_changed (GtkEntry *entry,
g_assert (GTK_IS_ENTRY (entry)); g_assert (GTK_IS_ENTRY (entry));
g_assert (SYSPROF_IS_MODEL_FILTER (filter)); g_assert (SYSPROF_IS_MODEL_FILTER (filter));
text = gtk_entry_get_text (entry); text = gtk_editable_get_text (GTK_EDITABLE (entry));
sysprof_model_filter_set_filter_func (filter, filter_cb, g_strdup (text), g_free); sysprof_model_filter_set_filter_func (filter, filter_cb, g_strdup (text), g_free);
//gtk_list_box_bind_model (GTK_LIST_BOX (list), G_LIST_MODEL (filter), create_row, NULL, NULL); gtk_list_box_bind_model (GTK_LIST_BOX (list), G_LIST_MODEL (filter), create_row, NULL, NULL);
} }
gint gint
@ -46,8 +46,11 @@ main (gint argc,
GtkWidget *box; GtkWidget *box;
GtkWidget *scroller; GtkWidget *scroller;
GtkWidget *entry; GtkWidget *entry;
GMainLoop *main_loop;
gtk_init (&argc, &argv); gtk_init ();
main_loop = g_main_loop_new (NULL, FALSE);
window = g_object_new (GTK_TYPE_WINDOW, window = g_object_new (GTK_TYPE_WINDOW,
"title", "Sysprof Process List", "title", "Sysprof Process List",
@ -59,23 +62,24 @@ main (gint argc,
"orientation", GTK_ORIENTATION_VERTICAL, "orientation", GTK_ORIENTATION_VERTICAL,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (window), box); gtk_window_set_child (GTK_WINDOW (window), box);
entry = g_object_new (GTK_TYPE_ENTRY, entry = g_object_new (GTK_TYPE_ENTRY,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (box), entry); gtk_box_append (GTK_BOX (box), entry);
scroller = g_object_new (GTK_TYPE_SCROLLED_WINDOW, scroller = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
"visible", TRUE, "visible", TRUE,
"expand", TRUE, "vexpand", TRUE,
"hexpand", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (box), scroller); gtk_box_append (GTK_BOX (box), scroller);
list = g_object_new (GTK_TYPE_LIST_BOX, list = g_object_new (GTK_TYPE_LIST_BOX,
"visible", TRUE, "visible", TRUE,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (scroller), list); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroller), list);
model = sysprof_process_model_new (); model = sysprof_process_model_new ();
sysprof_process_model_set_no_proxy (model, TRUE); sysprof_process_model_set_no_proxy (model, TRUE);
@ -87,9 +91,9 @@ main (gint argc,
G_CALLBACK (on_entry_changed), G_CALLBACK (on_entry_changed),
filter); filter);
g_signal_connect_swapped (window, "close-request", G_CALLBACK (g_main_loop_quit), main_loop);
gtk_window_present (GTK_WINDOW (window)); gtk_window_present (GTK_WINDOW (window));
g_signal_connect (window, "delete-event", gtk_main_quit, NULL); g_main_loop_run (main_loop);
gtk_main ();
g_object_unref (model); g_object_unref (model);

View File

@ -1,5 +0,0 @@
[wrap-file]
directory=libdazzle-3.35.3
source_url=https://download.gnome.org/sources/libdazzle/3.35/libdazzle-3.35.3.tar.xz
source_filename=libdazzle-3.35.3.tar.xz
source_hash=df67f7a68096e4b33a70ee0bad14cd8a6778425deb087879b5cd8fef8f671304