|
Packit |
76ec6a |
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
Packit |
76ec6a |
#include <config.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <glib/gi18n.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <glibtop.h>
|
|
Packit |
76ec6a |
#include <glibtop/cpu.h>
|
|
Packit |
76ec6a |
#include <glibtop/mem.h>
|
|
Packit |
76ec6a |
#include <glibtop/swap.h>
|
|
Packit |
76ec6a |
#include <glibtop/netload.h>
|
|
Packit |
76ec6a |
#include <glibtop/netlist.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include "application.h"
|
|
Packit |
76ec6a |
#include "load-graph.h"
|
|
Packit |
76ec6a |
#include "util.h"
|
|
Packit |
76ec6a |
#include "legacy/gsm_color_button.h"
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void LoadGraph::clear_background()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
if (background) {
|
|
Packit |
76ec6a |
cairo_surface_destroy (background);
|
|
Packit |
76ec6a |
background = NULL;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
unsigned LoadGraph::num_bars() const
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
unsigned n;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// keep 100 % num_bars == 0
|
|
Packit |
76ec6a |
switch (static_cast<int>(draw_height / (fontsize + 14)))
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
case 0:
|
|
Packit |
76ec6a |
case 1:
|
|
Packit |
76ec6a |
n = 1;
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case 2:
|
|
Packit |
76ec6a |
case 3:
|
|
Packit |
76ec6a |
n = 2;
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case 4:
|
|
Packit |
76ec6a |
n = 4;
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
default:
|
|
Packit |
76ec6a |
n = 5;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return n;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#define FRAME_WIDTH 4
|
|
Packit |
76ec6a |
void draw_background(LoadGraph *graph) {
|
|
Packit |
76ec6a |
GtkAllocation allocation;
|
|
Packit |
76ec6a |
cairo_t *cr;
|
|
Packit |
76ec6a |
guint i;
|
|
Packit |
76ec6a |
unsigned num_bars;
|
|
Packit |
76ec6a |
char *caption;
|
|
Packit |
76ec6a |
PangoLayout* layout;
|
|
Packit |
76ec6a |
PangoFontDescription* font_desc;
|
|
Packit |
76ec6a |
PangoRectangle extents;
|
|
Packit |
76ec6a |
cairo_surface_t *surface;
|
|
Packit |
76ec6a |
GdkRGBA fg;
|
|
Packit |
76ec6a |
GdkRGBA fg_grid;
|
|
Packit |
76ec6a |
double const border_alpha = 0.7;
|
|
Packit |
76ec6a |
double const grid_alpha = border_alpha / 2.0;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
num_bars = graph->num_bars();
|
|
Packit |
76ec6a |
graph->graph_dely = (graph->draw_height - 15) / num_bars; /* round to int to avoid AA blur */
|
|
Packit |
76ec6a |
graph->real_draw_height = graph->graph_dely * num_bars;
|
|
Packit |
76ec6a |
graph->graph_delx = (graph->draw_width - 2.0 - graph->indent) / (LoadGraph::NUM_POINTS - 3);
|
|
Packit |
76ec6a |
graph->graph_buffer_offset = (int) (1.5 * graph->graph_delx) + FRAME_WIDTH ;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_get_allocation (GTK_WIDGET (graph->disp), &allocation);
|
|
Packit |
76ec6a |
surface = gdk_window_create_similar_surface (gtk_widget_get_window (GTK_WIDGET (graph->disp)),
|
|
Packit |
76ec6a |
CAIRO_CONTENT_COLOR_ALPHA,
|
|
Packit |
76ec6a |
allocation.width,
|
|
Packit |
76ec6a |
allocation.height);
|
|
Packit |
76ec6a |
cr = cairo_create (surface);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (GsmApplication::get()->stack));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &fg;;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
cairo_paint_with_alpha (cr, 0.0);
|
|
Packit |
76ec6a |
layout = pango_cairo_create_layout (cr);
|
|
Packit |
76ec6a |
gtk_style_context_get (context, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_FONT, &font_desc, NULL);
|
|
Packit |
76ec6a |
pango_font_description_set_size (font_desc, 0.8 * graph->fontsize * PANGO_SCALE);
|
|
Packit |
76ec6a |
pango_layout_set_font_description (layout, font_desc);
|
|
Packit |
76ec6a |
pango_font_description_free (font_desc);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* draw frame */
|
|
Packit |
76ec6a |
cairo_translate (cr, FRAME_WIDTH, FRAME_WIDTH);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Draw background rectangle */
|
|
Packit |
76ec6a |
/* When a user uses a dark theme, the hard-coded
|
|
Packit |
76ec6a |
* white background in GSM is a lone white on the
|
|
Packit |
76ec6a |
* display, which makes the user unhappy. To fix
|
|
Packit |
76ec6a |
* this, here we offer the user a chance to set
|
|
Packit |
76ec6a |
* his favorite background color. */
|
|
Packit |
76ec6a |
gtk_style_context_save (context);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Here we specify the name of the class. Now in
|
|
Packit |
76ec6a |
* the theme's CSS we can specify the own colors
|
|
Packit |
76ec6a |
* for this class. */
|
|
Packit |
76ec6a |
gtk_style_context_add_class (context, "loadgraph");
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* And in case the user does not care, we add
|
|
Packit |
76ec6a |
* classes that usually have a white background. */
|
|
Packit |
76ec6a |
gtk_style_context_add_class (context, GTK_STYLE_CLASS_PAPER);
|
|
Packit |
76ec6a |
gtk_style_context_add_class (context, GTK_STYLE_CLASS_ENTRY);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* And, as a bonus, the user can choose the color of the grid. */
|
|
Packit |
76ec6a |
gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &fg_grid);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Why not use the new features of the
|
|
Packit |
76ec6a |
* GTK instead of cairo_rectangle ?! :) */
|
|
Packit |
76ec6a |
gtk_render_background (context, cr, graph->indent, 0.0,
|
|
Packit |
76ec6a |
graph->draw_width - graph->rmargin - graph->indent,
|
|
Packit |
76ec6a |
graph->real_draw_height);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_style_context_restore (context);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
cairo_set_line_width (cr, 1.0);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (i = 0; i <= num_bars; ++i) {
|
|
Packit |
76ec6a |
double y;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (i == 0)
|
|
Packit |
76ec6a |
y = 0.5 + graph->fontsize / 2.0;
|
|
Packit |
76ec6a |
else if (i == num_bars)
|
|
Packit |
76ec6a |
y = i * graph->graph_dely + 0.5;
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
y = i * graph->graph_dely + graph->fontsize / 2.0;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gdk_cairo_set_source_rgba (cr, &fg;;
|
|
Packit |
76ec6a |
if (graph->type == LOAD_GRAPH_NET) {
|
|
Packit |
76ec6a |
// operation orders matters so it's 0 if i == num_bars
|
|
Packit |
76ec6a |
guint64 rate = graph->net.max - (i * graph->net.max / num_bars);
|
|
Packit |
76ec6a |
const std::string captionstr(procman::format_network_rate(rate));
|
|
Packit |
76ec6a |
caption = g_strdup(captionstr.c_str());
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
// operation orders matters so it's 0 if i == num_bars
|
|
Packit |
76ec6a |
caption = g_strdup_printf("%d %%", 100 - i * (100 / num_bars));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
|
|
Packit |
76ec6a |
pango_layout_set_text (layout, caption, -1);
|
|
Packit |
76ec6a |
pango_layout_get_extents (layout, NULL, &extents);
|
|
Packit |
76ec6a |
cairo_move_to (cr, graph->draw_width - graph->indent - 23,
|
|
Packit |
76ec6a |
y - 1.0 * extents.height / PANGO_SCALE / 2);
|
|
Packit |
76ec6a |
pango_cairo_show_layout (cr, layout);
|
|
Packit |
76ec6a |
g_free(caption);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (i==0 || i==num_bars)
|
|
Packit |
76ec6a |
fg_grid.alpha = border_alpha;
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
fg_grid.alpha = grid_alpha;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gdk_cairo_set_source_rgba (cr, &fg_grid);
|
|
Packit |
76ec6a |
cairo_move_to (cr, graph->indent, i * graph->graph_dely + 0.5);
|
|
Packit |
76ec6a |
cairo_line_to (cr, graph->draw_width - graph->rmargin + 0.5 + 4, i * graph->graph_dely + 0.5);
|
|
Packit |
76ec6a |
cairo_stroke (cr);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
const unsigned total_seconds = graph->speed * (LoadGraph::NUM_POINTS - 2) / 1000;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (unsigned int i = 0; i < 7; i++) {
|
|
Packit |
76ec6a |
double x = (i) * (graph->draw_width - graph->rmargin - graph->indent) / 6;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (i==0 || i==6)
|
|
Packit |
76ec6a |
fg_grid.alpha = border_alpha;
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
fg_grid.alpha = grid_alpha;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gdk_cairo_set_source_rgba (cr, &fg_grid);
|
|
Packit |
76ec6a |
cairo_move_to (cr, (ceil(x) + 0.5) + graph->indent, 0.5);
|
|
Packit |
76ec6a |
cairo_line_to (cr, (ceil(x) + 0.5) + graph->indent, graph->real_draw_height + 4.5);
|
|
Packit |
76ec6a |
cairo_stroke(cr);
|
|
Packit |
76ec6a |
unsigned seconds = total_seconds - i * total_seconds / 6;
|
|
Packit |
76ec6a |
const char* format;
|
|
Packit |
76ec6a |
if (i == 0)
|
|
Packit |
76ec6a |
format = dngettext(GETTEXT_PACKAGE, "%u second", "%u seconds", seconds);
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
format = "%u";
|
|
Packit |
76ec6a |
caption = g_strdup_printf(format, seconds);
|
|
Packit |
76ec6a |
pango_layout_set_text (layout, caption, -1);
|
|
Packit |
76ec6a |
pango_layout_get_extents (layout, NULL, &extents);
|
|
Packit |
76ec6a |
cairo_move_to (cr,
|
|
Packit |
76ec6a |
(ceil(x) + 0.5 + graph->indent) - (1.0 * extents.width / PANGO_SCALE / 2),
|
|
Packit |
76ec6a |
graph->draw_height - 1.0 * extents.height / PANGO_SCALE);
|
|
Packit |
76ec6a |
gdk_cairo_set_source_rgba (cr, &fg;;
|
|
Packit |
76ec6a |
pango_cairo_show_layout (cr, layout);
|
|
Packit |
76ec6a |
g_free (caption);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
g_object_unref(layout);
|
|
Packit |
76ec6a |
cairo_stroke (cr);
|
|
Packit |
76ec6a |
cairo_destroy (cr);
|
|
Packit |
76ec6a |
graph->background = surface;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Redraws the backing buffer for the load graph and updates the window */
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
load_graph_queue_draw (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
/* repaint */
|
|
Packit |
76ec6a |
gtk_widget_queue_draw (GTK_WIDGET (graph->disp));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static int load_graph_update (gpointer user_data); // predeclare load_graph_update so we can compile ;)
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static gboolean
|
|
Packit |
76ec6a |
load_graph_configure (GtkWidget *widget,
|
|
Packit |
76ec6a |
GdkEventConfigure *event,
|
|
Packit |
76ec6a |
gpointer data_ptr)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
GtkAllocation allocation;
|
|
Packit |
76ec6a |
LoadGraph * const graph = static_cast<LoadGraph*>(data_ptr);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_get_allocation (widget, &allocation);
|
|
Packit |
76ec6a |
graph->draw_width = allocation.width - 2 * FRAME_WIDTH;
|
|
Packit |
76ec6a |
graph->draw_height = allocation.height - 2 * FRAME_WIDTH;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->clear_background();
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
load_graph_queue_draw (graph);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return TRUE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void force_refresh (LoadGraph * const graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
graph->clear_background();
|
|
Packit |
76ec6a |
load_graph_queue_draw (graph);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
load_graph_style_updated (GtkWidget *widget,
|
|
Packit |
76ec6a |
gpointer data_ptr)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
LoadGraph * const graph = static_cast<LoadGraph*>(data_ptr);
|
|
Packit |
76ec6a |
force_refresh (graph);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static gboolean
|
|
Packit |
76ec6a |
load_graph_state_changed (GtkWidget *widget,
|
|
Packit |
76ec6a |
GtkStateFlags *flags,
|
|
Packit |
76ec6a |
gpointer data_ptr)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
LoadGraph * const graph = static_cast<LoadGraph*>(data_ptr);
|
|
Packit |
76ec6a |
force_refresh (graph);
|
|
Packit |
76ec6a |
return TRUE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static gboolean
|
|
Packit |
76ec6a |
load_graph_draw (GtkWidget *widget,
|
|
Packit |
76ec6a |
cairo_t * cr,
|
|
Packit |
76ec6a |
gpointer data_ptr)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
LoadGraph * const graph = static_cast<LoadGraph*>(data_ptr);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
guint i;
|
|
Packit |
76ec6a |
gint j;
|
|
Packit |
76ec6a |
gdouble sample_width, x_offset;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Number of pixels wide for one graph point */
|
|
Packit |
76ec6a |
sample_width = (float)(graph->draw_width - graph->rmargin - graph->indent) / (float)LoadGraph::NUM_POINTS;
|
|
Packit |
76ec6a |
/* General offset */
|
|
Packit |
76ec6a |
x_offset = graph->draw_width - graph->rmargin;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Subframe offset */
|
|
Packit |
76ec6a |
x_offset += graph->rmargin - ((sample_width / graph->frames_per_unit) * graph->render_counter);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* draw the graph */
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (graph->background == NULL) {
|
|
Packit |
76ec6a |
draw_background(graph);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
cairo_set_source_surface (cr, graph->background, 0, 0);
|
|
Packit |
76ec6a |
cairo_paint (cr);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
cairo_set_line_width (cr, 1);
|
|
Packit |
76ec6a |
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
|
Packit |
76ec6a |
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
|
Packit |
76ec6a |
cairo_rectangle (cr, graph->indent + FRAME_WIDTH + 1, FRAME_WIDTH - 1,
|
|
Packit |
76ec6a |
graph->draw_width - graph->rmargin - graph->indent - 1,
|
|
Packit |
76ec6a |
graph->real_draw_height + FRAME_WIDTH - 1);
|
|
Packit |
76ec6a |
cairo_clip(cr);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
bool drawStacked = graph->type == LOAD_GRAPH_CPU && GsmApplication::get()->config.draw_stacked;
|
|
Packit |
76ec6a |
bool drawSmooth = graph->type != LOAD_GRAPH_CPU || GsmApplication::get()->config.draw_smooth;
|
|
Packit |
76ec6a |
for (j = graph->n-1; j >= 0; j--) {
|
|
Packit |
76ec6a |
gdk_cairo_set_source_rgba (cr, &(graph->colors [j]));
|
|
Packit |
76ec6a |
if (drawStacked) {
|
|
Packit |
76ec6a |
cairo_move_to (cr, x_offset, graph->real_draw_height + 3.5f);
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
cairo_move_to (cr, x_offset, (1.0f - graph->data[0][j]) * graph->real_draw_height + 3.5f);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
for (i = 1; i < LoadGraph::NUM_POINTS; ++i) {
|
|
Packit |
76ec6a |
if (graph->data[i][j] == -1.0f)
|
|
Packit |
76ec6a |
continue;
|
|
Packit |
76ec6a |
if (drawSmooth) {
|
|
Packit |
76ec6a |
cairo_curve_to (cr,
|
|
Packit |
76ec6a |
x_offset - ((i - 0.5f) * graph->graph_delx),
|
|
Packit |
76ec6a |
(1.0 - graph->data[i-1][j]) * graph->real_draw_height + 3.5,
|
|
Packit |
76ec6a |
x_offset - ((i - 0.5f) * graph->graph_delx),
|
|
Packit |
76ec6a |
(1.0 - graph->data[i][j]) * graph->real_draw_height + 3.5,
|
|
Packit |
76ec6a |
x_offset - (i * graph->graph_delx),
|
|
Packit |
76ec6a |
(1.0 - graph->data[i][j]) * graph->real_draw_height + 3.5);
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
cairo_line_to (cr, x_offset - (i * graph->graph_delx),
|
|
Packit |
76ec6a |
(1.0 - graph->data[i][j]) * graph->real_draw_height + 3.5);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
if (drawStacked) {
|
|
Packit |
76ec6a |
cairo_rel_line_to (cr, 0, graph->real_draw_height + 3.5f);
|
|
Packit |
76ec6a |
//cairo_stroke_preserve(cr);
|
|
Packit |
76ec6a |
//cairo_close_path(cr);
|
|
Packit |
76ec6a |
cairo_fill(cr);
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
cairo_stroke (cr);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return TRUE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
load_graph_reset (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
std::fill(graph->data_block.begin(), graph->data_block.end(), -1.0);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
get_load (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
guint i;
|
|
Packit |
76ec6a |
glibtop_cpu cpu;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
glibtop_get_cpu (&cpu);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#undef NOW
|
|
Packit |
76ec6a |
#undef LAST
|
|
Packit |
76ec6a |
#define NOW (graph->cpu.times[graph->cpu.now])
|
|
Packit |
76ec6a |
#define LAST (graph->cpu.times[graph->cpu.now ^ 1])
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (graph->n == 1) {
|
|
Packit |
76ec6a |
NOW[0][CPU_TOTAL] = cpu.total;
|
|
Packit |
76ec6a |
NOW[0][CPU_USED] = cpu.user + cpu.nice + cpu.sys;
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
for (i = 0; i < graph->n; i++) {
|
|
Packit |
76ec6a |
NOW[i][CPU_TOTAL] = cpu.xcpu_total[i];
|
|
Packit |
76ec6a |
NOW[i][CPU_USED] = cpu.xcpu_user[i] + cpu.xcpu_nice[i]
|
|
Packit |
76ec6a |
+ cpu.xcpu_sys[i];
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// on the first call, LAST is 0
|
|
Packit |
76ec6a |
// which means data is set to the average load since boot
|
|
Packit |
76ec6a |
// that value has no meaning, we just want all the
|
|
Packit |
76ec6a |
// graphs to be aligned, so the CPU graph needs to start
|
|
Packit |
76ec6a |
// immediately
|
|
Packit |
76ec6a |
bool drawStacked = graph->type == LOAD_GRAPH_CPU && GsmApplication::get()->config.draw_stacked;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (i = 0; i < graph->n; i++) {
|
|
Packit |
76ec6a |
float load;
|
|
Packit |
76ec6a |
float total, used;
|
|
Packit |
76ec6a |
gchar *text;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
total = NOW[i][CPU_TOTAL] - LAST[i][CPU_TOTAL];
|
|
Packit |
76ec6a |
used = NOW[i][CPU_USED] - LAST[i][CPU_USED];
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
load = used / MAX(total, 1.0f);
|
|
Packit |
76ec6a |
graph->data[0][i] = load;
|
|
Packit |
76ec6a |
if (drawStacked) {
|
|
Packit |
76ec6a |
graph->data[0][i] /= graph->n;
|
|
Packit |
76ec6a |
if (i > 0) {
|
|
Packit |
76ec6a |
graph->data[0][i] += graph->data[0][i-1];
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Update label */
|
|
Packit |
76ec6a |
text = g_strdup_printf("%.1f%%", load * 100.0f);
|
|
Packit |
76ec6a |
gtk_label_set_text(GTK_LABEL(graph->labels.cpu[i]), text);
|
|
Packit |
76ec6a |
g_free(text);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->cpu.now ^= 1;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#undef NOW
|
|
Packit |
76ec6a |
#undef LAST
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
namespace
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void set_memory_label_and_picker(GtkLabel* label, GsmColorButton* picker,
|
|
Packit |
76ec6a |
guint64 used, guint64 total, double percent)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
char* used_text;
|
|
Packit |
76ec6a |
char* total_text;
|
|
Packit |
76ec6a |
char* text;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
used_text = g_format_size_full(used, G_FORMAT_SIZE_IEC_UNITS);
|
|
Packit |
76ec6a |
total_text = g_format_size_full(total, G_FORMAT_SIZE_IEC_UNITS);
|
|
Packit |
76ec6a |
if (total == 0) {
|
|
Packit |
76ec6a |
text = g_strdup(_("not available"));
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
// xgettext: 540MiB (53 %) of 1.0 GiB
|
|
Packit |
76ec6a |
text = g_strdup_printf(_("%s (%.1f%%) of %s"), used_text, 100.0 * percent, total_text);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
gtk_label_set_text(label, text);
|
|
Packit |
76ec6a |
g_free(used_text);
|
|
Packit |
76ec6a |
g_free(total_text);
|
|
Packit |
76ec6a |
g_free(text);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (picker)
|
|
Packit |
76ec6a |
gsm_color_button_set_fraction(picker, percent);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
get_memory (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
float mempercent, swappercent;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
glibtop_mem mem;
|
|
Packit |
76ec6a |
glibtop_swap swap;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
glibtop_get_mem (&mem;;
|
|
Packit |
76ec6a |
glibtop_get_swap (&swap;;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* There's no swap on LiveCD : 0.0f is better than NaN :) */
|
|
Packit |
76ec6a |
swappercent = (swap.total ? (float)swap.used / (float)swap.total : 0.0f);
|
|
Packit |
76ec6a |
mempercent = (float)mem.user / (float)mem.total;
|
|
Packit |
76ec6a |
set_memory_label_and_picker(GTK_LABEL(graph->labels.memory),
|
|
Packit |
76ec6a |
GSM_COLOR_BUTTON(graph->mem_color_picker),
|
|
Packit |
76ec6a |
mem.user, mem.total, mempercent);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
set_memory_label_and_picker(GTK_LABEL(graph->labels.swap),
|
|
Packit |
76ec6a |
GSM_COLOR_BUTTON(graph->swap_color_picker),
|
|
Packit |
76ec6a |
swap.used, swap.total, swappercent);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_set_sensitive (GTK_WIDGET (graph->swap_color_picker), swap.total > 0);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->data[0][0] = mempercent;
|
|
Packit |
76ec6a |
graph->data[0][1] = swap.total>0 ? swappercent : -1.0;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Nice Numbers for Graph Labels after Paul Heckbert
|
|
Packit |
76ec6a |
nicenum: find a "nice" number approximately equal to x.
|
|
Packit |
76ec6a |
Round the number if round=1, take ceiling if round=0 */
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static double
|
|
Packit |
76ec6a |
nicenum (double x, int round)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
int expv; /* exponent of x */
|
|
Packit |
76ec6a |
double f; /* fractional part of x */
|
|
Packit |
76ec6a |
double nf; /* nice, rounded fraction */
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
expv = floor(log10(x));
|
|
Packit |
76ec6a |
f = x/pow(10.0, expv); /* between 1 and 10 */
|
|
Packit |
76ec6a |
if (round) {
|
|
Packit |
76ec6a |
if (f < 1.5)
|
|
Packit |
76ec6a |
nf = 1.0;
|
|
Packit |
76ec6a |
else if (f < 3.0)
|
|
Packit |
76ec6a |
nf = 2.0;
|
|
Packit |
76ec6a |
else if (f < 7.0)
|
|
Packit |
76ec6a |
nf = 5.0;
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
nf = 10.0;
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
if (f <= 1.0)
|
|
Packit |
76ec6a |
nf = 1.0;
|
|
Packit |
76ec6a |
else if (f <= 2.0)
|
|
Packit |
76ec6a |
nf = 2.0;
|
|
Packit |
76ec6a |
else if (f <= 5.0)
|
|
Packit |
76ec6a |
nf = 5.0;
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
nf = 10.0;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
return nf * pow(10.0, expv);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
net_scale (LoadGraph *graph, guint64 din, guint64 dout)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
graph->data[0][0] = 1.0f * din / graph->net.max;
|
|
Packit |
76ec6a |
graph->data[0][1] = 1.0f * dout / graph->net.max;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
guint64 dmax = std::max(din, dout);
|
|
Packit |
76ec6a |
graph->net.values[graph->net.cur] = dmax;
|
|
Packit |
76ec6a |
graph->net.cur = (graph->net.cur + 1) % LoadGraph::NUM_POINTS;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
guint64 new_max;
|
|
Packit |
76ec6a |
// both way, new_max is the greatest value
|
|
Packit |
76ec6a |
if (dmax >= graph->net.max)
|
|
Packit |
76ec6a |
new_max = dmax;
|
|
Packit |
76ec6a |
else
|
|
Packit |
76ec6a |
new_max = *std::max_element(&graph->net.values[0],
|
|
Packit |
76ec6a |
&graph->net.values[LoadGraph::NUM_POINTS]);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
//
|
|
Packit |
76ec6a |
// Round network maximum
|
|
Packit |
76ec6a |
//
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
const guint64 bak_max(new_max);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (GsmApplication::get()->config.network_in_bits) {
|
|
Packit |
76ec6a |
// nice number is for the ticks
|
|
Packit |
76ec6a |
unsigned ticks = graph->num_bars();
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// gets messy at low values due to division by 8
|
|
Packit |
76ec6a |
guint64 bit_max = std::max( new_max*8, G_GUINT64_CONSTANT(10000) );
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// our tick size leads to max
|
|
Packit |
76ec6a |
double d = nicenum(bit_max/ticks, 0);
|
|
Packit |
76ec6a |
bit_max = ticks * d;
|
|
Packit |
76ec6a |
new_max = bit_max / 8;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
procman_debug("bak*8 %" G_GUINT64_FORMAT ", ticks %d, d %f"
|
|
Packit |
76ec6a |
", bit_max %" G_GUINT64_FORMAT ", new_max %" G_GUINT64_FORMAT,
|
|
Packit |
76ec6a |
bak_max*8, ticks, d, bit_max, new_max );
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
// round up to get some extra space
|
|
Packit |
76ec6a |
// yes, it can overflow
|
|
Packit |
76ec6a |
new_max = 1.1 * new_max;
|
|
Packit |
76ec6a |
// make sure max is not 0 to avoid / 0
|
|
Packit |
76ec6a |
// default to 1 KiB
|
|
Packit |
76ec6a |
new_max = std::max(new_max, G_GUINT64_CONSTANT(1024));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// decompose new_max = coef10 * 2**(base10 * 10)
|
|
Packit |
76ec6a |
// where coef10 and base10 are integers and coef10 < 2**10
|
|
Packit |
76ec6a |
//
|
|
Packit |
76ec6a |
// e.g: ceil(100.5 KiB) = 101 KiB = 101 * 2**(1 * 10)
|
|
Packit |
76ec6a |
// where base10 = 1, coef10 = 101, pow2 = 16
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
guint64 pow2 = std::floor(log2(new_max));
|
|
Packit |
76ec6a |
guint64 base10 = pow2 / 10.0;
|
|
Packit |
76ec6a |
guint64 coef10 = std::ceil(new_max / double(G_GUINT64_CONSTANT(1) << (base10 * 10)));
|
|
Packit |
76ec6a |
g_assert(new_max <= (coef10 * (G_GUINT64_CONSTANT(1) << (base10 * 10))));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// then decompose coef10 = x * 10**factor10
|
|
Packit |
76ec6a |
// where factor10 is integer and x < 10
|
|
Packit |
76ec6a |
// so we new_max has only 1 significant digit
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
guint64 factor10 = std::pow(10.0, std::floor(std::log10(coef10)));
|
|
Packit |
76ec6a |
coef10 = std::ceil(coef10 / double(factor10)) * factor10;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
new_max = coef10 * (G_GUINT64_CONSTANT(1) << guint64(base10 * 10));
|
|
Packit |
76ec6a |
procman_debug("bak %" G_GUINT64_FORMAT " new_max %" G_GUINT64_FORMAT
|
|
Packit |
76ec6a |
"pow2 %" G_GUINT64_FORMAT " coef10 %" G_GUINT64_FORMAT,
|
|
Packit |
76ec6a |
bak_max, new_max, pow2, coef10);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (bak_max > new_max) {
|
|
Packit |
76ec6a |
procman_debug("overflow detected: bak=%" G_GUINT64_FORMAT
|
|
Packit |
76ec6a |
" new=%" G_GUINT64_FORMAT,
|
|
Packit |
76ec6a |
bak_max, new_max);
|
|
Packit |
76ec6a |
new_max = bak_max;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// if max is the same or has decreased but not so much, don't
|
|
Packit |
76ec6a |
// do anything to avoid rescaling
|
|
Packit |
76ec6a |
if ((0.8 * graph->net.max) < new_max && new_max <= graph->net.max)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
const double scale = 1.0f * graph->net.max / new_max;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (size_t i = 0; i < LoadGraph::NUM_POINTS; i++) {
|
|
Packit |
76ec6a |
if (graph->data[i][0] >= 0.0f) {
|
|
Packit |
76ec6a |
graph->data[i][0] *= scale;
|
|
Packit |
76ec6a |
graph->data[i][1] *= scale;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
procman_debug("rescale dmax = %" G_GUINT64_FORMAT
|
|
Packit |
76ec6a |
" max = %" G_GUINT64_FORMAT
|
|
Packit |
76ec6a |
" new_max = %" G_GUINT64_FORMAT,
|
|
Packit |
76ec6a |
dmax, graph->net.max, new_max);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->net.max = new_max;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// force the graph background to be redrawn now that scale has changed
|
|
Packit |
76ec6a |
graph->clear_background();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static void
|
|
Packit |
76ec6a |
get_net (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
glibtop_netlist netlist;
|
|
Packit |
76ec6a |
char **ifnames;
|
|
Packit |
76ec6a |
guint32 i;
|
|
Packit |
76ec6a |
guint64 in = 0, out = 0;
|
|
Packit |
76ec6a |
GTimeVal time;
|
|
Packit |
76ec6a |
guint64 din, dout;
|
|
Packit |
76ec6a |
gboolean first = true;
|
|
Packit |
76ec6a |
ifnames = glibtop_get_netlist(&netlist);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (i = 0; i < netlist.number; ++i)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
glibtop_netload netload;
|
|
Packit |
76ec6a |
glibtop_get_netload (&netload, ifnames[i]);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK))
|
|
Packit |
76ec6a |
continue;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Skip interfaces without any IPv4/IPv6 address (or
|
|
Packit |
76ec6a |
those with only a LINK ipv6 addr) However we need to
|
|
Packit |
76ec6a |
be able to exclude these while still keeping the
|
|
Packit |
76ec6a |
value so when they get online (with NetworkManager
|
|
Packit |
76ec6a |
for example) we don't get a suddent peak. Once we're
|
|
Packit |
76ec6a |
able to get this, ignoring down interfaces will be
|
|
Packit |
76ec6a |
possible too. */
|
|
Packit |
76ec6a |
if (not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6)
|
|
Packit |
76ec6a |
and netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK)
|
|
Packit |
76ec6a |
and not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS)))
|
|
Packit |
76ec6a |
continue;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Don't skip interfaces that are down (GLIBTOP_IF_FLAGS_UP)
|
|
Packit |
76ec6a |
to avoid spikes when they are brought up */
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
in += netload.bytes_in;
|
|
Packit |
76ec6a |
out += netload.bytes_out;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_strfreev(ifnames);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_get_current_time (&time);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (in >= graph->net.last_in && out >= graph->net.last_out && graph->net.time.tv_sec != 0) {
|
|
Packit |
76ec6a |
float dtime;
|
|
Packit |
76ec6a |
dtime = time.tv_sec - graph->net.time.tv_sec +
|
|
Packit |
76ec6a |
(double) (time.tv_usec - graph->net.time.tv_usec) / G_USEC_PER_SEC;
|
|
Packit |
76ec6a |
din = static_cast<guint64>((in - graph->net.last_in) / dtime);
|
|
Packit |
76ec6a |
dout = static_cast<guint64>((out - graph->net.last_out) / dtime);
|
|
Packit |
76ec6a |
} else {
|
|
Packit |
76ec6a |
/* Don't calc anything if new data is less than old (interface
|
|
Packit |
76ec6a |
removed, counters reset, ...) or if it is the first time */
|
|
Packit |
76ec6a |
din = 0;
|
|
Packit |
76ec6a |
dout = 0;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
first = first && (graph->net.time.tv_sec==0);
|
|
Packit |
76ec6a |
graph->net.last_in = in;
|
|
Packit |
76ec6a |
graph->net.last_out = out;
|
|
Packit |
76ec6a |
graph->net.time = time;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (!first)
|
|
Packit |
76ec6a |
net_scale(graph, din, dout);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_label_set_text (GTK_LABEL (graph->labels.net_in), procman::format_network_rate(din).c_str());
|
|
Packit |
76ec6a |
gtk_label_set_text (GTK_LABEL (graph->labels.net_in_total), procman::format_network(in).c_str());
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_label_set_text (GTK_LABEL (graph->labels.net_out), procman::format_network_rate(dout).c_str());
|
|
Packit |
76ec6a |
gtk_label_set_text (GTK_LABEL (graph->labels.net_out_total), procman::format_network(out).c_str());
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Updates the load graph when the timeout expires */
|
|
Packit |
76ec6a |
static gboolean
|
|
Packit |
76ec6a |
load_graph_update (gpointer user_data)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
LoadGraph * const graph = static_cast<LoadGraph*>(user_data);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (graph->render_counter == graph->frames_per_unit - 1) {
|
|
Packit |
76ec6a |
std::rotate(&graph->data[0],
|
|
Packit |
76ec6a |
&graph->data[LoadGraph::NUM_POINTS - 1],
|
|
Packit |
76ec6a |
&graph->data[LoadGraph::NUM_POINTS]);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
switch (graph->type) {
|
|
Packit |
76ec6a |
case LOAD_GRAPH_CPU:
|
|
Packit |
76ec6a |
get_load(graph);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case LOAD_GRAPH_MEM:
|
|
Packit |
76ec6a |
get_memory(graph);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case LOAD_GRAPH_NET:
|
|
Packit |
76ec6a |
get_net(graph);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
default:
|
|
Packit |
76ec6a |
g_assert_not_reached();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (graph->draw)
|
|
Packit |
76ec6a |
load_graph_queue_draw (graph);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->render_counter++;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (graph->render_counter >= graph->frames_per_unit)
|
|
Packit |
76ec6a |
graph->render_counter = 0;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return TRUE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
LoadGraph::~LoadGraph()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
load_graph_stop(this);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (timer_index)
|
|
Packit |
76ec6a |
g_source_remove(timer_index);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
clear_background();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static gboolean
|
|
Packit |
76ec6a |
load_graph_destroy (GtkWidget *widget, gpointer data_ptr)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
LoadGraph * const graph = static_cast<LoadGraph*>(data_ptr);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
delete graph;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return FALSE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
LoadGraph::LoadGraph(guint type)
|
|
Packit |
76ec6a |
: fontsize(8.0),
|
|
Packit |
76ec6a |
rmargin(7 * fontsize),
|
|
Packit |
76ec6a |
indent(24.0),
|
|
Packit |
76ec6a |
n(0),
|
|
Packit |
76ec6a |
type(type),
|
|
Packit |
76ec6a |
speed(0),
|
|
Packit |
76ec6a |
draw_width(0),
|
|
Packit |
76ec6a |
draw_height(0),
|
|
Packit |
76ec6a |
render_counter(0),
|
|
Packit |
76ec6a |
frames_per_unit(10), // this will be changed but needs initialising
|
|
Packit |
76ec6a |
graph_dely(0),
|
|
Packit |
76ec6a |
real_draw_height(0),
|
|
Packit |
76ec6a |
graph_delx(0.0),
|
|
Packit |
76ec6a |
graph_buffer_offset(0),
|
|
Packit |
76ec6a |
colors(),
|
|
Packit |
76ec6a |
data_block(),
|
|
Packit |
76ec6a |
main_widget(NULL),
|
|
Packit |
76ec6a |
disp(NULL),
|
|
Packit |
76ec6a |
background(NULL),
|
|
Packit |
76ec6a |
timer_index(0),
|
|
Packit |
76ec6a |
draw(FALSE),
|
|
Packit |
76ec6a |
labels(),
|
|
Packit |
76ec6a |
mem_color_picker(NULL),
|
|
Packit |
76ec6a |
swap_color_picker(NULL),
|
|
Packit |
76ec6a |
cpu(),
|
|
Packit |
76ec6a |
net()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
LoadGraph * const graph = this;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// FIXME:
|
|
Packit |
76ec6a |
// on configure, graph->frames_per_unit = graph->draw_width/(LoadGraph::NUM_POINTS);
|
|
Packit |
76ec6a |
// knock FRAMES down to 5 until cairo gets faster
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
switch (type) {
|
|
Packit |
76ec6a |
case LOAD_GRAPH_CPU:
|
|
Packit |
76ec6a |
memset(&cpu, 0, sizeof cpu);
|
|
Packit |
76ec6a |
n = GsmApplication::get()->config.num_cpus;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for(guint i = 0; i < G_N_ELEMENTS(labels.cpu); ++i)
|
|
Packit |
76ec6a |
labels.cpu[i] = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
case LOAD_GRAPH_MEM:
|
|
Packit |
76ec6a |
n = 2;
|
|
Packit |
76ec6a |
labels.memory = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
gtk_widget_set_valign (GTK_WIDGET (labels.memory), GTK_ALIGN_CENTER);
|
|
Packit |
76ec6a |
gtk_widget_set_halign (GTK_WIDGET (labels.memory), GTK_ALIGN_START);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (labels.memory));
|
|
Packit |
76ec6a |
labels.swap = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
gtk_widget_set_valign (GTK_WIDGET (labels.swap), GTK_ALIGN_CENTER);
|
|
Packit |
76ec6a |
gtk_widget_set_halign (GTK_WIDGET (labels.swap), GTK_ALIGN_START);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (labels.swap));
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
case LOAD_GRAPH_NET:
|
|
Packit |
76ec6a |
memset(&net, 0, sizeof net);
|
|
Packit |
76ec6a |
n = 2;
|
|
Packit |
76ec6a |
net.max = 1;
|
|
Packit |
76ec6a |
labels.net_in = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
gtk_label_set_width_chars(labels.net_in, 10);
|
|
Packit |
76ec6a |
gtk_widget_set_valign (GTK_WIDGET (labels.net_in), GTK_ALIGN_CENTER);
|
|
Packit |
76ec6a |
gtk_widget_set_halign (GTK_WIDGET (labels.net_in), GTK_ALIGN_END);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (labels.net_in));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
labels.net_in_total = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
gtk_widget_set_valign (GTK_WIDGET (labels.net_in_total), GTK_ALIGN_CENTER);
|
|
Packit |
76ec6a |
gtk_widget_set_halign (GTK_WIDGET (labels.net_in_total), GTK_ALIGN_END);
|
|
Packit |
76ec6a |
gtk_label_set_width_chars(labels.net_in_total, 10);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (labels.net_in_total));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
labels.net_out = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
gtk_widget_set_valign (GTK_WIDGET (labels.net_out), GTK_ALIGN_CENTER);
|
|
Packit |
76ec6a |
gtk_widget_set_halign (GTK_WIDGET (labels.net_out), GTK_ALIGN_END);
|
|
Packit |
76ec6a |
gtk_label_set_width_chars(labels.net_out, 10);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (labels.net_out));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
labels.net_out_total = GTK_LABEL (gtk_label_new(NULL));
|
|
Packit |
76ec6a |
gtk_widget_set_valign (GTK_WIDGET (labels.net_out_total), GTK_ALIGN_CENTER);
|
|
Packit |
76ec6a |
gtk_widget_set_halign (GTK_WIDGET (labels.net_out), GTK_ALIGN_END);
|
|
Packit |
76ec6a |
gtk_label_set_width_chars(labels.net_out_total, 10);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (labels.net_out_total));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
speed = GsmApplication::get()->config.graph_update_interval;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
colors.resize(n);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
switch (type) {
|
|
Packit |
76ec6a |
case LOAD_GRAPH_CPU:
|
|
Packit |
76ec6a |
memcpy(&colors[0], GsmApplication::get()->config.cpu_color,
|
|
Packit |
76ec6a |
n * sizeof colors[0]);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case LOAD_GRAPH_MEM:
|
|
Packit |
76ec6a |
colors[0] = GsmApplication::get()->config.mem_color;
|
|
Packit |
76ec6a |
colors[1] = GsmApplication::get()->config.swap_color;
|
|
Packit |
76ec6a |
mem_color_picker = gsm_color_button_new (&colors[0],
|
|
Packit |
76ec6a |
GSMCP_TYPE_PIE);
|
|
Packit |
76ec6a |
swap_color_picker = gsm_color_button_new (&colors[1],
|
|
Packit |
76ec6a |
GSMCP_TYPE_PIE);
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
case LOAD_GRAPH_NET:
|
|
Packit |
76ec6a |
colors[0] = GsmApplication::get()->config.net_in_color;
|
|
Packit |
76ec6a |
colors[1] = GsmApplication::get()->config.net_out_color;
|
|
Packit |
76ec6a |
break;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
timer_index = 0;
|
|
Packit |
76ec6a |
render_counter = (frames_per_unit - 1);
|
|
Packit |
76ec6a |
draw = FALSE;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
main_widget = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, 6));
|
|
Packit |
76ec6a |
gtk_widget_set_size_request(GTK_WIDGET (main_widget), -1, LoadGraph::GRAPH_MIN_HEIGHT);
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (main_widget));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
disp = GTK_DRAWING_AREA (gtk_drawing_area_new ());
|
|
Packit |
76ec6a |
gtk_widget_show (GTK_WIDGET (disp));
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT (disp), "draw",
|
|
Packit |
76ec6a |
G_CALLBACK (load_graph_draw), graph);
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT(disp), "configure_event",
|
|
Packit |
76ec6a |
G_CALLBACK (load_graph_configure), graph);
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT(disp), "destroy",
|
|
Packit |
76ec6a |
G_CALLBACK (load_graph_destroy), graph);
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT(disp), "state-flags-changed",
|
|
Packit |
76ec6a |
G_CALLBACK (load_graph_state_changed), graph);
|
|
Packit |
76ec6a |
g_signal_connect (G_OBJECT(disp), "style-updated",
|
|
Packit |
76ec6a |
G_CALLBACK (load_graph_style_updated), graph);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_set_events (GTK_WIDGET (disp), GDK_EXPOSURE_MASK);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_box_pack_start (main_widget, GTK_WIDGET (disp), TRUE, TRUE, 0);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/* Allocate data in a contiguous block */
|
|
Packit |
76ec6a |
data_block = std::vector<double>(n * LoadGraph::NUM_POINTS, -1.0);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (guint i = 0; i < LoadGraph::NUM_POINTS; ++i)
|
|
Packit |
76ec6a |
data[i] = &data_block[0] + i * n;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
gtk_widget_show_all (GTK_WIDGET (main_widget));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
load_graph_start (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
if (!graph->timer_index) {
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
load_graph_update(graph);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->timer_index = g_timeout_add (graph->speed / graph->frames_per_unit,
|
|
Packit |
76ec6a |
load_graph_update,
|
|
Packit |
76ec6a |
graph);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->draw = TRUE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
load_graph_stop (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
/* don't draw anymore, but continue to poll */
|
|
Packit |
76ec6a |
graph->draw = FALSE;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
load_graph_change_speed (LoadGraph *graph,
|
|
Packit |
76ec6a |
guint new_speed)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
if (graph->speed == new_speed)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->speed = new_speed;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (graph->timer_index) {
|
|
Packit |
76ec6a |
g_source_remove (graph->timer_index);
|
|
Packit |
76ec6a |
graph->timer_index = g_timeout_add (graph->speed / graph->frames_per_unit,
|
|
Packit |
76ec6a |
load_graph_update,
|
|
Packit |
76ec6a |
graph);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
graph->clear_background();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
LoadGraphLabels*
|
|
Packit |
76ec6a |
load_graph_get_labels (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return &graph->labels;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
GtkBox*
|
|
Packit |
76ec6a |
load_graph_get_widget (LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return graph->main_widget;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
GsmColorButton*
|
|
Packit |
76ec6a |
load_graph_get_mem_color_picker(LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return graph->mem_color_picker;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
GsmColorButton*
|
|
Packit |
76ec6a |
load_graph_get_swap_color_picker(LoadGraph *graph)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return graph->swap_color_picker;
|
|
Packit |
76ec6a |
}
|