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",
"config-opts" : [

View File

@ -1,20 +1,5 @@
<schemalist>
<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">
<default>''</default>
<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')
pkgconfig = import('pkgconfig')
i18n = import('i18n')
libsysprof_api_version = 4
libsysprof_ui_api_version = 5
version_split = meson.project_version().split('.')
datadir = get_option('datadir')
datadir_for_pc_file = join_paths('${prefix}', datadir)
podir = join_paths(meson.current_source_dir(), 'po')
glib_req_version = '>= 2.67.4'
gtk_req_version = '>= 3.22'
glib_req_version = '>= 2.68.0'
gtk_req_version = '>= 4.4'
polkit_req_version = '>= 0.105'
dazzle_req_version = '>= 3.30.0'
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('VERSION', 'PACKAGE_VERSION')
# Detect and set symbol visibility
if get_option('default_library') != 'static'
if host_machine.system() == 'windows'

View File

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

View File

@ -13,6 +13,11 @@ libsysprof_ui_public_sources = [
]
libsysprof_ui_private_sources = [
'egg-handle.c',
'egg-paned.c',
'egg-resizer.c',
'egg-three-grid.c',
'pointcache.c',
'rectangles.c',
'sysprof-aid.c',
@ -23,6 +28,7 @@ libsysprof_ui_private_sources = [
'sysprof-callgraph-page.c',
'sysprof-cell-renderer-duration.c',
'sysprof-cell-renderer-percent.c',
'sysprof-cell-renderer-progress.c',
'sysprof-color-cycle.c',
'sysprof-counters-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
libsysprof_ui_pkg_deps = [
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 + [
@ -98,15 +105,8 @@ libsysprof_ui_deps = libsysprof_ui_pkg_deps + [
# dependency object
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(
'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,
dependencies: libsysprof_ui_deps + [librax_dep],
@ -124,16 +124,16 @@ libsysprof_ui_dep = declare_dependency(
pkgconfig.generate(
libsysprof_ui,
subdirs: [ sysprof_header_subdir ],
subdirs: [ sysprof_ui_header_subdir ],
description: 'The UI library for GTK applications embedding sysprof',
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,
variables: [
'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

View File

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

View File

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

View File

@ -39,11 +39,12 @@
#include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h>
#include "../stackstash.h"
#include "egg-paned-private.h"
#include "sysprof-callgraph-page.h"
#include "sysprof-cell-renderer-percent.h"
@ -56,6 +57,9 @@ typedef struct
GtkTreeView *descendants_view;
GtkTreeViewColumn *descendants_name_column;
GtkStack *stack;
GtkWidget *empty_state;
GtkWidget *loading_state;
GtkWidget *callgraph;
GQueue *history;
@ -208,7 +212,7 @@ sysprof_callgraph_page_load (SysprofCallgraphPage *self,
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);
}
@ -220,7 +224,7 @@ _sysprof_callgraph_page_set_failed (SysprofCallgraphPage *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
@ -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->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);
}
static void
static gboolean
descendants_view_move_cursor_cb (GtkTreeView *descendants_view,
GtkMovementStep step,
int direction,
gboolean extend,
gboolean modify,
gpointer user_data)
{
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);
g_signal_stop_emission_by_name (descendants_view, "move-cursor");
return FALSE;
}
else if (direction == -1)
{
gtk_tree_view_collapse_row (descendants_view, path);
g_signal_stop_emission_by_name (descendants_view, "move-cursor");
return FALSE;
}
gtk_tree_path_free (path);
}
return TRUE;
}
static void
@ -732,7 +742,7 @@ static void
copy_tree_view_selection (GtkTreeView *tree_view)
{
g_autoptr(GString) str = NULL;
GtkClipboard *clipboard;
GdkClipboard *clipboard;
g_assert (GTK_IS_TREE_VIEW (tree_view));
@ -741,24 +751,26 @@ copy_tree_view_selection (GtkTreeView *tree_view)
copy_tree_view_selection_cb,
str);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view), GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text (clipboard, str->str, str->len);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view));
gdk_clipboard_set_text (clipboard, str->str);
}
static void
sysprof_callgraph_page_copy_cb (GtkWidget *widget,
SysprofCallgraphPage *self)
sysprof_callgraph_page_copy_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofCallgraphPage *self = (SysprofCallgraphPage *)widget;
SysprofCallgraphPagePrivate *priv = sysprof_callgraph_page_get_instance_private (self);
GtkWidget *toplevel;
GtkRoot *toplevel;
GtkWidget *focus;
g_assert (GTK_IS_WIDGET (widget));
g_assert (SYSPROF_IS_CALLGRAPH_PAGE (self));
if (!(toplevel = gtk_widget_get_toplevel (widget)) ||
!GTK_IS_WINDOW (toplevel) ||
!(focus = gtk_window_get_focus (GTK_WINDOW (toplevel))))
if (!(toplevel = gtk_widget_get_root (widget)) ||
!GTK_IS_ROOT (toplevel) ||
!(focus = gtk_root_get_focus (toplevel)))
return;
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);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass);
GtkBindingSet *bindings;
object_class->finalize = sysprof_callgraph_page_finalize;
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_name_column);
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_binding_entry_add_signal (bindings, GDK_KEY_Left, GDK_MOD1_MASK, "go-previous", 0);
gtk_widget_class_install_action (widget_class, "page.copy", NULL, sysprof_callgraph_page_copy_cb);
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);
}
@ -937,7 +954,6 @@ static void
sysprof_callgraph_page_init (SysprofCallgraphPage *self)
{
SysprofCallgraphPagePrivate *priv = sysprof_callgraph_page_get_instance_private (self);
DzlShortcutController *controller;
GtkTreeSelection *selection;
GtkCellRenderer *cell;
@ -945,7 +961,7 @@ sysprof_callgraph_page_init (SysprofCallgraphPage *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);
@ -991,16 +1007,6 @@ sysprof_callgraph_page_init (SysprofCallgraphPage *self)
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->descendants_view),
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;
@ -1287,7 +1293,7 @@ _sysprof_callgraph_page_set_loading (SysprofCallgraphPage *self,
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
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">
<child>
<object class="GtkStack" id="stack">
<property name="visible">true</property>
<child>
<object class="GtkPaned">
<object class="EggPaned" id="callgraph">
<property name="orientation">horizontal</property>
<property name="position">450</property>
<property name="visible">true</property>
<child>
<object class="GtkPaned">
<object class="EggPaned">
<property name="orientation">vertical</property>
<property name="visible">true</property>
<property name="width-request">400</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<property name="vexpand">true</property>
<child>
<object class="GtkTreeView" id="functions_view">
<property name="fixed-height-mode">true</property>
<property name="visible">true</property>
<child>
<object class="GtkTreeViewColumn" id="function_name_column">
<property name="expand">true</property>
@ -70,16 +66,12 @@
</object>
</child>
</object>
<packing>
<property name="resize">true</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<property name="vexpand">true</property>
<child>
<object class="GtkTreeView" id="callers_view">
<property name="visible">true</property>
<child>
<object class="GtkTreeViewColumn" id="callers_name_column">
<property name="expand">true</property>
@ -131,18 +123,14 @@
</object>
</child>
</object>
<packing>
<property name="resize">true</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<property name="hexpand">true</property>
<child>
<object class="GtkTreeView" id="descendants_view">
<property name="visible">true</property>
<child>
<object class="GtkTreeViewColumn" id="descendants_name_column">
<property name="expand">true</property>
@ -203,31 +191,20 @@
</object>
</child>
</object>
<packing>
<property name="name">callgraph</property>
</packing>
</child>
<child>
<object class="DzlEmptyState">
<object class="AdwStatusPage" id="loading_state">
<property name="icon-name">content-loading-symbolic</property>
<property name="title" translatable="yes">Generating Callgraph</property>
<property name="subtitle" translatable="yes">Sysprof is busy creating the selected callgraph.</property>
<property name="visible">true</property>
<property name="description" translatable="yes">Sysprof is busy creating the selected callgraph.</property>
</object>
<packing>
<property name="name">loading</property>
</packing>
</child>
<child>
<object class="DzlEmptyState">
<object class="AdwStatusPage" id="empty_state">
<property name="icon-name">computer-fail-symbolic</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="visible">false</property>
<property name="description" translatable="yes">More samples are necessary to display a callgraph.</property>
</object>
<packing>
<property name="name">empty-state</property>
</packing>
</child>
</object>
</child>

View File

@ -55,38 +55,87 @@ G_DEFINE_TYPE_WITH_PRIVATE (SysprofCellRendererDuration, sysprof_cell_renderer_d
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
sysprof_cell_renderer_duration_render (GtkCellRenderer *renderer,
cairo_t *cr,
GtkWidget *widget,
const GdkRectangle *bg_area,
const GdkRectangle *cell_area,
GtkCellRendererState state)
sysprof_cell_renderer_duration_snapshot (GtkCellRenderer *renderer,
GtkSnapshot *snapshot,
GtkWidget *widget,
const GdkRectangle *bg_area,
const GdkRectangle *cell_area,
GtkCellRendererState state)
{
SysprofCellRendererDuration *self = (SysprofCellRendererDuration *)renderer;
SysprofCellRendererDurationPrivate *priv = sysprof_cell_renderer_duration_get_instance_private (self);
g_autoptr(GString) str = NULL;
GtkStyleContext *style_context;
cairo_t *cr;
gdouble x1, x2;
GdkRGBA rgba;
GdkRectangle r;
gint64 duration;
g_assert (SYSPROF_IS_CELL_RENDERER_DURATION (self));
g_assert (cr != NULL);
g_assert (snapshot != NULL);
g_assert (GTK_IS_WIDGET (widget));
if (priv->zoom_manager == NULL)
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);
if (priv->color_set)
rgba = priv->color;
else
gtk_style_context_get_color (style_context,
gtk_style_context_get_state (style_context),
&rgba);
gtk_style_context_get_color (style_context, &rgba);
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)
{
dzl_cairo_rounded_rectangle (cr, &r, 2, 2);
rounded_rectangle (cr, &r, 2, 2);
cairo_fill (cr);
}
else if (r.width > 1)
@ -166,6 +215,8 @@ sysprof_cell_renderer_duration_render (GtkCellRenderer *renderer,
g_object_unref (layout);
}
cairo_destroy (cr);
}
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_width = sysprof_cell_renderer_duration_get_preferred_width;
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 */

View File

@ -37,7 +37,7 @@ enum {
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];

View File

