[gnome-system-monitor] Add data points config option



commit 753fb7a4a90734f37aef98b240d8732707985056
Author: ToMe25 <tome25 gmx de>
Date:   Wed Nov 4 17:37:32 2020 +0000

    Add data points config option
    
    This allows the user to set the number of data points shown in the
    resources view to anything between 30 and 600.

 data/preferences.ui                               |  50 +++++++-
 src/application.cpp                               |  14 +++
 src/application.h                                 |   2 +
 src/legacy/gsm_color_button.c                     |   1 +
 src/load-graph.cpp                                | 146 ++++++++++++++++++----
 src/load-graph.h                                  |  13 +-
 src/org.gnome.gnome-system-monitor.gschema.xml.in |   6 +
 src/prefsdialog.cpp                               |  40 +++++-
 src/settings-keys.h                               |   1 +
 9 files changed, 239 insertions(+), 34 deletions(-)
---
diff --git a/data/preferences.ui b/data/preferences.ui
index 6f4b7b0b..54c18df2 100644
--- a/data/preferences.ui
+++ b/data/preferences.ui
@@ -379,6 +379,50 @@
                                 <property name="height">1</property>
                               </packing>
                             </child>
+                            <child>
+                              <object class="GtkGrid" id="graph_data_points">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="hexpand">True</property>
+                                <property name="column_spacing">12</property>
+                                <child>
+                                  <object class="GtkLabel" id="graph_data_points_label">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">_Chart data points:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">graph_data_points_scale</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                    <property name="width">1</property>
+                                    <property name="height">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkScale" id="graph_data_points_scale">
+                                    <property name="orientation">horizontal</property>
+                                    <property name="visible">True</property>
+                                    <property name="draw-value">True</property>
+                                    <property name="value-pos">right</property>
+                                    <property name="digits">0</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="top_attach">0</property>
+                                    <property name="width">18</property>
+                                    <property name="height">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">1</property>
+                                <property name="width">1</property>
+                                <property name="height">1</property>
+                              </packing>
+                            </child>
                             <child>
                               <object class="GtkCheckButton" id="draw_stacked_button">
                                 <property name="label" translatable="yes">_Draw CPU chart as stacked area 
chart</property>
@@ -392,7 +436,7 @@
                               </object>
                               <packing>
                                 <property name="left_attach">0</property>
-                                <property name="top_attach">1</property>
+                                <property name="top_attach">2</property>
                                 <property name="width">1</property>
                                 <property name="height">1</property>
                               </packing>
@@ -410,7 +454,7 @@
                               </object>
                               <packing>
                                 <property name="left_attach">0</property>
-                                <property name="top_attach">2</property>
+                                <property name="top_attach">3</property>
                                 <property name="width">1</property>
                                 <property name="height">1</property>
                               </packing>
@@ -428,7 +472,7 @@
                               </object>
                               <packing>
                                 <property name="left_attach">0</property>
-                                <property name="top_attach">3</property>
+                                <property name="top_attach">4</property>
                                 <property name="width">1</property>
                                 <property name="height">1</property>
                               </packing>
diff --git a/src/application.cpp b/src/application.cpp
index b08305c7..9af91110 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -83,6 +83,15 @@ cb_timeouts_changed (Gio::Settings& settings, Glib::ustring key, GsmApplication*
     }
 }
 
