mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
libsysprof-ui: land new UI design
This comprises a massive rewrite of the UI for browsing captures. We use the SysprofAid class to scan capture files for content and then auto- matically add visualizers and details pages. To avoid breaking things incrementally, we just land this as a very large commit. Not necessarily ideal, but given the amount of stuff that could break, this is easier. As part of this process, we're removing a lot of the surface API so that we can limit how much we need to maintain in terms of ABI.
This commit is contained in:
89
src/libsysprof-ui/css/SysprofDisplay-shared.css
Normal file
89
src/libsysprof-ui/css/SysprofDisplay-shared.css
Normal file
@ -0,0 +1,89 @@
|
||||
SysprofDisplay dzlmultipaned {
|
||||
-DzlMultiPaned-handle-size: 0;
|
||||
}
|
||||
|
||||
SysprofVisualizer {
|
||||
background: @content_view_bg;
|
||||
}
|
||||
SysprofVisualizer:not(:last-child) {
|
||||
border-bottom: 1px solid alpha(@borders, 0.3);
|
||||
}
|
||||
|
||||
SysprofVisualizerGroup {
|
||||
border-bottom: 1px solid @borders;
|
||||
}
|
||||
SysprofVisualizerGroup:last-child {
|
||||
box-shadow: 0 20px 15px 15px alpha(@borders, 0.3);
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame box.horizontal.inline-toolbar {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame scrollbar.horizontal {
|
||||
color: mix(@theme_fg_color, @theme_selected_bg_color, 0.5);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame scrollbar.horizontal contents trough {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame scrollbar.horizontal contents trough slider {
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
padding: 6px;
|
||||
min-height: 14px;
|
||||
background: alpha(@content_view_bg, 0.2);
|
||||
border-radius: 3px;
|
||||
border: 2px solid @theme_selected_bg_color;
|
||||
box-shadow: inset 0 10px 5px alpha(@content_view_bg,.3),
|
||||
inset 0 -15px 5px alpha(@content_view_bg,.1),
|
||||
0px 2px 4px @borders;
|
||||
}
|
||||
|
||||
SysprofVisualizerTicks {
|
||||
color: mix(@theme_fg_color, @borders, 0.5);
|
||||
background-color: @theme_bg_color;
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame list {
|
||||
background-color: @theme_bg_color;
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame list.visualizer-groups row {
|
||||
padding: 0;
|
||||
border-bottom: 1px solid @borders;
|
||||
}
|
||||
SysprofVisualizersFrame list.visualizer-groups row:not(:selected) {
|
||||
background-color: @theme_bg_color;
|
||||
}
|
||||
SysprofVisualizersFrame list.visualizer-groups row:last-child {
|
||||
box-shadow: 0 20px 15px 15px alpha(@borders, 0.3);
|
||||
}
|
||||
|
||||
SysprofVisualizersFrame .left-column .small-button.flat {
|
||||
border-color: transparent;
|
||||
min-height: 8px;
|
||||
min-width: 8px;
|
||||
}
|
||||
SysprofVisualizersFrame .left-column .small-button.flat:checked,
|
||||
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);
|
||||
box-shadow: inset 0 10px 5px alpha(@content_view_bg,.3),
|
||||
inset 0 -15px 5px alpha(@content_view_bg,.1),
|
||||
inset 0 0 1px 1px @theme_selected_bg_color;
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
visualizers list row {
|
||||
background-color: #201f21;
|
||||
background-size: 8px 8px;
|
||||
background-image: repeating-linear-gradient(0deg, #232224, #232224 1px, transparent 1px, transparent 8px),
|
||||
repeating-linear-gradient(-90deg, #232224, #232224 1px, transparent 1px, transparent 8px);
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
visualizers list row {
|
||||
background-color: #f6f7f8;
|
||||
background-size: 8px 8px;
|
||||
background-image: repeating-linear-gradient(0deg, #f0f1f2, #f0f1f2 1px, transparent 1px, transparent 8px),
|
||||
repeating-linear-gradient(-90deg, #f0f1f2, #f0f1f2 1px, transparent 1px, transparent 8px);
|
||||
}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
visualizers.selection {
|
||||
background: none;
|
||||
background-color: alpha(@theme_selected_bg_color, 0.35);
|
||||
box-shadow: 0 0 0 1px @theme_selected_bg_color inset;
|
||||
}
|
||||
visualizers.selection:backdrop {
|
||||
background: none;
|
||||
background-color: alpha(@theme_selected_bg_color, 0.15);
|
||||
border: none;
|
||||
}
|
||||
visualizers list row:not(:first-child) {
|
||||
border-top: 1px solid alpha(@borders, 0.4);
|
||||
}
|
||||
@ -2,9 +2,7 @@
|
||||
<gresources>
|
||||
<gresource prefix="/org/gnome/sysprof">
|
||||
<file compressed="true">css/SysprofEnvironEditor-shared.css</file>
|
||||
<file compressed="true">css/SysprofVisualizerView-shared.css</file>
|
||||
<file compressed="true">css/SysprofVisualizerView-Adwaita.css</file>
|
||||
<file compressed="true">css/SysprofVisualizerView-Adwaita-dark.css</file>
|
||||
<file compressed="true">css/SysprofDisplay-shared.css</file>
|
||||
|
||||
<!-- Application icons -->
|
||||
<file alias="icons/scalable/apps/org.gnome.Sysprof.svg">../../data/icons/scalable/apps/org.gnome.Sysprof.svg</file>
|
||||
@ -14,20 +12,18 @@
|
||||
|
||||
<gresource prefix="/org/gnome/sysprof/ui">
|
||||
<file preprocess="xml-stripblanks">sysprof-aid-icon.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-callgraph-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-capture-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-callgraph-page.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-details-page.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-display.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-details-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-empty-state-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-environ-editor-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-failed-state-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-logs-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-marks-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-logs-page.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-marks-page.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-process-model-row.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-profiler-assistant.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-recording-state-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-tab.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-time-label.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-visualizer-view.ui</file>
|
||||
<file preprocess="xml-stripblanks">sysprof-visualizers-frame.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@ -1,84 +1,71 @@
|
||||
if get_option('enable_gtk') and get_option('libsysprof')
|
||||
|
||||
libsysprof_ui_public_sources = [
|
||||
'sysprof-aid.c',
|
||||
'sysprof-capture-view.c',
|
||||
'sysprof-callgraph-aid.c',
|
||||
'sysprof-callgraph-view.c',
|
||||
'sysprof-check.c',
|
||||
'sysprof-color-cycle.c',
|
||||
'sysprof-cpu-aid.c',
|
||||
'sysprof-cpu-visualizer-row.c',
|
||||
'sysprof-display.c',
|
||||
'sysprof-empty-state-view.c',
|
||||
'sysprof-failed-state-view.c',
|
||||
'sysprof-line-visualizer-row.c',
|
||||
'sysprof-marks-model.c',
|
||||
'sysprof-marks-view.c',
|
||||
'sysprof-mark-visualizer-row.c',
|
||||
'sysprof-memory-aid.c',
|
||||
'sysprof-model-filter.c',
|
||||
'sysprof-notebook.c',
|
||||
'sysprof-page.c',
|
||||
'sysprof-process-model-row.c',
|
||||
'sysprof-proxy-aid.c',
|
||||
'sysprof-profiler-assistant.c',
|
||||
'sysprof-recording-state-view.c',
|
||||
'sysprof-visualizer-list.c',
|
||||
'sysprof-visualizer-row.c',
|
||||
'sysprof-visualizer-ticks.c',
|
||||
'sysprof-visualizer-view.c',
|
||||
'sysprof-visualizer.c',
|
||||
'sysprof-visualizer-group.c',
|
||||
'sysprof-zoom-manager.c',
|
||||
]
|
||||
|
||||
libsysprof_ui_private_sources = [
|
||||
'pointcache.c',
|
||||
'rectangles.c',
|
||||
'sysprof-aid.c',
|
||||
'sysprof-aid-icon.c',
|
||||
'sysprof-details-view.c',
|
||||
'sysprof-battery-aid.c',
|
||||
'sysprof-cairo.c',
|
||||
'sysprof-callgraph-aid.c',
|
||||
'sysprof-callgraph-page.c',
|
||||
'sysprof-cell-renderer-duration.c',
|
||||
'sysprof-cell-renderer-percent.c',
|
||||
'sysprof-depth-visualizer-row.c',
|
||||
'sysprof-environ-editor-row.c',
|
||||
'sysprof-environ-editor.c',
|
||||
'sysprof-environ-variable.c',
|
||||
'sysprof-color-cycle.c',
|
||||
'sysprof-counters-aid.c',
|
||||
'sysprof-cpu-aid.c',
|
||||
'sysprof-depth-visualizer.c',
|
||||
'sysprof-details-page.c',
|
||||
'sysprof-display.c',
|
||||
'sysprof-environ.c',
|
||||
'sysprof-environ-editor.c',
|
||||
'sysprof-environ-editor-row.c',
|
||||
'sysprof-environ-variable.c',
|
||||
'sysprof-failed-state-view.c',
|
||||
'sysprof-line-visualizer.c',
|
||||
'sysprof-log-model.c',
|
||||
'sysprof-logs-view.c',
|
||||
'sysprof-logs-aid.c',
|
||||
'sysprof-logs-page.c',
|
||||
'sysprof-marks-aid.c',
|
||||
'sysprof-marks-model.c',
|
||||
'sysprof-marks-page.c',
|
||||
'sysprof-mark-visualizer.c',
|
||||
'sysprof-memory-aid.c',
|
||||
'sysprof-profiler-assistant.c',
|
||||
'sysprof-proxy-aid.c',
|
||||
'sysprof-recording-state-view.c',
|
||||
'sysprof-scrollmap.c',
|
||||
'sysprof-tab.c',
|
||||
'sysprof-time-label.c',
|
||||
'sysprof-theme-manager.c',
|
||||
'sysprof-time-label.c',
|
||||
'sysprof-time-visualizer.c',
|
||||
'sysprof-visualizer-group-header.c',
|
||||
'sysprof-visualizers-frame.c',
|
||||
'sysprof-visualizer-ticks.c',
|
||||
'../stackstash.c',
|
||||
]
|
||||
|
||||
libsysprof_ui_public_headers = [
|
||||
'sysprof-aid.h',
|
||||
'sysprof-capture-view.h',
|
||||
'sysprof-callgraph-aid.h',
|
||||
'sysprof-callgraph-view.h',
|
||||
'sysprof-cell-renderer-percent.h',
|
||||
'sysprof-check.h',
|
||||
'sysprof-cpu-aid.h',
|
||||
'sysprof-cpu-visualizer-row.h',
|
||||
'sysprof-display.h',
|
||||
'sysprof-empty-state-view.h',
|
||||
'sysprof-failed-state-view.h',
|
||||
'sysprof-line-visualizer-row.h',
|
||||
'sysprof-marks-model.h',
|
||||
'sysprof-marks-view.h',
|
||||
'sysprof-mark-visualizer-row.h',
|
||||
'sysprof-memory-aid.h',
|
||||
'sysprof-model-filter.c',
|
||||
'sysprof-model-filter.h',
|
||||
'sysprof-notebook.h',
|
||||
'sysprof-page.h',
|
||||
'sysprof-process-model-row.h',
|
||||
'sysprof-proxy-aid.h',
|
||||
'sysprof-profiler-assistant.h',
|
||||
'sysprof-recording-state-view.h',
|
||||
'sysprof-visualizer-list.h',
|
||||
'sysprof-visualizer-row.h',
|
||||
'sysprof-visualizer-ticks.h',
|
||||
'sysprof-visualizer-view.h',
|
||||
'sysprof-visualizer.h',
|
||||
'sysprof-visualizer-group.h',
|
||||
'sysprof-zoom-manager.h',
|
||||
'sysprof-ui.h',
|
||||
]
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
#include "rectangles.h"
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -153,18 +153,18 @@ rectangles_draw (Rectangles *self,
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
gdouble range;
|
||||
guint n_rows;
|
||||
guint ns;
|
||||
|
||||
g_assert (self != NULL);
|
||||
g_assert (SYSPROF_IS_VISUALIZER_ROW (row));
|
||||
g_assert (SYSPROF_IS_VISUALIZER (row));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
if (!self->sorted)
|
||||
rectangles_sort (self);
|
||||
|
||||
gtk_widget_get_allocation (row, &alloc);
|
||||
n_rows = g_hash_table_size (self->y_indexes);
|
||||
if (n_rows == 0 || alloc.height == 0)
|
||||
ns = g_hash_table_size (self->y_indexes);
|
||||
if (ns == 0 || alloc.height == 0)
|
||||
return;
|
||||
|
||||
range = self->end_time - self->begin_time;
|
||||
@ -173,24 +173,24 @@ rectangles_draw (Rectangles *self,
|
||||
{
|
||||
Rectangle *rect = &g_array_index (self->rectangles, Rectangle, i);
|
||||
guint y_index = GPOINTER_TO_UINT (g_hash_table_lookup (self->y_indexes, rect->name));
|
||||
SysprofVisualizerRowRelativePoint in_points[2];
|
||||
SysprofVisualizerRowAbsolutePoint out_points[2];
|
||||
SysprofVisualizerRelativePoint in_points[2];
|
||||
SysprofVisualizerAbsolutePoint out_points[2];
|
||||
GdkRectangle r;
|
||||
GdkRGBA *rgba;
|
||||
|
||||
g_assert (y_index > 0);
|
||||
g_assert (y_index <= n_rows);
|
||||
g_assert (y_index <= ns);
|
||||
|
||||
in_points[0].x = (rect->begin - self->begin_time) / range;
|
||||
in_points[0].y = (y_index - 1) / (gdouble)n_rows;
|
||||
in_points[0].y = (y_index - 1) / (gdouble)ns;
|
||||
in_points[1].x = (rect->end - self->begin_time) / range;
|
||||
in_points[1].y = 0;
|
||||
|
||||
sysprof_visualizer_row_translate_points (SYSPROF_VISUALIZER_ROW (row),
|
||||
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (row),
|
||||
in_points, G_N_ELEMENTS (in_points),
|
||||
out_points, G_N_ELEMENTS (out_points));
|
||||
|
||||
r.height = alloc.height / (gdouble)n_rows;
|
||||
r.height = alloc.height / (gdouble)ns;
|
||||
r.x = out_points[0].x;
|
||||
r.y = out_points[0].y - r.height;
|
||||
|
||||
|
||||
@ -49,6 +49,29 @@ enum {
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void
|
||||
sysprof_aid_real_present_async (SysprofAid *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_task_report_new_error (self, callback, user_data,
|
||||
sysprof_aid_real_present_async,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_SUPPORTED,
|
||||
"Not supported");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_aid_real_present_finish (SysprofAid *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_aid_finalize (GObject *object)
|
||||
{
|
||||
@ -121,6 +144,9 @@ sysprof_aid_class_init (SysprofAidClass *klass)
|
||||
object_class->get_property = sysprof_aid_get_property;
|
||||
object_class->set_property = sysprof_aid_set_property;
|
||||
|
||||
klass->present_async = sysprof_aid_real_present_async;
|
||||
klass->present_finish = sysprof_aid_real_present_finish;
|
||||
|
||||
properties [PROP_DISPLAY_NAME] =
|
||||
g_param_spec_string ("display-name",
|
||||
"Display Name",
|
||||
@ -146,7 +172,7 @@ sysprof_aid_class_init (SysprofAidClass *klass)
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_aid_init (SysprofAid *self)
|
||||
sysprof_aid_init (SysprofAid *self G_GNUC_UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
@ -258,10 +284,10 @@ sysprof_aid_prepare (SysprofAid *self,
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_aid_add_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *object,
|
||||
const gchar *type)
|
||||
sysprof_aid_add_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *object,
|
||||
const gchar *type G_GNUC_UNUSED)
|
||||
{
|
||||
SysprofAid *self = (SysprofAid *)buildable;
|
||||
SysprofAidPrivate *priv = sysprof_aid_get_instance_private (self);
|
||||
@ -298,3 +324,30 @@ sysprof_aid_new (const gchar *display_name,
|
||||
"icon-name", icon_name,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_aid_present_async (SysprofAid *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_AID (self));
|
||||
g_return_if_fail (reader != NULL);
|
||||
g_return_if_fail (SYSPROF_IS_DISPLAY (display));
|
||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
SYSPROF_AID_GET_CLASS (self)->present_async (self, reader, display, cancellable, callback, user_data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
sysprof_aid_present_finish (SysprofAid *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_AID (self), FALSE);
|
||||
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
|
||||
|
||||
return SYSPROF_AID_GET_CLASS (self)->present_finish (self, result, error);
|
||||
}
|
||||
|
||||
@ -20,49 +20,57 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-display.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_AID (sysprof_aid_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofAid, sysprof_aid, SYSPROF, AID, GObject)
|
||||
|
||||
struct _SysprofAidClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*prepare) (SysprofAid *self,
|
||||
SysprofProfiler *profiler);
|
||||
void (*prepare) (SysprofAid *self,
|
||||
SysprofProfiler *profiler);
|
||||
void (*present_async) (SysprofAid *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean (*present_finish) (SysprofAid *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/*< gpointer >*/
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofAid *sysprof_aid_new (const gchar *display_name,
|
||||
const gchar *icon_name);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
const gchar *sysprof_aid_get_display_name (SysprofAid *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_aid_set_display_name (SysprofAid *self,
|
||||
const gchar *display_name);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GIcon *sysprof_aid_get_icon (SysprofAid *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_aid_set_icon (SysprofAid *self,
|
||||
GIcon *icon);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_aid_set_icon_name (SysprofAid *self,
|
||||
const gchar *icon_name);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_aid_prepare (SysprofAid *self,
|
||||
SysprofProfiler *profiler);
|
||||
SysprofAid *sysprof_aid_new (const gchar *display_name,
|
||||
const gchar *icon_name);
|
||||
const gchar *sysprof_aid_get_display_name (SysprofAid *self);
|
||||
void sysprof_aid_set_display_name (SysprofAid *self,
|
||||
const gchar *display_name);
|
||||
GIcon *sysprof_aid_get_icon (SysprofAid *self);
|
||||
void sysprof_aid_set_icon (SysprofAid *self,
|
||||
GIcon *icon);
|
||||
void sysprof_aid_set_icon_name (SysprofAid *self,
|
||||
const gchar *icon_name);
|
||||
void sysprof_aid_prepare (SysprofAid *self,
|
||||
SysprofProfiler *profiler);
|
||||
void sysprof_aid_present_async (SysprofAid *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean sysprof_aid_present_finish (SysprofAid *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
239
src/libsysprof-ui/sysprof-battery-aid.c
Normal file
239
src/libsysprof-ui/sysprof-battery-aid.c
Normal file
@ -0,0 +1,239 @@
|
||||
/* sysprof-battery-aid.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-battery-aid"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-battery-aid.h"
|
||||
#include "sysprof-line-visualizer.h"
|
||||
|
||||
struct _SysprofBatteryAid
|
||||
{
|
||||
SysprofAid parent_instance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureCursor *cursor;
|
||||
SysprofDisplay *display;
|
||||
} Present;
|
||||
|
||||
G_DEFINE_TYPE (SysprofBatteryAid, sysprof_battery_aid, SYSPROF_TYPE_AID)
|
||||
|
||||
static void
|
||||
present_free (gpointer data)
|
||||
{
|
||||
Present *p = data;
|
||||
|
||||
g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_object (&p->display);
|
||||
g_slice_free (Present, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_battery_aid_new:
|
||||
*
|
||||
* Create a new #SysprofBatteryAid.
|
||||
*
|
||||
* Returns: (transfer full): a newly created #SysprofBatteryAid
|
||||
*
|
||||
* Since: 3.34
|
||||
*/
|
||||
SysprofAid *
|
||||
sysprof_battery_aid_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_BATTERY_AID, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_battery_aid_prepare (SysprofAid *self,
|
||||
SysprofProfiler *profiler)
|
||||
{
|
||||
#ifdef __linux__
|
||||
g_autoptr(SysprofSource) source = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_BATTERY_AID (self));
|
||||
g_assert (SYSPROF_IS_PROFILER (profiler));
|
||||
|
||||
source = sysprof_battery_source_new ();
|
||||
sysprof_profiler_add_source (profiler, source);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
collect_battery_counters (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofCaptureCounterDefine *def = (SysprofCaptureCounterDefine *)frame;
|
||||
GArray *counters = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF);
|
||||
g_assert (counters != NULL);
|
||||
|
||||
for (guint i = 0; i < def->n_counters; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *counter = &def->counters[i];
|
||||
|
||||
if (g_strcmp0 (counter->category, "Battery Charge") == 0)
|
||||
g_array_append_vals (counters, counter, 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_battery_aid_present_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Present *present = task_data;
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_BATTERY_AID (source_object));
|
||||
g_assert (present != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
counters = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounter));
|
||||
sysprof_capture_cursor_foreach (present->cursor, collect_battery_counters, counters);
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&counters),
|
||||
(GDestroyNotify) g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_battery_aid_present_async (SysprofAid *aid,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_CTRDEF };
|
||||
g_autoptr(SysprofCaptureCondition) condition = NULL;
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
Present present;
|
||||
|
||||
g_assert (SYSPROF_IS_BATTERY_AID (aid));
|
||||
g_assert (reader != NULL);
|
||||
g_assert (SYSPROF_IS_DISPLAY (display));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
condition = sysprof_capture_condition_new_where_type_in (1, types);
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
present.cursor = g_steal_pointer (&cursor);
|
||||
present.display = g_object_ref (display);
|
||||
|
||||
task = g_task_new (aid, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_battery_aid_present_async);
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Present, &present),
|
||||
present_free);
|
||||
g_task_run_in_thread (task, sysprof_battery_aid_present_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_battery_aid_present_finish (SysprofAid *aid,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
Present *present;
|
||||
|
||||
g_assert (SYSPROF_IS_AID (aid));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
present = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
if ((counters = g_task_propagate_pointer (G_TASK (result), error)))
|
||||
{
|
||||
g_autoptr(SysprofColorCycle) cycle = sysprof_color_cycle_new ();
|
||||
SysprofVisualizerGroup *group;
|
||||
|
||||
group = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"title", _("Battery Charge"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
for (guint i = 0; i < counters->len; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *ctr = &g_array_index (counters, SysprofCaptureCounter, i);
|
||||
|
||||
if (g_strcmp0 (ctr->category, "Battery Charge") == 0)
|
||||
{
|
||||
g_autofree gchar *title = NULL;
|
||||
gboolean is_combined = g_str_equal (ctr->name, "Combined");
|
||||
GtkWidget *row;
|
||||
GdkRGBA rgba;
|
||||
|
||||
if (is_combined)
|
||||
title = g_strdup (_("Battery Charge (All)"));
|
||||
else
|
||||
title = g_strdup_printf ("Battery Charge (%s)", ctr->name);
|
||||
|
||||
row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
"title", title,
|
||||
"height-request", 35,
|
||||
"visible", is_combined,
|
||||
NULL);
|
||||
sysprof_color_cycle_next (cycle, &rgba);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
sysprof_visualizer_group_insert (group,
|
||||
SYSPROF_VISUALIZER (row),
|
||||
is_combined ? 0 : -1,
|
||||
!is_combined);
|
||||
}
|
||||
}
|
||||
|
||||
if (counters->len > 0)
|
||||
sysprof_display_add_group (present->display, group);
|
||||
else
|
||||
gtk_widget_destroy (GTK_WIDGET (group));
|
||||
}
|
||||
|
||||
return counters != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_battery_aid_class_init (SysprofBatteryAidClass *klass)
|
||||
{
|
||||
SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass);
|
||||
|
||||
aid_class->prepare = sysprof_battery_aid_prepare;
|
||||
aid_class->present_async = sysprof_battery_aid_present_async;
|
||||
aid_class->present_finish = sysprof_battery_aid_present_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_battery_aid_init (SysprofBatteryAid *self)
|
||||
{
|
||||
sysprof_aid_set_display_name (SYSPROF_AID (self), _("Battery"));
|
||||
sysprof_aid_set_icon_name (SYSPROF_AID (self), "battery-low-charging-symbolic");
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
/* sysprof-depth-visualizer-row.h
|
||||
/* sysprof-battery-aid.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
@ -20,12 +20,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-aid.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_DEPTH_VISUALIZER_ROW (sysprof_depth_visualizer_row_get_type())
|
||||
#define SYSPROF_TYPE_BATTERY_AID (sysprof_battery_aid_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofDepthVisualizerRow, sysprof_depth_visualizer_row, SYSPROF, DEPTH_VISUALIZER_ROW, SysprofVisualizerRow)
|
||||
G_DECLARE_FINAL_TYPE (SysprofBatteryAid, sysprof_battery_aid, SYSPROF, BATTERY_AID, SysprofAid)
|
||||
|
||||
SysprofAid *sysprof_battery_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
@ -25,14 +25,46 @@
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-callgraph-aid.h"
|
||||
#include "sysprof-callgraph-page.h"
|
||||
#include "sysprof-depth-visualizer.h"
|
||||
|
||||
struct _SysprofCallgraphAid
|
||||
{
|
||||
SysprofAid parent_instance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureCursor *cursor;
|
||||
SysprofDisplay *display;
|
||||
guint has_samples : 1;
|
||||
} Present;
|
||||
|
||||
G_DEFINE_TYPE (SysprofCallgraphAid, sysprof_callgraph_aid, SYSPROF_TYPE_AID)
|
||||
|
||||
static void
|
||||
present_free (gpointer data)
|
||||
{
|
||||
Present *p = data;
|
||||
|
||||
g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_object (&p->display);
|
||||
g_slice_free (Present, p);
|
||||
}
|
||||
|
||||
static void
|
||||
on_group_activated_cb (SysprofVisualizerGroup *group,
|
||||
SysprofPage *page)
|
||||
{
|
||||
SysprofDisplay *display;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_GROUP (group));
|
||||
g_assert (SYSPROF_IS_PAGE (page));
|
||||
|
||||
display = SYSPROF_DISPLAY (gtk_widget_get_ancestor (GTK_WIDGET (page), SYSPROF_TYPE_DISPLAY));
|
||||
sysprof_display_set_visible_page (display, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_callgraph_aid_new:
|
||||
*
|
||||
@ -82,12 +114,157 @@ sysprof_callgraph_aid_prepare (SysprofAid *self,
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
discover_samples_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
Present *p = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (p != NULL);
|
||||
|
||||
if (frame->type == SYSPROF_CAPTURE_FRAME_SAMPLE)
|
||||
{
|
||||
p->has_samples = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_callgraph_aid_present_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Present *p = task_data;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_CALLGRAPH_AID (source_object));
|
||||
g_assert (p != NULL);
|
||||
g_assert (p->cursor != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
/* If we find a sample frame, then we should enable the callgraph
|
||||
* and stack visualizers.
|
||||
*/
|
||||
sysprof_capture_cursor_foreach (p->cursor, discover_samples_cb, p);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_callgraph_aid_present_async (SysprofAid *aid,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_SAMPLE };
|
||||
g_autoptr(SysprofCaptureCondition) condition = NULL;
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
Present present;
|
||||
|
||||
g_assert (SYSPROF_IS_CALLGRAPH_AID (aid));
|
||||
g_assert (reader != NULL);
|
||||
g_assert (SYSPROF_IS_DISPLAY (display));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
condition = sysprof_capture_condition_new_where_type_in (1, types);
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
present.cursor = g_steal_pointer (&cursor);
|
||||
present.display = g_object_ref (display);
|
||||
|
||||
task = g_task_new (aid, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_callgraph_aid_present_async);
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Present, &present),
|
||||
present_free);
|
||||
g_task_run_in_thread (task, sysprof_callgraph_aid_present_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_callgraph_aid_present_finish (SysprofAid *aid,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
Present *p;
|
||||
|
||||
g_assert (SYSPROF_IS_CALLGRAPH_AID (aid));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
p = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
if (p->has_samples)
|
||||
{
|
||||
SysprofVisualizerGroup *group;
|
||||
SysprofVisualizer *depth;
|
||||
SysprofPage *page;
|
||||
|
||||
group = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"has-page", TRUE,
|
||||
"priority", -500,
|
||||
"title", _("Stack Traces"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
depth = sysprof_depth_visualizer_new (SYSPROF_DEPTH_VISUALIZER_COMBINED);
|
||||
g_object_set (depth,
|
||||
"title", _("Stack Traces"),
|
||||
"height-request", 35,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
sysprof_visualizer_group_insert (group, depth, 0, FALSE);
|
||||
|
||||
depth = sysprof_depth_visualizer_new (SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY);
|
||||
g_object_set (depth,
|
||||
"title", _("Stack Traces (In Kernel)"),
|
||||
"height-request", 35,
|
||||
"visible", FALSE,
|
||||
NULL);
|
||||
sysprof_visualizer_group_insert (group, depth, 1, TRUE);
|
||||
|
||||
depth = sysprof_depth_visualizer_new (SYSPROF_DEPTH_VISUALIZER_USER_ONLY);
|
||||
g_object_set (depth,
|
||||
"title", _("Stack Traces (In User)"),
|
||||
"height-request", 35,
|
||||
"visible", FALSE,
|
||||
NULL);
|
||||
sysprof_visualizer_group_insert (group, depth, 2, TRUE);
|
||||
|
||||
sysprof_display_add_group (p->display, group);
|
||||
|
||||
page = g_object_new (SYSPROF_TYPE_CALLGRAPH_PAGE,
|
||||
"title", _("Callgraph"),
|
||||
"vexpand", TRUE,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
sysprof_display_add_page (p->display, page);
|
||||
sysprof_display_set_visible_page (p->display, page);
|
||||
|
||||
g_signal_connect_object (group,
|
||||
"group-activated",
|
||||
G_CALLBACK (on_group_activated_cb),
|
||||
page,
|
||||
0);
|
||||
}
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_callgraph_aid_class_init (SysprofCallgraphAidClass *klass)
|
||||
{
|
||||
SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass);
|
||||
|
||||
aid_class->prepare = sysprof_callgraph_aid_prepare;
|
||||
aid_class->present_async = sysprof_callgraph_aid_present_async;
|
||||
aid_class->present_finish = sysprof_callgraph_aid_present_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -26,10 +26,8 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CALLGRAPH_AID (sysprof_callgraph_aid_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofCallgraphAid, sysprof_callgraph_aid, SYSPROF, CALLGRAPH_AID, SysprofAid)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofAid *sysprof_callgraph_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
1293
src/libsysprof-ui/sysprof-callgraph-page.c
Normal file
1293
src/libsysprof-ui/sysprof-callgraph-page.c
Normal file
File diff suppressed because it is too large
Load Diff
51
src/libsysprof-ui/sysprof-callgraph-page.h
Normal file
51
src/libsysprof-ui/sysprof-callgraph-page.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* sysprof-callgraph-page.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-page.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CALLGRAPH_PAGE (sysprof_callgraph_page_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofCallgraphPage, sysprof_callgraph_page, SYSPROF, CALLGRAPH_PAGE, SysprofPage)
|
||||
|
||||
struct _SysprofCallgraphPageClass
|
||||
{
|
||||
SysprofPageClass parent_class;
|
||||
|
||||
void (*go_previous) (SysprofCallgraphPage *self);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
GtkWidget *sysprof_callgraph_page_new (void);
|
||||
SysprofCallgraphProfile *sysprof_callgraph_page_get_profile (SysprofCallgraphPage *self);
|
||||
void sysprof_callgraph_page_set_profile (SysprofCallgraphPage *self,
|
||||
SysprofCallgraphProfile *profile);
|
||||
gchar *sysprof_callgraph_page_screenshot (SysprofCallgraphPage *self);
|
||||
guint sysprof_callgraph_page_get_n_functions (SysprofCallgraphPage *self);
|
||||
|
||||
G_END_DECLS
|
||||
235
src/libsysprof-ui/sysprof-callgraph-page.ui
Normal file
235
src/libsysprof-ui/sysprof-callgraph-page.ui
Normal file
@ -0,0 +1,235 @@
|
||||
<interface>
|
||||
<template class="SysprofCallgraphPage" parent="SysprofPage">
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="position">450</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<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>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">0</property>
|
||||
<property name="title" translatable="yes">Functions</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="ellipsize">middle</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="function_self_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">1</property>
|
||||
<property name="title" translatable="yes">Self</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererPercent">
|
||||
<property name="width">65</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="percent">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="function_total_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">2</property>
|
||||
<property name="title" translatable="yes">Total</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererPercent">
|
||||
<property name="width">65</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="percent">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</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>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">0</property>
|
||||
<property name="title" translatable="yes">Callers</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="ellipsize">middle</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="callers_self_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">1</property>
|
||||
<property name="title" translatable="yes">Self</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererPercent">
|
||||
<property name="width">65</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="percent">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="callers_total_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">2</property>
|
||||
<property name="title" translatable="yes">Total</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererPercent">
|
||||
<property name="width">65</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="percent">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</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>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="sort-column-id">0</property>
|
||||
<property name="title" translatable="yes">Descendants</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="descendants_self_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">1</property>
|
||||
<property name="title" translatable="yes">Self</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererPercent">
|
||||
<property name="width">65</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="percent">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="descendants_total_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="sort-column-id">2</property>
|
||||
<property name="title" translatable="yes">Total</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererPercent">
|
||||
<property name="width">65</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="percent">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="function_hits_column">
|
||||
<property name="expand">false</property>
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="title" translatable="yes">Hits</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">1.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">4</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">callgraph</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="DzlEmptyState">
|
||||
<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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">loading</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="DzlEmptyState">
|
||||
<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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">empty-state</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@ -20,10 +20,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
@ -31,7 +27,6 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CALLGRAPH_VIEW (sysprof_callgraph_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofCallgraphView, sysprof_callgraph_view, SYSPROF, CALLGRAPH_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofCallgraphViewClass
|
||||
@ -39,20 +34,13 @@ struct _SysprofCallgraphViewClass
|
||||
GtkBinClass parent_class;
|
||||
|
||||
void (*go_previous) (SysprofCallgraphView *self);
|
||||
|
||||
gpointer padding[8];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_callgraph_view_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofCallgraphProfile *sysprof_callgraph_view_get_profile (SysprofCallgraphView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_callgraph_view_set_profile (SysprofCallgraphView *self,
|
||||
SysprofCallgraphProfile *profile);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gchar *sysprof_callgraph_view_screenshot (SysprofCallgraphView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
guint sysprof_callgraph_view_get_n_functions (SysprofCallgraphView *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,75 +0,0 @@
|
||||
/* sysprof-capture-view.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <unknown@domain.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CAPTURE_VIEW (sysprof_capture_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofCaptureView, sysprof_capture_view, SYSPROF, CAPTURE_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofCaptureViewClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
void (*load_async) (SysprofCaptureView *self,
|
||||
SysprofCaptureReader *reader,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean (*load_finish) (SysprofCaptureView *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[32];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_capture_view_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofZoomManager *sysprof_capture_view_get_zoom_manager (SysprofCaptureView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofCaptureReader *sysprof_capture_view_get_reader (SysprofCaptureView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_capture_view_load_async (SysprofCaptureView *self,
|
||||
SysprofCaptureReader *reader,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_capture_view_load_finish (SysprofCaptureView *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_capture_view_get_busy (SysprofCaptureView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_capture_view_fit_to_width (SysprofCaptureView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_capture_view_get_can_replay (SysprofCaptureView *self);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,187 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofCaptureView" parent="GtkBin">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="action-name">zoom.zoom-out</property>
|
||||
<property name="focus-on-click">false</property>
|
||||
<property name="visible">true</property>
|
||||
<property name="tooltip-text" translatable="yes">Zoom Out</property>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="image-button"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">zoom-out-symbolic</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="action-name">capture-view.fit-zoom</property>
|
||||
<property name="focus-on-click">false</property>
|
||||
<property name="tooltip-text" translatable="yes">Resize to Fit</property>
|
||||
<property name="visible">true</property>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="image-button"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="icon-name">zoom-fit-best-symbolic</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="action-name">zoom.zoom-in</property>
|
||||
<property name="focus-on-click">false</property>
|
||||
<property name="tooltip-text" translatable="yes">Zoom In</property>
|
||||
<property name="visible">true</property>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
<class name="image-button"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">zoom-in-symbolic</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="center">
|
||||
<object class="GtkStackSwitcher" id="stack_switcher">
|
||||
<property name="stack">stack</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="visible">true</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="DzlMultiPaned">
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofVisualizerView" id="visualizer_view">
|
||||
<property name="zoom-manager">zoom_manager</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="homogeneous">true</property>
|
||||
<property name="visible">true</property>
|
||||
<property name="vexpand">true</property>
|
||||
<child>
|
||||
<object class="SysprofCallgraphView" id="callgraph_view">
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<!-- translators: the _ is used to denote the accelerator key -->
|
||||
<property name="title" translatable="yes">_Callgraph</property>
|
||||
<property name="name">callgraph</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofMarksView" id="marks_view">
|
||||
<property name="kind">marks</property>
|
||||
<property name="zoom-manager">zoom_manager</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<!-- translators: the _ is used to denote the accelerator key -->
|
||||
<property name="title" translatable="yes">_Timings</property>
|
||||
<property name="name">timings</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofMarksView" id="counters_view">
|
||||
<property name="kind">counters</property>
|
||||
<property name="zoom-manager">zoom_manager</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<!-- translators: the _ is used to denote the accelerator key -->
|
||||
<property name="title" translatable="yes">C_ounters</property>
|
||||
<property name="name">counters</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofLogsView" id="logs_view">
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<!-- translators: the _ is used to denote the accelerator key -->
|
||||
<property name="title" translatable="yes">_Logs</property>
|
||||
<property name="name">logs</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofDetailsView" id="details_view">
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<!-- translators: the _ is used to denote the accelerator key -->
|
||||
<property name="title" translatable="yes">_Details</property>
|
||||
<property name="name">details</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
<object class="SysprofZoomManager" id="zoom_manager"/>
|
||||
<object class="GtkAdjustment" id="time_adj">
|
||||
<property name="step-increment">20</property>
|
||||
</object>
|
||||
</interface>
|
||||
@ -110,7 +110,7 @@ sysprof_cell_renderer_duration_render (GtkCellRenderer *renderer,
|
||||
|
||||
if (r.width > 3)
|
||||
{
|
||||
_sysprof_rounded_rectangle (cr, &r, 2, 2);
|
||||
dzl_cairo_rounded_rectangle (cr, &r, 2, 2);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
else if (r.width > 1)
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-cell-renderer-percent"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
@ -20,14 +20,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "sysprof-version-macros.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CELL_RENDERER_PERCENT (sysprof_cell_renderer_percent_get_type())
|
||||
@ -50,16 +44,13 @@ struct _SysprofCellRendererPercentClass
|
||||
{
|
||||
GtkCellRendererProgressClass parent_class;
|
||||
|
||||
gpointer padding[4];
|
||||
/*< private >*/
|
||||
gpointer _reserved[4];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GType sysprof_cell_renderer_percent_get_type (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkCellRenderer *sysprof_cell_renderer_percent_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gdouble sysprof_cell_renderer_percent_get_percent (SysprofCellRendererPercent *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_cell_renderer_percent_set_percent (SysprofCellRendererPercent *self,
|
||||
gdouble percent);
|
||||
|
||||
|
||||
@ -27,30 +27,47 @@
|
||||
G_DEFINE_BOXED_TYPE (SysprofColorCycle, sysprof_color_cycle, sysprof_color_cycle_ref, sysprof_color_cycle_unref)
|
||||
|
||||
static const gchar *default_colors[] = {
|
||||
"#73d216",
|
||||
"#f57900",
|
||||
"#3465a4",
|
||||
"#ef2929",
|
||||
"#75507b",
|
||||
"#ce5c00",
|
||||
"#c17d11",
|
||||
"#cc0000",
|
||||
"#edd400",
|
||||
"#555753",
|
||||
"#4e9a06",
|
||||
"#204a87",
|
||||
"#5c3566",
|
||||
"#a40000",
|
||||
"#c4a000",
|
||||
"#8f5902",
|
||||
"#2e3436",
|
||||
"#8ae234",
|
||||
"#729fcf",
|
||||
"#ad7fa8",
|
||||
"#fce94f",
|
||||
"#fcaf3e",
|
||||
"#e9b96e",
|
||||
"#888a85",
|
||||
|
||||
"#1a5fb4", /* Blue 5 */
|
||||
"#26a269", /* Green 5 */
|
||||
"#e5a50a", /* Yellow 5 */
|
||||
"#c64600", /* Orange 5 */
|
||||
"#a51d2d", /* Red 5 */
|
||||
"#613583", /* Purple 5 */
|
||||
"#63452c", /* Brown 5 */
|
||||
|
||||
"#1c71d8", /* Blue 4 */
|
||||
"#2ec27e", /* Green 4 */
|
||||
"#f5c211", /* Yellow 4 */
|
||||
"#e66100", /* Orange 4 */
|
||||
"#c01c28", /* Red 4 */
|
||||
"#813d9c", /* Purple 4 */
|
||||
"#865e3c", /* Brown 4 */
|
||||
|
||||
"#3584e4", /* Blue 3 */
|
||||
"#33d17a", /* Green 3 */
|
||||
"#f6d32d", /* Yellow 3 */
|
||||
"#ff7800", /* Orange 3 */
|
||||
"#e01b24", /* Red 3 */
|
||||
"#9141ac", /* Purple 3 */
|
||||
"#986a44", /* Brown 3 */
|
||||
|
||||
"#62a0ea", /* Blue 2 */
|
||||
"#57e389", /* Green 2 */
|
||||
"#f8e45c", /* Yellow 2 */
|
||||
"#ffa348", /* Orange 2 */
|
||||
"#ed333b", /* Red 2 */
|
||||
"#c061cb", /* Purple 2 */
|
||||
"#b5835a", /* Brown 2 */
|
||||
|
||||
"#99c1f1", /* Blue 1 */
|
||||
"#8ff0a4", /* Green 1 */
|
||||
"#f9f06b", /* Yellow 1 */
|
||||
"#ffbe6f", /* Orange 1 */
|
||||
"#f66151", /* Red 1 */
|
||||
"#dc8add", /* Purple 1 */
|
||||
"#cdab8f", /* Brown 1 */
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@ -20,32 +20,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "sysprof-version-macros.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_COLOR_CYCLE (sysprof_color_cycle_get_type())
|
||||
|
||||
typedef struct _SysprofColorCycle SysprofColorCycle;
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GType sysprof_color_cycle_get_type (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofColorCycle *sysprof_color_cycle_ref (SysprofColorCycle *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_color_cycle_unref (SysprofColorCycle *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofColorCycle *sysprof_color_cycle_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_color_cycle_reset (SysprofColorCycle *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_color_cycle_next (SysprofColorCycle *self,
|
||||
GdkRGBA *rgba);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofColorCycle, sysprof_color_cycle_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
248
src/libsysprof-ui/sysprof-counters-aid.c
Normal file
248
src/libsysprof-ui/sysprof-counters-aid.c
Normal file
@ -0,0 +1,248 @@
|
||||
/* sysprof-counters-aid.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-counters-aid"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-counters-aid.h"
|
||||
#include "sysprof-line-visualizer.h"
|
||||
#include "sysprof-marks-page.h"
|
||||
#include "sysprof-time-visualizer.h"
|
||||
|
||||
struct _SysprofCountersAid
|
||||
{
|
||||
SysprofAid parent_instance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureCursor *cursor;
|
||||
SysprofDisplay *display;
|
||||
} Present;
|
||||
|
||||
G_DEFINE_TYPE (SysprofCountersAid, sysprof_counters_aid, SYSPROF_TYPE_AID)
|
||||
|
||||
static void
|
||||
present_free (gpointer data)
|
||||
{
|
||||
Present *p = data;
|
||||
|
||||
g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_object (&p->display);
|
||||
g_slice_free (Present, p);
|
||||
}
|
||||
|
||||
static void
|
||||
on_group_activated_cb (SysprofVisualizerGroup *group,
|
||||
SysprofPage *page)
|
||||
{
|
||||
SysprofDisplay *display;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_GROUP (group));
|
||||
g_assert (SYSPROF_IS_PAGE (page));
|
||||
|
||||
display = SYSPROF_DISPLAY (gtk_widget_get_ancestor (GTK_WIDGET (page), SYSPROF_TYPE_DISPLAY));
|
||||
sysprof_display_set_visible_page (display, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_counters_aid_new:
|
||||
*
|
||||
* Create a new #SysprofCountersAid.
|
||||
*
|
||||
* Returns: (transfer full): a newly created #SysprofCountersAid
|
||||
*
|
||||
* Since: 3.34
|
||||
*/
|
||||
SysprofAid *
|
||||
sysprof_counters_aid_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_COUNTERS_AID, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_counters_aid_prepare (SysprofAid *self,
|
||||
SysprofProfiler *profiler)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
collect_counters (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofCaptureCounterDefine *def = (SysprofCaptureCounterDefine *)frame;
|
||||
GArray *counters = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF);
|
||||
g_assert (counters != NULL);
|
||||
|
||||
if (def->n_counters > 0)
|
||||
g_array_append_vals (counters, def->counters, def->n_counters);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_counters_aid_present_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Present *present = task_data;
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_COUNTERS_AID (source_object));
|
||||
g_assert (present != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
counters = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounter));
|
||||
sysprof_capture_cursor_foreach (present->cursor, collect_counters, counters);
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&counters),
|
||||
(GDestroyNotify) g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_counters_aid_present_async (SysprofAid *aid,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_CTRDEF };
|
||||
g_autoptr(SysprofCaptureCondition) condition = NULL;
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
Present present;
|
||||
|
||||
g_assert (SYSPROF_IS_COUNTERS_AID (aid));
|
||||
g_assert (reader != NULL);
|
||||
g_assert (SYSPROF_IS_DISPLAY (display));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
condition = sysprof_capture_condition_new_where_type_in (1, types);
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
present.cursor = g_steal_pointer (&cursor);
|
||||
present.display = g_object_ref (display);
|
||||
|
||||
task = g_task_new (aid, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_counters_aid_present_async);
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Present, &present),
|
||||
present_free);
|
||||
g_task_run_in_thread (task, sysprof_counters_aid_present_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_counters_aid_present_finish (SysprofAid *aid,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
Present *present;
|
||||
|
||||
g_assert (SYSPROF_IS_AID (aid));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
present = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
if ((counters = g_task_propagate_pointer (G_TASK (result), error)) && counters->len > 0)
|
||||
{
|
||||
g_autoptr(SysprofColorCycle) cycle = sysprof_color_cycle_new ();
|
||||
SysprofVisualizerGroup *group;
|
||||
SysprofVisualizer *combined;
|
||||
GtkWidget *page;
|
||||
|
||||
group = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"has-page", TRUE,
|
||||
"title", _("Counters"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
combined = g_object_new (SYSPROF_TYPE_TIME_VISUALIZER,
|
||||
"title", _("Counters"),
|
||||
"height-request", 35,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
sysprof_visualizer_group_insert (group, combined, -1, TRUE);
|
||||
|
||||
for (guint i = 0; i < counters->len; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *ctr = &g_array_index (counters, SysprofCaptureCounter, i);
|
||||
g_autofree gchar *title = g_strdup_printf ("%s — %s", ctr->category, ctr->name);
|
||||
GtkWidget *row;
|
||||
GdkRGBA rgba;
|
||||
|
||||
row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
"title", title,
|
||||
"height-request", 35,
|
||||
"visible", FALSE,
|
||||
NULL);
|
||||
sysprof_color_cycle_next (cycle, &rgba);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
rgba.alpha = .5;
|
||||
sysprof_line_visualizer_set_fill (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
sysprof_time_visualizer_add_counter (SYSPROF_TIME_VISUALIZER (combined), ctr->id, &rgba);
|
||||
sysprof_visualizer_group_insert (group, SYSPROF_VISUALIZER (row), -1, TRUE);
|
||||
}
|
||||
|
||||
sysprof_display_add_group (present->display, group);
|
||||
|
||||
page = sysprof_marks_page_new (sysprof_display_get_zoom_manager (present->display),
|
||||
SYSPROF_MARKS_MODEL_COUNTERS);
|
||||
gtk_widget_show (page);
|
||||
|
||||
g_signal_connect_object (group,
|
||||
"group-activated",
|
||||
G_CALLBACK (on_group_activated_cb),
|
||||
page,
|
||||
0);
|
||||
sysprof_display_add_page (present->display, SYSPROF_PAGE (page));
|
||||
}
|
||||
|
||||
return counters != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_counters_aid_class_init (SysprofCountersAidClass *klass)
|
||||
{
|
||||
SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass);
|
||||
|
||||
aid_class->prepare = sysprof_counters_aid_prepare;
|
||||
aid_class->present_async = sysprof_counters_aid_present_async;
|
||||
aid_class->present_finish = sysprof_counters_aid_present_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_counters_aid_init (SysprofCountersAid *self)
|
||||
{
|
||||
sysprof_aid_set_display_name (SYSPROF_AID (self), _("Battery"));
|
||||
sysprof_aid_set_icon_name (SYSPROF_AID (self), "org.gnome.Sysprof3-symbolic");
|
||||
}
|
||||
33
src/libsysprof-ui/sysprof-counters-aid.h
Normal file
33
src/libsysprof-ui/sysprof-counters-aid.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* sysprof-counters-aid.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-aid.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_COUNTERS_AID (sysprof_counters_aid_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofCountersAid, sysprof_counters_aid, SYSPROF, COUNTERS_AID, SysprofAid)
|
||||
|
||||
SysprofAid *sysprof_counters_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
@ -24,15 +24,33 @@
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-cpu-aid.h"
|
||||
#include "sysprof-line-visualizer.h"
|
||||
|
||||
struct _SysprofCpuAid
|
||||
{
|
||||
SysprofAid parent_instance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureCursor *cursor;
|
||||
SysprofDisplay *display;
|
||||
} Present;
|
||||
|
||||
G_DEFINE_TYPE (SysprofCpuAid, sysprof_cpu_aid, SYSPROF_TYPE_AID)
|
||||
|
||||
static void
|
||||
present_free (gpointer data)
|
||||
{
|
||||
Present *p = data;
|
||||
|
||||
g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_object (&p->display);
|
||||
g_slice_free (Present, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_cpu_aid_new:
|
||||
*
|
||||
@ -63,12 +81,243 @@ sysprof_cpu_aid_prepare (SysprofAid *self,
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
collect_cpu_counters (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofCaptureCounterDefine *def = (SysprofCaptureCounterDefine *)frame;
|
||||
GArray *counters = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF);
|
||||
g_assert (counters != NULL);
|
||||
|
||||
for (guint i = 0; i < def->n_counters; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *counter = &def->counters[i];
|
||||
|
||||
if (g_strcmp0 (counter->category, "CPU Percent") == 0 ||
|
||||
g_strcmp0 (counter->category, "CPU Frequency") == 0)
|
||||
g_array_append_vals (counters, counter, 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_aid_present_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Present *present = task_data;
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_CPU_AID (source_object));
|
||||
g_assert (present != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
counters = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounter));
|
||||
sysprof_capture_cursor_foreach (present->cursor, collect_cpu_counters, counters);
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&counters),
|
||||
(GDestroyNotify) g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_aid_present_async (SysprofAid *aid,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_CTRDEF };
|
||||
g_autoptr(SysprofCaptureCondition) condition = NULL;
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
Present present;
|
||||
|
||||
g_assert (SYSPROF_IS_CPU_AID (aid));
|
||||
g_assert (reader != NULL);
|
||||
g_assert (SYSPROF_IS_DISPLAY (display));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
condition = sysprof_capture_condition_new_where_type_in (1, types);
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
present.cursor = g_steal_pointer (&cursor);
|
||||
present.display = g_object_ref (display);
|
||||
|
||||
task = g_task_new (aid, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_cpu_aid_present_async);
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Present, &present),
|
||||
present_free);
|
||||
g_task_run_in_thread (task, sysprof_cpu_aid_present_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_cpu_aid_present_finish (SysprofAid *aid,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
Present *present;
|
||||
|
||||
g_assert (SYSPROF_IS_AID (aid));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
present = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
if ((counters = g_task_propagate_pointer (G_TASK (result), error)))
|
||||
{
|
||||
g_autoptr(SysprofColorCycle) cycle = sysprof_color_cycle_new ();
|
||||
g_autoptr(SysprofColorCycle) freq_cycle = sysprof_color_cycle_new ();
|
||||
SysprofVisualizerGroup *usage;
|
||||
SysprofVisualizerGroup *freq;
|
||||
SysprofVisualizer *freq_row = NULL;
|
||||
SysprofVisualizer *over_row = NULL;
|
||||
gboolean found_combined = FALSE;
|
||||
gboolean has_usage = FALSE;
|
||||
gboolean has_freq = FALSE;
|
||||
|
||||
usage = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"priority", -1000,
|
||||
"title", _("CPU Usage"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
freq = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"priority", -999,
|
||||
"title", _("CPU Frequency"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
freq_row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
"title", _("CPU Frequency (All)"),
|
||||
"height-request", 35,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (freq), GTK_WIDGET (freq_row));
|
||||
|
||||
over_row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
"title", _("CPU Usage (All)"),
|
||||
"height-request", 35,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
|
||||
for (guint i = 0; i < counters->len; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *ctr = &g_array_index (counters, SysprofCaptureCounter, i);
|
||||
|
||||
if (g_strcmp0 (ctr->category, "CPU Percent") == 0)
|
||||
{
|
||||
if (strstr (ctr->name, "Combined") != NULL)
|
||||
{
|
||||
GtkWidget *row;
|
||||
GdkRGBA rgba;
|
||||
|
||||
found_combined = TRUE;
|
||||
|
||||
gdk_rgba_parse (&rgba, "#1a5fb4");
|
||||
row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
/* Translators: CPU is the processor. */
|
||||
"title", _("CPU Usage (All)"),
|
||||
"height-request", 35,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
rgba.alpha = 0.5;
|
||||
sysprof_line_visualizer_set_fill (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
sysprof_visualizer_group_insert (usage, SYSPROF_VISUALIZER (row), 0, FALSE);
|
||||
has_usage = TRUE;
|
||||
}
|
||||
else if (g_str_has_prefix (ctr->name, "Total CPU "))
|
||||
{
|
||||
GtkWidget *row;
|
||||
GdkRGBA rgba;
|
||||
|
||||
sysprof_color_cycle_next (cycle, &rgba);
|
||||
row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
"title", ctr->name,
|
||||
"height-request", 35,
|
||||
"visible", FALSE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (over_row), ctr->id, &rgba);
|
||||
rgba.alpha = 0.5;
|
||||
sysprof_line_visualizer_set_fill (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
sysprof_visualizer_group_insert (usage, SYSPROF_VISUALIZER (row), -1, TRUE);
|
||||
has_usage = TRUE;
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (ctr->category, "CPU Frequency") == 0)
|
||||
{
|
||||
if (g_str_has_prefix (ctr->name, "CPU "))
|
||||
{
|
||||
g_autofree gchar *title = g_strdup_printf ("%s Frequency", ctr->name);
|
||||
GtkWidget *row;
|
||||
GdkRGBA rgba;
|
||||
|
||||
sysprof_color_cycle_next (freq_cycle, &rgba);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (freq_row), ctr->id, &rgba);
|
||||
sysprof_line_visualizer_set_dash (SYSPROF_LINE_VISUALIZER (freq_row), ctr->id, TRUE);
|
||||
|
||||
row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER,
|
||||
"title", title,
|
||||
"height-request", 35,
|
||||
"visible", FALSE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
sysprof_line_visualizer_add_counter (SYSPROF_LINE_VISUALIZER (row), ctr->id, &rgba);
|
||||
sysprof_line_visualizer_set_dash (SYSPROF_LINE_VISUALIZER (row), ctr->id, TRUE);
|
||||
sysprof_visualizer_group_insert (freq, SYSPROF_VISUALIZER (row), -1, TRUE);
|
||||
|
||||
has_freq = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_usage && !found_combined)
|
||||
sysprof_visualizer_group_insert (usage, over_row, 0, FALSE);
|
||||
else
|
||||
gtk_widget_destroy (GTK_WIDGET (over_row));
|
||||
|
||||
if (has_usage)
|
||||
sysprof_display_add_group (present->display, usage);
|
||||
else
|
||||
gtk_widget_destroy (GTK_WIDGET (usage));
|
||||
|
||||
if (has_freq)
|
||||
sysprof_display_add_group (present->display, freq);
|
||||
else
|
||||
gtk_widget_destroy (GTK_WIDGET (freq));
|
||||
}
|
||||
|
||||
return counters != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_aid_class_init (SysprofCpuAidClass *klass)
|
||||
{
|
||||
SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass);
|
||||
|
||||
aid_class->prepare = sysprof_cpu_aid_prepare;
|
||||
aid_class->present_async = sysprof_cpu_aid_present_async;
|
||||
aid_class->present_finish = sysprof_cpu_aid_present_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -26,10 +26,8 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CPU_AID (sysprof_cpu_aid_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofCpuAid, sysprof_cpu_aid, SYSPROF, CPU_AID, SysprofAid)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofAid *sysprof_cpu_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -1,239 +0,0 @@
|
||||
/* sysprof-cpu-visualizer-row.c
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-cpu-visualizer-row"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-cpu-visualizer-row.h"
|
||||
|
||||
struct _SysprofCpuVisualizerRow
|
||||
{
|
||||
SysprofLineVisualizerRow parent_instance;
|
||||
SysprofColorCycle *colors;
|
||||
gchar *category;
|
||||
guint use_dash : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CATEGORY,
|
||||
PROP_USE_DASH,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
G_DEFINE_TYPE (SysprofCpuVisualizerRow, sysprof_cpu_visualizer_row, SYSPROF_TYPE_LINE_VISUALIZER_ROW)
|
||||
|
||||
static gboolean
|
||||
sysprof_cpu_visualizer_counter_found (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
const SysprofCaptureCounterDefine *def = (SysprofCaptureCounterDefine *)frame;
|
||||
struct {
|
||||
SysprofCpuVisualizerRow *self;
|
||||
GArray *counters;
|
||||
} *state = user_data;
|
||||
gboolean found = FALSE;
|
||||
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF);
|
||||
g_assert (state != NULL);
|
||||
|
||||
/*
|
||||
* In practice, all the CPU counters are defined at once, so we can avoid
|
||||
* walking the rest of the capture by returning after we find our CTRDEF.
|
||||
*/
|
||||
|
||||
for (guint i = 0; i < def->n_counters; i++)
|
||||
{
|
||||
if (strcmp (def->counters[i].category, state->self->category) == 0 &&
|
||||
strstr (def->counters[i].name, "(Combined)") == NULL)
|
||||
{
|
||||
guint id = def->counters[i].id;
|
||||
g_array_append_val (state->counters, id);
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return !found;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_visualizer_row_discover_counters (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *canellable)
|
||||
{
|
||||
const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_CTRDEF };
|
||||
SysprofCaptureReader *reader = task_data;
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
struct {
|
||||
SysprofCpuVisualizerRow *self;
|
||||
GArray *counters;
|
||||
} state;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_CPU_VISUALIZER_ROW (source_object));
|
||||
g_assert (reader != NULL);
|
||||
|
||||
counters = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
|
||||
state.self = source_object;
|
||||
state.counters = counters;
|
||||
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (cursor, sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types));
|
||||
sysprof_capture_cursor_foreach (cursor, sysprof_cpu_visualizer_counter_found, &state);
|
||||
g_task_return_pointer (task, g_steal_pointer (&counters), (GDestroyNotify)g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_counters (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofCpuVisualizerRow *self = (SysprofCpuVisualizerRow *)object;
|
||||
g_autoptr(GArray) counters = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_CPU_VISUALIZER_ROW (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
counters = g_task_propagate_pointer (G_TASK (result), NULL);
|
||||
|
||||
if (counters != NULL)
|
||||
{
|
||||
for (guint i = 0; i < counters->len; i++)
|
||||
{
|
||||
guint counter_id = g_array_index (counters, guint, i);
|
||||
GdkRGBA color;
|
||||
|
||||
sysprof_color_cycle_next (self->colors, &color);
|
||||
sysprof_line_visualizer_row_add_counter (SYSPROF_LINE_VISUALIZER_ROW (self), counter_id, &color);
|
||||
|
||||
if (self->use_dash)
|
||||
sysprof_line_visualizer_row_set_dash (SYSPROF_LINE_VISUALIZER_ROW (self), counter_id, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide ourself if we failed to locate counters */
|
||||
gtk_widget_set_visible (GTK_WIDGET (self), counters != NULL && counters->len > 0);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_visualizer_row_set_reader (SysprofVisualizerRow *row,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofCpuVisualizerRow *self = (SysprofCpuVisualizerRow *)row;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_CPU_VISUALIZER_ROW (row));
|
||||
|
||||
sysprof_color_cycle_reset (self->colors);
|
||||
|
||||
sysprof_line_visualizer_row_clear (SYSPROF_LINE_VISUALIZER_ROW (row));
|
||||
|
||||
SYSPROF_VISUALIZER_ROW_CLASS (sysprof_cpu_visualizer_row_parent_class)->set_reader (row, reader);
|
||||
|
||||
if (reader != NULL)
|
||||
{
|
||||
task = g_task_new (self, NULL, complete_counters, NULL);
|
||||
g_task_set_source_tag (task, sysprof_cpu_visualizer_row_set_reader);
|
||||
g_task_set_task_data (task, sysprof_capture_reader_copy (reader),
|
||||
(GDestroyNotify)sysprof_capture_reader_unref);
|
||||
g_task_run_in_thread (task, sysprof_cpu_visualizer_row_discover_counters);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_visualizer_row_finalize (GObject *object)
|
||||
{
|
||||
SysprofCpuVisualizerRow *self = (SysprofCpuVisualizerRow *)object;
|
||||
|
||||
g_clear_pointer (&self->colors, sysprof_color_cycle_unref);
|
||||
g_clear_pointer (&self->category, g_free);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_cpu_visualizer_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_visualizer_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofCpuVisualizerRow *self = SYSPROF_CPU_VISUALIZER_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CATEGORY:
|
||||
g_free (self->category);
|
||||
self->category = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_USE_DASH:
|
||||
self->use_dash = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_visualizer_row_class_init (SysprofCpuVisualizerRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
SysprofVisualizerRowClass *row_class = SYSPROF_VISUALIZER_ROW_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_cpu_visualizer_row_finalize;
|
||||
object_class->set_property = sysprof_cpu_visualizer_row_set_property;
|
||||
|
||||
row_class->set_reader = sysprof_cpu_visualizer_row_set_reader;
|
||||
|
||||
properties [PROP_CATEGORY] =
|
||||
g_param_spec_string ("category", NULL, NULL,
|
||||
"CPU Percent",
|
||||
(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_USE_DASH] =
|
||||
g_param_spec_boolean ("use-dash", NULL, NULL,
|
||||
FALSE,
|
||||
(G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_cpu_visualizer_row_init (SysprofCpuVisualizerRow *self)
|
||||
{
|
||||
self->category = g_strdup ("CPU Percent");
|
||||
self->colors = sysprof_color_cycle_new ();
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
sysprof_cpu_visualizer_row_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_CPU_VISUALIZER_ROW, NULL);
|
||||
}
|
||||
@ -1,357 +0,0 @@
|
||||
/* sysprof-depth-visualizer-row.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-depth-visualizer-row"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "pointcache.h"
|
||||
#include "sysprof-depth-visualizer-row.h"
|
||||
|
||||
struct _SysprofDepthVisualizerRow
|
||||
{
|
||||
SysprofVisualizerRow parent_instance;
|
||||
SysprofCaptureReader *reader;
|
||||
PointCache *points;
|
||||
guint reload_source;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
PointCache *pc;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
gint64 duration;
|
||||
guint max_n_addrs;
|
||||
} State;
|
||||
|
||||
G_DEFINE_TYPE (SysprofDepthVisualizerRow, sysprof_depth_visualizer_row, SYSPROF_TYPE_VISUALIZER_ROW)
|
||||
|
||||
static void
|
||||
state_free (State *st)
|
||||
{
|
||||
g_clear_pointer (&st->reader, sysprof_capture_reader_unref);
|
||||
g_clear_pointer (&st->pc, point_cache_unref);
|
||||
g_slice_free (State, st);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
discover_max_n_addr (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
const SysprofCaptureSample *sample = (const SysprofCaptureSample *)frame;
|
||||
State *st = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_SAMPLE);
|
||||
g_assert (st != NULL);
|
||||
|
||||
st->max_n_addrs = MAX (st->max_n_addrs, sample->n_addrs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
build_point_cache_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
const SysprofCaptureSample *sample = (const SysprofCaptureSample *)frame;
|
||||
State *st = user_data;
|
||||
gdouble x, y;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_SAMPLE);
|
||||
g_assert (st != NULL);
|
||||
|
||||
x = (frame->time - st->begin_time) / (gdouble)st->duration;
|
||||
y = sample->n_addrs / (gdouble)st->max_n_addrs;
|
||||
|
||||
/* If this contains a context-switch (meaning we're going into the kernel
|
||||
* to do some work, use a negative value for Y so that we know later on
|
||||
* that we should draw it with a different color (after removing the negation
|
||||
* on the value.
|
||||
*
|
||||
* We skip past the first index, which is always a context switch as it is
|
||||
* our perf handler.
|
||||
*/
|
||||
for (guint i = 1; i < sample->n_addrs; i++)
|
||||
{
|
||||
SysprofAddressContext kind;
|
||||
|
||||
if (sysprof_address_is_context_switch (sample->addrs[i], &kind))
|
||||
{
|
||||
y = -y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
point_cache_add_point_to_set (st->pc, 1, x, y);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_SAMPLE, };
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
SysprofCaptureCondition *condition;
|
||||
State *st = task_data;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER_ROW (source_object));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
if (st->duration != 0)
|
||||
{
|
||||
cursor = sysprof_capture_cursor_new (st->reader);
|
||||
condition = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
sysprof_capture_cursor_foreach (cursor, discover_max_n_addr, st);
|
||||
sysprof_capture_cursor_reset (cursor);
|
||||
sysprof_capture_cursor_foreach (cursor, build_point_cache_cb, st);
|
||||
}
|
||||
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&st->pc),
|
||||
(GDestroyNotify) point_cache_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_point_cache_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofDepthVisualizerRow *self = (SysprofDepthVisualizerRow *)object;
|
||||
PointCache *pc;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER_ROW (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
if ((pc = g_task_propagate_pointer (G_TASK (result), NULL)))
|
||||
{
|
||||
g_clear_pointer (&self->points, point_cache_unref);
|
||||
self->points = g_steal_pointer (&pc);
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_reload (SysprofDepthVisualizerRow *self)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
GtkAllocation alloc;
|
||||
State *st;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER_ROW (self));
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
|
||||
st = g_slice_new0 (State);
|
||||
st->reader = sysprof_capture_reader_ref (self->reader);
|
||||
st->pc = point_cache_new ();
|
||||
st->max_n_addrs = 0;
|
||||
st->begin_time = sysprof_capture_reader_get_start_time (self->reader);
|
||||
st->end_time = sysprof_capture_reader_get_end_time (self->reader);
|
||||
st->duration = st->end_time - st->begin_time;
|
||||
|
||||
point_cache_add_set (st->pc, 1);
|
||||
|
||||
task = g_task_new (self, NULL, apply_point_cache_cb, NULL);
|
||||
g_task_set_source_tag (task, sysprof_depth_visualizer_row_reload);
|
||||
g_task_set_task_data (task, st, (GDestroyNotify) state_free);
|
||||
g_task_run_in_thread (task, sysprof_depth_visualizer_row_worker);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_set_reader (SysprofVisualizerRow *row,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofDepthVisualizerRow *self = (SysprofDepthVisualizerRow *)row;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER_ROW (self));
|
||||
|
||||
if (self->reader != reader)
|
||||
{
|
||||
if (self->reader != NULL)
|
||||
{
|
||||
sysprof_capture_reader_unref (self->reader);
|
||||
self->reader = NULL;
|
||||
}
|
||||
|
||||
if (reader != NULL)
|
||||
{
|
||||
self->reader = sysprof_capture_reader_ref (reader);
|
||||
sysprof_depth_visualizer_row_reload (self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_depth_visualizer_row_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofDepthVisualizerRow *self = (SysprofDepthVisualizerRow *)widget;
|
||||
GtkStyleContext *style_context;
|
||||
GtkAllocation alloc;
|
||||
const Point *points;
|
||||
guint n_points = 0;
|
||||
GdkRGBA user;
|
||||
GdkRGBA system;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER_ROW (self));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
GTK_WIDGET_CLASS (sysprof_depth_visualizer_row_parent_class)->draw (widget, cr);
|
||||
|
||||
if (self->points == NULL)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
style_context = gtk_widget_get_style_context (widget);
|
||||
gtk_style_context_get_color (style_context,
|
||||
gtk_style_context_get_state (style_context),
|
||||
&user);
|
||||
gdk_rgba_parse (&system, "#ef2929");
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
if ((points = point_cache_get_points (self->points, 1, &n_points)))
|
||||
{
|
||||
g_autofree SysprofVisualizerRowAbsolutePoint *out_points = NULL;
|
||||
gint last = 1;
|
||||
|
||||
out_points = g_new (SysprofVisualizerRowAbsolutePoint, n_points);
|
||||
sysprof_visualizer_row_translate_points (SYSPROF_VISUALIZER_ROW (widget),
|
||||
(const SysprofVisualizerRowRelativePoint *)points,
|
||||
n_points, out_points, n_points);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
gdk_cairo_set_source_rgba (cr, &user);
|
||||
|
||||
if (n_points > 0 && points[0].y < 0)
|
||||
gdk_cairo_set_source_rgba (cr, &system);
|
||||
|
||||
for (guint i = 0; i < n_points; i++)
|
||||
{
|
||||
if ((points[i].y < 0 && last > 0) ||
|
||||
(points[i].y > 0 && last < 0))
|
||||
cairo_stroke (cr);
|
||||
|
||||
last = points[i].y > 0 ? 1 : -1;
|
||||
|
||||
cairo_move_to (cr, .5 + alloc.x + (guint)out_points[i].x, alloc.height);
|
||||
cairo_line_to (cr, .5 + alloc.x + out_points[i].x, out_points[i].y);
|
||||
|
||||
if (last > 0)
|
||||
gdk_cairo_set_source_rgba (cr, &user);
|
||||
else
|
||||
gdk_cairo_set_source_rgba (cr, &system);
|
||||
}
|
||||
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_depth_visualizer_row_do_reload (gpointer data)
|
||||
{
|
||||
SysprofDepthVisualizerRow *self = data;
|
||||
self->reload_source = 0;
|
||||
sysprof_depth_visualizer_row_reload (self);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_queue_reload (SysprofDepthVisualizerRow *self)
|
||||
{
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER_ROW (self));
|
||||
|
||||
if (self->reload_source)
|
||||
g_source_remove (self->reload_source);
|
||||
|
||||
self->reload_source = gdk_threads_add_idle (sysprof_depth_visualizer_row_do_reload, self);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *alloc)
|
||||
{
|
||||
GTK_WIDGET_CLASS (sysprof_depth_visualizer_row_parent_class)->size_allocate (widget, alloc);
|
||||
|
||||
sysprof_depth_visualizer_row_queue_reload (SYSPROF_DEPTH_VISUALIZER_ROW (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_finalize (GObject *object)
|
||||
{
|
||||
SysprofDepthVisualizerRow *self = (SysprofDepthVisualizerRow *)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_OBJECT_CLASS (sysprof_depth_visualizer_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_class_init (SysprofDepthVisualizerRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofVisualizerRowClass *row_class = SYSPROF_VISUALIZER_ROW_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_depth_visualizer_row_finalize;
|
||||
|
||||
widget_class->draw = sysprof_depth_visualizer_row_draw;
|
||||
widget_class->size_allocate = sysprof_depth_visualizer_row_size_allocate;
|
||||
|
||||
row_class->set_reader = sysprof_depth_visualizer_row_set_reader;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_row_init (SysprofDepthVisualizerRow *self)
|
||||
{
|
||||
PangoAttrList *attrs = pango_attr_list_new ();
|
||||
GtkWidget *label;
|
||||
|
||||
pango_attr_list_insert (attrs, pango_attr_scale_new (PANGO_SCALE_SMALL * PANGO_SCALE_SMALL));
|
||||
label = g_object_new (GTK_TYPE_LABEL,
|
||||
"label", _("Stack Depth"),
|
||||
"attributes", attrs,
|
||||
"visible", TRUE,
|
||||
"xalign", 0.0f,
|
||||
"yalign", 0.0f,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (label));
|
||||
pango_attr_list_unref (attrs);
|
||||
}
|
||||
430
src/libsysprof-ui/sysprof-depth-visualizer.c
Normal file
430
src/libsysprof-ui/sysprof-depth-visualizer.c
Normal file
@ -0,0 +1,430 @@
|
||||
/* sysprof-depth-visualizer.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-depth-visualizer"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "pointcache.h"
|
||||
#include "sysprof-depth-visualizer.h"
|
||||
|
||||
struct _SysprofDepthVisualizer
|
||||
{
|
||||
SysprofVisualizer parent_instance;
|
||||
SysprofCaptureReader *reader;
|
||||
PointCache *points;
|
||||
guint reload_source;
|
||||
guint mode;
|
||||
GtkAllocation last_alloc;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
PointCache *pc;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
gint64 duration;
|
||||
guint max_n_addrs;
|
||||
guint mode;
|
||||
} State;
|
||||
|
||||
G_DEFINE_TYPE (SysprofDepthVisualizer, sysprof_depth_visualizer, SYSPROF_TYPE_VISUALIZER)
|
||||
|
||||
static void
|
||||
state_free (State *st)
|
||||
{
|
||||
g_clear_pointer (&st->reader, sysprof_capture_reader_unref);
|
||||
g_clear_pointer (&st->pc, point_cache_unref);
|
||||
g_slice_free (State, st);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
discover_max_n_addr (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
const SysprofCaptureSample *sample = (const SysprofCaptureSample *)frame;
|
||||
State *st = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_SAMPLE);
|
||||
g_assert (st != NULL);
|
||||
|
||||
st->max_n_addrs = MAX (st->max_n_addrs, sample->n_addrs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
build_point_cache_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
const SysprofCaptureSample *sample = (const SysprofCaptureSample *)frame;
|
||||
State *st = user_data;
|
||||
gdouble x, y;
|
||||
gboolean has_kernel = FALSE;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_SAMPLE);
|
||||
g_assert (st != NULL);
|
||||
|
||||
x = (frame->time - st->begin_time) / (gdouble)st->duration;
|
||||
y = sample->n_addrs / (gdouble)st->max_n_addrs;
|
||||
|
||||
/* If this contains a context-switch (meaning we're going into the kernel
|
||||
* to do some work, use a negative value for Y so that we know later on
|
||||
* that we should draw it with a different color (after removing the negation
|
||||
* on the value.
|
||||
*
|
||||
* We skip past the first index, which is always a context switch as it is
|
||||
* our perf handler.
|
||||
*/
|
||||
for (guint i = 1; i < sample->n_addrs; i++)
|
||||
{
|
||||
SysprofAddressContext kind;
|
||||
|
||||
if (sysprof_address_is_context_switch (sample->addrs[i], &kind))
|
||||
{
|
||||
has_kernel = TRUE;
|
||||
y = -y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_kernel)
|
||||
point_cache_add_point_to_set (st->pc, 1, x, y);
|
||||
else
|
||||
point_cache_add_point_to_set (st->pc, 2, x, y);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_SAMPLE, };
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
SysprofCaptureCondition *condition;
|
||||
State *st = task_data;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (source_object));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
if (st->duration != 0)
|
||||
{
|
||||
cursor = sysprof_capture_cursor_new (st->reader);
|
||||
condition = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
sysprof_capture_cursor_foreach (cursor, discover_max_n_addr, st);
|
||||
sysprof_capture_cursor_reset (cursor);
|
||||
sysprof_capture_cursor_foreach (cursor, build_point_cache_cb, st);
|
||||
}
|
||||
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&st->pc),
|
||||
(GDestroyNotify) point_cache_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_point_cache_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)object;
|
||||
PointCache *pc;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
if ((pc = g_task_propagate_pointer (G_TASK (result), NULL)))
|
||||
{
|
||||
g_clear_pointer (&self->points, point_cache_unref);
|
||||
self->points = g_steal_pointer (&pc);
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_reload (SysprofDepthVisualizer *self)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
GtkAllocation alloc;
|
||||
State *st;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
|
||||
st = g_slice_new0 (State);
|
||||
st->reader = sysprof_capture_reader_ref (self->reader);
|
||||
st->pc = point_cache_new ();
|
||||
st->max_n_addrs = 0;
|
||||
st->begin_time = sysprof_capture_reader_get_start_time (self->reader);
|
||||
st->end_time = sysprof_capture_reader_get_end_time (self->reader);
|
||||
st->duration = st->end_time - st->begin_time;
|
||||
st->mode = self->mode;
|
||||
|
||||
point_cache_add_set (st->pc, 1);
|
||||
point_cache_add_set (st->pc, 2);
|
||||
|
||||
task = g_task_new (self, NULL, apply_point_cache_cb, NULL);
|
||||
g_task_set_source_tag (task, sysprof_depth_visualizer_reload);
|
||||
g_task_set_task_data (task, st, (GDestroyNotify) state_free);
|
||||
g_task_run_in_thread (task, sysprof_depth_visualizer_worker);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_set_reader (SysprofVisualizer *row,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)row;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
|
||||
|
||||
if (self->reader != reader)
|
||||
{
|
||||
if (self->reader != NULL)
|
||||
{
|
||||
sysprof_capture_reader_unref (self->reader);
|
||||
self->reader = NULL;
|
||||
}
|
||||
|
||||
if (reader != NULL)
|
||||
{
|
||||
self->reader = sysprof_capture_reader_ref (reader);
|
||||
sysprof_depth_visualizer_reload (self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_depth_visualizer_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofDepthVisualizer *self = (SysprofDepthVisualizer *)widget;
|
||||
GtkAllocation alloc;
|
||||
GdkRectangle clip;
|
||||
const Point *points;
|
||||
gboolean ret;
|
||||
guint n_points = 0;
|
||||
GdkRGBA user;
|
||||
GdkRGBA system;
|
||||
|
||||
g_assert (SYSPROF_IS_DEPTH_VISUALIZER (self));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
ret = GTK_WIDGET_CLASS (sysprof_depth_visualizer_parent_class)->draw (widget, cr);
|
||||
|
||||
if (self->points == NULL)
|
||||
return ret;
|
||||
|
||||
gdk_rgba_parse (&user, "#1a5fb4");
|
||||
gdk_rgba_parse (&system, "#3584e4");
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
if (!gdk_cairo_get_clip_rectangle (cr, &clip))
|
||||
return ret;
|
||||
|
||||
/* Draw user-space stacks */
|
||||
if (self->mode != SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY &&
|
||||
(points = point_cache_get_points (self->points, 1, &n_points)))
|
||||
{
|
||||
g_autofree SysprofVisualizerAbsolutePoint *out_points = NULL;
|
||||
|
||||
out_points = g_new (SysprofVisualizerAbsolutePoint, n_points);
|
||||
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (widget),
|
||||
(const SysprofVisualizerRelativePoint *)points,
|
||||
n_points, out_points, n_points);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
gdk_cairo_set_source_rgba (cr, &user);
|
||||
|
||||
for (guint i = 0; i < n_points; i++)
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
x = out_points[i].x;
|
||||
y = out_points[i].y;
|
||||
|
||||
if (x < clip.x)
|
||||
continue;
|
||||
|
||||
if (x > clip.x + clip.width)
|
||||
break;
|
||||
|
||||
for (guint j = i + 1; j < n_points; j++)
|
||||
{
|
||||
if (out_points[j].x != x)
|
||||
break;
|
||||
|
||||
y = MIN (y, out_points[j].y);
|
||||
}
|
||||
|
||||
x += alloc.x;
|
||||
|
||||
cairo_move_to (cr, (guint)x + .5, alloc.height);
|
||||
cairo_line_to (cr, (guint)x + .5, y);
|
||||
}
|
||||
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
/* Draw kernel-space stacks */
|
||||
if (self->mode != SYSPROF_DEPTH_VISUALIZER_USER_ONLY &&
|
||||
(points = point_cache_get_points (self->points, 2, &n_points)))
|
||||
{
|
||||
g_autofree SysprofVisualizerAbsolutePoint *out_points = NULL;
|
||||
|
||||
out_points = g_new (SysprofVisualizerAbsolutePoint, n_points);
|
||||
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (widget),
|
||||
(const SysprofVisualizerRelativePoint *)points,
|
||||
n_points, out_points, n_points);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
gdk_cairo_set_source_rgba (cr, &system);
|
||||
|
||||
for (guint i = 0; i < n_points; i++)
|
||||
{
|
||||
gdouble x, y;
|
||||
|
||||
x = out_points[i].x;
|
||||
y = out_points[i].y;
|
||||
|
||||
if (x < clip.x)
|
||||
continue;
|
||||
|
||||
if (x > clip.x + clip.width)
|
||||
break;
|
||||
|
||||
for (guint j = i + 1; j < n_points; j++)
|
||||
{
|
||||
if (out_points[j].x != x)
|
||||
break;
|
||||
|
||||
y = MIN (y, out_points[j].y);
|
||||
}
|
||||
|
||||
x += alloc.x;
|
||||
|
||||
cairo_move_to (cr, (guint)x + .5, alloc.height);
|
||||
cairo_line_to (cr, (guint)x + .5, y);
|
||||
}
|
||||
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_depth_visualizer_do_reload (gpointer data)
|
||||
{
|
||||
SysprofDepthVisualizer *self = data;
|
||||
self->reload_source = 0;
|
||||
sysprof_depth_visualizer_reload (self);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *alloc)
|
||||
{
|
||||
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)
|
||||
{
|
||||
sysprof_depth_visualizer_queue_reload (SYSPROF_DEPTH_VISUALIZER (widget));
|
||||
self->last_alloc = *alloc;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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_OBJECT_CLASS (sysprof_depth_visualizer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_class_init (SysprofDepthVisualizerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofVisualizerClass *row_class = SYSPROF_VISUALIZER_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_depth_visualizer_finalize;
|
||||
|
||||
widget_class->draw = sysprof_depth_visualizer_draw;
|
||||
widget_class->size_allocate = sysprof_depth_visualizer_size_allocate;
|
||||
|
||||
row_class->set_reader = sysprof_depth_visualizer_set_reader;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_depth_visualizer_init (SysprofDepthVisualizer *self)
|
||||
{
|
||||
}
|
||||
|
||||
SysprofVisualizer *
|
||||
sysprof_depth_visualizer_new (SysprofDepthVisualizerMode mode)
|
||||
{
|
||||
SysprofDepthVisualizer *self;
|
||||
|
||||
g_return_val_if_fail (mode == SYSPROF_DEPTH_VISUALIZER_COMBINED ||
|
||||
mode == SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY ||
|
||||
mode == SYSPROF_DEPTH_VISUALIZER_USER_ONLY,
|
||||
NULL);
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_DEPTH_VISUALIZER, NULL);
|
||||
self->mode = mode;
|
||||
|
||||
return SYSPROF_VISUALIZER (g_steal_pointer (&self));
|
||||
}
|
||||
40
src/libsysprof-ui/sysprof-depth-visualizer.h
Normal file
40
src/libsysprof-ui/sysprof-depth-visualizer.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* sysprof-depth-visualizer.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SYSPROF_DEPTH_VISUALIZER_COMBINED,
|
||||
SYSPROF_DEPTH_VISUALIZER_KERNEL_ONLY,
|
||||
SYSPROF_DEPTH_VISUALIZER_USER_ONLY,
|
||||
} SysprofDepthVisualizerMode;
|
||||
|
||||
#define SYSPROF_TYPE_DEPTH_VISUALIZER (sysprof_depth_visualizer_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofDepthVisualizer, sysprof_depth_visualizer, SYSPROF, DEPTH_VISUALIZER, SysprofVisualizer)
|
||||
|
||||
SysprofVisualizer *sysprof_depth_visualizer_new (SysprofDepthVisualizerMode mode);
|
||||
|
||||
G_END_DECLS
|
||||
324
src/libsysprof-ui/sysprof-details-page.c
Normal file
324
src/libsysprof-ui/sysprof-details-page.c
Normal file
@ -0,0 +1,324 @@
|
||||
/* sysprof-details-page.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-details-page"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <dazzle.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sysprof-details-page.h"
|
||||
#include "sysprof-ui-private.h"
|
||||
|
||||
#define NSEC_PER_SEC (G_USEC_PER_SEC * 1000L)
|
||||
|
||||
struct _SysprofDetailsPage
|
||||
{
|
||||
SysprofPage parent_instance;
|
||||
|
||||
/* Template Objects */
|
||||
DzlThreeGrid *three_grid;
|
||||
GtkListStore *marks_store;
|
||||
GtkTreeView *marks_view;
|
||||
GtkLabel *counters;
|
||||
GtkLabel *duration;
|
||||
GtkLabel *filename;
|
||||
GtkLabel *forks;
|
||||
GtkLabel *marks;
|
||||
GtkLabel *processes;
|
||||
GtkLabel *samples;
|
||||
GtkLabel *start_time;
|
||||
GtkLabel *cpu_label;
|
||||
|
||||
guint next_row;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SysprofDetailsPage, sysprof_details_page, GTK_TYPE_BIN)
|
||||
|
||||
#if GLIB_CHECK_VERSION(2, 56, 0)
|
||||
# define _g_date_time_new_from_iso8601 g_date_time_new_from_iso8601
|
||||
#else
|
||||
static GDateTime *
|
||||
_g_date_time_new_from_iso8601 (const gchar *str,
|
||||
GTimeZone *default_tz)
|
||||
{
|
||||
GTimeVal tv;
|
||||
|
||||
if (g_time_val_from_iso8601 (str, &tv))
|
||||
{
|
||||
g_autoptr(GDateTime) dt = g_date_time_new_from_timeval_utc (&tv);
|
||||
|
||||
if (default_tz)
|
||||
return g_date_time_to_timezone (dt, default_tz);
|
||||
else
|
||||
return g_steal_pointer (&dt);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
sysprof_details_page_class_init (SysprofDetailsPageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-details-page.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, counters);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, cpu_label);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, duration);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, filename);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, forks);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, marks);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, marks_store);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, marks_view);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, processes);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofDetailsPage, samples);
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_details_page_init (SysprofDetailsPage *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (self->marks_view),
|
||||
GTK_SELECTION_MULTIPLE);
|
||||
|
||||
self->next_row = 8;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
sysprof_details_page_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_DETAILS_PAGE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
update_cpu_info_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(SysprofDetailsPage) self = user_data;
|
||||
g_autofree gchar *str = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_DETAILS_PAGE (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
if ((str = g_task_propagate_pointer (G_TASK (result), NULL)))
|
||||
gtk_label_set_label (self->cpu_label, str);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cpu_info_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
const SysprofCaptureFileChunk *fc = (gpointer)frame;
|
||||
const gchar *endptr;
|
||||
const gchar *line;
|
||||
gchar **str = user_data;
|
||||
|
||||
endptr = (gchar *)fc->data + fc->len;
|
||||
line = memmem ((gchar *)fc->data, fc->len, "model name", 10);
|
||||
endptr = memchr (line, '\n', endptr - line);
|
||||
|
||||
if (endptr)
|
||||
{
|
||||
gchar *tmp = *str = g_strndup (line, endptr - line);
|
||||
for (; *tmp && *tmp != ':'; tmp++)
|
||||
*tmp = ' ';
|
||||
if (*tmp == ':')
|
||||
*tmp = ' ';
|
||||
g_strstrip (*str);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_details_page_update_cpu_info_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
SysprofCaptureCursor *cursor = task_data;
|
||||
gchar *str = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (cursor != NULL);
|
||||
|
||||
sysprof_capture_cursor_foreach (cursor, cpu_info_cb, &str);
|
||||
g_task_return_pointer (task, g_steal_pointer (&str), g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_details_page_update_cpu_info (SysprofDetailsPage *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_DETAILS_PAGE (self));
|
||||
g_assert (reader != NULL);
|
||||
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (cursor,
|
||||
sysprof_capture_condition_new_where_file ("/proc/cpuinfo"));
|
||||
|
||||
task = g_task_new (NULL, NULL, update_cpu_info_cb, g_object_ref (self));
|
||||
g_task_set_task_data (task,
|
||||
g_steal_pointer (&cursor),
|
||||
(GDestroyNotify) sysprof_capture_cursor_unref);
|
||||
g_task_run_in_thread (task, sysprof_details_page_update_cpu_info_worker);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_details_page_set_reader (SysprofDetailsPage *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
g_autoptr(GDateTime) dt = NULL;
|
||||
g_autoptr(GDateTime) local = NULL;
|
||||
g_autofree gchar *duration_str = NULL;
|
||||
const gchar *filename;
|
||||
const gchar *capture_at;
|
||||
SysprofCaptureStat st_buf;
|
||||
gint64 duration;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_DETAILS_PAGE (self));
|
||||
g_return_if_fail (reader != NULL);
|
||||
|
||||
sysprof_details_page_update_cpu_info (self, reader);
|
||||
|
||||
if (!(filename = sysprof_capture_reader_get_filename (reader)))
|
||||
filename = _("Memory Capture");
|
||||
|
||||
gtk_label_set_label (self->filename, filename);
|
||||
|
||||
if ((capture_at = sysprof_capture_reader_get_time (reader)) &&
|
||||
(dt = _g_date_time_new_from_iso8601 (capture_at, NULL)) &&
|
||||
(local = g_date_time_to_local (dt)))
|
||||
{
|
||||
g_autofree gchar *str = g_date_time_format (local, "%x %X");
|
||||
gtk_label_set_label (self->start_time, str);
|
||||
}
|
||||
|
||||
duration = sysprof_capture_reader_get_end_time (reader) -
|
||||
sysprof_capture_reader_get_start_time (reader);
|
||||
duration_str = g_strdup_printf (_("%0.4lf seconds"), duration / (gdouble)NSEC_PER_SEC);
|
||||
gtk_label_set_label (self->duration, duration_str);
|
||||
|
||||
if (sysprof_capture_reader_get_stat (reader, &st_buf))
|
||||
{
|
||||
#define SET_FRAME_COUNT(field, TYPE) \
|
||||
G_STMT_START { \
|
||||
g_autofree gchar *str = NULL; \
|
||||
str = g_strdup_printf ("%"G_GSIZE_FORMAT, st_buf.frame_count[TYPE]); \
|
||||
gtk_label_set_label (self->field, str); \
|
||||
} G_STMT_END
|
||||
|
||||
SET_FRAME_COUNT (samples, SYSPROF_CAPTURE_FRAME_SAMPLE);
|
||||
SET_FRAME_COUNT (marks, SYSPROF_CAPTURE_FRAME_MARK);
|
||||
SET_FRAME_COUNT (processes, SYSPROF_CAPTURE_FRAME_PROCESS);
|
||||
SET_FRAME_COUNT (forks, SYSPROF_CAPTURE_FRAME_FORK);
|
||||
SET_FRAME_COUNT (counters, SYSPROF_CAPTURE_FRAME_CTRSET);
|
||||
|
||||
#undef SET_FRAME_COUNT
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_details_page_add_item (SysprofDetailsPage *self,
|
||||
GtkWidget *left,
|
||||
GtkWidget *center)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_DETAILS_PAGE (self));
|
||||
g_return_if_fail (!left || GTK_IS_WIDGET (left));
|
||||
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);
|
||||
|
||||
if (center)
|
||||
gtk_container_add_with_properties (GTK_CONTAINER (self->three_grid), center,
|
||||
"row", self->next_row,
|
||||
"column", DZL_THREE_GRID_COLUMN_CENTER,
|
||||
NULL);
|
||||
|
||||
self->next_row++;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_details_page_add_mark (SysprofDetailsPage *self,
|
||||
const gchar *mark,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gint64 avg,
|
||||
gint64 hits)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_DETAILS_PAGE (self));
|
||||
|
||||
gtk_list_store_append (self->marks_store, &iter);
|
||||
gtk_list_store_set (self->marks_store, &iter,
|
||||
0, mark,
|
||||
1, min ? _sysprof_format_duration (min) : "—",
|
||||
2, max ? _sysprof_format_duration (max) : "—",
|
||||
3, avg ? _sysprof_format_duration (avg) : "—",
|
||||
4, hits,
|
||||
-1);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_details_page_add_marks (SysprofDetailsPage *self,
|
||||
const SysprofMarkStat *marks,
|
||||
guint n_marks)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_DETAILS_PAGE (self));
|
||||
g_return_if_fail (marks != NULL || n_marks == 0);
|
||||
|
||||
if (marks == NULL || n_marks == 0)
|
||||
return;
|
||||
|
||||
/* Be reasonable */
|
||||
if (n_marks > 100)
|
||||
n_marks = 100;
|
||||
|
||||
for (guint i = 0; i < n_marks; i++)
|
||||
sysprof_details_page_add_mark (self,
|
||||
marks[i].name,
|
||||
marks[i].min,
|
||||
marks[i].max,
|
||||
marks[i].avg,
|
||||
marks[i].count);
|
||||
}
|
||||
60
src/libsysprof-ui/sysprof-details-page.h
Normal file
60
src/libsysprof-ui/sysprof-details-page.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* sysprof-details-page.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
SYSPROF_ALIGNED_BEGIN (8)
|
||||
typedef struct
|
||||
{
|
||||
gchar name[152];
|
||||
guint64 count;
|
||||
gint64 max;
|
||||
gint64 min;
|
||||
gint64 avg;
|
||||
guint64 avg_count;
|
||||
} SysprofMarkStat
|
||||
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)
|
||||
|
||||
GtkWidget *sysprof_details_page_new (void);
|
||||
void sysprof_details_page_set_reader (SysprofDetailsPage *self,
|
||||
SysprofCaptureReader *reader);
|
||||
void sysprof_details_page_add_marks (SysprofDetailsPage *self,
|
||||
const SysprofMarkStat *marks,
|
||||
guint n_marks);
|
||||
void sysprof_details_page_add_mark (SysprofDetailsPage *self,
|
||||
const gchar *mark,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gint64 avg,
|
||||
gint64 hits);
|
||||
void sysprof_details_page_add_item (SysprofDetailsPage *self,
|
||||
GtkWidget *left,
|
||||
GtkWidget *center);
|
||||
|
||||
G_END_DECLS
|
||||
372
src/libsysprof-ui/sysprof-details-page.ui
Normal file
372
src/libsysprof-ui/sysprof-details-page.ui
Normal file
@ -0,0 +1,372 @@
|
||||
<?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>
|
||||
<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>
|
||||
<property name="column-spacing">12</property>
|
||||
<property name="row-spacing">6</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">true</property>
|
||||
<property name="label" translatable="yes">Filename</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">true</property>
|
||||
<property name="label" translatable="yes">Captured at</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</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>
|
||||
</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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="margin-top">12</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Samples Captured</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Marks Captured</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Processes Captured</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Forks Captured</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="label" translatable="yes">Counters Captured</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">left</property>
|
||||
<property name="row">8</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</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="margin-bottom">12</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">center</property>
|
||||
<property name="row">8</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">
|
||||
<property name="model">marks_store</property>
|
||||
<property name="width-request">500</property>
|
||||
<property name="height-request">100</property>
|
||||
<property name="enable-grid-lines">both</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="expand">true</property>
|
||||
<property name="title" translatable="yes">Mark</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Hits</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">4</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Min</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Max</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Avg</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="column">center</property>
|
||||
<property name="row">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
<object class="GtkListStore" id="marks_store">
|
||||
<columns>
|
||||
<!-- column-name Mark -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name Min -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name Max -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name Avg -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name Hits -->
|
||||
<column type="gint64"/>
|
||||
</columns>
|
||||
</object>
|
||||
</interface>
|
||||
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,9 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-version-macros.h"
|
||||
#include "sysprof-page.h"
|
||||
#include "sysprof-visualizer-group.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -32,38 +34,59 @@ G_BEGIN_DECLS
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofDisplay, sysprof_display, SYSPROF, DISPLAY, GtkBin)
|
||||
|
||||
SYSPROF_ALIGNED_BEGIN(8)
|
||||
struct _SysprofDisplayClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
}
|
||||
SYSPROF_ALIGNED_END(8);
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_display_new (void);
|
||||
GtkWidget *sysprof_display_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_display_new_for_profiler (SysprofProfiler *profiler);
|
||||
GtkWidget *sysprof_display_new_for_profiler (SysprofProfiler *profiler);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gchar *sysprof_display_dup_title (SysprofDisplay *self);
|
||||
char *sysprof_display_dup_title (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofProfiler *sysprof_display_get_profiler (SysprofDisplay *self);
|
||||
SysprofProfiler *sysprof_display_get_profiler (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_display_is_empty (SysprofDisplay *self);
|
||||
void sysprof_display_add_group (SysprofDisplay *self,
|
||||
SysprofVisualizerGroup *group);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_display_open (SysprofDisplay *self,
|
||||
GFile *file);
|
||||
void sysprof_display_add_page (SysprofDisplay *self,
|
||||
SysprofPage *page);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_display_save (SysprofDisplay *self);
|
||||
SysprofPage *sysprof_display_get_visible_page (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_display_get_can_save (SysprofDisplay *self);
|
||||
void sysprof_display_set_visible_page (SysprofDisplay *self,
|
||||
SysprofPage *page);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_display_stop_recording (SysprofDisplay *self);
|
||||
SysprofZoomManager *sysprof_display_get_zoom_manager (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_display_get_can_replay (SysprofDisplay *self);
|
||||
void sysprof_display_load_async (SysprofDisplay *self,
|
||||
SysprofCaptureReader *reader,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofDisplay *sysprof_display_replay (SysprofDisplay *self);
|
||||
gboolean sysprof_display_load_finish (SysprofDisplay *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_display_is_empty (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_display_open (SysprofDisplay *self,
|
||||
GFile *file);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_display_save (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_display_get_can_save (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_display_stop_recording (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_display_get_can_replay (SysprofDisplay *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofDisplay *sysprof_display_replay (SysprofDisplay *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -14,11 +14,40 @@
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofCaptureView" id="capture_view">
|
||||
<object class="DzlMultiPaned">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="SysprofVisualizersFrame" id="visualizers">
|
||||
<property name="vexpand">false</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="visible">true</property>
|
||||
</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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">capture</property>
|
||||
<property name="name">view</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
@ -26,14 +55,11 @@
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">recording</property>
|
||||
<property name="name">record</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofEmptyStateView" id="failed_view">
|
||||
<property name="icon-name">computer-fail-symbolic</property>
|
||||
<property name="title" translatable="yes">Something went wrong</property>
|
||||
<property name="subtitle" translatable="yes">Sysprof failed to access the requested performance data.</property>
|
||||
<object class="SysprofFailedStateView" id="failed_view">
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
||||
@ -20,10 +20,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
@ -31,7 +27,6 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_EMPTY_STATE_VIEW (sysprof_empty_state_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofEmptyStateView, sysprof_empty_state_view, SYSPROF, EMPTY_STATE_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofEmptyStateViewClass
|
||||
@ -41,7 +36,6 @@ struct _SysprofEmptyStateViewClass
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_empty_state_view_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -20,10 +20,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
@ -31,7 +27,6 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_FAILED_STATE_VIEW (sysprof_failed_state_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofFailedStateView, sysprof_failed_state_view, SYSPROF, FAILED_STATE_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofFailedStateViewClass
|
||||
@ -41,9 +36,7 @@ struct _SysprofFailedStateViewClass
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_failed_state_view_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_failed_state_view_set_profiler (SysprofFailedStateView *self,
|
||||
SysprofProfiler *profiler);
|
||||
|
||||
|
||||
@ -1,70 +0,0 @@
|
||||
/* sysprof-line-visualizer-row.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-visualizer-row.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_LINE_VISUALIZER_ROW (sysprof_line_visualizer_row_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofLineVisualizerRow, sysprof_line_visualizer_row, SYSPROF, LINE_VISUALIZER_ROW, SysprofVisualizerRow)
|
||||
|
||||
struct _SysprofLineVisualizerRowClass
|
||||
{
|
||||
SysprofVisualizerRowClass parent_class;
|
||||
|
||||
void (*counter_added) (SysprofLineVisualizerRow *self,
|
||||
guint counter_id);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_line_visualizer_row_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_line_visualizer_row_clear (SysprofLineVisualizerRow *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_line_visualizer_row_add_counter (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_line_visualizer_row_set_line_width (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
gdouble width);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_line_visualizer_row_set_fill (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_line_visualizer_row_set_dash (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
gboolean use_dash);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,4 +1,4 @@
|
||||
/* sysprof-line-visualizer-row.c
|
||||
/* sysprof-line-visualizer.c
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
@ -18,7 +18,7 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-line-visualizer-row"
|
||||
#define G_LOG_DOMAIN "sysprof-line-visualizer"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "pointcache.h"
|
||||
#include "sysprof-line-visualizer-row.h"
|
||||
#include "sysprof-line-visualizer.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -49,11 +49,6 @@ typedef struct
|
||||
*/
|
||||
PointCache *cache;
|
||||
|
||||
/*
|
||||
* Child widget to display the label in the upper corner.
|
||||
*/
|
||||
GtkLabel *label;
|
||||
|
||||
/*
|
||||
* Range of the scale for lower and upper.
|
||||
*/
|
||||
@ -69,7 +64,7 @@ typedef struct
|
||||
|
||||
guint y_lower_set : 1;
|
||||
guint y_upper_set : 1;
|
||||
} SysprofLineVisualizerRowPrivate;
|
||||
} SysprofLineVisualizerPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -96,19 +91,18 @@ typedef struct
|
||||
guint y_upper_set : 1;
|
||||
} LoadData;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofLineVisualizerRow, sysprof_line_visualizer_row, SYSPROF_TYPE_VISUALIZER_ROW)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofLineVisualizer, sysprof_line_visualizer, SYSPROF_TYPE_VISUALIZER)
|
||||
|
||||
static void sysprof_line_visualizer_row_load_data_async (SysprofLineVisualizerRow *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
static PointCache *sysprof_line_visualizer_row_load_data_finish (SysprofLineVisualizerRow *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
static void sysprof_line_visualizer_load_data_async (SysprofLineVisualizer *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
static PointCache *sysprof_line_visualizer_load_data_finish (SysprofLineVisualizer *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TITLE,
|
||||
PROP_Y_LOWER,
|
||||
PROP_Y_UPPER,
|
||||
N_PROPS
|
||||
@ -144,34 +138,38 @@ copy_array (GArray *ar)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_line_visualizer_row_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
sysprof_line_visualizer_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = (SysprofLineVisualizerRow *)widget;
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = (SysprofLineVisualizer *)widget;
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
GtkStyleContext *style_context;
|
||||
GtkStateFlags flags;
|
||||
GtkAllocation alloc;
|
||||
GdkRectangle clip;
|
||||
GdkRGBA foreground;
|
||||
gboolean ret;
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (widget));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (widget));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
ret = GTK_WIDGET_CLASS (sysprof_line_visualizer_row_parent_class)->draw (widget, cr);
|
||||
ret = GTK_WIDGET_CLASS (sysprof_line_visualizer_parent_class)->draw (widget, cr);
|
||||
|
||||
if (priv->cache == NULL)
|
||||
return ret;
|
||||
|
||||
if (!gdk_cairo_get_clip_rectangle (cr, &clip))
|
||||
return ret;
|
||||
|
||||
style_context = gtk_widget_get_style_context (widget);
|
||||
flags = gtk_widget_get_state_flags (widget);
|
||||
gtk_style_context_get_color (style_context, flags, &foreground);
|
||||
|
||||
for (guint line = 0; line < priv->lines->len; line++)
|
||||
{
|
||||
g_autofree SysprofVisualizerRowAbsolutePoint *points = NULL;
|
||||
g_autofree SysprofVisualizerAbsolutePoint *points = NULL;
|
||||
const LineInfo *line_info = &g_array_index (priv->lines, LineInfo, line);
|
||||
const Point *fpoints;
|
||||
guint n_fpoints = 0;
|
||||
@ -181,19 +179,32 @@ sysprof_line_visualizer_row_draw (GtkWidget *widget,
|
||||
|
||||
if (n_fpoints > 0)
|
||||
{
|
||||
gdouble last_x;
|
||||
gdouble last_y;
|
||||
gdouble last_x = 0;
|
||||
gdouble last_y = 0;
|
||||
guint p;
|
||||
|
||||
points = g_new0 (SysprofVisualizerRowAbsolutePoint, n_fpoints);
|
||||
points = g_new0 (SysprofVisualizerAbsolutePoint, n_fpoints);
|
||||
|
||||
sysprof_visualizer_row_translate_points (SYSPROF_VISUALIZER_ROW (self),
|
||||
(const SysprofVisualizerRowRelativePoint *)fpoints,
|
||||
n_fpoints,
|
||||
points,
|
||||
n_fpoints);
|
||||
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (self),
|
||||
(const SysprofVisualizerRelativePoint *)fpoints,
|
||||
n_fpoints,
|
||||
points,
|
||||
n_fpoints);
|
||||
|
||||
last_x = points[0].x;
|
||||
last_y = points[0].y;
|
||||
for (p = 0; p < n_fpoints; p++)
|
||||
{
|
||||
if (points[p].x >= clip.x)
|
||||
break;
|
||||
}
|
||||
|
||||
if (p >= n_fpoints)
|
||||
return ret;
|
||||
|
||||
if (p > 0)
|
||||
p--;
|
||||
|
||||
last_x = points[p].x;
|
||||
last_y = points[p].y;
|
||||
|
||||
if (line_info->fill)
|
||||
{
|
||||
@ -205,7 +216,7 @@ sysprof_line_visualizer_row_draw (GtkWidget *widget,
|
||||
cairo_move_to (cr, last_x, last_y);
|
||||
}
|
||||
|
||||
for (guint i = 1; i < n_fpoints; i++)
|
||||
for (guint i = p + 1; i < n_fpoints; i++)
|
||||
{
|
||||
cairo_curve_to (cr,
|
||||
last_x + ((points[i].x - last_x) / 2),
|
||||
@ -214,8 +225,12 @@ sysprof_line_visualizer_row_draw (GtkWidget *widget,
|
||||
points[i].y,
|
||||
points[i].x,
|
||||
points[i].y);
|
||||
|
||||
last_x = points[i].x;
|
||||
last_y = points[i].y;
|
||||
|
||||
if (points[i].x > clip.x + clip.width)
|
||||
break;
|
||||
}
|
||||
|
||||
if (line_info->fill)
|
||||
@ -249,18 +264,18 @@ sysprof_line_visualizer_row_draw (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_load_data_cb (GObject *object,
|
||||
sysprof_line_visualizer_load_data_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = (SysprofLineVisualizerRow *)object;
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = (SysprofLineVisualizer *)object;
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(PointCache) cache = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
cache = sysprof_line_visualizer_row_load_data_finish (self, result, &error);
|
||||
cache = sysprof_line_visualizer_load_data_finish (self, result, &error);
|
||||
|
||||
if (cache == NULL)
|
||||
{
|
||||
@ -275,20 +290,20 @@ sysprof_line_visualizer_row_load_data_cb (GObject *object,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_line_visualizer_row_do_reload (gpointer data)
|
||||
sysprof_line_visualizer_do_reload (gpointer data)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = data;
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = data;
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
priv->queued_load = 0;
|
||||
|
||||
if (priv->reader != NULL)
|
||||
{
|
||||
sysprof_line_visualizer_row_load_data_async (self,
|
||||
sysprof_line_visualizer_load_data_async (self,
|
||||
NULL,
|
||||
sysprof_line_visualizer_row_load_data_cb,
|
||||
sysprof_line_visualizer_load_data_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@ -296,29 +311,29 @@ sysprof_line_visualizer_row_do_reload (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_queue_reload (SysprofLineVisualizerRow *self)
|
||||
sysprof_line_visualizer_queue_reload (SysprofLineVisualizer *self)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (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_row_do_reload,
|
||||
sysprof_line_visualizer_do_reload,
|
||||
self,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_set_reader (SysprofVisualizerRow *row,
|
||||
SysprofCaptureReader *reader)
|
||||
sysprof_line_visualizer_set_reader (SysprofVisualizer *row,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = (SysprofLineVisualizerRow *)row;
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = (SysprofLineVisualizer *)row;
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
if (priv->reader != reader)
|
||||
{
|
||||
@ -331,15 +346,15 @@ sysprof_line_visualizer_row_set_reader (SysprofVisualizerRow *row,
|
||||
if (reader != NULL)
|
||||
priv->reader = sysprof_capture_reader_ref (reader);
|
||||
|
||||
sysprof_line_visualizer_row_queue_reload (self);
|
||||
sysprof_line_visualizer_queue_reload (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_finalize (GObject *object)
|
||||
sysprof_line_visualizer_finalize (GObject *object)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = (SysprofLineVisualizerRow *)object;
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = (SysprofLineVisualizer *)object;
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->lines, g_array_unref);
|
||||
g_clear_pointer (&priv->cache, point_cache_unref);
|
||||
@ -351,24 +366,20 @@ sysprof_line_visualizer_row_finalize (GObject *object)
|
||||
priv->queued_load = 0;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (sysprof_line_visualizer_row_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (sysprof_line_visualizer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
sysprof_line_visualizer_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = SYSPROF_LINE_VISUALIZER_ROW (object);
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = SYSPROF_LINE_VISUALIZER (object);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_object_get_property (G_OBJECT (priv->label), "label", value);
|
||||
break;
|
||||
|
||||
case PROP_Y_LOWER:
|
||||
g_value_set_double (value, priv->y_lower);
|
||||
break;
|
||||
@ -383,20 +394,16 @@ sysprof_line_visualizer_row_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
sysprof_line_visualizer_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofLineVisualizerRow *self = SYSPROF_LINE_VISUALIZER_ROW (object);
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizer *self = SYSPROF_LINE_VISUALIZER (object);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_object_set_property (G_OBJECT (priv->label), "label", value);
|
||||
break;
|
||||
|
||||
case PROP_Y_LOWER:
|
||||
priv->y_lower = g_value_get_double (value);
|
||||
priv->y_lower_set = TRUE;
|
||||
@ -415,26 +422,19 @@ sysprof_line_visualizer_row_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_class_init (SysprofLineVisualizerRowClass *klass)
|
||||
sysprof_line_visualizer_class_init (SysprofLineVisualizerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofVisualizerRowClass *visualizer_class = SYSPROF_VISUALIZER_ROW_CLASS (klass);
|
||||
SysprofVisualizerClass *visualizer_class = SYSPROF_VISUALIZER_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_line_visualizer_row_finalize;
|
||||
object_class->get_property = sysprof_line_visualizer_row_get_property;
|
||||
object_class->set_property = sysprof_line_visualizer_row_set_property;
|
||||
object_class->finalize = sysprof_line_visualizer_finalize;
|
||||
object_class->get_property = sysprof_line_visualizer_get_property;
|
||||
object_class->set_property = sysprof_line_visualizer_set_property;
|
||||
|
||||
widget_class->draw = sysprof_line_visualizer_row_draw;
|
||||
widget_class->draw = sysprof_line_visualizer_draw;
|
||||
|
||||
visualizer_class->set_reader = sysprof_line_visualizer_row_set_reader;
|
||||
|
||||
properties [PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"The title of the row",
|
||||
NULL,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
visualizer_class->set_reader = sysprof_line_visualizer_set_reader;
|
||||
|
||||
properties [PROP_Y_LOWER] =
|
||||
g_param_spec_double ("y-lower",
|
||||
@ -458,35 +458,22 @@ sysprof_line_visualizer_row_class_init (SysprofLineVisualizerRowClass *klass)
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_init (SysprofLineVisualizerRow *self)
|
||||
sysprof_line_visualizer_init (SysprofLineVisualizer *self)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
PangoAttrList *attrs = pango_attr_list_new ();
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
priv->lines = g_array_new (FALSE, FALSE, sizeof (LineInfo));
|
||||
|
||||
pango_attr_list_insert (attrs, pango_attr_scale_new (PANGO_SCALE_SMALL * PANGO_SCALE_SMALL));
|
||||
|
||||
priv->label = g_object_new (GTK_TYPE_LABEL,
|
||||
"attributes", attrs,
|
||||
"visible", TRUE,
|
||||
"xalign", 0.0f,
|
||||
"yalign", 0.0f,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (priv->label));
|
||||
|
||||
pango_attr_list_unref (attrs);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_line_visualizer_row_add_counter (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color)
|
||||
sysprof_line_visualizer_add_counter (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
LineInfo line_info = { 0 };
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
g_assert (priv->lines != NULL);
|
||||
|
||||
line_info.id = counter_id;
|
||||
@ -506,18 +493,18 @@ sysprof_line_visualizer_row_add_counter (SysprofLineVisualizerRow *self,
|
||||
|
||||
g_array_append_val (priv->lines, line_info);
|
||||
|
||||
if (SYSPROF_LINE_VISUALIZER_ROW_GET_CLASS (self)->counter_added)
|
||||
SYSPROF_LINE_VISUALIZER_ROW_GET_CLASS (self)->counter_added (self, counter_id);
|
||||
if (SYSPROF_LINE_VISUALIZER_GET_CLASS (self)->counter_added)
|
||||
SYSPROF_LINE_VISUALIZER_GET_CLASS (self)->counter_added (self, counter_id);
|
||||
|
||||
sysprof_line_visualizer_row_queue_reload (self);
|
||||
sysprof_line_visualizer_queue_reload (self);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_line_visualizer_row_clear (SysprofLineVisualizerRow *self)
|
||||
sysprof_line_visualizer_clear (SysprofLineVisualizer *self)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
if (priv->lines->len > 0)
|
||||
g_array_remove_range (priv->lines, 0, priv->lines->len);
|
||||
@ -580,8 +567,8 @@ calc_y_int64 (gint64 lower,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_line_visualizer_row_load_data_frame_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
sysprof_line_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
LoadData *load = user_data;
|
||||
|
||||
@ -622,8 +609,8 @@ sysprof_line_visualizer_row_load_data_frame_cb (const SysprofCaptureFrame *frame
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_line_visualizer_row_load_data_range_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
sysprof_line_visualizer_load_data_range_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
LoadData *load = user_data;
|
||||
|
||||
@ -689,16 +676,16 @@ sysprof_line_visualizer_row_load_data_range_cb (const SysprofCaptureFrame *frame
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_load_data_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
sysprof_line_visualizer_load_data_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
LoadData *load = task_data;
|
||||
g_autoptr(GArray) counter_ids = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (source_object));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (source_object));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
counter_ids = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
@ -716,7 +703,7 @@ sysprof_line_visualizer_row_load_data_worker (GTask *task,
|
||||
/* If y boundaries are not set, we need to discover them by scaning the data. */
|
||||
if (!load->y_lower_set || !load->y_upper_set)
|
||||
{
|
||||
sysprof_capture_cursor_foreach (load->cursor, sysprof_line_visualizer_row_load_data_range_cb, load);
|
||||
sysprof_capture_cursor_foreach (load->cursor, sysprof_line_visualizer_load_data_range_cb, load);
|
||||
sysprof_capture_cursor_reset (load->cursor);
|
||||
|
||||
/* Add extra boundary for some space above the graph line */
|
||||
@ -724,26 +711,26 @@ sysprof_line_visualizer_row_load_data_worker (GTask *task,
|
||||
load->y_upper = load->y_upper + ((load->y_upper - load->y_lower) * .25);
|
||||
}
|
||||
|
||||
sysprof_capture_cursor_foreach (load->cursor, sysprof_line_visualizer_row_load_data_frame_cb, load);
|
||||
sysprof_capture_cursor_foreach (load->cursor, sysprof_line_visualizer_load_data_frame_cb, load);
|
||||
g_task_return_pointer (task, g_steal_pointer (&load->cache), (GDestroyNotify)point_cache_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_line_visualizer_row_load_data_async (SysprofLineVisualizerRow *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
sysprof_line_visualizer_load_data_async (SysprofLineVisualizer *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
g_autoptr(GTask) task = NULL;
|
||||
LoadData *load;
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, G_PRIORITY_LOW);
|
||||
g_task_set_source_tag (task, sysprof_line_visualizer_row_load_data_async);
|
||||
g_task_set_source_tag (task, sysprof_line_visualizer_load_data_async);
|
||||
|
||||
if (priv->reader == NULL)
|
||||
{
|
||||
@ -773,18 +760,18 @@ sysprof_line_visualizer_row_load_data_async (SysprofLineVisualizerRow *self,
|
||||
}
|
||||
|
||||
g_task_set_task_data (task, load, load_data_free);
|
||||
g_task_run_in_thread (task, sysprof_line_visualizer_row_load_data_worker);
|
||||
g_task_run_in_thread (task, sysprof_line_visualizer_load_data_worker);
|
||||
}
|
||||
|
||||
static PointCache *
|
||||
sysprof_line_visualizer_row_load_data_finish (SysprofLineVisualizerRow *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
sysprof_line_visualizer_load_data_finish (SysprofLineVisualizer *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
LoadData *state;
|
||||
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
state = g_task_get_task_data (G_TASK (result));
|
||||
@ -805,13 +792,13 @@ sysprof_line_visualizer_row_load_data_finish (SysprofLineVisualizerRow *self,
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_line_visualizer_row_set_line_width (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
gdouble width)
|
||||
sysprof_line_visualizer_set_line_width (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
gdouble width)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
for (guint i = 0; i < priv->lines->len; i++)
|
||||
{
|
||||
@ -820,20 +807,20 @@ sysprof_line_visualizer_row_set_line_width (SysprofLineVisualizerRow *self,
|
||||
if (info->id == counter_id)
|
||||
{
|
||||
info->line_width = width;
|
||||
sysprof_line_visualizer_row_queue_reload (self);
|
||||
sysprof_line_visualizer_queue_reload (self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_line_visualizer_row_set_fill (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color)
|
||||
sysprof_line_visualizer_set_fill (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
for (guint i = 0; i < priv->lines->len; i++)
|
||||
{
|
||||
@ -844,20 +831,20 @@ sysprof_line_visualizer_row_set_fill (SysprofLineVisualizerRow *self,
|
||||
info->fill = !!color;
|
||||
if (color != NULL)
|
||||
info->background = *color;
|
||||
sysprof_line_visualizer_row_queue_reload (self);
|
||||
sysprof_line_visualizer_queue_reload (self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_line_visualizer_row_set_dash (SysprofLineVisualizerRow *self,
|
||||
guint counter_id,
|
||||
gboolean use_dash)
|
||||
sysprof_line_visualizer_set_dash (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
gboolean use_dash)
|
||||
{
|
||||
SysprofLineVisualizerRowPrivate *priv = sysprof_line_visualizer_row_get_instance_private (self);
|
||||
SysprofLineVisualizerPrivate *priv = sysprof_line_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER_ROW (self));
|
||||
g_return_if_fail (SYSPROF_IS_LINE_VISUALIZER (self));
|
||||
|
||||
for (guint i = 0; i < priv->lines->len; i++)
|
||||
{
|
||||
@ -866,7 +853,7 @@ sysprof_line_visualizer_row_set_dash (SysprofLineVisualizerRow *self,
|
||||
if (info->id == counter_id)
|
||||
{
|
||||
info->use_dash = !!use_dash;
|
||||
sysprof_line_visualizer_row_queue_reload (self);
|
||||
sysprof_line_visualizer_queue_reload (self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
57
src/libsysprof-ui/sysprof-line-visualizer.h
Normal file
57
src/libsysprof-ui/sysprof-line-visualizer.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* sysprof-line-visualizer.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_LINE_VISUALIZER (sysprof_line_visualizer_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofLineVisualizer, sysprof_line_visualizer, SYSPROF, LINE_VISUALIZER, SysprofVisualizer)
|
||||
|
||||
struct _SysprofLineVisualizerClass
|
||||
{
|
||||
SysprofVisualizerClass parent_class;
|
||||
|
||||
void (*counter_added) (SysprofLineVisualizer *self,
|
||||
guint counter_id);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
GtkWidget *sysprof_line_visualizer_new (void);
|
||||
void sysprof_line_visualizer_clear (SysprofLineVisualizer *self);
|
||||
void sysprof_line_visualizer_add_counter (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color);
|
||||
void sysprof_line_visualizer_set_line_width (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
gdouble width);
|
||||
void sysprof_line_visualizer_set_fill (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color);
|
||||
void sysprof_line_visualizer_set_dash (SysprofLineVisualizer *self,
|
||||
guint counter_id,
|
||||
gboolean use_dash);
|
||||
|
||||
G_END_DECLS
|
||||
237
src/libsysprof-ui/sysprof-logs-aid.c
Normal file
237
src/libsysprof-ui/sysprof-logs-aid.c
Normal file
@ -0,0 +1,237 @@
|
||||
/* sysprof-logs-aid.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-logs-aid"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-logs-aid.h"
|
||||
#include "sysprof-logs-page.h"
|
||||
#include "sysprof-mark-visualizer.h"
|
||||
|
||||
struct _SysprofLogsAid
|
||||
{
|
||||
SysprofAid parent_instance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofDisplay *display;
|
||||
SysprofCaptureCursor *cursor;
|
||||
GArray *log_marks;
|
||||
} Present;
|
||||
|
||||
G_DEFINE_TYPE (SysprofLogsAid, sysprof_logs_aid, SYSPROF_TYPE_AID)
|
||||
|
||||
static void
|
||||
present_free (gpointer data)
|
||||
{
|
||||
Present *p = data;
|
||||
|
||||
g_clear_pointer (&p->log_marks, g_array_unref);
|
||||
g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_object (&p->display);
|
||||
g_slice_free (Present, p);
|
||||
}
|
||||
|
||||
static void
|
||||
on_group_activated_cb (SysprofVisualizerGroup *group,
|
||||
SysprofPage *page)
|
||||
{
|
||||
SysprofDisplay *display;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_GROUP (group));
|
||||
g_assert (SYSPROF_IS_PAGE (page));
|
||||
|
||||
display = SYSPROF_DISPLAY (gtk_widget_get_ancestor (GTK_WIDGET (page), SYSPROF_TYPE_DISPLAY));
|
||||
sysprof_display_set_visible_page (display, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_logs_aid_new:
|
||||
*
|
||||
* Create a new #SysprofLogsAid.
|
||||
*
|
||||
* Returns: (transfer full): a newly created #SysprofLogsAid
|
||||
*/
|
||||
SysprofAid *
|
||||
sysprof_logs_aid_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_LOGS_AID, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_marks_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
Present *p = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (p != NULL);
|
||||
|
||||
if (frame->type == SYSPROF_CAPTURE_FRAME_LOG)
|
||||
{
|
||||
SysprofMarkTimeSpan span = { frame->time, frame->time };
|
||||
g_array_append_val (p->log_marks, span);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_span (const SysprofMarkTimeSpan *a,
|
||||
const SysprofMarkTimeSpan *b)
|
||||
{
|
||||
if (a->kind < b->kind)
|
||||
return -1;
|
||||
|
||||
if (b->kind < a->kind)
|
||||
return 1;
|
||||
|
||||
if (a->begin < b->begin)
|
||||
return -1;
|
||||
|
||||
if (b->begin < a->begin)
|
||||
return 1;
|
||||
|
||||
if (b->end > a->end)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_aid_present_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Present *p = task_data;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (p != NULL);
|
||||
g_assert (SYSPROF_IS_DISPLAY (p->display));
|
||||
g_assert (p->cursor != NULL);
|
||||
g_assert (SYSPROF_IS_LOGS_AID (source_object));
|
||||
|
||||
sysprof_capture_cursor_foreach (p->cursor, find_marks_cb, p);
|
||||
g_array_sort (p->log_marks, (GCompareFunc)compare_span);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_aid_present_async (SysprofAid *aid,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const SysprofCaptureFrameType logs[] = {
|
||||
SYSPROF_CAPTURE_FRAME_LOG,
|
||||
};
|
||||
SysprofLogsAid *self = (SysprofLogsAid *)aid;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
Present p = {0};
|
||||
|
||||
g_assert (SYSPROF_IS_LOGS_AID (self));
|
||||
|
||||
p.display = g_object_ref (display);
|
||||
p.log_marks = g_array_new (FALSE, FALSE, sizeof (SysprofMarkTimeSpan));
|
||||
p.cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (p.cursor,
|
||||
sysprof_capture_condition_new_where_type_in (1, logs));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_logs_aid_present_async);
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Present, &p),
|
||||
present_free);
|
||||
g_task_run_in_thread (task, sysprof_logs_aid_present_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_logs_aid_present_finish (SysprofAid *aid,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
Present *p;
|
||||
|
||||
g_assert (SYSPROF_IS_LOGS_AID (aid));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
p = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
if (p->log_marks->len > 0)
|
||||
{
|
||||
g_autoptr(GHashTable) items = NULL;
|
||||
SysprofVisualizerGroup *group;
|
||||
SysprofVisualizer *marks;
|
||||
SysprofPage *page;
|
||||
|
||||
items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify) g_array_unref);
|
||||
g_hash_table_insert (items, g_strdup (_("Logs")), g_array_ref (p->log_marks));
|
||||
|
||||
group = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"title", _("Logs"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
marks = sysprof_mark_visualizer_new (items);
|
||||
sysprof_visualizer_set_title (marks, _("Logs"));
|
||||
gtk_widget_show (GTK_WIDGET (marks));
|
||||
sysprof_visualizer_group_insert (group, marks, 0, FALSE);
|
||||
sysprof_display_add_group (p->display, group);
|
||||
|
||||
page = g_object_new (SYSPROF_TYPE_LOGS_PAGE,
|
||||
"title", _("Logs"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
sysprof_display_add_page (p->display, page);
|
||||
|
||||
g_signal_connect_object (group,
|
||||
"group-activated",
|
||||
G_CALLBACK (on_group_activated_cb),
|
||||
page,
|
||||
0);
|
||||
}
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_aid_class_init (SysprofLogsAidClass *klass)
|
||||
{
|
||||
SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass);
|
||||
|
||||
aid_class->present_async = sysprof_logs_aid_present_async;
|
||||
aid_class->present_finish = sysprof_logs_aid_present_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_aid_init (SysprofLogsAid *self)
|
||||
{
|
||||
}
|
||||
33
src/libsysprof-ui/sysprof-logs-aid.h
Normal file
33
src/libsysprof-ui/sysprof-logs-aid.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* sysprof-logs-aid.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-aid.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_LOGS_AID (sysprof_logs_aid_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofLogsAid, sysprof_logs_aid, SYSPROF, LOGS_AID, SysprofAid)
|
||||
|
||||
SysprofAid *sysprof_logs_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
116
src/libsysprof-ui/sysprof-logs-page.c
Normal file
116
src/libsysprof-ui/sysprof-logs-page.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* sysprof-logs-page.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-logs-page"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-log-model.h"
|
||||
#include "sysprof-logs-page.h"
|
||||
|
||||
struct _SysprofLogsPage
|
||||
{
|
||||
SysprofPage parent_instance;
|
||||
|
||||
/* Template Widgets */
|
||||
GtkTreeView *tree_view;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SysprofLogsPage, sysprof_logs_page, SYSPROF_TYPE_PAGE)
|
||||
|
||||
static void
|
||||
sysprof_logs_page_load_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofLogsPage *self;
|
||||
g_autoptr(SysprofLogModel) model = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = user_data;
|
||||
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if (!(model = sysprof_log_model_new_finish (result, &error)))
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
|
||||
gtk_tree_view_set_model (self->tree_view, GTK_TREE_MODEL (model));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_page_load_async (SysprofPage *page,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
SysprofCaptureCondition *filter,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofLogsPage *self = (SysprofLogsPage *)page;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_LOGS_PAGE (self));
|
||||
g_assert (reader != NULL);
|
||||
g_assert (!selection || SYSPROF_IS_SELECTION (selection));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_logs_page_load_async);
|
||||
|
||||
sysprof_log_model_new_async (reader,
|
||||
selection,
|
||||
cancellable,
|
||||
sysprof_logs_page_load_cb,
|
||||
g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_logs_page_load_finish (SysprofPage *page,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_assert (SYSPROF_IS_LOGS_PAGE (page));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_page_class_init (SysprofLogsPageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass);
|
||||
|
||||
page_class->load_async = sysprof_logs_page_load_async;
|
||||
page_class->load_finish = sysprof_logs_page_load_finish;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-logs-page.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofLogsPage, tree_view);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_logs_page_init (SysprofLogsPage *self)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/* sysprof-visualizer-row-private.h
|
||||
/* sysprof-logs-page.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
* Copyright 2019 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
|
||||
@ -20,10 +20,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-page.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gint _sysprof_visualizer_row_get_graph_width (SysprofVisualizerRow *self);
|
||||
#define SYSPROF_TYPE_LOGS_PAGE (sysprof_logs_page_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofLogsPage, sysprof_logs_page, SYSPROF, LOGS_PAGE, SysprofPage)
|
||||
|
||||
G_END_DECLS
|
||||
75
src/libsysprof-ui/sysprof-logs-page.ui
Normal file
75
src/libsysprof-ui/sysprof-logs-page.ui
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofLogsPage" parent="SysprofPage">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="tree_view">
|
||||
<property name="tooltip-column">3</property>
|
||||
<property name="headers-visible">true</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="expand">false</property>
|
||||
<property name="title" translatable="yes">Time</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">4</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="expand">false</property>
|
||||
<property name="title" translatable="yes">Severity</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="expand">false</property>
|
||||
<property name="resizable">true</property>
|
||||
<property name="title" translatable="yes">Domain</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="expand">true</property>
|
||||
<property name="title" translatable="yes">Message</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@ -1,492 +0,0 @@
|
||||
/* sysprof-mark-visualizer-row.c
|
||||
*
|
||||
* Copyright 2018-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-mark-visualizer-row"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sysprof-capture-condition.h"
|
||||
#include "sysprof-capture-cursor.h"
|
||||
#include "rectangles.h"
|
||||
#include "sysprof-mark-visualizer-row.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* Our reader as assigned by the visualizer system.
|
||||
*/
|
||||
SysprofCaptureReader *reader;
|
||||
|
||||
/*
|
||||
* The group we care about for displaying marks. The idea is that we only
|
||||
* show one group per-row, so tooling from separate systems can either be
|
||||
* displayed together or not, based on usefulness.
|
||||
*/
|
||||
gchar *group;
|
||||
|
||||
/*
|
||||
* Rectangle information we have built from the marks that belong to this
|
||||
* row of information.
|
||||
*/
|
||||
Rectangles *rectangles;
|
||||
|
||||
/*
|
||||
* Child widget to display the label in the upper corner.
|
||||
*/
|
||||
GtkLabel *label;
|
||||
} SysprofMarkVisualizerRowPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *group;
|
||||
SysprofCaptureCursor *cursor;
|
||||
Rectangles *rects;
|
||||
GHashTable *inferred_rects;
|
||||
} BuildState;
|
||||
|
||||
typedef struct {
|
||||
gint64 time;
|
||||
gchar *name;
|
||||
gchar *message;
|
||||
} InferredRect;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_GROUP,
|
||||
PROP_TITLE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofMarkVisualizerRow, sysprof_mark_visualizer_row, SYSPROF_TYPE_VISUALIZER_ROW)
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void
|
||||
free_inferred_rect (InferredRect *rect)
|
||||
{
|
||||
g_free (rect->name);
|
||||
g_free (rect->message);
|
||||
g_slice_free (InferredRect, rect);
|
||||
}
|
||||
|
||||
static void
|
||||
add_inferred_rect_point (BuildState *state,
|
||||
InferredRect *rect)
|
||||
{
|
||||
rectangles_add (state->rects,
|
||||
rect->time,
|
||||
rect->time,
|
||||
rect->name,
|
||||
rect->message);
|
||||
}
|
||||
|
||||
static void
|
||||
build_state_free (BuildState *state)
|
||||
{
|
||||
g_hash_table_remove_all (state->inferred_rects);
|
||||
g_clear_pointer (&state->inferred_rects, g_hash_table_unref);
|
||||
g_free (state->group);
|
||||
g_clear_pointer (&state->cursor, sysprof_capture_cursor_unref);
|
||||
g_slice_free (BuildState, state);
|
||||
}
|
||||
|
||||
/* Creates rectangles for GPU marks.
|
||||
*
|
||||
* GPU marks come in as a begin and an end, but since those things are
|
||||
* processessed on potentially different CPUs, perf doesn't record
|
||||
* them in sequence order in the mmap ringbuffer. Thus, we have to
|
||||
* shuffle things back around at visualization time.
|
||||
*/
|
||||
static gboolean
|
||||
process_gpu_mark (BuildState *state,
|
||||
const SysprofCaptureMark *mark)
|
||||
{
|
||||
InferredRect *rect = g_hash_table_lookup (state->inferred_rects,
|
||||
mark->message);
|
||||
|
||||
if (rect)
|
||||
{
|
||||
gboolean ours_begins = strstr (mark->name, "begin") != NULL;
|
||||
gboolean theirs_begins = strstr (rect->name, "begin") != NULL;
|
||||
|
||||
if (ours_begins != theirs_begins)
|
||||
{
|
||||
rectangles_add (state->rects,
|
||||
ours_begins ? mark->frame.time : rect->time,
|
||||
ours_begins ? rect->time : mark->frame.time,
|
||||
ours_begins ? mark->name : rect->name,
|
||||
rect->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something went weird with the tracking (GPU hang caused
|
||||
* two starts?), so just put up both time points as vertical
|
||||
* bars for now.
|
||||
*/
|
||||
rectangles_add (state->rects,
|
||||
mark->frame.time,
|
||||
mark->frame.time,
|
||||
mark->name,
|
||||
mark->message);
|
||||
|
||||
add_inferred_rect_point (state, rect);
|
||||
}
|
||||
|
||||
g_hash_table_remove (state->inferred_rects,
|
||||
rect->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = g_slice_new0 (InferredRect);
|
||||
rect->name = g_strdup (mark->name);
|
||||
rect->message = g_strdup (mark->message);
|
||||
rect->time = mark->frame.time;
|
||||
|
||||
g_hash_table_insert (state->inferred_rects, rect->message, rect);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
sysprof_mark_visualizer_row_add_rect (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
BuildState *state = user_data;
|
||||
const SysprofCaptureMark *mark = (const SysprofCaptureMark *)frame;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_MARK);
|
||||
g_assert (state != NULL);
|
||||
g_assert (state->rects != NULL);
|
||||
|
||||
if (g_strcmp0 (mark->group, state->group) == 0)
|
||||
{
|
||||
if (strstr (mark->name, "gpu begin") != NULL ||
|
||||
strstr (mark->name, "gpu end") != NULL)
|
||||
process_gpu_mark (state, mark);
|
||||
else
|
||||
rectangles_add (state->rects,
|
||||
frame->time,
|
||||
frame->time + mark->duration,
|
||||
mark->name,
|
||||
mark->message);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
BuildState *state = task_data;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
gint64 end_time;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER_ROW (source_object));
|
||||
g_assert (state != NULL);
|
||||
g_assert (state->cursor != NULL);
|
||||
|
||||
sysprof_capture_cursor_foreach (state->cursor, sysprof_mark_visualizer_row_add_rect, state);
|
||||
|
||||
/* If any inferred rects are left incomplete, just drop them in as
|
||||
* point events for now.
|
||||
*/
|
||||
g_hash_table_iter_init (&iter, state->inferred_rects);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
InferredRect *rect = value;
|
||||
|
||||
add_inferred_rect_point (state, rect);
|
||||
}
|
||||
g_hash_table_remove_all (state->inferred_rects);
|
||||
|
||||
end_time = sysprof_capture_reader_get_end_time (sysprof_capture_cursor_get_reader (state->cursor));
|
||||
rectangles_set_end_time (state->rects, end_time);
|
||||
g_task_return_pointer (task, g_steal_pointer (&state->rects), (GDestroyNotify)rectangles_free);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_mark_visualizer_row_query_tooltip (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard_mode,
|
||||
GtkTooltip *tooltip)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = (SysprofMarkVisualizerRow *)widget;
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER_ROW (self));
|
||||
|
||||
if (priv->rectangles == NULL)
|
||||
return FALSE;
|
||||
|
||||
return rectangles_query_tooltip (priv->rectangles, tooltip, priv->group, x, y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_mark_visualizer_row_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = (SysprofMarkVisualizerRow *)widget;
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
GtkStyleContext *style_context;
|
||||
GtkStateFlags flags;
|
||||
GdkRGBA foreground;
|
||||
GtkAllocation alloc;
|
||||
gboolean ret;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER_ROW (widget));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
ret = GTK_WIDGET_CLASS (sysprof_mark_visualizer_row_parent_class)->draw (widget, cr);
|
||||
|
||||
if (priv->rectangles == NULL)
|
||||
return ret;
|
||||
|
||||
style_context = gtk_widget_get_style_context (widget);
|
||||
flags = gtk_widget_get_state_flags (widget);
|
||||
gtk_style_context_get_color (style_context, flags, &foreground);
|
||||
|
||||
rectangles_draw (priv->rectangles, GTK_WIDGET (self), cr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
data_load_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = (SysprofMarkVisualizerRow *)object;
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER_ROW (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
g_clear_pointer (&priv->rectangles, rectangles_free);
|
||||
priv->rectangles = g_task_propagate_pointer (G_TASK (result), NULL);
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_reload (SysprofMarkVisualizerRow *self)
|
||||
{
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
SysprofCaptureCondition *condition;
|
||||
BuildState *state;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER_ROW (self));
|
||||
|
||||
g_clear_pointer (&priv->rectangles, rectangles_free);
|
||||
|
||||
condition = sysprof_capture_condition_new_where_type_in (1, (SysprofCaptureFrameType[]) { SYSPROF_CAPTURE_FRAME_MARK });
|
||||
cursor = sysprof_capture_cursor_new (priv->reader);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
state = g_slice_new0 (BuildState);
|
||||
state->inferred_rects = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL,
|
||||
(GDestroyNotify)free_inferred_rect);
|
||||
state->group = g_strdup (priv->group);
|
||||
state->cursor = g_steal_pointer (&cursor);
|
||||
state->rects = rectangles_new (sysprof_capture_reader_get_start_time (priv->reader),
|
||||
sysprof_capture_reader_get_end_time (priv->reader));
|
||||
|
||||
task = g_task_new (self, NULL, data_load_cb, NULL);
|
||||
g_task_set_task_data (task, state, (GDestroyNotify)build_state_free);
|
||||
g_task_run_in_thread (task, sysprof_mark_visualizer_row_worker);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_set_reader (SysprofVisualizerRow *row,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = (SysprofMarkVisualizerRow *)row;
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER_ROW (self));
|
||||
|
||||
if (reader != priv->reader)
|
||||
{
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
if (reader != NULL)
|
||||
priv->reader = sysprof_capture_reader_ref (reader);
|
||||
sysprof_mark_visualizer_row_reload (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_finalize (GObject *object)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = (SysprofMarkVisualizerRow *)object;
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->group, g_free);
|
||||
g_clear_pointer (&priv->rectangles, rectangles_free);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_mark_visualizer_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = SYSPROF_MARK_VISUALIZER_ROW (object);
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_GROUP:
|
||||
g_value_set_string (value, sysprof_mark_visualizer_row_get_group (self));
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, gtk_label_get_label (priv->label));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarkVisualizerRow *self = SYSPROF_MARK_VISUALIZER_ROW (object);
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_GROUP:
|
||||
sysprof_mark_visualizer_row_set_group (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
gtk_label_set_label (priv->label, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_class_init (SysprofMarkVisualizerRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
SysprofVisualizerRowClass *visualizer_class = SYSPROF_VISUALIZER_ROW_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_mark_visualizer_row_finalize;
|
||||
object_class->get_property = sysprof_mark_visualizer_row_get_property;
|
||||
object_class->set_property = sysprof_mark_visualizer_row_set_property;
|
||||
|
||||
widget_class->draw = sysprof_mark_visualizer_row_draw;
|
||||
widget_class->query_tooltip = sysprof_mark_visualizer_row_query_tooltip;
|
||||
|
||||
visualizer_class->set_reader = sysprof_mark_visualizer_row_set_reader;
|
||||
|
||||
properties [PROP_GROUP] =
|
||||
g_param_spec_string ("group",
|
||||
"Group",
|
||||
"The group of the row",
|
||||
NULL,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"The title of the row",
|
||||
NULL,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_row_init (SysprofMarkVisualizerRow *self)
|
||||
{
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
PangoAttrList *attrs = pango_attr_list_new ();
|
||||
|
||||
gtk_widget_set_has_tooltip (GTK_WIDGET (self), TRUE);
|
||||
|
||||
pango_attr_list_insert (attrs, pango_attr_scale_new (PANGO_SCALE_SMALL * PANGO_SCALE_SMALL));
|
||||
|
||||
priv->label = g_object_new (GTK_TYPE_LABEL,
|
||||
"attributes", attrs,
|
||||
"visible", TRUE,
|
||||
"xalign", 0.0f,
|
||||
"yalign", 0.0f,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (priv->label));
|
||||
|
||||
pango_attr_list_unref (attrs);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
sysprof_mark_visualizer_row_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_MARK_VISUALIZER_ROW, NULL);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
sysprof_mark_visualizer_row_get_group (SysprofMarkVisualizerRow *self)
|
||||
{
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_MARK_VISUALIZER_ROW (self), NULL);
|
||||
|
||||
return priv->group;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_mark_visualizer_row_set_group (SysprofMarkVisualizerRow *self,
|
||||
const gchar *group)
|
||||
{
|
||||
SysprofMarkVisualizerRowPrivate *priv = sysprof_mark_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_MARK_VISUALIZER_ROW (self));
|
||||
|
||||
if (g_strcmp0 (priv->group, group) != 0)
|
||||
{
|
||||
g_free (priv->group);
|
||||
priv->group = g_strdup (group);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_GROUP]);
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/* sysprof-mark-visualizer-row.h
|
||||
*
|
||||
* Copyright 2018-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-version-macros.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_MARK_VISUALIZER_ROW (sysprof_mark_visualizer_row_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofMarkVisualizerRow, sysprof_mark_visualizer_row, SYSPROF, MARK_VISUALIZER_ROW, SysprofVisualizerRow)
|
||||
|
||||
struct _SysprofMarkVisualizerRowClass
|
||||
{
|
||||
SysprofVisualizerRowClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_mark_visualizer_row_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
const gchar *sysprof_mark_visualizer_row_get_group (SysprofMarkVisualizerRow *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_mark_visualizer_row_set_group (SysprofMarkVisualizerRow *self,
|
||||
const gchar *group);
|
||||
|
||||
G_END_DECLS
|
||||
287
src/libsysprof-ui/sysprof-mark-visualizer.c
Normal file
287
src/libsysprof-ui/sysprof-mark-visualizer.c
Normal file
@ -0,0 +1,287 @@
|
||||
/* sysprof-mark-visualizer.c
|
||||
*
|
||||
* Copyright 2018-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-mark-visualizer"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-mark-visualizer.h"
|
||||
|
||||
#define RECT_HEIGHT (4)
|
||||
#define RECT_MIN_WIDTH (3)
|
||||
#define RECT_OVERLAP (-1)
|
||||
|
||||
struct _SysprofMarkVisualizer
|
||||
{
|
||||
SysprofVisualizer parent_instance;
|
||||
GHashTable *spans_by_group;
|
||||
GHashTable *rgba_by_group;
|
||||
GHashTable *rgba_by_kind;
|
||||
GHashTable *row_by_kind;
|
||||
guint x_is_dirty : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SysprofMarkVisualizer, sysprof_mark_visualizer, SYSPROF_TYPE_VISUALIZER)
|
||||
|
||||
static void
|
||||
reset_positions (SysprofMarkVisualizer *self)
|
||||
{
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER (self));
|
||||
|
||||
self->x_is_dirty = TRUE;
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
SysprofVisualizer *
|
||||
sysprof_mark_visualizer_new (GHashTable *groups)
|
||||
{
|
||||
SysprofMarkVisualizer *self;
|
||||
guint n_items;
|
||||
gint height;
|
||||
|
||||
g_return_val_if_fail (groups != NULL, NULL);
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_MARK_VISUALIZER, NULL);
|
||||
self->spans_by_group = g_hash_table_ref (groups);
|
||||
|
||||
reset_positions (self);
|
||||
|
||||
n_items = g_hash_table_size (groups);
|
||||
height = MAX (35, n_items * (RECT_HEIGHT - RECT_OVERLAP));
|
||||
gtk_widget_set_size_request (GTK_WIDGET (self), -1, height);
|
||||
|
||||
return SYSPROF_VISUALIZER (g_steal_pointer (&self));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_mark_visualizer_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofMarkVisualizer *self = (SysprofMarkVisualizer *)widget;
|
||||
SysprofVisualizer *vis = (SysprofVisualizer *)widget;
|
||||
GHashTableIter iter;
|
||||
GtkAllocation alloc;
|
||||
gpointer k, v;
|
||||
gboolean ret;
|
||||
gint n_groups = 0;
|
||||
gint y = 0;
|
||||
|
||||
g_assert (SYSPROF_IS_MARK_VISUALIZER (self));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
ret = GTK_WIDGET_CLASS (sysprof_mark_visualizer_parent_class)->draw (widget, cr);
|
||||
if (self->spans_by_group == NULL)
|
||||
return ret;
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
/* Pre-calculate all time slots so we can join later */
|
||||
if (self->x_is_dirty)
|
||||
{
|
||||
g_hash_table_iter_init (&iter, self->spans_by_group);
|
||||
while (g_hash_table_iter_next (&iter, &k, &v))
|
||||
{
|
||||
const GArray *spans = v;
|
||||
|
||||
for (guint i = 0; i < spans->len; i++)
|
||||
{
|
||||
SysprofMarkTimeSpan *span = &g_array_index (spans, SysprofMarkTimeSpan, i);
|
||||
|
||||
span->x = sysprof_visualizer_get_x_for_time (vis, span->begin);
|
||||
span->x2 = sysprof_visualizer_get_x_for_time (vis, span->end);
|
||||
}
|
||||
}
|
||||
|
||||
self->x_is_dirty = FALSE;
|
||||
}
|
||||
|
||||
n_groups = g_hash_table_size (self->spans_by_group);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (guint i = 0; i < spans->len; i++)
|
||||
{
|
||||
gint x1, x2;
|
||||
|
||||
span = &g_array_index (spans, SysprofMarkTimeSpan, i);
|
||||
|
||||
if (n_groups == 1)
|
||||
{
|
||||
rgba = &black;
|
||||
if ((kindrgba = g_hash_table_lookup (self->rgba_by_kind, GUINT_TO_POINTER (span->kind))))
|
||||
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;
|
||||
x2 = x1 + RECT_MIN_WIDTH;
|
||||
|
||||
if (span->x2 > x2)
|
||||
x2 = span->x2;
|
||||
|
||||
/* If we are limited to one group, we might need to get the row
|
||||
* height for the kind of span this is.
|
||||
*/
|
||||
if (n_groups == 1)
|
||||
{
|
||||
gint row = GPOINTER_TO_INT (g_hash_table_lookup (self->row_by_kind, GUINT_TO_POINTER (span->kind)));
|
||||
y = row * (RECT_HEIGHT - RECT_OVERLAP);
|
||||
}
|
||||
|
||||
for (guint j = i + 1; j < spans->len; j++)
|
||||
{
|
||||
const SysprofMarkTimeSpan *next = &g_array_index (spans, SysprofMarkTimeSpan, j);
|
||||
|
||||
/* Don't join this if we are about to draw a different kind */
|
||||
if (n_groups == 1 && next->kind != span->kind)
|
||||
break;
|
||||
|
||||
if (next->x <= x2)
|
||||
{
|
||||
x2 = MAX (x2, next->x2);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cairo_rectangle (cr, x1, y, x2 - x1, RECT_HEIGHT);
|
||||
|
||||
if (n_groups == 1)
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
if (n_groups > 1)
|
||||
cairo_fill (cr);
|
||||
|
||||
y += RECT_HEIGHT + RECT_OVERLAP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *alloc)
|
||||
{
|
||||
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);
|
||||
|
||||
reset_positions (self);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_finalize (GObject *object)
|
||||
{
|
||||
SysprofMarkVisualizer *self = (SysprofMarkVisualizer *)object;
|
||||
|
||||
g_clear_pointer (&self->spans_by_group, g_hash_table_unref);
|
||||
g_clear_pointer (&self->rgba_by_group, g_hash_table_unref);
|
||||
g_clear_pointer (&self->rgba_by_kind, g_hash_table_unref);
|
||||
g_clear_pointer (&self->row_by_kind, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_mark_visualizer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_class_init (SysprofMarkVisualizerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_mark_visualizer_finalize;
|
||||
|
||||
widget_class->draw = sysprof_mark_visualizer_draw;
|
||||
widget_class->size_allocate = sysprof_mark_visualizer_size_allocate;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_mark_visualizer_init (SysprofMarkVisualizer *self)
|
||||
{
|
||||
self->rgba_by_kind = g_hash_table_new_full (NULL, NULL, NULL, g_free);
|
||||
self->row_by_kind = g_hash_table_new (NULL, NULL);
|
||||
self->rgba_by_group = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_mark_visualizer_set_group_rgba (SysprofMarkVisualizer *self,
|
||||
const gchar *group,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_MARK_VISUALIZER (self));
|
||||
g_return_if_fail (group != NULL);
|
||||
|
||||
g_hash_table_insert (self->rgba_by_group,
|
||||
g_strdup (group),
|
||||
g_memdup (rgba, sizeof *rgba));
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_mark_visualizer_set_kind_rgba (SysprofMarkVisualizer *self,
|
||||
GHashTable *rgba_by_kind)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_MARK_VISUALIZER (self));
|
||||
|
||||
if (rgba_by_kind != self->rgba_by_kind)
|
||||
{
|
||||
g_hash_table_remove_all (self->row_by_kind);
|
||||
|
||||
g_clear_pointer (&self->rgba_by_kind, g_hash_table_unref);
|
||||
|
||||
if (rgba_by_kind)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
guint row = 0;
|
||||
gpointer k;
|
||||
|
||||
self->rgba_by_kind = g_hash_table_ref (rgba_by_kind);
|
||||
|
||||
g_hash_table_iter_init (&iter, rgba_by_kind);
|
||||
while (g_hash_table_iter_next (&iter, &k, NULL))
|
||||
g_hash_table_insert (self->row_by_kind, k, GUINT_TO_POINTER (row++));
|
||||
|
||||
gtk_widget_set_size_request (GTK_WIDGET (self),
|
||||
-1,
|
||||
MAX (35, row * (RECT_HEIGHT - RECT_OVERLAP)));
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/libsysprof-ui/sysprof-mark-visualizer.h
Normal file
47
src/libsysprof-ui/sysprof-mark-visualizer.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* sysprof-mark-visualizer.h
|
||||
*
|
||||
* Copyright 2018-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint64 begin;
|
||||
gint64 end;
|
||||
guint kind;
|
||||
gint x;
|
||||
gint x2;
|
||||
} SysprofMarkTimeSpan;
|
||||
|
||||
#define SYSPROF_TYPE_MARK_VISUALIZER (sysprof_mark_visualizer_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofMarkVisualizer, sysprof_mark_visualizer, SYSPROF, MARK_VISUALIZER, SysprofVisualizer)
|
||||
|
||||
SysprofVisualizer *sysprof_mark_visualizer_new (GHashTable *groups);
|
||||
void sysprof_mark_visualizer_set_group_rgba (SysprofMarkVisualizer *self,
|
||||
const gchar *group,
|
||||
const GdkRGBA *rgba);
|
||||
void sysprof_mark_visualizer_set_kind_rgba (SysprofMarkVisualizer *self,
|
||||
GHashTable *rgba_by_kind);
|
||||
|
||||
G_END_DECLS
|
||||
319
src/libsysprof-ui/sysprof-marks-aid.c
Normal file
319
src/libsysprof-ui/sysprof-marks-aid.c
Normal file
@ -0,0 +1,319 @@
|
||||
/* sysprof-marks-aid.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-marks-aid"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-color-cycle.h"
|
||||
#include "sysprof-marks-aid.h"
|
||||
#include "sysprof-marks-page.h"
|
||||
#include "sysprof-mark-visualizer.h"
|
||||
|
||||
struct _SysprofMarksAid
|
||||
{
|
||||
SysprofAid parent_instance;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofDisplay *display;
|
||||
SysprofCaptureCursor *cursor;
|
||||
GHashTable *categories;
|
||||
GHashTable *kinds;
|
||||
guint last_kind;
|
||||
guint has_marks : 1;
|
||||
} Present;
|
||||
|
||||
G_DEFINE_TYPE (SysprofMarksAid, sysprof_marks_aid, SYSPROF_TYPE_AID)
|
||||
|
||||
static void
|
||||
present_free (gpointer data)
|
||||
{
|
||||
Present *p = data;
|
||||
|
||||
g_clear_pointer (&p->categories, g_hash_table_unref);
|
||||
g_clear_pointer (&p->kinds, g_hash_table_unref);
|
||||
g_clear_pointer (&p->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_object (&p->display);
|
||||
g_slice_free (Present, p);
|
||||
}
|
||||
|
||||
static void
|
||||
on_group_activated_cb (SysprofVisualizerGroup *group,
|
||||
SysprofPage *page)
|
||||
{
|
||||
SysprofDisplay *display;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_GROUP (group));
|
||||
g_assert (SYSPROF_IS_PAGE (page));
|
||||
|
||||
display = SYSPROF_DISPLAY (gtk_widget_get_ancestor (GTK_WIDGET (page), SYSPROF_TYPE_DISPLAY));
|
||||
sysprof_display_set_visible_page (display, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_marks_aid_new:
|
||||
*
|
||||
* Create a new #SysprofMarksAid.
|
||||
*
|
||||
* Returns: (transfer full): a newly created #SysprofMarksAid
|
||||
*/
|
||||
SysprofAid *
|
||||
sysprof_marks_aid_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_MARKS_AID, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_marks_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
Present *p = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (p != NULL);
|
||||
|
||||
if (frame->type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||
{
|
||||
const SysprofCaptureMark *mark = (const SysprofCaptureMark *)frame;
|
||||
SysprofMarkTimeSpan span = { frame->time, frame->time + mark->duration };
|
||||
gchar joined[64];
|
||||
gpointer kptr;
|
||||
GArray *items;
|
||||
|
||||
p->has_marks = TRUE;
|
||||
|
||||
if G_UNLIKELY (!(items = g_hash_table_lookup (p->categories, mark->group)))
|
||||
{
|
||||
items = g_array_new (FALSE, FALSE, sizeof (SysprofMarkTimeSpan));
|
||||
g_hash_table_insert (p->categories, g_strdup (mark->group), items);
|
||||
}
|
||||
|
||||
g_snprintf (joined, sizeof joined, "%s:%s", mark->group, mark->name);
|
||||
|
||||
if G_UNLIKELY (!(kptr = g_hash_table_lookup (p->kinds, joined)))
|
||||
{
|
||||
p->last_kind++;
|
||||
kptr = GINT_TO_POINTER (p->last_kind);
|
||||
g_hash_table_insert (p->kinds, g_strdup (joined), kptr);
|
||||
}
|
||||
|
||||
span.kind = GPOINTER_TO_INT (kptr);
|
||||
|
||||
g_array_append_val (items, span);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_span (const SysprofMarkTimeSpan *a,
|
||||
const SysprofMarkTimeSpan *b)
|
||||
{
|
||||
if (a->kind < b->kind)
|
||||
return -1;
|
||||
|
||||
if (b->kind < a->kind)
|
||||
return 1;
|
||||
|
||||
if (a->begin < b->begin)
|
||||
return -1;
|
||||
|
||||
if (b->begin < a->begin)
|
||||
return 1;
|
||||
|
||||
if (b->end > a->end)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_aid_present_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Present *p = task_data;
|
||||
GHashTableIter iter;
|
||||
gpointer k, v;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (p != NULL);
|
||||
g_assert (SYSPROF_IS_DISPLAY (p->display));
|
||||
g_assert (p->cursor != NULL);
|
||||
g_assert (SYSPROF_IS_MARKS_AID (source_object));
|
||||
|
||||
sysprof_capture_cursor_foreach (p->cursor, find_marks_cb, p);
|
||||
|
||||
g_hash_table_iter_init (&iter, p->categories);
|
||||
while (g_hash_table_iter_next (&iter, &k, &v))
|
||||
{
|
||||
GArray *spans = v;
|
||||
|
||||
g_array_sort (spans, (GCompareFunc)compare_span);
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_aid_present_async (SysprofAid *aid,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofDisplay *display,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const SysprofCaptureFrameType marks[] = {
|
||||
SYSPROF_CAPTURE_FRAME_MARK,
|
||||
};
|
||||
SysprofMarksAid *self = (SysprofMarksAid *)aid;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
Present p = {0};
|
||||
|
||||
g_assert (SYSPROF_IS_MARKS_AID (self));
|
||||
|
||||
p.display = g_object_ref (display);
|
||||
p.categories = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify) g_array_unref);
|
||||
p.kinds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
p.cursor = sysprof_capture_cursor_new (reader);
|
||||
sysprof_capture_cursor_add_condition (p.cursor,
|
||||
sysprof_capture_condition_new_where_type_in (1, marks));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_marks_aid_present_async);
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Present, &p),
|
||||
present_free);
|
||||
g_task_run_in_thread (task, sysprof_marks_aid_present_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_marks_aid_present_finish (SysprofAid *aid,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
Present *p;
|
||||
|
||||
g_assert (SYSPROF_IS_MARKS_AID (aid));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
p = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
if (p->has_marks)
|
||||
{
|
||||
g_autoptr(SysprofColorCycle) cycle = sysprof_color_cycle_new ();
|
||||
SysprofVisualizerGroup *group;
|
||||
SysprofVisualizer *marks;
|
||||
SysprofPage *page;
|
||||
GHashTableIter iter;
|
||||
gpointer k, v;
|
||||
|
||||
group = g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
"can-focus", TRUE,
|
||||
"has-page", TRUE,
|
||||
"title", _("Timings"),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
marks = sysprof_mark_visualizer_new (p->categories);
|
||||
sysprof_visualizer_set_title (marks, _("Timings"));
|
||||
gtk_widget_show (GTK_WIDGET (marks));
|
||||
|
||||
g_hash_table_iter_init (&iter, p->categories);
|
||||
while (g_hash_table_iter_next (&iter, &k, &v))
|
||||
{
|
||||
g_autoptr(GHashTable) seen = g_hash_table_new_full (NULL, NULL, NULL, g_free);
|
||||
g_autoptr(GHashTable) scoped = NULL;
|
||||
SysprofVisualizer *scoped_vis;
|
||||
GArray *spans = v;
|
||||
const gchar *name = k;
|
||||
GdkRGBA rgba;
|
||||
GdkRGBA kind_rgba;
|
||||
gdouble ratio;
|
||||
|
||||
sysprof_color_cycle_next (cycle, &rgba);
|
||||
sysprof_mark_visualizer_set_group_rgba (SYSPROF_MARK_VISUALIZER (marks), name, &rgba);
|
||||
|
||||
/* Now make a scoped row just for this group */
|
||||
scoped = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify)g_array_unref);
|
||||
g_hash_table_insert (scoped, g_strdup (name), g_array_ref (spans));
|
||||
|
||||
scoped_vis = sysprof_mark_visualizer_new (scoped);
|
||||
sysprof_visualizer_set_title (scoped_vis, name);
|
||||
sysprof_mark_visualizer_set_group_rgba (SYSPROF_MARK_VISUALIZER (scoped_vis), name, &rgba);
|
||||
sysprof_visualizer_group_insert (group, scoped_vis, -1, TRUE);
|
||||
|
||||
ratio = .4 / p->last_kind;
|
||||
|
||||
for (guint i = 0; i < spans->len; i++)
|
||||
{
|
||||
const SysprofMarkTimeSpan *span = &g_array_index (spans, SysprofMarkTimeSpan, i);
|
||||
|
||||
if (!g_hash_table_contains (seen, GUINT_TO_POINTER (span->kind)))
|
||||
{
|
||||
dzl_rgba_shade (&rgba, &kind_rgba, 1 + (ratio * span->kind));
|
||||
g_hash_table_insert (seen,
|
||||
GUINT_TO_POINTER (span->kind),
|
||||
g_memdup (&kind_rgba, sizeof kind_rgba));
|
||||
}
|
||||
}
|
||||
|
||||
sysprof_mark_visualizer_set_kind_rgba (SYSPROF_MARK_VISUALIZER (scoped_vis), seen);
|
||||
}
|
||||
|
||||
page = g_object_new (SYSPROF_TYPE_MARKS_PAGE,
|
||||
"zoom-manager", sysprof_display_get_zoom_manager (p->display),
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
|
||||
g_signal_connect_object (group,
|
||||
"group-activated",
|
||||
G_CALLBACK (on_group_activated_cb),
|
||||
page,
|
||||
0);
|
||||
|
||||
sysprof_visualizer_group_insert (group, marks, 0, FALSE);
|
||||
sysprof_display_add_group (p->display, group);
|
||||
sysprof_display_add_page (p->display, page);
|
||||
}
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_aid_class_init (SysprofMarksAidClass *klass)
|
||||
{
|
||||
SysprofAidClass *aid_class = SYSPROF_AID_CLASS (klass);
|
||||
|
||||
aid_class->present_async = sysprof_marks_aid_present_async;
|
||||
aid_class->present_finish = sysprof_marks_aid_present_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_aid_init (SysprofMarksAid *self)
|
||||
{
|
||||
}
|
||||
33
src/libsysprof-ui/sysprof-marks-aid.h
Normal file
33
src/libsysprof-ui/sysprof-marks-aid.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* sysprof-marks-aid.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-aid.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_MARKS_AID (sysprof_marks_aid_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofMarksAid, sysprof_marks_aid, SYSPROF, MARKS_AID, SysprofAid)
|
||||
|
||||
SysprofAid *sysprof_marks_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,4 +1,4 @@
|
||||
/* sysprof-marks-view.c
|
||||
/* sysprof-marks-page.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
@ -18,13 +18,13 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-marks-view"
|
||||
#define G_LOG_DOMAIN "sysprof-marks-page"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-cell-renderer-duration.h"
|
||||
#include "sysprof-marks-model.h"
|
||||
#include "sysprof-marks-view.h"
|
||||
#include "sysprof-marks-page.h"
|
||||
#include "sysprof-ui-private.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
@ -42,10 +42,16 @@ typedef struct
|
||||
/* Template objects */
|
||||
GtkScrolledWindow *scroller;
|
||||
GtkTreeView *tree_view;
|
||||
GtkBox *details_box;
|
||||
GtkTreeViewColumn *duration_column;
|
||||
SysprofCellRendererDuration *duration_cell;
|
||||
GtkStack *stack;
|
||||
} SysprofMarksViewPrivate;
|
||||
GtkLabel *group;
|
||||
GtkLabel *mark;
|
||||
GtkLabel *time;
|
||||
GtkLabel *duration;
|
||||
GtkTextView *message;
|
||||
} SysprofMarksPagePrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@ -56,17 +62,17 @@ enum {
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofMarksView, sysprof_marks_view, GTK_TYPE_BIN)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofMarksPage, sysprof_marks_page, SYSPROF_TYPE_PAGE)
|
||||
|
||||
static gboolean
|
||||
sysprof_marks_view_tree_view_key_press_event_cb (SysprofMarksView *self,
|
||||
sysprof_marks_page_tree_view_key_press_event_cb (SysprofMarksPage *self,
|
||||
const GdkEventKey *key,
|
||||
GtkTreeView *tree_view)
|
||||
{
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
gint dir = 0;
|
||||
|
||||
g_assert (SYSPROF_MARKS_VIEW (self));
|
||||
g_assert (SYSPROF_MARKS_PAGE (self));
|
||||
g_assert (key != NULL);
|
||||
|
||||
if (key->state == 0)
|
||||
@ -127,21 +133,29 @@ get_first_selected (GtkTreeSelection *selection,
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_selection_changed_cb (SysprofMarksView *self,
|
||||
sysprof_marks_page_selection_changed_cb (SysprofMarksPage *self,
|
||||
GtkTreeSelection *selection)
|
||||
{
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_assert (SYSPROF_IS_MARKS_VIEW (self));
|
||||
g_assert (SYSPROF_IS_MARKS_PAGE (self));
|
||||
g_assert (GTK_IS_TREE_SELECTION (selection));
|
||||
|
||||
if (get_first_selected (selection, &model, &iter))
|
||||
{
|
||||
g_autofree gchar *group = NULL;
|
||||
g_autofree gchar *name = NULL;
|
||||
g_autofree gchar *duration_str = NULL;
|
||||
g_autofree gchar *time_str = NULL;
|
||||
g_autofree gchar *text = NULL;
|
||||
GtkAdjustment *adj;
|
||||
gdouble x;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
gint64 duration;
|
||||
gint64 otime;
|
||||
gdouble lower;
|
||||
gdouble upper;
|
||||
gdouble value;
|
||||
@ -149,9 +163,26 @@ sysprof_marks_view_selection_changed_cb (SysprofMarksView *self,
|
||||
gint width;
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
SYSPROF_MARKS_MODEL_COLUMN_GROUP, &group,
|
||||
SYSPROF_MARKS_MODEL_COLUMN_NAME, &name,
|
||||
SYSPROF_MARKS_MODEL_COLUMN_BEGIN_TIME, &begin_time,
|
||||
SYSPROF_MARKS_MODEL_COLUMN_END_TIME, &end_time,
|
||||
SYSPROF_MARKS_MODEL_COLUMN_TEXT, &text,
|
||||
-1);
|
||||
|
||||
duration = end_time - begin_time;
|
||||
duration_str = _sysprof_format_duration (duration);
|
||||
|
||||
otime = begin_time - priv->capture_begin_time;
|
||||
time_str = _sysprof_format_duration (otime);
|
||||
|
||||
gtk_label_set_label (priv->group, group);
|
||||
gtk_label_set_label (priv->mark, name);
|
||||
gtk_label_set_label (priv->duration, duration_str);
|
||||
gtk_label_set_label (priv->time, time_str);
|
||||
|
||||
gtk_text_buffer_set_text (gtk_text_view_get_buffer (priv->message), text, -1);
|
||||
|
||||
adj = gtk_scrolled_window_get_hadjustment (priv->scroller);
|
||||
width = gtk_tree_view_column_get_width (priv->duration_column);
|
||||
x = sysprof_zoom_manager_get_offset_at_time (priv->zoom_manager,
|
||||
@ -173,19 +204,19 @@ sysprof_marks_view_selection_changed_cb (SysprofMarksView *self,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_marks_view_tree_view_query_tooltip_cb (SysprofMarksView *self,
|
||||
sysprof_marks_page_tree_view_query_tooltip_cb (SysprofMarksPage *self,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard_mode,
|
||||
GtkTooltip *tooltip,
|
||||
GtkTreeView *tree_view)
|
||||
{
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
g_autoptr(GtkTreePath) path = NULL;
|
||||
GtkTreeViewColumn *column;
|
||||
gint cell_x, cell_y;
|
||||
|
||||
g_assert (SYSPROF_IS_MARKS_VIEW (self));
|
||||
g_assert (SYSPROF_IS_MARKS_PAGE (self));
|
||||
g_assert (GTK_IS_TOOLTIP (tooltip));
|
||||
g_assert (GTK_IS_TREE_VIEW (tree_view));
|
||||
|
||||
@ -229,162 +260,22 @@ sysprof_marks_view_tree_view_query_tooltip_cb (SysprofMarksView *self,
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_finalize (GObject *object)
|
||||
{
|
||||
SysprofMarksView *self = (SysprofMarksView *)object;
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->zoom_manager);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_marks_view_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarksView *self = SYSPROF_MARKS_VIEW (object);
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_KIND:
|
||||
g_value_set_enum (value, priv->kind);
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
g_value_set_object (value, priv->zoom_manager);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarksView *self = SYSPROF_MARKS_VIEW (object);
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_KIND:
|
||||
priv->kind = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
if (g_set_object (&priv->zoom_manager, g_value_get_object (value)))
|
||||
{
|
||||
g_object_set (priv->duration_cell,
|
||||
"zoom-manager", priv->zoom_manager,
|
||||
NULL);
|
||||
if (priv->zoom_manager)
|
||||
g_signal_connect_object (priv->zoom_manager,
|
||||
"notify::zoom",
|
||||
G_CALLBACK (gtk_tree_view_column_queue_resize),
|
||||
priv->duration_column,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_class_init (SysprofMarksViewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_marks_view_finalize;
|
||||
object_class->get_property = sysprof_marks_view_get_property;
|
||||
object_class->set_property = sysprof_marks_view_set_property;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-marks-view.ui");
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, scroller);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, tree_view);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, duration_cell);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, duration_column);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, stack);
|
||||
|
||||
properties [PROP_KIND] =
|
||||
g_param_spec_enum ("kind", NULL, NULL,
|
||||
SYSPROF_TYPE_MARKS_MODEL_KIND,
|
||||
SYSPROF_MARKS_MODEL_MARKS,
|
||||
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_ZOOM_MANAGER] =
|
||||
g_param_spec_object ("zoom-manager", NULL, NULL,
|
||||
SYSPROF_TYPE_ZOOM_MANAGER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_CELL_RENDERER_DURATION);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_init (SysprofMarksView *self)
|
||||
{
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
|
||||
priv->kind = SYSPROF_MARKS_MODEL_MARKS;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (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",
|
||||
G_CALLBACK (sysprof_marks_view_tree_view_key_press_event_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->tree_view,
|
||||
"query-tooltip",
|
||||
G_CALLBACK (sysprof_marks_view_tree_view_query_tooltip_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (gtk_tree_view_get_selection (priv->tree_view),
|
||||
"changed",
|
||||
G_CALLBACK (sysprof_marks_view_selection_changed_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
sysprof_marks_view_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_MARKS_VIEW, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_view_load_cb (GObject *object,
|
||||
sysprof_marks_page_load_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(SysprofMarksModel) model = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = user_data;
|
||||
SysprofMarksViewPrivate *priv;
|
||||
SysprofMarksPagePrivate *priv;
|
||||
SysprofCaptureReader *reader;
|
||||
SysprofMarksView *self;
|
||||
SysprofMarksPage *self;
|
||||
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
priv = sysprof_marks_view_get_instance_private (self);
|
||||
priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
if (!(model = sysprof_marks_model_new_finish (result, &error)))
|
||||
{
|
||||
@ -414,24 +305,26 @@ sysprof_marks_view_load_cb (GObject *object,
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_marks_view_load_async (SysprofMarksView *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
static void
|
||||
sysprof_marks_page_load_async (SysprofPage *page,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
SysprofCaptureCondition *filter,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
SysprofMarksPage *self = (SysprofMarksPage *)page;
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_MARKS_VIEW (self));
|
||||
g_return_if_fail (SYSPROF_IS_MARKS_PAGE (self));
|
||||
g_return_if_fail (reader != NULL);
|
||||
g_return_if_fail (!selection || SYSPROF_IS_SELECTION (selection));
|
||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_marks_view_load_async);
|
||||
g_task_set_source_tag (task, sysprof_marks_page_load_async);
|
||||
g_task_set_task_data (task,
|
||||
sysprof_capture_reader_ref (reader),
|
||||
(GDestroyNotify) sysprof_capture_reader_unref);
|
||||
@ -440,28 +333,218 @@ sysprof_marks_view_load_async (SysprofMarksView *self,
|
||||
priv->kind,
|
||||
selection,
|
||||
cancellable,
|
||||
sysprof_marks_view_load_cb,
|
||||
sysprof_marks_page_load_cb,
|
||||
g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
gboolean
|
||||
sysprof_marks_view_load_finish (SysprofMarksView *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
static gboolean
|
||||
sysprof_marks_page_load_finish (SysprofPage *page,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_MARKS_VIEW (self), FALSE);
|
||||
g_return_val_if_fail (SYSPROF_IS_MARKS_PAGE (page), FALSE);
|
||||
g_return_val_if_fail (G_IS_TASK (result), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_set_hadjustment (SysprofPage *page,
|
||||
GtkAdjustment *hadjustment)
|
||||
{
|
||||
SysprofMarksPage *self = (SysprofMarksPage *)page;
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_MARKS_PAGE (self));
|
||||
g_assert (!hadjustment || GTK_IS_ADJUSTMENT (hadjustment));
|
||||
|
||||
gtk_scrolled_window_set_hadjustment (priv->scroller, hadjustment);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_set_size_group (SysprofPage *page,
|
||||
GtkSizeGroup *size_group)
|
||||
{
|
||||
SysprofMarksPage *self = (SysprofMarksPage *)page;
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_MARKS_PAGE (self));
|
||||
g_assert (GTK_IS_SIZE_GROUP (size_group));
|
||||
|
||||
gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->details_box));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_finalize (GObject *object)
|
||||
{
|
||||
SysprofMarksPage *self = (SysprofMarksPage *)object;
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->zoom_manager);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_marks_page_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarksPage *self = SYSPROF_MARKS_PAGE (object);
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_KIND:
|
||||
g_value_set_enum (value, priv->kind);
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
g_value_set_object (value, priv->zoom_manager);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofMarksPage *self = SYSPROF_MARKS_PAGE (object);
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_KIND:
|
||||
priv->kind = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
if (g_set_object (&priv->zoom_manager, g_value_get_object (value)))
|
||||
{
|
||||
g_object_set (priv->duration_cell,
|
||||
"zoom-manager", priv->zoom_manager,
|
||||
NULL);
|
||||
if (priv->zoom_manager)
|
||||
g_signal_connect_object (priv->zoom_manager,
|
||||
"notify::zoom",
|
||||
G_CALLBACK (gtk_tree_view_column_queue_resize),
|
||||
priv->duration_column,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_class_init (SysprofMarksPageClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofPageClass *page_class = SYSPROF_PAGE_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_marks_page_finalize;
|
||||
object_class->get_property = sysprof_marks_page_get_property;
|
||||
object_class->set_property = sysprof_marks_page_set_property;
|
||||
|
||||
page_class->load_async = sysprof_marks_page_load_async;
|
||||
page_class->load_finish = sysprof_marks_page_load_finish;
|
||||
page_class->set_hadjustment = sysprof_marks_page_set_hadjustment;
|
||||
page_class->set_size_group = sysprof_marks_page_set_size_group;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-marks-page.ui");
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, details_box);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, duration_cell);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, duration_column);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, scroller);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, stack);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, tree_view);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, group);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksPage, mark);
|
||||
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);
|
||||
|
||||
properties [PROP_KIND] =
|
||||
g_param_spec_enum ("kind", NULL, NULL,
|
||||
SYSPROF_TYPE_MARKS_MODEL_KIND,
|
||||
SYSPROF_MARKS_MODEL_MARKS,
|
||||
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_ZOOM_MANAGER] =
|
||||
g_param_spec_object ("zoom-manager", NULL, NULL,
|
||||
SYSPROF_TYPE_ZOOM_MANAGER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_CELL_RENDERER_DURATION);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_marks_page_init (SysprofMarksPage *self)
|
||||
{
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
priv->kind = SYSPROF_MARKS_MODEL_MARKS;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (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",
|
||||
G_CALLBACK (sysprof_marks_page_tree_view_key_press_event_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->tree_view,
|
||||
"query-tooltip",
|
||||
G_CALLBACK (sysprof_marks_page_tree_view_query_tooltip_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (gtk_tree_view_get_selection (priv->tree_view),
|
||||
"changed",
|
||||
G_CALLBACK (sysprof_marks_page_selection_changed_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
sysprof_marks_page_new (SysprofZoomManager *zoom_manager,
|
||||
SysprofMarksModelKind kind)
|
||||
{
|
||||
SysprofMarksPage *self;
|
||||
SysprofMarksPagePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_ZOOM_MANAGER (zoom_manager), NULL);
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_MARKS_PAGE,
|
||||
"zoom-manager", zoom_manager,
|
||||
NULL);
|
||||
priv = sysprof_marks_page_get_instance_private (self);
|
||||
priv->kind = kind;
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
||||
|
||||
void
|
||||
_sysprof_marks_view_set_hadjustment (SysprofMarksView *self,
|
||||
_sysprof_marks_page_set_hadjustment (SysprofMarksPage *self,
|
||||
GtkAdjustment *hadjustment)
|
||||
{
|
||||
SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self);
|
||||
SysprofMarksPagePrivate *priv = sysprof_marks_page_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_MARKS_VIEW (self));
|
||||
g_return_if_fail (SYSPROF_IS_MARKS_PAGE (self));
|
||||
g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment));
|
||||
|
||||
gtk_scrolled_window_set_hadjustment (priv->scroller, hadjustment);
|
||||
@ -1,6 +1,6 @@
|
||||
/* sysprof-cpu-visualizer-row.h
|
||||
/* sysprof-marks-page.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
* Copyright 2019 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
|
||||
@ -20,22 +20,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "sysprof-line-visualizer-row.h"
|
||||
|
||||
#include "sysprof-version-macros.h"
|
||||
#include "sysprof-marks-model.h"
|
||||
#include "sysprof-page.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_CPU_VISUALIZER_ROW (sysprof_cpu_visualizer_row_get_type())
|
||||
#define SYSPROF_TYPE_MARKS_PAGE (sysprof_marks_page_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofCpuVisualizerRow, sysprof_cpu_visualizer_row, SYSPROF, CPU_VISUALIZER_ROW, SysprofLineVisualizerRow)
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofMarksPage, sysprof_marks_page, SYSPROF, MARKS_PAGE, SysprofPage)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_cpu_visualizer_row_new (void);
|
||||
struct _SysprofMarksPageClass
|
||||
{
|
||||
SysprofPageClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
GtkWidget *sysprof_marks_page_new (SysprofZoomManager *zoom_manager,
|
||||
SysprofMarksModelKind kind);
|
||||
|
||||
G_END_DECLS
|
||||
231
src/libsysprof-ui/sysprof-marks-page.ui
Normal file
231
src/libsysprof-ui/sysprof-marks-page.ui
Normal file
@ -0,0 +1,231 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofMarksPage" parent="SysprofPage">
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="homogeneous">false</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<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-bottom">6</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="hexpand">false</property>
|
||||
<property name="vexpand">true</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="visible">true</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>
|
||||
</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>
|
||||
</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>
|
||||
</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">Duration</property>
|
||||
<property name="visible">true</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</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">Message</property>
|
||||
<property name="visible">true</property>
|
||||
<property name="xalign">1</property>
|
||||
<property name="yalign">0</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top-attach">4</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>
|
||||
</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="wrap">true</property>
|
||||
</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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top-attach">2</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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top-attach">3</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>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top-attach">4</property>
|
||||
<property name="left-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<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>
|
||||
<property name="expand">true</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererDuration" id="duration_cell">
|
||||
<property name="xalign">0</property>
|
||||
<property name="ypad">1</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">5</attribute>
|
||||
<attribute name="begin-time">2</attribute>
|
||||
<attribute name="end-time">3</attribute>
|
||||
</attributes>
|
||||
<cell-packing>
|
||||
<property name="expand">true</property>
|
||||
</cell-packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</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>
|
||||
<packing>
|
||||
<property name="name">empty-state</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@ -1,55 +0,0 @@
|
||||
/* sysprof-marks-view.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sysprof.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_MARKS_VIEW (sysprof_marks_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofMarksView, sysprof_marks_view, SYSPROF, MARKS_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofMarksViewClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_marks_view_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_marks_view_load_async (SysprofMarksView *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_marks_view_load_finish (SysprofMarksView *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofMarksView" parent="GtkBin">
|
||||
<child>
|
||||
<object class="GtkStack" id="stack">
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scroller">
|
||||
<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>
|
||||
<property name="expand">true</property>
|
||||
<child>
|
||||
<object class="SysprofCellRendererDuration" id="duration_cell">
|
||||
<property name="xalign">0</property>
|
||||
<property name="ypad">1</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">5</attribute>
|
||||
<attribute name="begin-time">2</attribute>
|
||||
<attribute name="end-time">3</attribute>
|
||||
</attributes>
|
||||
<cell-packing>
|
||||
<property name="expand">true</property>
|
||||
</cell-packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">marks</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="SysprofEmptyStateView">
|
||||
<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 collected.</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">empty-state</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
@ -26,10 +26,8 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_MEMORY_AID (sysprof_memory_aid_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofMemoryAid, sysprof_memory_aid, SYSPROF, MEMORY_AID, SysprofAid)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofAid *sysprof_memory_aid_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -33,7 +33,7 @@ G_BEGIN_DECLS
|
||||
#define SYSPROF_TYPE_MODEL_FILTER (sysprof_model_filter_get_type())
|
||||
|
||||
typedef gboolean (*SysprofModelFilterFunc) (GObject *object,
|
||||
gpointer user_data);
|
||||
gpointer user_data);
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofModelFilter, sysprof_model_filter, SYSPROF, MODEL_FILTER, GObject)
|
||||
|
||||
@ -20,6 +20,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
|
||||
235
src/libsysprof-ui/sysprof-page.c
Normal file
235
src/libsysprof-ui/sysprof-page.c
Normal file
@ -0,0 +1,235 @@
|
||||
/* sysprof-page.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-page"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-page.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *title;
|
||||
} SysprofPagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofPage, sysprof_page, GTK_TYPE_BIN)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_TITLE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
/**
|
||||
* sysprof_page_new:
|
||||
*
|
||||
* Create a new #SysprofPage.
|
||||
*
|
||||
* Returns: (transfer full) (type SysprofPage): a newly created #SysprofPage
|
||||
*/
|
||||
GtkWidget *
|
||||
sysprof_page_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_PAGE, NULL);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
sysprof_page_get_title (SysprofPage *self)
|
||||
{
|
||||
SysprofPagePrivate *priv = sysprof_page_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_PAGE (self), NULL);
|
||||
|
||||
return priv->title;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_page_set_title (SysprofPage *self,
|
||||
const gchar *title)
|
||||
{
|
||||
SysprofPagePrivate *priv = sysprof_page_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_PAGE (self));
|
||||
|
||||
if (g_strcmp0 (priv->title, title) != 0)
|
||||
{
|
||||
g_free (priv->title);
|
||||
priv->title = g_strdup (title);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_page_real_load_async (SysprofPage *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
SysprofCaptureCondition *condition,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_task_report_new_error (self, callback, user_data,
|
||||
sysprof_page_load_async,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_SUPPORTED,
|
||||
"Operation not supported");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_page_real_load_finish (SysprofPage *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_page_finalize (GObject *object)
|
||||
{
|
||||
SysprofPage *self = (SysprofPage *)object;
|
||||
SysprofPagePrivate *priv = sysprof_page_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->title, g_free);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_page_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_page_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofPage *self = SYSPROF_PAGE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, sysprof_page_get_title (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_page_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofPage *self = SYSPROF_PAGE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
sysprof_page_set_title (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_page_class_init (SysprofPageClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_page_finalize;
|
||||
object_class->get_property = sysprof_page_get_property;
|
||||
object_class->set_property = sysprof_page_set_property;
|
||||
|
||||
klass->load_async = sysprof_page_real_load_async;
|
||||
klass->load_finish = sysprof_page_real_load_finish;
|
||||
|
||||
properties [PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"The title for the page",
|
||||
NULL,
|
||||
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_page_init (SysprofPage *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_page_load_async:
|
||||
* @condition: (nullable): a #sysprofCaptureCondition or %NULL
|
||||
* @cancellable: (nullable): a #GCancellable or %NULL
|
||||
*
|
||||
* Since: 3.34
|
||||
*/
|
||||
void
|
||||
sysprof_page_load_async (SysprofPage *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
SysprofCaptureCondition *condition,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_PAGE (self));
|
||||
g_return_if_fail (reader != NULL);
|
||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
SYSPROF_PAGE_GET_CLASS (self)->load_async (self, reader, selection, condition, cancellable, callback, user_data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
sysprof_page_load_finish (SysprofPage *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_PAGE (self), FALSE);
|
||||
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
|
||||
|
||||
return SYSPROF_PAGE_GET_CLASS (self)->load_finish (self, result, error);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_page_set_size_group (SysprofPage *self,
|
||||
GtkSizeGroup *size_group)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_PAGE (self));
|
||||
g_return_if_fail (!size_group || GTK_IS_SIZE_GROUP (size_group));
|
||||
|
||||
if (SYSPROF_PAGE_GET_CLASS (self)->set_size_group)
|
||||
SYSPROF_PAGE_GET_CLASS (self)->set_size_group (self, size_group);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_page_set_hadjustment (SysprofPage *self,
|
||||
GtkAdjustment *hadjustment)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_PAGE (self));
|
||||
g_return_if_fail (!hadjustment || GTK_IS_ADJUSTMENT (hadjustment));
|
||||
|
||||
if (SYSPROF_PAGE_GET_CLASS (self)->set_hadjustment)
|
||||
SYSPROF_PAGE_GET_CLASS (self)->set_hadjustment (self, hadjustment);
|
||||
}
|
||||
86
src/libsysprof-ui/sysprof-page.h
Normal file
86
src/libsysprof-ui/sysprof-page.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* sysprof-page.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
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)
|
||||
|
||||
struct _SysprofPageClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
void (*load_async) (SysprofPage *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
SysprofCaptureCondition *condition,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean (*load_finish) (SysprofPage *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
void (*set_hadjustment) (SysprofPage *self,
|
||||
GtkAdjustment *hadjustment);
|
||||
void (*set_size_group) (SysprofPage *self,
|
||||
GtkSizeGroup *size_group);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_page_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_page_load_async (SysprofPage *self,
|
||||
SysprofCaptureReader *reader,
|
||||
SysprofSelection *selection,
|
||||
SysprofCaptureCondition *condition,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_page_load_finish (SysprofPage *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
const gchar *sysprof_page_get_title (SysprofPage *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_page_set_title (SysprofPage *self,
|
||||
const gchar *title);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_page_set_hadjustment (SysprofPage *self,
|
||||
GtkAdjustment *hadjustment);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_page_set_size_group (SysprofPage *self,
|
||||
GtkSizeGroup *size_group);
|
||||
|
||||
G_END_DECLS
|
||||
@ -27,13 +27,17 @@
|
||||
#include "sysprof-platform.h"
|
||||
|
||||
#include "sysprof-aid-icon.h"
|
||||
#include "sysprof-cpu-aid.h"
|
||||
#include "sysprof-environ-editor.h"
|
||||
#include "sysprof-profiler-assistant.h"
|
||||
#include "sysprof-proxy-aid.h"
|
||||
#include "sysprof-process-model-row.h"
|
||||
#include "sysprof-ui-private.h"
|
||||
|
||||
#include "sysprof-battery-aid.h"
|
||||
#include "sysprof-callgraph-aid.h"
|
||||
#include "sysprof-cpu-aid.h"
|
||||
#include "sysprof-memory-aid.h"
|
||||
#include "sysprof-proxy-aid.h"
|
||||
|
||||
struct _SysprofProfilerAssistant
|
||||
{
|
||||
GtkBin parent_instance;
|
||||
@ -298,9 +302,12 @@ sysprof_profiler_assistant_class_init (SysprofProfilerAssistantClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofProfilerAssistant, inherit_switch);
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_AID_ICON);
|
||||
g_type_ensure (SYSPROF_TYPE_BATTERY_AID);
|
||||
g_type_ensure (SYSPROF_TYPE_CPU_AID);
|
||||
g_type_ensure (SYSPROF_TYPE_MEMORY_AID);
|
||||
g_type_ensure (SYSPROF_TYPE_PROXY_AID);
|
||||
g_type_ensure (SYSPROF_TYPE_ENVIRON_EDITOR);
|
||||
g_type_ensure (SYSPROF_TYPE_CALLGRAPH_AID);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -28,10 +28,8 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_PROFILER_ASSISTANT (sysprof_profiler_assistant_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofProfilerAssistant, sysprof_profiler_assistant, SYSPROF, PROFILER_ASSISTANT, GtkBin)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_profiler_assistant_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -43,13 +43,7 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="SysprofAid" id="battery_aid">
|
||||
<property name="display-name">Battery</property>
|
||||
<property name="icon-name">battery-low-charging-symbolic</property>
|
||||
<child>
|
||||
<object class="SysprofBatterySource"/>
|
||||
</child>
|
||||
</object>
|
||||
<object class="SysprofBatteryAid" id="battery_aid"/>
|
||||
<template class="SysprofProfilerAssistant" parent="GtkBin">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
|
||||
@ -36,13 +36,10 @@ struct _SysprofProxyAidClass
|
||||
gpointer _reserved[8];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_proxy_aid_set_bus_type (SysprofProxyAid *self,
|
||||
GBusType bus_type);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_proxy_aid_set_bus_name (SysprofProxyAid *self,
|
||||
const gchar *bus_name);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_proxy_aid_set_object_path (SysprofProxyAid *self,
|
||||
const gchar *obj_path);
|
||||
|
||||
|
||||
@ -20,10 +20,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
@ -31,7 +27,6 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_RECORDING_STATE_VIEW (sysprof_recording_state_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofRecordingStateView, sysprof_recording_state_view, SYSPROF, RECORDING_STATE_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofRecordingStateViewClass
|
||||
@ -41,9 +36,7 @@ struct _SysprofRecordingStateViewClass
|
||||
gpointer padding[4];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_recording_state_view_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_recording_state_view_set_profiler (SysprofRecordingStateView *self,
|
||||
SysprofProfiler *profiler);
|
||||
|
||||
|
||||
306
src/libsysprof-ui/sysprof-scrollmap.c
Normal file
306
src/libsysprof-ui/sysprof-scrollmap.c
Normal file
@ -0,0 +1,306 @@
|
||||
/* sysprof-scrollmap.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-scrollmap"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-scrollmap.h"
|
||||
|
||||
#define BOX_SIZE 4
|
||||
|
||||
struct _SysprofScrollmap
|
||||
{
|
||||
GtkScrollbar parent_instance;
|
||||
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
|
||||
GArray *timings;
|
||||
GArray *buckets;
|
||||
GCancellable *cancellable;
|
||||
|
||||
gint most;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
GArray *timings;
|
||||
gint width;
|
||||
gint height;
|
||||
} Recalculate;
|
||||
|
||||
G_DEFINE_TYPE (SysprofScrollmap, sysprof_scrollmap, GTK_TYPE_SCROLLBAR)
|
||||
|
||||
static void
|
||||
recalculate_free (gpointer data)
|
||||
{
|
||||
Recalculate *state = data;
|
||||
|
||||
g_clear_pointer (&state->timings, g_array_unref);
|
||||
g_slice_free (Recalculate, state);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scrollmap_recalculate_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Recalculate *state = task_data;
|
||||
g_autoptr(GArray) buckets = NULL;
|
||||
gint64 duration;
|
||||
gint n_buckets;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_SCROLLMAP (source_object));
|
||||
g_assert (state != NULL);
|
||||
g_assert (state->timings != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
duration = state->end_time - state->begin_time;
|
||||
n_buckets = MAX (1, state->width / (BOX_SIZE + 1));
|
||||
buckets = g_array_sized_new (FALSE, TRUE, sizeof (gint), n_buckets);
|
||||
g_array_set_size (buckets, n_buckets);
|
||||
|
||||
for (guint i = 0; i < state->timings->len; i++)
|
||||
{
|
||||
gint64 t = g_array_index (state->timings, gint64, i);
|
||||
gint n;
|
||||
|
||||
if (t < state->begin_time || t > state->end_time)
|
||||
continue;
|
||||
|
||||
n = ((t - state->begin_time) / (gdouble)duration) * n_buckets;
|
||||
|
||||
g_assert (n < n_buckets);
|
||||
|
||||
g_array_index (buckets, gint, n)++;
|
||||
}
|
||||
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&buckets),
|
||||
(GDestroyNotify) g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scrollmap_recalculate_async (SysprofScrollmap *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
GtkAllocation alloc;
|
||||
Recalculate state;
|
||||
|
||||
g_assert (SYSPROF_IS_SCROLLMAP (self));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_scrollmap_recalculate_async);
|
||||
|
||||
if (self->timings == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_CANCELLED,
|
||||
"The operation was cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
|
||||
state.begin_time = self->begin_time;
|
||||
state.end_time = self->end_time;
|
||||
state.width = alloc.width;
|
||||
state.height = alloc.height;
|
||||
state.timings = g_array_ref (self->timings);
|
||||
|
||||
g_task_set_task_data (task,
|
||||
g_slice_dup (Recalculate, &state),
|
||||
recalculate_free);
|
||||
g_task_run_in_thread (task, sysprof_scrollmap_recalculate_worker);
|
||||
}
|
||||
|
||||
static GArray *
|
||||
sysprof_scrollmap_recalculate_finish (SysprofScrollmap *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_assert (SYSPROF_IS_SCROLLMAP (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_boxes (const GtkAllocation *alloc,
|
||||
cairo_t *cr,
|
||||
gint x,
|
||||
gint n_boxes)
|
||||
{
|
||||
gint y;
|
||||
|
||||
g_assert (cr != NULL);
|
||||
|
||||
y = alloc->height - BOX_SIZE;
|
||||
|
||||
for (gint i = 0; i < n_boxes; i++)
|
||||
{
|
||||
cairo_rectangle (cr, x, y, BOX_SIZE, -BOX_SIZE);
|
||||
y -= (BOX_SIZE + 1);
|
||||
}
|
||||
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_scrollmap_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofScrollmap *self = (SysprofScrollmap *)widget;
|
||||
GtkStyleContext *style_context;
|
||||
GtkAllocation alloc;
|
||||
GdkRGBA color;
|
||||
gint max_boxes;
|
||||
|
||||
g_assert (SYSPROF_IS_SCROLLMAP (self));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
if (self->buckets == NULL)
|
||||
goto chainup;
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
#if 1
|
||||
if (n > 0)
|
||||
b = MAX (b, 1);
|
||||
#endif
|
||||
|
||||
draw_boxes (&alloc, cr, x, b);
|
||||
}
|
||||
|
||||
chainup:
|
||||
return GTK_WIDGET_CLASS (sysprof_scrollmap_parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scrollmap_recalculate_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofScrollmap *self = (SysprofScrollmap *)object;
|
||||
g_autoptr(GArray) buckets = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_SCROLLMAP (self));
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (user_data == NULL);
|
||||
|
||||
if ((buckets = sysprof_scrollmap_recalculate_finish (self, result, NULL)))
|
||||
{
|
||||
self->most = 0;
|
||||
|
||||
for (guint i = 0; i < buckets->len; i++)
|
||||
{
|
||||
gint n = g_array_index (buckets, gint, i);
|
||||
self->most = MAX (self->most, n);
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->buckets, g_array_unref);
|
||||
self->buckets = g_steal_pointer (&buckets);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scrollmap_finalize (GObject *object)
|
||||
{
|
||||
SysprofScrollmap *self = (SysprofScrollmap *)object;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
|
||||
widget_class->draw = sysprof_scrollmap_draw;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scrollmap_init (SysprofScrollmap *self)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_scrollmap_set_timings (SysprofScrollmap *self,
|
||||
GArray *timings)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_SCROLLMAP (self));
|
||||
|
||||
if (timings != self->timings)
|
||||
{
|
||||
g_clear_pointer (&self->timings, g_array_unref);
|
||||
self->timings = timings ? g_array_ref (timings) : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_scrollmap_set_time_range (SysprofScrollmap *self,
|
||||
gint64 begin_time,
|
||||
gint64 end_time)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_SCROLLMAP (self));
|
||||
|
||||
self->begin_time = begin_time;
|
||||
self->end_time = end_time;
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
self->cancellable = g_cancellable_new ();
|
||||
|
||||
sysprof_scrollmap_recalculate_async (self,
|
||||
self->cancellable,
|
||||
sysprof_scrollmap_recalculate_cb,
|
||||
NULL);
|
||||
}
|
||||
37
src/libsysprof-ui/sysprof-scrollmap.h
Normal file
37
src/libsysprof-ui/sysprof-scrollmap.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* sysprof-scrollmap.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_SCROLLMAP (sysprof_scrollmap_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofScrollmap, sysprof_scrollmap, SYSPROF, SCROLLMAP, GtkScrollbar)
|
||||
|
||||
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
|
||||
@ -202,9 +202,9 @@ sysprof_theme_manager_get_default (void)
|
||||
|
||||
guint
|
||||
sysprof_theme_manager_register_resource (SysprofThemeManager *self,
|
||||
const gchar *theme_name,
|
||||
const gchar *variant,
|
||||
const gchar *resource)
|
||||
const gchar *theme_name,
|
||||
const gchar *variant,
|
||||
const gchar *resource)
|
||||
{
|
||||
ThemeResource *theme_resource;
|
||||
static guint counter;
|
||||
|
||||
543
src/libsysprof-ui/sysprof-time-visualizer.c
Normal file
543
src/libsysprof-ui/sysprof-time-visualizer.c
Normal file
@ -0,0 +1,543 @@
|
||||
/* sysprof-time-visualizer.c
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-time-visualizer"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "pointcache.h"
|
||||
#include "sysprof-time-visualizer.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* Our reader as assigned by the visualizer system.
|
||||
*/
|
||||
SysprofCaptureReader *reader;
|
||||
|
||||
/*
|
||||
* An array of LineInfo which contains information about the counters
|
||||
* we need to render.
|
||||
*/
|
||||
GArray *lines;
|
||||
|
||||
/*
|
||||
* This is our set of cached points to render. Once it is assigned here,
|
||||
* it is immutable (and therefore may be shared with worker processes
|
||||
* that are rendering the points).
|
||||
*/
|
||||
PointCache *cache;
|
||||
|
||||
/*
|
||||
* If we have a new counter discovered or the reader is set, we might
|
||||
* want to delay loading until we return to the main loop. This can
|
||||
* help us avoid doing duplicate work.
|
||||
*/
|
||||
guint queued_load;
|
||||
} SysprofTimeVisualizerPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint id;
|
||||
gdouble line_width;
|
||||
GdkRGBA rgba;
|
||||
guint use_default_style : 1;
|
||||
guint use_dash : 1;
|
||||
} LineInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureCursor *cursor;
|
||||
GArray *lines;
|
||||
PointCache *cache;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
} LoadData;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofTimeVisualizer, sysprof_time_visualizer, SYSPROF_TYPE_VISUALIZER)
|
||||
|
||||
static void sysprof_time_visualizer_load_data_async (SysprofTimeVisualizer *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
static PointCache *sysprof_time_visualizer_load_data_finish (SysprofTimeVisualizer *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
static gdouble dashes[] = { 1.0, 2.0 };
|
||||
|
||||
static void
|
||||
load_data_free (gpointer data)
|
||||
{
|
||||
LoadData *load = data;
|
||||
|
||||
if (load != NULL)
|
||||
{
|
||||
g_clear_pointer (&load->lines, g_array_unref);
|
||||
g_clear_pointer (&load->cursor, sysprof_capture_cursor_unref);
|
||||
g_clear_pointer (&load->cache, point_cache_unref);
|
||||
g_slice_free (LoadData, load);
|
||||
}
|
||||
}
|
||||
|
||||
static GArray *
|
||||
copy_array (GArray *ar)
|
||||
{
|
||||
GArray *ret;
|
||||
|
||||
ret = g_array_sized_new (FALSE, FALSE, g_array_get_element_size (ar), ar->len);
|
||||
g_array_set_size (ret, ar->len);
|
||||
memcpy (ret->data, ar->data, ar->len * g_array_get_element_size (ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_time_visualizer_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofTimeVisualizer *self = (SysprofTimeVisualizer *)widget;
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
GtkStyleContext *style_context;
|
||||
GtkStateFlags flags;
|
||||
GtkAllocation alloc;
|
||||
GdkRectangle clip;
|
||||
GdkRGBA foreground;
|
||||
gboolean ret;
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (widget));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
ret = GTK_WIDGET_CLASS (sysprof_time_visualizer_parent_class)->draw (widget, cr);
|
||||
|
||||
if (priv->cache == NULL)
|
||||
return ret;
|
||||
|
||||
if (!gdk_cairo_get_clip_rectangle (cr, &clip))
|
||||
return ret;
|
||||
|
||||
style_context = gtk_widget_get_style_context (widget);
|
||||
flags = gtk_widget_get_state_flags (widget);
|
||||
gtk_style_context_get_color (style_context, flags, &foreground);
|
||||
|
||||
gdk_cairo_set_source_rgba (cr, &foreground);
|
||||
|
||||
for (guint line = 0; line < priv->lines->len; line++)
|
||||
{
|
||||
g_autofree SysprofVisualizerAbsolutePoint *points = NULL;
|
||||
const LineInfo *line_info = &g_array_index (priv->lines, LineInfo, line);
|
||||
const Point *fpoints;
|
||||
guint n_fpoints = 0;
|
||||
|
||||
fpoints = point_cache_get_points (priv->cache, line_info->id, &n_fpoints);
|
||||
|
||||
if (n_fpoints > 0)
|
||||
{
|
||||
guint last_x = G_MAXUINT;
|
||||
|
||||
points = g_new0 (SysprofVisualizerAbsolutePoint, n_fpoints);
|
||||
|
||||
sysprof_visualizer_translate_points (SYSPROF_VISUALIZER (self),
|
||||
(const SysprofVisualizerRelativePoint *)fpoints,
|
||||
n_fpoints,
|
||||
points,
|
||||
n_fpoints);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
for (guint i = 0; i < n_fpoints; i++)
|
||||
{
|
||||
if ((guint)points[i].x != last_x)
|
||||
last_x = (guint)points[i].x;
|
||||
else
|
||||
continue;
|
||||
|
||||
cairo_move_to (cr, (guint)points[i].x + .5, alloc.height / 3);
|
||||
cairo_line_to (cr, (guint)points[i].x + .5, alloc.height / 3 * 2);
|
||||
}
|
||||
|
||||
if (line_info->use_dash)
|
||||
cairo_set_dash (cr, dashes, G_N_ELEMENTS (dashes), 0);
|
||||
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_load_data_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofTimeVisualizer *self = (SysprofTimeVisualizer *)object;
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(PointCache) cache = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
cache = sysprof_time_visualizer_load_data_finish (self, result, &error);
|
||||
|
||||
if (cache == NULL)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->cache, point_cache_unref);
|
||||
priv->cache = g_steal_pointer (&cache);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_time_visualizer_do_reload (gpointer data)
|
||||
{
|
||||
SysprofTimeVisualizer *self = data;
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
priv->queued_load = 0;
|
||||
if (priv->reader != NULL)
|
||||
sysprof_time_visualizer_load_data_async (self,
|
||||
NULL,
|
||||
sysprof_time_visualizer_load_data_cb,
|
||||
NULL);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_queue_reload (SysprofTimeVisualizer *self)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
if (priv->queued_load == 0)
|
||||
priv->queued_load =
|
||||
gdk_threads_add_idle_full (G_PRIORITY_LOW,
|
||||
sysprof_time_visualizer_do_reload,
|
||||
self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_set_reader (SysprofVisualizer *row,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofTimeVisualizer *self = (SysprofTimeVisualizer *)row;
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
if (priv->reader != reader)
|
||||
{
|
||||
if (priv->reader != NULL)
|
||||
{
|
||||
sysprof_capture_reader_unref (priv->reader);
|
||||
priv->reader = NULL;
|
||||
}
|
||||
|
||||
if (reader != NULL)
|
||||
priv->reader = sysprof_capture_reader_ref (reader);
|
||||
|
||||
sysprof_time_visualizer_queue_reload (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_finalize (GObject *object)
|
||||
{
|
||||
SysprofTimeVisualizer *self = (SysprofTimeVisualizer *)object;
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->lines, g_array_unref);
|
||||
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_OBJECT_CLASS (sysprof_time_visualizer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_class_init (SysprofTimeVisualizerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofVisualizerClass *visualizer_class = SYSPROF_VISUALIZER_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_time_visualizer_finalize;
|
||||
|
||||
widget_class->draw = sysprof_time_visualizer_draw;
|
||||
|
||||
visualizer_class->set_reader = sysprof_time_visualizer_set_reader;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_init (SysprofTimeVisualizer *self)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
priv->lines = g_array_new (FALSE, FALSE, sizeof (LineInfo));
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_time_visualizer_add_counter (SysprofTimeVisualizer *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
LineInfo line_info = {0};
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
g_assert (priv->lines != NULL);
|
||||
|
||||
line_info.id = counter_id;
|
||||
line_info.line_width = 1.0;
|
||||
|
||||
if (color != NULL)
|
||||
{
|
||||
line_info.rgba = *color;
|
||||
line_info.use_default_style = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
line_info.use_default_style = TRUE;
|
||||
}
|
||||
|
||||
g_array_append_val (priv->lines, line_info);
|
||||
|
||||
if (SYSPROF_TIME_VISUALIZER_GET_CLASS (self)->counter_added)
|
||||
SYSPROF_TIME_VISUALIZER_GET_CLASS (self)->counter_added (self, counter_id);
|
||||
|
||||
sysprof_time_visualizer_queue_reload (self);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_time_visualizer_clear (SysprofTimeVisualizer *self)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
if (priv->lines->len > 0)
|
||||
g_array_remove_range (priv->lines, 0, priv->lines->len);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
contains_id (GArray *ar,
|
||||
guint id)
|
||||
{
|
||||
for (guint i = 0; i < ar->len; i++)
|
||||
{
|
||||
const LineInfo *info = &g_array_index (ar, LineInfo, i);
|
||||
|
||||
if (info->id == id)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gdouble
|
||||
calc_x (gint64 lower,
|
||||
gint64 upper,
|
||||
gint64 value)
|
||||
{
|
||||
return (gdouble)(value - lower) / (gdouble)(upper - lower);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_time_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
LoadData *load = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (frame->type == SYSPROF_CAPTURE_FRAME_CTRSET ||
|
||||
frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF);
|
||||
g_assert (load != NULL);
|
||||
|
||||
if (frame->type == SYSPROF_CAPTURE_FRAME_CTRSET)
|
||||
{
|
||||
const SysprofCaptureCounterSet *set = (SysprofCaptureCounterSet *)frame;
|
||||
gdouble x = calc_x (load->begin_time, load->end_time, frame->time);
|
||||
|
||||
for (guint i = 0; i < set->n_values; i++)
|
||||
{
|
||||
const SysprofCaptureCounterValues *group = &set->values[i];
|
||||
|
||||
for (guint j = 0; j < G_N_ELEMENTS (group->ids); j++)
|
||||
{
|
||||
guint counter_id = group->ids[j];
|
||||
|
||||
if (counter_id != 0 && contains_id (load->lines, counter_id))
|
||||
point_cache_add_point_to_set (load->cache, counter_id, x, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_load_data_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
LoadData *load = task_data;
|
||||
g_autoptr(GArray) counter_ids = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (source_object));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
counter_ids = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
|
||||
for (guint i = 0; i < load->lines->len; i++)
|
||||
{
|
||||
const LineInfo *line_info = &g_array_index (load->lines, LineInfo, i);
|
||||
g_array_append_val (counter_ids, line_info->id);
|
||||
}
|
||||
|
||||
sysprof_capture_cursor_add_condition (load->cursor,
|
||||
sysprof_capture_condition_new_where_counter_in (counter_ids->len,
|
||||
(guint *)(gpointer)counter_ids->data));
|
||||
sysprof_capture_cursor_foreach (load->cursor, sysprof_time_visualizer_load_data_frame_cb, load);
|
||||
g_task_return_pointer (task, g_steal_pointer (&load->cache), (GDestroyNotify)point_cache_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_time_visualizer_load_data_async (SysprofTimeVisualizer *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
g_autoptr(GTask) task = NULL;
|
||||
LoadData *load;
|
||||
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_priority (task, G_PRIORITY_LOW);
|
||||
g_task_set_source_tag (task, sysprof_time_visualizer_load_data_async);
|
||||
|
||||
if (priv->reader == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"No data loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
load = g_slice_new0 (LoadData);
|
||||
load->cache = point_cache_new ();
|
||||
load->begin_time = sysprof_capture_reader_get_start_time (priv->reader);
|
||||
load->end_time = sysprof_capture_reader_get_end_time (priv->reader);
|
||||
load->cursor = sysprof_capture_cursor_new (priv->reader);
|
||||
load->lines = copy_array (priv->lines);
|
||||
|
||||
for (guint i = 0; i < load->lines->len; i++)
|
||||
{
|
||||
const LineInfo *line_info = &g_array_index (load->lines, LineInfo, i);
|
||||
|
||||
point_cache_add_set (load->cache, line_info->id);
|
||||
}
|
||||
|
||||
g_task_set_task_data (task, load, load_data_free);
|
||||
g_task_run_in_thread (task, sysprof_time_visualizer_load_data_worker);
|
||||
}
|
||||
|
||||
static PointCache *
|
||||
sysprof_time_visualizer_load_data_finish (SysprofTimeVisualizer *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_assert (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_time_visualizer_set_line_width (SysprofTimeVisualizer *self,
|
||||
guint counter_id,
|
||||
gdouble width)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
for (guint i = 0; i < priv->lines->len; i++)
|
||||
{
|
||||
LineInfo *info = &g_array_index (priv->lines, LineInfo, i);
|
||||
|
||||
if (info->id == counter_id)
|
||||
{
|
||||
info->line_width = width;
|
||||
sysprof_time_visualizer_queue_reload (self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_time_visualizer_set_dash (SysprofTimeVisualizer *self,
|
||||
guint counter_id,
|
||||
gboolean use_dash)
|
||||
{
|
||||
SysprofTimeVisualizerPrivate *priv = sysprof_time_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_TIME_VISUALIZER (self));
|
||||
|
||||
for (guint i = 0; i < priv->lines->len; i++)
|
||||
{
|
||||
LineInfo *info = &g_array_index (priv->lines, LineInfo, i);
|
||||
|
||||
if (info->id == counter_id)
|
||||
{
|
||||
info->use_dash = !!use_dash;
|
||||
sysprof_time_visualizer_queue_reload (self);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/libsysprof-ui/sysprof-time-visualizer.h
Normal file
54
src/libsysprof-ui/sysprof-time-visualizer.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* sysprof-time-visualizer.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_TIME_VISUALIZER (sysprof_time_visualizer_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofTimeVisualizer, sysprof_time_visualizer, SYSPROF, TIME_VISUALIZER, SysprofVisualizer)
|
||||
|
||||
struct _SysprofTimeVisualizerClass
|
||||
{
|
||||
SysprofVisualizerClass parent_class;
|
||||
|
||||
void (*counter_added) (SysprofTimeVisualizer *self,
|
||||
guint counter_id);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
GtkWidget *sysprof_time_visualizer_new (void);
|
||||
void sysprof_time_visualizer_clear (SysprofTimeVisualizer *self);
|
||||
void sysprof_time_visualizer_add_counter (SysprofTimeVisualizer *self,
|
||||
guint counter_id,
|
||||
const GdkRGBA *color);
|
||||
void sysprof_time_visualizer_set_line_width (SysprofTimeVisualizer *self,
|
||||
guint counter_id,
|
||||
gdouble width);
|
||||
void sysprof_time_visualizer_set_dash (SysprofTimeVisualizer *self,
|
||||
guint counter_id,
|
||||
gboolean use_dash);
|
||||
|
||||
G_END_DECLS
|
||||
@ -20,42 +20,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-callgraph-view.h"
|
||||
#include "sysprof-callgraph-page.h"
|
||||
#include "sysprof-display.h"
|
||||
#include "sysprof-marks-view.h"
|
||||
#include "sysprof-profiler-assistant.h"
|
||||
#include "sysprof-visualizer-view.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *name;
|
||||
guint64 count;
|
||||
gint64 max;
|
||||
gint64 min;
|
||||
gint64 avg;
|
||||
guint64 avg_count;
|
||||
} SysprofMarkStat;
|
||||
|
||||
SysprofMarkStat *_sysprof_mark_stat_new (const gchar *name);
|
||||
void _sysprof_mark_stat_free (SysprofMarkStat *self);
|
||||
void _sysprof_marks_view_set_hadjustment (SysprofMarksView *self,
|
||||
GtkAdjustment *hadjustment);
|
||||
void _sysprof_visualizer_view_set_hadjustment (SysprofVisualizerView *self,
|
||||
GtkAdjustment *hadjustment);
|
||||
void _sysprof_rounded_rectangle (cairo_t *cr,
|
||||
const GdkRectangle *rect,
|
||||
gint x_radius,
|
||||
gint y_radius);
|
||||
gchar *_sysprof_format_duration (gint64 duration);
|
||||
void _sysprof_callgraph_view_set_failed (SysprofCallgraphView *self);
|
||||
void _sysprof_callgraph_view_set_loading (SysprofCallgraphView *self,
|
||||
gboolean loading);
|
||||
void _sysprof_display_focus_record (SysprofDisplay *self);
|
||||
void _sysprof_profiler_assistant_focus_record (SysprofProfilerAssistant *self);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofMarkStat, _sysprof_mark_stat_free)
|
||||
void _sysprof_callgraph_page_set_failed (SysprofCallgraphPage *self);
|
||||
void _sysprof_callgraph_page_set_loading (SysprofCallgraphPage *self,
|
||||
gboolean loading);
|
||||
void _sysprof_display_focus_record (SysprofDisplay *self);
|
||||
void _sysprof_profiler_assistant_focus_record (SysprofProfilerAssistant *self);
|
||||
gchar *_sysprof_format_duration (gint64 duration);
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 56, 0)
|
||||
# define g_clear_weak_pointer(ptr) \
|
||||
|
||||
@ -27,31 +27,14 @@ G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_UI_INSIDE
|
||||
|
||||
# include "sysprof-aid.h"
|
||||
# include "sysprof-callgraph-view.h"
|
||||
# include "sysprof-capture-view.h"
|
||||
# include "sysprof-callgraph-aid.h"
|
||||
# include "sysprof-cell-renderer-percent.h"
|
||||
# include "sysprof-check.h"
|
||||
# include "sysprof-cpu-aid.h"
|
||||
# include "sysprof-cpu-visualizer-row.h"
|
||||
# include "sysprof-display.h"
|
||||
# include "sysprof-empty-state-view.h"
|
||||
# include "sysprof-failed-state-view.h"
|
||||
# include "sysprof-line-visualizer-row.h"
|
||||
# include "sysprof-marks-model.h"
|
||||
# include "sysprof-marks-view.h"
|
||||
# include "sysprof-mark-visualizer-row.h"
|
||||
# include "sysprof-memory-aid.h"
|
||||
# include "sysprof-model-filter.h"
|
||||
# include "sysprof-notebook.h"
|
||||
# include "sysprof-page.h"
|
||||
# include "sysprof-process-model-row.h"
|
||||
# include "sysprof-profiler-assistant.h"
|
||||
# include "sysprof-proxy-aid.h"
|
||||
# include "sysprof-recording-state-view.h"
|
||||
# include "sysprof-visualizer-row.h"
|
||||
# include "sysprof-visualizer-view.h"
|
||||
# include "sysprof-zoom-manager.h"
|
||||
# include "sysprof-visualizer-group.h"
|
||||
# include "sysprof-visualizer.h"
|
||||
|
||||
#undef SYSPROF_UI_INSIDE
|
||||
|
||||
|
||||
159
src/libsysprof-ui/sysprof-visualizer-group-header.c
Normal file
159
src/libsysprof-ui/sysprof-visualizer-group-header.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* sysprof-visualizer-group-header.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer-group-header"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
#include "sysprof-visualizer-group.h"
|
||||
#include "sysprof-visualizer-group-header.h"
|
||||
|
||||
struct _SysprofVisualizerGroupHeader
|
||||
{
|
||||
GtkListBoxRow parent_instance;
|
||||
|
||||
GtkBox *box;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SysprofVisualizerGroupHeader, sysprof_visualizer_group_header, GTK_TYPE_LIST_BOX_ROW)
|
||||
|
||||
static void
|
||||
sysprof_visualizer_group_header_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (sysprof_visualizer_group_header_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_group_header_class_init (SysprofVisualizerGroupHeaderClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_visualizer_group_header_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_group_header_init (SysprofVisualizerGroupHeader *self)
|
||||
{
|
||||
self->box = g_object_new (GTK_TYPE_BOX,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->box));
|
||||
}
|
||||
|
||||
void
|
||||
_sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
|
||||
guint position,
|
||||
const gchar *title,
|
||||
GMenuModel *menu,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkBox *box;
|
||||
GtkWidget *group;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP_HEADER (self));
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER (widget));
|
||||
g_return_if_fail (!menu || G_IS_MENU_MODEL (menu));
|
||||
|
||||
box = g_object_new (GTK_TYPE_BOX,
|
||||
"orientation", GTK_ORIENTATION_HORIZONTAL,
|
||||
"spacing", 6,
|
||||
"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);
|
||||
|
||||
if (title != NULL)
|
||||
{
|
||||
g_autoptr(GtkSizeGroup) size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
|
||||
PangoAttrList *attrs = pango_attr_list_new ();
|
||||
GtkLabel *label;
|
||||
|
||||
pango_attr_list_insert (attrs, pango_attr_scale_new (0.83333));
|
||||
label = g_object_new (GTK_TYPE_LABEL,
|
||||
"attributes", attrs,
|
||||
"ellipsize", PANGO_ELLIPSIZE_MIDDLE,
|
||||
"margin", 6,
|
||||
"hexpand", TRUE,
|
||||
"label", title,
|
||||
"visible", TRUE,
|
||||
"xalign", 0.0f,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (label));
|
||||
pango_attr_list_unref (attrs);
|
||||
|
||||
gtk_size_group_add_widget (size_group, widget);
|
||||
gtk_size_group_add_widget (size_group, GTK_WIDGET (box));
|
||||
}
|
||||
|
||||
group = gtk_widget_get_ancestor (widget, SYSPROF_TYPE_VISUALIZER_GROUP);
|
||||
|
||||
if (position == 0 && sysprof_visualizer_group_get_has_page (SYSPROF_VISUALIZER_GROUP (group)))
|
||||
{
|
||||
GtkImage *image;
|
||||
|
||||
image = g_object_new (GTK_TYPE_IMAGE,
|
||||
"icon-name", "view-paged-symbolic",
|
||||
"tooltip-text", _("Select for more details"),
|
||||
"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));
|
||||
}
|
||||
|
||||
if (menu != NULL)
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
GtkMenuButton *button;
|
||||
|
||||
button = g_object_new (GTK_TYPE_MENU_BUTTON,
|
||||
"child", g_object_new (GTK_TYPE_IMAGE,
|
||||
"icon-name", "view-more-symbolic",
|
||||
"visible", TRUE,
|
||||
NULL),
|
||||
"margin-right", 6,
|
||||
"direction", GTK_ARROW_RIGHT,
|
||||
"halign", GTK_ALIGN_CENTER,
|
||||
"menu-model", menu,
|
||||
"tooltip-text", _("Display supplimental graphs"),
|
||||
"use-popover", FALSE,
|
||||
"valign", GTK_ALIGN_CENTER,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
style_context = gtk_widget_get_style_context (GTK_WIDGET (button));
|
||||
gtk_style_context_add_class (style_context, "image-button");
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
SysprofVisualizerGroupHeader *
|
||||
_sysprof_visualizer_group_header_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP_HEADER, NULL);
|
||||
}
|
||||
31
src/libsysprof-ui/sysprof-visualizer-group-header.h
Normal file
31
src/libsysprof-ui/sysprof-visualizer-group-header.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* sysprof-visualizer-group-header.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_VISUALIZER_GROUP_HEADER (sysprof_visualizer_group_header_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofVisualizerGroupHeader, sysprof_visualizer_group_header, SYSPROF, VISUALIZER_GROUP_HEADER, GtkListBoxRow)
|
||||
|
||||
G_END_DECLS
|
||||
48
src/libsysprof-ui/sysprof-visualizer-group-private.h
Normal file
48
src/libsysprof-ui/sysprof-visualizer-group-private.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* sysprof-visualizers-group-private.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
#include "sysprof-visualizer-group.h"
|
||||
#include "sysprof-visualizer-group-header.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _sysprof_visualizer_set_data_width (SysprofVisualizer *self,
|
||||
gint width);
|
||||
void _sysprof_visualizer_group_set_data_width (SysprofVisualizerGroup *self,
|
||||
gint width);
|
||||
void _sysprof_visualizer_group_set_reader (SysprofVisualizerGroup *self,
|
||||
SysprofCaptureReader *reader);
|
||||
SysprofVisualizerGroupHeader *_sysprof_visualizer_group_header_new (void);
|
||||
void _sysprof_visualizer_group_header_add_row (SysprofVisualizerGroupHeader *self,
|
||||
guint position,
|
||||
const gchar *title,
|
||||
GMenuModel *menu,
|
||||
GtkWidget *row);
|
||||
void _sysprof_visualizer_group_header_remove_row (SysprofVisualizerGroupHeader *self,
|
||||
guint row);
|
||||
void _sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
|
||||
SysprofVisualizerGroupHeader *header);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
511
src/libsysprof-ui/sysprof-visualizer-group.c
Normal file
511
src/libsysprof-ui/sysprof-visualizer-group.c
Normal file
@ -0,0 +1,511 @@
|
||||
/* sysprof-visualizer-group.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer-group"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
#include "sysprof-visualizer-group.h"
|
||||
#include "sysprof-visualizer-group-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Owned pointers */
|
||||
GMenuModel *menu;
|
||||
GMenu *default_menu;
|
||||
GMenu *rows_menu;
|
||||
gchar *title;
|
||||
GtkSizeGroup *size_group;
|
||||
GSimpleActionGroup *actions;
|
||||
|
||||
gint priority;
|
||||
|
||||
guint has_page : 1;
|
||||
|
||||
/* Weak pointers */
|
||||
SysprofVisualizerGroupHeader *header;
|
||||
|
||||
/* Child Widgets */
|
||||
GtkBox *visualizers;
|
||||
} SysprofVisualizerGroupPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizerGroup, sysprof_visualizer_group, GTK_TYPE_LIST_BOX_ROW)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_HAS_PAGE,
|
||||
PROP_MENU,
|
||||
PROP_PRIORITY,
|
||||
PROP_TITLE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
enum {
|
||||
GROUP_ACTIVATED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
static guint signals [N_SIGNALS];
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_group_new:
|
||||
*
|
||||
* Create a new #SysprofVisualizerGroup.
|
||||
*
|
||||
* Returns: (transfer full): a newly created #SysprofVisualizerGroup
|
||||
*/
|
||||
SysprofVisualizerGroup *
|
||||
sysprof_visualizer_group_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_VISUALIZER_GROUP, NULL);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
sysprof_visualizer_group_get_title (SysprofVisualizerGroup *self)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self), NULL);
|
||||
|
||||
return priv->title;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_group_set_title (SysprofVisualizerGroup *self,
|
||||
const gchar *title)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
|
||||
|
||||
if (g_strcmp0 (priv->title, title) != 0)
|
||||
{
|
||||
g_free (priv->title);
|
||||
priv->title = g_strdup (title);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_group_get_menu:
|
||||
*
|
||||
* Gets the menu for the group.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GMenuModel or %NULL
|
||||
*
|
||||
* Since: 3.34
|
||||
*/
|
||||
GMenuModel *
|
||||
sysprof_visualizer_group_get_menu (SysprofVisualizerGroup *self)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self), NULL);
|
||||
|
||||
return priv->menu;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_group_set_menu (SysprofVisualizerGroup *self,
|
||||
GMenuModel *menu)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
|
||||
g_return_if_fail (!menu || G_IS_MENU_MODEL (menu));
|
||||
|
||||
if (g_set_object (&priv->menu, menu))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MENU]);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
create_action_name (const gchar *str)
|
||||
{
|
||||
GString *ret = g_string_new (NULL);
|
||||
|
||||
for (; *str; str = g_utf8_next_char (str))
|
||||
{
|
||||
gunichar ch = g_utf8_get_char (str);
|
||||
|
||||
if (g_unichar_isalnum (ch))
|
||||
g_string_append_unichar (ret, ch);
|
||||
else
|
||||
g_string_append_c (ret, '_');
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SysprofVisualizerGroup *self = (SysprofVisualizerGroup *)object;
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->title, g_free);
|
||||
g_clear_object (&priv->menu);
|
||||
g_clear_object (&priv->size_group);
|
||||
g_clear_object (&priv->default_menu);
|
||||
g_clear_object (&priv->rows_menu);
|
||||
g_clear_object (&priv->actions);
|
||||
|
||||
g_clear_weak_pointer (&priv->header);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_visualizer_group_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_group_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerGroup *self = SYSPROF_VISUALIZER_GROUP (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HAS_PAGE:
|
||||
g_value_set_boolean (value, sysprof_visualizer_group_get_has_page (self));
|
||||
break;
|
||||
|
||||
case PROP_MENU:
|
||||
g_value_set_object (value, sysprof_visualizer_group_get_menu (self));
|
||||
break;
|
||||
|
||||
case PROP_PRIORITY:
|
||||
g_value_set_int (value, sysprof_visualizer_group_get_priority (self));
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, sysprof_visualizer_group_get_title (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_group_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerGroup *self = SYSPROF_VISUALIZER_GROUP (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HAS_PAGE:
|
||||
sysprof_visualizer_group_set_has_page (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_MENU:
|
||||
sysprof_visualizer_group_set_menu (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_PRIORITY:
|
||||
sysprof_visualizer_group_set_priority (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
sysprof_visualizer_group_set_title (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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",
|
||||
"Has Page",
|
||||
FALSE,
|
||||
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_MENU] =
|
||||
g_param_spec_object ("menu",
|
||||
"Menu",
|
||||
"Menu",
|
||||
G_TYPE_MENU_MODEL,
|
||||
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_PRIORITY] =
|
||||
g_param_spec_int ("priority",
|
||||
"Priority",
|
||||
"The Priority of the group, used for sorting",
|
||||
G_MININT, G_MAXINT, 0,
|
||||
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"The title of the row",
|
||||
NULL,
|
||||
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
|
||||
signals [GROUP_ACTIVATED] =
|
||||
g_signal_new ("group-activated",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "SysprofVisualizerGroup");
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_group_init (SysprofVisualizerGroup *self)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
g_autoptr(GMenuItem) item = NULL;
|
||||
|
||||
priv->actions = g_simple_action_group_new ();
|
||||
|
||||
priv->default_menu = g_menu_new ();
|
||||
priv->rows_menu = g_menu_new ();
|
||||
|
||||
item = g_menu_item_new_section (NULL, G_MENU_MODEL (priv->rows_menu));
|
||||
g_menu_append_item (priv->default_menu, item);
|
||||
|
||||
priv->menu = g_object_ref (G_MENU_MODEL (priv->default_menu));
|
||||
|
||||
priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
|
||||
gtk_size_group_add_widget (priv->size_group, GTK_WIDGET (self));
|
||||
|
||||
priv->visualizers = g_object_new (GTK_TYPE_BOX,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (priv->visualizers));
|
||||
}
|
||||
|
||||
void
|
||||
_sysprof_visualizer_group_set_header (SysprofVisualizerGroup *self,
|
||||
SysprofVisualizerGroupHeader *header)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
|
||||
g_return_if_fail (!header || SYSPROF_IS_VISUALIZER_GROUP_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),
|
||||
"group",
|
||||
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)
|
||||
{
|
||||
SysprofVisualizer *vis = iter->data;
|
||||
const gchar *title;
|
||||
GMenuModel *menu = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER (vis));
|
||||
|
||||
if (position == 0)
|
||||
menu = priv->menu;
|
||||
|
||||
title = sysprof_visualizer_get_title (vis);
|
||||
|
||||
if (title == NULL)
|
||||
title = priv->title;
|
||||
|
||||
_sysprof_visualizer_group_header_add_row (header,
|
||||
position,
|
||||
title,
|
||||
menu,
|
||||
GTK_WIDGET (vis));
|
||||
|
||||
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)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (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);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_group_insert (SysprofVisualizerGroup *self,
|
||||
SysprofVisualizer *visualizer,
|
||||
gint position,
|
||||
gboolean can_toggle)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
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);
|
||||
|
||||
if (can_toggle)
|
||||
{
|
||||
const gchar *title = sysprof_visualizer_get_title (visualizer);
|
||||
g_autofree gchar *action_name = create_action_name (title);
|
||||
g_autofree gchar *full_action_name = g_strdup_printf ("group.%s", action_name);
|
||||
g_autoptr(GMenuItem) item = g_menu_item_new (title, full_action_name);
|
||||
g_autoptr(GPropertyAction) action = NULL;
|
||||
|
||||
action = g_property_action_new (action_name, visualizer, "visible");
|
||||
g_action_map_add_action (G_ACTION_MAP (priv->actions), G_ACTION (action));
|
||||
g_menu_item_set_attribute (item, "role", "s", "check");
|
||||
g_menu_append_item (priv->rows_menu, item);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
propagate_data_width_cb (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
_sysprof_visualizer_set_data_width (SYSPROF_VISUALIZER (widget),
|
||||
GPOINTER_TO_INT (user_data));
|
||||
}
|
||||
|
||||
void
|
||||
_sysprof_visualizer_group_set_data_width (SysprofVisualizerGroup *self,
|
||||
gint width)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
|
||||
|
||||
gtk_container_foreach (GTK_CONTAINER (priv->visualizers),
|
||||
propagate_data_width_cb,
|
||||
GINT_TO_POINTER (width));
|
||||
}
|
||||
|
||||
gint
|
||||
sysprof_visualizer_group_get_priority (SysprofVisualizerGroup *self)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self), 0);
|
||||
|
||||
return priv->priority;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_group_set_priority (SysprofVisualizerGroup *self,
|
||||
gint priority)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
|
||||
|
||||
if (priv->priority != priority)
|
||||
{
|
||||
priv->priority = priority;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PRIORITY]);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
sysprof_visualizer_group_get_has_page (SysprofVisualizerGroup *self)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self), FALSE);
|
||||
|
||||
return priv->has_page;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_group_set_has_page (SysprofVisualizerGroup *self,
|
||||
gboolean has_page)
|
||||
{
|
||||
SysprofVisualizerGroupPrivate *priv = sysprof_visualizer_group_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_GROUP (self));
|
||||
|
||||
has_page = !!has_page;
|
||||
|
||||
if (has_page != priv->has_page)
|
||||
{
|
||||
priv->has_page = has_page;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_HAS_PAGE]);
|
||||
}
|
||||
}
|
||||
76
src/libsysprof-ui/sysprof-visualizer-group.h
Normal file
76
src/libsysprof-ui/sysprof-visualizer-group.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* sysprof-visualizer-group.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_VISUALIZER_GROUP (sysprof_visualizer_group_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofVisualizerGroup, sysprof_visualizer_group, SYSPROF, VISUALIZER_GROUP, GtkListBoxRow)
|
||||
|
||||
struct _SysprofVisualizerGroupClass
|
||||
{
|
||||
GtkListBoxRowClass parent_class;
|
||||
|
||||
void (*group_activated) (SysprofVisualizerGroup *self);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofVisualizerGroup *sysprof_visualizer_group_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GMenuModel *sysprof_visualizer_group_get_menu (SysprofVisualizerGroup *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_group_set_menu (SysprofVisualizerGroup *self,
|
||||
GMenuModel *menu);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gint sysprof_visualizer_group_get_priority (SysprofVisualizerGroup *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_group_set_priority (SysprofVisualizerGroup *self,
|
||||
gint priority);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
const gchar *sysprof_visualizer_group_get_title (SysprofVisualizerGroup *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_group_set_title (SysprofVisualizerGroup *self,
|
||||
const gchar *title);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_visualizer_group_get_has_page (SysprofVisualizerGroup *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_group_set_has_page (SysprofVisualizerGroup *self,
|
||||
gboolean has_page);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_group_insert (SysprofVisualizerGroup *self,
|
||||
SysprofVisualizer *visualizer,
|
||||
gint position,
|
||||
gboolean can_toggle);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,582 +0,0 @@
|
||||
/* sysprof-visualizer-list.c
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer-list"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-cpu-visualizer-row.h"
|
||||
#include "sysprof-depth-visualizer-row.h"
|
||||
#include "sysprof-visualizer-list.h"
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-mark-visualizer-row.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
SysprofZoomManager *zoom_manager;
|
||||
} SysprofVisualizerListPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureCursor *cursor;
|
||||
GHashTable *mark_groups;
|
||||
guint fps_counter;
|
||||
guint pixels_counter;
|
||||
guint combined_cpu_counter;
|
||||
GArray *memory;
|
||||
guint batteries[4];
|
||||
guint has_battery : 1;
|
||||
guint has_cpu : 1;
|
||||
guint has_sample : 1;
|
||||
} Discovery;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_READER,
|
||||
PROP_ZOOM_MANAGER,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizerList, sysprof_visualizer_list, GTK_TYPE_LIST_BOX)
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void
|
||||
discovery_free (Discovery *state)
|
||||
{
|
||||
g_clear_pointer (&state->mark_groups, g_hash_table_unref);
|
||||
g_clear_pointer (&state->memory, g_array_unref);
|
||||
g_clear_pointer (&state->cursor, sysprof_capture_cursor_unref);
|
||||
g_slice_free (Discovery, state);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_list_add (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
SysprofVisualizerList *self = (SysprofVisualizerList *)container;
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
|
||||
GTK_CONTAINER_CLASS (sysprof_visualizer_list_parent_class)->add (container, widget);
|
||||
|
||||
if (SYSPROF_IS_VISUALIZER_ROW (widget))
|
||||
{
|
||||
sysprof_visualizer_row_set_reader (SYSPROF_VISUALIZER_ROW (widget), priv->reader);
|
||||
sysprof_visualizer_row_set_zoom_manager (SYSPROF_VISUALIZER_ROW (widget), priv->zoom_manager);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_list_finalize (GObject *object)
|
||||
{
|
||||
SysprofVisualizerList *self = (SysprofVisualizerList *)object;
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_visualizer_list_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_list_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerList *self = SYSPROF_VISUALIZER_LIST (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_READER:
|
||||
g_value_set_boxed (value, sysprof_visualizer_list_get_reader (self));
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
g_value_set_object (value, sysprof_visualizer_list_get_zoom_manager (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_list_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerList *self = SYSPROF_VISUALIZER_LIST (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_READER:
|
||||
sysprof_visualizer_list_set_reader (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
sysprof_visualizer_list_set_zoom_manager (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_list_class_init (SysprofVisualizerListClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_visualizer_list_finalize;
|
||||
object_class->get_property = sysprof_visualizer_list_get_property;
|
||||
object_class->set_property = sysprof_visualizer_list_set_property;
|
||||
|
||||
container_class->add = sysprof_visualizer_list_add;
|
||||
|
||||
properties [PROP_READER] =
|
||||
g_param_spec_boxed ("reader",
|
||||
"Reader",
|
||||
"The capture reader",
|
||||
SYSPROF_TYPE_CAPTURE_READER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_ZOOM_MANAGER] =
|
||||
g_param_spec_object ("zoom-manager",
|
||||
"Zoom Manager",
|
||||
"The zoom manager",
|
||||
SYSPROF_TYPE_ZOOM_MANAGER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_list_init (SysprofVisualizerList *self)
|
||||
{
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
sysprof_visualizer_list_new (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_VISUALIZER_ROW, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_list_get_reader:
|
||||
*
|
||||
* Gets the reader that is being used for the #SysprofVisualizerList.
|
||||
*
|
||||
* Returns: (transfer none): An #SysprofCaptureReader
|
||||
*/
|
||||
SysprofCaptureReader *
|
||||
sysprof_visualizer_list_get_reader (SysprofVisualizerList *self)
|
||||
{
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_LIST (self), NULL);
|
||||
|
||||
return priv->reader;
|
||||
}
|
||||
|
||||
static void
|
||||
add_battery_id (Discovery *state,
|
||||
guint battery_id)
|
||||
{
|
||||
for (guint i = 0; i < G_N_ELEMENTS (state->batteries); i++)
|
||||
{
|
||||
if (state->batteries[i] == 0)
|
||||
{
|
||||
state->batteries[i] = battery_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
discover_new_rows_frame_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
Discovery *state = user_data;
|
||||
|
||||
g_assert (frame != NULL);
|
||||
g_assert (state != NULL);
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* It would be nice if we could redesign this all around the concept of
|
||||
* an "gadget" or something which combines a data collection series
|
||||
* and widget views to be displayed.
|
||||
*/
|
||||
|
||||
if (frame->type == SYSPROF_CAPTURE_FRAME_SAMPLE)
|
||||
{
|
||||
state->has_sample = TRUE;
|
||||
}
|
||||
else if (frame->type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||
{
|
||||
const SysprofCaptureMark *mark = (const SysprofCaptureMark *)frame;
|
||||
|
||||
if (!g_hash_table_contains (state->mark_groups, mark->group))
|
||||
g_hash_table_add (state->mark_groups, g_strdup (mark->group));
|
||||
}
|
||||
else if (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF)
|
||||
{
|
||||
const SysprofCaptureCounterDefine *def = (const SysprofCaptureCounterDefine *)frame;
|
||||
|
||||
for (guint i = 0; i < def->n_counters; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *ctr = &def->counters[i];
|
||||
|
||||
if (!state->combined_cpu_counter &&
|
||||
strcmp (ctr->category, "CPU Percent") == 0 &&
|
||||
strcmp (ctr->name, "Combined") == 0)
|
||||
state->combined_cpu_counter = ctr->id;
|
||||
else if (!state->has_cpu &&
|
||||
strstr (ctr->category, "CPU Percent") != NULL)
|
||||
state->has_cpu = TRUE;
|
||||
else if (!state->fps_counter &&
|
||||
strstr (ctr->category, "gtk") != NULL && strstr (ctr->name, "fps") != NULL)
|
||||
state->fps_counter = ctr->id;
|
||||
else if (!state->pixels_counter &&
|
||||
strstr (ctr->category, "gtk") != NULL && strstr (ctr->name, "frame pixels") != NULL)
|
||||
state->pixels_counter = ctr->id;
|
||||
else if (strcmp (ctr->category, "Battery Charge") == 0)
|
||||
{
|
||||
state->has_battery = TRUE;
|
||||
add_battery_id (state, ctr->id);
|
||||
}
|
||||
else if (strcmp ("Memory", ctr->category) == 0 &&
|
||||
strcmp ("Used", ctr->name) == 0)
|
||||
{
|
||||
guint counter_id = ctr->id;
|
||||
g_array_append_val (state->memory, counter_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
discover_new_rows_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
Discovery *state = task_data;
|
||||
|
||||
g_assert (state != NULL);
|
||||
g_assert (state->cursor != NULL);
|
||||
|
||||
sysprof_capture_cursor_foreach (state->cursor, discover_new_rows_frame_cb, state);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_capture_results (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofVisualizerList *self = (SysprofVisualizerList *)object;
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
Discovery *state;
|
||||
const gchar *key;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (self));
|
||||
g_assert (G_IS_TASK (result));
|
||||
g_assert (user_data == NULL);
|
||||
|
||||
state = g_task_get_task_data (G_TASK (result));
|
||||
|
||||
/*
|
||||
* TODO: It would be really nice if we had a more structured way to do this
|
||||
* so that data collections and visualizations could be mapped
|
||||
* together. One way to do so might be to create the concept of an
|
||||
* "instrument" which represents that pair and allows the user to
|
||||
* select what sort of data collections they'd like to see.
|
||||
*/
|
||||
|
||||
if (state->combined_cpu_counter != 0)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER_ROW,
|
||||
/* Translators: CPU is the processor. */
|
||||
"title", _("CPU (Combined)"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
gdk_rgba_parse (&rgba, "#3465a4");
|
||||
sysprof_line_visualizer_row_add_counter (SYSPROF_LINE_VISUALIZER_ROW (row),
|
||||
state->combined_cpu_counter,
|
||||
&rgba);
|
||||
rgba.alpha = 0.5;
|
||||
sysprof_line_visualizer_row_set_fill (SYSPROF_LINE_VISUALIZER_ROW (row),
|
||||
state->combined_cpu_counter,
|
||||
&rgba);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
else if (state->has_cpu)
|
||||
{
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_CPU_VISUALIZER_ROW,
|
||||
"category", "CPU Percent",
|
||||
/* Translators: CPU is the processor. */
|
||||
"title", _("CPU"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
|
||||
if (state->has_cpu)
|
||||
{
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_CPU_VISUALIZER_ROW,
|
||||
"category", "CPU Frequency",
|
||||
/* Translators: CPU is the processor. */
|
||||
"title", _("CPU Frequency"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 100.0,
|
||||
"use-dash", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
|
||||
if (state->has_battery)
|
||||
{
|
||||
for (guint i = 0; i < G_N_ELEMENTS (state->batteries); i++)
|
||||
{
|
||||
GtkWidget *row;
|
||||
|
||||
if (state->batteries[i] == 0)
|
||||
break;
|
||||
|
||||
row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER_ROW,
|
||||
/* Translators: CPU is the processor. */
|
||||
"title", _("Battery Charge"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
sysprof_line_visualizer_row_add_counter (SYSPROF_LINE_VISUALIZER_ROW (row),
|
||||
state->batteries[i],
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->has_sample)
|
||||
{
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_DEPTH_VISUALIZER_ROW,
|
||||
"zoom-manager", priv->zoom_manager,
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
|
||||
for (guint i = 0; i < state->memory->len; i++)
|
||||
{
|
||||
guint counter_id = g_array_index (state->memory, guint, i);
|
||||
GdkRGBA rgba;
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER_ROW,
|
||||
"title", _("Memory Used"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
NULL);
|
||||
gdk_rgba_parse (&rgba, "#204a87");
|
||||
sysprof_line_visualizer_row_add_counter (SYSPROF_LINE_VISUALIZER_ROW (row), counter_id, &rgba);
|
||||
rgba.alpha = 0.3;
|
||||
sysprof_line_visualizer_row_set_fill (SYSPROF_LINE_VISUALIZER_ROW (row), counter_id, &rgba);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
|
||||
if (state->fps_counter)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER_ROW,
|
||||
/* Translators: FPS is frames per second. */
|
||||
"title", _("FPS"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
"y-upper", 150.0,
|
||||
NULL);
|
||||
gdk_rgba_parse (&rgba, "#204a87");
|
||||
sysprof_line_visualizer_row_add_counter (SYSPROF_LINE_VISUALIZER_ROW (row), state->fps_counter, &rgba);
|
||||
rgba.alpha = 0.3;
|
||||
sysprof_line_visualizer_row_set_fill (SYSPROF_LINE_VISUALIZER_ROW (row), state->fps_counter, &rgba);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
|
||||
if (state->pixels_counter)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_LINE_VISUALIZER_ROW,
|
||||
/* Translators: amount of pixels drawn per frame. */
|
||||
"title", _("Pixel Bandwidth"),
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
"y-lower", 0.0,
|
||||
NULL);
|
||||
gdk_rgba_parse (&rgba, "#ad7fa8");
|
||||
sysprof_line_visualizer_row_add_counter (SYSPROF_LINE_VISUALIZER_ROW (row), state->pixels_counter, &rgba);
|
||||
rgba.alpha = 0.3;
|
||||
sysprof_line_visualizer_row_set_fill (SYSPROF_LINE_VISUALIZER_ROW (row), state->pixels_counter, &rgba);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
|
||||
if (g_hash_table_size (state->mark_groups) < 30)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, state->mark_groups);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
|
||||
{
|
||||
GtkWidget *row = g_object_new (SYSPROF_TYPE_MARK_VISUALIZER_ROW,
|
||||
"group", key,
|
||||
"title", key,
|
||||
"height-request", 35,
|
||||
"selectable", FALSE,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self), row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
discover_new_rows (SysprofVisualizerList *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
static const SysprofCaptureFrameType types[] = {
|
||||
SYSPROF_CAPTURE_FRAME_CTRDEF,
|
||||
SYSPROF_CAPTURE_FRAME_MARK,
|
||||
SYSPROF_CAPTURE_FRAME_SAMPLE,
|
||||
};
|
||||
g_autoptr(SysprofCaptureCursor) cursor = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
SysprofCaptureCondition *condition;
|
||||
Discovery *state;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (self));
|
||||
g_assert (reader != NULL);
|
||||
|
||||
/*
|
||||
* The goal here is to automatically discover what rows should be added to
|
||||
* the visualizer list based on events we find in the capture file. In the
|
||||
* future, we might be able to add a UI flow to ask what the user wants or
|
||||
* denote capabilities at the beginning of the capture stream.
|
||||
*/
|
||||
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
condition = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types);
|
||||
sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
|
||||
|
||||
state = g_slice_new0 (Discovery);
|
||||
state->mark_groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
state->cursor = g_steal_pointer (&cursor);
|
||||
state->memory = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
|
||||
task = g_task_new (self, NULL, handle_capture_results, NULL);
|
||||
g_task_set_task_data (task, g_steal_pointer (&state), (GDestroyNotify)discovery_free);
|
||||
g_task_run_in_thread (task, discover_new_rows_worker);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_list_set_reader (SysprofVisualizerList *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_LIST (self));
|
||||
|
||||
if (reader != priv->reader)
|
||||
{
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
|
||||
if (reader != NULL)
|
||||
{
|
||||
priv->reader = sysprof_capture_reader_ref (reader);
|
||||
discover_new_rows (self, reader);
|
||||
}
|
||||
|
||||
gtk_container_foreach (GTK_CONTAINER (self),
|
||||
(GtkCallback)sysprof_visualizer_row_set_reader,
|
||||
reader);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_READER]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_list_set_zoom_manager (SysprofVisualizerList *self,
|
||||
SysprofZoomManager *zoom_manager)
|
||||
{
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_LIST (self));
|
||||
g_return_if_fail (SYSPROF_IS_ZOOM_MANAGER (zoom_manager));
|
||||
|
||||
if (g_set_object (&priv->zoom_manager, zoom_manager))
|
||||
{
|
||||
gtk_container_foreach (GTK_CONTAINER (self),
|
||||
(GtkCallback)sysprof_visualizer_row_set_zoom_manager,
|
||||
zoom_manager);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ZOOM_MANAGER]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_list_get_zoom_manager:
|
||||
*
|
||||
* Returns: (nullable) (transfer): A #SysprofZoomManager or %NULL.
|
||||
*/
|
||||
SysprofZoomManager *
|
||||
sysprof_visualizer_list_get_zoom_manager (SysprofVisualizerList *self)
|
||||
{
|
||||
SysprofVisualizerListPrivate *priv = sysprof_visualizer_list_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_LIST (self), NULL);
|
||||
|
||||
return priv->zoom_manager;
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
/* sysprof-visualizer-list.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "sysprof-capture-reader.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_VISUALIZER_LIST (sysprof_visualizer_list_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofVisualizerList, sysprof_visualizer_list, SYSPROF, VISUALIZER_LIST, GtkListBox)
|
||||
|
||||
struct _SysprofVisualizerListClass
|
||||
{
|
||||
GtkListBoxClass parent_class;
|
||||
|
||||
gpointer _reserved1;
|
||||
gpointer _reserved2;
|
||||
gpointer _reserved3;
|
||||
gpointer _reserved4;
|
||||
gpointer _reserved5;
|
||||
gpointer _reserved6;
|
||||
gpointer _reserved7;
|
||||
gpointer _reserved8;
|
||||
};
|
||||
|
||||
GtkWidget *sysprof_visualizer_list_new (void);
|
||||
void sysprof_visualizer_list_set_reader (SysprofVisualizerList *self,
|
||||
SysprofCaptureReader *reader);
|
||||
SysprofCaptureReader *sysprof_visualizer_list_get_reader (SysprofVisualizerList *self);
|
||||
SysprofZoomManager *sysprof_visualizer_list_get_zoom_manager (SysprofVisualizerList *self);
|
||||
void sysprof_visualizer_list_set_zoom_manager (SysprofVisualizerList *self,
|
||||
SysprofZoomManager *zoom_manager);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,300 +0,0 @@
|
||||
/* sysprof-visualizer-row.c
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer-row"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-visualizer-row-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
SysprofZoomManager *zoom_manager;
|
||||
} SysprofVisualizerRowPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ZOOM_MANAGER,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SysprofVisualizerRow, sysprof_visualizer_row, GTK_TYPE_LIST_BOX_ROW)
|
||||
|
||||
gint
|
||||
_sysprof_visualizer_row_get_graph_width (SysprofVisualizerRow *self)
|
||||
{
|
||||
SysprofVisualizerRowPrivate *priv = sysprof_visualizer_row_get_instance_private (self);
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_ROW (self));
|
||||
|
||||
if (priv->reader == NULL || priv->zoom_manager == NULL)
|
||||
return 0;
|
||||
|
||||
begin_time = sysprof_capture_reader_get_start_time (priv->reader);
|
||||
end_time = sysprof_capture_reader_get_end_time (priv->reader);
|
||||
|
||||
return sysprof_zoom_manager_get_width_for_duration (priv->zoom_manager, end_time - begin_time);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_get_preferred_width (GtkWidget *widget,
|
||||
gint *min_width,
|
||||
gint *nat_width)
|
||||
{
|
||||
SysprofVisualizerRow *self = (SysprofVisualizerRow *)widget;
|
||||
gint graph_width;
|
||||
gint real_min_width = 0;
|
||||
gint real_nat_width = 0;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_ROW (self));
|
||||
|
||||
GTK_WIDGET_CLASS (sysprof_visualizer_row_parent_class)->get_preferred_width (widget, &real_min_width, &real_nat_width);
|
||||
|
||||
graph_width = _sysprof_visualizer_row_get_graph_width (self);
|
||||
|
||||
*min_width = *nat_width = real_min_width + graph_width;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerRow *self = SYSPROF_VISUALIZER_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ZOOM_MANAGER:
|
||||
g_value_set_object (value, sysprof_visualizer_row_get_zoom_manager (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerRow *self = SYSPROF_VISUALIZER_ROW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ZOOM_MANAGER:
|
||||
sysprof_visualizer_row_set_zoom_manager (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_finalize (GObject *object)
|
||||
{
|
||||
SysprofVisualizerRow *self = (SysprofVisualizerRow *)object;
|
||||
SysprofVisualizerRowPrivate *priv = sysprof_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
g_clear_object (&priv->zoom_manager);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_visualizer_row_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_class_init (SysprofVisualizerRowClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_visualizer_row_finalize;
|
||||
object_class->get_property = sysprof_visualizer_row_get_property;
|
||||
object_class->set_property = sysprof_visualizer_row_set_property;
|
||||
|
||||
widget_class->get_preferred_width = sysprof_visualizer_row_get_preferred_width;
|
||||
|
||||
properties [PROP_ZOOM_MANAGER] =
|
||||
g_param_spec_object ("zoom-manager",
|
||||
"Zoom Manager",
|
||||
"Zoom Manager",
|
||||
SYSPROF_TYPE_ZOOM_MANAGER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_init (SysprofVisualizerRow *self)
|
||||
{
|
||||
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), FALSE);
|
||||
gtk_list_box_row_set_selectable (GTK_LIST_BOX_ROW (self), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_row_zoom_manager_notify_zoom (SysprofVisualizerRow *self,
|
||||
GParamSpec *pspec,
|
||||
SysprofZoomManager *zoom_manager)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_ROW (self));
|
||||
g_assert (SYSPROF_IS_ZOOM_MANAGER (zoom_manager));
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_row_get_zoom_manager:
|
||||
*
|
||||
* Returns: (transfer none) (nullable): A #SysprofZoomManager or %NULL.
|
||||
*/
|
||||
SysprofZoomManager *
|
||||
sysprof_visualizer_row_get_zoom_manager (SysprofVisualizerRow *self)
|
||||
{
|
||||
SysprofVisualizerRowPrivate *priv = sysprof_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_ROW (self), NULL);
|
||||
|
||||
return priv->zoom_manager;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_row_set_zoom_manager (SysprofVisualizerRow *self,
|
||||
SysprofZoomManager *zoom_manager)
|
||||
{
|
||||
SysprofVisualizerRowPrivate *priv = sysprof_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_ROW (self));
|
||||
g_return_if_fail (!zoom_manager || SYSPROF_IS_ZOOM_MANAGER (zoom_manager));
|
||||
|
||||
if (priv->zoom_manager != zoom_manager)
|
||||
{
|
||||
if (priv->zoom_manager != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->zoom_manager,
|
||||
G_CALLBACK (sysprof_visualizer_row_zoom_manager_notify_zoom),
|
||||
self);
|
||||
g_clear_object (&priv->zoom_manager);
|
||||
}
|
||||
|
||||
if (zoom_manager != NULL)
|
||||
{
|
||||
priv->zoom_manager = g_object_ref (zoom_manager);
|
||||
g_signal_connect_object (priv->zoom_manager,
|
||||
"notify::zoom",
|
||||
G_CALLBACK (sysprof_visualizer_row_zoom_manager_notify_zoom),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ZOOM_MANAGER]);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_row_set_reader (SysprofVisualizerRow *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofVisualizerRowPrivate *priv = sysprof_visualizer_row_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_ROW (self));
|
||||
|
||||
if (priv->reader != reader)
|
||||
{
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
|
||||
if (reader != NULL)
|
||||
priv->reader = sysprof_capture_reader_ref (reader);
|
||||
|
||||
if (SYSPROF_VISUALIZER_ROW_GET_CLASS (self)->set_reader)
|
||||
SYSPROF_VISUALIZER_ROW_GET_CLASS (self)->set_reader (self, reader);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
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 (SysprofVisualizerRow *self,
|
||||
GtkAllocation *alloc)
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
GtkBorder border;
|
||||
GtkStateFlags state;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_ROW (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);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_row_translate_points (SysprofVisualizerRow *self,
|
||||
const SysprofVisualizerRowRelativePoint *in_points,
|
||||
guint n_in_points,
|
||||
SysprofVisualizerRowAbsolutePoint *out_points,
|
||||
guint n_out_points)
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
gint graph_width;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_ROW (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);
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
adjust_alloc_for_borders (self, &alloc);
|
||||
|
||||
graph_width = _sysprof_visualizer_row_get_graph_width (self);
|
||||
|
||||
for (guint i = 0; i < n_in_points; i++)
|
||||
{
|
||||
out_points[i].x = (in_points[i].x * graph_width);
|
||||
out_points[i].y = alloc.height - (ABS (in_points[i].y) * alloc.height);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,83 +0,0 @@
|
||||
/* sysprof-visualizer-row.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_VISUALIZER_ROW (sysprof_visualizer_row_get_type())
|
||||
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofVisualizerRow, sysprof_visualizer_row, SYSPROF, VISUALIZER_ROW, GtkListBoxRow)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
} SysprofVisualizerRowRelativePoint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
} SysprofVisualizerRowAbsolutePoint;
|
||||
|
||||
struct _SysprofVisualizerRowClass
|
||||
{
|
||||
GtkListBoxRowClass parent_class;
|
||||
|
||||
/**
|
||||
* SysprofVisualizerRow::set_reader:
|
||||
*
|
||||
* Sets the reader that the row should use to extract counters.
|
||||
* This reader is private to the row and should be freed when
|
||||
* no longer in use with sysprof_capture_reader_unref().
|
||||
*/
|
||||
void (*set_reader) (SysprofVisualizerRow *self,
|
||||
SysprofCaptureReader *reader);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_row_set_reader (SysprofVisualizerRow *self,
|
||||
SysprofCaptureReader *reader);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofZoomManager *sysprof_visualizer_row_get_zoom_manager (SysprofVisualizerRow *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_row_set_zoom_manager (SysprofVisualizerRow *self,
|
||||
SysprofZoomManager *zoom_manager);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_row_translate_points (SysprofVisualizerRow *self,
|
||||
const SysprofVisualizerRowRelativePoint *in_points,
|
||||
guint n_in_points,
|
||||
SysprofVisualizerRowAbsolutePoint *out_points,
|
||||
guint n_out_points);
|
||||
|
||||
G_END_DECLS
|
||||
@ -18,19 +18,24 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer-ticks"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-visualizer-ticks.h"
|
||||
|
||||
#define NSEC_PER_SEC G_GINT64_CONSTANT(1000000000)
|
||||
#define NSEC_PER_HOUR (NSEC_PER_SEC * 60 * 60)
|
||||
#define NSEC_PER_MIN (NSEC_PER_SEC * 60)
|
||||
#define NSEC_PER_DAY (NSEC_PER_SEC * 60L * 60L * 24L)
|
||||
#define NSEC_PER_HOUR (NSEC_PER_SEC * 60L * 60L)
|
||||
#define NSEC_PER_MIN (NSEC_PER_SEC * 60L)
|
||||
#define NSEC_PER_MSEC (NSEC_PER_SEC/G_GINT64_CONSTANT(1000))
|
||||
#define MIN_TICK_DISTANCE 20
|
||||
#define LABEL_HEIGHT_PX 8
|
||||
#define LABEL_HEIGHT_PX 10
|
||||
|
||||
SYSPROF_ALIGNED_BEGIN (8)
|
||||
struct _SysprofVisualizerTicks
|
||||
{
|
||||
GtkDrawingArea parent_instance;
|
||||
@ -38,7 +43,7 @@ struct _SysprofVisualizerTicks
|
||||
gint64 epoch;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
} __attribute__((aligned(8)));
|
||||
} SYSPROF_ALIGNED_END (8);
|
||||
|
||||
enum {
|
||||
TICK_MINUTES,
|
||||
@ -50,6 +55,7 @@ enum {
|
||||
TICK_TENTHS,
|
||||
TICK_HUNDREDTHS,
|
||||
TICK_THOUSANDTHS,
|
||||
TICK_TEN_THOUSANDTHS,
|
||||
N_TICKS
|
||||
};
|
||||
|
||||
@ -67,6 +73,7 @@ struct {
|
||||
{ 1, 5, NSEC_PER_SEC / 10 },
|
||||
{ 1, 4, NSEC_PER_SEC / 100 },
|
||||
{ 1, 3, NSEC_PER_SEC / 1000 },
|
||||
{ 1, 1, NSEC_PER_SEC / 10000 },
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SysprofVisualizerTicks, sysprof_visualizer_ticks, GTK_TYPE_DRAWING_AREA)
|
||||
@ -82,6 +89,7 @@ update_label_text (PangoLayout *layout,
|
||||
gint hours = 0;
|
||||
gint min = 0;
|
||||
gint sec = 0;
|
||||
G_GNUC_UNUSED gint days = 0;
|
||||
|
||||
g_assert (PANGO_IS_LAYOUT (layout));
|
||||
|
||||
@ -89,6 +97,12 @@ update_label_text (PangoLayout *layout,
|
||||
time -= tmp;
|
||||
msec = tmp / 100000L;
|
||||
|
||||
if (time >= NSEC_PER_DAY)
|
||||
{
|
||||
days = time / NSEC_PER_DAY;
|
||||
time %= NSEC_PER_DAY;
|
||||
}
|
||||
|
||||
if (time >= NSEC_PER_HOUR)
|
||||
{
|
||||
hours = time / NSEC_PER_HOUR;
|
||||
@ -135,18 +149,6 @@ get_x_for_time (SysprofVisualizerTicks *self,
|
||||
return alloc->width * x_ratio;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline gint64
|
||||
get_time_at_x (SysprofVisualizerTicks *self,
|
||||
const GtkAllocation *alloc,
|
||||
gdouble x)
|
||||
{
|
||||
return self->begin_time
|
||||
- self->epoch
|
||||
+ ((self->end_time - self->begin_time) / (gdouble)alloc->width * x);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
draw_ticks (SysprofVisualizerTicks *self,
|
||||
cairo_t *cr,
|
||||
@ -186,8 +188,10 @@ draw_ticks (SysprofVisualizerTicks *self,
|
||||
PangoLayout *layout;
|
||||
PangoFontDescription *font_desc;
|
||||
gboolean want_msec;
|
||||
gint last_x2 = G_MININT;
|
||||
gint w, h;
|
||||
|
||||
layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "00:10:00");
|
||||
layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "00:10:00.0000");
|
||||
|
||||
font_desc = pango_font_description_new ();
|
||||
pango_font_description_set_family_static (font_desc, "Monospace");
|
||||
@ -195,6 +199,8 @@ draw_ticks (SysprofVisualizerTicks *self,
|
||||
pango_layout_set_font_description (layout, font_desc);
|
||||
pango_font_description_free (font_desc);
|
||||
|
||||
pango_layout_get_pixel_size (layout, &w, &h);
|
||||
|
||||
/* If we are operating on smaller than seconds here, then we want
|
||||
* to ensure we include msec with the timestamps.
|
||||
*/
|
||||
@ -206,9 +212,15 @@ draw_ticks (SysprofVisualizerTicks *self,
|
||||
{
|
||||
gdouble x = get_x_for_time (self, &alloc, t);
|
||||
|
||||
cairo_move_to (cr, (gint)x + .5 - (gint)half, alloc.height - LABEL_HEIGHT_PX);
|
||||
if (x < (last_x2 + MIN_TICK_DISTANCE))
|
||||
continue;
|
||||
|
||||
cairo_move_to (cr, (gint)x + 2.5 - (gint)half, 2);
|
||||
update_label_text (layout, t - self->epoch, want_msec);
|
||||
pango_layout_get_pixel_size (layout, &w, &h);
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
|
||||
last_x2 = x + w;
|
||||
}
|
||||
|
||||
g_clear_object (&layout);
|
||||
@ -221,8 +233,8 @@ draw_ticks (SysprofVisualizerTicks *self,
|
||||
{
|
||||
gdouble x = get_x_for_time (self, &alloc, t);
|
||||
|
||||
cairo_move_to (cr, (gint)x - .5 - (gint)half, 0);
|
||||
cairo_line_to (cr, (gint)x - .5 - (gint)half, tick_sizing[ticks].height);
|
||||
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);
|
||||
count++;
|
||||
}
|
||||
|
||||
@ -235,7 +247,7 @@ draw_ticks (SysprofVisualizerTicks *self,
|
||||
|
||||
static gboolean
|
||||
sysprof_visualizer_ticks_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofVisualizerTicks *self = SYSPROF_VISUALIZER_TICKS (widget);
|
||||
GtkStyleContext *style;
|
||||
@ -250,9 +262,12 @@ sysprof_visualizer_ticks_draw (GtkWidget *widget,
|
||||
if (0 == (timespan = self->end_time - self->begin_time))
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
gtk_render_background (style, cr, 0, 0, alloc.width, alloc.height);
|
||||
|
||||
state = gtk_widget_get_state_flags (widget);
|
||||
gtk_style_context_get_color (style, state, &color);
|
||||
|
||||
@ -290,8 +305,8 @@ sysprof_visualizer_ticks_draw (GtkWidget *widget,
|
||||
|
||||
static void
|
||||
sysprof_visualizer_ticks_get_preferred_height (GtkWidget *widget,
|
||||
gint *min_height,
|
||||
gint *nat_height)
|
||||
gint *min_height,
|
||||
gint *nat_height)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_TICKS (widget));
|
||||
|
||||
@ -306,7 +321,7 @@ sysprof_visualizer_ticks_class_init (SysprofVisualizerTicksClass *klass)
|
||||
widget_class->draw = sysprof_visualizer_ticks_draw;
|
||||
widget_class->get_preferred_height = sysprof_visualizer_ticks_get_preferred_height;
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "ticks");
|
||||
gtk_widget_class_set_css_name (widget_class, "SysprofVisualizerTicks");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -325,8 +340,8 @@ sysprof_visualizer_ticks_new (void)
|
||||
|
||||
void
|
||||
sysprof_visualizer_ticks_get_time_range (SysprofVisualizerTicks *self,
|
||||
gint64 *begin_time,
|
||||
gint64 *end_time)
|
||||
gint64 *begin_time,
|
||||
gint64 *end_time)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_TICKS (self));
|
||||
g_return_if_fail (begin_time != NULL || end_time != NULL);
|
||||
@ -340,8 +355,8 @@ sysprof_visualizer_ticks_get_time_range (SysprofVisualizerTicks *self,
|
||||
|
||||
void
|
||||
sysprof_visualizer_ticks_set_time_range (SysprofVisualizerTicks *self,
|
||||
gint64 begin_time,
|
||||
gint64 end_time)
|
||||
gint64 begin_time,
|
||||
gint64 end_time)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_TICKS (self));
|
||||
|
||||
@ -390,3 +405,11 @@ sysprof_visualizer_ticks_set_epoch (SysprofVisualizerTicks *self,
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
gint64
|
||||
sysprof_visualizer_ticks_get_duration (SysprofVisualizerTicks *self)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_TICKS (self), 0);
|
||||
|
||||
return self->end_time - self->begin_time;
|
||||
}
|
||||
|
||||
@ -20,10 +20,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -42,5 +38,6 @@ void sysprof_visualizer_ticks_get_time_range (SysprofVisualizerTicks *self
|
||||
void sysprof_visualizer_ticks_set_time_range (SysprofVisualizerTicks *self,
|
||||
gint64 begin_time,
|
||||
gint64 end_time);
|
||||
gint64 sysprof_visualizer_ticks_get_duration (SysprofVisualizerTicks *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -1,762 +0,0 @@
|
||||
/* sysprof-visualizer-view.c
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer-view"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "sysprof-theme-manager.h"
|
||||
#include "sysprof-visualizer-list.h"
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-visualizer-row-private.h"
|
||||
#include "sysprof-visualizer-ticks.h"
|
||||
#include "sysprof-visualizer-view.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureReader *reader;
|
||||
SysprofZoomManager *zoom_manager;
|
||||
SysprofSelection *selection;
|
||||
|
||||
SysprofVisualizerList *list;
|
||||
GtkScrolledWindow *scroller;
|
||||
SysprofVisualizerTicks *ticks;
|
||||
|
||||
gint64 drag_begin_at;
|
||||
gint64 drag_selection_at;
|
||||
|
||||
guint button_pressed : 1;
|
||||
} SysprofVisualizerViewPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SysprofVisualizerView *self;
|
||||
GtkStyleContext *style_context;
|
||||
cairo_t *cr;
|
||||
GtkAllocation alloc;
|
||||
} SelectionDraw;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_READER,
|
||||
PROP_ZOOM_MANAGER,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
enum {
|
||||
VISUALIZER_ADDED,
|
||||
VISUALIZER_REMOVED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static void buildable_iface_init (GtkBuildableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (SysprofVisualizerView, sysprof_visualizer_view, GTK_TYPE_BIN, 0,
|
||||
G_ADD_PRIVATE (SysprofVisualizerView)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init))
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
static guint signals [N_SIGNALS];
|
||||
static GtkBuildableIface *parent_buildable;
|
||||
|
||||
static void
|
||||
find_row1 (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget **row1 = data;
|
||||
|
||||
if (*row1 == NULL && SYSPROF_IS_VISUALIZER_ROW (widget))
|
||||
*row1 = widget;
|
||||
}
|
||||
|
||||
static gint64
|
||||
get_time_from_coordinates (SysprofVisualizerView *self,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
SysprofVisualizerRow *row1 = NULL;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
gint graph_width;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
|
||||
if (priv->reader == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Find the first row so we can get an idea of how wide the graph is
|
||||
* (ignoring spacing caused by the widget being wider than the data points.
|
||||
*/
|
||||
gtk_container_foreach (GTK_CONTAINER (priv->list), find_row1, &row1);
|
||||
if (!SYSPROF_IS_VISUALIZER_ROW (row1))
|
||||
return 0;
|
||||
|
||||
begin_time = sysprof_capture_reader_get_start_time (priv->reader);
|
||||
end_time = sysprof_capture_reader_get_end_time (priv->reader);
|
||||
graph_width = _sysprof_visualizer_row_get_graph_width (row1);
|
||||
|
||||
return begin_time + ((end_time - begin_time) * (x / (gdouble)graph_width));
|
||||
}
|
||||
|
||||
static gint
|
||||
get_x_for_time_at (SysprofVisualizerView *self,
|
||||
const GtkAllocation *alloc,
|
||||
gint64 time_at)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
SysprofVisualizerRow *row1 = NULL;
|
||||
GtkAdjustment *hadjustment;
|
||||
gdouble nsec_per_pixel;
|
||||
gdouble value;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
gint graph_width;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (alloc != NULL);
|
||||
|
||||
/*
|
||||
* Find the first row so we can get an idea of how wide the graph is
|
||||
* (ignoring spacing caused by the widget being wider than the data points.
|
||||
*/
|
||||
gtk_container_foreach (GTK_CONTAINER (priv->list), find_row1, &row1);
|
||||
if (!SYSPROF_IS_VISUALIZER_ROW (row1))
|
||||
return 0;
|
||||
|
||||
hadjustment = gtk_scrolled_window_get_hadjustment (priv->scroller);
|
||||
value = gtk_adjustment_get_value (hadjustment);
|
||||
|
||||
begin_time = sysprof_capture_reader_get_start_time (priv->reader);
|
||||
end_time = sysprof_capture_reader_get_end_time (priv->reader);
|
||||
|
||||
graph_width = _sysprof_visualizer_row_get_graph_width (row1);
|
||||
nsec_per_pixel = (end_time - begin_time) / (gdouble)graph_width;
|
||||
begin_time += value * nsec_per_pixel;
|
||||
|
||||
return ((time_at - begin_time) / nsec_per_pixel);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_row_added (SysprofVisualizerView *self,
|
||||
GtkWidget *widget,
|
||||
SysprofVisualizerList *list)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (GTK_IS_WIDGET (widget));
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (list));
|
||||
|
||||
if (SYSPROF_IS_VISUALIZER_ROW (widget))
|
||||
g_signal_emit (self, signals [VISUALIZER_ADDED], 0, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_row_removed (SysprofVisualizerView *self,
|
||||
GtkWidget *widget,
|
||||
SysprofVisualizerList *list)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (GTK_IS_WIDGET (widget));
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (list));
|
||||
|
||||
if (SYSPROF_IS_VISUALIZER_ROW (widget))
|
||||
g_signal_emit (self, signals [VISUALIZER_REMOVED], 0, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_update_ticks (SysprofVisualizerView *self)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
GtkAdjustment *hadjustment;
|
||||
GtkAllocation alloc;
|
||||
gdouble value;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
|
||||
hadjustment = gtk_scrolled_window_get_hadjustment (priv->scroller);
|
||||
value = gtk_adjustment_get_value (hadjustment);
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
|
||||
begin_time = get_time_from_coordinates (self, alloc.x + value, alloc.y);
|
||||
end_time = get_time_from_coordinates (self, alloc.x + value + alloc.width, alloc.y);
|
||||
|
||||
sysprof_visualizer_ticks_set_time_range (priv->ticks, begin_time, end_time);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_hadjustment_value_changed (SysprofVisualizerView *self,
|
||||
GtkAdjustment *adjustment)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (GTK_IS_ADJUSTMENT (adjustment));
|
||||
|
||||
sysprof_visualizer_view_update_ticks (self);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
SysprofVisualizerView *self = (SysprofVisualizerView *)widget;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (allocation != NULL);
|
||||
|
||||
GTK_WIDGET_CLASS (sysprof_visualizer_view_parent_class)->size_allocate (widget, allocation);
|
||||
|
||||
sysprof_visualizer_view_update_ticks (self);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_selection_cb (SysprofSelection *selection,
|
||||
gint64 range_begin,
|
||||
gint64 range_end,
|
||||
gpointer user_data)
|
||||
{
|
||||
SelectionDraw *draw = user_data;
|
||||
GdkRectangle area;
|
||||
|
||||
g_assert (SYSPROF_IS_SELECTION (selection));
|
||||
g_assert (draw != NULL);
|
||||
g_assert (draw->cr != NULL);
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (draw->self));
|
||||
|
||||
area.x = get_x_for_time_at (draw->self, &draw->alloc, range_begin);
|
||||
area.width = get_x_for_time_at (draw->self, &draw->alloc, range_end) - area.x;
|
||||
area.y = 0;
|
||||
area.height = draw->alloc.height;
|
||||
|
||||
if (area.width < 0)
|
||||
{
|
||||
area.width = ABS (area.width);
|
||||
area.x -= area.width;
|
||||
}
|
||||
|
||||
gtk_render_background (draw->style_context, draw->cr, area.x, area.y, area.width, area.height);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_visualizer_view_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
SysprofVisualizerView *self = (SysprofVisualizerView *)widget;
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
SelectionDraw draw = { 0 };
|
||||
gboolean ret;
|
||||
|
||||
g_assert (GTK_IS_WIDGET (widget));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
draw.style_context = gtk_widget_get_style_context (widget);
|
||||
draw.self = self;
|
||||
draw.cr = cr;
|
||||
|
||||
gtk_widget_get_allocation (widget, &draw.alloc);
|
||||
|
||||
ret = GTK_WIDGET_CLASS (sysprof_visualizer_view_parent_class)->draw (widget, cr);
|
||||
|
||||
if (sysprof_selection_get_has_selection (priv->selection) || priv->button_pressed)
|
||||
{
|
||||
gtk_style_context_add_class (draw.style_context, "selection");
|
||||
sysprof_selection_foreach (priv->selection, draw_selection_cb, &draw);
|
||||
if (priv->button_pressed)
|
||||
draw_selection_cb (priv->selection, priv->drag_begin_at, priv->drag_selection_at, &draw);
|
||||
gtk_style_context_remove_class (draw.style_context, "selection");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_visualizer_view_list_button_press_event (SysprofVisualizerView *self,
|
||||
GdkEventButton *ev,
|
||||
SysprofVisualizerList *list)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (ev != NULL);
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (list));
|
||||
|
||||
if (priv->reader == NULL)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
if (ev->button != GDK_BUTTON_PRIMARY)
|
||||
{
|
||||
if (sysprof_selection_get_has_selection (priv->selection))
|
||||
{
|
||||
sysprof_selection_unselect_all (priv->selection);
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
if ((ev->state & GDK_SHIFT_MASK) == 0)
|
||||
sysprof_selection_unselect_all (priv->selection);
|
||||
|
||||
priv->button_pressed = TRUE;
|
||||
|
||||
priv->drag_begin_at = get_time_from_coordinates (self, ev->x, ev->y);
|
||||
priv->drag_selection_at = priv->drag_begin_at;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_visualizer_view_list_button_release_event (SysprofVisualizerView *self,
|
||||
GdkEventButton *ev,
|
||||
SysprofVisualizerList *list)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (ev != NULL);
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (list));
|
||||
|
||||
if (!priv->button_pressed || ev->button != GDK_BUTTON_PRIMARY)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
priv->button_pressed = FALSE;
|
||||
|
||||
if (priv->drag_begin_at != priv->drag_selection_at)
|
||||
{
|
||||
sysprof_selection_select_range (priv->selection,
|
||||
priv->drag_begin_at,
|
||||
priv->drag_selection_at);
|
||||
priv->drag_begin_at = -1;
|
||||
priv->drag_selection_at = -1;
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_visualizer_view_list_motion_notify_event (SysprofVisualizerView *self,
|
||||
GdkEventMotion *ev,
|
||||
SysprofVisualizerList *list)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (ev != NULL);
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (list));
|
||||
|
||||
if (!priv->button_pressed)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
priv->drag_selection_at = get_time_from_coordinates (self, ev->x, ev->y);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_list_realize_after (SysprofVisualizerView *self,
|
||||
SysprofVisualizerList *list)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkWindow *window;
|
||||
GdkCursor *cursor;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (SYSPROF_IS_VISUALIZER_LIST (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 void
|
||||
sysprof_visualizer_view_selection_changed (SysprofVisualizerView *self,
|
||||
SysprofSelection *selection)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (SYSPROF_IS_SELECTION (selection));
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_finalize (GObject *object)
|
||||
{
|
||||
SysprofVisualizerView *self = (SysprofVisualizerView *)object;
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
g_clear_object (&priv->zoom_manager);
|
||||
g_clear_object (&priv->selection);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_visualizer_view_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerView *self = SYSPROF_VISUALIZER_VIEW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_READER:
|
||||
g_value_set_boxed (value, sysprof_visualizer_view_get_reader (self));
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
g_value_set_object (value, sysprof_visualizer_view_get_zoom_manager (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizerView *self = SYSPROF_VISUALIZER_VIEW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_READER:
|
||||
sysprof_visualizer_view_set_reader (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_ZOOM_MANAGER:
|
||||
sysprof_visualizer_view_set_zoom_manager (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_class_init (SysprofVisualizerViewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
SysprofThemeManager *theme_manager = sysprof_theme_manager_get_default ();
|
||||
|
||||
object_class->finalize = sysprof_visualizer_view_finalize;
|
||||
object_class->get_property = sysprof_visualizer_view_get_property;
|
||||
object_class->set_property = sysprof_visualizer_view_set_property;
|
||||
|
||||
widget_class->draw = sysprof_visualizer_view_draw;
|
||||
widget_class->size_allocate = sysprof_visualizer_view_size_allocate;
|
||||
|
||||
properties [PROP_READER] =
|
||||
g_param_spec_boxed ("reader",
|
||||
"Reader",
|
||||
"The reader for the visualizers",
|
||||
SYSPROF_TYPE_CAPTURE_READER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_ZOOM_MANAGER] =
|
||||
g_param_spec_object ("zoom-manager",
|
||||
"Zoom Manager",
|
||||
"The zoom manager for the view",
|
||||
SYSPROF_TYPE_ZOOM_MANAGER,
|
||||
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
|
||||
signals [VISUALIZER_ADDED] =
|
||||
g_signal_new ("visualizer-added",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (SysprofVisualizerViewClass, visualizer_added),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, SYSPROF_TYPE_VISUALIZER_ROW);
|
||||
|
||||
signals [VISUALIZER_REMOVED] =
|
||||
g_signal_new ("visualizer-removed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (SysprofVisualizerViewClass, visualizer_removed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, SYSPROF_TYPE_VISUALIZER_ROW);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-visualizer-view.ui");
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofVisualizerView, list);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofVisualizerView, scroller);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, SysprofVisualizerView, ticks);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "visualizers");
|
||||
|
||||
sysprof_theme_manager_register_resource (theme_manager, NULL, NULL, "/org/gnome/sysprof/css/SysprofVisualizerView-shared.css");
|
||||
sysprof_theme_manager_register_resource (theme_manager, "Adwaita", NULL, "/org/gnome/sysprof/css/SysprofVisualizerView-Adwaita.css");
|
||||
sysprof_theme_manager_register_resource (theme_manager, "Adwaita", "dark", "/org/gnome/sysprof/css/SysprofVisualizerView-Adwaita-dark.css");
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_VISUALIZER_LIST);
|
||||
g_type_ensure (SYSPROF_TYPE_VISUALIZER_TICKS);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_init (SysprofVisualizerView *self)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
GtkAdjustment *hadjustment;
|
||||
|
||||
priv->drag_begin_at = -1;
|
||||
priv->drag_selection_at = -1;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
priv->selection = g_object_new (SYSPROF_TYPE_SELECTION, NULL);
|
||||
|
||||
g_signal_connect_object (priv->selection,
|
||||
"changed",
|
||||
G_CALLBACK (sysprof_visualizer_view_selection_changed),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->list,
|
||||
"button-press-event",
|
||||
G_CALLBACK (sysprof_visualizer_view_list_button_press_event),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->list,
|
||||
"button-release-event",
|
||||
G_CALLBACK (sysprof_visualizer_view_list_button_release_event),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->list,
|
||||
"motion-notify-event",
|
||||
G_CALLBACK (sysprof_visualizer_view_list_motion_notify_event),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->list,
|
||||
"realize",
|
||||
G_CALLBACK (sysprof_visualizer_view_list_realize_after),
|
||||
self,
|
||||
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
|
||||
|
||||
g_signal_connect_object (priv->list,
|
||||
"add",
|
||||
G_CALLBACK (sysprof_visualizer_view_row_added),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (priv->list,
|
||||
"remove",
|
||||
G_CALLBACK (sysprof_visualizer_view_row_removed),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
hadjustment = gtk_scrolled_window_get_hadjustment (priv->scroller);
|
||||
|
||||
g_signal_connect_object (hadjustment,
|
||||
"value-changed",
|
||||
G_CALLBACK (sysprof_visualizer_view_hadjustment_value_changed),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_view_get_reader:
|
||||
*
|
||||
* Returns: (transfer none): An #SysprofCaptureReader
|
||||
*/
|
||||
SysprofCaptureReader *
|
||||
sysprof_visualizer_view_get_reader (SysprofVisualizerView *self)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_VIEW (self), NULL);
|
||||
|
||||
return priv->reader;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_view_set_reader (SysprofVisualizerView *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
|
||||
if (priv->reader != reader)
|
||||
{
|
||||
g_clear_pointer (&priv->reader, sysprof_capture_reader_unref);
|
||||
|
||||
if (reader != NULL)
|
||||
{
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
|
||||
priv->reader = sysprof_capture_reader_ref (reader);
|
||||
|
||||
begin_time = sysprof_capture_reader_get_start_time (priv->reader);
|
||||
end_time = sysprof_capture_reader_get_end_time (priv->reader);
|
||||
|
||||
sysprof_visualizer_ticks_set_epoch (priv->ticks, begin_time);
|
||||
sysprof_visualizer_ticks_set_time_range (priv->ticks, begin_time, end_time);
|
||||
|
||||
sysprof_selection_unselect_all (priv->selection);
|
||||
}
|
||||
|
||||
sysprof_visualizer_list_set_reader (priv->list, reader);
|
||||
sysprof_visualizer_view_update_ticks (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_READER]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_add_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *type)
|
||||
{
|
||||
SysprofVisualizerView *self = (SysprofVisualizerView *)buildable;
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (GTK_IS_BUILDER (builder));
|
||||
g_assert (G_IS_OBJECT (child));
|
||||
|
||||
if (g_strcmp0 (type, "visualizer") == 0 && GTK_IS_WIDGET (child))
|
||||
{
|
||||
gtk_container_add (GTK_CONTAINER (priv->list), GTK_WIDGET (child));
|
||||
return;
|
||||
}
|
||||
|
||||
parent_buildable->add_child (buildable, builder, child, type);
|
||||
}
|
||||
|
||||
static void
|
||||
buildable_iface_init (GtkBuildableIface *iface)
|
||||
{
|
||||
parent_buildable = g_type_interface_peek_parent (iface);
|
||||
iface->add_child = sysprof_visualizer_view_add_child;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_view_zoom_manager_notify_zoom (SysprofVisualizerView *self,
|
||||
GParamSpec *pspec,
|
||||
SysprofZoomManager *zoom_manager)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_assert (SYSPROF_IS_ZOOM_MANAGER (zoom_manager));
|
||||
|
||||
sysprof_visualizer_view_update_ticks (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_view_get_zoom_manager:
|
||||
*
|
||||
* Returns: (transfer none) (nullable): An #SysprofZoomManager or %NULL
|
||||
*/
|
||||
SysprofZoomManager *
|
||||
sysprof_visualizer_view_get_zoom_manager (SysprofVisualizerView *self)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_VIEW (self), NULL);
|
||||
|
||||
return priv->zoom_manager;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_view_set_zoom_manager (SysprofVisualizerView *self,
|
||||
SysprofZoomManager *zoom_manager)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_return_if_fail (!zoom_manager || SYSPROF_IS_ZOOM_MANAGER (zoom_manager));
|
||||
|
||||
if (priv->zoom_manager != zoom_manager)
|
||||
{
|
||||
if (priv->zoom_manager != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->zoom_manager,
|
||||
G_CALLBACK (sysprof_visualizer_view_zoom_manager_notify_zoom),
|
||||
self);
|
||||
g_clear_object (&priv->zoom_manager);
|
||||
}
|
||||
|
||||
if (zoom_manager != NULL)
|
||||
{
|
||||
priv->zoom_manager = g_object_ref (zoom_manager);
|
||||
g_signal_connect_object (priv->zoom_manager,
|
||||
"notify::zoom",
|
||||
G_CALLBACK (sysprof_visualizer_view_zoom_manager_notify_zoom),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
sysprof_visualizer_list_set_zoom_manager (priv->list, zoom_manager);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ZOOM_MANAGER]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizer_view_get_selection:
|
||||
*
|
||||
* Gets the #SysprofSelection instance for the visualizer view.
|
||||
* This can be used to alter the selection or selections of the visualizers.
|
||||
*
|
||||
* Returns: (transfer none): An #SysprofSelection.
|
||||
*/
|
||||
SysprofSelection *
|
||||
sysprof_visualizer_view_get_selection (SysprofVisualizerView *self)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER_VIEW (self), NULL);
|
||||
|
||||
return priv->selection;
|
||||
}
|
||||
|
||||
void
|
||||
_sysprof_visualizer_view_set_hadjustment (SysprofVisualizerView *self,
|
||||
GtkAdjustment *hadjustment)
|
||||
{
|
||||
SysprofVisualizerViewPrivate *priv = sysprof_visualizer_view_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER_VIEW (self));
|
||||
g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment));
|
||||
|
||||
gtk_scrolled_window_set_hadjustment (priv->scroller, hadjustment);
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
/* sysprof-visualizer-view.h
|
||||
*
|
||||
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-visualizer-row.h"
|
||||
#include "sysprof-selection.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
#include "sysprof-version-macros.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_VISUALIZER_VIEW (sysprof_visualizer_view_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofVisualizerView, sysprof_visualizer_view, SYSPROF, VISUALIZER_VIEW, GtkBin)
|
||||
|
||||
struct _SysprofVisualizerViewClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
|
||||
void (*visualizer_added) (SysprofVisualizerView *self,
|
||||
SysprofVisualizerRow *visualizer);
|
||||
void (*visualizer_removed) (SysprofVisualizerView *self,
|
||||
SysprofVisualizerRow *visualizer);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkWidget *sysprof_visualizer_view_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofCaptureReader *sysprof_visualizer_view_get_reader (SysprofVisualizerView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_view_set_reader (SysprofVisualizerView *self,
|
||||
SysprofCaptureReader *reader);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofZoomManager *sysprof_visualizer_view_get_zoom_manager (SysprofVisualizerView *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_view_set_zoom_manager (SysprofVisualizerView *self,
|
||||
SysprofZoomManager *zoom_manager);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofSelection *sysprof_visualizer_view_get_selection (SysprofVisualizerView *self);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="SysprofVisualizerView" parent="GtkBin">
|
||||
<child>
|
||||
<object class="GtkOverlay">
|
||||
<property name="visible">true</property>
|
||||
<child type="overlay">
|
||||
<object class="SysprofVisualizerTicks" id="ticks">
|
||||
<property name="valign">start</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pass-through">true</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scroller">
|
||||
<property name="propagate-natural-height">true</property>
|
||||
<property name="propagate-natural-width">false</property>
|
||||
<property name="visible">true</property>
|
||||
<child>
|
||||
<object class="SysprofVisualizerList" id="list">
|
||||
<property name="visible">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
346
src/libsysprof-ui/sysprof-visualizer.c
Normal file
346
src/libsysprof-ui/sysprof-visualizer.c
Normal file
@ -0,0 +1,346 @@
|
||||
/* sysprof-visualizer.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizer"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-visualizer.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *title;
|
||||
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
gint64 duration;
|
||||
|
||||
/* The width for [begin_time..end_time] which may be less
|
||||
* than what the widgets allocation is.
|
||||
*/
|
||||
gint data_width;
|
||||
} SysprofVisualizerPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (SysprofVisualizer, sysprof_visualizer, DZL_TYPE_BIN)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_BEGIN_TIME,
|
||||
PROP_END_TIME,
|
||||
PROP_TITLE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static gboolean
|
||||
sysprof_visualizer_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZER (widget));
|
||||
g_assert (cr != NULL);
|
||||
|
||||
GTK_WIDGET_CLASS (sysprof_visualizer_parent_class)->draw (widget, cr);
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_get_preferred_width (GtkWidget *widget,
|
||||
gint *min_width,
|
||||
gint *nat_width)
|
||||
{
|
||||
SysprofVisualizer *self = (SysprofVisualizer *)widget;
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZER (self));
|
||||
g_assert (min_width != NULL);
|
||||
g_assert (nat_width != NULL);
|
||||
|
||||
*min_width = *nat_width = priv->data_width ? priv->data_width : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_finalize (GObject *object)
|
||||
{
|
||||
SysprofVisualizer *self = (SysprofVisualizer *)object;
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->title, g_free);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_visualizer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizer *self = SYSPROF_VISUALIZER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, sysprof_visualizer_get_title (self));
|
||||
break;
|
||||
|
||||
case PROP_BEGIN_TIME:
|
||||
g_value_set_int64 (value, sysprof_visualizer_get_begin_time (self));
|
||||
break;
|
||||
|
||||
case PROP_END_TIME:
|
||||
g_value_set_int64 (value, sysprof_visualizer_get_end_time (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizer *self = SYSPROF_VISUALIZER (object);
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TITLE:
|
||||
sysprof_visualizer_set_title (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_BEGIN_TIME:
|
||||
priv->begin_time = g_value_get_int64 (value);
|
||||
priv->duration = priv->end_time - priv->begin_time;
|
||||
break;
|
||||
|
||||
case PROP_END_TIME:
|
||||
priv->end_time = g_value_get_int64 (value);
|
||||
priv->duration = priv->end_time - priv->begin_time;
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_class_init (SysprofVisualizerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = sysprof_visualizer_finalize;
|
||||
object_class->get_property = sysprof_visualizer_get_property;
|
||||
object_class->set_property = sysprof_visualizer_set_property;
|
||||
|
||||
widget_class->draw = sysprof_visualizer_draw;
|
||||
widget_class->get_preferred_width = sysprof_visualizer_get_preferred_width;
|
||||
|
||||
properties [PROP_BEGIN_TIME] =
|
||||
g_param_spec_int64 ("begin-time",
|
||||
"Begin Time",
|
||||
"Begin Time",
|
||||
G_MININT64,
|
||||
G_MAXINT64,
|
||||
0,
|
||||
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_END_TIME] =
|
||||
g_param_spec_int64 ("end-time",
|
||||
"End Time",
|
||||
"End Time",
|
||||
G_MININT64,
|
||||
G_MAXINT64,
|
||||
0,
|
||||
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"The title for the row",
|
||||
NULL,
|
||||
(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, "SysprofVisualizer");
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizer_init (SysprofVisualizer *self)
|
||||
{
|
||||
}
|
||||
|
||||
const gchar *
|
||||
sysprof_visualizer_get_title (SysprofVisualizer *self)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER (self), 0);
|
||||
|
||||
return priv->title;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_set_title (SysprofVisualizer *self,
|
||||
const gchar *title)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER (self));
|
||||
|
||||
if (g_strcmp0 (priv->title, title) != 0)
|
||||
{
|
||||
g_free (priv->title);
|
||||
priv->title = g_strdup (title);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
|
||||
}
|
||||
}
|
||||
|
||||
gint64
|
||||
sysprof_visualizer_get_begin_time (SysprofVisualizer *self)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER (self), 0);
|
||||
|
||||
return priv->begin_time;
|
||||
}
|
||||
|
||||
gint64
|
||||
sysprof_visualizer_get_end_time (SysprofVisualizer *self)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZER (self), 0);
|
||||
|
||||
return priv->end_time;
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_set_reader (SysprofVisualizer *self,
|
||||
SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER (self));
|
||||
g_return_if_fail (reader != NULL);
|
||||
|
||||
if (priv->begin_time == 0 || priv->end_time == 0)
|
||||
{
|
||||
priv->begin_time = sysprof_capture_reader_get_start_time (reader);
|
||||
priv->end_time = sysprof_capture_reader_get_end_time (reader);
|
||||
priv->duration = priv->end_time - priv->begin_time;
|
||||
}
|
||||
|
||||
if (SYSPROF_VISUALIZER_GET_CLASS (self)->set_reader)
|
||||
SYSPROF_VISUALIZER_GET_CLASS (self)->set_reader (self, reader);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizer_translate_points (SysprofVisualizer *self,
|
||||
const SysprofVisualizerRelativePoint *in_points,
|
||||
guint n_in_points,
|
||||
SysprofVisualizerAbsolutePoint *out_points,
|
||||
guint n_out_points)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
GtkAllocation alloc;
|
||||
gint graph_width;
|
||||
|
||||
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);
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
|
||||
adjust_alloc_for_borders (self, &alloc);
|
||||
|
||||
graph_width = priv->data_width;
|
||||
|
||||
for (guint i = 0; i < n_in_points; i++)
|
||||
{
|
||||
out_points[i].x = (in_points[i].x * graph_width);
|
||||
out_points[i].y = alloc.height - (ABS (in_points[i].y) * alloc.height);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_sysprof_visualizer_set_data_width (SysprofVisualizer *self,
|
||||
gint data_width)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZER (self));
|
||||
|
||||
if (priv->data_width != data_width)
|
||||
{
|
||||
priv->data_width = data_width;
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
sysprof_visualizer_get_x_for_time (SysprofVisualizer *self,
|
||||
gint64 time)
|
||||
{
|
||||
SysprofVisualizerPrivate *priv = sysprof_visualizer_get_instance_private (self);
|
||||
|
||||
return ((time - priv->begin_time) / (gdouble)priv->duration) * priv->data_width;
|
||||
}
|
||||
82
src/libsysprof-ui/sysprof-visualizer.h
Normal file
82
src/libsysprof-ui/sysprof-visualizer.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* sysprof-visualizer.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <dazzle.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
} SysprofVisualizerRelativePoint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint x;
|
||||
gint y;
|
||||
} SysprofVisualizerAbsolutePoint;
|
||||
|
||||
#define SYSPROF_TYPE_VISUALIZER (sysprof_visualizer_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofVisualizer, sysprof_visualizer, SYSPROF, VISUALIZER, DzlBin)
|
||||
|
||||
struct _SysprofVisualizerClass
|
||||
{
|
||||
DzlBinClass parent_class;
|
||||
|
||||
void (*set_reader) (SysprofVisualizer *self,
|
||||
SysprofCaptureReader *reader);
|
||||
|
||||
/*< private >*/
|
||||
gpointer _reserved[16];
|
||||
};
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
const gchar *sysprof_visualizer_get_title (SysprofVisualizer *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_set_title (SysprofVisualizer *self,
|
||||
const gchar *title);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gint64 sysprof_visualizer_get_begin_time (SysprofVisualizer *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gint64 sysprof_visualizer_get_end_time (SysprofVisualizer *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_set_reader (SysprofVisualizer *self,
|
||||
SysprofCaptureReader *reader);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gint sysprof_visualizer_get_x_for_time (SysprofVisualizer *self,
|
||||
gint64 time);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_visualizer_translate_points (SysprofVisualizer *self,
|
||||
const SysprofVisualizerRelativePoint *in_points,
|
||||
guint n_in_points,
|
||||
SysprofVisualizerAbsolutePoint *out_points,
|
||||
guint n_out_points);
|
||||
|
||||
G_END_DECLS
|
||||
767
src/libsysprof-ui/sysprof-visualizers-frame.c
Normal file
767
src/libsysprof-ui/sysprof-visualizers-frame.c
Normal file
@ -0,0 +1,767 @@
|
||||
/* sysprof-visualizers-frame.c
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "sysprof-visualizers-frame"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-scrollmap.h"
|
||||
#include "sysprof-visualizer-group-private.h"
|
||||
#include "sysprof-visualizer-ticks.h"
|
||||
#include "sysprof-visualizers-frame.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
struct _SysprofVisualizersFrame
|
||||
{
|
||||
GtkBin parent_instance;
|
||||
|
||||
/* Drag selection tracking */
|
||||
SysprofSelection *selection;
|
||||
gint64 drag_begin_at;
|
||||
gint64 drag_selection_at;
|
||||
guint button_pressed : 1;
|
||||
|
||||
/* Help avoid over-resizing/allocating */
|
||||
GtkAllocation last_alloc;
|
||||
gdouble last_zoom;
|
||||
|
||||
/* Known time range from the capture */
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
|
||||
/* Template Widgets */
|
||||
GtkListBox *groups;
|
||||
GtkListBox *visualizers;
|
||||
SysprofScrollmap *hscrollbar;
|
||||
SysprofVisualizerTicks *ticks;
|
||||
GtkScrolledWindow *ticks_scroller;
|
||||
GtkScrolledWindow *hscroller;
|
||||
GtkScrolledWindow *vscroller;
|
||||
SysprofZoomManager *zoom_manager;
|
||||
GtkScale *zoom_scale;
|
||||
GtkSizeGroup *left_column;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkListBox *list;
|
||||
GtkStyleContext *style_context;
|
||||
cairo_t *cr;
|
||||
GtkAllocation alloc;
|
||||
gint64 begin_time;
|
||||
gint64 duration;
|
||||
} SelectionDraw;
|
||||
|
||||
G_DEFINE_TYPE (SysprofVisualizersFrame, sysprof_visualizers_frame, GTK_TYPE_BIN)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SELECTED_GROUP,
|
||||
PROP_SELECTION,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static gint64
|
||||
get_time_from_x (SysprofVisualizersFrame *self,
|
||||
gdouble x)
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
gdouble ratio;
|
||||
gint64 duration;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self->ticks), &alloc);
|
||||
duration = sysprof_visualizer_ticks_get_duration (self->ticks);
|
||||
|
||||
if (alloc.width < 1)
|
||||
return 0;
|
||||
|
||||
ratio = x / alloc.width;
|
||||
|
||||
return self->begin_time + (ratio * duration);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_selection_cb (SysprofSelection *selection,
|
||||
gint64 range_begin,
|
||||
gint64 range_end,
|
||||
gpointer user_data)
|
||||
{
|
||||
SelectionDraw *draw = user_data;
|
||||
GdkRectangle area;
|
||||
gdouble x, x2;
|
||||
|
||||
g_assert (SYSPROF_IS_SELECTION (selection));
|
||||
g_assert (draw != NULL);
|
||||
g_assert (draw->cr != 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.y = 0;
|
||||
area.height = draw->alloc.height;
|
||||
|
||||
if (area.width < 0)
|
||||
{
|
||||
area.width = ABS (area.width);
|
||||
area.x -= area.width;
|
||||
}
|
||||
|
||||
gtk_render_background (draw->style_context, draw->cr, area.x + 2, area.y + 2, area.width - 4, area.height - 4);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
visualizers_draw_after_cb (SysprofVisualizersFrame *self,
|
||||
cairo_t *cr,
|
||||
GtkListBox *list)
|
||||
{
|
||||
SelectionDraw draw;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (GTK_IS_LIST_BOX (list));
|
||||
|
||||
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_ticks_get_duration (self->ticks);
|
||||
|
||||
if (draw.duration == 0)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (list), &draw.alloc);
|
||||
|
||||
if (sysprof_selection_get_has_selection (self->selection) || self->button_pressed)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (ev != NULL);
|
||||
g_assert (GTK_IS_LIST_BOX (visualizers));
|
||||
|
||||
if (ev->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;
|
||||
}
|
||||
|
||||
if ((ev->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_selection_at = self->drag_begin_at;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (visualizers));
|
||||
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
visualizers_button_release_event_cb (SysprofVisualizersFrame *self,
|
||||
GdkEventButton *ev,
|
||||
GtkListBox *list)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (ev != NULL);
|
||||
g_assert (GTK_IS_LIST_BOX (list));
|
||||
|
||||
if (!self->button_pressed || ev->button != GDK_BUTTON_PRIMARY)
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
|
||||
self->button_pressed = FALSE;
|
||||
|
||||
if (self->drag_begin_at != self->drag_selection_at)
|
||||
{
|
||||
sysprof_selection_select_range (self->selection,
|
||||
self->drag_begin_at,
|
||||
self->drag_selection_at);
|
||||
self->drag_begin_at = -1;
|
||||
self->drag_selection_at = -1;
|
||||
}
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (list));
|
||||
|
||||
return GDK_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
visualizers_motion_notify_event_cb (SysprofVisualizersFrame *self,
|
||||
GdkEventMotion *ev,
|
||||
GtkListBox *list)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (ev != NULL);
|
||||
g_assert (GTK_IS_LIST_BOX (list));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
propagate_data_width_cb (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
_sysprof_visualizer_group_set_data_width (SYSPROF_VISUALIZER_GROUP (widget),
|
||||
GPOINTER_TO_INT (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_notify_zoom (SysprofVisualizersFrame *self,
|
||||
GParamSpec *pspec,
|
||||
SysprofZoomManager *zoom_manager)
|
||||
{
|
||||
gint data_width;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (SYSPROF_IS_ZOOM_MANAGER (zoom_manager));
|
||||
|
||||
data_width = sysprof_zoom_manager_get_width_for_duration (self->zoom_manager,
|
||||
self->end_time - self->begin_time);
|
||||
gtk_container_foreach (GTK_CONTAINER (self->visualizers),
|
||||
propagate_data_width_cb,
|
||||
GINT_TO_POINTER (data_width));
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_apply_zoom (SysprofVisualizersFrame *self,
|
||||
const GtkAllocation *alloc)
|
||||
{
|
||||
gint64 duration;
|
||||
gint64 end_time;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
|
||||
duration = sysprof_zoom_manager_get_duration_for_width (self->zoom_manager, alloc->width);
|
||||
end_time = self->begin_time + duration;
|
||||
|
||||
sysprof_scrollmap_set_time_range (self->hscrollbar,
|
||||
self->begin_time,
|
||||
MAX (self->end_time, end_time));
|
||||
sysprof_visualizer_ticks_set_epoch (self->ticks, self->begin_time);
|
||||
sysprof_visualizer_ticks_set_time_range (self->ticks, self->begin_time, end_time);
|
||||
}
|
||||
|
||||
static gint
|
||||
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)
|
||||
{
|
||||
SysprofVisualizerGroup *group = iter->data;
|
||||
gint prio = sysprof_visualizer_group_get_priority (group);
|
||||
const gchar *item = sysprof_visualizer_group_get_title (group);
|
||||
|
||||
if (priority < prio ||
|
||||
(priority == prio && g_strcmp0 (title, item) < 0))
|
||||
break;
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_add (GtkContainer *container,
|
||||
GtkWidget *child)
|
||||
{
|
||||
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)container;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (GTK_IS_WIDGET (child));
|
||||
|
||||
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);
|
||||
|
||||
gtk_list_box_insert (self->visualizers, child, 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));
|
||||
|
||||
sysprof_visualizers_frame_notify_zoom (self, NULL, self->zoom_manager);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GTK_CONTAINER_CLASS (sysprof_visualizers_frame_parent_class)->add (container, child);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *alloc)
|
||||
{
|
||||
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)widget;
|
||||
gdouble zoom;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (alloc != NULL);
|
||||
|
||||
GTK_WIDGET_CLASS (sysprof_visualizers_frame_parent_class)->size_allocate (widget, alloc);
|
||||
|
||||
zoom = sysprof_zoom_manager_get_zoom (self->zoom_manager);
|
||||
|
||||
if (alloc->width != self->last_alloc.width || zoom != self->last_zoom)
|
||||
sysprof_visualizers_frame_apply_zoom (self, alloc);
|
||||
|
||||
self->last_alloc = *alloc;
|
||||
self->last_zoom = zoom;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_selection_changed (SysprofVisualizersFrame *self,
|
||||
SysprofSelection *selection)
|
||||
{
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (SYSPROF_IS_SELECTION (selection));
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (self->visualizers));
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SELECTION]);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_group_activated_cb (SysprofVisualizersFrame *self,
|
||||
SysprofVisualizerGroupHeader *row,
|
||||
GtkListBox *list)
|
||||
{
|
||||
SysprofVisualizerGroup *group;
|
||||
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_assert (SYSPROF_IS_VISUALIZER_GROUP_HEADER (row));
|
||||
|
||||
group = g_object_get_data (G_OBJECT (row), "VISUALIZER_GROUP");
|
||||
g_assert (SYSPROF_IS_VISUALIZER_GROUP (group));
|
||||
|
||||
g_signal_emit_by_name (group, "group-activated");
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_finalize (GObject *object)
|
||||
{
|
||||
SysprofVisualizersFrame *self = (SysprofVisualizersFrame *)object;
|
||||
|
||||
g_clear_object (&self->selection);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_visualizers_frame_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SysprofVisualizersFrame *self = SYSPROF_VISUALIZERS_FRAME (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SELECTED_GROUP:
|
||||
g_value_set_object (value, sysprof_visualizers_frame_get_selected_group (self));
|
||||
break;
|
||||
|
||||
case PROP_SELECTION:
|
||||
g_value_set_object (value, sysprof_visualizers_frame_get_selection (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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->get_property = sysprof_visualizers_frame_get_property;
|
||||
|
||||
widget_class->size_allocate = sysprof_visualizers_frame_size_allocate;
|
||||
|
||||
container_class->add = sysprof_visualizers_frame_add;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-visualizers-frame.ui");
|
||||
gtk_widget_class_set_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);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, hscroller);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, left_column);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, ticks);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, ticks_scroller);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, visualizers);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, vscroller);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, zoom_manager);
|
||||
gtk_widget_class_bind_template_child (widget_class, SysprofVisualizersFrame, zoom_scale);
|
||||
|
||||
properties [PROP_SELECTED_GROUP] =
|
||||
g_param_spec_object ("selected-group",
|
||||
"Selected Group",
|
||||
"The selected group",
|
||||
SYSPROF_TYPE_VISUALIZER_GROUP,
|
||||
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
properties [PROP_SELECTION] =
|
||||
g_param_spec_object ("selection",
|
||||
"Selection",
|
||||
"The time selection",
|
||||
SYSPROF_TYPE_SELECTION,
|
||||
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
|
||||
g_type_ensure (SYSPROF_TYPE_SCROLLMAP);
|
||||
g_type_ensure (SYSPROF_TYPE_VISUALIZER_TICKS);
|
||||
g_type_ensure (SYSPROF_TYPE_ZOOM_MANAGER);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_visualizers_frame_init (SysprofVisualizersFrame *self)
|
||||
{
|
||||
GtkAdjustment *hadj;
|
||||
GtkAdjustment *zadj;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
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);
|
||||
gtk_range_set_adjustment (GTK_RANGE (self->zoom_scale), zadj);
|
||||
|
||||
gtk_widget_insert_action_group (GTK_WIDGET (self),
|
||||
"zoom",
|
||||
G_ACTION_GROUP (self->zoom_manager));
|
||||
|
||||
g_signal_connect_object (self->groups,
|
||||
"row-activated",
|
||||
G_CALLBACK (sysprof_visualizers_frame_group_activated_cb),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
g_signal_connect_object (self->selection,
|
||||
"changed",
|
||||
G_CALLBACK (sysprof_visualizers_frame_selection_changed),
|
||||
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),
|
||||
self,
|
||||
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizers_frame_get_selected_group:
|
||||
*
|
||||
* Gets the currently selected group.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the selected row
|
||||
*
|
||||
* Since: 3.34
|
||||
*/
|
||||
SysprofVisualizerGroup *
|
||||
sysprof_visualizers_frame_get_selected_group (SysprofVisualizersFrame *self)
|
||||
{
|
||||
GtkListBoxRow *row;
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), NULL);
|
||||
|
||||
row = gtk_list_box_get_selected_row (self->groups);
|
||||
|
||||
return SYSPROF_VISUALIZER_GROUP (row);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizers_frame_get_selection:
|
||||
*
|
||||
* Get the time selection
|
||||
*
|
||||
* Returns: (transfer none): a #SysprofSelection
|
||||
*
|
||||
* Since: 3.34
|
||||
*/
|
||||
SysprofSelection *
|
||||
sysprof_visualizers_frame_get_selection (SysprofVisualizersFrame *self)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), NULL);
|
||||
|
||||
return self->selection;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_gint64 (const gint64 *a,
|
||||
const gint64 *b)
|
||||
{
|
||||
if (*a < *b)
|
||||
return -1;
|
||||
else if (*a > *b)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
index_frame_times_frame_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
GArray *array = user_data;
|
||||
|
||||
/* Track timing, but ignore some common types at startup */
|
||||
if (frame->type != SYSPROF_CAPTURE_FRAME_MAP &&
|
||||
frame->type != SYSPROF_CAPTURE_FRAME_PROCESS)
|
||||
g_array_append_val (array, frame->time);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
index_frame_times_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
SysprofCaptureCursor *cursor = task_data;
|
||||
GArray *timings = NULL;
|
||||
|
||||
g_assert (G_IS_TASK (task));
|
||||
g_assert (SYSPROF_IS_VISUALIZERS_FRAME (source_object));
|
||||
g_assert (cursor != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
timings = g_array_new (FALSE, FALSE, sizeof (gint64));
|
||||
sysprof_capture_cursor_foreach (cursor, index_frame_times_frame_cb, timings);
|
||||
g_array_sort (timings, (GCompareFunc) compare_gint64);
|
||||
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&timings),
|
||||
(GDestroyNotify) g_array_unref);
|
||||
}
|
||||
|
||||
void
|
||||
sysprof_visualizers_frame_load_async (SysprofVisualizersFrame *self,
|
||||
SysprofCaptureReader *reader,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
GtkAllocation alloc;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self));
|
||||
g_return_if_fail (reader != NULL);
|
||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self->ticks), &alloc);
|
||||
|
||||
/* At this point, the SysprofDisplay should have already scanned the
|
||||
* reader for all of the events and therefore we can trust the begin
|
||||
* and end time for the capture.
|
||||
*/
|
||||
self->begin_time = sysprof_capture_reader_get_start_time (reader);
|
||||
self->end_time = sysprof_capture_reader_get_end_time (reader);
|
||||
|
||||
if (alloc.width)
|
||||
sysprof_visualizers_frame_apply_zoom (self, &alloc);
|
||||
|
||||
/* Now we need to run through the frames and index their times
|
||||
* so that we can calculate the number of items per bucket when
|
||||
* drawing the scrollbar.
|
||||
*/
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, sysprof_visualizers_frame_load_async);
|
||||
g_task_set_task_data (task,
|
||||
sysprof_capture_cursor_new (reader),
|
||||
(GDestroyNotify) sysprof_capture_cursor_unref);
|
||||
g_task_run_in_thread (task, index_frame_times_worker);
|
||||
}
|
||||
|
||||
gboolean
|
||||
sysprof_visualizers_frame_load_finish (SysprofVisualizersFrame *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GArray) timings = NULL;
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), FALSE);
|
||||
g_return_val_if_fail (G_IS_TASK (result), FALSE);
|
||||
|
||||
if ((timings = g_task_propagate_pointer (G_TASK (result), error)))
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self->ticks), &alloc);
|
||||
sysprof_scrollmap_set_timings (self->hscrollbar, timings);
|
||||
sysprof_visualizers_frame_apply_zoom (self, &alloc);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizers_frame_get_zoom_manager:
|
||||
*
|
||||
* Gets the zoom manager for the frame.
|
||||
*
|
||||
* Returns: (transfer none): a #SysprofZoomManager
|
||||
*/
|
||||
SysprofZoomManager *
|
||||
sysprof_visualizers_frame_get_zoom_manager (SysprofVisualizersFrame *self)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), NULL);
|
||||
|
||||
return self->zoom_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizers_frame_get_size_group:
|
||||
*
|
||||
* gets the left column size group.
|
||||
*
|
||||
* Returns: (transfer none): a size group
|
||||
*/
|
||||
GtkSizeGroup *
|
||||
sysprof_visualizers_frame_get_size_group (SysprofVisualizersFrame *self)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_VISUALIZERS_FRAME (self), NULL);
|
||||
|
||||
return self->left_column;
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_visualizers_frame_get_hadjustment:
|
||||
*
|
||||
* Gets the scroll adjustment used for horizontal scrolling
|
||||
*
|
||||
* Returns: (transfer none): a #GtkAdjustment
|
||||
*/
|
||||
GtkAdjustment *
|
||||
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));
|
||||
}
|
||||
49
src/libsysprof-ui/sysprof-visualizers-frame.h
Normal file
49
src/libsysprof-ui/sysprof-visualizers-frame.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* sysprof-visualizers-frame.h
|
||||
*
|
||||
* Copyright 2019 Christian Hergert <chergert@redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
#include "sysprof-visualizer-group.h"
|
||||
#include "sysprof-zoom-manager.h"
|
||||
|
||||
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)
|
||||
|
||||
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);
|
||||
void sysprof_visualizers_frame_load_async (SysprofVisualizersFrame *self,
|
||||
SysprofCaptureReader *reader,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean sysprof_visualizers_frame_load_finish (SysprofVisualizersFrame *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GtkSizeGroup *sysprof_visualizers_frame_get_size_group (SysprofVisualizersFrame *self);
|
||||
GtkAdjustment *sysprof_visualizers_frame_get_hadjustment (SysprofVisualizersFrame *self);
|
||||
|
||||
G_END_DECLS
|
||||
419
src/libsysprof-ui/sysprof-visualizers-frame.ui
Normal file
419
src/libsysprof-ui/sysprof-visualizers-frame.ui
Normal file
@ -0,0 +1,419 @@
|
||||
<?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>
|
||||
<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">
|
||||
<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>
|
||||
<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>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<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"/>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">preferences-system-details-symbolic</property>
|
||||
<property name="pixel-size">16</property>
|
||||
<property name="visible">true</property>
|
||||
</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="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>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<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>
|
||||
<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">browse</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>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
<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="round_digits">1</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>
|
||||
<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>
|
||||
</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>
|
||||
</template>
|
||||
<object class="GtkSizeGroup" id="left_column">
|
||||
<widgets>
|
||||
<widget name="box1"/>
|
||||
<widget name="groups"/>
|
||||
<widget name="box2"/>
|
||||
</widgets>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="top_row">
|
||||
<property name="mode">vertical</property>
|
||||
<widgets>
|
||||
<widget name="box1"/>
|
||||
<widget name="ticks_box"/>
|
||||
</widgets>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="row_size_group">
|
||||
<widgets>
|
||||
<widget name="ticks"/>
|
||||
<widget name="visualizers"/>
|
||||
</widgets>
|
||||
</object>
|
||||
<object class="SysprofZoomManager" id="zoom_manager"/>
|
||||
</interface>
|
||||
@ -20,61 +20,38 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (SYSPROF_UI_INSIDE) && !defined (SYSPROF_UI_COMPILATION)
|
||||
# error "Only <sysprof-ui.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "sysprof-version-macros.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_ZOOM_MANAGER (sysprof_zoom_manager_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofZoomManager, sysprof_zoom_manager, SYSPROF, ZOOM_MANAGER, GObject)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofZoomManager *sysprof_zoom_manager_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GtkAdjustment *sysprof_zoom_manager_get_adjustment (SysprofZoomManager *self);
|
||||
gboolean sysprof_zoom_manager_get_can_zoom_in (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_zoom_manager_get_can_zoom_out (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_zoom_manager_get_min_zoom (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gboolean sysprof_zoom_manager_get_max_zoom (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_zoom_manager_set_min_zoom (SysprofZoomManager *self,
|
||||
gdouble min_zoom);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_zoom_manager_set_max_zoom (SysprofZoomManager *self,
|
||||
gdouble max_zoom);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_zoom_manager_zoom_in (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_zoom_manager_zoom_out (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_zoom_manager_reset (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gdouble sysprof_zoom_manager_get_zoom (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_zoom_manager_set_zoom (SysprofZoomManager *self,
|
||||
gdouble zoom);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gchar *sysprof_zoom_manager_get_zoom_label (SysprofZoomManager *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gint sysprof_zoom_manager_get_width_for_duration (SysprofZoomManager *self,
|
||||
gint64 duration);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gint64 sysprof_zoom_manager_get_duration_for_width (SysprofZoomManager *self,
|
||||
gint width);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gdouble sysprof_zoom_manager_fit_zoom_for_duration (SysprofZoomManager *self,
|
||||
gint64 duration,
|
||||
gint width);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
gdouble sysprof_zoom_manager_get_offset_at_time (SysprofZoomManager *self,
|
||||
gint64 offset,
|
||||
gint width);
|
||||
|
||||
@ -61,7 +61,8 @@ if get_option('enable_gtk')
|
||||
dependencies: test_ui_deps,
|
||||
)
|
||||
|
||||
test_zoom = executable('test-zoom', 'test-zoom.c',
|
||||
test_zoom = executable('test-zoom',
|
||||
['test-zoom.c', '../libsysprof-ui/sysprof-zoom-manager.c'],
|
||||
c_args: test_cflags,
|
||||
dependencies: test_ui_deps,
|
||||
)
|
||||
|
||||
@ -25,7 +25,7 @@ main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
GtkWindow *window;
|
||||
SysprofCaptureView *view;
|
||||
SysprofDisplay *view;
|
||||
SysprofCaptureReader *reader;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
@ -44,16 +44,16 @@ main (gint argc,
|
||||
}
|
||||
|
||||
window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"title", "SysprofCaptureView",
|
||||
"title", "SysprofDisplay",
|
||||
"default-width", 800,
|
||||
"default-height", 600,
|
||||
NULL);
|
||||
view = g_object_new (SYSPROF_TYPE_CAPTURE_VIEW,
|
||||
view = g_object_new (SYSPROF_TYPE_DISPLAY,
|
||||
"visible", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (view));
|
||||
|
||||
sysprof_capture_view_load_async (view, reader, NULL, NULL, NULL);
|
||||
sysprof_display_load_async (view, reader, NULL, NULL, NULL);
|
||||
|
||||
g_signal_connect (window, "delete-event", gtk_main_quit, NULL);
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
|
||||
Reference in New Issue
Block a user