@ -20,7 +20,7 @@
#pragma once
#include <gtk/gtk.h>
#include "sysprof-cell-renderer-progress.h"
G_BEGIN_DECLS
@ -37,12 +37,12 @@ typedef struct _SysprofCellRendererPercentClass SysprofCellRendererPercentClass;
struct _SysprofCellRendererPercent
{
GtkCellRendererProgress parent;
SysprofCellRendererProgress parent;
};
struct _SysprofCellRendererPercentClass
{
GtkCellRendererProgressClass parent_class;
SysprofCellRendererProgressClass parent_class;
/*< private >*/
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-upper", 100.0,
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,
"title", _("CPU Usage (All)"),
@ -323,17 +323,17 @@ sysprof_cpu_aid_present_finish (SysprofAid *aid,
if (has_usage && !found_combined)
sysprof_visualizer_group_insert (usage, over_row, 0, FALSE);
else
gtk_widget_destroy (GTK_WIDGET (over_row));
g_object_unref (g_object_ref_sink (over_row));
if (has_usage)
sysprof_display_add_group (present->display, usage);
else
gtk_widget_destroy (GTK_WIDGET (usage));
g_object_unref (g_object_ref_sink (usage));
if (has_freq)
sysprof_display_add_group (present->display, freq);
else
gtk_widget_destroy (GTK_WIDGET (freq));
g_object_unref (g_object_ref_sink (freq));
}
return counters != NULL;

View File

@ -34,7 +34,8 @@ struct _SysprofDepthVisualizer
PointCache *points;
guint reload_source;
guint mode;
GtkAllocation last_alloc;
int last_width;
int last_height;
guint reloading : 1;
guint needs_reload : 1;
};
@ -238,34 +239,46 @@ sysprof_depth_visualizer_set_reader (SysprofVisualizer *row,
}
}
static gboolean
sysprof_depth_visualizer_draw (GtkWidget *widget,
cairo_t *cr)
static void
sysprof_depth_visualizer_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget;
GtkAllocation alloc;
GdkRectangle clip;
const Point *points;
gboolean ret;
cairo_t *cr;
guint n_points = 0;
GdkRGBA user;
GdkRGBA system;
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)
return ret;
return;
gdk_rgba_parse (&user, "#1a5fb4");
gdk_rgba_parse (&system, "#3584e4");
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))
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 */
if (self->mode != SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY &&
@ -355,7 +368,7 @@ sysprof_depth_visualizer_draw (GtkWidget *widget,
cairo_stroke (cr);
}
return ret;
cairo_destroy (cr);
}
static gboolean
@ -372,25 +385,23 @@ sysprof_depth_visualizer_queue_reload (SysprofDepthVisualizer *self)
{
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
if (self->reload_source)
g_source_remove (self->reload_source);
self->reload_source = gdk_threads_add_idle (sysprof_depth_visualizer_do_reload, self);
g_clear_handle_id (&self->reload_source, g_source_remove);
self->reload_source = g_idle_add (sysprof_depth_visualizer_do_reload, self);
}
static void
sysprof_depth_visualizer_size_allocate (GtkWidget *widget,
GtkAllocation *alloc)
sysprof_depth_visualizer_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget;
GTK_WIDGET_CLASS (sysprof_depth_visualizer_parent_class)->size_allocate (widget, alloc);
if (alloc->width != self->last_alloc.x ||
alloc->height != self->last_alloc.height)
if (width != self->last_width || height != self->last_height)
{
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;
g_clear_pointer (&self->reader, sysprof_capture_reader_unref);
if (self->reload_source)
{
g_source_remove (self->reload_source);
self->reload_source = 0;
}
g_clear_handle_id (&self->reload_source, g_source_remove);
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;
widget_class->draw = sysprof_depth_visualizer_draw;
widget_class->snapshot = sysprof_depth_visualizer_snapshot;
widget_class->size_allocate = sysprof_depth_visualizer_size_allocate;
row_class->set_reader = sysprof_depth_visualizer_set_reader;

View File

@ -22,19 +22,20 @@
#include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h>
#include <string.h>
#include "sysprof-details-page.h"
#include "sysprof-ui-private.h"
#include "egg-three-grid.h"
struct _SysprofDetailsPage
{
SysprofPage parent_instance;
GtkWidget parent_instance;
/* Template Objects */
DzlThreeGrid *three_grid;
EggThreeGrid *three_grid;
GtkListStore *marks_store;
GtkTreeView *marks_view;
GtkLabel *counters;
@ -51,7 +52,7 @@ struct _SysprofDetailsPage
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)
# 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
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
sysprof_details_page_class_init (SysprofDetailsPageClass *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_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, counters);
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, three_grid);
g_type_ensure (DZL_TYPE_THREE_GRID);
g_type_ensure (EGG_TYPE_THREE_GRID);
}
static void
@ -264,16 +281,10 @@ sysprof_details_page_add_item (SysprofDetailsPage *self,
g_return_if_fail (!center || GTK_IS_WIDGET (center));
if (left)
gtk_container_add_with_properties (GTK_CONTAINER (self->three_grid), left,
"row", self->next_row,
"column", DZL_THREE_GRID_COLUMN_LEFT,
NULL);
egg_three_grid_add (self->three_grid, left, self->next_row, EGG_THREE_GRID_COLUMN_LEFT);
if (center)
gtk_container_add_with_properties (GTK_CONTAINER (self->three_grid), center,
"row", self->next_row,
"column", DZL_THREE_GRID_COLUMN_CENTER,
NULL);
egg_three_grid_add (self->three_grid, center, self->next_row, EGG_THREE_GRID_COLUMN_CENTER);
self->next_row++;
}

View File

@ -39,7 +39,7 @@ SYSPROF_ALIGNED_END (8);
#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);
void sysprof_details_page_set_reader (SysprofDetailsPage *self,

View File

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

View File

@ -245,7 +245,7 @@ sysprof_diskstat_aid_present_finish (SysprofAid *aid,
if (counters->len > 0)
sysprof_display_add_group (present->display, group);
else
gtk_widget_destroy (GTK_WIDGET (group));
g_object_unref (g_object_ref_sink (group));
}
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
* 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
* 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
#define SYSPROF_WINDOW_SETTINGS_H
#pragma once
#include <gtk/gtk.h>
#include "sysprof-display.h"
G_BEGIN_DECLS
void sysprof_window_settings_register (GtkWindow *window);
void _sysprof_display_destroy (SysprofDisplay *self);
G_END_DECLS
#endif /* SYSPROF_WINDOW_SETTINGS_H */

View File

@ -22,11 +22,12 @@
#include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h>
#include "egg-paned-private.h"
#include "sysprof-details-page.h"
#include "sysprof-display.h"
#include "sysprof-display-private.h"
#include "sysprof-profiler-assistant.h"
#include "sysprof-failed-state-view.h"
#include "sysprof-recording-state-view.h"
@ -72,7 +73,7 @@ typedef struct
SysprofCaptureFlags flags;
} SysprofDisplayPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofDisplay, sysprof_display, GTK_TYPE_BIN)
G_DEFINE_TYPE_WITH_PRIVATE (SysprofDisplay, sysprof_display, GTK_TYPE_WIDGET)
enum {
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))
{
g_autofree gchar *title = sysprof_display_dup_title (self);
gtk_container_child_set (GTK_CONTAINER (parent), GTK_WIDGET (self),
"menu-label", title,
NULL);
gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (parent), GTK_WIDGET (self), 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 */
if (priv->reader != NULL)
{
GList *pages = gtk_container_get_children (GTK_CONTAINER (priv->pages));
for (const GList *iter = pages; iter; iter = iter->next)
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->pages));
child;
child = gtk_widget_get_next_sibling (child))
{
if (SYSPROF_IS_PAGE (iter->data))
sysprof_page_load_async (iter->data,
if (SYSPROF_IS_PAGE (child))
sysprof_page_load_async (SYSPROF_PAGE (child),
priv->reader,
selection,
priv->filter,
NULL, NULL, NULL);
}
g_list_free (pages);
}
}
}
@ -372,15 +368,21 @@ stop_recording_cb (GSimpleAction *action,
}
static void
sysprof_display_finalize (GObject *object)
sysprof_display_dispose (GObject *object)
{
SysprofDisplay *self = (SysprofDisplay *)object;
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->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
@ -443,7 +445,7 @@ sysprof_display_class_init (SysprofDisplayClass *klass)
GObjectClass *object_class = G_OBJECT_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->set_property = sysprof_display_set_property;
@ -453,6 +455,7 @@ sysprof_display_class_init (SysprofDisplayClass *klass)
"/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_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
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, details);
@ -499,7 +502,7 @@ sysprof_display_class_init (SysprofDisplayClass *klass)
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_FAILED_STATE_VIEW);
g_type_ensure (SYSPROF_TYPE_PROFILER_ASSISTANT);
@ -552,7 +555,7 @@ sysprof_display_add_group (SysprofDisplay *self,
if (priv->reader != NULL)
_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
@ -567,10 +570,7 @@ sysprof_display_add_page (SysprofDisplay *self,
g_return_if_fail (SYSPROF_IS_PAGE (page));
title = sysprof_page_get_title (page);
gtk_container_add_with_properties (GTK_CONTAINER (priv->pages), GTK_WIDGET (page),
"title", title,
NULL);
gtk_stack_add_titled (priv->pages, GTK_WIDGET (page), NULL, title);
selection = sysprof_visualizers_frame_get_selection (priv->visualizers);
@ -933,7 +933,6 @@ sysprof_display_load_scan_cb (GObject *object,
SysprofCaptureReader *reader;
SysprofSelection *selection;
GCancellable *cancellable;
GList *pages;
g_assert (SYSPROF_IS_DISPLAY (self));
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);
/* Opportunistically load pages */
pages = gtk_container_get_children (GTK_CONTAINER (priv->pages));
for (const GList *iter = pages; iter; iter = iter->next)
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->pages));
child;
child = gtk_widget_get_next_sibling (child))
{
if (SYSPROF_IS_PAGE (iter->data))
sysprof_page_load_async (iter->data,
if (SYSPROF_IS_PAGE (child))
sysprof_page_load_async (SYSPROF_PAGE (child),
reader,
selection,
priv->filter,
NULL, NULL, NULL);
}
g_list_free (pages);
gtk_stack_set_visible_child_name (priv->stack, "view");
}
@ -1097,12 +1096,13 @@ sysprof_display_open (SysprofDisplay *self,
error->message);
g_signal_connect (dialog,
"response",
G_CALLBACK (gtk_widget_destroy),
G_CALLBACK (gtk_window_destroy),
NULL);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
gtk_window_present (GTK_WINDOW (dialog));
gtk_widget_destroy (GTK_WIDGET (self));
_sysprof_display_destroy (self);
return;
}
@ -1200,36 +1200,21 @@ sysprof_display_new_for_profiler (SysprofProfiler *profiler)
return GTK_WIDGET (g_steal_pointer (&self));
}
void
sysprof_display_save (SysprofDisplay *self)
static void
on_save_response_cb (SysprofDisplay *self,
int res,
GtkFileChooserNative *chooser)
{
SysprofDisplayPrivate *priv = sysprof_display_get_instance_private (self);
g_autoptr(GFile) file = NULL;
GtkFileChooserNative *native;
GtkWindow *parent;
gint res;
g_return_if_fail (SYSPROF_IS_DISPLAY (self));
g_return_if_fail (priv->reader != NULL);
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));
g_assert (SYSPROF_IS_DISPLAY (self));
g_assert (GTK_IS_FILE_CHOOSER_NATIVE (chooser));
switch (res)
{
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))
{
@ -1239,17 +1224,24 @@ sysprof_display_save (SysprofDisplay *self)
if (!sysprof_capture_reader_save_as_with_error (priv->reader, path, &error))
{
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_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("Failed to save recording: %s"),
error->message);
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;
@ -1258,7 +1250,35 @@ sysprof_display_save (SysprofDisplay *self)
}
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
@ -1294,3 +1314,15 @@ sysprof_display_add_to_selection (SysprofDisplay *self,
selection = sysprof_visualizers_frame_get_selection (priv->visualizers);
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())
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
{
GtkBinClass parent_class;
GtkWidgetClass parent_class;
/*< private >*/
gpointer _reserved[16];

View File

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

View File

@ -296,35 +296,37 @@ sysprof_duplex_visualizer_set_reader (SysprofVisualizer *visualizer,
g_task_run_in_thread (task, sysprof_duplex_visualizer_worker);
}
static gboolean
sysprof_duplex_visualizer_draw (GtkWidget *widget,
cairo_t *cr)
static void
sysprof_duplex_visualizer_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
static const gdouble dashes[] = { 1.0, 2.0 };
SysprofDuplexVisualizer *self = (SysprofDuplexVisualizer *)widget;
PangoFontDescription *font_desc;
GtkStyleContext *style_context;
PangoLayout *layout;
cairo_t *cr;
GtkAllocation alloc;
GdkRectangle clip;
gboolean ret;
GdkRGBA fg;
guint mid;
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);
gdk_cairo_get_clip_rectangle (cr, &clip);
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);
gtk_style_context_get_color (style_context,
gtk_style_context_get_state (style_context),
&fg);
gtk_style_context_get_color (style_context, &fg);
fg.alpha *= 0.4;
/* Draw our center line */
@ -366,6 +368,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
n_fpoints);
/* Skip past data that we won't see anyway */
#if 0
for (p = 0; p < n_fpoints; p++)
{
if (points[p].x >= clip.x)
@ -373,7 +376,8 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
}
if (p >= n_fpoints)
return ret;
return;
#endif
/* But get at least one data point to anchor out of view */
if (p > 0)
@ -398,8 +402,10 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
last_x = points[i].x;
last_y = points[i].y;
#if 0
if (points[i].x > clip.x + clip.width)
break;
#endif
}
cairo_line_to (cr, last_x, mid);
@ -436,6 +442,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
points,
n_fpoints);
#if 0
/* Skip past data that we won't see anyway */
for (p = 0; p < n_fpoints; p++)
{
@ -445,6 +452,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
if (p >= n_fpoints)
return ret;
#endif
/* But get at least one data point to anchor out of view */
if (p > 0)
@ -469,8 +477,10 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
last_x = points[i].x;
last_y = points[i].y;
#if 0
if (points[i].x > clip.x + clip.width)
break;
#endif
}
cairo_line_to (cr, last_x, mid);
@ -510,7 +520,7 @@ sysprof_duplex_visualizer_draw (GtkWidget *widget,
pango_font_description_free (font_desc);
g_object_unref (layout);
return ret;
cairo_destroy (cr);
}
static void
@ -534,7 +544,7 @@ sysprof_duplex_visualizer_class_init (SysprofDuplexVisualizerClass *klass)
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;
}