+static void
+cb_data_points_changed(Gio::Settings& settings, Glib::ustring key, GsmApplication* app) {
+       app->config.graph_data_points = settings.get_int (key);
+       unsigned points = app->config.graph_data_points + 2;
+       load_graph_change_num_points(app->cpu_graph, points);
+       load_graph_change_num_points(app->mem_graph, points);
+       load_graph_change_num_points(app->net_graph, points);
+}
+
 static void
 apply_cpu_color_settings(Gio::Settings& settings, GsmApplication* app)
 {
@@ -189,6 +198,11 @@ GsmApplication::load_settings()
     config.disks_update_interval = this->settings->get_int (GSM_SETTING_DISKS_UPDATE_INTERVAL);
     this->settings->signal_changed (GSM_SETTING_DISKS_UPDATE_INTERVAL).connect (cbtc);
 
+    config.graph_data_points = this->settings->get_int (GSM_SETTING_GRAPH_DATA_POINTS);
+    this->settings->signal_changed (GSM_SETTING_GRAPH_DATA_POINTS).connect ([this](const Glib::ustring& key) 
{
+        cb_data_points_changed (*this->settings.operator->(), key, this);
+    });
+
     glibtop_get_cpu (&cpu);
     frequency = cpu.frequency;
 
diff --git a/src/application.h b/src/application.h
index 57385f6a..dbaf8d29 100644
--- a/src/application.h
+++ b/src/application.h
@@ -33,6 +33,7 @@ struct ProcConfig
       : update_interval(0),
        graph_update_interval(0),
        disks_update_interval(0),
+       graph_data_points(0),
        mem_color(),
        swap_color(),
        net_in_color(),
@@ -51,6 +52,7 @@ struct ProcConfig
     int             update_interval;
     int             graph_update_interval;
     int             disks_update_interval;
+    int             graph_data_points;
     GdkRGBA         cpu_color[GLIBTOP_NCPU];
     GdkRGBA         mem_color;
     GdkRGBA         swap_color;
diff --git a/src/legacy/gsm_color_button.c b/src/legacy/gsm_color_button.c
index e23e9b6e..81aebb7e 100644
--- a/src/legacy/gsm_color_button.c
+++ b/src/legacy/gsm_color_button.c
@@ -852,6 +852,7 @@ gsm_color_button_get_property (GObject * object,
       break;
     case PROP_TYPE:
       g_value_set_uint (value, gsm_color_button_get_cbtype (color_button));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
       break;
diff --git a/src/load-graph.cpp b/src/load-graph.cpp
index 6656746c..715be931 100644
--- a/src/load-graph.cpp
+++ b/src/load-graph.cpp
@@ -72,8 +72,8 @@ static void draw_background(LoadGraph *graph) {
     num_bars = graph->num_bars();
     graph->graph_dely = (graph->draw_height - 15) / num_bars; /* round to int to avoid AA blur */
     graph->real_draw_height = graph->graph_dely * num_bars;
-    graph->graph_delx = (graph->draw_width - 2.0 - graph->indent) / (LoadGraph::NUM_POINTS - 3);
-    graph->graph_buffer_offset = (int) (1.5 * graph->graph_delx) + FRAME_WIDTH ;
+    graph->graph_delx = (graph->draw_width - 2.0 - graph->indent) / (graph->num_points - 3);
+    graph->graph_buffer_offset = (int) (1.5 * graph->graph_delx) + FRAME_WIDTH;
 
     gtk_widget_get_allocation (GTK_WIDGET (graph->disp), &allocation);
     surface = gdk_window_create_similar_surface (gtk_widget_get_window (GTK_WIDGET (graph->disp)),
@@ -172,7 +172,7 @@ static void draw_background(LoadGraph *graph) {
     }
     
 
-    const unsigned total_seconds = graph->speed * (LoadGraph::NUM_POINTS - 2) / 1000;
+    const unsigned total_seconds = graph->speed * (graph->num_points - 2) / 1000;
 
     for (unsigned int i = 0; i < 7; i++) {
         double x = (i) * (graph->draw_width - graph->rmargin - graph->indent) / 6;
@@ -187,16 +187,57 @@ static void draw_background(LoadGraph *graph) {
         cairo_line_to (cr, (ceil(x) + 0.5) + graph->indent, graph->real_draw_height + 4.5);
         cairo_stroke(cr);
         unsigned seconds = total_seconds - i * total_seconds / 6;
-        const char* format;
-        if (i == 0)
-            format = dngettext(GETTEXT_PACKAGE, "%u second", "%u seconds", seconds);
-        else
-            format = "%u";
-        caption = g_strdup_printf(format, seconds);
+        unsigned minutes = seconds / 60;
+        unsigned hours = seconds / 3600;
+        caption = NULL;
+
+        if (hours != 0) {
+            if (minutes % 60 == 0) {
+                // If minutes mod 60 is 0 set it to 0, to prevent it from showing full hours in
+                // minutes in addition to hours.
+                minutes = 0;
+            } else {
+                // Round minutes as seconds wont get shown if neither hours nor minutes are 0.
+                minutes = int(rint(seconds / 60.0)) % 60;
+                if (minutes == 0) {
+                    // Increase hours if rounding minutes results in 0, because that would be
+                    // what it would be rounded to.
+                    hours++;
+                    // Set seconds to hours * 3600 to prevent seconds from being drawn.
+                    seconds = hours * 3600;
+                }
+            }
+
+            caption = g_strdup_printf(dngettext(GETTEXT_PACKAGE, "%u hr ", "%u hrs ", hours), hours);
+        }
+        if (minutes != 0) {
+            char* captionM = g_strdup_printf(dngettext(GETTEXT_PACKAGE, "%u min", "%u mins", minutes),
+                                             minutes);
+            if (caption == NULL) {
+                caption = captionM;
+            } else {
+                caption = strcat(caption, captionM);
+            }
+
+            // Add a whitespace if minutes and seconds are shown
+            if (hours == 0 && seconds % 60 != 0) {
+                caption = strcat(caption, " ");
+            }
+        }
+        if (caption == NULL || (seconds % 60 != 0 && (minutes == 0 || hours == 0))) {
+            char* captionS = g_strdup_printf(dngettext(GETTEXT_PACKAGE, "%u sec", "%u secs", seconds % 60),
+                                             seconds % 60);
+            if (caption == NULL) {
+                caption = captionS;
+            } else {
+                caption = strcat(caption, captionS);
+            }
+        }
+
         pango_layout_set_text (layout, caption, -1);
         pango_layout_get_extents (layout, NULL, &extents);
         cairo_move_to (cr,
-                       (ceil(x) + 0.5 + graph->indent) - (1.0 * extents.width / PANGO_SCALE / 2),
+                       (ceil(x) + 0.5 + graph->indent) - (1.0 * extents.width / PANGO_SCALE / 2) + 1.0,
                        graph->draw_height - 1.0 * extents.height / PANGO_SCALE);
         gdk_cairo_set_source_rgba (cr, &fg);
         pango_cairo_show_layout (cr, layout);
@@ -274,7 +315,7 @@ load_graph_draw (GtkWidget *widget,
     gdouble sample_width, x_offset;
 
     /* Number of pixels wide for one sample point */
-    sample_width = (double)(graph->draw_width - graph->rmargin - graph->indent) / 
(double)LoadGraph::NUM_POINTS;
+    sample_width = (double)(graph->draw_width - graph->rmargin - graph->indent) / (double)graph->num_points;
     /* Lines start at the right edge of the drawing,
      * a bit outside the clip rectangle. */
     x_offset = graph->draw_width - graph->rmargin + sample_width + 2;
@@ -305,7 +346,7 @@ load_graph_draw (GtkWidget *widget,
         cairo_move_to (cr, x_offset, (1.0f - graph->data[0][j]) * graph->real_draw_height + 3);
         // then draw the path of the line.
         // Loop starts at 1 because the curve accesses the 0th data point.
-        for (i = 1; i < LoadGraph::NUM_POINTS; ++i) {
+        for (i = 1; i < graph->num_points; ++i) {
             if (graph->data[i][j] == -1.0f)
                 continue;
             if (drawSmooth) {
@@ -477,12 +518,12 @@ get_memory (LoadGraph *graph)
 static double
 nicenum (double x, int round)
 {
-    int expv;                          /* exponent of x */
-    double f;                          /* fractional part of x */
-    double nf;                         /* nice, rounded fraction */
+    int expv;                /* exponent of x */
+    double f;                /* fractional part of x */
+    double nf;                /* nice, rounded fraction */
 
     expv = floor(log10(x));
-    f = x/pow(10.0, expv);             /* between 1 and 10 */
+    f = x/pow(10.0, expv);        /* between 1 and 10 */
     if (round) {
         if (f < 1.5)
             nf = 1.0;
@@ -512,8 +553,11 @@ net_scale (LoadGraph *graph, guint64 din, guint64 dout)
     graph->data[0][1] = 1.0f * dout / graph->net.max;
 
     guint64 dmax = std::max(din, dout);
-    graph->net.values[graph->net.cur] = dmax;
-    graph->net.cur = (graph->net.cur + 1) % LoadGraph::NUM_POINTS;
+    if (graph->latest == 0) {
+        graph->net.values[graph->num_points - 1] = dmax;
+    } else {
+        graph->net.values[graph->latest - 1] = dmax;
+    }
 
     guint64 new_max;
     // both way, new_max is the greatest value
@@ -521,7 +565,7 @@ net_scale (LoadGraph *graph, guint64 din, guint64 dout)
         new_max = dmax;
     else
         new_max = *std::max_element(&graph->net.values[0],
-                                    &graph->net.values[LoadGraph::NUM_POINTS]);
+                                    &graph->net.values[graph->num_points]);
 
     //
     // Round network maximum
@@ -590,7 +634,7 @@ net_scale (LoadGraph *graph, guint64 din, guint64 dout)
 
     const double scale = 1.0f * graph->net.max / new_max;
 
-    for (size_t i = 0; i < LoadGraph::NUM_POINTS; i++) {
+    for (size_t i = 0; i < graph->num_points; i++) {
         if (graph->data[i][0] >= 0.0f) {
             graph->data[i][0] *= scale;
             graph->data[i][1] *= scale;
@@ -685,8 +729,11 @@ load_graph_update_data (LoadGraph *graph)
 {
     // Rotate data one element down.
     std::rotate(&graph->data[0],
-                &graph->data[LoadGraph::NUM_POINTS - 1],
-                &graph->data[LoadGraph::NUM_POINTS]);
+                &graph->data[graph->num_points - 1],
+                &graph->data[graph->num_points]);
+
+    // Update rotation counter.
+    graph->latest = (graph->latest + 1) % graph->num_points;
 
     // Replace the 0th element
     switch (graph->type) {
@@ -758,6 +805,8 @@ LoadGraph::LoadGraph(guint type)
       n(0),
       type(type),
       speed(0),
+      num_points(0),
+      latest(0),
       draw_width(0),
       draw_height(0),
       render_counter(0),
@@ -768,6 +817,7 @@ LoadGraph::LoadGraph(guint type)
       graph_buffer_offset(0),
       colors(),
       data_block(),
+      data(),
       main_widget(NULL),
       disp(NULL),
       background(NULL),
@@ -838,7 +888,9 @@ LoadGraph::LoadGraph(guint type)
             break;
     }
 
-    speed  = GsmApplication::get()->config.graph_update_interval;
+    speed = GsmApplication::get()->config.graph_update_interval;
+
+    num_points = GsmApplication::get()->config.graph_data_points + 2;
 
     colors.resize(n);
 
@@ -856,6 +908,7 @@ LoadGraph::LoadGraph(guint type)
                                                          GSMCP_TYPE_PIE);
             break;
         case LOAD_GRAPH_NET:
+            net.values = std::vector<unsigned>(num_points);
             colors[0] = GsmApplication::get()->config.net_in_color;
             colors[1] = GsmApplication::get()->config.net_out_color;
             break;
@@ -886,11 +939,11 @@ LoadGraph::LoadGraph(guint type)
 
     gtk_box_pack_start (main_widget, GTK_WIDGET (disp), TRUE, TRUE, 0);
 
-
+    data = std::vector<double*>(num_points);
     /* Allocate data in a contiguous block */
-    data_block = std::vector<double>(n * LoadGraph::NUM_POINTS, -1.0);
+    data_block = std::vector<double>(n * num_points, -1.0);
 
-    for (guint i = 0; i < LoadGraph::NUM_POINTS; ++i)
+    for (guint i = 0; i < num_points; ++i)
         data[i] = &data_block[0] + i * n;
 
     gtk_widget_show_all (GTK_WIDGET (main_widget));
@@ -939,6 +992,47 @@ load_graph_change_speed (LoadGraph *graph,
     graph->clear_background();
 }
 
+void
+load_graph_change_num_points(LoadGraph *graph,
+                             guint new_num_points)
+{
+    //Don't do anything if the value didn't change.
+    if (graph->num_points == new_num_points)
+        return;
+
+    // Sort the values in the data_block vector in the order they were accessed in by the pointers in data.
+    std::rotate(&graph->data_block[0],
+                &graph->data_block[(graph->num_points - graph->latest) * graph->n],
+                &graph->data_block[graph->num_points * graph->n]);
+
+    // Reset rotation counter.
+    graph->latest = 0;
+
+    // Resize the vectors to the new amount of data points.
+    graph->data.resize(new_num_points);
+    graph->data_block.resize(graph->n * new_num_points);
+    if (graph->type == LOAD_GRAPH_NET) {
+        graph->net.values.resize(new_num_points);
+    }
+
+    // Fill the new values with -1 instead of 0 if the vectors got bigger.
+    if (new_num_points > graph->num_points) {
+        std::fill(&graph->data_block[graph->n * graph->num_points],
+                  &graph->data_block[graph->n * new_num_points], -1.0);
+    }
+
+    // Replace the pointers in data, to match the new data_block values.
+    for (guint i = 0; i < new_num_points; ++i) {
+        graph->data[i] = &graph->data_block[0] + i * graph->n;
+    }
+
+    // Set the actual number of data points to be used by the graph.
+    graph->num_points = new_num_points;
+
+    // Force the scale to be redrawn.
+    graph->clear_background();
+}
+
 
 LoadGraphLabels*
 load_graph_get_labels (LoadGraph *graph)
diff --git a/src/load-graph.h b/src/load-graph.h
index 1be59ad1..a49736de 100644
--- a/src/load-graph.h
+++ b/src/load-graph.h
@@ -36,7 +36,6 @@ struct LoadGraphLabels
 struct LoadGraph
   : private procman::NonCopyable
 {
-    static const unsigned NUM_POINTS = 60 + 2;
     static const unsigned GRAPH_MIN_HEIGHT = 40;
 
     LoadGraph(guint type);
@@ -53,6 +52,8 @@ struct LoadGraph
     guint n;
     gint type;
     guint speed;
+    guint num_points;
+    guint latest;
     guint draw_width, draw_height;
     guint render_counter;
     guint frames_per_unit;
@@ -64,7 +65,7 @@ struct LoadGraph
     std::vector<GdkRGBA> colors;
 
     std::vector<double> data_block;
-    double* data[NUM_POINTS];
+    std::vector<double*> data;
 
     GtkBox *main_widget;
     GtkDrawingArea *disp;
@@ -93,8 +94,7 @@ struct LoadGraph
         guint64 last_in, last_out;
         guint64 time;
         guint64 max;
-        unsigned values[NUM_POINTS];
-        size_t cur;
+        std::vector<unsigned> values;
     } net;
     /* }; */
 };
@@ -116,6 +116,11 @@ void
 load_graph_change_speed (LoadGraph *g,
                          guint new_speed);
 
+/* Change load graph data points and restart it if it has been previously started */
+void
+load_graph_change_num_points(LoadGraph *g,
+                             guint new_num_points);
+
 /* Clear the history data. */
 void
 load_graph_reset (LoadGraph *g);
diff --git a/src/org.gnome.gnome-system-monitor.gschema.xml.in 
b/src/org.gnome.gnome-system-monitor.gschema.xml.in
index 0c7a03d1..e66a91f7 100644
--- a/src/org.gnome.gnome-system-monitor.gschema.xml.in
+++ b/src/org.gnome.gnome-system-monitor.gschema.xml.in
@@ -69,6 +69,12 @@
       <summary>Time in milliseconds between updates of the devices list</summary>
     </key>
 
+    <key name="graph-data-points" type="i">
+      <range min="30" max="600"/>
+      <default>60</default>
+      <summary>Time amount of data points in the resource graphs</summary>
+    </key>
+
     <key name="show-whose-processes" type="s">
       <default>'user'</default>
       <choices>
diff --git a/src/prefsdialog.cpp b/src/prefsdialog.cpp
index 9f18fd72..d433265b 100644
--- a/src/prefsdialog.cpp
+++ b/src/prefsdialog.cpp
@@ -43,7 +43,7 @@ private:
 
     void update(GtkSpinButton* spin)
     {
-        int new_value = int(1000 * gtk_spin_button_get_value(spin));
+        int new_value = 1000 * gtk_spin_button_get_value(spin);
 
         GsmApplication::get()->settings->set_int(this->key, new_value);
 
@@ -53,6 +53,34 @@ private:
     const string key;
 };
 
+class ScaleUpdater
+{
+public:
+       ScaleUpdater(const string& key)
+           : key(key)
+       { }
+
+       static gboolean callback(GtkRange *range, gpointer data)
+       {
+               ScaleUpdater* updater = static_cast<ScaleUpdater*>(data);
+               updater->update(range);
+               return FALSE;
+       }
+
+private:
+
+       void update(GtkRange* range)
+       {
+               int new_value = gtk_range_get_value(range);
+
+               GsmApplication::get()->settings->set_int(this->key, new_value);
+
+               procman_debug("set %s to %d", this->key.c_str(), new_value);
+       }
+
+       const string key;
+};
+
 static void
 field_toggled (const gchar *gsettings_parent, gchar *path_str, gpointer data)
 {
@@ -199,6 +227,7 @@ create_preferences_dialog (GsmApplication *app)
     static SBU interval_updater("update-interval");
     static SBU graph_interval_updater("graph-update-interval");
     static SBU disks_interval_updater("disks-interval");
+    static ScaleUpdater graph_points_updater("graph-data-points");
 
     GtkNotebook *notebook;
     GtkAdjustment *adjustment;
@@ -266,6 +295,15 @@ create_preferences_dialog (GsmApplication *app)
                       G_CALLBACK(SBU::callback),
                       &graph_interval_updater);
 
+    update = (gfloat) app->config.graph_data_points;
+    GtkRange* range = GTK_RANGE (gtk_builder_get_object (builder, "graph_data_points_scale"));
+    adjustment = gtk_range_get_adjustment (range);
+    gtk_adjustment_configure (adjustment, update, 30,
+                                 600, 10, 50, 0);
+    g_signal_connect (G_OBJECT (range), "value-changed",
+                         G_CALLBACK(ScaleUpdater::callback),
+                                         &graph_points_updater);
+
     GtkCheckButton *bits_button = GTK_CHECK_BUTTON (gtk_builder_get_object (builder, "bits_button"));
     g_settings_bind(app->settings->gobj (), GSM_SETTING_NETWORK_IN_BITS,
                     bits_button, "active",
diff --git a/src/settings-keys.h b/src/settings-keys.h
index 87fbb9f7..52bdc812 100644
--- a/src/settings-keys.h
+++ b/src/settings-keys.h
@@ -26,6 +26,7 @@
 #define GSM_SETTING_DRAW_STACKED            "cpu-stacked-area-chart"
 #define GSM_SETTING_DRAW_SMOOTH             "cpu-smooth-graph"
 #define GSM_SETTING_NETWORK_IN_BITS         "network-in-bits"
+#define GSM_SETTING_GRAPH_DATA_POINTS       "graph-data-points"
 #define GSM_SETTING_SHOW_CPU                "show-cpu"
 #define GSM_SETTING_SHOW_MEM                "show-mem"
 #define GSM_SETTING_SHOW_NETWORK            "show-network"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]