View File

@ -127,9 +127,9 @@ value_entry_activate (GtkWidget *entry,
}
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)
{
@ -137,7 +137,7 @@ sysprof_environ_editor_row_destroy (GtkWidget *widget)
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
@ -184,11 +184,10 @@ sysprof_environ_editor_row_class_init (SysprofEnvironEditorRowClass *klass)
GObjectClass *object_class = G_OBJECT_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->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_bind_template_child (widget_class, SysprofEnvironEditorRow, delete_button);
gtk_widget_class_bind_template_child (widget_class, SysprofEnvironEditorRow, key_entry);

View File

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

View File

@ -30,13 +30,14 @@
struct _SysprofEnvironEditor
{
GtkListBox parent_instance;
GtkWidget parent_instance;
GtkListBox *list_box;
SysprofEnviron *environ;
GtkWidget *dummy_row;
SysprofEnvironVariable *dummy;
};
G_DEFINE_TYPE (SysprofEnvironEditor, sysprof_environ_editor, GTK_TYPE_LIST_BOX)
G_DEFINE_TYPE (SysprofEnvironEditor, sysprof_environ_editor, GTK_TYPE_WIDGET)
enum {
PROP_0,
@ -69,7 +70,10 @@ sysprof_environ_editor_create_dummy_row (SysprofEnvironEditor *self)
label = g_object_new (GTK_TYPE_LABEL,
"label", _("New variable…"),
"margin", 6,
"margin-start", 6,
"margin-end", 6,
"margin-top", 6,
"margin-bottom", 6,
"visible", TRUE,
"xalign", 0.0f,
NULL);
@ -114,8 +118,7 @@ sysprof_environ_editor_disconnect (SysprofEnvironEditor *self)
g_assert (SYSPROF_IS_ENVIRON_EDITOR (self));
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);
}
@ -125,12 +128,12 @@ sysprof_environ_editor_connect (SysprofEnvironEditor *self)
g_assert (SYSPROF_IS_ENVIRON_EDITOR (self));
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),
sysprof_environ_editor_create_row, self, NULL);
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
@ -168,17 +171,19 @@ find_row (SysprofEnvironEditor *self,
g_assert (SYSPROF_IS_ENVIRON_EDITOR (self));
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;
}
static void
sysprof_environ_editor_row_activated (GtkListBox *list_box,
GtkListBoxRow *row)
sysprof_environ_editor_row_activated (SysprofEnvironEditor *self,
GtkListBoxRow *row,
GtkListBox *list_box)
{
SysprofEnvironEditor *self = (SysprofEnvironEditor *)list_box;
g_assert (GTK_IS_LIST_BOX (list_box));
g_assert (GTK_IS_LIST_BOX_ROW (row));
@ -196,13 +201,19 @@ sysprof_environ_editor_row_activated (GtkListBox *list_box,
}
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_OBJECT_CLASS (sysprof_environ_editor_parent_class)->dispose (object);
}
static void
@ -248,16 +259,12 @@ sysprof_environ_editor_class_init (SysprofEnvironEditorClass *klass)
{
GObjectClass *object_class = G_OBJECT_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 ();
object_class->dispose = sysprof_environ_editor_dispose;
object_class->get_property = sysprof_environ_editor_get_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] =
g_param_spec_object ("environ",
"Environment",
@ -267,16 +274,26 @@ sysprof_environ_editor_class_init (SysprofEnvironEditorClass *klass)
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");
}
static void
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)),
"environ-editor");
gtk_list_box_set_selection_mode (self->list_box, GTK_SELECTION_NONE);
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 *

View File

@ -28,11 +28,11 @@ G_BEGIN_DECLS
#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);
SysprofEnviron *sysprof_environ_editor_get_environ (SysprofEnvironEditor *self);
void sysprof_environ_editor_set_environ (SysprofEnvironEditor *self,
SysprofEnviron *environ);
SysprofEnviron *environ);
G_END_DECLS

View File

@ -22,7 +22,7 @@
#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 *
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);
}
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
sysprof_failed_state_view_class_init (SysprofFailedStateViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_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,
"/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())
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
{
GtkBinClass parent;
gpointer padding[4];
GtkWidgetClass parent;
};
GtkWidget *sysprof_failed_state_view_new (void);

View File

@ -1,9 +1,12 @@
<?xml version="1.0"?>
<interface>
<template class="SysprofFailedStateView" parent="GtkBin">
<template class="SysprofFailedStateView" parent="GtkWidget">
<child>
<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="spacing">12</property>
<property name="visible">true</property>
@ -17,7 +20,23 @@
</style>
</object>
</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">
<property name="label" translatable="yes">Ouch, that hurt!</property>
<property name="visible">true</property>
@ -29,34 +48,6 @@
<attribute name="weight" value="bold"/>
</attributes>
</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>
</object>
</child>

View File

@ -141,9 +141,9 @@ copy_array (GArray *ar)
return ret;
}
static gboolean
sysprof_line_visualizer_draw (GtkWidget *widget,
cairo_t *cr)
static void
sysprof_line_visualizer_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
static PangoAttrList *attrs = NULL;
SysprofLineVisualizer *self = (SysprofLineVisualizer *)widget;
@ -151,28 +151,35 @@ sysprof_line_visualizer_draw (GtkWidget *widget,
g_autofree gchar *upper = NULL;
GtkStyleContext *style_context;
PangoLayout *layout;
GtkStateFlags flags;
cairo_t *cr;
GtkAllocation alloc;
GdkRectangle clip;
GdkRGBA foreground;
gboolean ret;
g_assert (SYSPROF_IS_LINE_VISUALIZER (widget));
g_assert (cr != NULL);
g_assert (snapshot != NULL);
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)
return ret;
return;
#if 0
if (!gdk_cairo_get_clip_rectangle (cr, &clip))
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);
flags = gtk_widget_get_state_flags (widget);
gtk_style_context_get_color (style_context, flags, &foreground);
gtk_style_context_get_color (style_context, &foreground);
for (guint line = 0; line < priv->lines->len; line++)
{
@ -205,7 +212,7 @@ sysprof_line_visualizer_draw (GtkWidget *widget,
}
if (p >= n_fpoints)
return ret;
goto cleanup;
if (p > 0)
p--;
@ -289,7 +296,8 @@ sysprof_line_visualizer_draw (GtkWidget *widget,
g_clear_object (&layout);
}
return ret;
cleanup:
cairo_destroy (cr);
}
static void
@ -347,12 +355,10 @@ sysprof_line_visualizer_queue_reload (SysprofLineVisualizer *self)
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
if (priv->queued_load == 0)
{
priv->queued_load = gdk_threads_add_idle_full (G_PRIORITY_LOW,
sysprof_line_visualizer_do_reload,
self,
NULL);
}
priv->queued_load = g_idle_add_full (G_PRIORITY_LOW,
sysprof_line_visualizer_do_reload,
self,
NULL);
}
static void
@ -390,11 +396,7 @@ sysprof_line_visualizer_finalize (GObject *object)
g_clear_pointer (&priv->cache, point_cache_unref);
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
if (priv->queued_load != 0)
{
g_source_remove (priv->queued_load);
priv->queued_load = 0;
}
g_clear_handle_id (&priv->queued_load, g_source_remove);
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->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;

View File

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

View File

@ -46,6 +46,177 @@ typedef struct
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
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)))
{
dzl_rgba_shade (&rgba, &kind_rgba, 1 + (ratio * span->kind));
rgba_shade (&rgba, &kind_rgba, 1 + (ratio * span->kind));
g_hash_table_insert (seen,
GUINT_TO_POINTER (span->kind),
g_memdup2 (&kind_rgba, sizeof kind_rgba));

View File

@ -50,6 +50,8 @@ typedef struct
GtkLabel *end;
GtkLabel *duration;
GtkTextView *message;
GtkWidget *failed;
GtkWidget *marks;
} SysprofMarksPagePrivate;
enum {
@ -64,19 +66,21 @@ static GParamSpec *properties [N_PROPS];
G_DEFINE_TYPE_WITH_PRIVATE (SysprofMarksPage, sysprof_marks_page, SYSPROF_TYPE_PAGE)
static gboolean
sysprof_marks_page_tree_view_key_press_event_cb (SysprofMarksPage *self,
const GdkEventKey *key,
GtkTreeView *tree_view)
sysprof_marks_page_tree_view_key_press_event_cb (SysprofMarksPage *self,
guint keyval,
guint keycode,
GdkModifierType state,
GtkEventControllerKey *controller)
{
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
gint dir = 0;
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:
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));
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
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);
}
@ -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, time);
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] =
g_param_spec_enum ("kind", NULL, NULL,
@ -536,6 +542,7 @@ static void
sysprof_marks_page_init (SysprofMarksPage *self)
{
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
GtkEventController *controller;
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_SELECTION_MULTIPLE);
g_signal_connect_object (priv->tree_view,
"key-press-event",
controller = gtk_event_controller_key_new ();
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),
self,
G_CONNECT_SWAPPED);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
g_signal_connect_object (priv->tree_view,
"row-activated",

View File

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

View File

@ -39,11 +39,13 @@
#include "config.h"
#include <dazzle.h>
#include <glib/gi18n.h>
#include "../stackstash.h"
#include "egg-paned-private.h"
#include "egg-three-grid.h"
#include "sysprof-cell-renderer-percent.h"
#include "sysprof-memprof-page.h"
#include "sysprof-profile.h"
@ -59,15 +61,19 @@ typedef struct
GtkTreeViewColumn *function_size_column;
GtkCellRendererText *function_size_cell;
GtkStack *stack;
GtkRadioButton *summary;
GtkRadioButton *all_allocs;
GtkRadioButton *temp_allocs;
GtkRadioButton *leaked_allocs_button;
GtkToggleButton *summary;
GtkToggleButton *all_allocs;
GtkToggleButton *temp_allocs;
GtkToggleButton *leaked_allocs_button;
GtkLabel *temp_allocs_count;
GtkLabel *num_allocs;
GtkLabel *leaked_allocs;
GtkLabel *peak_allocs;
GtkListBox *by_size;
GtkWidget *callgraph;
GtkWidget *summary_page;
GtkWidget *loading_state;
GtkWidget *empty_state;
GCancellable *cancellable;
@ -174,6 +180,7 @@ update_summary (SysprofMemprofPage *self,
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
SysprofMemprofStats stats;
g_autoptr(GString) str = NULL;
GtkWidget *child;
g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
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);
g_string_truncate (str, 0);
gtk_container_foreach (GTK_CONTAINER (priv->by_size),
(GtkCallback)gtk_widget_destroy,
NULL);
while ((child = gtk_widget_get_first_child (GTK_WIDGET (priv->by_size))))
gtk_list_box_remove (priv->by_size, child);
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_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_end (box, 6);
@ -267,13 +273,11 @@ update_summary (SysprofMemprofPage *self,
gtk_level_bar_set_value (GTK_LEVEL_BAR (prog),
stats.by_size[i].n_allocs);
gtk_container_add (GTK_CONTAINER (row), box);
gtk_container_add (GTK_CONTAINER (box), title);
gtk_container_add (GTK_CONTAINER (box), prog);
gtk_container_add (GTK_CONTAINER (box), subtitle);
gtk_container_add (GTK_CONTAINER (priv->by_size), row);
gtk_widget_show_all (row);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_box_append (GTK_BOX (box), title);
gtk_box_append (GTK_BOX (box), prog);
gtk_box_append (GTK_BOX (box), subtitle);
gtk_list_box_append (priv->by_size, row);
}
}
@ -310,7 +314,7 @@ sysprof_memprof_page_load (SysprofMemprofPage *self,
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;
}
@ -345,7 +349,7 @@ sysprof_memprof_page_load (SysprofMemprofPage *self,
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);
}
@ -357,7 +361,7 @@ _sysprof_memprof_page_set_failed (SysprofMemprofPage *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
@ -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->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)
{
g_autoptr(GString) str = NULL;
GtkClipboard *clipboard;
GdkClipboard *clipboard;
g_assert (GTK_IS_TREE_VIEW (tree_view));
@ -896,24 +900,25 @@ copy_tree_view_selection (GtkTreeView *tree_view)
copy_tree_view_selection_cb,
str);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view), GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text (clipboard, str->str, str->len);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (tree_view));
gdk_clipboard_set_text (clipboard, str->str);
}
static void
sysprof_memprof_page_copy_cb (GtkWidget *widget,
SysprofMemprofPage *self)
sysprof_memprof_page_copy_cb (GtkWidget *widget,
const char *action_name,
GVariant *param)
{
SysprofMemprofPage *self = (SysprofMemprofPage *)widget;
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
GtkWidget *toplevel;
GtkWidget *focus;
GtkRoot *toplevel;
g_assert (GTK_IS_WIDGET (widget));
g_assert (SYSPROF_IS_MEMPROF_PAGE (self));
if (!(toplevel = gtk_widget_get_toplevel (widget)) ||
!GTK_IS_WINDOW (toplevel) ||
!(focus = gtk_window_get_focus (GTK_WINDOW (toplevel))))
if (!(toplevel = gtk_widget_get_root (widget)) ||
!GTK_IS_ROOT (toplevel) ||
!(focus = gtk_root_get_focus (toplevel)))
return;
if (focus == GTK_WIDGET (priv->descendants_view))
@ -973,7 +978,7 @@ sysprof_memprof_page_load_async (SysprofPage *page,
else
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);
g_task_set_source_tag (task, sysprof_memprof_page_load_async);
@ -1015,12 +1020,12 @@ do_allocs (SysprofMemprofPage *self,
static void
mode_notify_active (SysprofMemprofPage *self,
GParamSpec *pspec,
GtkRadioButton *button)
GtkToggleButton *button)
{
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (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)))
{
@ -1106,7 +1111,6 @@ sysprof_memprof_page_class_init (SysprofMemprofPageClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass);
GtkBindingSet *bindings;
object_class->finalize = sysprof_memprof_page_finalize;
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_button);
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_binding_entry_add_signal (bindings, GDK_KEY_Left, GDK_MOD1_MASK, "go-previous", 0);
gtk_widget_class_install_action (widget_class, "page.copy", NULL, sysprof_memprof_page_copy_cb);
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);
}
@ -1163,7 +1175,6 @@ static void
sysprof_memprof_page_init (SysprofMemprofPage *self)
{
SysprofMemprofPagePrivate *priv = sysprof_memprof_page_get_instance_private (self);
DzlShortcutController *controller;
GtkTreeSelection *selection;
GtkCellRenderer *cell;
@ -1172,7 +1183,7 @@ sysprof_memprof_page_init (SysprofMemprofPage *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);
@ -1246,16 +1257,6 @@ sysprof_memprof_page_init (SysprofMemprofPage *self)
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->descendants_view),
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;
@ -1542,7 +1543,7 @@ _sysprof_memprof_page_set_loading (SysprofMemprofPage *self,
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
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>
<template class="SysprofMemprofPage" parent="SysprofPage">
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="visible">true</property>
<child>
<object class="GtkBox">
<object class="GtkCenterBox">
<property name="orientation">horizontal</property>
<property name="visible">true</property>
<child type="center">
<object class="GtkBox">
<property name="margin-top">6</property>
<property name="margin-bottom">6</property>
<property name="orientation">horizontal</property>
<property name="homogeneous">true</property>
<property name="visible">true</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkRadioButton" id="summary">
<object class="GtkToggleButton" id="summary">
<property name="label" translatable="yes">Summary</property>
<property name="draw-indicator">false</property>
<property name="visible">true</property>
<property name="active">false</property>
</object>
</child>
<child>
<object class="GtkRadioButton" id="all_allocs">
<object class="GtkToggleButton" id="all_allocs">
<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="active">true</property>
</object>
</child>
<child>
<object class="GtkRadioButton" id="temp_allocs">
<object class="GtkToggleButton" id="temp_allocs">
<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="group">summary</property>
</object>
@ -48,7 +40,6 @@
<object class="GtkRadioButton" id="leaked_allocs_button">
<property name="label" translatable="yes">Leaked Allocations</property>
<property name="draw-indicator">false</property>
<property name="visible">true</property>
<property name="active">false</property>
<property name="group">summary</property>
</object>
@ -60,27 +51,25 @@
<child>
<object class="GtkSeparator">
<property name="orientation">horizontal</property>
<property name="visible">true</property>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="visible">true</property>
<child>
<object class="GtkScrolledWindow">
<object class="GtkScrolledWindow" id="summary_page">
<property name="hscrollbar-policy">never</property>
<property name="visible">true</property>
<child>
<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="visible">true</property>
<child>
<object class="DzlThreeGrid">
<property name="expand">true</property>
<object class="EggThreeGrid">
<property name="hexpand">true</property>
<property name="row-spacing">6</property>
<property name="column-spacing">18</property>
<property name="visible">true</property>
<child>
<object class="GtkLabel">
<property name="label">Peak Allocation</property>
@ -89,47 +78,45 @@
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="column">left</property>
<property name="row">0</property>
</layout>
</object>
<packing>
<property name="column">left</property>
<property name="row">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="peak_allocs">
<property name="xalign">0</property>
<property name="selectable">true</property>
<property name="visible">false</property>
<layout>
<property name="column">center</property>
<property name="row">0</property>
</layout>
</object>
<packing>
<property name="column">center</property>
<property name="row">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="label">Number of Allocations</property>
<property name="halign">end</property>
<property name="visible">true</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="column">left</property>
<property name="row">1</property>
</layout>
</object>
<packing>
<property name="column">left</property>
<property name="row">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="num_allocs">
<property name="xalign">0</property>
<property name="selectable">true</property>
<property name="visible">true</property>
<layout>
<property name="column">center</property>
<property name="row">1</property>
</layout>
</object>
<packing>
<property name="column">center</property>
<property name="row">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
@ -139,104 +126,92 @@
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="column">left</property>
<property name="row">2</property>
</layout>
</object>
<packing>
<property name="column">left</property>
<property name="row">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="leaked_allocs">
<property name="xalign">0</property>
<property name="selectable">true</property>
<property name="visible">false</property>
<layout>
<property name="column">center</property>
<property name="row">2</property>
</layout>
</object>
<packing>
<property name="column">center</property>
<property name="row">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="label">Temporary Allocations</property>
<property name="halign">end</property>
<property name="visible">true</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="column">left</property>
<property name="row">3</property>
</layout>
</object>
<packing>
<property name="column">left</property>
<property name="row">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="temp_allocs_count">
<property name="xalign">0</property>
<property name="selectable">true</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>
<packing>
<property name="column">center</property>
<property name="row">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="label">Allocations by Size</property>
<property name="halign">end</property>
<property name="valign">start</property>
<property name="visible">true</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="column">left</property>
<property name="row">4</property>
</layout>
</object>
<packing>
<property name="column">left</property>
<property name="row">4</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">true</property>
<child>
<object class="GtkListBox" id="by_size">
<property name="visible">true</property>
</object>
</child>
<layout>
<property name="column">center</property>
<property name="row">4</property>
</layout>
</object>
<packing>
<property name="column">center</property>
<property name="row">4</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="name">summary</property>
</packing>
</child>
<child>
<object class="GtkPaned">
<object class="EggPaned" id="callgraph">
<property name="orientation">horizontal</property>
<property name="position">450</property>
<property name="expand">true</property>
<property name="visible">true</property>
<property name="vexpand">true</property>
<child>
<object class="GtkPaned">
<object class="EggPaned">
<property name="width-request">400</property>
<property name="orientation">vertical</property>
<property name="visible">true</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<child>
<object class="GtkTreeView" id="functions_view">
<property name="fixed-height-mode">true</property>
<property name="visible">true</property>
<child>
<object class="GtkTreeViewColumn" id="function_name_column">
<property name="expand">true</property>
@ -289,16 +264,11 @@
</object>
</child>
</object>
<packing>
<property name="resize">true</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<child>
<object class="GtkTreeView" id="callers_view">
<property name="visible">true</property>
<child>
<object class="GtkTreeViewColumn" id="callers_name_column">
<property name="expand">true</property>
@ -351,18 +321,13 @@
</object>
</child>
</object>
<packing>
<property name="resize">true</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">true</property>
<child>
<object class="GtkTreeView" id="descendants_view">
<property name="visible">true</property>
<child>
<object class="GtkTreeViewColumn" id="descendants_name_column">
<property name="expand">true</property>
@ -421,31 +386,20 @@
</object>
</child>
</object>
<packing>
<property name="name">callgraph</property>
</packing>
</child>
<child>
<object class="DzlEmptyState">
<object class="AdwStatusPage" id="loading_state">
<property name="icon-name">content-loading-symbolic</property>
<property name="title" translatable="yes">Analyzing Memory Allocations</property>
<property name="subtitle" translatable="yes">Sysprof is busy analyzing memory allocations.</property>
<property name="visible">true</property>
<property name="description" translatable="yes">Sysprof is busy analyzing memory allocations.</property>
</object>
<packing>
<property name="name">loading</property>
</packing>
</child>
<child>
<object class="DzlEmptyState">
<object class="AdwStatusPage" id="empty_state">
<property name="icon-name">computer-fail-symbolic</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="visible">false</property>
<property name="description" translatable="yes">More samples are necessary to display a callgraph.</property>
</object>
<packing>
<property name="name">empty-state</property>
</packing>
</child>
</object>
</child>

View File

@ -528,49 +528,46 @@ sysprof_memprof_visualizer_queue_redraw (SysprofMemprofVisualizer *self)
}
static void
sysprof_memprof_visualizer_size_allocate (GtkWidget *widget,
GtkAllocation *alloc)
sysprof_memprof_visualizer_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)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);
sysprof_memprof_visualizer_queue_redraw (SYSPROF_MEMPROF_VISUALIZER (widget));
}
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->surface, cairo_surface_destroy);
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
sysprof_memprof_visualizer_draw (GtkWidget *widget,
cairo_t *cr)
static void
sysprof_memprof_visualizer_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
SysprofMemprofVisualizer *self = (SysprofMemprofVisualizer *)widget;
gboolean ret;
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)
{
cairo_t *cr;
GtkAllocation 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_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_paint (cr);
cairo_restore (cr);
}
return ret;
cairo_destroy (cr);
}
}
static void
sysprof_memprof_visualizer_class_init (SysprofMemprofVisualizerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
SysprofVisualizerClass *visualizer_class = SYSPROF_VISUALIZER_CLASS (klass);
widget_class->destroy = sysprof_memprof_visualizer_destroy;
widget_class->draw = sysprof_memprof_visualizer_draw;
object_class->dispose = sysprof_memprof_visualizer_dispose;
widget_class->snapshot = sysprof_memprof_visualizer_snapshot;
widget_class->size_allocate = sysprof_memprof_visualizer_size_allocate;
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)
sysprof_display_add_group (present->display, group);
else
gtk_widget_destroy (GTK_WIDGET (group));
g_object_unref (g_object_ref_sink (group));
}
return counters != NULL;

View File

@ -29,10 +29,15 @@
typedef struct
{
GtkNotebook *notebook;
guint always_show_tabs : 1;
} 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 {
PROP_0,
@ -83,15 +88,16 @@ sysprof_notebook_notify_can_replay_cb (SysprofNotebook *self,
}
static void
sysprof_notebook_page_added (GtkNotebook *notebook,
GtkWidget *child,
guint page_num)
sysprof_notebook_page_added (SysprofNotebook *self,
GtkWidget *child,
guint page_num,
GtkNotebook *notebook)
{
SysprofNotebook *self = (SysprofNotebook *)notebook;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_assert (SYSPROF_IS_NOTEBOOK (self));
g_assert (GTK_IS_WIDGET (child));
g_assert (GTK_IS_NOTEBOOK (notebook));
gtk_notebook_set_show_tabs (notebook,
(priv->always_show_tabs ||
@ -107,13 +113,13 @@ sysprof_notebook_page_added (GtkNotebook *notebook,
g_signal_connect_object (child,
"notify::can-replay",
G_CALLBACK (sysprof_notebook_notify_can_replay_cb),
notebook,
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (child,
"notify::can-save",
G_CALLBACK (sysprof_notebook_notify_can_save_cb),
notebook,
self,
G_CONNECT_SWAPPED);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_REPLAY]);
@ -125,15 +131,16 @@ sysprof_notebook_page_added (GtkNotebook *notebook,
}
static void
sysprof_notebook_page_removed (GtkNotebook *notebook,
GtkWidget *child,
guint page_num)
sysprof_notebook_page_removed (SysprofNotebook *self,
GtkWidget *child,
guint page_num,
GtkNotebook *notebook)
{
SysprofNotebook *self = (SysprofNotebook *)notebook;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
g_assert (SYSPROF_IS_NOTEBOOK (self));
g_assert (GTK_IS_WIDGET (child));
g_assert (GTK_IS_NOTEBOOK (notebook));
if (gtk_widget_in_destruction (GTK_WIDGET (notebook)))
return;
@ -141,16 +148,16 @@ sysprof_notebook_page_removed (GtkNotebook *notebook,
if (gtk_notebook_get_n_pages (notebook) == 0)
{
child = sysprof_display_new ();
gtk_container_add (GTK_CONTAINER (notebook), child);
gtk_notebook_append_page (notebook, child, NULL);
gtk_widget_show (child);
g_signal_handlers_disconnect_by_func (child,
G_CALLBACK (sysprof_notebook_notify_can_save_cb),
notebook);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_REPLAY]);
g_object_notify_by_pspec (G_OBJECT (notebook), 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_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]);
}
gtk_notebook_set_show_tabs (notebook,
@ -159,18 +166,33 @@ sysprof_notebook_page_removed (GtkNotebook *notebook,
}
static void
sysprof_notebook_switch_page (GtkNotebook *notebook,
GtkWidget *widget,
guint page)
sysprof_notebook_switch_page (SysprofNotebook *self,
GtkWidget *widget,
guint page,
GtkNotebook *notebook)
{
g_assert (SYSPROF_IS_NOTEBOOK (self));
g_assert (GTK_IS_NOTEBOOK (notebook));
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]);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CAN_SAVE]);
g_object_notify_by_pspec (G_OBJECT (notebook), properties [PROP_CURRENT]);
static void
sysprof_notebook_dispose (GObject *object)
{
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
@ -227,15 +249,12 @@ static void
sysprof_notebook_class_init (SysprofNotebookClass *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->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] =
g_param_spec_boolean ("always-show-tabs",
"Always Show Tabs",
@ -265,71 +284,86 @@ sysprof_notebook_class_init (SysprofNotebookClass *klass)
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
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
sysprof_notebook_init (SysprofNotebook *self)
{
gtk_notebook_set_show_border (GTK_NOTEBOOK (self), FALSE);
gtk_notebook_set_scrollable (GTK_NOTEBOOK (self), TRUE);
gtk_notebook_popup_enable (GTK_NOTEBOOK (self));
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (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
sysprof_notebook_close_current (SysprofNotebook *self)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
gint page;
g_return_if_fail (SYSPROF_IS_NOTEBOOK (self));
if ((page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self))) >= 0)
gtk_widget_destroy (gtk_notebook_get_nth_page (GTK_NOTEBOOK (self), 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;
if ((page = gtk_notebook_get_current_page (priv->notebook)) >= 0)
gtk_notebook_remove_page (priv->notebook, page);
}
void
sysprof_notebook_open (SysprofNotebook *self,
GFile *file)
{
GtkWidget *display = NULL;
gint page;
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
SysprofDisplay *display = NULL;
int page;
g_return_if_fail (SYSPROF_IS_NOTEBOOK (self));
g_return_if_fail (g_file_is_native (file));
gtk_container_foreach (GTK_CONTAINER (self),
find_empty_display_cb,
&display);
for (page = 0; page < sysprof_notebook_get_n_pages (self); page++)
{
SysprofDisplay *child = sysprof_notebook_get_nth_page (self, page);
if (sysprof_display_is_empty (child))
{
display = child;
break;
}
}
if (display == NULL)
{
display = sysprof_display_new ();
page = gtk_notebook_insert_page (GTK_NOTEBOOK (self), display, NULL, -1);
gtk_widget_show (display);
display = SYSPROF_DISPLAY (sysprof_display_new ());
page = sysprof_notebook_append (self, display);
}
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);
}
@ -337,12 +371,13 @@ sysprof_notebook_open (SysprofNotebook *self,
SysprofDisplay *
sysprof_notebook_get_current (SysprofNotebook *self)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
gint page;
g_assert (SYSPROF_IS_NOTEBOOK (self));
if ((page = gtk_notebook_get_current_page (GTK_NOTEBOOK (self))) >= 0)
return SYSPROF_DISPLAY (gtk_notebook_get_nth_page (GTK_NOTEBOOK (self), page));
if ((page = gtk_notebook_get_current_page (priv->notebook)) >= 0)
return SYSPROF_DISPLAY (gtk_notebook_get_nth_page (priv->notebook, page));
return NULL;
}
@ -387,6 +422,7 @@ sysprof_notebook_get_can_replay (SysprofNotebook *self)
void
sysprof_notebook_replay (SysprofNotebook *self)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
SysprofDisplay *display;
SysprofDisplay *replay;
gint page;
@ -401,15 +437,16 @@ sysprof_notebook_replay (SysprofNotebook *self)
g_return_if_fail (SYSPROF_IS_DISPLAY (replay));
gtk_widget_show (GTK_WIDGET (replay));
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (replay));
page = gtk_notebook_page_num (GTK_NOTEBOOK (self), GTK_WIDGET (replay));
gtk_notebook_set_current_page (GTK_NOTEBOOK (self), page);
gtk_notebook_append_page (priv->notebook, GTK_WIDGET (replay), NULL);
page = gtk_notebook_page_num (priv->notebook, GTK_WIDGET (replay));
gtk_notebook_set_current_page (priv->notebook, page);
}
void
sysprof_notebook_add_profiler (SysprofNotebook *self,
SysprofProfiler *profiler)
{
SysprofNotebookPrivate *priv = sysprof_notebook_get_instance_private (self);
GtkWidget *display;
gint page;
@ -419,9 +456,9 @@ sysprof_notebook_add_profiler (SysprofNotebook *self,
display = sysprof_display_new_for_profiler (profiler);
gtk_widget_show (display);
gtk_container_add (GTK_CONTAINER (self), display);
page = gtk_notebook_page_num (GTK_NOTEBOOK (self), display);
gtk_notebook_set_current_page (GTK_NOTEBOOK (self), page);
gtk_notebook_append_page (priv->notebook, GTK_WIDGET (display), NULL);
page = gtk_notebook_page_num (priv->notebook, display);
gtk_notebook_set_current_page (priv->notebook, page);
}
gboolean
@ -447,9 +484,78 @@ sysprof_notebook_set_always_show_tabs (SysprofNotebook *self,
if (always_show_tabs != priv->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 ||
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]);
}
}
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())
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
{
GtkNotebookClass parent_class;
GtkWidgetClass parent_class;
/*< private >*/
gpointer _reserved[16];
@ -70,5 +70,16 @@ gboolean sysprof_notebook_get_always_show_tabs (SysprofNotebook *self);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_notebook_set_always_show_tabs (SysprofNotebook *self,
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

View File

@ -31,7 +31,7 @@ typedef struct
gchar *title;
} SysprofPagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofPage, sysprof_page, GTK_TYPE_BIN)
G_DEFINE_TYPE_WITH_PRIVATE (SysprofPage, sysprof_page, GTK_TYPE_WIDGET)
enum {
PROP_0,
@ -105,14 +105,18 @@ sysprof_page_real_load_finish (SysprofPage *self,
}
static void
sysprof_page_finalize (GObject *object)
sysprof_page_dispose (GObject *object)
{
SysprofPage *self = (SysprofPage *)object;
SysprofPagePrivate *priv = sysprof_page_get_instance_private (self);
GtkWidget *child;
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
@ -157,8 +161,9 @@ static void
sysprof_page_class_init (SysprofPageClass *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->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_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
static void
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())
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
{
GtkBinClass parent_class;
GtkWidgetClass parent_class;
void (*load_async) (SysprofPage *self,
SysprofCaptureReader *reader,

View File

@ -4,7 +4,10 @@
<child>
<object class="GtkBox">
<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>
<child>
<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);
}
static gboolean
sysprof_procs_visualizer_draw (GtkWidget *widget,
cairo_t *cr)
static void
sysprof_procs_visualizer_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
SysprofProcsVisualizer *self = (SysprofProcsVisualizer *)widget;
g_autofree SysprofVisualizerAbsolutePoint *points = NULL;
gboolean ret = GDK_EVENT_PROPAGATE;
GtkAllocation alloc;
GdkRGBA background;
GdkRGBA foreground;
const Point *fpoints;
guint n_fpoints = 0;
Discovery *d;
cairo_t *cr;
gdouble last_x = 0;
gdouble last_y = 0;
g_assert (SYSPROF_IS_PROCS_VISUALIZER (self));
g_assert (cr != NULL);
g_assert (snapshot != NULL);
gtk_widget_get_allocation (widget, &alloc);
@ -208,14 +208,17 @@ sysprof_procs_visualizer_draw (GtkWidget *widget,
background = foreground;
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)
return ret;
return;
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);
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (self),
@ -254,7 +257,7 @@ sysprof_procs_visualizer_draw (GtkWidget *widget,
gdk_cairo_set_source_rgba (cr, &foreground);
cairo_stroke (cr);
return ret;
cairo_destroy (cr);
}
static void
@ -276,7 +279,7 @@ sysprof_procs_visualizer_class_init (SysprofProcsVisualizerClass *klass)
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;
}

View File

@ -24,6 +24,8 @@
#include <sysprof.h>
#include "egg-three-grid.h"
#include "sysprof-platform.h"
#include "sysprof-aid-icon.h"
@ -45,7 +47,7 @@
struct _SysprofProfilerAssistant
{
GtkBin parent_instance;
GtkWidget parent_instance;
SysprofProcessModel *process_model;
@ -61,6 +63,7 @@ struct _SysprofProfilerAssistant
GtkSwitch *whole_system_switch;
GtkSwitch *launch_switch;
GtkSwitch *inherit_switch;
GtkWidget *scroller;
};
enum {
@ -70,7 +73,7 @@ enum {
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:
@ -155,12 +158,12 @@ sysprof_profiler_assistant_command_line_changed_cb (SysprofProfilerAssistant *se
g_assert (GTK_IS_ENTRY (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))
gtk_style_context_remove_class (style_context, GTK_STYLE_CLASS_ERROR);
gtk_style_context_remove_class (style_context, "error");
else
gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_ERROR);
gtk_style_context_add_class (style_context, "error");
}
static void
@ -222,9 +225,10 @@ sysprof_profiler_assistant_record_clicked_cb (SysprofProfilerAssistant *self,
sysprof_profiler_set_writer (profiler, writer);
/* Add pids to profiler */
gtk_container_foreach (GTK_CONTAINER (self->process_list_box),
(GtkCallback) sysprof_profiler_assistant_foreach_cb,
profiler);
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->process_list_box));
child;
child = gtk_widget_get_next_sibling (child))
sysprof_profiler_assistant_foreach_cb (child, profiler);
/* Setup whole system profiling */
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;
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);
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);
/* Now allow the aids to add their sources */
gtk_container_foreach (GTK_CONTAINER (self->aid_flow_box),
(GtkCallback) sysprof_profiler_assistant_foreach_cb,
profiler);
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->aid_flow_box));
child;
child = gtk_widget_get_next_sibling (child))
sysprof_profiler_assistant_foreach_cb (child, 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);
text = gtk_entry_get_text (GTK_ENTRY (search_entry));
text = gtk_editable_get_text (GTK_EDITABLE (search_entry));
if (text[0] == 0)
{
@ -345,21 +350,23 @@ sysprof_profiler_assistant_search_changed_cb (SysprofProfilerAssistant *self,
}
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_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
sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass)
{
GObjectClass *object_class = G_OBJECT_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:
@ -377,6 +384,7 @@ sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass)
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_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, aid_flow_box);
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, inherit_switch);
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_BATTERY_AID);
@ -465,12 +476,12 @@ sysprof_profiler_assistant_set_executable (SysprofProfilerAssistant *self,
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);
}
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_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())
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);
void sysprof_profiler_assistant_set_executable (SysprofProfilerAssistant *self,

View File

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

View File

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

View File

@ -31,7 +31,7 @@ typedef struct
gulong notify_elapsed_handler;
} 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 {
PROP_0,
@ -79,18 +79,22 @@ sysprof_recording_state_view_notify_elapsed (SysprofRecordingStateView *self,
}
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);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
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);
}
GTK_WIDGET_CLASS (sysprof_recording_state_view_parent_class)->destroy (widget);
G_OBJECT_CLASS (sysprof_recording_state_view_parent_class)->dispose (object);
}
static void
@ -138,11 +142,10 @@ sysprof_recording_state_view_class_init (SysprofRecordingStateViewClass *klass)
GObjectClass *object_class = G_OBJECT_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->set_property = sysprof_recording_state_view_set_property;
widget_class->destroy = sysprof_recording_state_view_destroy;
properties [PROP_PROFILER] =
g_param_spec_object ("profiler",
"Profiler",
@ -153,6 +156,7 @@ sysprof_recording_state_view_class_init (SysprofRecordingStateViewClass *klass)
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_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, samples);

View File

@ -27,13 +27,11 @@ G_BEGIN_DECLS
#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
{
GtkBinClass parent;
gpointer padding[4];
GtkWidgetClass parent;
};
GtkWidget *sysprof_recording_state_view_new (void);

View File

@ -1,11 +1,14 @@
<?xml version="1.0"?>
<interface>
<template class="SysprofRecordingStateView" parent="GtkBin">
<template class="SysprofRecordingStateView" parent="GtkWidget">
<child>
<object class="GtkBox">
<property name="width-request">500</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="spacing">12</property>
<property name="visible">true</property>

View File

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

View File

@ -22,14 +22,15 @@
#include "config.h"
#include "sysprof-display.h"
#include "sysprof-display-private.h"
#include "sysprof-tab.h"
#include "sysprof-ui-private.h"
struct _SysprofTab
{
GtkBox parent_instance;
GtkWidget parent_instance;
GtkWidget *center_box;
GtkButton *close_button;
GtkLabel *title;
GtkImage *recording;
@ -37,7 +38,7 @@ struct _SysprofTab
SysprofDisplay *display;
};
G_DEFINE_TYPE (SysprofTab, sysprof_tab, GTK_TYPE_BOX)
G_DEFINE_TYPE (SysprofTab, sysprof_tab, GTK_TYPE_WIDGET)
enum {
PROP_0,
@ -62,18 +63,19 @@ sysprof_tab_close_clicked (SysprofTab *self,
g_assert (SYSPROF_IS_TAB (self));
g_assert (GTK_IS_BUTTON (button));
if (self->display != NULL)
gtk_widget_destroy (GTK_WIDGET (self->display));
if (self->display)
_sysprof_display_destroy (self->display);
}
static void
sysprof_tab_finalize (GObject *object)
sysprof_tab_dispose (GObject *object)
{
SysprofTab *self = (SysprofTab *)object;
g_clear_pointer (&self->center_box, gtk_widget_unparent);
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
@ -122,11 +124,13 @@ sysprof_tab_class_init (SysprofTabClass *klass)
GObjectClass *object_class = G_OBJECT_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->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_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, recording);
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())
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);

View File

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

View File

@ -58,8 +58,8 @@ theme_resource_free (gpointer data)
if (theme_resource->provider != NULL)
{
gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (theme_resource->provider));
gtk_style_context_remove_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (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 ();
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_PROVIDER (theme_resource->provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (theme_resource->provider),
GTK_STYLE_PROVIDER_PRIORITY_THEME+1);
}
}
else
{
if (theme_resource->provider != NULL)
{
gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (theme_resource->provider));
gtk_style_context_remove_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (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));
if (self->reload_source == 0)
self->reload_source = gdk_threads_add_idle_full (G_PRIORITY_LOW,
sysprof_theme_manager_do_reload,
self,
NULL);
self->reload_source = g_idle_add_full (G_PRIORITY_LOW,
sysprof_theme_manager_do_reload,
self,
NULL);
}
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);
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
{
GtkBox parent;
GtkLabel *minutes;
GtkLabel *seconds;
GtkWidget parent_instance;
GtkCenterBox *box;
GtkLabel *minutes;
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
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
@ -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_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,
"attributes", attrs,
"visible", TRUE,
"xalign", 1.0f,
"hexpand", TRUE,
NULL);
gtk_container_add_with_properties (GTK_CONTAINER (self), GTK_WIDGET (self->minutes),
"pack-type", GTK_PACK_START,
"expand", TRUE,
"fill", TRUE,
NULL);
gtk_center_box_set_start_widget (self->box, GTK_WIDGET (self->minutes));
sep = g_object_new (GTK_TYPE_LABEL,
"margin-start", 3,
"margin-end", 3,
"attributes", attrs,
"visible", TRUE,
"label", ":",
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,
"attributes", attrs,
"visible", TRUE,
"xalign", 0.0f,
"hexpand", TRUE,
NULL);
gtk_container_add_with_properties (GTK_CONTAINER (self), GTK_WIDGET (self->seconds),
"pack-type", GTK_PACK_END,
"expand", TRUE,
"fill", TRUE,
NULL);
gtk_center_box_set_end_widget (self->box, GTK_WIDGET (self->seconds));
}
void

View File

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

View File

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

View File

@ -38,17 +38,28 @@ struct _SysprofVisualizerGroupHeader
G_DEFINE_TYPE (SysprofVisualizerGroupHeader, sysprof_visualizer_group_header, GTK_TYPE_LIST_BOX_ROW)
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
sysprof_visualizer_group_header_class_init (SysprofVisualizerGroupHeaderClass *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
@ -58,7 +69,7 @@ sysprof_visualizer_group_header_init (SysprofVisualizerGroupHeader *self)
"orientation", GTK_ORIENTATION_VERTICAL,
"visible", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->box));
gtk_widget_set_parent (GTK_WIDGET (self->box), GTK_WIDGET (self));
}
void
@ -68,8 +79,9 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
GMenuModel *menu,
GtkWidget *widget)
{
GtkBox *box;
GtkWidget *group;
GtkWidget *sibling;
GtkBox *box;
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP_HEADER (self));
g_return_if_fail (SYSPROF_IS_VISUALIZER (widget));
@ -81,9 +93,11 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
"visible", TRUE,
NULL);
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,
NULL);
sibling = gtk_widget_get_first_child (GTK_WIDGET (self->box));
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)
{
@ -95,13 +109,16 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
label = g_object_new (GTK_TYPE_LABEL,
"attributes", attrs,
"ellipsize", PANGO_ELLIPSIZE_MIDDLE,
"margin", 6,
"margin-top", 6,
"margin-bottom", 6,
"margin-start", 6,
"margin-end", 6,
"hexpand", TRUE,
"label", title,
"visible", TRUE,
"xalign", 0.0f,
NULL);
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (label));
gtk_box_append (box, GTK_WIDGET (label));
pango_attr_list_unref (attrs);
gtk_size_group_add_widget (size_group, widget);
@ -120,8 +137,8 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
"pixel-size", 16,
"visible", TRUE,
NULL);
dzl_gtk_widget_add_style_class (GTK_WIDGET (image), "dim-label");
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (image));
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (image)), "dim-label");
gtk_box_append (box, GTK_WIDGET (image));
}
if (menu != NULL)
@ -134,12 +151,11 @@ _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
"icon-name", "view-more-symbolic",
"visible", TRUE,
NULL),
"margin-right", 6,
"margin-end", 6,
"direction", GTK_ARROW_RIGHT,
"halign", GTK_ALIGN_CENTER,
"menu-model", menu,
"tooltip-text", _("Display supplemental graphs"),
"use-popover", FALSE,
"valign", GTK_ALIGN_CENTER,
"visible", TRUE,
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, "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 <dazzle.h>
#include <glib/gi18n.h>
#include "sysprof-visualizer.h"
@ -158,21 +157,6 @@ create_action_name (const gchar *str)
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
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->actions);
dzl_clear_weak_pointer (&priv->header);
g_clear_weak_pointer (&priv->header);
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);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->finalize = sysprof_visualizer_group_finalize;
object_class->get_property = sysprof_visualizer_group_get_property;
object_class->set_property = sysprof_visualizer_group_set_property;
container_class->add = sysprof_visualizer_group_add;
properties [PROP_HAS_PAGE] =
g_param_spec_boolean ("has-page",
"Has Page",
@ -331,7 +312,7 @@ sysprof_visualizer_group_init (SysprofVisualizerGroup *self)
"orientation", GTK_ORIENTATION_VERTICAL,
"visible", TRUE,
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
@ -343,11 +324,10 @@ _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
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)
{
GList *children;
guint position = 0;
gtk_widget_insert_action_group (GTK_WIDGET (header),
@ -355,11 +335,11 @@ _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
G_ACTION_GROUP (priv->actions));
gtk_size_group_add_widget (priv->size_group, GTK_WIDGET (header));
children = gtk_container_get_children (GTK_CONTAINER (priv->visualizers));
for (const GList *iter = children; iter; iter = iter->next)
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->visualizers));
child;
child = gtk_widget_get_next_sibling (child))
{
SysprofVisualizer *vis = iter->data;
SysprofVisualizer *vis = SYSPROF_VISUALIZER (child);
const gchar *title;
GMenuModel *menu = NULL;
@ -381,19 +361,10 @@ _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
position++;
}
g_list_free (children);
}
}
}
static void
sysprof_visualizer_group_set_reader_cb (SysprofVisualizer *visualizer,
SysprofCaptureReader *reader)
{
sysprof_visualizer_set_reader (visualizer, reader);
}
void
_sysprof_visualizer_group_set_reader (SysprofVisualizerGroup *self,
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 (reader != NULL);
gtk_container_foreach (GTK_CONTAINER (priv->visualizers),
(GtkCallback) sysprof_visualizer_group_set_reader_cb,
reader);
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (priv->visualizers));
child;
child = gtk_widget_get_next_sibling (child))
sysprof_visualizer_set_reader (SYSPROF_VISUALIZER (child), reader);
}
void
@ -415,13 +387,18 @@ sysprof_visualizer_group_insert (SysprofVisualizerGroup *self,
gboolean can_toggle)
{
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 (visualizer));
gtk_container_add_with_properties (GTK_CONTAINER (priv->visualizers), GTK_WIDGET (visualizer),
"position", position,
NULL);
sibling = gtk_widget_get_first_child (GTK_WIDGET (priv->visualizers));
while (position > 1 && sibling)
{
sibling = gtk_widget_get_next_sibling (sibling);
position--;
}
gtk_box_insert_child_after (priv->visualizers, GTK_WIDGET (visualizer), sibling);
if (can_toggle)
{

View File

@ -135,10 +135,11 @@ update_label_text (PangoLayout *layout,
static gboolean
draw_ticks (SysprofVisualizerTicks *self,
cairo_t *cr,
GtkAllocation *area,
gint ticks,
gboolean label_mode)
GtkSnapshot *snapshot,
GtkAllocation *area,
gint ticks,
gboolean label_mode,
const GdkRGBA *color)
{
GtkAllocation alloc;
gint64 begin_time, end_time;
@ -146,7 +147,7 @@ draw_ticks (SysprofVisualizerTicks *self,
gint count = 0;
g_assert (SYSPROF_IS_VISUALIZER_TICKS (self));
g_assert (cr != NULL);
g_assert (snapshot != NULL);
g_assert (area != NULL);
g_assert (ticks >= 0);
g_assert (ticks < N_TICKS);
@ -195,12 +196,16 @@ draw_ticks (SysprofVisualizerTicks *self,
if (x < (last_x2 + MIN_TICK_DISTANCE))
continue;
cairo_move_to (cr, (gint)x + 2.5 - (gint)half, 2);
update_label_text (layout, t - begin_time, want_msec);
pango_layout_get_pixel_size (layout, &w, &h);
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;
}
@ -212,48 +217,44 @@ draw_ticks (SysprofVisualizerTicks *self,
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);
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++;
}
cairo_set_line_width (cr, tick_sizing[ticks].width);
cairo_stroke (cr);
}
return count > 2;
}
static gboolean
sysprof_visualizer_ticks_draw (GtkWidget *widget,
cairo_t *cr)
static void
sysprof_visualizer_ticks_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
SysprofVisualizerTicks *self = SYSPROF_VISUALIZER_TICKS (widget);
GtkStyleContext *style;
GtkAllocation alloc;
GtkStateFlags state;
gint64 timespan;
GdkRGBA color;
g_assert (SYSPROF_IS_VISUALIZER_TICKS (self));
g_assert (cr != NULL);
g_assert (snapshot != NULL);
timespan = sysprof_visualizer_get_duration (SYSPROF_VISUALIZER (self));
if (timespan == 0)
return GDK_EVENT_PROPAGATE;
style = gtk_widget_get_style_context (widget);
return;
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
alloc.x = 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_style_context_get_color (style, state, &color);
gdk_cairo_set_source_rgba (cr, &color);
gtk_snapshot_render_background (snapshot, style, 0, 0, alloc.width, alloc.height);
/*
* 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--)
{
if (draw_ticks (self, cr, &alloc, j - 1, FALSE))
if (draw_ticks (self, snapshot, &alloc, j - 1, FALSE, &color))
largest_match = j - 1;
}
if (largest_match != -1)
draw_ticks (self, cr, &alloc, largest_match, TRUE);
draw_ticks (self, snapshot, &alloc, largest_match, TRUE, &color);
break;
}
return GDK_EVENT_PROPAGATE;
}
static void
sysprof_visualizer_ticks_get_preferred_height (GtkWidget *widget,
gint *min_height,
gint *nat_height)
sysprof_visualizer_ticks_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
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
@ -300,8 +306,8 @@ sysprof_visualizer_ticks_class_init (SysprofVisualizerTicksClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->draw = sysprof_visualizer_ticks_draw;
widget_class->get_preferred_height = sysprof_visualizer_ticks_get_preferred_height;
widget_class->snapshot = sysprof_visualizer_ticks_snapshot;
widget_class->measure = sysprof_visualizer_ticks_measure;
gtk_widget_class_set_css_name (widget_class, "SysprofVisualizerTicks");
}

View File

@ -31,14 +31,9 @@ typedef struct
gint64 begin_time;
gint64 end_time;
gint64 duration;
/* A cached allocation that has the borders subtracted so that
* we place the content within the expected area.
*/
GtkAllocation cache_alloc;
} SysprofVisualizerPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizer, sysprof_visualizer, DZL_TYPE_BIN)
G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizer, sysprof_visualizer, GTK_TYPE_WIDGET)
enum {
PROP_0,
@ -50,53 +45,6 @@ enum {
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
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->set_property = sysprof_visualizer_set_property;
widget_class->size_allocate = sysprof_visualizer_size_allocate;
properties [PROP_BEGIN_TIME] =
g_param_spec_int64 ("begin-time",
"Begin Time",
@ -296,20 +242,21 @@ sysprof_visualizer_translate_points (SysprofVisualizer *self,
SysprofVisualizerAbsolutePoint *out_points,
guint n_out_points)
{
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
const GtkAllocation *a;
int width;
int height;
g_return_if_fail (SYSPROF_IS_VISUALIZER (self));
g_return_if_fail (in_points != NULL);
g_return_if_fail (out_points != NULL);
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++)
{
out_points[i].x = (in_points[i].x * a->width);
out_points[i].y = a->height - (ABS (in_points[i].y) * a->height);
out_points[i].x = (in_points[i].x * width);
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);
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

View File

@ -24,7 +24,7 @@
# error "Only <sysprof-ui.h> can be included directly."
#endif
#include <dazzle.h>
#include <gtk/gtk.h>
#include <sysprof.h>
G_BEGIN_DECLS
@ -44,11 +44,11 @@ typedef struct
#define SYSPROF_TYPE_VISUALIZER (sysprof_visualizer_get_type())
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
{
DzlBinClass parent_class;
GtkWidgetClass parent_class;
void (*set_reader) (SysprofVisualizer *self,
SysprofCaptureReader *reader);

View File

@ -30,7 +30,7 @@
struct _SysprofVisualizersFrame
{
GtkBin parent_instance;
GtkWidget parent_instance;
/* Drag selection tracking */
SysprofSelection *selection;
@ -65,13 +65,14 @@ typedef struct
{
GtkListBox *list;
GtkStyleContext *style_context;
cairo_t *cr;
GtkAllocation alloc;
GtkSnapshot *snapshot;
int width;
int height;
gint64 begin_time;
gint64 duration;
} SelectionDraw;
G_DEFINE_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, GTK_TYPE_BIN)
G_DEFINE_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, GTK_TYPE_WIDGET)
enum {
PROP_0,
@ -115,16 +116,16 @@ draw_selection_cb (SysprofSelection *selection,
g_assert (SYSPROF_IS_SELECTION (selection));
g_assert (draw != NULL);
g_assert (draw->cr != NULL);
g_assert (draw->snapshot != NULL);
g_assert (GTK_IS_LIST_BOX (draw->list));
x = (range_begin - draw->begin_time) / (gdouble)draw->duration;
x2 = (range_end - draw->begin_time) / (gdouble)draw->duration;
area.x = x * draw->alloc.width;
area.width = (x2 * draw->alloc.width) - area.x;
area.x = x * draw->width;
area.width = (x2 * draw->width) - area.x;
area.y = 0;
area.height = draw->alloc.height;
area.height = draw->height;
if (area.width < 0)
{
@ -132,104 +133,106 @@ draw_selection_cb (SysprofSelection *selection,
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
visualizers_draw_after_cb (SysprofVisualizersFrame *self,
cairo_t *cr,
GtkListBox *list)
static void
sysprof_visualizers_frame_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)widget;
SelectionDraw draw;
GtkAllocation alloc;
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));
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)
{
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");
sysprof_selection_foreach (self->selection, draw_selection_cb, &draw);
if (self->button_pressed)
draw_selection_cb (self->selection, self->drag_begin_at, self->drag_selection_at, &draw);
gtk_style_context_remove_class (draw.style_context, "selection");
}
return GDK_EVENT_PROPAGATE;
gtk_snapshot_restore (snapshot);
}
}
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,
GdkEventButton *ev,
GtkListBox *visualizers)
int n_presses,
double x,
double y,
GtkGestureClick *gesture)
{
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (ev != NULL);
g_assert (GTK_IS_LIST_BOX (visualizers));
GdkModifierType state;
guint button;
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))
{
sysprof_selection_unselect_all (self->selection);
return GDK_EVENT_STOP;
}
return GDK_EVENT_PROPAGATE;
sysprof_selection_unselect_all (self->selection);
return;
}
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);
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;
gtk_widget_queue_draw (GTK_WIDGET (visualizers));
return GDK_EVENT_PROPAGATE;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static gboolean
static void
visualizers_button_release_event_cb (SysprofVisualizersFrame *self,
GdkEventButton *ev,
GtkListBox *list)
int n_release,
double x,
double y,
GtkGestureClick *gesture)
{
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (ev != NULL);
g_assert (GTK_IS_LIST_BOX (list));
guint button;
if (!self->button_pressed || ev->button != GDK_BUTTON_PRIMARY)
return GDK_EVENT_PROPAGATE;
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 (!self->button_pressed || button != GDK_BUTTON_PRIMARY)
return;
self->button_pressed = FALSE;
@ -242,46 +245,33 @@ visualizers_button_release_event_cb (SysprofVisualizersFrame *self,
self->drag_selection_at = -1;
}
gtk_widget_queue_draw (GTK_WIDGET (list));
return GDK_EVENT_STOP;
gtk_widget_queue_draw (GTK_WIDGET (self));
}
static gboolean
visualizers_motion_notify_event_cb (SysprofVisualizersFrame *self,
GdkEventMotion *ev,
GtkListBox *list)
static void
visualizers_motion_notify_event_cb (SysprofVisualizersFrame *self,
double x,
double y,
GtkEventControllerMotion *motion)
{
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (ev != NULL);
g_assert (GTK_IS_LIST_BOX (list));
g_assert (GTK_IS_EVENT_CONTROLLER_MOTION (motion));
if (!self->button_pressed)
return GDK_EVENT_PROPAGATE;
self->drag_selection_at = get_time_from_x (self, ev->x);
gtk_widget_queue_draw (GTK_WIDGET (list));
return GDK_EVENT_PROPAGATE;
if (self->button_pressed)
{
self->drag_selection_at = get_time_from_x (self, x);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
}
static void
set_children_width_request_cb (GtkWidget *widget,
gpointer data)
set_children_width_request (GtkWidget *widget,
int width)
{
gtk_widget_set_size_request (widget, GPOINTER_TO_INT (data), -1);
}
static void
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));
for (GtkWidget *child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
gtk_widget_set_size_request (child, width, -1);
}
static void
@ -297,8 +287,8 @@ sysprof_visualizers_frame_notify_zoom (SysprofVisualizersFrame *self,
duration = self->end_time - self->begin_time;
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_CONTAINER (self->visualizers_viewport), data_width);
set_children_width_request (GTK_WIDGET (self->ticks_viewport), data_width);
set_children_width_request (GTK_WIDGET (self->visualizers_viewport), data_width);
}
static gint
@ -306,17 +296,16 @@ find_pos (SysprofVisualizersFrame *self,
const gchar *title,
gint priority)
{
GList *list;
gint pos = 0;
if (title == NULL)
return -1;
list = gtk_container_get_children (GTK_CONTAINER (self->visualizers));
for (const GList *iter = list; iter; iter = iter->next)
for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->visualizers));
child;
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);
const gchar *item = sysprof_visualizer_group_get_title (group);
@ -327,41 +316,34 @@ find_pos (SysprofVisualizersFrame *self,
pos++;
}
g_list_free (list);
return pos;
}
static void
sysprof_visualizers_frame_add (GtkContainer *container,
GtkWidget *child)
void
sysprof_visualizers_frame_add_group (SysprofVisualizersFrame *self,
SysprofVisualizerGroup *group)
{
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)container;
SysprofVisualizerGroupHeader *header;
const char *title;
int priority;
int pos;
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_assert (GTK_IS_WIDGET (child));
g_return_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self));
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (group));
if (SYSPROF_IS_VISUALIZER_GROUP (child))
{
SysprofVisualizerGroupHeader *header;
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);
title = sysprof_visualizer_group_get_title (group);
priority = sysprof_visualizer_group_get_priority (group);
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 ();
g_object_set_data (G_OBJECT (header), "VISUALIZER_GROUP", child);
gtk_list_box_insert (self->groups, GTK_WIDGET (header), pos);
_sysprof_visualizer_group_set_header (SYSPROF_VISUALIZER_GROUP (child), header);
gtk_widget_show (GTK_WIDGET (header));
header = _sysprof_visualizer_group_header_new ();
g_object_set_data (G_OBJECT (header), "VISUALIZER_GROUP", group);
gtk_list_box_insert (self->groups, GTK_WIDGET (header), pos);
_sysprof_visualizer_group_set_header (group, header);
gtk_widget_show (GTK_WIDGET (header));
sysprof_visualizers_frame_notify_zoom (self, NULL, self->zoom_manager);
return;
}
GTK_CONTAINER_CLASS (sysprof_visualizers_frame_parent_class)->add (container, child);
sysprof_visualizers_frame_notify_zoom (self, NULL, self->zoom_manager);
}
static void
@ -392,27 +374,17 @@ sysprof_visualizers_frame_group_activated_cb (SysprofVisualizersFrame *self
}
static void
sysprof_visualizers_frame_size_allocate (GtkWidget *widget,
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)
sysprof_visualizers_frame_dispose (GObject *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_OBJECT_CLASS (sysprof_visualizers_frame_parent_class)->finalize (object);
G_OBJECT_CLASS (sysprof_visualizers_frame_parent_class)->dispose (object);
}
static void
@ -443,16 +415,14 @@ sysprof_visualizers_frame_class_init (SysprofVisualizersFrameClass *klass)
{
GObjectClass *object_class = G_OBJECT_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;
widget_class->size_allocate = sysprof_visualizers_frame_size_allocate;
container_class->add = sysprof_visualizers_frame_add;
widget_class->snapshot = sysprof_visualizers_frame_snapshot;
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_bind_template_child (widget_class, SysprofVisualizersFrame, groups);
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, hscrollbar);
@ -491,18 +461,43 @@ sysprof_visualizers_frame_class_init (SysprofVisualizersFrameClass *klass)
static void
sysprof_visualizers_frame_init (SysprofVisualizersFrame *self)
{
GtkEventController *controller;
GtkAdjustment *hadj;
GtkAdjustment *zadj;
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);
zadj = sysprof_zoom_manager_get_adjustment (self->zoom_manager);
hadj = gtk_scrolled_window_get_hadjustment (self->hscroller);
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_widget_insert_action_group (GTK_WIDGET (self),
@ -521,36 +516,6 @@ sysprof_visualizers_frame_init (SysprofVisualizersFrame *self)
self,
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,
"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);
return gtk_range_get_adjustment (GTK_RANGE (self->hscrollbar));
return sysprof_scrollmap_get_adjustment (self->hscrollbar);
}
void

View File

@ -30,8 +30,10 @@ G_BEGIN_DECLS
#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);
SysprofVisualizerGroup *sysprof_visualizers_frame_get_selected_group (SysprofVisualizersFrame *self);
SysprofZoomManager *sysprof_visualizers_frame_get_zoom_manager (SysprofVisualizersFrame *self);

View File

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

View File

@ -1,4 +1,5 @@
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 = 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')
sysprof_sources = [
'egg-binding-group.c',
'sysprof.c',
'sysprof-application.c',
'sysprof-window.c',
'sysprof-window-settings.c',
]
sysprof_resources = gnome.compile_resources('sysprof-resources', 'sysprof.gresource.xml',
@ -18,6 +18,7 @@ sysprof_deps = [
libsysprof_dep,
libsysprof_ui_dep,
dependency('pangoft2', required: false),
dependency('libadwaita-1'),
]
sysprof = executable('sysprof', sysprof_resources + sysprof_sources,

View File

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

View File

@ -18,13 +18,13 @@
#pragma once
#include <dazzle.h>
#include <adwaita.h>
G_BEGIN_DECLS
#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);

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 <sysprof-ui.h>
#include "egg-binding-group.h"
#include "sysprof-window.h"
struct _SysprofWindow
{
DzlApplicationWindow parent_instance;
AdwApplicationWindow parent_instance;
DzlBindingGroup *bindings;
EggBindingGroup *bindings;
SysprofNotebook *notebook;
GtkButton *open_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:
@ -63,9 +65,11 @@ sysprof_window_notify_can_replay_cb (SysprofWindow *self,
g_assert (SYSPROF_IS_WINDOW (self));
g_assert (SYSPROF_IS_NOTEBOOK (notebook));
#if 0
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "replay-capture",
"enabled", sysprof_notebook_get_can_replay (notebook),
NULL);
#endif
}
static void
@ -76,9 +80,11 @@ sysprof_window_notify_can_save_cb (SysprofWindow *self,
g_assert (SYSPROF_IS_WINDOW (self));
g_assert (SYSPROF_IS_NOTEBOOK (notebook));
#if 0
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "save-capture",
"enabled", sysprof_notebook_get_can_save (notebook),
NULL);
#endif
}
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));
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
@ -114,20 +120,17 @@ close_tab_cb (GSimpleAction *action,
gpointer user_data)
{
SysprofWindow *self = user_data;
GtkNotebook *notebook;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
notebook = GTK_NOTEBOOK (self->notebook);
if (gtk_notebook_get_n_pages (notebook) == 1)
if (sysprof_notebook_get_n_pages (self->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) &&
sysprof_display_is_empty (SYSPROF_DISPLAY (child)))
{
gtk_widget_destroy (GTK_WIDGET (self));
gtk_window_destroy (GTK_WINDOW (self));
return;
}
}
@ -175,7 +178,7 @@ sysprof_window_finalize (GObject *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_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, 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_DISPLAY);
}
@ -201,7 +215,6 @@ sysprof_window_class_init (SysprofWindowClass *klass)
static void
sysprof_window_init (SysprofWindow *self)
{
DzlShortcutController *controller;
static GActionEntry actions[] = {
{ "close-tab", close_tab_cb },
{ "new-tab", new_tab_cb },
@ -210,9 +223,13 @@ sysprof_window_init (SysprofWindow *self)
{ "save-capture", save_capture_cb },
{ "stop-recording", stop_recording_cb },
};
GMenu *menu;
gtk_widget_init_template (GTK_WIDGET (self));
menu = gtk_application_get_menu_by_id (GTK_APPLICATION (g_application_get_default ()), "win-menu");
gtk_menu_button_set_menu_model (self->menu_button, G_MENU_MODEL (menu));
g_action_map_add_action_entries (G_ACTION_MAP (self),
actions,
G_N_ELEMENTS (actions),
@ -230,24 +247,20 @@ sysprof_window_init (SysprofWindow *self)
self,
G_CONNECT_SWAPPED);
self->bindings = dzl_binding_group_new ();
dzl_binding_group_bind (self->bindings, "title", self, "title", G_BINDING_SYNC_CREATE);
self->bindings = egg_binding_group_new ();
egg_binding_group_bind (self->bindings, "title", self, "title", G_BINDING_SYNC_CREATE);
g_object_bind_property (self->notebook, "current", self->bindings, "source",
G_BINDING_SYNC_CREATE);
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");
#if 0
/* Switch to using gtk_widget_action_set_enabled() */
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "save-capture",
"enabled", FALSE,
NULL);
dzl_gtk_widget_action_set (GTK_WIDGET (self), "win", "replay-capture",
"enabled", FALSE,
NULL);
#endif
}
void
@ -260,12 +273,30 @@ sysprof_window_open (SysprofWindow *self,
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
sysprof_window_open_from_dialog (SysprofWindow *self)
{
GtkFileChooserNative *dialog;
GtkFileFilter *filter;
gint response;
g_return_if_fail (SYSPROF_IS_WINDOW (self));
@ -278,8 +309,6 @@ sysprof_window_open_from_dialog (SysprofWindow *self)
/* Translators: This is a button. */
_("Cancel"));
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Sysprof Captures"));
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_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)
{
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));
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
void
@ -312,8 +337,6 @@ sysprof_window_new_tab (SysprofWindow *self)
g_return_if_fail (SYSPROF_IS_WINDOW (self));
display = sysprof_display_new ();
page = gtk_notebook_insert_page (GTK_NOTEBOOK (self->notebook), display, NULL, -1);
gtk_widget_show (display);
gtk_notebook_set_current_page (GTK_NOTEBOOK (self->notebook), page);
page = sysprof_notebook_append (self->notebook, SYSPROF_DISPLAY (display));
sysprof_notebook_set_current_page (self->notebook, page);
}

View File

@ -20,7 +20,7 @@
#pragma once
#include <dazzle.h>
#include <adwaita.h>
#include "sysprof-application.h"
@ -28,7 +28,7 @@ G_BEGIN_DECLS
#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);
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 -->
<file compressed="true">theme/shared.css</file>
<file compressed="true">theme/Adwaita-shared.css</file>
</gresource>
<!-- UI Files -->
<file preprocess="xml-stripblanks">ui/sysprof-window.ui</file>
<gresource prefix="/org/gnome/sysprof/ui">
<file preprocess="xml-stripblanks">sysprof-window.ui</file>
</gresource>
</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 {
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 = [
libsysprof_dep,
libsysprof_ui_dep,
dependency('gtk+-3.0', version: gtk_req_version),
dependency('libdazzle-1.0', version: dazzle_req_version, fallback: ['libdazzle', 'libdazzle_dep']),
dependency('gtk4', version: gtk_req_version),
dependency('pangoft2', required: false),
]

View File

@ -28,8 +28,9 @@ main (gint argc,
SysprofDisplay *view;
SysprofCaptureReader *reader;
g_autoptr(GError) error = NULL;
GMainLoop *main_loop;
gtk_init (&argc, &argv);
gtk_init ();
if (argc != 2)
{
@ -43,6 +44,8 @@ main (gint argc,
return 1;
}
main_loop = g_main_loop_new (NULL, FALSE);
window = g_object_new (GTK_TYPE_WINDOW,
"title", "SysprofDisplay",
"default-width", 800,
@ -51,13 +54,13 @@ main (gint argc,
view = g_object_new (SYSPROF_TYPE_DISPLAY,
"visible", TRUE,
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);
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_main ();
g_main_loop_run (main_loop);
return 0;
}

View File

@ -18,11 +18,11 @@ filter_cb (GObject *object,
const gchar *needle = user_data;
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
on_entry_changed (GtkEntry *entry,
on_entry_changed (GtkEntry *entry,
SysprofModelFilter *filter)
{
const gchar *text;
@ -30,10 +30,10 @@ on_entry_changed (GtkEntry *entry,
g_assert (GTK_IS_ENTRY (entry));
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);
//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
@ -46,8 +46,11 @@ main (gint argc,
GtkWidget *box;
GtkWidget *scroller;
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,
"title", "Sysprof Process List",
@ -59,23 +62,24 @@ main (gint argc,
"orientation", GTK_ORIENTATION_VERTICAL,
"visible", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (window), box);
gtk_window_set_child (GTK_WINDOW (window), box);
entry = g_object_new (GTK_TYPE_ENTRY,
"visible", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (box), entry);
gtk_box_append (GTK_BOX (box), entry);
scroller = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
"visible", TRUE,
"expand", TRUE,
"vexpand", TRUE,
"hexpand", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (box), scroller);
gtk_box_append (GTK_BOX (box), scroller);
list = g_object_new (GTK_TYPE_LIST_BOX,
"visible", TRUE,
NULL);
gtk_container_add (GTK_CONTAINER (scroller), list);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scroller), list);
model = sysprof_process_model_new ();
sysprof_process_model_set_no_proxy (model, TRUE);
@ -87,9 +91,9 @@ main (gint argc,
G_CALLBACK (on_entry_changed),
filter);
g_signal_connect_swapped (window, "close-request", G_CALLBACK (g_main_loop_quit), main_loop);
gtk_window_present (GTK_WINDOW (window));
g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
gtk_main ();
g_main_loop_run (main_loop);
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