From 0b2d46d9dbe52b067032950486abaacfbed408c9 Mon Sep 17 00:00:00 2001 From: Ryo Nakano <26003928+ryonakano@users.noreply.github.com> Date: Sun, 26 Jul 2020 11:45:17 +0900 Subject: [PATCH 01/45] Save the last opened view --- data/com.github.stsdc.monitor.gschema.xml | 5 +++++ src/MainWindow.vala | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/data/com.github.stsdc.monitor.gschema.xml b/data/com.github.stsdc.monitor.gschema.xml index b7f8c63b..90fc778d 100644 --- a/data/com.github.stsdc.monitor.gschema.xml +++ b/data/com.github.stsdc.monitor.gschema.xml @@ -40,5 +40,10 @@ To start Monitor in background or not To start Monitor in background or not + + 'process_view' + Opened view + The last opened view + diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 7adce5b4..f36441ac 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -10,6 +10,7 @@ public ProcessView process_view; public SystemView system_view; + private Gtk.Stack stack; private Statusbar statusbar; @@ -29,7 +30,7 @@ process_view = new ProcessView (); system_view = new SystemView (resources); - Gtk.Stack stack = new Gtk.Stack (); + stack = new Gtk.Stack (); stack.set_transition_type (Gtk.StackTransitionType.SLIDE_LEFT_RIGHT); stack.add_titled (process_view, "process_view", _("Processes")); stack.add_titled (system_view, "system_view", _("System")); @@ -48,6 +49,8 @@ main_box.pack_start (statusbar, false, true, 0); this.add (main_box); + show_all (); + dbusserver = DBusServer.get_default (); stack.notify["visible-child-name"].connect (() => { @@ -87,6 +90,8 @@ MonitorApp.settings.set_int ("position-y", position_y); MonitorApp.settings.set_boolean ("is-maximized", this.is_maximized); + MonitorApp.settings.set_string ("opened-view", stack.visible_child_name); + if (MonitorApp.settings.get_boolean ("indicator-state")) { this.hide_on_delete (); } else { @@ -98,6 +103,7 @@ }); dbusserver.indicator_state (MonitorApp.settings.get_boolean ("indicator-state")); + stack.visible_child_name = MonitorApp.settings.get_string ("opened-view"); } private void setup_window_state () { From 9704009d4d0073df87c962a8b0bfb7a056c87089 Mon Sep 17 00:00:00 2001 From: Ryo Nakano <26003928+ryonakano@users.noreply.github.com> Date: Sun, 26 Jul 2020 12:05:29 +0900 Subject: [PATCH 02/45] Fix compiler warnings --- src/Views/ProcessView/ProcessInfoView/Chart.vala | 2 +- .../ProcessView/ProcessInfoView/Preventor.vala | 10 +++++----- .../ProcessInfoView/ProcessInfoView.vala | 7 ------- .../ProcessTreeView/CPUProcessTreeView.vala | 14 +++++++------- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Views/ProcessView/ProcessInfoView/Chart.vala b/src/Views/ProcessView/ProcessInfoView/Chart.vala index 3e320b5e..3ccbf737 100644 --- a/src/Views/ProcessView/ProcessInfoView/Chart.vala +++ b/src/Views/ProcessView/ProcessInfoView/Chart.vala @@ -46,7 +46,7 @@ public class Monitor.Chart : Gtk.Box { chart.add_value (serie, value); } - public void set_data (Gee.ArrayList history) { + public new void set_data (Gee.ArrayList history) { var refresh_rate_is_ms = 2000; //your own refresh rate in milliseconds chart.add_unaware_timestamp_collection(serie, history, refresh_rate_is_ms); } diff --git a/src/Views/ProcessView/ProcessInfoView/Preventor.vala b/src/Views/ProcessView/ProcessInfoView/Preventor.vala index f09f5673..df5e80bc 100644 --- a/src/Views/ProcessView/ProcessInfoView/Preventor.vala +++ b/src/Views/ProcessView/ProcessInfoView/Preventor.vala @@ -5,7 +5,7 @@ public class Monitor.Preventor : Gtk.Stack { private Gtk.Button confirm_button; private Gtk.Button deny_button; - private Gtk.Widget child; + private Gtk.Widget child_widget; public signal void confirmed (bool is_confirmed); @@ -33,19 +33,19 @@ public class Monitor.Preventor : Gtk.Stack { } public Preventor (Gtk.Widget _child, string name) { - child = _child; - add_named (child, name); + child_widget = _child; + add_named (child_widget, name); add_named (preventive_action_bar, "preventive_action_bar"); deny_button.clicked.connect (() => { set_transition_type(Gtk.StackTransitionType.SLIDE_UP); - set_visible_child (child); + set_visible_child (child_widget); confirmed(false); }); confirm_button.clicked.connect(() => { set_transition_type(Gtk.StackTransitionType.SLIDE_UP); - set_visible_child (child); + set_visible_child (child_widget); confirmed(true); }); } diff --git a/src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala b/src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala index 26929c1f..c0163bd7 100644 --- a/src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala +++ b/src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala @@ -22,7 +22,6 @@ public class Monitor.ProcessInfoView : Gtk.Box { } } public string ? icon_name; - private Gtk.ScrolledWindow command_wrapper; private Gtk.InfoBar permission_error_infobar; private Gtk.Label permission_error_label; @@ -31,15 +30,9 @@ public class Monitor.ProcessInfoView : Gtk.Box { private ProcessInfoIOStats process_info_io_stats; private ProcessInfoCPURAM process_info_cpu_ram; - - private Regex ? regex; - private Gtk.Grid grid; - private Gtk.Button end_process_button; private Gtk.Button kill_process_button; - private Preventor preventor; - public ProcessInfoView () { orientation = Gtk.Orientation.VERTICAL; hexpand = true; diff --git a/src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala b/src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala index 149c910f..31ae9d01 100644 --- a/src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala +++ b/src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala @@ -82,12 +82,12 @@ public class Monitor.CPUProcessTreeView : Gtk.TreeView { try { Gdk.Pixbuf icon = new Gdk.Pixbuf.from_file_at_size (path, 16, -1); - (icon_cell as Gtk.CellRendererPixbuf).pixbuf = icon; + ((Gtk.CellRendererPixbuf)icon_cell).pixbuf = icon; } catch (Error e) { warning (e.message); } } else { - (icon_cell as Gtk.CellRendererPixbuf).icon_name = path; + ((Gtk.CellRendererPixbuf)icon_cell).icon_name = path; } } @@ -99,9 +99,9 @@ public class Monitor.CPUProcessTreeView : Gtk.TreeView { // format the double into a string if (cpu_usage < 0.0) - (cell as Gtk.CellRendererText).text = Utils.NO_DATA; + ((Gtk.CellRendererText)cell).text = Utils.NO_DATA; else - (cell as Gtk.CellRendererText).text = "%.0f%%".printf (cpu_usage); + ((Gtk.CellRendererText)cell).text = "%.0f%%".printf (cpu_usage); } public void memory_usage_cell_layout (Gtk.CellLayout cell_layout, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { @@ -126,9 +126,9 @@ public class Monitor.CPUProcessTreeView : Gtk.TreeView { // format the double into a string if (memory_usage == 0) - (cell as Gtk.CellRendererText).text = Utils.NO_DATA; + ((Gtk.CellRendererText)cell).text = Utils.NO_DATA; else - (cell as Gtk.CellRendererText).text = "%.1f %s".printf (memory_usage_double, units); + ((Gtk.CellRendererText)cell).text = "%.1f %s".printf (memory_usage_double, units); } private void pid_cell_layout (Gtk.CellLayout cell_layout, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { @@ -137,7 +137,7 @@ public class Monitor.CPUProcessTreeView : Gtk.TreeView { int pid = pid_value.get_int (); // format the double into a string if (pid == 0) { - (cell as Gtk.CellRendererText).text = Utils.NO_DATA; + ((Gtk.CellRendererText)cell).text = Utils.NO_DATA; } } From d44a55dfa2771d8c9bc6e4ab903a460b34ce82a5 Mon Sep 17 00:00:00 2001 From: stsdc Date: Mon, 27 Jul 2020 01:25:58 +0200 Subject: [PATCH 03/45] =?UTF-8?q?just=20messing=20around:=20remove=20threa?= =?UTF-8?q?ds,=20add=20cpu=20name;=20rename=20CPU=20=E2=86=92=20Overall=20?= =?UTF-8?q?usage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/Application.css | 8 ++++ src/Views/SystemView/SystemCPUChart.vala | 1 - src/Views/SystemView/SystemCPUView.vala | 61 ++++++++++++++++++++---- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/data/Application.css b/data/Application.css index 4a728fba..484f09de 100644 --- a/data/Application.css +++ b/data/Application.css @@ -93,3 +93,11 @@ font-size:9px; color: @SILVER_700; margin: 6px; } + +.bold { + font-weight: bold; +} + +.text-secondary { + color: @SILVER_700; +} \ No newline at end of file diff --git a/src/Views/SystemView/SystemCPUChart.vala b/src/Views/SystemView/SystemCPUChart.vala index 492112c6..038e1e3c 100644 --- a/src/Views/SystemView/SystemCPUChart.vala +++ b/src/Views/SystemView/SystemCPUChart.vala @@ -36,7 +36,6 @@ public class Monitor.SystemCPUChart : Gtk.Box { red= 1, green= 1, blue= 1, alpha= 1 }; //White background - } public SystemCPUChart (int cores_quantity) { diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 7914ffad..67d42835 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -3,11 +3,15 @@ public class Monitor.SystemCPUView : Gtk.Grid { private CPU cpu; private Gtk.Label cpu_percentage_label; + private Gtk.Label processor_name_label; + + private Gtk.Button view_threads_usage_button; private Gee.ArrayList core_label_list; construct { margin = 12; + margin_top = 6; column_spacing = 12; set_vexpand (false); @@ -19,17 +23,38 @@ public class Monitor.SystemCPUView : Gtk.Grid { public SystemCPUView(CPU _cpu) { cpu = _cpu; - cpu_percentage_label = new Gtk.Label (_("CPU: ") + Utils.NO_DATA); - cpu_percentage_label.get_style_context ().add_class ("h2"); + cpu_percentage_label = new Gtk.Label (_("Overall usage: ") + Utils.NO_DATA); + cpu_percentage_label.get_style_context ().add_class ("h3"); cpu_percentage_label.valign = Gtk.Align.START; cpu_percentage_label.halign = Gtk.Align.START; - cpu_percentage_label.margin_start = 6; + cpu_percentage_label.margin_start = 12; + cpu_percentage_label.margin_top = 6; + + processor_name_label = new Gtk.Label ("AMD Ryzen 5 2400G with Radeon Vega Graphics"); + processor_name_label.get_style_context ().add_class ("h4"); + // processor_name_label.get_style_context ().add_class ("text-secondary"); + processor_name_label.valign = Gtk.Align.START; + processor_name_label.halign = Gtk.Align.START; + processor_name_label.margin_start = 6; + // processor_name_label.margin_top = 6; cpu_chart = new SystemCPUChart (cpu.core_list.size); - attach (grid_core_labels (), 0, 0, 1); - attach (cpu_percentage_label, 1, 0, 1, 1); - attach (cpu_chart, 1, 0, 1, 2); + view_threads_usage_button = new Gtk.Button (); + view_threads_usage_button.has_tooltip = true; + view_threads_usage_button.tooltip_text = (_("Settings")); + var icon = new Gtk.Image (); + icon.gicon = new ThemedIcon ("view-more-horizontal-symbolic"); + icon.pixel_size = 16; + view_threads_usage_button.set_image (icon); + + // attach (grid_core_labels (), 0, 0, 1, 1); + // attach (grid_info_labels (), 0, 0, 1, 1); + attach (processor_name_label, 0, 0, 1, 1); + attach (grid_usage_labels(), 0, 1, 1, 1); + // attach (view_threads_usage_button, 1, 1, 1, 1); + // attach (processor_name_label, 0, 0, 1, 1); + attach (cpu_chart, 0, 1, 1, 1); } @@ -39,10 +64,30 @@ public class Monitor.SystemCPUView : Gtk.Grid { double core_percentage = cpu.core_list[i].percentage_used; cpu_chart.update(i, core_percentage); string percentage_formatted = ("% 3d%%").printf ( (int)core_percentage); - core_label_list[i].set_text (_("Thread %d: %s").printf (i, percentage_formatted)); + // core_label_list[i].set_text (_("Thread %d: %s").printf (i, percentage_formatted)); } - cpu_percentage_label.set_text ((_("CPU: % 3d%%")).printf (cpu.percentage)); + cpu_percentage_label.set_text ((_("Overall usage: % 3d%%")).printf (cpu.percentage)); + } + + private Gtk.Grid grid_info_labels () { + Gtk.Grid grid = new Gtk.Grid (); + grid.column_spacing = 12; + + grid.attach(processor_name_label, 0, 0, 1, 1); + grid.attach(cpu_percentage_label, 0, 1, 1, 1); + + return grid; + } + + private Gtk.Grid grid_usage_labels () { + Gtk.Grid grid = new Gtk.Grid (); + grid.column_spacing = 12; + + grid.attach(cpu_percentage_label, 0, 0, 1, 1); + grid.attach(view_threads_usage_button, 1, 0, 1, 1); + + return grid; } private Gtk.Grid grid_core_labels () { From 91de09c875bcfa3210e9a9b7b262fb422702cb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 29 Jul 2020 19:01:10 +0200 Subject: [PATCH 04/45] add vertical label --- data/Application.css | 19 +++++++++++-- meson.build | 5 ++-- src/Views/SystemView/SystemCPUView.vala | 18 ++++++------ .../Labels}/RoundyLabel.vala | 2 +- src/Widgets/Labels/VerticalLabel.vala | 28 +++++++++++++++++++ 5 files changed, 57 insertions(+), 15 deletions(-) rename src/{Views/ProcessView/ProcessInfoView => Widgets/Labels}/RoundyLabel.vala (87%) create mode 100644 src/Widgets/Labels/VerticalLabel.vala diff --git a/data/Application.css b/data/Application.css index 484f09de..a7d66c05 100644 --- a/data/Application.css +++ b/data/Application.css @@ -14,6 +14,19 @@ border-width: 0; } +.vertical-label, +.vertical-label:hover, +.vertical-label:selected, +.vertical-label:selected:focus, +.vertical-label:hover:selected { + color: alpha(@text_color, 1); + font-size: 28px; + font-weight: 100; + /* padding: 0 6px; + margin: 0 3px; */ + border-width: 0; +} + .username-current { background-color: @SILVER_300; color: @SILVER_900; @@ -59,10 +72,10 @@ font-family: monospace; } -.pid { +.small-text { color:grey; -font-weight:bold; -font-size:9px; + font-weight:bold; + font-size:9px; } .graph { diff --git a/meson.build b/meson.build index 230091e3..d2795eab 100644 --- a/meson.build +++ b/meson.build @@ -73,7 +73,6 @@ executable( # Widgets related only to ProcessInfoView 'src/Views/ProcessView/ProcessInfoView/Preventor.vala', - 'src/Views/ProcessView/ProcessInfoView/RoundyLabel.vala', 'src/Views/ProcessView/ProcessInfoView/Chart.vala', 'src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala', 'src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala', @@ -84,7 +83,9 @@ executable( 'src/Widgets/Headerbar/Headerbar.vala', 'src/Widgets/Headerbar/Search.vala', 'src/Widgets/Statusbar/Statusbar.vala', - + 'src/Widgets/Labels/VerticalLabel.vala', + 'src/Widgets/Labels/RoundyLabel.vala', + # Models 'src/Models/TreeViewModel.vala', diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 67d42835..2c0f0486 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -2,7 +2,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { private SystemCPUChart cpu_chart; private CPU cpu; - private Gtk.Label cpu_percentage_label; + private VerticalLabel cpu_percentage_label; private Gtk.Label processor_name_label; private Gtk.Button view_threads_usage_button; @@ -23,12 +23,12 @@ public class Monitor.SystemCPUView : Gtk.Grid { public SystemCPUView(CPU _cpu) { cpu = _cpu; - cpu_percentage_label = new Gtk.Label (_("Overall usage: ") + Utils.NO_DATA); - cpu_percentage_label.get_style_context ().add_class ("h3"); - cpu_percentage_label.valign = Gtk.Align.START; - cpu_percentage_label.halign = Gtk.Align.START; - cpu_percentage_label.margin_start = 12; - cpu_percentage_label.margin_top = 6; + cpu_percentage_label = new VerticalLabel (_("UTILIZATION")); + // cpu_percentage_label.get_style_context ().add_class ("h3"); + // cpu_percentage_label.valign = Gtk.Align.START; + // cpu_percentage_label.halign = Gtk.Align.START; + // cpu_percentage_label.margin_start = 12; + // cpu_percentage_label.margin_top = 6; processor_name_label = new Gtk.Label ("AMD Ryzen 5 2400G with Radeon Vega Graphics"); processor_name_label.get_style_context ().add_class ("h4"); @@ -67,7 +67,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { // core_label_list[i].set_text (_("Thread %d: %s").printf (i, percentage_formatted)); } - cpu_percentage_label.set_text ((_("Overall usage: % 3d%%")).printf (cpu.percentage)); + cpu_percentage_label.set_text ((_("%d%%")).printf (cpu.percentage)); } private Gtk.Grid grid_info_labels () { @@ -85,7 +85,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { grid.column_spacing = 12; grid.attach(cpu_percentage_label, 0, 0, 1, 1); - grid.attach(view_threads_usage_button, 1, 0, 1, 1); + // grid.attach(view_threads_usage_button, 1, 0, 1, 1); return grid; } diff --git a/src/Views/ProcessView/ProcessInfoView/RoundyLabel.vala b/src/Widgets/Labels/RoundyLabel.vala similarity index 87% rename from src/Views/ProcessView/ProcessInfoView/RoundyLabel.vala rename to src/Widgets/Labels/RoundyLabel.vala index 7a8964d4..a399279b 100644 --- a/src/Views/ProcessView/ProcessInfoView/RoundyLabel.vala +++ b/src/Widgets/Labels/RoundyLabel.vala @@ -8,7 +8,7 @@ public class Monitor.RoundyLabel : Gtk.Fixed { val.get_style_context ().add_class ("roundy-label"); desc = new Gtk.Label (description); - desc.get_style_context ().add_class ("pid"); + desc.get_style_context ().add_class ("small-text"); put(val, 0, 12); put(desc, 6, 0); diff --git a/src/Widgets/Labels/VerticalLabel.vala b/src/Widgets/Labels/VerticalLabel.vala new file mode 100644 index 00000000..3de928b2 --- /dev/null +++ b/src/Widgets/Labels/VerticalLabel.vala @@ -0,0 +1,28 @@ +public class Monitor.VerticalLabel : Gtk.Grid { + + public Gtk.Label val; + public Gtk.Label desc; + + construct { + margin_start = 12; + margin_top = 6; + } + + public VerticalLabel (string description) { + val = new Gtk.Label (Utils.NO_DATA); + // val.get_style_context ().add_class ("h2"); + + val.get_style_context ().add_class ("vertical-label"); + + desc = new Gtk.Label (description); + // desc.get_style_context ().add_class ("h4"); + desc.get_style_context ().add_class ("small-text"); + + attach(desc, 0, 0, 1, 1); + attach(val, 0, 1, 1, 1); + } + + public void set_text (string text) { + val.set_text (text); + } +} \ No newline at end of file From b8cb0cd08d219aac93de9c9ad0a80ad7f83da5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 29 Jul 2020 19:47:56 +0200 Subject: [PATCH 05/45] get processor's name --- src/Resources/CPU.vala | 64 +++++++++++++++++++++++++ src/Views/SystemView/SystemCPUView.vala | 2 +- vapi/libgtop-2.0.vapi | 8 ++-- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/Resources/CPU.vala b/src/Resources/CPU.vala index df0ded16..3f40c573 100644 --- a/src/Resources/CPU.vala +++ b/src/Resources/CPU.vala @@ -3,6 +3,8 @@ public class Monitor.CPU : Object { private float last_total; private float load; + public string? cpu_name; + GTop.Cpu ? cpu; public int percentage { @@ -27,6 +29,7 @@ public class Monitor.CPU : Object { core_list = new Gee.ArrayList (); + cpu_name = get_cpu_info (); debug ("Number of cores: %d", (int) get_num_processors ()); for (int i = 0; i < (int) get_num_processors (); i++) { @@ -83,4 +86,65 @@ public class Monitor.CPU : Object { _frequency = (double)maxcur; } + + // straight from elementary about-plug + private string? get_cpu_info () { + unowned GTop.SysInfo? info = GTop.glibtop_get_sysinfo (); + + if (info == null) { + return null; + } + + var counts = new Gee.HashMap (); + const string[] KEYS = { "model name", "cpu", "Processor" }; + + for (int i = 0; i < info.ncpu; i++) { + unowned GLib.HashTable values = info.cpuinfo[i].values; + string? model = null; + foreach (var key in KEYS) { + model = values.lookup (key); + + if (model != null) { + break; + } + } + + string? core_count = values.lookup ("cpu cores"); + if (core_count != null) { + counts.@set (model, int.parse (core_count)); + continue; + } + + if (!counts.has_key (model)) { + counts.@set (model, 1); + } else { + counts.@set (model, counts.@get (model) + 1); + } + } + + if (counts.size == 0) { + return null; + } + + string result = ""; + foreach (var cpu in counts.entries) { + if (result.length > 0) { + result += "\n"; + } + + if (cpu.@value == 2) { + result += _("Dual-Core %s").printf ( (cpu.key)); + } else if (cpu.@value == 4) { + result += _("Quad-Core %s").printf ( (cpu.key)); + } else if (cpu.@value == 6) { + result += _("Hexa-Core %s").printf ( (cpu.key)); + } else { + result += "%u\u00D7 %s ".printf (cpu.@value, (cpu.key)); + } + } + + debug("%s", result); + + return result; + } } diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 2c0f0486..fccead49 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -30,7 +30,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { // cpu_percentage_label.margin_start = 12; // cpu_percentage_label.margin_top = 6; - processor_name_label = new Gtk.Label ("AMD Ryzen 5 2400G with Radeon Vega Graphics"); + processor_name_label = new Gtk.Label (cpu.cpu_name); processor_name_label.get_style_context ().add_class ("h4"); // processor_name_label.get_style_context ().add_class ("text-secondary"); processor_name_label.valign = Gtk.Align.START; diff --git a/vapi/libgtop-2.0.vapi b/vapi/libgtop-2.0.vapi index e8db74b8..53be24b9 100644 --- a/vapi/libgtop-2.0.vapi +++ b/vapi/libgtop-2.0.vapi @@ -127,9 +127,9 @@ namespace GTop { [CCode (cheader_filename = "glibtop/sysinfo.h", cname = "glibtop_entry", has_type_id = false)] public struct Entry { - public weak GLib.GenericArray labels; - public weak GLib.HashTable values; - public weak GLib.HashTable descriptions; + public GLib.PtrArray labels; + public GLib.HashTable values; + public GLib.HashTable descriptions; } [CCode (cheader_filename = "glibtop/fsusage.h", cname = "glibtop_fsusage", has_type_id = false)] @@ -521,7 +521,7 @@ namespace GTop { public uint64 flags; public uint64 ncpu; [CCode (array_length = false, array_null_terminated = true)] - public weak GTop.Entry[] cpuinfo; + public unowned Entry[] cpuinfo; } [CCode (cheader_filename = "glibtop/union.h", cname = "glibtop_union")] From b786f5bedca9fc773730c5c5fc52edc3879ea4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Fri, 31 Jul 2020 00:02:51 +0200 Subject: [PATCH 06/45] refactoring --- meson.build | 9 ++-- .../ProcessInfoView/ProcessInfoCPURAM.vala | 8 ++-- .../ProcessInfoView/ProcessInfoHeader.vala | 28 ++++++------- src/Views/SystemView/SystemCPUView.vala | 18 +++----- src/Views/SystemView/SystemMemoryView.vala | 24 +++++------ .../Chart/Chart.vala} | 42 ++++++++----------- .../Chart/ProcessChart.vala} | 4 +- src/Widgets/Labels/LabelH4.vala | 14 +++++++ .../{RoundyLabel.vala => LabelRoundy.vala} | 4 +- ...{VerticalLabel.vala => LabelVertical.vala} | 4 +- 10 files changed, 78 insertions(+), 77 deletions(-) rename src/{Views/SystemView/SystemCPUChart.vala => Widgets/Chart/Chart.vala} (55%) rename src/{Views/ProcessView/ProcessInfoView/Chart.vala => Widgets/Chart/ProcessChart.vala} (97%) create mode 100644 src/Widgets/Labels/LabelH4.vala rename src/Widgets/Labels/{RoundyLabel.vala => LabelRoundy.vala} (81%) rename src/Widgets/Labels/{VerticalLabel.vala => LabelVertical.vala} (86%) diff --git a/meson.build b/meson.build index d2795eab..249087f0 100644 --- a/meson.build +++ b/meson.build @@ -67,13 +67,11 @@ executable( 'src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala', 'src/Views/SystemView/SystemView.vala', - 'src/Views/SystemView/SystemCPUChart.vala', 'src/Views/SystemView/SystemCPUView.vala', 'src/Views/SystemView/SystemMemoryView.vala', # Widgets related only to ProcessInfoView 'src/Views/ProcessView/ProcessInfoView/Preventor.vala', - 'src/Views/ProcessView/ProcessInfoView/Chart.vala', 'src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala', 'src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala', 'src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala', @@ -83,8 +81,11 @@ executable( 'src/Widgets/Headerbar/Headerbar.vala', 'src/Widgets/Headerbar/Search.vala', 'src/Widgets/Statusbar/Statusbar.vala', - 'src/Widgets/Labels/VerticalLabel.vala', - 'src/Widgets/Labels/RoundyLabel.vala', + 'src/Widgets/Labels/LabelVertical.vala', + 'src/Widgets/Labels/LabelRoundy.vala', + 'src/Widgets/Labels/LabelH4.vala', + 'src/Widgets/Chart/Chart.vala', + 'src/Widgets/Chart/ProcessChart.vala', # Models diff --git a/src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala b/src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala index 70ca1541..755c321c 100644 --- a/src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala +++ b/src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala @@ -2,8 +2,8 @@ public class Monitor.ProcessInfoCPURAM : Gtk.Grid { private Gtk.Label cpu_label; private Gtk.Label ram_label; - private Chart cpu_chart; - private Chart ram_chart; + private ProcessChart cpu_chart; + private ProcessChart ram_chart; construct { column_spacing = 6; @@ -12,8 +12,8 @@ public class Monitor.ProcessInfoCPURAM : Gtk.Grid { column_homogeneous = true; row_homogeneous = false; - cpu_chart = new Chart (); - ram_chart = new Chart (); + cpu_chart = new ProcessChart (); + ram_chart = new ProcessChart (); var cpu_graph_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); diff --git a/src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala b/src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala index aa072fbf..1704d346 100644 --- a/src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala +++ b/src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala @@ -2,13 +2,13 @@ public class Monitor.ProcessInfoHeader : Gtk.Grid { private Gtk.Image icon; public Gtk.Label state; public Gtk.Label application_name; - public RoundyLabel pid; - public RoundyLabel ppid; - public RoundyLabel pgrp; - public RoundyLabel nice; - public RoundyLabel priority; - public RoundyLabel num_threads; - public RoundyLabel username; + public LabelRoundy pid; + public LabelRoundy ppid; + public LabelRoundy pgrp; + public LabelRoundy nice; + public LabelRoundy priority; + public LabelRoundy num_threads; + public LabelRoundy username; private Regex ? regex; @@ -36,15 +36,15 @@ public class Monitor.ProcessInfoHeader : Gtk.Grid { application_name.halign = Gtk.Align.START; application_name.valign = Gtk.Align.START; - pid = new RoundyLabel (_ ("PID")); - nice = new RoundyLabel (_ ("NI")); - priority = new RoundyLabel (_ ("PRI")); - num_threads = new RoundyLabel (_ ("THR")); - // ppid = new RoundyLabel (_("PPID")); - // pgrp = new RoundyLabel (_("PGRP")); + pid = new LabelRoundy (_ ("PID")); + nice = new LabelRoundy (_ ("NI")); + priority = new LabelRoundy (_ ("PRI")); + num_threads = new LabelRoundy (_ ("THR")); + // ppid = new LabelRoundy (_("PPID")); + // pgrp = new LabelRoundy (_("PGRP")); // TODO: tooltip_text UID - username = new RoundyLabel (""); + username = new LabelRoundy (""); var wrapper = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); wrapper.add (pid); diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index fccead49..d3794449 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -1,9 +1,9 @@ public class Monitor.SystemCPUView : Gtk.Grid { - private SystemCPUChart cpu_chart; + private Chart cpu_chart; private CPU cpu; - private VerticalLabel cpu_percentage_label; - private Gtk.Label processor_name_label; + private LabelVertical cpu_percentage_label; + private LabelH4 processor_name_label; private Gtk.Button view_threads_usage_button; @@ -23,22 +23,16 @@ public class Monitor.SystemCPUView : Gtk.Grid { public SystemCPUView(CPU _cpu) { cpu = _cpu; - cpu_percentage_label = new VerticalLabel (_("UTILIZATION")); + cpu_percentage_label = new LabelVertical (_("UTILIZATION")); // cpu_percentage_label.get_style_context ().add_class ("h3"); // cpu_percentage_label.valign = Gtk.Align.START; // cpu_percentage_label.halign = Gtk.Align.START; // cpu_percentage_label.margin_start = 12; // cpu_percentage_label.margin_top = 6; - processor_name_label = new Gtk.Label (cpu.cpu_name); - processor_name_label.get_style_context ().add_class ("h4"); - // processor_name_label.get_style_context ().add_class ("text-secondary"); - processor_name_label.valign = Gtk.Align.START; - processor_name_label.halign = Gtk.Align.START; - processor_name_label.margin_start = 6; - // processor_name_label.margin_top = 6; + processor_name_label = new LabelH4 (cpu.cpu_name); - cpu_chart = new SystemCPUChart (cpu.core_list.size); + cpu_chart = new Chart (cpu.core_list.size); view_threads_usage_button = new Gtk.Button (); view_threads_usage_button.has_tooltip = true; diff --git a/src/Views/SystemView/SystemMemoryView.vala b/src/Views/SystemView/SystemMemoryView.vala index 16cd0a72..f2c0647d 100644 --- a/src/Views/SystemView/SystemMemoryView.vala +++ b/src/Views/SystemView/SystemMemoryView.vala @@ -1,8 +1,9 @@ public class Monitor.SystemMemoryView : Gtk.Grid { - private SystemCPUChart memory_chart; + private Chart memory_chart; private Memory memory; - private Gtk.Label memory_percentage_label; + private LabelH4 memory_name_label; + private LabelVertical memory_percentage_label; private Gtk.Label memory_shared_label; private Gtk.Label memory_buffered_label; private Gtk.Label memory_cached_label; @@ -21,11 +22,9 @@ public class Monitor.SystemMemoryView : Gtk.Grid { public SystemMemoryView(Memory _memory) { memory = _memory; - memory_percentage_label = new Gtk.Label (_("Memory: ") + Utils.NO_DATA); - memory_percentage_label.get_style_context ().add_class ("h2"); - memory_percentage_label.halign = Gtk.Align.START; - memory_percentage_label.valign = Gtk.Align.START; - memory_percentage_label.margin_start = 6; + memory_name_label = new LabelH4 (_("Memory")); + + memory_percentage_label = new LabelVertical (_("UTILIZATION")); memory_total_label = new Gtk.Label (_("Total: ") + Utils.NO_DATA); memory_total_label.halign = Gtk.Align.START; @@ -45,11 +44,12 @@ public class Monitor.SystemMemoryView : Gtk.Grid { memory_locked_label = new Gtk.Label (_("Locked: ") + Utils.NO_DATA); memory_locked_label.halign = Gtk.Align.START; - memory_chart = new SystemCPUChart (1); + memory_chart = new Chart (1); - attach (memory_percentage_label, 1, 0, 1, 1); - attach (memory_usage_grid (), 0, 0, 1); - attach (memory_chart, 1, 0, 1, 2); + attach (memory_name_label, 0, 0, 1, 1); + attach (memory_percentage_label, 0, 1, 1, 1); + // attach (memory_usage_grid (), 0, 0, 1); + attach (memory_chart, 0, 1, 1, 2); } @@ -70,7 +70,7 @@ public class Monitor.SystemMemoryView : Gtk.Grid { public void update () { - memory_percentage_label.set_text ((_("Memory: % 3d%%")).printf (memory.percentage)); + memory_percentage_label.set_text ((_("%d%%")).printf (memory.percentage)); memory_chart.update (0, memory.percentage); memory_total_label.set_text ((_("Total: %s")).printf (Utils.HumanUnitFormatter.double_bytes_to_human(memory.total))); diff --git a/src/Views/SystemView/SystemCPUChart.vala b/src/Widgets/Chart/Chart.vala similarity index 55% rename from src/Views/SystemView/SystemCPUChart.vala rename to src/Widgets/Chart/Chart.vala index 038e1e3c..7a173946 100644 --- a/src/Views/SystemView/SystemCPUChart.vala +++ b/src/Widgets/Chart/Chart.vala @@ -1,13 +1,8 @@ -public class Monitor.SystemCPUChart : Gtk.Box { - private LiveChart.Chart chart; +public class Monitor.Chart : Gtk.Box { + private LiveChart.Chart live_chart; private LiveChart.Config config; - // private Gee.ArrayList serie_list; - - construct { - // serie_list = new Gee.ArrayList (); - get_style_context ().add_class ("graph"); vexpand = true; @@ -28,42 +23,39 @@ public class Monitor.SystemCPUChart : Gtk.Box { left = -1 }; - chart = new LiveChart.Chart (config); - chart.expand = true; - chart.legend.visible = false; - chart.grid.visible = true; - chart.background.main_color = Gdk.RGBA () { + live_chart = new LiveChart.Chart (config); + live_chart.expand = true; + live_chart.legend.visible = false; + live_chart.grid.visible = true; + live_chart.background.main_color = Gdk.RGBA () { red= 1, green= 1, blue= 1, alpha= 1 }; //White background } - public SystemCPUChart (int cores_quantity) { - for (int i = 0; i < cores_quantity; i++) { + public Chart (int series_quantity) { + for (int i = 0; i < series_quantity; i++) { var renderer = new LiveChart.SmoothLineArea (new LiveChart.Values(1000)); var serie = new LiveChart.Serie ("Core x", renderer); serie.set_main_color ({ 0.35 + i/20, 0.8, 0.1, 1.0}); - chart.add_serie (serie); - // serie_list.add (serie); + live_chart.add_serie (serie); } - - add (chart); + add (live_chart); } public void update (int serie_number, double value) { - // debug("%f", value); - // chart.add_value (serie_list.get(serie_number), value); - chart.add_value_by_index (serie_number, value); + live_chart.add_value_by_index (serie_number, value); } - // public void set_data (Gee.ArrayList history) { + // public void set_data (int serie_number, Gee.ArrayList history) { // var refresh_rate_is_ms = 2000; //your own refresh rate in milliseconds - // chart.add_unaware_timestamp_collection(serie_list[0], history, refresh_rate_is_ms); + // live_chart.add_unaware_timestamp_collection(live_chart.series[serie_number], history, refresh_rate_is_ms); // } + public void clear () { - // var series = chart.series; - // foreach (var serie in serie_list) { + // var series = live_chart.series; + // foreach (var serie in series) { // serie.clear(); // } } diff --git a/src/Views/ProcessView/ProcessInfoView/Chart.vala b/src/Widgets/Chart/ProcessChart.vala similarity index 97% rename from src/Views/ProcessView/ProcessInfoView/Chart.vala rename to src/Widgets/Chart/ProcessChart.vala index 3e320b5e..3b88ad77 100644 --- a/src/Views/ProcessView/ProcessInfoView/Chart.vala +++ b/src/Widgets/Chart/ProcessChart.vala @@ -1,4 +1,4 @@ -public class Monitor.Chart : Gtk.Box { +public class Monitor.ProcessChart : Gtk.Box { private LiveChart.Serie serie; private LiveChart.SmoothLineArea renderer; private LiveChart.Chart chart; @@ -54,4 +54,4 @@ public class Monitor.Chart : Gtk.Box { public void clear () { serie.clear(); } -} +} \ No newline at end of file diff --git a/src/Widgets/Labels/LabelH4.vala b/src/Widgets/Labels/LabelH4.vala new file mode 100644 index 00000000..55f1560b --- /dev/null +++ b/src/Widgets/Labels/LabelH4.vala @@ -0,0 +1,14 @@ +class LabelH4 : Gtk.Label { + + construct { + get_style_context ().add_class ("h4"); + valign = Gtk.Align.START; + halign = Gtk.Align.START; + margin_start = 6; + ellipsize = Pango.EllipsizeMode.END; + } + + public LabelH4 (string label) { + Object (label: label); + } +} \ No newline at end of file diff --git a/src/Widgets/Labels/RoundyLabel.vala b/src/Widgets/Labels/LabelRoundy.vala similarity index 81% rename from src/Widgets/Labels/RoundyLabel.vala rename to src/Widgets/Labels/LabelRoundy.vala index a399279b..dd490cdd 100644 --- a/src/Widgets/Labels/RoundyLabel.vala +++ b/src/Widgets/Labels/LabelRoundy.vala @@ -1,9 +1,9 @@ -public class Monitor.RoundyLabel : Gtk.Fixed { +public class Monitor.LabelRoundy : Gtk.Fixed { public Gtk.Label val; public Gtk.Label desc; - public RoundyLabel (string description) { + public LabelRoundy (string description) { val = new Gtk.Label (Utils.NO_DATA); val.get_style_context ().add_class ("roundy-label"); diff --git a/src/Widgets/Labels/VerticalLabel.vala b/src/Widgets/Labels/LabelVertical.vala similarity index 86% rename from src/Widgets/Labels/VerticalLabel.vala rename to src/Widgets/Labels/LabelVertical.vala index 3de928b2..49eba170 100644 --- a/src/Widgets/Labels/VerticalLabel.vala +++ b/src/Widgets/Labels/LabelVertical.vala @@ -1,4 +1,4 @@ -public class Monitor.VerticalLabel : Gtk.Grid { +public class Monitor.LabelVertical : Gtk.Grid { public Gtk.Label val; public Gtk.Label desc; @@ -8,7 +8,7 @@ public class Monitor.VerticalLabel : Gtk.Grid { margin_top = 6; } - public VerticalLabel (string description) { + public LabelVertical (string description) { val = new Gtk.Label (Utils.NO_DATA); // val.get_style_context ().add_class ("h2"); From e12767f968bfd9ff47d18d528d7d425f4dd06d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Fri, 31 Jul 2020 00:16:05 +0200 Subject: [PATCH 07/45] remove patreon --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 24edbd7d..8b137891 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -patreon: stsdc + From 249343ff1098a0ac25f56ed0bc5b61e93f4eec94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Tue, 4 Aug 2020 00:34:14 +0200 Subject: [PATCH 08/45] beautify strings --- src/Resources/CPU.vala | 4 +- src/Utils.vala | 124 ++++++++++++++++++++++++++--------------- 2 files changed, 80 insertions(+), 48 deletions(-) diff --git a/src/Resources/CPU.vala b/src/Resources/CPU.vala index 3f40c573..eb17bab9 100644 --- a/src/Resources/CPU.vala +++ b/src/Resources/CPU.vala @@ -143,8 +143,6 @@ public class Monitor.CPU : Object { } } - debug("%s", result); - - return result; + return Utils.Strings.beautify (result); } } diff --git a/src/Utils.vala b/src/Utils.vala index 4d020acf..628dbaf9 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -1,54 +1,88 @@ namespace Monitor.Utils { - const string NOT_AVAILABLE = (_("N/A")); + const string NOT_AVAILABLE = (_ ("N/A")); const string NO_DATA = "\u2014"; } +public class Monitor.Utils.Strings { + // straight from elementary about-plug + + struct GraphicsReplaceStrings { + string regex; + string replacement; + } + + public static string beautify (string info) { + string pretty = GLib.Markup.escape_text (info).strip (); + + + const GraphicsReplaceStrings REPLACE_STRINGS[] = { + // { "Mesa DRI ", ""}, + { "[(]R[)]", "®"}, + { "[(]TM[)]", "™"}, + // { "Gallium .* on (AMD .*)", "\\1"}, + // { "(AMD .*) [(].*", "\\1"}, + // { "(AMD [A-Z])(.*)", "\\1\\L\\2\\E"}, + // { "Graphics Controller", "Graphics"}, + }; + + try { + foreach (GraphicsReplaceStrings replace_string in REPLACE_STRINGS) { + GLib.Regex re = new GLib.Regex (replace_string.regex, 0, 0); + pretty = re.replace (pretty, -1, 0, replace_string.replacement, 0); + } + } catch (Error e) { + critical ("Couldn't cleanup vendor string: %s", e.message); + } + + return pretty; + } +} + +/** + * Static helper class for unit formatting + * Author: Laurent Callarec @lcallarec + */ +public class Monitor.Utils.HumanUnitFormatter { + const string[] SIZE_UNITS = {"B", "KiB", "MiB", "GiB", "TiB"}; + const double KFACTOR = 1024; + /** - * Static helper class for unit formatting - * Author: Laurent Callarec @lcallarec + * format a string of bytes to an human readable format with units */ - public class Monitor.Utils.HumanUnitFormatter { - - const string[] SIZE_UNITS = {"B", "KiB", "MiB", "GiB", "TiB"}; - const double KFACTOR = 1024; - - /** - * format a string of bytes to an human readable format with units - */ - public static string string_bytes_to_human(string bytes) { - double current_size = double.parse(bytes); - string current_size_formatted = bytes.to_string() + HumanUnitFormatter.SIZE_UNITS[0]; - - for (int i = 0; i<= HumanUnitFormatter.SIZE_UNITS.length; i++) { - if (current_size < HumanUnitFormatter.KFACTOR) { - return GLib.Math.round(current_size).to_string() + HumanUnitFormatter.SIZE_UNITS[i]; - } - current_size = current_size / HumanUnitFormatter.KFACTOR; - } - - return current_size_formatted; - } - - public static string double_bytes_to_human(double bytes) { - string units = _ ("B"); - - // convert to MiB if needed - if (bytes > 1024.0) { - bytes /= 1024.0; - units = _ ("KiB"); - } - - // convert to GiB if needed - if (bytes > 1024.0) { - bytes /= 1024.0; - units = _ ("MiB"); - } + public static string string_bytes_to_human (string bytes) { + double current_size = double.parse (bytes); + string current_size_formatted = bytes.to_string () + HumanUnitFormatter.SIZE_UNITS[0]; - if (bytes > 1024.0) { - bytes /= 1024.0; - units = _ ("GiB"); + for (int i = 0; i<= HumanUnitFormatter.SIZE_UNITS.length; i++) { + if (current_size < HumanUnitFormatter.KFACTOR) { + return GLib.Math.round (current_size).to_string () + HumanUnitFormatter.SIZE_UNITS[i]; } + current_size = current_size / HumanUnitFormatter.KFACTOR; + } + + return current_size_formatted; + } + + public static string double_bytes_to_human (double bytes) { + string units = _ ("B"); - return "%.1f %s".printf (bytes, units); - } - } + // convert to MiB if needed + if (bytes > 1024.0) { + bytes /= 1024.0; + units = _ ("KiB"); + } + + // convert to GiB if needed + if (bytes > 1024.0) { + bytes /= 1024.0; + units = _ ("MiB"); + } + + if (bytes > 1024.0) { + bytes /= 1024.0; + units = _ ("GiB"); + } + + return "%.1f %s".printf (bytes, units); + } +} From 2b452906e3c253458ea976d6b84c677f74d3b5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Tue, 4 Aug 2020 18:56:56 +0200 Subject: [PATCH 09/45] use revealer to show more data --- src/Views/SystemView/SystemCPUView.vala | 55 +++++++++++++++++-------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index d3794449..77e006e5 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -3,11 +3,14 @@ public class Monitor.SystemCPUView : Gtk.Grid { private CPU cpu; private LabelVertical cpu_percentage_label; + private LabelRoundy cpu_frequency_label; private LabelH4 processor_name_label; private Gtk.Button view_threads_usage_button; - private Gee.ArrayList core_label_list; + private Gtk.Revealer cpu_threads_revealer; + + private Gee.ArrayList core_label_list; construct { margin = 12; @@ -15,7 +18,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { column_spacing = 12; set_vexpand (false); - core_label_list = new Gee.ArrayList (); + core_label_list = new Gee.ArrayList (); } @@ -24,6 +27,8 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu = _cpu; cpu_percentage_label = new LabelVertical (_("UTILIZATION")); + // cpu_percentage_label.valign = Gtk.Align.CENTER; + cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); // cpu_percentage_label.get_style_context ().add_class ("h3"); // cpu_percentage_label.valign = Gtk.Align.START; // cpu_percentage_label.halign = Gtk.Align.START; @@ -34,13 +39,18 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu_chart = new Chart (cpu.core_list.size); - view_threads_usage_button = new Gtk.Button (); + view_threads_usage_button = new Gtk.Button.with_label (">>"); view_threads_usage_button.has_tooltip = true; - view_threads_usage_button.tooltip_text = (_("Settings")); - var icon = new Gtk.Image (); - icon.gicon = new ThemedIcon ("view-more-horizontal-symbolic"); - icon.pixel_size = 16; - view_threads_usage_button.set_image (icon); + view_threads_usage_button.tooltip_text = (_("View more")); + view_threads_usage_button.valign = Gtk.Align.CENTER; + // var icon = new Gtk.Image (); + // icon.gicon = new ThemedIcon ("view-more-horizontal-symbolic"); + // icon.pixel_size = 16; + // view_threads_usage_button.set_image (icon); + + view_threads_usage_button.clicked.connect(() => { + cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); + }); // attach (grid_core_labels (), 0, 0, 1, 1); // attach (grid_info_labels (), 0, 0, 1, 1); @@ -58,15 +68,16 @@ public class Monitor.SystemCPUView : Gtk.Grid { double core_percentage = cpu.core_list[i].percentage_used; cpu_chart.update(i, core_percentage); string percentage_formatted = ("% 3d%%").printf ( (int)core_percentage); - // core_label_list[i].set_text (_("Thread %d: %s").printf (i, percentage_formatted)); + core_label_list[i].set_text (percentage_formatted); } cpu_percentage_label.set_text ((_("%d%%")).printf (cpu.percentage)); + cpu_frequency_label.set_text (("%.2f %s").printf (cpu.frequency, _ ("GHz"))); } private Gtk.Grid grid_info_labels () { Gtk.Grid grid = new Gtk.Grid (); - grid.column_spacing = 12; + // grid.column_spacing = 12; grid.attach(processor_name_label, 0, 0, 1, 1); grid.attach(cpu_percentage_label, 0, 1, 1, 1); @@ -75,24 +86,31 @@ public class Monitor.SystemCPUView : Gtk.Grid { } private Gtk.Grid grid_usage_labels () { + Gtk.Grid grid = new Gtk.Grid (); - grid.column_spacing = 12; + grid.column_spacing = 0; grid.attach(cpu_percentage_label, 0, 0, 1, 1); - // grid.attach(view_threads_usage_button, 1, 0, 1, 1); + grid.attach(view_threads_usage_button, 2, 0, 1, 1); + grid.attach(grid_core_labels(), 1, 0, 1, 1); return grid; } - private Gtk.Grid grid_core_labels () { + private Gtk.Revealer grid_core_labels () { + cpu_threads_revealer = new Gtk.Revealer(); + cpu_threads_revealer.margin = 6; + cpu_threads_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT; + cpu_threads_revealer.valign = Gtk.Align.CENTER; + Gtk.Grid grid = new Gtk.Grid (); - grid.column_spacing = 12; - grid.width_request = 300; + grid.column_spacing = 8; + grid.row_spacing = 4; int column = 0; int row = 0; for (int i = 0; i < cpu.core_list.size; i++) { - var core_label = new Gtk.Label(_("Thread %d: ").printf (i) + Utils.NO_DATA); - core_label.halign = Gtk.Align.START; + var core_label = new LabelRoundy(_("Thread %d").printf (i)); + core_label.set_text (Utils.NO_DATA); core_label_list.add (core_label); grid.attach(core_label, column, row, 1, 1); @@ -103,7 +121,8 @@ public class Monitor.SystemCPUView : Gtk.Grid { column = 0; } } + cpu_threads_revealer.add (grid); - return grid; + return cpu_threads_revealer; } } \ No newline at end of file From 8e0f1ada02cc0377a466eb2a1c7ba6bb756a769d Mon Sep 17 00:00:00 2001 From: stsdc Date: Tue, 4 Aug 2020 23:54:43 +0200 Subject: [PATCH 10/45] add columns, not rows --- src/Views/SystemView/SystemCPUView.vala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 77e006e5..67ea3b33 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -115,10 +115,10 @@ public class Monitor.SystemCPUView : Gtk.Grid { grid.attach(core_label, column, row, 1, 1); - column++; - if (column > 1) { - row++; - column = 0; + row++; + if (row > 1) { + column++; + row = 0; } } cpu_threads_revealer.add (grid); From 36008a179834a32afbb42b770fb320c4ca5ec1a4 Mon Sep 17 00:00:00 2001 From: stsdc Date: Wed, 5 Aug 2020 00:31:33 +0200 Subject: [PATCH 11/45] add core badge styles --- data/Application.css | 29 +++++++++++++++++++++++++ src/Views/SystemView/SystemCPUView.vala | 9 ++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/data/Application.css b/data/Application.css index a7d66c05..356d2fb6 100644 --- a/data/Application.css +++ b/data/Application.css @@ -58,6 +58,35 @@ border-width: 0; } +.core_badge { + background-color: @SILVER_100; + border-radius: 8px; + padding-right: 4px; + padding-left:2px; + font-size: 10px; + font-weight:bold; + color: @SILVER_900; + border: 1px solid @SILVER_300; +} + +.core_badge-mild-warning { + background-color: @SBANANA_100; + color: @BANANA_900; + border: 1px solid @BANANA_300; +} + +.core_badge-strong-warning { + background-color: @ORANGE_100; + color: @ORANGE_900; + border: 1px solid @ORANGE_300; +} + +.core_badge-critical-warning { + background-color: @STRAWBERRY_100; + color: @STRAWBERRY_700; + border: 1px solid @STRAWBERRY_300; +} + .command_wrapper { background-color: #fdf6e3; border-radius: 3px; diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 67ea3b33..d5cd724f 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -10,7 +10,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { private Gtk.Revealer cpu_threads_revealer; - private Gee.ArrayList core_label_list; + private Gee.ArrayList core_label_list; construct { margin = 12; @@ -18,7 +18,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { column_spacing = 12; set_vexpand (false); - core_label_list = new Gee.ArrayList (); + core_label_list = new Gee.ArrayList (); } @@ -109,8 +109,9 @@ public class Monitor.SystemCPUView : Gtk.Grid { int column = 0; int row = 0; for (int i = 0; i < cpu.core_list.size; i++) { - var core_label = new LabelRoundy(_("Thread %d").printf (i)); - core_label.set_text (Utils.NO_DATA); + var core_label = new Gtk.Label (Utils.NO_DATA); + core_label.get_style_context ().add_class ("core_badge"); + // core_label.set_text (Utils.NO_DATA); core_label_list.add (core_label); grid.attach(core_label, column, row, 1, 1); From 7feb3cf03db456ae376cf49956dbcc6db34ce73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 5 Aug 2020 18:54:19 +0200 Subject: [PATCH 12/45] reveal additional info clicking on utilization label --- data/Application.css | 2 +- src/Views/SystemView/SystemCPUView.vala | 30 +++++-------------------- src/Widgets/Labels/LabelVertical.vala | 27 ++++++++++++++++------ 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/data/Application.css b/data/Application.css index 356d2fb6..3872a3b7 100644 --- a/data/Application.css +++ b/data/Application.css @@ -20,7 +20,7 @@ .vertical-label:selected:focus, .vertical-label:hover:selected { color: alpha(@text_color, 1); - font-size: 28px; + font-size: 30px; font-weight: 100; /* padding: 0 6px; margin: 0 3px; */ diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index d5cd724f..02df08d7 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -27,39 +27,18 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu = _cpu; cpu_percentage_label = new LabelVertical (_("UTILIZATION")); - // cpu_percentage_label.valign = Gtk.Align.CENTER; cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); - // cpu_percentage_label.get_style_context ().add_class ("h3"); - // cpu_percentage_label.valign = Gtk.Align.START; - // cpu_percentage_label.halign = Gtk.Align.START; - // cpu_percentage_label.margin_start = 12; - // cpu_percentage_label.margin_top = 6; - processor_name_label = new LabelH4 (cpu.cpu_name); cpu_chart = new Chart (cpu.core_list.size); - view_threads_usage_button = new Gtk.Button.with_label (">>"); - view_threads_usage_button.has_tooltip = true; - view_threads_usage_button.tooltip_text = (_("View more")); - view_threads_usage_button.valign = Gtk.Align.CENTER; - // var icon = new Gtk.Image (); - // icon.gicon = new ThemedIcon ("view-more-horizontal-symbolic"); - // icon.pixel_size = 16; - // view_threads_usage_button.set_image (icon); - - view_threads_usage_button.clicked.connect(() => { + cpu_percentage_label.clicked.connect(() => { cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); }); - // attach (grid_core_labels (), 0, 0, 1, 1); - // attach (grid_info_labels (), 0, 0, 1, 1); attach (processor_name_label, 0, 0, 1, 1); attach (grid_usage_labels(), 0, 1, 1, 1); - // attach (view_threads_usage_button, 1, 1, 1, 1); - // attach (processor_name_label, 0, 0, 1, 1); attach (cpu_chart, 0, 1, 1, 1); - } @@ -77,7 +56,6 @@ public class Monitor.SystemCPUView : Gtk.Grid { private Gtk.Grid grid_info_labels () { Gtk.Grid grid = new Gtk.Grid (); - // grid.column_spacing = 12; grid.attach(processor_name_label, 0, 0, 1, 1); grid.attach(cpu_percentage_label, 0, 1, 1, 1); @@ -88,7 +66,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { private Gtk.Grid grid_usage_labels () { Gtk.Grid grid = new Gtk.Grid (); - grid.column_spacing = 0; + grid.column_spacing = 6; grid.attach(cpu_percentage_label, 0, 0, 1, 1); grid.attach(view_threads_usage_button, 2, 0, 1, 1); @@ -124,6 +102,10 @@ public class Monitor.SystemCPUView : Gtk.Grid { } cpu_threads_revealer.add (grid); + var threads_label = new Gtk.Label ("THREADS"); + threads_label.get_style_context ().add_class ("small-text"); + grid.attach(threads_label, 0, -1, column, 1); + return cpu_threads_revealer; } } \ No newline at end of file diff --git a/src/Widgets/Labels/LabelVertical.vala b/src/Widgets/Labels/LabelVertical.vala index 49eba170..ceaecbd8 100644 --- a/src/Widgets/Labels/LabelVertical.vala +++ b/src/Widgets/Labels/LabelVertical.vala @@ -1,25 +1,38 @@ -public class Monitor.LabelVertical : Gtk.Grid { +public class Monitor.LabelVertical : Gtk.EventBox { + + private Gtk.Grid grid; + + public signal void clicked (); public Gtk.Label val; public Gtk.Label desc; construct { - margin_start = 12; - margin_top = 6; + grid = new Gtk.Grid (); + grid.margin_start = 12; + grid.margin_top = 6; } public LabelVertical (string description) { val = new Gtk.Label (Utils.NO_DATA); - // val.get_style_context ().add_class ("h2"); val.get_style_context ().add_class ("vertical-label"); desc = new Gtk.Label (description); - // desc.get_style_context ().add_class ("h4"); desc.get_style_context ().add_class ("small-text"); - attach(desc, 0, 0, 1, 1); - attach(val, 0, 1, 1, 1); + grid.attach(desc, 0, 0, 1, 1); + grid.attach(val, 0, 1, 1, 1); + + add (grid); + + events |= Gdk.EventMask.BUTTON_RELEASE_MASK; + + button_release_event.connect ((event) => { + clicked (); + return false; + }); + } public void set_text (string text) { From d1871e111b9392273236aa1fab40c7993da72cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 5 Aug 2020 19:25:41 +0200 Subject: [PATCH 13/45] core labels not bold --- data/Application.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Application.css b/data/Application.css index 3872a3b7..e163793c 100644 --- a/data/Application.css +++ b/data/Application.css @@ -64,8 +64,8 @@ padding-right: 4px; padding-left:2px; font-size: 10px; - font-weight:bold; - color: @SILVER_900; + /* font-weight:bold; */ + color: black; border: 1px solid @SILVER_300; } From af464ac8bedf5b73bbe0e8bc50c4b707af021d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 5 Aug 2020 19:26:06 +0200 Subject: [PATCH 14/45] memory info in revealer --- src/Views/SystemView/SystemCPUView.vala | 1 - src/Views/SystemView/SystemMemoryView.vala | 25 +++++++++++++++++----- src/Widgets/Labels/LabelVertical.vala | 2 ++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 02df08d7..cbb6cea9 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -69,7 +69,6 @@ public class Monitor.SystemCPUView : Gtk.Grid { grid.column_spacing = 6; grid.attach(cpu_percentage_label, 0, 0, 1, 1); - grid.attach(view_threads_usage_button, 2, 0, 1, 1); grid.attach(grid_core_labels(), 1, 0, 1, 1); return grid; diff --git a/src/Views/SystemView/SystemMemoryView.vala b/src/Views/SystemView/SystemMemoryView.vala index f2c0647d..00a26eb1 100644 --- a/src/Views/SystemView/SystemMemoryView.vala +++ b/src/Views/SystemView/SystemMemoryView.vala @@ -10,6 +10,7 @@ public class Monitor.SystemMemoryView : Gtk.Grid { private Gtk.Label memory_locked_label; private Gtk.Label memory_total_label; private Gtk.Label memory_used_label; + private Gtk.Revealer memory_usage_revealer; construct { margin = 12; @@ -26,6 +27,10 @@ public class Monitor.SystemMemoryView : Gtk.Grid { memory_percentage_label = new LabelVertical (_("UTILIZATION")); + memory_percentage_label.clicked.connect(() => { + memory_usage_revealer.reveal_child = !(memory_usage_revealer.child_revealed); + }); + memory_total_label = new Gtk.Label (_("Total: ") + Utils.NO_DATA); memory_total_label.halign = Gtk.Align.START; @@ -46,14 +51,22 @@ public class Monitor.SystemMemoryView : Gtk.Grid { memory_chart = new Chart (1); + var lil_gridy = new Gtk.Grid (); + lil_gridy.attach (memory_percentage_label, 0, 0, 1, 1); + lil_gridy.attach (memory_usage_grid (), 1, 0, 1, 1); + attach (memory_name_label, 0, 0, 1, 1); - attach (memory_percentage_label, 0, 1, 1, 1); - // attach (memory_usage_grid (), 0, 0, 1); - attach (memory_chart, 0, 1, 1, 2); + attach (lil_gridy, 0, 1, 1, 1); + attach (memory_chart, 0, 1, 2, 2); } - private Gtk.Grid memory_usage_grid () { + private Gtk.Revealer memory_usage_grid () { + memory_usage_revealer = new Gtk.Revealer(); + memory_usage_revealer.margin = 6; + memory_usage_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT; + memory_usage_revealer.valign = Gtk.Align.CENTER; + Gtk.Grid grid = new Gtk.Grid (); grid.column_spacing = 12; grid.width_request = 300; @@ -65,7 +78,9 @@ public class Monitor.SystemMemoryView : Gtk.Grid { grid.attach (memory_cached_label, 0, 2, 1, 1); grid.attach (memory_locked_label, 1, 2, 1, 1); - return grid; + memory_usage_revealer.add (grid); + + return memory_usage_revealer; } diff --git a/src/Widgets/Labels/LabelVertical.vala b/src/Widgets/Labels/LabelVertical.vala index ceaecbd8..49ec8283 100644 --- a/src/Widgets/Labels/LabelVertical.vala +++ b/src/Widgets/Labels/LabelVertical.vala @@ -11,6 +11,8 @@ public class Monitor.LabelVertical : Gtk.EventBox { grid = new Gtk.Grid (); grid.margin_start = 12; grid.margin_top = 6; + + get_style_context ().add_class (Gtk.STYLE_CLASS_CURSOR_HANDLE); } public LabelVertical (string description) { From 1412d40ada6b17573bdda231faf944fc6f4c17a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 5 Aug 2020 19:44:40 +0200 Subject: [PATCH 15/45] change colour of core badge if utilization is high --- data/Application.css | 2 +- src/Views/SystemView/SystemCPUView.vala | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/data/Application.css b/data/Application.css index e163793c..c1e15d04 100644 --- a/data/Application.css +++ b/data/Application.css @@ -70,7 +70,7 @@ } .core_badge-mild-warning { - background-color: @SBANANA_100; + background-color: @BANANA_100; color: @BANANA_900; border: 1px solid @BANANA_300; } diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index cbb6cea9..92914157 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -48,6 +48,19 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu_chart.update(i, core_percentage); string percentage_formatted = ("% 3d%%").printf ( (int)core_percentage); core_label_list[i].set_text (percentage_formatted); + + if (core_percentage > 75.0) { + core_label_list[i].get_style_context ().add_class ("core_badge-mild-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-strong-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-critical-warning"); + } + if (core_percentage > 85.0) { + core_label_list[i].get_style_context ().add_class ("core_badge-strong-warning"); + } + + if (core_percentage > 90.0) { + core_label_list[i].get_style_context ().add_class ("core_badge-critical-warning"); + } } cpu_percentage_label.set_text ((_("%d%%")).printf (cpu.percentage)); From 5cda2ff387a3f87ca61562dc3e7b6d7e0a78f9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 5 Aug 2020 20:00:39 +0200 Subject: [PATCH 16/45] better handling class add/remove for core badges --- src/Views/SystemView/SystemCPUView.vala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 92914157..b1d59efe 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -49,6 +49,11 @@ public class Monitor.SystemCPUView : Gtk.Grid { string percentage_formatted = ("% 3d%%").printf ( (int)core_percentage); core_label_list[i].set_text (percentage_formatted); + core_label_list[i].get_style_context ().remove_class ("core_badge-mild-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-strong-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-critical-warning"); + + if (core_percentage > 75.0) { core_label_list[i].get_style_context ().add_class ("core_badge-mild-warning"); core_label_list[i].get_style_context ().remove_class ("core_badge-strong-warning"); @@ -56,10 +61,14 @@ public class Monitor.SystemCPUView : Gtk.Grid { } if (core_percentage > 85.0) { core_label_list[i].get_style_context ().add_class ("core_badge-strong-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-mild-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-critical-warning"); } if (core_percentage > 90.0) { core_label_list[i].get_style_context ().add_class ("core_badge-critical-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-mild-warning"); + core_label_list[i].get_style_context ().remove_class ("core_badge-strong-warning"); } } From 496c29d7ffa206022555f7f3d31e4e3272c67119 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sat, 8 Aug 2020 22:01:16 +0200 Subject: [PATCH 17/45] make it a little more obvious, that you can click on a label --- data/Application.css | 16 +++++++++++++++- src/Views/SystemView/SystemCPUView.vala | 12 ++++++++++++ src/Views/SystemView/SystemMemoryView.vala | 12 ++++++++++++ src/Widgets/Labels/LabelVertical.vala | 8 ++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/data/Application.css b/data/Application.css index c1e15d04..74f90a78 100644 --- a/data/Application.css +++ b/data/Application.css @@ -14,11 +14,19 @@ border-width: 0; } -.vertical-label, +/* .vertical-label, .vertical-label:hover, .vertical-label:selected, .vertical-label:selected:focus, .vertical-label:hover:selected { + +} */ + +.label-vertical { + +} + +.label-vertical-val { color: alpha(@text_color, 1); font-size: 30px; font-weight: 100; @@ -27,6 +35,12 @@ border-width: 0; } +.usage-label-container { + border: 1px solid @SILVER_300;; + border-radius: 3px; + background-color: alpha(@SILVER_100, 0.5); + } + .username-current { background-color: @SILVER_300; color: @SILVER_900; diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index b1d59efe..d42cc4e7 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -27,6 +27,8 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu = _cpu; cpu_percentage_label = new LabelVertical (_("UTILIZATION")); + cpu_percentage_label.has_tooltip = true; + cpu_percentage_label.tooltip_text = (_("Show detailed info")); cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); processor_name_label = new LabelH4 (cpu.cpu_name); @@ -34,6 +36,12 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu_percentage_label.clicked.connect(() => { cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); + + if (cpu_threads_revealer.child_revealed) { + cpu_percentage_label.tooltip_text = (_("Show detailed info")); + } else { + cpu_percentage_label.tooltip_text = (_("Hide detailed info")); + } }); attach (processor_name_label, 0, 0, 1, 1); @@ -89,6 +97,10 @@ public class Monitor.SystemCPUView : Gtk.Grid { Gtk.Grid grid = new Gtk.Grid (); grid.column_spacing = 6; + grid.margin = 6; + grid.valign = Gtk.Align.START; + grid.halign = Gtk.Align.START; + grid.get_style_context ().add_class ("usage-label-container"); grid.attach(cpu_percentage_label, 0, 0, 1, 1); grid.attach(grid_core_labels(), 1, 0, 1, 1); diff --git a/src/Views/SystemView/SystemMemoryView.vala b/src/Views/SystemView/SystemMemoryView.vala index 00a26eb1..8c08ad94 100644 --- a/src/Views/SystemView/SystemMemoryView.vala +++ b/src/Views/SystemView/SystemMemoryView.vala @@ -26,9 +26,16 @@ public class Monitor.SystemMemoryView : Gtk.Grid { memory_name_label = new LabelH4 (_("Memory")); memory_percentage_label = new LabelVertical (_("UTILIZATION")); + memory_percentage_label.has_tooltip = true; + memory_percentage_label.tooltip_text = (_("Show detailed info")); memory_percentage_label.clicked.connect(() => { memory_usage_revealer.reveal_child = !(memory_usage_revealer.child_revealed); + if (memory_usage_revealer.child_revealed) { + memory_percentage_label.tooltip_text = (_("Show detailed info")); + } else { + memory_percentage_label.tooltip_text = (_("Hide detailed info")); + } }); memory_total_label = new Gtk.Label (_("Total: ") + Utils.NO_DATA); @@ -52,6 +59,11 @@ public class Monitor.SystemMemoryView : Gtk.Grid { memory_chart = new Chart (1); var lil_gridy = new Gtk.Grid (); + lil_gridy.margin = 6; + lil_gridy.column_spacing = 6; + lil_gridy.valign = Gtk.Align.START; + lil_gridy.halign = Gtk.Align.START; + lil_gridy.get_style_context ().add_class ("usage-label-container"); lil_gridy.attach (memory_percentage_label, 0, 0, 1, 1); lil_gridy.attach (memory_usage_grid (), 1, 0, 1, 1); diff --git a/src/Widgets/Labels/LabelVertical.vala b/src/Widgets/Labels/LabelVertical.vala index 49ec8283..f7fa2546 100644 --- a/src/Widgets/Labels/LabelVertical.vala +++ b/src/Widgets/Labels/LabelVertical.vala @@ -9,16 +9,16 @@ public class Monitor.LabelVertical : Gtk.EventBox { construct { grid = new Gtk.Grid (); - grid.margin_start = 12; - grid.margin_top = 6; + margin_start = 12; + margin_top = 6; - get_style_context ().add_class (Gtk.STYLE_CLASS_CURSOR_HANDLE); + get_style_context ().add_class ("label-vertical"); } public LabelVertical (string description) { val = new Gtk.Label (Utils.NO_DATA); - val.get_style_context ().add_class ("vertical-label"); + val.get_style_context ().add_class ("label-vertical-val"); desc = new Gtk.Label (description); desc.get_style_context ().add_class ("small-text"); From 16f99cf9b103aedd37eae4b5a1bdd668af86f3d0 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 9 Aug 2020 23:44:13 +0200 Subject: [PATCH 18/45] add cpu info button --- src/Views/SystemView/SystemCPUView.vala | 35 ++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index d42cc4e7..577c8e02 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -30,8 +30,41 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu_percentage_label.has_tooltip = true; cpu_percentage_label.tooltip_text = (_("Show detailed info")); cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); + processor_name_label = new LabelH4 (cpu.cpu_name); + var processor_info_button = new Gtk.ToggleButton (); + processor_info_button.get_style_context ().add_class ("circular"); + // processor_info_button.get_style_context ().add_class ("popup"); + processor_info_button.has_focus = false; + var icon = new Gtk.Image (); + icon.gicon = new ThemedIcon ("dialog-information"); + icon.pixel_size = 16; + processor_info_button.set_image (icon); + processor_info_button.valign = Gtk.Align.START; + processor_info_button.halign = Gtk.Align.START; + + + + var title_grid = new Gtk.Grid (); + title_grid.attach (processor_name_label, 0, 0, 1, 1); + title_grid.attach (processor_info_button, 1, 0, 1, 1); + title_grid.column_spacing = 6; + + var popover = new Gtk.Popover (processor_info_button); + var box2 = new Gtk.Box(Gtk.Orientation.VERTICAL, 5); + popover.add(box2); + var label = new Gtk.Label("A Label Widget"); + box2.add(label); + var checkbutton = new Gtk.CheckButton.with_label("A CheckButton Widget"); + box2.add(checkbutton); + var radiobutton = new Gtk.RadioButton.with_label(null, "A RadioButton Widget"); + box2.add(radiobutton); + + processor_info_button.clicked.connect(() => { + popover.show_all(); + }); + cpu_chart = new Chart (cpu.core_list.size); cpu_percentage_label.clicked.connect(() => { @@ -44,7 +77,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { } }); - attach (processor_name_label, 0, 0, 1, 1); + attach (title_grid, 0, 0, 1, 1); attach (grid_usage_labels(), 0, 1, 1, 1); attach (cpu_chart, 0, 1, 1, 1); } From 0655c7e5d16b7aba0d62cf0f6efbdf16bf0d579a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Mon, 10 Aug 2020 18:33:52 +0200 Subject: [PATCH 19/45] adds popover with other cpu info --- meson.build | 1 + src/Resources/CPU.vala | 37 ++++++++++++- .../SystemView/SystemCPUInfoPopover.vala | 52 +++++++++++++++++++ src/Views/SystemView/SystemCPUView.vala | 14 ++--- 4 files changed, 91 insertions(+), 13 deletions(-) create mode 100644 src/Views/SystemView/SystemCPUInfoPopover.vala diff --git a/meson.build b/meson.build index 249087f0..c40e772c 100644 --- a/meson.build +++ b/meson.build @@ -68,6 +68,7 @@ executable( 'src/Views/SystemView/SystemView.vala', 'src/Views/SystemView/SystemCPUView.vala', + 'src/Views/SystemView/SystemCPUInfoPopover.vala', 'src/Views/SystemView/SystemMemoryView.vala', # Widgets related only to ProcessInfoView diff --git a/src/Resources/CPU.vala b/src/Resources/CPU.vala index eb17bab9..895dc875 100644 --- a/src/Resources/CPU.vala +++ b/src/Resources/CPU.vala @@ -3,7 +3,15 @@ public class Monitor.CPU : Object { private float last_total; private float load; - public string? cpu_name; + public string? model_name; + public string? model; + public string? family; + public string? microcode; + public string? cache_size; + public string? flags; + public string? bogomips; + public string? bugs; + public string? address_sizes; GTop.Cpu ? cpu; @@ -29,7 +37,9 @@ public class Monitor.CPU : Object { core_list = new Gee.ArrayList (); - cpu_name = get_cpu_info (); + model_name = get_cpu_info (); + + parse_cpuinfo (); debug ("Number of cores: %d", (int) get_num_processors ()); for (int i = 0; i < (int) get_num_processors (); i++) { @@ -87,6 +97,29 @@ public class Monitor.CPU : Object { _frequency = (double)maxcur; } + private void parse_cpuinfo () { + unowned GTop.SysInfo? info = GTop.glibtop_get_sysinfo (); + + if (info == null) { + warning ("No CPU info"); + return; + } + + // let core 0 represents whole processor + // TODO: parse all the values to corresponding core objects in core_list + // does it even makes sense?? + + unowned GLib.HashTable values = info.cpuinfo[0].values; + model = values["model"]; + family = values["cpu family"]; + microcode = values["microcode"]; + cache_size = values["cache size"]; + flags = values["flags"]; + bogomips = values["bogomips"]; + bugs = values["bugs"]; + address_sizes = values["address sizes"]; + } + // straight from elementary about-plug private string? get_cpu_info () { unowned GTop.SysInfo? info = GTop.glibtop_get_sysinfo (); diff --git a/src/Views/SystemView/SystemCPUInfoPopover.vala b/src/Views/SystemView/SystemCPUInfoPopover.vala new file mode 100644 index 00000000..8e096242 --- /dev/null +++ b/src/Views/SystemView/SystemCPUInfoPopover.vala @@ -0,0 +1,52 @@ +public class Monitor.SystemCPUInfoPopover : Gtk.Popover { + private Gtk.Grid grid; + + private CPU cpu; + + construct { + grid = new Gtk.Grid (); + grid.margin = 12; + grid.column_spacing = 6; + + grid.attach (label(_("Model")), 0, 0, 1, 1); + grid.attach (label(_("Family")), 0, 1, 1, 1); + grid.attach (label(_("Microcode ver.")), 0, 2, 1, 1); + grid.attach (label(_("Bogomips")), 0, 3, 1, 1); + grid.attach (label(_("Cache size")), 0, 4, 1, 1); + grid.attach (label(_("Address sizes")), 0, 5, 1, 1); + grid.attach (label(_("Flags")), 0, 6, 1, 1); + grid.attach (label(_("Bugs")), 0, 7, 1, 1); + + for (int i; i <= 7; i++) { + grid.attach ( label (":"), 1, i, 1, 1); + } + + add (grid); + } + + + public SystemCPUInfoPopover(Gtk.Widget? relative_to, CPU _cpu) { + Object (relative_to : relative_to); + + cpu = _cpu; + + grid.attach (label(cpu.model), 2, 0, 1, 1); + grid.attach (label(cpu.family), 2, 1, 1, 1); + grid.attach (label(cpu.microcode), 2, 2, 1, 1); + grid.attach (label(cpu.bogomips), 2, 3, 1, 1); + grid.attach (label(cpu.cache_size), 2, 4, 1, 1); + grid.attach (label(cpu.address_sizes), 2, 5, 1, 1); + grid.attach (label(cpu.flags), 2, 6, 1, 1); + grid.attach (label(cpu.bugs), 2, 7, 1, 1); + } + + private Gtk.Label label(string text) { + var label = new Gtk.Label (text); + label.halign = Gtk.Align.START; + label.valign = Gtk.Align.START; + label.wrap = true; + label.max_width_chars = 80; + + return label; + } +} \ No newline at end of file diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 577c8e02..dbb4d4fa 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -31,7 +31,7 @@ public class Monitor.SystemCPUView : Gtk.Grid { cpu_percentage_label.tooltip_text = (_("Show detailed info")); cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); - processor_name_label = new LabelH4 (cpu.cpu_name); + processor_name_label = new LabelH4 (cpu.model_name); var processor_info_button = new Gtk.ToggleButton (); processor_info_button.get_style_context ().add_class ("circular"); @@ -51,16 +51,8 @@ public class Monitor.SystemCPUView : Gtk.Grid { title_grid.attach (processor_info_button, 1, 0, 1, 1); title_grid.column_spacing = 6; - var popover = new Gtk.Popover (processor_info_button); - var box2 = new Gtk.Box(Gtk.Orientation.VERTICAL, 5); - popover.add(box2); - var label = new Gtk.Label("A Label Widget"); - box2.add(label); - var checkbutton = new Gtk.CheckButton.with_label("A CheckButton Widget"); - box2.add(checkbutton); - var radiobutton = new Gtk.RadioButton.with_label(null, "A RadioButton Widget"); - box2.add(radiobutton); - + var popover = new SystemCPUInfoPopover (processor_info_button, cpu); + processor_info_button.clicked.connect(() => { popover.show_all(); }); From 426c850dba96aa14d6bae12cb38071f8acfb6690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Mon, 10 Aug 2020 18:42:16 +0200 Subject: [PATCH 20/45] untoggle the button when popover is closed --- src/Views/SystemView/SystemCPUView.vala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index dbb4d4fa..2bfb6152 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -52,6 +52,9 @@ public class Monitor.SystemCPUView : Gtk.Grid { title_grid.column_spacing = 6; var popover = new SystemCPUInfoPopover (processor_info_button, cpu); + popover.closed.connect (() => { + processor_info_button.set_active(false); + }); processor_info_button.clicked.connect(() => { popover.show_all(); From a610a62d1ce1eb27945386ac546af81d6d6bf4ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Mon, 10 Aug 2020 18:44:05 +0200 Subject: [PATCH 21/45] move closed signal to the class itself --- src/Views/SystemView/SystemCPUInfoPopover.vala | 4 +++- src/Views/SystemView/SystemCPUView.vala | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Views/SystemView/SystemCPUInfoPopover.vala b/src/Views/SystemView/SystemCPUInfoPopover.vala index 8e096242..3fa74028 100644 --- a/src/Views/SystemView/SystemCPUInfoPopover.vala +++ b/src/Views/SystemView/SystemCPUInfoPopover.vala @@ -25,9 +25,11 @@ public class Monitor.SystemCPUInfoPopover : Gtk.Popover { } - public SystemCPUInfoPopover(Gtk.Widget? relative_to, CPU _cpu) { + public SystemCPUInfoPopover(Gtk.ToggleButton? relative_to, CPU _cpu) { Object (relative_to : relative_to); + closed.connect (() => { relative_to.set_active(false); }); + cpu = _cpu; grid.attach (label(cpu.model), 2, 0, 1, 1); diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 2bfb6152..dbb4d4fa 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -52,9 +52,6 @@ public class Monitor.SystemCPUView : Gtk.Grid { title_grid.column_spacing = 6; var popover = new SystemCPUInfoPopover (processor_info_button, cpu); - popover.closed.connect (() => { - processor_info_button.set_active(false); - }); processor_info_button.clicked.connect(() => { popover.show_all(); From a3e1c62bff4563762d0dce048a8ae713e718beac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 12 Aug 2020 00:07:33 +0200 Subject: [PATCH 22/45] fix gee_collection_get_size: assertion 'self != NULL' failed --- src/Widgets/Chart/Chart.vala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Widgets/Chart/Chart.vala b/src/Widgets/Chart/Chart.vala index 7a173946..f654516b 100644 --- a/src/Widgets/Chart/Chart.vala +++ b/src/Widgets/Chart/Chart.vala @@ -36,14 +36,19 @@ public class Monitor.Chart : Gtk.Box { public Chart (int series_quantity) { for (int i = 0; i < series_quantity; i++) { var renderer = new LiveChart.SmoothLineArea (new LiveChart.Values(1000)); - var serie = new LiveChart.Serie ("Core x", renderer); + var serie = new LiveChart.Serie (("Serie %d").printf(i), renderer); serie.set_main_color ({ 0.35 + i/20, 0.8, 0.1, 1.0}); live_chart.add_serie (serie); + + // workaround for `gee_collection_get_size: assertion 'self != NULL' failed` + // https://github.com/lcallarec/live-chart/issues/16 + live_chart.add_value (serie, 0); } add (live_chart); } public void update (int serie_number, double value) { + debug ("update called"); live_chart.add_value_by_index (serie_number, value); } From 511b7fbb77a04553942b70ee0ea47394bb0702e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Wed, 12 Aug 2020 19:43:46 +0200 Subject: [PATCH 23/45] wip layout --- src/Views/SystemView/SystemCPUView.vala | 42 ++++++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index dbb4d4fa..edf46939 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -1,5 +1,7 @@ -public class Monitor.SystemCPUView : Gtk.Grid { - private Chart cpu_chart; +public class Monitor.SystemCPUView : Gtk.Box { + private Chart cpu_utilization_chart; + private Chart cpu_frequency_chart; + private Chart cpu_temperature_chart; private CPU cpu; private LabelVertical cpu_percentage_label; @@ -15,8 +17,9 @@ public class Monitor.SystemCPUView : Gtk.Grid { construct { margin = 12; margin_top = 6; - column_spacing = 12; - set_vexpand (false); + // column_spacing = 12; + // set_vexpand (false); + // orintantation = Gtk.Orientation.VERTICAL; core_label_list = new Gee.ArrayList (); } @@ -53,11 +56,11 @@ public class Monitor.SystemCPUView : Gtk.Grid { var popover = new SystemCPUInfoPopover (processor_info_button, cpu); - processor_info_button.clicked.connect(() => { - popover.show_all(); - }); + processor_info_button.clicked.connect(() => { popover.show_all(); }); - cpu_chart = new Chart (cpu.core_list.size); + cpu_utilization_chart = new Chart (cpu.core_list.size); + cpu_frequency_chart = new Chart (1); + cpu_temperature_chart = new Chart (1); cpu_percentage_label.clicked.connect(() => { cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); @@ -69,16 +72,31 @@ public class Monitor.SystemCPUView : Gtk.Grid { } }); - attach (title_grid, 0, 0, 1, 1); - attach (grid_usage_labels(), 0, 1, 1, 1); - attach (cpu_chart, 0, 1, 1, 1); + var smol_charts_container = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + smol_charts_container.width_request = 200; + smol_charts_container.halign = Gtk.Align.START; + smol_charts_container.add (cpu_frequency_chart); + smol_charts_container.add (cpu_temperature_chart); + + var big_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); + // big_box.add (smol_charts_container); + // big_box.add (cpu_utilization_chart); + + add (cpu_utilization_chart); + add (smol_charts_container); + + grid_usage_labels(); + + // attach (title_grid, 0, 0, 1, 1); + // attach (grid_usage_labels(), 0, 1, 1, 1); + // attach (big_box, 0, 1, 1, 1); } public void update () { for (int i = 0; i < cpu.core_list.size; i++) { double core_percentage = cpu.core_list[i].percentage_used; - cpu_chart.update(i, core_percentage); + // cpu_utilization_chart.update(i, core_percentage); string percentage_formatted = ("% 3d%%").printf ( (int)core_percentage); core_label_list[i].set_text (percentage_formatted); From 3bf3900307d55ede113f6c80535901fe070d7961 Mon Sep 17 00:00:00 2001 From: stsdc Date: Wed, 12 Aug 2020 20:43:44 +0200 Subject: [PATCH 24/45] made some layout --- src/Views/SystemView/SystemCPUView.vala | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index edf46939..a6b7abcc 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -18,8 +18,8 @@ public class Monitor.SystemCPUView : Gtk.Box { margin = 12; margin_top = 6; // column_spacing = 12; - // set_vexpand (false); - // orintantation = Gtk.Orientation.VERTICAL; + set_vexpand (false); + orientation = Gtk.Orientation.VERTICAL; core_label_list = new Gee.ArrayList (); } @@ -47,7 +47,6 @@ public class Monitor.SystemCPUView : Gtk.Box { processor_info_button.valign = Gtk.Align.START; processor_info_button.halign = Gtk.Align.START; - var title_grid = new Gtk.Grid (); title_grid.attach (processor_name_label, 0, 0, 1, 1); @@ -60,7 +59,10 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_utilization_chart = new Chart (cpu.core_list.size); cpu_frequency_chart = new Chart (1); + cpu_frequency_chart.height_request = -1; cpu_temperature_chart = new Chart (1); + cpu_temperature_chart.margin_top = 6; + cpu_temperature_chart.height_request = -1; cpu_percentage_label.clicked.connect(() => { cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); @@ -74,22 +76,24 @@ public class Monitor.SystemCPUView : Gtk.Box { var smol_charts_container = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); smol_charts_container.width_request = 200; + smol_charts_container.hexpand = false; smol_charts_container.halign = Gtk.Align.START; smol_charts_container.add (cpu_frequency_chart); smol_charts_container.add (cpu_temperature_chart); + smol_charts_container.margin_left = 6; - var big_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - // big_box.add (smol_charts_container); - // big_box.add (cpu_utilization_chart); + var charts_container = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - add (cpu_utilization_chart); - add (smol_charts_container); + charts_container.pack_start (cpu_utilization_chart, true, true, 0); + charts_container.pack_start(smol_charts_container, false, false, 0); grid_usage_labels(); // attach (title_grid, 0, 0, 1, 1); // attach (grid_usage_labels(), 0, 1, 1, 1); // attach (big_box, 0, 1, 1, 1); + + add (charts_container); } From 6656e94b16f759ce4d4b815b29f93f3363309103 Mon Sep 17 00:00:00 2001 From: stsdc Date: Wed, 12 Aug 2020 21:02:30 +0200 Subject: [PATCH 25/45] bring back utilization label --- src/Views/SystemView/SystemCPUView.vala | 28 ++++++++----------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index a6b7abcc..82d0ff72 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -17,7 +17,6 @@ public class Monitor.SystemCPUView : Gtk.Box { construct { margin = 12; margin_top = 6; - // column_spacing = 12; set_vexpand (false); orientation = Gtk.Orientation.VERTICAL; @@ -58,6 +57,12 @@ public class Monitor.SystemCPUView : Gtk.Box { processor_info_button.clicked.connect(() => { popover.show_all(); }); cpu_utilization_chart = new Chart (cpu.core_list.size); + + var grid_utilization_info = new Gtk.Grid (); + grid_utilization_info.attach (grid_usage_labels(), 0, 0, 1, 1); + grid_utilization_info.attach (cpu_utilization_chart, 0, 0, 1, 1); + + cpu_frequency_chart = new Chart (1); cpu_frequency_chart.height_request = -1; cpu_temperature_chart = new Chart (1); @@ -82,17 +87,11 @@ public class Monitor.SystemCPUView : Gtk.Box { smol_charts_container.add (cpu_temperature_chart); smol_charts_container.margin_left = 6; + // Thanks Goncalo var charts_container = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - - charts_container.pack_start (cpu_utilization_chart, true, true, 0); + charts_container.pack_start (grid_utilization_info, true, true, 0); charts_container.pack_start(smol_charts_container, false, false, 0); - grid_usage_labels(); - - // attach (title_grid, 0, 0, 1, 1); - // attach (grid_usage_labels(), 0, 1, 1, 1); - // attach (big_box, 0, 1, 1, 1); - add (charts_container); } @@ -100,7 +99,7 @@ public class Monitor.SystemCPUView : Gtk.Box { public void update () { for (int i = 0; i < cpu.core_list.size; i++) { double core_percentage = cpu.core_list[i].percentage_used; - // cpu_utilization_chart.update(i, core_percentage); + cpu_utilization_chart.update(i, core_percentage); string percentage_formatted = ("% 3d%%").printf ( (int)core_percentage); core_label_list[i].set_text (percentage_formatted); @@ -131,15 +130,6 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_frequency_label.set_text (("%.2f %s").printf (cpu.frequency, _ ("GHz"))); } - private Gtk.Grid grid_info_labels () { - Gtk.Grid grid = new Gtk.Grid (); - - grid.attach(processor_name_label, 0, 0, 1, 1); - grid.attach(cpu_percentage_label, 0, 1, 1, 1); - - return grid; - } - private Gtk.Grid grid_usage_labels () { Gtk.Grid grid = new Gtk.Grid (); From d82f15436ffc43c1e08a27a1a3f8c08091d07dfd Mon Sep 17 00:00:00 2001 From: stsdc Date: Wed, 12 Aug 2020 21:36:45 +0200 Subject: [PATCH 26/45] update frequency chart --- src/Views/SystemView/SystemCPUView.vala | 4 ++++ src/Widgets/Chart/Chart.vala | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 82d0ff72..98d33c41 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -65,6 +65,7 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_frequency_chart = new Chart (1); cpu_frequency_chart.height_request = -1; + cpu_frequency_chart.config.y_axis.fixed_max = 5.0; cpu_temperature_chart = new Chart (1); cpu_temperature_chart.margin_top = 6; cpu_temperature_chart.height_request = -1; @@ -92,11 +93,14 @@ public class Monitor.SystemCPUView : Gtk.Box { charts_container.pack_start (grid_utilization_info, true, true, 0); charts_container.pack_start(smol_charts_container, false, false, 0); + add (title_grid); add (charts_container); } public void update () { + cpu_frequency_chart.update (0, cpu.frequency); + for (int i = 0; i < cpu.core_list.size; i++) { double core_percentage = cpu.core_list[i].percentage_used; cpu_utilization_chart.update(i, core_percentage); diff --git a/src/Widgets/Chart/Chart.vala b/src/Widgets/Chart/Chart.vala index f654516b..be898927 100644 --- a/src/Widgets/Chart/Chart.vala +++ b/src/Widgets/Chart/Chart.vala @@ -1,6 +1,6 @@ public class Monitor.Chart : Gtk.Box { private LiveChart.Chart live_chart; - private LiveChart.Config config; + public LiveChart.Config config; construct { get_style_context ().add_class ("graph"); From b921f36f45b8cd8e558c97639661ffcb6ba12f1b Mon Sep 17 00:00:00 2001 From: stsdc Date: Thu, 13 Aug 2020 23:36:24 +0200 Subject: [PATCH 27/45] add a frequency label --- src/Views/SystemView/SystemCPUView.vala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 98d33c41..8db2a41e 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -32,6 +32,7 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_percentage_label.has_tooltip = true; cpu_percentage_label.tooltip_text = (_("Show detailed info")); cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); + cpu_frequency_label.margin = 6; processor_name_label = new LabelH4 (cpu.model_name); @@ -63,6 +64,7 @@ public class Monitor.SystemCPUView : Gtk.Box { grid_utilization_info.attach (cpu_utilization_chart, 0, 0, 1, 1); + cpu_frequency_chart = new Chart (1); cpu_frequency_chart.height_request = -1; cpu_frequency_chart.config.y_axis.fixed_max = 5.0; @@ -70,6 +72,11 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_temperature_chart.margin_top = 6; cpu_temperature_chart.height_request = -1; + var grid_frequency_info = new Gtk.Grid (); + grid_frequency_info.attach (cpu_frequency_label, 0, 0, 1, 1); + grid_frequency_info.attach (cpu_frequency_chart, 0, 0, 1, 1); + + cpu_percentage_label.clicked.connect(() => { cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); @@ -84,7 +91,7 @@ public class Monitor.SystemCPUView : Gtk.Box { smol_charts_container.width_request = 200; smol_charts_container.hexpand = false; smol_charts_container.halign = Gtk.Align.START; - smol_charts_container.add (cpu_frequency_chart); + smol_charts_container.add (grid_frequency_info); smol_charts_container.add (cpu_temperature_chart); smol_charts_container.margin_left = 6; From 266d0e8b1507e9e274ef894db6f5142ca025f961 Mon Sep 17 00:00:00 2001 From: stsdc Date: Fri, 14 Aug 2020 02:19:38 +0200 Subject: [PATCH 28/45] temperature sensor WIP --- meson.build | 1 + src/Resources/CPU.vala | 2 ++ src/Resources/TemperatureSensor.vala | 54 ++++++++++++++++++++++++++++ src/Widgets/Chart/Chart.vala | 1 - 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/Resources/TemperatureSensor.vala diff --git a/meson.build b/meson.build index c40e772c..8d9b9522 100644 --- a/meson.build +++ b/meson.build @@ -109,6 +109,7 @@ executable( 'src/Resources/Core.vala', 'src/Resources/Memory.vala', 'src/Resources/Swap.vala', + 'src/Resources/TemperatureSensor.vala', c_args: c_args, dependencies: [ glib, diff --git a/src/Resources/CPU.vala b/src/Resources/CPU.vala index 895dc875..9c74cc47 100644 --- a/src/Resources/CPU.vala +++ b/src/Resources/CPU.vala @@ -46,6 +46,8 @@ public class Monitor.CPU : Object { var core = new Core(i); core_list.add (core); } + + var temp = new TemperatureSensor.cpu (); } public void update () { diff --git a/src/Resources/TemperatureSensor.vala b/src/Resources/TemperatureSensor.vala new file mode 100644 index 00000000..ab317846 --- /dev/null +++ b/src/Resources/TemperatureSensor.vala @@ -0,0 +1,54 @@ +class TemperatureSensor : Object { + private const string hwmon_path = "/sys/class/hwmon"; + + public struct Sensor { + public string location; + public double tdie_current_temperature; + public double tdie_critical_temperature; + public double tctl_current_temperature; + public double tctl_critical_temperature; + } public Sensor at_cpu; + + construct { } + + public TemperatureSensor() { + } + + public TemperatureSensor.cpu () { + traverser (); + } + + + private void traverser () { + int hwmon_counter = 0; + + Dir hwmon_dir = Dir.open (hwmon_path, 0); + + string ? hwmonx = null; + while ((hwmonx = hwmon_dir.read_name ()) != null) { + string hwmonx_name = Path.build_filename (hwmon_path, hwmonx, "name"); + string sensor_location = open_file (hwmonx_name).replace ("\n",""); + + if (sensor_location == "coretemp" || sensor_location == "k10temp") { + debug (sensor_location); + + Dir hwmonx_dir = Dir.open (Path.build_filename (hwmon_path, hwmonx), 0); + string ? hwmonx_props = null; + while ((hwmonx_props = hwmonx_dir.read_name ()) != null) { + debug (hwmonx_props); + } + } + } + } + + private string open_file (string filename) { + try { + string read; + FileUtils.get_contents (filename, out read); + return read; + } catch (FileError e) { + error ("%s\n", e.message); + return "0"; + } + } +} \ No newline at end of file diff --git a/src/Widgets/Chart/Chart.vala b/src/Widgets/Chart/Chart.vala index be898927..dfd85ec8 100644 --- a/src/Widgets/Chart/Chart.vala +++ b/src/Widgets/Chart/Chart.vala @@ -48,7 +48,6 @@ public class Monitor.Chart : Gtk.Box { } public void update (int serie_number, double value) { - debug ("update called"); live_chart.add_value_by_index (serie_number, value); } From ba096ea84ceea383b5ebb9e38d5f530d62f175e9 Mon Sep 17 00:00:00 2001 From: stsdc Date: Fri, 14 Aug 2020 20:56:47 +0200 Subject: [PATCH 29/45] detect some more sensors --- src/Resources/TemperatureSensor.vala | 39 ++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Resources/TemperatureSensor.vala b/src/Resources/TemperatureSensor.vala index ab317846..6ae498ad 100644 --- a/src/Resources/TemperatureSensor.vala +++ b/src/Resources/TemperatureSensor.vala @@ -1,13 +1,17 @@ class TemperatureSensor : Object { private const string hwmon_path = "/sys/class/hwmon"; + private string? cpu_temp_path; public struct Sensor { public string location; - public double tdie_current_temperature; - public double tdie_critical_temperature; - public double tctl_current_temperature; - public double tctl_critical_temperature; - } public Sensor at_cpu; + public float temperature; + public float temperature_critical; + // public double tdie_current_temperature; + // public double tdie_critical_temperature; + // public double tctl_current_temperature; + // public double tctl_critical_temperature; + } public Sensor sensor; + construct { } @@ -27,16 +31,29 @@ class TemperatureSensor : Object { string ? hwmonx = null; while ((hwmonx = hwmon_dir.read_name ()) != null) { string hwmonx_name = Path.build_filename (hwmon_path, hwmonx, "name"); - string sensor_location = open_file (hwmonx_name).replace ("\n",""); + string sensor_location = open_file (hwmonx_name); if (sensor_location == "coretemp" || sensor_location == "k10temp") { - debug (sensor_location); + debug ("Found temp. sensor: %s", sensor_location); Dir hwmonx_dir = Dir.open (Path.build_filename (hwmon_path, hwmonx), 0); - string ? hwmonx_props = null; - while ((hwmonx_props = hwmonx_dir.read_name ()) != null) { - debug (hwmonx_props); + string ? hwmonx_prop = null; + while ((hwmonx_prop = hwmonx_dir.read_name ()) != null) { + // debug (open_file (hwmonx_name)); + + if (hwmonx_prop.contains ("temp")) { + // Tdie contains true temperature value, while Tctl contains value for fans + // Tctl = Tdie + offset + if ("Tdie" == open_file (Path.build_filename (hwmon_path, hwmonx, hwmonx_prop))) { + cpu_temp_path = Path.build_filename (hwmon_path, hwmonx, "temp%c_input".printf(hwmonx_prop[4])); + debug (open_file (cpu_temp_path)); + } + } } + } else if (sensor_location == "amdgpu" ) { + debug ("Found temp. sensor: %s", sensor_location); + } else { + debug ("Found temp. sensor: %s", sensor_location); } } } @@ -45,7 +62,7 @@ class TemperatureSensor : Object { try { string read; FileUtils.get_contents (filename, out read); - return read; + return read.replace ("\n",""); } catch (FileError e) { error ("%s\n", e.message); return "0"; From 6ab3b2eb4b6691a230d2af54414cd6ee0ed81c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw?= Date: Fri, 14 Aug 2020 23:07:02 +0200 Subject: [PATCH 30/45] support intel --- src/Resources/TemperatureSensor.vala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Resources/TemperatureSensor.vala b/src/Resources/TemperatureSensor.vala index 6ae498ad..4cf6f73a 100644 --- a/src/Resources/TemperatureSensor.vala +++ b/src/Resources/TemperatureSensor.vala @@ -47,6 +47,11 @@ class TemperatureSensor : Object { if ("Tdie" == open_file (Path.build_filename (hwmon_path, hwmonx, hwmonx_prop))) { cpu_temp_path = Path.build_filename (hwmon_path, hwmonx, "temp%c_input".printf(hwmonx_prop[4])); debug (open_file (cpu_temp_path)); + // Intel stuff + // But what core to choose + } else if (open_file (Path.build_filename (hwmon_path, hwmonx, hwmonx_prop)).contains ("Core")) { + cpu_temp_path = Path.build_filename (hwmon_path, hwmonx, "temp%c_input".printf(hwmonx_prop[4])); + debug (open_file (cpu_temp_path)); } } } From 2ef29e1ff4a4a36ffaf0c8b441891e3a112191bc Mon Sep 17 00:00:00 2001 From: stsdc Date: Fri, 14 Aug 2020 23:38:21 +0200 Subject: [PATCH 31/45] save pathes in array --- src/Resources/TemperatureSensor.vala | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Resources/TemperatureSensor.vala b/src/Resources/TemperatureSensor.vala index 4cf6f73a..8b697196 100644 --- a/src/Resources/TemperatureSensor.vala +++ b/src/Resources/TemperatureSensor.vala @@ -1,6 +1,9 @@ class TemperatureSensor : Object { private const string hwmon_path = "/sys/class/hwmon"; - private string? cpu_temp_path; + + // contains list of paths to files with a temperature values + // Intel reports per core temperature, while AMD Ryzen Tdie + public Gee.ArrayList cpu_temp_paths; public struct Sensor { public string location; @@ -13,9 +16,12 @@ class TemperatureSensor : Object { } public Sensor sensor; - construct { } + construct { + cpu_temp_paths = new Gee.ArrayList (); + } public TemperatureSensor() { + } public TemperatureSensor.cpu () { @@ -42,16 +48,21 @@ class TemperatureSensor : Object { // debug (open_file (hwmonx_name)); if (hwmonx_prop.contains ("temp")) { + // AMD stuff // Tdie contains true temperature value, while Tctl contains value for fans - // Tctl = Tdie + offset + // Tctl = Tdie + offset in some processors if ("Tdie" == open_file (Path.build_filename (hwmon_path, hwmonx, hwmonx_prop))) { - cpu_temp_path = Path.build_filename (hwmon_path, hwmonx, "temp%c_input".printf(hwmonx_prop[4])); - debug (open_file (cpu_temp_path)); + string tempx_input = "temp%c_input".printf(hwmonx_prop[4]); + cpu_temp_paths.add (Path.build_filename (hwmon_path, hwmonx, tempx_input)); + + debug (open_file (cpu_temp_paths[0])); + // Intel stuff - // But what core to choose + // Intel reports per core } else if (open_file (Path.build_filename (hwmon_path, hwmonx, hwmonx_prop)).contains ("Core")) { - cpu_temp_path = Path.build_filename (hwmon_path, hwmonx, "temp%c_input".printf(hwmonx_prop[4])); - debug (open_file (cpu_temp_path)); + string tempx_input = "temp%c_input".printf(hwmonx_prop[4]); + cpu_temp_paths.add (Path.build_filename (hwmon_path, hwmonx, tempx_input)); + debug (open_file (cpu_temp_paths[0])); } } } From 7c7d4e5152904b0d37aadf9de8fe566e45b6ede6 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sat, 15 Aug 2020 00:10:44 +0200 Subject: [PATCH 32/45] displaying cpu temperature --- src/Resources/CPU.vala | 11 ++++++++++- src/Resources/TemperatureSensor.vala | 26 ++++++++++--------------- src/Views/SystemView/SystemCPUView.vala | 21 ++++++++++++++++---- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/Resources/CPU.vala b/src/Resources/CPU.vala index 9c74cc47..8700a4f7 100644 --- a/src/Resources/CPU.vala +++ b/src/Resources/CPU.vala @@ -2,6 +2,7 @@ public class Monitor.CPU : Object { private float last_used; private float last_total; private float load; + private TemperatureSensor temperature_sensor; public string? model_name; public string? model; @@ -31,6 +32,12 @@ public class Monitor.CPU : Object { } } + public double temperature { + get { + return temperature_sensor.cpu / 1000; + } + } + construct { last_used = 0; last_total = 0; @@ -47,7 +54,9 @@ public class Monitor.CPU : Object { core_list.add (core); } - var temp = new TemperatureSensor.cpu (); + // Temperature sensor shouldn't be created here since it + // will provides not only cpu temperature + temperature_sensor = new TemperatureSensor (); } public void update () { diff --git a/src/Resources/TemperatureSensor.vala b/src/Resources/TemperatureSensor.vala index 8b697196..b64a8e20 100644 --- a/src/Resources/TemperatureSensor.vala +++ b/src/Resources/TemperatureSensor.vala @@ -5,33 +5,27 @@ class TemperatureSensor : Object { // Intel reports per core temperature, while AMD Ryzen Tdie public Gee.ArrayList cpu_temp_paths; - public struct Sensor { - public string location; - public float temperature; - public float temperature_critical; - // public double tdie_current_temperature; - // public double tdie_critical_temperature; - // public double tctl_current_temperature; - // public double tctl_critical_temperature; - } public Sensor sensor; - + public double cpu { + get { + double total_temperature = 0; + foreach (var path in cpu_temp_paths) { + total_temperature += double.parse (open_file (path)); + } + return total_temperature / cpu_temp_paths.size; + } + } construct { cpu_temp_paths = new Gee.ArrayList (); + traverser (); } public TemperatureSensor() { } - public TemperatureSensor.cpu () { - traverser (); - } - private void traverser () { - int hwmon_counter = 0; - Dir hwmon_dir = Dir.open (hwmon_path, 0); string ? hwmonx = null; diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 8db2a41e..96a69383 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -6,6 +6,7 @@ public class Monitor.SystemCPUView : Gtk.Box { private LabelVertical cpu_percentage_label; private LabelRoundy cpu_frequency_label; + private LabelRoundy cpu_temperature_label; private LabelH4 processor_name_label; private Gtk.Button view_threads_usage_button; @@ -31,8 +32,14 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_percentage_label = new LabelVertical (_("UTILIZATION")); cpu_percentage_label.has_tooltip = true; cpu_percentage_label.tooltip_text = (_("Show detailed info")); + cpu_frequency_label = new LabelRoundy (_("FREQUENCY")); cpu_frequency_label.margin = 6; + cpu_frequency_label.margin_top = 2; + + cpu_temperature_label = new LabelRoundy (_("TEMPERATURE")); + cpu_temperature_label.margin = 6; + cpu_temperature_label.margin_top = 2; processor_name_label = new LabelH4 (cpu.model_name); @@ -69,13 +76,16 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_frequency_chart.height_request = -1; cpu_frequency_chart.config.y_axis.fixed_max = 5.0; cpu_temperature_chart = new Chart (1); - cpu_temperature_chart.margin_top = 6; cpu_temperature_chart.height_request = -1; var grid_frequency_info = new Gtk.Grid (); grid_frequency_info.attach (cpu_frequency_label, 0, 0, 1, 1); grid_frequency_info.attach (cpu_frequency_chart, 0, 0, 1, 1); + var grid_temperature_info = new Gtk.Grid (); + grid_temperature_info.attach (cpu_temperature_label, 0, 0, 1, 1); + grid_temperature_info.attach (cpu_temperature_chart, 0, 0, 1, 1); + cpu_percentage_label.clicked.connect(() => { cpu_threads_revealer.reveal_child = !(cpu_threads_revealer.child_revealed); @@ -87,12 +97,13 @@ public class Monitor.SystemCPUView : Gtk.Box { } }); - var smol_charts_container = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); + var smol_charts_container = new Gtk.Grid (); smol_charts_container.width_request = 200; smol_charts_container.hexpand = false; smol_charts_container.halign = Gtk.Align.START; - smol_charts_container.add (grid_frequency_info); - smol_charts_container.add (cpu_temperature_chart); + smol_charts_container.attach (grid_frequency_info, 0, 0, 1, 1); + smol_charts_container.attach (grid_temperature_info, 0, 1, 1, 1); + smol_charts_container.row_spacing = 6; smol_charts_container.margin_left = 6; // Thanks Goncalo @@ -107,6 +118,7 @@ public class Monitor.SystemCPUView : Gtk.Box { public void update () { cpu_frequency_chart.update (0, cpu.frequency); + cpu_temperature_chart.update (0, cpu.temperature); for (int i = 0; i < cpu.core_list.size; i++) { double core_percentage = cpu.core_list[i].percentage_used; @@ -139,6 +151,7 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_percentage_label.set_text ((_("%d%%")).printf (cpu.percentage)); cpu_frequency_label.set_text (("%.2f %s").printf (cpu.frequency, _ ("GHz"))); + cpu_temperature_label.set_text (("%.2f %s").printf (cpu.temperature, _ ("C"))); } private Gtk.Grid grid_usage_labels () { From 4c5a99d775e17c59d7c6d709e7e04d01f8836cf2 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sat, 15 Aug 2020 19:25:10 +0200 Subject: [PATCH 33/45] getting some network info --- meson.build | 2 + src/Resources/Network.vala | 72 +++++++++++++++++++++ src/Resources/Resources.vala | 4 ++ src/Views/SystemView/SystemCPUView.vala | 2 +- src/Views/SystemView/SystemNetworkView.vala | 52 +++++++++++++++ src/Views/SystemView/SystemView.vala | 2 + vapi/libgtop-2.0.vapi | 3 + 7 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 src/Resources/Network.vala create mode 100644 src/Views/SystemView/SystemNetworkView.vala diff --git a/meson.build b/meson.build index 8d9b9522..82daaa09 100644 --- a/meson.build +++ b/meson.build @@ -70,6 +70,7 @@ executable( 'src/Views/SystemView/SystemCPUView.vala', 'src/Views/SystemView/SystemCPUInfoPopover.vala', 'src/Views/SystemView/SystemMemoryView.vala', + 'src/Views/SystemView/SystemNetworkView.vala', # Widgets related only to ProcessInfoView 'src/Views/ProcessView/ProcessInfoView/Preventor.vala', @@ -110,6 +111,7 @@ executable( 'src/Resources/Memory.vala', 'src/Resources/Swap.vala', 'src/Resources/TemperatureSensor.vala', + 'src/Resources/Network.vala', c_args: c_args, dependencies: [ glib, diff --git a/src/Resources/Network.vala b/src/Resources/Network.vala new file mode 100644 index 00000000..8d22fe2c --- /dev/null +++ b/src/Resources/Network.vala @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2020 Tudor Plugaru (https://github.com/PlugaruT/wingpanel-monitor) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Authored by: Tudor Plugaru + */ + + +public class Monitor.Network : GLib.Object { + private int _bytes_in; + private int _bytes_in_old; + private bool control; + + private int _bytes_out; + private int _bytes_out_old; + + public Network () { + _bytes_in = 0; + _bytes_in_old = 0; + _bytes_out = 0; + _bytes_out_old = 0; + control = false; + } + + public int[] get_bytes () { + if (control == false) { + control = true; + update_bytes_total (); + } else { + control = false; + } + int[] ret; + ret = {_bytes_out, _bytes_in}; + return ret; + } + + private void update_bytes_total () { + GTop.NetList netlist; + GTop.NetLoad netload; + + var devices = GTop.get_netlist (out netlist); + var n_bytes_out = 0; + var n_bytes_in = 0; + for (uint j = 0; j < netlist.number; ++j) { + var device = devices[j]; + if (device != "lo" && device.substring (0, 3) != "tun") { + GTop.get_netload (out netload, device); + + n_bytes_out += (int)netload.bytes_out; + n_bytes_in += (int)netload.bytes_in; + } + } + _bytes_out = (n_bytes_out - _bytes_out_old) / 1; + _bytes_in = (n_bytes_in - _bytes_in_old) / 1; + _bytes_out_old = n_bytes_out; + _bytes_in_old = n_bytes_in; + } + } diff --git a/src/Resources/Resources.vala b/src/Resources/Resources.vala index 1deef74c..14215537 100644 --- a/src/Resources/Resources.vala +++ b/src/Resources/Resources.vala @@ -2,16 +2,20 @@ public class Monitor.Resources : Object { public CPU cpu; public Memory memory; public Swap swap; + public Network network; construct { memory = new Memory (); cpu = new CPU (); swap = new Swap (); + network = new Network (); } public void update() { cpu.update(); memory.update(); + + debug ("%d", network.get_bytes ()[0]); } public ResourcesSerialized serialize () { return ResourcesSerialized () { diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 96a69383..33a0d67e 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -151,7 +151,7 @@ public class Monitor.SystemCPUView : Gtk.Box { cpu_percentage_label.set_text ((_("%d%%")).printf (cpu.percentage)); cpu_frequency_label.set_text (("%.2f %s").printf (cpu.frequency, _ ("GHz"))); - cpu_temperature_label.set_text (("%.2f %s").printf (cpu.temperature, _ ("C"))); + cpu_temperature_label.set_text (("%.2f %s").printf (cpu.temperature, _ ("℃"))); } private Gtk.Grid grid_usage_labels () { diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala new file mode 100644 index 00000000..a9c49258 --- /dev/null +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -0,0 +1,52 @@ +public class Monitor.SystemNetworkView : Gtk.Grid { + private Chart network_chart; + private Network network; + + private LabelH4 memory_name_label; + private LabelVertical memory_percentage_label; + private Gtk.Label memory_shared_label; + private Gtk.Label memory_buffered_label; + private Gtk.Label memory_cached_label; + private Gtk.Label memory_locked_label; + private Gtk.Label memory_total_label; + private Gtk.Label memory_used_label; + private Gtk.Revealer memory_usage_revealer; + + construct { + margin = 12; + column_spacing = 12; + set_vexpand (false); + } + + + + public SystemNetworkView(Network _network) { + network = _network; + + memory_name_label = new LabelH4 (_("Network")); + + network_chart = new Chart (1); + + + + attach (memory_name_label, 0, 0, 1, 1); + attach (network_chart, 0, 1, 2, 2); + + } + + private Gtk.Revealer memory_usage_grid () { + + Gtk.Grid grid = new Gtk.Grid (); + grid.column_spacing = 12; + grid.width_request = 300; + + return memory_usage_revealer; + } + + + public void update () { + // network_chart.update (0, network); + + } + +} \ No newline at end of file diff --git a/src/Views/SystemView/SystemView.vala b/src/Views/SystemView/SystemView.vala index 162d5467..b9d277da 100644 --- a/src/Views/SystemView/SystemView.vala +++ b/src/Views/SystemView/SystemView.vala @@ -3,6 +3,7 @@ public class Monitor.SystemView : Gtk.Box { private SystemCPUView cpu_view; private SystemMemoryView memory_view; + private SystemNetworkView network_view; construct { orientation = Gtk.Orientation.VERTICAL; @@ -14,6 +15,7 @@ public class Monitor.SystemView : Gtk.Box { cpu_view = new SystemCPUView (resources.cpu); memory_view = new SystemMemoryView (resources.memory); + // memory_view = new SystemNetworkView (resources.memory); add (cpu_view); add (memory_view); diff --git a/vapi/libgtop-2.0.vapi b/vapi/libgtop-2.0.vapi index 53be24b9..b69e634b 100644 --- a/vapi/libgtop-2.0.vapi +++ b/vapi/libgtop-2.0.vapi @@ -45,6 +45,7 @@ namespace GTop { public void get_msg_limits_s (out GTop.MsgLimits buf); public void get_netload_l (out GTop.NetLoad buf, string @interface); public void get_netload_s (out GTop.NetLoad buf, string @interface); + public string[] get_netlist (out GTop.NetList buf); public ulong get_parameter_l (uint parameter, void* data_ptr, ulong data_size); public void get_ppp_l (out GTop.Ppp buf, ushort device); public void get_ppp_s (out GTop.Ppp buf, ushort device); @@ -1273,6 +1274,8 @@ namespace GTop { public static void get_msg_limits (out GTop.MsgLimits buf); [CCode (cheader_filename = "glibtop.h", cname = "glibtop_get_netload")] public static void get_netload (out GTop.NetLoad buf, string @interface); + [CCode (cheader_filename = "glibtop/netlist.h", cname = "glibtop_get_netlist", array_length = false, array_null_terminated = true)] + public static string[] get_netlist (out GTop.NetList buf); [CCode (cheader_filename = "glibtop.h", cname = "glibtop_get_ppp")] public static void get_ppp (out GTop.Ppp buf, ushort device); [CCode (cheader_filename = "glibtop.h", cname = "glibtop_get_proc_affinity")] From 471239bfb15b2bba0314f72bcc3f849e14a5acf7 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 16 Aug 2020 00:16:51 +0200 Subject: [PATCH 34/45] show labels with up/down traffic speed --- src/Resources/Resources.vala | 2 - src/Views/SystemView/SystemCPUView.vala | 1 + src/Views/SystemView/SystemNetworkView.vala | 48 +++++++++------------ src/Views/SystemView/SystemView.vala | 4 +- 4 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/Resources/Resources.vala b/src/Resources/Resources.vala index 14215537..04f2b898 100644 --- a/src/Resources/Resources.vala +++ b/src/Resources/Resources.vala @@ -14,8 +14,6 @@ public class Monitor.Resources : Object { public void update() { cpu.update(); memory.update(); - - debug ("%d", network.get_bytes ()[0]); } public ResourcesSerialized serialize () { return ResourcesSerialized () { diff --git a/src/Views/SystemView/SystemCPUView.vala b/src/Views/SystemView/SystemCPUView.vala index 33a0d67e..4187c1f4 100644 --- a/src/Views/SystemView/SystemCPUView.vala +++ b/src/Views/SystemView/SystemCPUView.vala @@ -182,6 +182,7 @@ public class Monitor.SystemCPUView : Gtk.Box { int row = 0; for (int i = 0; i < cpu.core_list.size; i++) { var core_label = new Gtk.Label (Utils.NO_DATA); + core_label.set_width_chars (4); core_label.get_style_context ().add_class ("core_badge"); // core_label.set_text (Utils.NO_DATA); core_label_list.add (core_label); diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala index a9c49258..4d2dc68b 100644 --- a/src/Views/SystemView/SystemNetworkView.vala +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -2,15 +2,9 @@ public class Monitor.SystemNetworkView : Gtk.Grid { private Chart network_chart; private Network network; - private LabelH4 memory_name_label; - private LabelVertical memory_percentage_label; - private Gtk.Label memory_shared_label; - private Gtk.Label memory_buffered_label; - private Gtk.Label memory_cached_label; - private Gtk.Label memory_locked_label; - private Gtk.Label memory_total_label; - private Gtk.Label memory_used_label; - private Gtk.Revealer memory_usage_revealer; + private LabelH4 network_name_label; + private LabelRoundy network_upload_label; + private LabelRoundy network_download_label; construct { margin = 12; @@ -20,33 +14,33 @@ public class Monitor.SystemNetworkView : Gtk.Grid { - public SystemNetworkView(Network _network) { + public SystemNetworkView (Network _network) { network = _network; - memory_name_label = new LabelH4 (_("Network")); + network_name_label = new LabelH4 (_ ("Network")); + network_download_label = new LabelRoundy (_ ("DOWN")); + network_upload_label = new LabelRoundy (_ ("UP")); - network_chart = new Chart (1); + network_chart = new Chart (2); + var labels_grid = new Gtk.Grid (); + labels_grid.row_spacing = 6; + labels_grid.column_spacing = 6; + labels_grid.margin = 6; + labels_grid.attach (network_upload_label, 0, 0, 1, 1); + labels_grid.attach (network_download_label, 1, 0, 1, 1); - - attach (memory_name_label, 0, 0, 1, 1); - attach (network_chart, 0, 1, 2, 2); - + attach (network_name_label, 0, 0, 1, 1); + attach (labels_grid, 0, 1, 2, 2); + attach (network_chart, 0, 1, 2, 2); } - private Gtk.Revealer memory_usage_grid () { - - Gtk.Grid grid = new Gtk.Grid (); - grid.column_spacing = 12; - grid.width_request = 300; - - return memory_usage_revealer; - } public void update () { - // network_chart.update (0, network); - + network_download_label.set_text (("%s/s").printf ( Utils.HumanUnitFormatter.string_bytes_to_human(network.get_bytes ()[1].to_string()))); + network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human(network.get_bytes ()[0].to_string()))); + network_chart.update (0, network.get_bytes ()[0]/1024); + network_chart.update (1, network.get_bytes ()[1]/1024); } - } \ No newline at end of file diff --git a/src/Views/SystemView/SystemView.vala b/src/Views/SystemView/SystemView.vala index b9d277da..c1dc8bee 100644 --- a/src/Views/SystemView/SystemView.vala +++ b/src/Views/SystemView/SystemView.vala @@ -15,14 +15,16 @@ public class Monitor.SystemView : Gtk.Box { cpu_view = new SystemCPUView (resources.cpu); memory_view = new SystemMemoryView (resources.memory); - // memory_view = new SystemNetworkView (resources.memory); + network_view = new SystemNetworkView (resources.network); add (cpu_view); add (memory_view); + add (network_view); } public void update () { cpu_view.update(); memory_view.update(); + network_view.update (); } } \ No newline at end of file From 65d925fd596082e5900885161d7f59563643d7c5 Mon Sep 17 00:00:00 2001 From: rottenpants466 <62076029+rottenpants466@users.noreply.github.com> Date: Sun, 16 Aug 2020 14:14:27 +0100 Subject: [PATCH 35/45] Update pt.po --- po/pt.po | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/po/pt.po b/po/pt.po index daab273e..d02e8a09 100644 --- a/po/pt.po +++ b/po/pt.po @@ -9,14 +9,14 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-04-28 22:18+0400\n" -"PO-Revision-Date: 2019-11-04 11:58+0000\n" -"Last-Translator: Hugo Carvalho \n" +"PO-Revision-Date: 2020-08-16 14:07+0100\n" +"Last-Translator: André Barata \n" "Language-Team: \n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.2.4\n" +"X-Generator: Poedit 2.4.1\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: src/Utils.vala:13 @@ -29,11 +29,11 @@ msgstr "" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:34 #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:35 msgid "N/A" -msgstr "" +msgstr "N/A" #: src/Utils.vala:45 msgid "B" -msgstr "" +msgstr "B" #: src/Utils.vala:50 #: src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala:113 @@ -55,19 +55,19 @@ msgstr "Fechar Monitor" #: src/Views/ProcessView/ProcessInfoView/OpenFilesListBox.vala:56 msgid "Deleted" -msgstr "" +msgstr "Apagado" #: src/Views/ProcessView/ProcessInfoView/Preventor.vala:21 msgid "Are you sure you want to do this?" -msgstr "" +msgstr "Tem a certeza que quer fazer isso?" #: src/Views/ProcessView/ProcessInfoView/Preventor.vala:24 msgid "Yes" -msgstr "" +msgstr "Sim" #: src/Views/ProcessView/ProcessInfoView/Preventor.vala:28 msgid "No" -msgstr "" +msgstr "Não" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala:39 #: src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala:59 @@ -76,36 +76,35 @@ msgstr "PID" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala:40 msgid "NI" -msgstr "" +msgstr "NI" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala:41 -#, fuzzy msgid "PRI" -msgstr "PID" +msgstr "PRI" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoHeader.vala:42 msgid "THR" -msgstr "" +msgstr "THR" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:18 msgid "Opened files" -msgstr "" +msgstr "Ficheiros abertos" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:22 msgid "Characters" -msgstr "" +msgstr "Caracteres" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:27 msgid "System calls" -msgstr "" +msgstr "Chamadas de sistema" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:32 msgid "Read/Written" -msgstr "" +msgstr "Ler/Escrita" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoIOStats.vala:37 msgid "Cancelled write" -msgstr "" +msgstr "Escrita cancelada" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala:79 msgid "End Process" @@ -125,11 +124,11 @@ msgstr "Matar processo selecionado" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala:96 msgid "Confirm kill of the process?" -msgstr "" +msgstr "Confirma matar o processo?" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoView.vala:103 msgid "Confirm end of the process?" -msgstr "" +msgstr "Confirma terminar o processo?" #. setup name column #: src/Views/ProcessView/ProcessTreeView/CPUProcessTreeView.vala:17 @@ -155,12 +154,12 @@ msgstr "GiB" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala:50 #, c-format msgid "CPU: %.1f%%" -msgstr "" +msgstr "CPU: %.1f%%" #: src/Views/ProcessView/ProcessInfoView/ProcessInfoCPURAM.vala:51 #, c-format msgid "RAM: %.1f%%" -msgstr "" +msgstr "RAM: %.1f%%" #: src/Widgets/Headerbar/Headerbar.vala:13 msgid "Monitor" @@ -188,7 +187,7 @@ msgstr "Escreva o nome do processo ou PID a pesquisar" #: src/Widgets/Statusbar/Statusbar.vala:14 msgid "Swap" -msgstr "" +msgstr "Trocar" #: src/Widgets/Statusbar/Statusbar.vala:16 #: src/Widgets/Statusbar/Statusbar.vala:20 @@ -198,7 +197,7 @@ msgstr "A calcular…" #: src/Widgets/Statusbar/Statusbar.vala:38 msgid "GHz" -msgstr "" +msgstr "GHz" #~ msgid "Monitor Indicator" #~ msgstr "Indicador do monitor" @@ -213,7 +212,7 @@ msgstr "" #~ msgstr "Ctrl+E" #~ msgid "CPU:" -#~ msgstr "CPU :" +#~ msgstr "CPU:" #~ msgid "Memory:" -#~ msgstr "Memória :" +#~ msgstr "Memória:" From a2bd25392692b6eed47b14a57d3110cef0dd80fb Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 16 Aug 2020 20:51:29 +0200 Subject: [PATCH 36/45] fix showing wrong uload/download speeds --- src/Views/SystemView/SystemNetworkView.vala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala index 4d2dc68b..0bd16f1e 100644 --- a/src/Views/SystemView/SystemNetworkView.vala +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -27,8 +27,8 @@ public class Monitor.SystemNetworkView : Gtk.Grid { labels_grid.row_spacing = 6; labels_grid.column_spacing = 6; labels_grid.margin = 6; - labels_grid.attach (network_upload_label, 0, 0, 1, 1); - labels_grid.attach (network_download_label, 1, 0, 1, 1); + labels_grid.attach (network_download_label, 0, 0, 1, 1); + labels_grid.attach (network_upload_label, 1, 0, 1, 1); attach (network_name_label, 0, 0, 1, 1); attach (labels_grid, 0, 1, 2, 2); @@ -38,8 +38,10 @@ public class Monitor.SystemNetworkView : Gtk.Grid { public void update () { - network_download_label.set_text (("%s/s").printf ( Utils.HumanUnitFormatter.string_bytes_to_human(network.get_bytes ()[1].to_string()))); - network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human(network.get_bytes ()[0].to_string()))); + double up_bytes = network.get_bytes ()[0] / 2; + double down_bytes = network.get_bytes ()[1] / 2; + network_download_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (down_bytes.to_string ()))); + network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (up_bytes.to_string ()))); network_chart.update (0, network.get_bytes ()[0]/1024); network_chart.update (1, network.get_bytes ()[1]/1024); } From c25bd5caafcbcdfc710e0f4034ff3449a3a4ed65 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 16 Aug 2020 21:39:19 +0200 Subject: [PATCH 37/45] adding network chart --- meson.build | 1 + src/Views/SystemView/SystemNetworkView.vala | 18 +++--- src/Widgets/Chart/NetworkChart.vala | 66 +++++++++++++++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/Widgets/Chart/NetworkChart.vala diff --git a/meson.build b/meson.build index 82daaa09..17aa7927 100644 --- a/meson.build +++ b/meson.build @@ -88,6 +88,7 @@ executable( 'src/Widgets/Labels/LabelH4.vala', 'src/Widgets/Chart/Chart.vala', 'src/Widgets/Chart/ProcessChart.vala', + 'src/Widgets/Chart/NetworkChart.vala', # Models diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala index 0bd16f1e..96845fad 100644 --- a/src/Views/SystemView/SystemNetworkView.vala +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -1,5 +1,5 @@ public class Monitor.SystemNetworkView : Gtk.Grid { - private Chart network_chart; + private NetworkChart network_chart; private Network network; private LabelH4 network_name_label; @@ -21,7 +21,7 @@ public class Monitor.SystemNetworkView : Gtk.Grid { network_download_label = new LabelRoundy (_ ("DOWN")); network_upload_label = new LabelRoundy (_ ("UP")); - network_chart = new Chart (2); + network_chart = new NetworkChart (2); var labels_grid = new Gtk.Grid (); labels_grid.row_spacing = 6; @@ -35,14 +35,16 @@ public class Monitor.SystemNetworkView : Gtk.Grid { attach (network_chart, 0, 1, 2, 2); } - - public void update () { double up_bytes = network.get_bytes ()[0] / 2; double down_bytes = network.get_bytes ()[1] / 2; - network_download_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (down_bytes.to_string ()))); - network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (up_bytes.to_string ()))); - network_chart.update (0, network.get_bytes ()[0]/1024); - network_chart.update (1, network.get_bytes ()[1]/1024); + + debug ("%f %f", up_bytes, down_bytes); + if (up_bytes >= 0 && down_bytes >= 0) { + network_download_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (down_bytes.to_string ()))); + network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (up_bytes.to_string ()))); + network_chart.update (0, up_bytes); + network_chart.update (1, down_bytes); + } } } \ No newline at end of file diff --git a/src/Widgets/Chart/NetworkChart.vala b/src/Widgets/Chart/NetworkChart.vala new file mode 100644 index 00000000..d4aa38c8 --- /dev/null +++ b/src/Widgets/Chart/NetworkChart.vala @@ -0,0 +1,66 @@ +public class Monitor.NetworkChart : Gtk.Box { + private LiveChart.Chart live_chart; + public LiveChart.Config config; + + construct { + get_style_context ().add_class ("graph"); + + vexpand = true; + height_request = 120; + + config = new LiveChart.Config (); + // config.y_axis.unit = "%"; + // config.y_axis.tick_interval = 25; + // config.y_axis.fixed_max = 100.0; + config.y_axis.labels.visible = false; + config.x_axis.labels.visible = false; + + config.padding = LiveChart.Padding () { + smart = LiveChart.AutoPadding.NONE, + top = 0, + right = 0, + bottom = 0, + left = -1 + }; + + live_chart = new LiveChart.Chart (config); + live_chart.expand = true; + live_chart.legend.visible = false; + live_chart.grid.visible = true; + live_chart.background.main_color = Gdk.RGBA () { + red= 1, green= 1, blue= 1, alpha= 1 + }; //White background + + } + + public NetworkChart (int series_quantity) { + for (int i = 0; i < series_quantity; i++) { + var renderer = new LiveChart.SmoothLineArea (new LiveChart.Values(1000)); + var serie = new LiveChart.Serie (("Serie %d").printf(i), renderer); + serie.set_main_color ({ 0.35 + i/20, 0.8, 0.1, 1.0}); + live_chart.add_serie (serie); + + // workaround for `gee_collection_get_size: assertion 'self != NULL' failed` + // https://github.com/lcallarec/live-chart/issues/16 + live_chart.add_value (serie, 3.0); + } + add (live_chart); + } + + public void update (int serie_number, double value) { + live_chart.add_value_by_index (serie_number, value); + } + + // public void set_data (int serie_number, Gee.ArrayList history) { + // var refresh_rate_is_ms = 2000; //your own refresh rate in milliseconds + // live_chart.add_unaware_timestamp_collection(live_chart.series[serie_number], history, refresh_rate_is_ms); + // } + + + public void clear () { + // var series = live_chart.series; + // foreach (var serie in series) { + // serie.clear(); + // } + } +} From ea5a70f1c83e348d66daeb7af79b72f6a3026cb9 Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 16 Aug 2020 21:41:51 +0200 Subject: [PATCH 38/45] add comment --- src/Widgets/Chart/NetworkChart.vala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Widgets/Chart/NetworkChart.vala b/src/Widgets/Chart/NetworkChart.vala index d4aa38c8..ae8e8b1c 100644 --- a/src/Widgets/Chart/NetworkChart.vala +++ b/src/Widgets/Chart/NetworkChart.vala @@ -42,7 +42,8 @@ public class Monitor.NetworkChart : Gtk.Box { // workaround for `gee_collection_get_size: assertion 'self != NULL' failed` // https://github.com/lcallarec/live-chart/issues/16 - live_chart.add_value (serie, 3.0); + // why 3? I don't know. + live_chart.add_value (serie, 3); } add (live_chart); } From aec98655616d58f9060419509e35f298e126fb8d Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 16 Aug 2020 22:20:22 +0200 Subject: [PATCH 39/45] fix peak at start in network --- src/Resources/Network.vala | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Resources/Network.vala b/src/Resources/Network.vala index 8d22fe2c..e459b261 100644 --- a/src/Resources/Network.vala +++ b/src/Resources/Network.vala @@ -28,12 +28,19 @@ public class Monitor.Network : GLib.Object { private int _bytes_out; private int _bytes_out_old; + private int i; + + // flag first run + // bc first calculasion is wrong + private bool dumb_flag; + public Network () { _bytes_in = 0; _bytes_in_old = 0; _bytes_out = 0; _bytes_out_old = 0; control = false; + dumb_flag = true; } public int[] get_bytes () { @@ -64,9 +71,21 @@ public class Monitor.Network : GLib.Object { n_bytes_in += (int)netload.bytes_in; } } - _bytes_out = (n_bytes_out - _bytes_out_old) / 1; - _bytes_in = (n_bytes_in - _bytes_in_old) / 1; + + var bout = (n_bytes_out - _bytes_out_old) / 1; + var bin = (n_bytes_in - _bytes_in_old) / 1; + _bytes_out_old = n_bytes_out; _bytes_in_old = n_bytes_in; + + if (!dumb_flag) { + _bytes_out = bout; + _bytes_in = bin; + + debug ("%d", i); + i++; + } + dumb_flag = false; + } } From 91886ef18de8e85e3cbc210bf48e4eda509b16ac Mon Sep 17 00:00:00 2001 From: stsdc Date: Sun, 16 Aug 2020 22:20:53 +0200 Subject: [PATCH 40/45] rm debug --- src/Resources/Network.vala | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Resources/Network.vala b/src/Resources/Network.vala index e459b261..272f2978 100644 --- a/src/Resources/Network.vala +++ b/src/Resources/Network.vala @@ -28,8 +28,6 @@ public class Monitor.Network : GLib.Object { private int _bytes_out; private int _bytes_out_old; - private int i; - // flag first run // bc first calculasion is wrong private bool dumb_flag; @@ -74,16 +72,13 @@ public class Monitor.Network : GLib.Object { var bout = (n_bytes_out - _bytes_out_old) / 1; var bin = (n_bytes_in - _bytes_in_old) / 1; - + _bytes_out_old = n_bytes_out; _bytes_in_old = n_bytes_in; if (!dumb_flag) { _bytes_out = bout; _bytes_in = bin; - - debug ("%d", i); - i++; } dumb_flag = false; From c8620ab6a562ab15ef58b615232f11f5ac77ca23 Mon Sep 17 00:00:00 2001 From: stsdc Date: Tue, 18 Aug 2020 21:02:49 +0200 Subject: [PATCH 41/45] reserve space for characters in some labels --- src/Views/SystemView/SystemNetworkView.vala | 3 ++- src/Widgets/Statusbar/Statusbar.vala | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala index 96845fad..f8ed9402 100644 --- a/src/Views/SystemView/SystemNetworkView.vala +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -19,7 +19,9 @@ public class Monitor.SystemNetworkView : Gtk.Grid { network_name_label = new LabelH4 (_ ("Network")); network_download_label = new LabelRoundy (_ ("DOWN")); + network_download_label.val.set_width_chars (7); network_upload_label = new LabelRoundy (_ ("UP")); + network_upload_label.val.set_width_chars (7); network_chart = new NetworkChart (2); @@ -38,7 +40,6 @@ public class Monitor.SystemNetworkView : Gtk.Grid { public void update () { double up_bytes = network.get_bytes ()[0] / 2; double down_bytes = network.get_bytes ()[1] / 2; - debug ("%f %f", up_bytes, down_bytes); if (up_bytes >= 0 && down_bytes >= 0) { network_download_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (down_bytes.to_string ()))); diff --git a/src/Widgets/Statusbar/Statusbar.vala b/src/Widgets/Statusbar/Statusbar.vala index d30193e6..26fa62bd 100644 --- a/src/Widgets/Statusbar/Statusbar.vala +++ b/src/Widgets/Statusbar/Statusbar.vala @@ -14,15 +14,21 @@ public class Monitor.Statusbar : Gtk.ActionBar { swap_icon.tooltip_text = _ ("Swap"); cpu_usage_label = new Gtk.Label (_("Calculating…")); + cpu_usage_label.set_width_chars (4); + cpu_usage_label.xalign = 0; pack_start (cpu_icon); pack_start (cpu_usage_label); memory_usage_label = new Gtk.Label (_("Calculating…")); + memory_usage_label.set_width_chars (4); + memory_usage_label.xalign = 0; ram_icon.margin_start = 6; pack_start (ram_icon); pack_start (memory_usage_label); swap_usage_label = new Gtk.Label (_("Calculating…")); + swap_usage_label.set_width_chars (4); + swap_usage_label.xalign = 0; swap_icon.margin_start = 6; pack_start (swap_icon); pack_start (swap_usage_label); From c2afc719898ef1e5ad888dcd33340dac9ce30606 Mon Sep 17 00:00:00 2001 From: stsdc Date: Tue, 18 Aug 2020 21:05:14 +0200 Subject: [PATCH 42/45] add fresh screenshot --- data/screenshots/monitor-system.png | Bin 54834 -> 99235 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/screenshots/monitor-system.png b/data/screenshots/monitor-system.png index da9946d8a653631909128249bdf6dcbc4cb8db5d..65d775000bb7578d51419a50e501d9980b3205bd 100644 GIT binary patch literal 99235 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 B(nKIekmw=1^wfz_*Aqs8+3rzm5HYB_q!|b zePBRI*K@aJ&%I8o(q`(rK!fYGe zin&{*_Viw#|6@JwMXfbQt)m&A2GI6h0GX{o^Hp;7s|0C3o&sO$U7zFTaEd~BE_I5h z5?seY&fELx?@?S?_~|I0u;<_lYUX#wWP#MFceC{J2Wy@Y6MMy538Zvkx$Mkt8n@PTv)7tjWWBRPTi<11)>KcKpax zp5FUHVLe_Z6^KhR0LCujFH8>pq@jlIop?gFYxfT}OJTGRf)*FS=j_lwRZWh)Qr*lr zpas1->JVXJWie_cuiiEPsDaYu!XK&S` zY=qf=4~98)(SA4kD;RLf*Eyu*1S>yLx~JgITO(I%QslVZ5Gp-|jlVZU^jT$a-#&}; z_H+`9)p)I2DL#W1d$e+h6g_@K+d{|033a^exeaJ${p*`8E4IHdEgc=5Ga-gZ!=d

+dj0`{2NigN1Z_d>ZPHTbO7`!#1$>kKcO= zq>#ET-uK%5tUsjSbE=%=I3Pt>SZ6)KnXgx;C3vwLcDwKQwSRsP`)FdwRJ-$jt7cnZ z%6Y>2wAZCRVmDTW7K%yg`qDJXDcbvVFeRs?WG~hb9by%{)|F3Jd@f9<+&A*Ie!NXx z?v7(yjFljD6Ga_uqm4fu^y-!xa9c^rBC@SjbeXgZ-1@PA%R?+;dN*s(d$HkqH?kOvHu+;4YeqXG#yN~UfT6&=581p9(#cf4yv~1E{;{`q>P(06K3$h7=<>43 zloMPRMDP-NnGPfS$rU-M(kJnB5H3Y3z$_pS4`~T-NcZDjGrwqN9-5lsH$v%O>^%n0 z;|6&C86zGcd3;ap!GKKl(XEkmC(VpMr&PN-BX0EPwqxxgWl58(n10D?-M?qiS0Fi9(b2*grRaWEw`{<3nWj1 zNpDAAr&>AY>9OB6bhfsoiqj>2jFGPA92YrD;of*sfl?&96c*Ka3mz4wVgW9YT( zWXC^eD|9~mHPn+PN%jOus)*CW%7%Qf{JK8p$Tlb3u9BhQVal!&BhaeW!=v0`MLu7% zR2*$>j16b@UWcVAAY_XOfHhv<*eG||o;K{|DYBjoP4YP0>=(JqpP_AAr)pCP^r6Ve zt=fHgbW&)1{fg|gFVGQ8ZwJDeO#SX(3;Ob-30}iVk8K&a%I~SK(rI%Fy}0o9I&LN- zwa2^G%v@$Q#(F-BDcEP8l@z_}fEy^XlIRe+RkcD2(ivEEDaeCPe&mocI@T}uCgnOp z@>9+?O|>el;?UVNE7@Io=4_eEX(>v5UH@W9zswXyny*zZos^VxIu5UICE>k_9?Z`V zLLW`8Gc}x*phLdb3hzvRFd!eG6BpY0&+f?u%_3j$X=c2U!9AUfhS^q5U%)5cq``7?o-ketYptyLFL3vf6CcxLiKm+?hbT~i<5y8{` zumf=Ri&&?w<(`BrkF6>R5N*`y@dts|FYUTgNQLnq#^RDdGSGJ#o{_}s(#ed&!O4ls z6F9gw^d1BI;BdlrB_B}#;K#Rkek(Czbn4BH^V@%D0bFLl#oT4MW;{z}2UTdJo*a^! zx1$!S470kH2HFHK>`1uZzT|b@Y4NfIXx(Q3Fn-v*TmvN+7k>a8{(Y0O~U2^@xSzFSrG+up9c zEWV#6r=(Y?-T+d7I7eDuWu-a@CNWOuNVw(6-copIo)7-58?ByGX6&?GCE{L~ednm7 zje6A9U=P;}pV5$}lvL1zAkkLXuQ$bwidKI{i+2^Q%hFqJ$EMrV!Rw<11&o9Nsi2|^ z@hHB?%%tKW#_fq?quwZvHvV0+mzjM<*X%|!z~n%YoK;^h5ET=1cMLu&_eRxC-vof4Ow{z@9$47 z^jx9?WjDH31|?TUeEgHB=;)k=27Ppfvn;I31ofO0n`!Tm&&7(5#l_i)CJc2js9<@t zH3jlXJ!La<=-4)xxrGp}bvpf%PxT-!ttUG4_9yduIBwS+tv6va4M|ZaMTR;5S;0_j z^6`f*r)yaoVLoT+$!^Pp){{RJFVAN#^9u?J8e7hDb92kh`k$Sn8ZK)Xf6TsDoO<;Q zj3-wue}GzGH|Tzr7kE?LDR8nZbQn0@(7((9wKO=}LiJYlMoFmSpA7YaLb#0PTUnV3 z*a}V-p};ygf-TYdxMg8a2eMYLaI4|+LXo8AO$%1OM)5Oh_@9cZ{jqS_HIM}eE87-! zYjxR3!%P#E%+>#{=9DcKNzccL{{6UCCGt`2wReNyf^+3WQl+IHX;@6P||5fS#4*hqTlF#beV^RCyY%%)FJ)I*u04svC^L8d}Y zss_yh&1wHVZt2gujIUJ8>7dQKCgp8fLn#7#GctTrg3J4{0Wy@KN+;dl&U&$W=;N3w z(<$ygLeCc7U2?5=9RA6?CJCw1B%vIj7!4BDVU$a%alnP!W~S7Uh@L*%>rmfh-FpVj zz~LE6!O9kVq^3Uq1nmdRnw@PNwy`9>-I!?aRD@g%)=?6FXFN2B3JuT zk4d9=b5&P#^B~)|a~y|hXY*8o)*`xg9@ezvZJwQ*2sgBCxBD;!oGRC?%OG>;`g6|v z5f*DRnIof&7`hxe_C4s=PwaFq5ln11KqKj8K52TbD2AUZhq zYm9?}==LU8oNRWd#y1JJvrWX)B-xJpov>~BV$EpE!M8cT4mvitS*!Evje^vo^|Qyr zTNOi?WwdFWC~(bu9BZ^tF6I)89Abm_TL!$OHFmE#vIsa|c(bL>ESPFWCkDunma0HQ zeQSGt@sH&PPgK>-1G31Op0_HgDOvA&K?tU@M^+iF5xRxnA1TsDois4j>wBdCeV{bd zyjjS#zTQuJG%9!J(y6=Rm4|4fMpO=M&LX?RWz??)mZ~W{pI>qX#8bAcQ7UbzxIA=; z)#l^Hf*!o92!!g>doRGoX>ej9_vP9u%84K|XUZwZ87^h~c)7UbEH-?G>0JIv=G+jD zf}e@&lZ?I1Hibj)wom`E2kGfOcPE~H6T`d&V)2!Cv?=bq&n&D3GE`V~H|?!j93hJg z`!8O##Q#aZv&ZOH1&~L{?PptQc`sW}@C3n(a*%%twLO^P=CwaY?;8~QKeqq>+-Uwi4*V4vBnG~!jc3-$;eRm0Sl&Ou^6qhj=tgefWB=d0 zKCo?0HG7T8nNa!3eX2k6@&95s`rqHb{-1k?)>Xm)#mxu5@6}h1oA?*R|Cd6I@1%`O zvCN+d;GDCs`lQ&CSf#y>e_^ahWJ0q}@>mTAAA z@YNwVeUYbgQ6>RV&-4-xfIqkHI8!yvhd(#~vlurqZj}z>$+khQkx!Pt_U>4bAg3V~ z6TJFl=Y20`!VVIx6H2Uzdg>J&mggx5h?<#I)YLLdN=n|u{IPIf#n%w(|4*##e-}mh zZ&+b#H)WG9_=xzy+QoWl#(d40^3W?nK!jpv~1 zPgK3mU2JJtJ`H9}#Frgb<*&=Glxj%Xw;K?!5}*AkS$(tLJv4g%mLLE}1k2W4$?}Nu z(j}L?*`R%nS==rlK{3B~0{X`dg-Oi5?y4dfK&NAO%e(9JMC7^=r} z9B$A}SJs_4Sh+kd*9(m_Z@EMjR@WBmGhLq6RQtegSD(%ZWaEvGtj$Rz4{D=4j880` znm%fpt@nkt!3MGV8{}nR0Q3hT$w1+!v+KZ$|2j&V=P)bOb^TXGW@pDl)w&`l#2UuR4XA$MDbFy(k_=xEkrD~_Jcth`~6I5AYmF}8osdFWe zu;_me7&1ABO@)~)7!=|sdxgs5I_IwK)*#!ENhOP4nk6l_l^go6Cp^O%=}`>1^buig z{xXb=zc{FA$blZH=(-`G7EfRPspU994g5}nCI(-}^Xqbz2eLH+X5rJ+*Z)<;sx4vs ziQRYS6A$E;an@Q>SFcLQaAv+XuWI>@Xb(LLg?b2nQk9M=eNKO{TSyLblf|@$q;8ML zkm@cYgZ`|dw!`OVn9k-3L#c%OD;?$gcdSDQ;_aq~PZu!-ztI&|iH7w4aBiqS@yQC% zl7>89U${I|_1Z0s*~m~52`3i`JlNd6OzYXLsy-N0UtRPC-+}$d!#91`67hnfq95_; z#uT_JUY0v2k@`TTRhMVwks!=y(ja{H+D=dL!j0OQiLnmFqAC*ou0}`6(^*S~67CPL zdZ-n0Y!7g53-Oqyq${sfSRnL|*7NxThtjbalJrwYr#~u1i!3#=0?3Y#atW)Nl8#tS zf1FN=)s$htGX<*B`J`6fe!{_>F)8}mRn=qS8)m=9^|RtuKNYdE6CG1OP2q*SZJwJN zzh6frx$RG;L1vDHGlh-kGUt91Nf)#{!Og5VQl}p6l%`3`T&@S5(+n1S8LA#5Rv4!6 z>@=S&PFvfECG8xy^2}P@t8wC5{7Jeci&4*X*FVXGt{Ly~++^CvjaI3Cwao*|QYV}F zj(J(~3Yj9HD`evECms^Lfvkuw@+&@W@F+<9%2_UUAyD5{`Z`V?E5m8FyxiTXO#m@b zDrZ|?CghP0c4P|PDZn-R;{!Pwbg(osHRlh%c|~D%32!#+n5iptMTNXJClY(m#&a@>;z=b%e?)=Uq~4&Xy6!Y3bI?THTBy8h?B#OP$NCYc7_aaF44Sjw7K&(?&ns!%Vp%+mlRAsVv_UC#Y^C6>xOJYxVLZ zHX0^twi4iEvCaq&ml4R%jZr7&y<&Y!X01#Do3TbG3p0JZ{`6|ykbLl;ShGnT6R|D+ z|16gozHXmmUn)|P&dh7DWs~E|GBDUwo;R)@YiZq5s$wR|r=h%r^d!9EYfIp?7 zVdEw=QL-K3i_A&(1mRKgv>adD?(h^+(j}?UT7w|z2r<$yr^LMLy;AW`ivg-k1Jxw{ z9d&(gcdYDB(XY8lWgC#L;lM@|xAW60>h_WScSH8hC1GO~G+h<_n?xKVq6zotp%EP} zvi@a}@^uag6m5@V;+Xa9dG-T#$JU`UdGT=Rj(c>P!Dp9}u9d-h+D39seKZqp~p zZ>$JjR*g?g7{_O3Dx?&k`N;hhSPX@eqoWyeeHehq(am#x0DN*BGmbF_M9p}eM`c0H z76f^4unO=fc+JeYO%edJ#)}O6M)I|P1Lj~)ucWRXBd{L_`wpl|A}*VuYNw5Z6PQo^ zs@LTrwP1goX>xWcOh7wZMH)b2N67l4ItA(^$8c|e!R6-X%VnD902G_-q+J4Fb)U4@ ze&0zEmw1}owXPT@IGU0G2n`zlQ3gaIpj0l-Rs`vugrH%7;bC?C{OD+WG*58n&K(O& zOJ%?<9Bz&QN(+#1jGEC;Vwh9K>pa+w?S`OEXFd%5Lu=1~6UcfzGc zk7{n9Z#I@$@+sB*F38^9ajV9!69_e3-6R0qqfvPVy;=>xACCX9OMg=w3$D%Ung-!N62>b@QDzMzU*bbpRoRrk$TWd14fw z`GklF34kf-a6nWH_4R!VA>y(aFEa-wDkA)wgGN)BfV<8Z7#Mg{&eQ&fNd;)we_&EE z!*~#7gO0sCE8lBtYd=O^JB%!OQ0;XjxE4?)I8w(@xmueOW~tWk{!PqpAV;i4vP|lA zbHJU`B_^M2uvEHE!>T!Xd6B?MAF1n*hqa~GY}ac8{v}04T|Mgv7*=>jK)_A0XZO*( zH@h5wJQeu)`7O-MxJ|}0&Eu;#OS&G0h=1;%W&zYHz<33qN;Fe|`q8R!&PTIFr>Ccl zhSD-JxBGng-0D_r<26|oWV)vFmmZPz$t2x3Y1O?mh<&nQc{HB^RUby9=~#P1Teeb%YmtQcw%0egTt=b2)K!L#ANIl}1lc=}p7WbdWYSNFm)Z^y1l_zs@Wx?#KYp9HWCVQ4REI^7jWYd| z{$dXL9=`q1z_Wf2Fs=2iEi?sBkFQJ{1u^-0F3g4_l4*`RP0mJuvwX%FhgZCP)qj=j zMYJm<=g_rl_KBH%p!RUV7yx#1-0GD->yV&N_wX+H_>Gal!F0e8P)2mTiDCUyT95ze<%l~a{nB;u?v3TvOj;b}exOytTwE?dn#6K$ zp+`b>bNQRxOR(xZcf(12&g{+sTcP6Pb1}jJaa{c(oZ4sSBS7Z$c)%6aHe^hbuU<_C z_sbXTpBtS{8!0LD*#N+d-0eRcGAOX$OJxlLK7hp8hyBU0VHkgAoyXDoUKbNtEq0s! z<*7PaWT39+1~utT%nl93JqLUV;Gy8E>blUqJ$oSj=wR<@T$piPxC7J!&CH8OsPeaS z!bx6-WA>2C3(I1Yo+s#2q?~k{F7BU{jQH%#3Z0x^uoT{p&bO5UQ+Eo8v@F1u07B59 zChu?3I^}fxUUImtU;e`0jv-SB!K=&)n-YpgDLAWG8{T*m>Zzcli&# z0PTelL2J><$F>Fc&Eht|j7HItJ6b++lBR~Ih|cyPMtJa zk`PuoyS7l0oWepfRbTd8LBP@Hspq z1#v-bz3MKyqUu%qf}^}mo4tqMqrJicMobclh@g}S2)La1y#;X=|H#>h!$s0pLXXDo zf!qaUtOK(k}$-1zM4$7}C=<#`chjX&4S04iaK`?W;QZ?eXv zaM~NF9X&zZ$!^qxgA@wDdaq4GGG*2{6?5}!3YvSja1I%znCg$y&>0{?LBQ?pgy=e% z@*rN|b|m~@t(mQ!`3EBS)6oXBAn-GOT6v4M%33^&QNrNc&J}v)7ySkH>Q0L5=o-xT z4e+GbZ;CZq5rAIf-*yWF${rv@;@(^V`k)*%ee@Zh;mHF6<2Rbo@$vCx9!ECTGxfTF z!Q5Z&A)34dDZdNhoC~N3FE1}GK&7A;7w8JmNt-l`dciHdfAs}~#NtOiB@hdl^~7^P z=04y74iyT7O;SqS#A<+D0(^Tq@DwGpZ!EZ@0V|I`-I6UR`4T z%5OLIrTOfiKo$E=Q7!JqwX47s0jV5}V(1!3u&t-*Dp_={kx1O*dF!dH9D&wQ0b&S9 zpK#>0gInH=ms`ew)CLH-#kbtxco-xKEF7H(Kr#=h3Y-f*h>Owp)-2YL1=MTrm+9uY zBKocYAPsVAB{W@)RF+o+6$z)+DD&bzNOsDAD+8(^KBN4SpdrD`g$BO1oEjF#%5%@%kWvDi7-QAq1K>Vr+jg09 ziaFfs@qFBv{&<-zf9})l)7FVQvNGo zv_WCTievcJ5e~}9rTr6-#<^T4fpmcb2$z5xngg2xVzwk;L=nY-R$eBjvYGWqn`7ys z&r;E<72qfHvxn%avU)k*5=5$5cMDLs0MBNOv3&bb50qx(yx6cub+ZmW#Bd0z%4;w97+!p$a%}12U0|9Yir|zzR$UnROb(YNzrv5 zzJWDIp+a>l=T#SxHW4kwlR1O!QwX(Fn%;*PX7 zcg{mG{v*IWp|bJVUkrrK8-7Ayy-1GC%C4f72teqCE*9@-(qEbZRuu$GRvZy16p9ug z^z!Y?T2I$%W~*4VAGE#eR|N!KB1Lv)rua&V&jrhhBP0nhmWBl`KkDgdX;l;zSv0ok z3TxBM*mD32-!b=gHC%?VA5i=0x;4%n>~cxor)z$x24JIszUuh6mRyQ}m+(P&T;buZc8VVNpyn( z&zm>CRv5c;il2DT&b9B1^R1UJd_R&9G<8oT3KF#;OkFYD1W663D?8kE6coa=w6t37 z*Kem66xg)47Z=BNd)*~axNM_)i1p|!zJ+}Z&AX!F-K1L{{0 zeGOz&c27LHWZdoBB zmy{?)Ma4-32Dcg|;t3?zQyVrEH7s8+SYYvIg)yB9rbFrn*hCP!_%!=+uN@eTDTh)% zwXYC+FDA?os@UepM1>Oi(_o=zh3Z}a?8?hzzz>2AOvveMFsy6g1<9~!Xs{^VWC*8w zgf3R_y>C+Cusjvp_cTf9w`5WQJ!N}@86=HM#1a{jPc}rn9R$hRGfcm*sw&k=3i5Ny zv-zGZnsCiz_+uMR@b8VhZ}!Kv#4BGgiK<%MHF3fF1#zn}HR3iue2U-t5; zy5vn8Wt|mtZ=~MY;puufhx_MpFVL4O2AAVKJd3F3yM)It@bCWUopXq$Q~8-4!QXLc zu-(n`ZHWH=V(P5|vg)F(VM0ofl(&x;y`c z=bZQZFT4@hvG$BH#vFSuRVOr)Kc)8j0Pe020 zclDVP6~YX5S8AIi{4qo?TD7#wM+={hT;t<`0sJxJVEyL(WqXFWR(UQ zdgzIu|MUFkRft-AGqf2->zE~f2~}w(^kV)O=u$pi$}Fy{-uc?^%(gMOVY$HPFSDeS zDP7Y*P8{{#ah- zdmBb$+AuxD6N=cVFGeHd=HZ8o&ac5;udOlx&x8RzQg);2T2jh)2ZTYn^PcApM!qtY z(z%PB=V|-(g`owwGw&eZxN$DO0xv#Pt#ILGifzgLGnS< zl{$88ZE0B6XFg$Nb=CrBfB=^cOboRwV`h5SC$--u>+2p~rcz>)lJZ(8v?T#TQGbdd z@rhpNx#F&6C@PT2BRAj?823)Ut86lP^R8}5Z|_@-M46*#DcGE&#eH?W;nTt6M6|P4 zP%9;PXn+1aH2#-!B@CBL{Air?&{IMG9p*P7c(TUifjn&%h*wB#_B&-(ms=fQrh32d zImw=jZk1WJGCIrlW^(U8mV_6IzLp5WyB_)bt*zbz^4~GPL>_#IG*ucN*4Qj&QV5Ah zEBMPqJW-)9{l>FkQAi`8phH=^>_Vu3lVOojHW{juCsQaNZ0H`QLtsz!g|@o>(lt%l zxqZ1dys&I+r?cquYrU?1upChs7FoEOd?YMa-2XqdO>y1p^77!vQevJA&A0ETgecMC zeNj!13ue)^{nSgpb}o90hL0%Ka(7OZ2P7Z7PCpf1&SB3L+B+lqK&C2;+e-6r->W>dRwu}4Hmq9ybnsLrm)>%_tsH*-TEeF&7!*c zW?noYQAOqcwnp%uU!|^KlJ$8w@Tu762-;~Hm+qvdjaVSQe0Rxcm22-jtUy%|)0C}? zGqkqc1J|2YvT|;Imd5dUPH2h4>O~o=vQ%$w9rf*O^@Kj_l;nRPJ%$g< z&z35DUSC=EXf@%APg>Qy*eLmwL|(JN>*UMzDb586R{4tf-0wgw*jwADwbEH89+XwtlWHz-U2ItsORWDRst=@#JYGnTv zh_lj*3vS#@j%mGqIdjv`*;(83#qXZOw2eJww{*j53B%V-Yk_=68p(l2nQF3Yl8x-* z;O*4j$jNCkwFdJIE?vl8%7;HcpJaw#&+F~kYUQ~P_&Fj62M#9_(tqv8YM|=k?hSv- zCEvS4T4*}IznQ9IQRbTg$pr($Bk@!xV`Ly;u?L_edIa3s`oSM#Kc`DntJXCQkG+GU zLF>sBULa-7sjYqK{ax0>seuGWJT>t5b80Hzu5aUV>T~HWbk^hG)B_5ZbBBZf5-sG; zz4MYn^~m35EfHmLmW6>y`B&4n6i8G@g{h%XX1lA2gu_^~03E$c$SIb-kyJF>8t&?+gbB5rjzabA({Bh z5|Z&l1`?)+2h;ZUY0Z!taDvqiiuNrkX_`YUCF2thIbO znAr(AWVHpMQ|l7Wu#nXHaa-m+k(?ti6ycXMOl#3hWDDP?I4Lg+$tsVkWowUkSfM!3 zYr;Hv>S5oYJJO>U%*V~0kJ9v6T)mXtyzYVPBa4eVIY^~7d9ZQxDafR5`G|V}_=sOA zk$AOiDW}(a+~L8cG8#hrU$vjpFQk@O4Ajc2>fAn#!Yx%&?jC`nsiCq}Po<6kQ%?NU z9esx-4{R7HNRx&MWjDTlT5nO6$sHb3f}RycgQxEs)dh>7mn0F-VH)T5Jxxxl4^AUc zm!G5C^9ob(o4Ii0>{4sV8{GDTMYNI$l!pz8TIT0WQz@C;-LH{h4CDhqU4~x>m0^oxifpJJ-1g_@HhFRGd1_pcr8l>WuY;6G(IWL~=vlD@|DpuTY5T>|JHfg6O z$l2>p-9KuTU5g3`lHD?J_3evA~@$oe;qNUCgVzh+)s*szGJ!N3UqYdOgDjcPkUfNXk76(OaJ2%5$X z&H>0-67_D@jHw*7eM`yH8^T?9nf{9&*Y3PcUz+|Ha!Go#6V2d8b6YYm2>d0DEXZ)OG%4Tg3@C|X-TWpCFzy#H}$M(;~8z!J0Aw!acQBv z4sL(oQWmfu4~cDEf~}GxhzvRw1ZFVvk<^G=6PL}cHe(vjqlj>8~oju(Ukd_{_;sTN4NLHTJV=-*WgDakz(sRTMK#!*!FIoq8}# zUT87sa_`81x1ipp9m5y)+M5o;a;GEiN81N0MT}&EqSa_>JkL9%lHXb3iBJlnQ3FIH zn-Zvt@l5rki>VonUC8U)<7ZuKeZ3#$D{^kwob%SH;#FD-P`axODnz8ry>yEBS$? zk}0=zCS@rV3Deb|{Z$c?g7!wR;?;e>Kvs*Hp8tv}VgB;h>tHn04uGq1uFJiM+teTx zSdBOVoDzi6=P(A+|L(B4PYL0~7A!|D$hW?``AkmmJ-*vyGxXaC$vHePsc^V~V9O%s zsXjImftPbCsabhG>0K+u%(_~nw6QJbUR_f#qSG z;5E^v%^yr-7rl&9zs$|S=c3km8LP;ky#70~)%ZWD*8iA+0F|DUnoEU*8JJ4v*_-HN zSiQ-0&zt>S4_GDA)2Ou&CAbs76&mc=PIjjg<(rzi&}kd@bsxE6AF5cH;gJR4n#R8V zi)F2*S^s!DMrx%}V|0*c{*`87N7iwD<4}vTb;)Xhn0sMx-n}MU%tGRF^WNq{^3HQO zAK0FMO)%DFOIEZb8iqx>G>v>HkZ8VDjqPum9Fv4x3Z7gF8ss@-);g9<2|);5OWEr3 zRxbsyZmm%E-`8iGbUl(Xs?=P(<%!(3xslxG{rH5l@Ow$Y#P{?T!ehmN50sA&r8-Q2 zPvcZ9x%_&!L8}JdW#Je7Dv%a0s-IcSn4ZwG_BMl|dAvu}-L?3s__-G3$1K@M--=9J z5B#Rfd(FjA~KpmZdSR811|ldeI6E z8562^Ui5~o!otC-YbE5zU#;^t&5hPW*(XFl+z#PCVX*)43HNM+cb@O&(^LdFJUPDQ zZ-0;dd#nIOn>JLe_OD1IoRavS^V6aM^a-i)dU8F!iF2AcRi1ugyB~u21;I6yba53P zt?)$h3Fg3|s#STSio3UGTdbv~mG3aDtdk1J;{Sz-Y%Sw5(fy66k(wdm--LW_(0gK< zHVGuSf=BQyvPeS?Mjf9D6B=Qm^T=4{R(b~>H$njR{z>#nD}IJn>HA9R5nRdyx9_AU z{ER(kNgPnFIKDgc$b)_r&{Qw39*V!-GJjP9l5=Kt9K(B1xf`DqI-Y|QbK)JE}G9UFE2+Q$xskgbK>vlcS{w6AK}9Z^@TvH z`2huGTR7Aip@$$#R{9{MF*3zwUt(+_@U_`<6k36Ga^v1r z2T;^1x1ZLDoZ+42EPR-dUVDu5?7jJ8iX|N9l2_}pHwhDX;@jXZG7i+ zf}jPS_9mOvXAI9IJn!2$>irV2PsT}`=lv&I(jxLey+-iV%?!R!*r8gqq4^E2BI!aO z4?=3Tj>Hl8s|b=L1;C}Rhbp2a1?%?~+^ElZ^X5J&bo8;fDwL(7f1NZM(3{vXiIjqA zM1tg~pyx9&0m(=un?d!rx$1V|MBbw5>3iJ0LcjtxhGX;X(UJLz63NhE z2zUV^A_z8PU<&>eweyG|s;|!(ldzqdDH(hRvD5evovkX%So$Mw&{Z)I0ATm&l;>z* z8}2QGAKYX1%sFcEo!XDOfbX9nq#Uw#x#qE^3f_Wsl%apb>-jh#A=w!c=elRzb_249*fmG-wIk z1M3oPG3a6aK$|xhQ(P_!GZIt0A9Dy{1$-&JL5pQLxEeF~+1Q`cx0TsP$%#@JFsW58 zy4A%$#Dwt2)L!70I~h=MY6hw&)d}D6c{#3UmscqXaouswd#=`M^UA6z^;1yiEw9`+ zL?7Ev5aV09U)iz2uvmfjgKXV8H#GP3BlCL>OZ(4F1;zR)Uw5rAuL;|Qx|533oI#OI zq>s+;58IafysOItKbN8y2d_+Ng>Kf>{16s2)mB(-M6&6+{iq-I?of!FdOO=V&8Fq{ z{#fU@(dc7Pw2ioUYFFJwE9&E6*H?=LCUN93NlGHhfFG1g+$Hv$4tT%$$XEF-7+dKa z#9Un0s!jDwc=?H18;-$^et{$ny>P1%r}39kfhbpKEt_{9oK*EYgQM5Wz3=R#=8#N^8=E%hggE5Z9JjG>#E*_6 z8y;-FXsv4pUNT+5iA;T^_u@Q4c+L<~_}=;13m#7(n@*}bhg^K8CJzojU%9B6v;A<| zXgBA(TcA9VQ<526!Cj5=QTw6QMPgUcMF*09ys>dvS@=qlIv|Fl z%l?xK-@O{QN&PiqS73QAG-CY>iL5ww^HJ5Il)Qd)Cz_<{H14CrBpV&KT6LQft zP0E+O@|?-BCOh~AiS*6GzUs|U8O_lB^%=9{Qr}4a=2_JCd+CVJv zz;m4)RI4kj&$$-9I!WhU%R4CR&!NXFpdB=(|F{vhp; z+)rM)$^%ZL<{n-%h|^>EdZ+s+`{-0rb43{X!;1OBT6fW&)9dRV z<5hyl^H(U8=fUD!;>fQhXn2E^Ol`W$R6;@Valpxgu$;^#7b=sgqTnQnJ=-H~xUi~p zTJ0XB#iI(fRzaK5S0iZMZYrsI{x{i1pv{;Px<=0BM^S3XxlKohI`l!RKim|Kl+7cCIse z<${{L-R&{gth~n8So60gYm)~~gC65pTiwr@MFjFCG$lM_@^||X40KP-y3*em;krfU zj!2Wwjf2q;3?n^|#AiNrQff2d_dHDVGL61f>D_vfk*R-hw>@;nfmh`TN;g_p;c; z{#vej2kpYT=6H|-u4z%O8eQRY5W_r`gMO5d??lTKqqWXjEAkw5v|7DXt`x!=j@{K2 z3|$c$-E8}`{MLD~#(Zs872bX5La*#hSe+41_@>{HmM(DV?B3xU>HHSy+%p%5pZCuo zxu+2szty>0$eKHf8usp(6L`R~F~4=!owTPOHglnN6VA^boAi?NL4;Wt-uT^czxLbx zXzsabh9`ChjY|)@;O<{fh3pc9PdHWg*3m*ixQkVvO!e|D1)Epwn=rjbkNBZQ5s4iZ z-$xA64h<(fU3!8BbgX+isYS~S2aqWx$)ArQQ|6$J%|8>;H8zDlgJGQtF&m!kFVkds zhGBXDUlx2xEnoqW6!i5`{79?qjiuy)a1TcEDQe46Upd8|PxQ_oN*H{-7#~b^vQgiHciqF@Ml0DvyRsL~j0Y}mF zS_EGUg#Xw!Cm^DwjytoPQr5lF#YiAWT3K#fgVh&B=p}l5x+z|*HwLv$K7{MG%D>hR zUKnd76oGo2&#sSa?rFbx7g~A`<<;{Czr&U)qMRF#B_1O3G7C#whL8>fdQpAEk!@ti zW^vJ7*ruPYJz2Log0P1!4jnW4d7-foXNZs9M_Qth=@X+Z)l9)mENn@V5F6=e_mWj- ze5gctGx2?&o|<(M52s#;r`nc)2Sp31{JaIXY24m%ad-RG0In6p5+B#^h!BnY%&fYm zvqymKhk)gEy=k~-MG3M=@bOKa#ee|D$Pr)uF|!NLl{a2Zu`^wzgc;W~^SF(L*egN9 zEA3lDoiQlCo}Es96@KiViyDIo)Q@>3xMH$QKTv(yVBvT9b=ox7NjO7w7^e7H_WyM0 zfxse;3ZI#ecN1OqnUxH0g*@O5@q*kYxMGEU>2&fB?%_QI={WpxEo1E<-*1fP#bJg+0N+m{o~u1g2wUa({I)EQOCyZ`YayVNELY1SNb9(4ZR@$8PM ztk0gwsSNVq;@O;Dw7nhbZYwrk6OX3v4LbNV(d=ijq7x90&I%%d262ro!Bx~j5KYTv z9n5}oVgb5DLUFl}?1i!H-)XSn`Xg?8MOBw`ZZ#GsTE!QP7*Z5pL6?hBQW9uX?m*(l}Wp+x!B*pYDjz860*=Zb~BP z7|%aUhi|DBguT+-DQ(4YVy8roZjb5i~V32y!WwoI#&9@Y_;v(`?Gx2FZq@NPbGPM-!I_=9#4x=-3(|wY;?m^7Fe~ms&dot^H}TpGdq?Dh|9z zIy;B1nf8a7rZT1j53tu1YWVRezmZDGg{T#iR_Sr^W@?dYMd@E6?q%f1`8>f*bO?4Q zr(9v5hEkgE!q|{;8dP$J!dmo%-NS3Kqe7Grn;kX)CDk;y0(8;j! z_QHea3TDk6^>oLapHmW)$z<+XBSuNL3K9@Y%Uk5y0J4sX^~L8kAXpKY>|hxxzf3>z}5+>VXvW(VWuA44J%i;Jw;>?qM#O`DYa2DEN(Sn&qY zJBJ12f<)0Y9R(6rHO)Ut&9dW52L4=mFHy!~O5Vc(*)$Hh7T*#pw)s8y$Kj&>9i)^) zqWU9-2l`aCx8Y55?*Q*Ae0YohqsRkpPS0fOS_g^T>H^pSrjxwvkK>Mzh~vOaDM(D$NMXr6mtheOs3 zX0CxR{C?O9uqcU&>?01?uC=(^@)#MKwn`?xc3&Cij>=0g*yuE?Wqwt(Z#@}3)+ctw zw~L6KAWH8^>hgbHfYw&R2e`?4)^1`?@@JK8*9R7qJaWJ9Mz z2Xo9kS)vtyHev zz+@*P8v(yxkZ!`pz5u2-N{L5w>69dDD{^p$;OOfwNQnsNXI^SwQ0%ZtTt0u}|NK75 zwt0Lq{JuS*;&1LkO{sR_`CSW<>vM9gBWii?Nv8ElgVQeF7tLk3ONVdFd4rUtZ5?*M znp89TSfBBabgcP5Mh?L7YEA0Xt`*>vHwp!{u%@nybK#3~@u1{MGK&e3ArYYX7x*KG zEYOyXcYXcjeT2*8n3y446JL1jw#Z#i2z4*zzSCY@{*8Sf<$1Mwz<9iPQT8cmm+2^? zxwv*P|I*awAOVx{Lx{Sue%XVaOEFcLp<<~HqhqUsj_`sF1FqEfDpIoOe8VYBDJ-&R zU_m0v`3^ssn^V$oQN9^mGY2SyB<_yr_z$99J~$jXGy|WF5}6a>CYk9QJ ziDN7~Dcbmt?1~z0tx+Kj!n1z|Xx37S=5Ww>`EQ@oTAM;DIV6z?Gx`q))_M0eLZHfJkT zgMq47WP9(&YADf3tdM3S(ku$^*czZ2x~c^@`|BTsK}#lHy6o8=9@)lg;*q)0*)#h3 zYS9T8s*b6J5NU7!)0D;M_|TM!bl7lt9qX>_>{cF+;n2aKD+j5t?nphmW`@4L>tv4n zw~qUB8@fTh>*>$yWHLhcP_FnL7BWut%o#Z)b}H8O9e3`$l)oxDweMjPDTuVXISJg3 zX3Xo2S^Q1W`|jN-cUT{vkpLUsT{;dJ%=q79)*$k3Ee0G?rqk3=0}}$HB%=+kiX1@A zBI$xu&6ahr26s|q9Vsf1Q1x!$1`&phxvUd{7RI2UX%`hcq%OGNwv^vl&$l=eFaCM> zaM$$6IgRbsn}vt{zfdGZ_UTGob{jb2SJ#p;`?NXh+gvvJlKTm8Uc4F{)k?xt^a}tD z-%fwoynEl2M>ndu0zU?m?nTP!;UQHc3)yC;uE$H^Lt_m&K=^?ya_)as4Srs3jYMFq{dD8f5`mK(jA0Z&8-uCzc zq&JJ?czg*fW+&X8`$?>z;u$4D(d37_*@Y&rSi7X%ts%fzW6`Hj1!^9CpxI8&6Ejm@ z>X@ncwjfr#UZbUQ&7Dpd5PsU$9yhh$-+7HS5;$NT{Y~OHVZ~s6%a%!P{$N>1^FWvw z5Cmd@LqL__5E;ibgZ!5!3vVSfa?k0%?x2r>Yxuh!FWMic?1 zSeL;LOoOABjP?3l4DNVh@hA;amDa;`$zTo~!oqOeY2hE~AJ6teTYNTfcgTK^)?f$Y zlo5#>00N~sWgEIFVsW2fpmT-wote>!$rBB5DHRCMoS>6NA2@O5T#fQn3+ns;bYge> zm+;t-<|cC)wxV^W1?@1ZZlvgo`?f!)*y1qn$+E(p7#Dj%a+L#|Pc(++$;!Q^Jw`+7 zK)*ev%JaIyY7p$5oZGkr1tjc-T*5G{~6L*06LI^9~;;JS3Ob}x2rC_MvB^7lZ zlPE7`z^nh);?2qy6V3El3}h1!sEyuyIkrJ7Uw zaU&Tak#1W=k75_eR{}V@vw%7%x@z{bH5?(k@h`>$xG9b^dUMgJzaUZWQfCfQ(+EaL z>V8YL9j|*av0Zs*j?c(X&^`AfJT+P*tZ1tzfj|AMTdntfxh9AAy61Q|DMZKQHW(cmQ=6TR-Abzi*g~m~Nw-c@wZ?XVQpLel-fq*!=5z5!tBig-BF!a8Y z>SEwhVx$asnG#N^or~C(?R$<)IexO1spfn~UQef^F+-`%g)jL^&{8%ezD%;JMG#uL zRn;KMS9+B0pEhRdwC|o3Ay@4zjS)0nb2$7ZFU(eqRQ0XGX3xs1$1*|6w!`-az5wLocl z`nAF{=|E=)c7!ovOdN+=y?%)hxf_frm)W~g!@$5{T)uD9nHEdMKg0n{if;hl|5+Lq zcuMWyRn~-YNvZ1@e*8p{mYLe0>+5h3MMvnK{l&ykMDIBTrNZj**wX6B$V{Y7ZH}-I_zo|x zrT~r>8*e~F;wY)*Q88)wf(77oHR~-B1=M+_h*eceF4sOAaqr)TeDhiB^W3s0*!Al5 zkxFnNyuqp2HRMVsl+12!ipd>YwBBBagYN@dud~A0WC@fG%mjPE>n(3KgaSdy`To1! z4}T+<>RJ5NX%aGg=6F;iZ%g9I8`i?B8iBNC0(p$BLOj7#H(Vh4lvlAVKo3vTtz8p_ zWt`E_CyjrR+LuIG53!{2zYbp+#Bvmf2;6g?1aJSr`xn6H&GBf+#2lsgj;!tV6pfmf z-5ttX+~I?0$Txq0u!#50^Ug_dp==}|5%KFQYtaP^a)Ns^E9zhk>~;wXPOy>W6ExrY zEj$K2-UY|NDN74Y{n3qxiganUUQ&WSn=tKXOy&uy5YuI9AkbU5F8jj1NZK1A6C_S3 zmkzZMNEFN}ve+`!V8H4KlB7b8DufRv_)=YJ;7b0Of}XvH@uB3x8cm06pq6D>{|@Qij=F)4kZQ49u(bPB{Cb-lny^;EIY&QjMYtFR|!Aq=*a|f)N6M`Hol~Li@#m4bdM#)XN;Pq!#NMxfKn6@xrG3 z^9g=4&`XWJI#z9pXubB&-X`5Tw`6m)1{z+9XKe0-7--F!%M6FNpvso=!?rC>{_brSK!OMYB=dEvR2~xx^WYCS4Wv z)_Kmcfxg&V9Q!gW1mzRg>};XezLIHKX;SL}=?xjS_)9RL3o1Bx<>thfpoy1-Ya+y@ z{i%&zDBg9rjgiRPQ-s8uFkF{$zg0c36D!7b5cdkZ0;YD_tM)fQT59`F+bnUNbZH!plmf;X+v(dYUi!#na3t_j<< zGL>$4G-Eo_I==$;aif8x88mCZpYJK@#X5k%&SaN-o81j(N=`MyuCPhhZ@y*;G&@)! zfeQq9;@((?FiNC!;tghMY9_N>Whv^~B%CC`^uM5~ZfF?$U{%p8ZNW zP%aU_xpQCge{*^9E@~k(1>dvtq@S~134)zk{z`HV+l#j1v^wM;?ZNFmF zw5;6u^>eNU4)WdIf`ie3PtflN0c+8XU4gr&VnbVG-tCIvf~{Rkw7pM$K%-e*EyjEO<8Sjb%S{9^X}g}>h{SaYRwI==7Q6*(~n^#E7F5JhcAIPY^;%W zTujPbYu%lZFHs-?1m>%HJQb)(o8ePs>)O<>$(aWS^;&o=y9(}J3eK=8b#iFqAOWSV zZ8GNO5I!JA#GQ>O5M@Gf#G5=!@g0dm#o-I?pNs!rpN zjpH>hAzb2IV*M-7`^SK~uUM}t0tp%K*Ur_gXpDT-l|emK9goG7yh^grJJ zZG5N$CWcp=h0;eW-AfR`#s>sIXg?f_di>Jb6vh!$TO_9mae006Ox>M@&FLVpG)^Ye zPQK>{i4r;N$m|Mq2tl_y-i_xKqMjgKMhC}bl5tvN-P^;uiHjm%@Ai$7!_F)Y?-uRt zrnZSEIlaajk@7QoiXvrl`g#>Mr;~R4Zw`g?B6VcSNx?)H6yee&%H(HQBM67xCGKTC zpw_{q_7`;cr@wH~${ZL4g0Q1N zytXn*&7eD;vyzC)g=@qt(PDtpgM7aLWHw0t$bNk!{#p9ly-2He>`OQK;fY;-Qg@?` zp)-21CpD$m;&*lNDJa4rQ*;@%j%{Z%X5N;JZp?08k(#@$&j39hX|US{NP2k*V=;ml z-vdFT&bz75ztlo&tq}(N__ehl<{UZ(RGQNUjQbJMCU050H%IR`xUgW#9f0~>V zs%+fri}zY~RL1uR#Pv!R#%`!8);!G9!g6n2s)|k_!A$Q@km`QNG!#a`zIa==yb~4u zt_;;w`Y8Ot8xbDS=J2L^Gm*k*+lUX_8@KFjdIuQ5N-Fhd&P*ck9tQi{b@tV-d=|E~ z)8{&}GJ7dlF<1jj*7E6wWI)LDlg$}I>eAUHAyfp=q1#~Z0Pp?V<^p$|91^7*bVESq zaxkToLpr+MR#xw~?9Z~m+<~ugLwN*oFH|_Xn`pu{SBU3=F?Hf-vy!1?*xZ8?%$eb# z2&G9C54pWYn!6fhwm7t~ui2w=Fay(^I{O;bAh9~oRswILn|Dpkrx^-$XV|<2gPtb}J`<@C=TtglsbR^vICDLs)@t2o#ICCg?<~!0R5PL*s9F=5 z6TMmsKeZNgpktfd+A`ZT?~eX(d&NwkK+0#V>`xEzj&^|8NN{>Mg_~MVxX%ec=NzdBy-R%x3n7*L93Y2I52}0wE|!+0%J2& z>(8Pa$2XC%NB)Nw9)^AIEYyVyf?&fPhX^F|YVu9`7l2=LQJ`lMFx<=MRZy2u$uy~3tx%EE(9U0lYKAJZL6 zzZ7<;mIbCQeaqzTVmiV0(`h64Cnz8E2CzgkC#Eib#cR0=GnSC|CeH}j0|WR%Qxm1$ zDo`-f*>Tn5bcP1oLZ(0c*2KX39iQDd8Cadz2H#mn%_6zHE(Df(y$kI?=)p;M?pmvQ zy3uLropOjFpr-mscc>R#>A}%2eooXQvrJ;pL&dcfDCwTD#|s4g<_oPNF72Xap2}`E z%j=G7aj4)v!z{JD{dsKj%E!P2c|>VGTt|H#HSuxKkCSLI1S!ZnBJKN#VdSGY%(c(n z^)md`^f&U6=}XBSm~;$bAK@`(0wr=kf2Yp&hS=|wGRPmm>}JcZq@CY4l5gm;VH*QQ zeqonAmftt??@A?7|I}`1g<$#cSN8eT);$NkzxJd&kq=Ggl(X-5Fu#evMAh4P0jF| z-Nne@zahu_@Q3YjR^(j*k?&j8f!Sg=c`-_ny0tAB@A3BRX5|d)$rEH#>_Jek;y$oj z3k0&E3+p@AJ0;z*8!r_oDARk19z;{xFK6AZ5SbiH+vKIhuI@WUJHW#E*HI8O{JwSr zr`t$H9m}exc(`94nx1~Za@09nw62lYwr=CSY{k*2^+qO*Ix*Qym#tltipK= z_N-tw`+D|sY!Y1%8bGlLR28-#A`yr>j4T%Qu=w1qbKgqGb50miIaLJ-ikvVt{#YW9 ztw#izpWM^Nou3%3N7F{`H(Ysae5Iud_&W(q2tBTfHr)V@L`OY5Z!}7=lekP!9Ff^r zOIcn^QLTd*+PO571yoWKD3OZM2tFrX>l&{RU9RafZR2193rHZd=jVUATH0Q==DR|k z-8u6#DFZMM5PRE7GBz|+L^Q*C3h@~%61k?ZCn{)H*8XL2YE99~8-twuy_Nhc!7#w= zL3Lh;$USiSowF^#beR?mK%^bCqHNX7klt+9J6$YK?$w%E=S`iGz4tR@1LQb&k%ugw1MM z-vFH#7|e7eQjWy8V7mg5hs~PcY<90+3g|U+im=JX07+@Zz*3Nm^q%{veDD<=EArJH zn*+wNd_Hv8)-18qNgsdrceFW~J^29QPc7PQ>gMgxUkggAZpfQ}kRO;C`Xih?(^~X< z#W*4@u5ZiT-*yroj~>0N;CCU{pE|1zt9x9Dee7`cEiy%0CLaiVk^xrEK1fy?^@gC( z1Q7f&Btf5qM}j`3#RxYT3j3o^VRN0(n|27Z+H#W-Tvrre?mw)|#bSNqt6EXyoP>U~ z5&PUl!(oWc|C+aXsAu|<5oviWq|28JXD{Mnd8PsGsDC>~%P*i} zkUdp~v@3L748SEB6!x6lXO)I-J9R9G=sgI;yFLjP0Vy^<38=uq($?-~V0z-eBglu( z*Q0*sCUSo3?KM7kbksWndbDinqOEJ(p*}eZwmzDu-;-NTquL7w*jNVIDyV?DAWn)Uu)6jj67Rx|%o-Sx*xFk2X|c{r=}n^!Tp#A6^7Porb?*~v zTX!T}G@&Ha>PCx<5Xyw3++FoTY@Kc)Ail;AM_^)bIIk~F*;`A03;gX7SpGb3Ynx68 zZMANP9xuT28U{iwRpJH!c78IW3|;ZZ;o%S{Vi_YtHF3}IYLwGXc#N&D=+bsZj&DQzl_nAA(6cjsqx0LX6 zA6TR^W*?X(SPbuzXwotZH)1l9Ym_ImPqG%~Sv-|k7r=zabH1#rXF&rmn&VL+5c^ME zfoxebnBNQ?8w5S%LO}6rV`JhA3ij{&>QGySepC$4q{)}B|IV4`F&PO4AF7s0(KEuk zHe^NKaf#kSzNC2_L)*#!N;W){Q18aI$K(tCeng_Uy4*WallJ6>1W<^hksgWPkv601 zMTzK6pRjn?9=9?o8B&RL#9kG-P@Yjd*ll?fpX&t-fN~@7NE_CSCFA*u+BC+LM2xm$(_WtK(%Fu5%8tzPwg|&(;#b>`=NEvlLx(wnnS4l;q4(N^vv}_$C9J}1< z&>mdBTq1O-8!xZ{n0hn%QHpNe)_M%eTI zy1RD3q*TZt?|r1A+a}-^kEsk(6G0;YsY5{L?fD_5&7R3++Wf{O<1v$7EXE$VlP6R*K^vMmz|l7JPy+O|gH9LBJ7+oM6j?#jANZ1EaHQl!PES^vyQSh<{c z7;AKLNh?dWS8TLHMhGB5aeqwYTm6x1t(Upm><-T=j&4L;F#>nPF~jsfM(mZ1UZ0QY zBEM!wBwvb1{n4}i!se+_rW~l}NmELGcXwWWT&WmaYHM!*1OC;p+Djv#XUbq=^+y;8 zIgn6q1DhWuO&|eC;*P(<4VtWQ7d(!9@rDJa@Oun;_!FPIxb#DXLKCRpt-6?tHjsG6 zP^^F^%GZNvy;GCyU20Wc;XJK{4{8q6^!AjSx}1@aCmI=xkNzQ{%=7QadD56zZ!w1g zS5}+K*`o@cGodIAM^?uKJfondi;2Y!*`QllA;v7PX&ech;sE};CuH0iGOUCPM% zfcNC+aJYu6--_pS z^NG)VkaSoB#;A5Srg=+=2Y962bT46O7guF36=QBp;=@CAC#0@zgqJcY+|cw)3pf`# z+8ZdvlD!V!p|XQjvRB5_dJQj&o&T5tT`Gf7Xq&ON`adr~vne|oDzOpL$TS$}@$vJ* zAo5J2pabtErr*q`;?s|QsXwG>c)<(=D+F_NThmYdmg>rK2zYe?iXtf{{=)8C4bn`3 zGL=+{%^j|DI~#;p+HfxLO&uK%0pyDBk{^$HsCJ#9@g;=sT0iA`<+c0wXF1)^0Q>`5 zKR78(m#kzJWmfjIw+q9aBn|==RSG=K7xU(Z)eLJAqm+lFp43V;ax5y%a?DuoGM2jtOiC*H z&5u=DuZ7R`)6=XuAx8#nO81sdVt&ZPyMvER$!_-?2C=x~1Vd;Bk%w^WG_Wgs$Z!8h zFRyxR*|SIhSPfST)`oR20*9&7FYRW|N=}Y~J}-4Ha+bRMv=s=i^W_K7Nbzn+N|E3Op~3zJb=DuI-Gp zKvPL{dQj;I18!il}9Z~RMeo72aE-WHMriH)HOS?`I( z883HW;hVWb;w851rFv}WmwlZRz(*r&5j)GlY!_8&GB^?QEuXMoIU8L33fA)6@(R2G z0U|);ScK)}l*~Ppa#R3Zb=0#1ncc)4KY3s8$X-zf<-=Z>NH7bulF(O*lHkM5Jp=E# z7b2K0q})6vni}oFbSgZOZzP=rg<<88JX?p6>0MWb8F-WI77a@A*QVcR@}yj-dXQ@6uIN?!EA;bT<`^O$mCYO=>rxcoxtf2-3=sZ0l=SW6ASXxI- zFRtH(&1NwFO>NSDxMh{&N5;%sbQtfIBmA7NkAJ-+0aLLBeLXS_OZRwNp60YE>TYMv zM}VXm#CrXxvF*SK17^+M{cMDx0msUpq9LcWFe9*-c@G;fAyUzS1rWorO4Tz>25tI2 zGKpIKFQhNy!&@0j7;&fL!d^0=>}|S*(0LCsFyVJ_2vZUTe-}$G0B@7f$cl3jNipF` z@T3I38ZH&H`)^ZcWj&^W4wI_(-SZCUX;OOAd%Ua-TaH(ZxLJMh+^#-(^js+ul(Uw5 z!v%TTM)?K8z76bX@U2T2t*v**R{!lHEROa{aEi^fS!?7^{d;D0>oCne`Y*#xF#r7m z$KhWN&I03fm3TLF;HUj>W5@#3msuNe$xeR%ZA$u?CEGIR+4C_IW%m!G;s0-6O$Xc! zN`b!|l0{SO117_iI&Q-M9i`V&wE!(gpEIL!Fi@^qE>P!X-v91-jZFEOrO8Q4kbCIBTovaOxFI!;LY?1-Vpe|OH)!~kRJQqJ?Q4ZE;(+< z!TBwkH_-`E?}JhJ=BYMks^9$PzrW_7kL%|o-^^Fe+ygz3gt}DPO+tMBs`(UXKj$asPKl znTan${aV(EY78Wt_Fma>wzwKfZJ*C{<>oea3F6AM=MuBL-)phl8R5pyWEq!kvFn^A zs$6|-@9OIMT5a?HcEHT>;^O7?CTnwmc^2qxIHpmtRq+%~Hw+(H&{u!NZ?q>Wzt5{t z+^(1vpq_Io$d}`y-B8Vqo0Wc${Qp|}5_c%O|No&e#OK?OkGv`UlygpwZQu_Ni~`bCU?j*22FW1iV+B8}-c`r#E6ROH6)X60!BJJmNpfy9g)+4=sUbVGu%oUvJc7<6xQ z=t1v$iG3GFc*!SQ8=~r$)AD8!>O%WzKEi3V*SoQmQ11w0O5K4Y2N1waE9ybp53dZXYX6!vs z@#*Eq!Y9AOqVt1hQSgm( zXPsZ*U4c71YQGnk$drJwkZ0{ooiA-q7OSR*D~_Z^Zp(6UwzTsJz&=ecJ(b_(c)vCM zgS0B@>y;T=2k=#%_6g$dT14orv}Xf6L#ns!kk8yc%`Fed*~BqZlcR<>|9IuHx_>0v z!i>7$>!uRw;-sfY^r$(T)~SsR3gMK9lDayEAR7R5GR&qd>0CA!yY2qodvnwh6H^nj zz_gViaW5BU+!Dn?qk!JT7OU*4vwo8CK}R}pJV|f zX1=xBs)P3qfJT9!H&?HY4FdxR_gw8FW46_S7B1Zdtre}rqzGJz~=dq==onZiSSMe2#%Uvc{hxozF zZLJLVhf>4cD;mF0DgBjfn^s2}_wWfPywpx+aA~&;lG-apHBQLa32qA+h{^nr{~EFW zC=f(5so-)(FR6?D7xou*;6d7qEY*x*?8Tzqw@p}OsPl9l|HqMc_YbE)=MfuxYfGQG zQ*+xPK_{R0fT8WlM*8uG74L8njJdK79$9A5+$K$*$#}pe;B_>Odj6W|X@g7NCwJaR z(hD_~+KUD9Oa~*aJ+}mcH@<)_hFM!%b$;=FzuE?WKURwx4b5s0!QRURV2{&oNCnYeT&2!Ji;wAz{eu-_sbH=Q8xB_Qu z?_PL$&}qxC+_CA=n8t`e!BQjlnWbjW7is~beidJ%;zs<=-u&6)xm4Yk`6cvN?eoBm3i=MH|{p9lz<{E`CgOgzFg8NJDp4E~0VkmUZ7SbGH;*ge2lO%!~F ziST2>Ra?H2CL>83{)+)4oS+{&i;wI|B?@n`gOX!QM%^Bi^V!_xy_&J5ygM=XU_6I5 z6oKDhOIv+I8`I;ekJ%L-sSE-SZ+uq^RxLkqOhy$aP*dPx88WG=jr=Hn{UJb)#WMMs zIPM5a8R)7eMmjHkv9tF4l9W_X&;Ehz`Kuv-+8rbio;Ecib<6wf3pi<&CI*V{yym=c zub<_5-v6r%QakemnV+d~sz2>$x073hM`{*)C>H@a4reNF87Q|?{x21Wa+oF?enx%)3c zH&_ku0Ww6j3retMocR%r;`!>TUE3e^cB_;x?i?Q~16jA_e;nLh_@+EMT^+NPkm-*~IWQk4(&vO0xnJp5Z3f*K6SU$ZolQ5D--RM7L_;sE34 z%|C15F~g$c)IrBq-vd-Xi4;sPj0m|X*6rw&Z)@{Ha&edJllL7)2OvECaq7T&1kio5 zeU=`H62C5V>J%HOd@*S80B8^(?vwaFIcaIVHD|=5M;nWKunTNPKld=>DP`5iW~Z&! z9xM-UnM|&34bQyVq@1abFnKnrb=Y%ens`E-lta>cmG45g>I zx`4zR9~Bl4!KLwo6hw8^THD@i9}GG4{#$})wY+ELq2EHhqkn61t3H~&qZFY&Niu)8 z`$w&2I|)dKNuO(f94i93urk#?*C%BRcG%{6ZbFF` z*$`*Y5zrSht)>ac#FZGbV5+>Ve(}d8OAo6y3x+Q&uDgfOcQpxSykIe#h7NUs&Cyxu zde_*Rk2YKO`T0MTi9x z3|q3%bOUb=V)Oj2l)!=*OZ~E@&Z`E8{;tw4aBjS$q-0Jn`Me0Z87Rd5Pf3L*w}qB8 zb=b~?6Le8tM{>Fu2)CCk65d!%rPslbj>)+e3G`f@q)!eScZ{xL14E6S}#57R&78 zl)%$(-I}aH)Ed)7;nq^i0CPX5Va1e1?BtRb%nvq!>?wbS^M8$K&;>G(4U zztXbYwH&4sOKu=7Nj|3Dtu`DTQJ>$L4@@=H$TyG2$K2>MmF>6KwTwhxmi#THt8oU} zO+?N8#BTqy0q`G>IcOK1Gf?DxD=d6E57})+=7GD0!M7Y(YkFUWJ7Bl*rJf%LoMUht z9g}A*#|kh%h|_9`YT=!Q;?@GFSKX(eFCNH%FBF|PcBKhd8-Vzk>j!7l;WlMLtCjcf zrJ_*6|^HWwpaMyHAOD0Dvy_!BgYJ7@I03aGg7v%WR49mPzsF$Ikd%Md2wNp_j_;GXx zPs=s4zXS}yucpo>Ynm}R+F*yUD{i{C%gPt9H3pbmaFkVWItG=6g196cM%Hw@V0$e% zm{D~`2%J~rX9)XNd|pTm8Bs2crq<9Yc$}QH^q-`w7tdh}LnQ&& zoRn%K@=GI`$0{;cda6S61H9gt10s^Pl&)zv9UI8T0o4M)-h;R;*0%T>YAt`CKUb45^8Ba za8+g$a+9XgL%_Vw@j1mE(ngXt{(6yK^pX? zT<|ApDwM00p@;083f|`1w<5zy>0L*^9rQBO`b7@iMCJl; zHR^>VcNe`lsnn2Mj2)ubkauP;8B;HKALw= zo0zMF_KP(?n-XZZb!n^6M&k1yPdVf(h-A1fP*kHkIXXfJEXkO4g1K)>MhF%8Fo(2& z-4;SwyuqB;SIT~DMIJR;T*lTlmiaYO+M+%y-Nk-*c#=NuU6?HVu0aZHCc+6nl?Rp= zVP~#s$}uwb=b*ES_*^;W>Q@)vB=Zs&5k{}BzyKwU&6+e#&4kRdA3t&Zc|_zHl10lC z1}xNN3Ylo-B`4PHQga)4grItKUHN=b&yoU0EmK$1JZrDaHZC z^+GgRMen>$g%uE0?JGp{)q_3eoRTQO-U;BKx5zC@|d==^aWD4>+2Jd5j)3Q5+-m z7j^>5g2xeRx;l0hOkza@UZ?vWa(qcunGNgbk{ zg9yhbigdc5P{Qml6Io@pk{wnG8YcM;@Nb+SmK(9~D8mT0ntMRet(Gph%1Z1WxWm65 zzi5{z^6l**2h2bhzt)GFQ%o=;5PQ11WMdx}DdtA>$wd5GX^TA=rLSDEh z-b$jC#Gsio2;~DrB%S)6LJD+O@>gvecdIYEmmBJgZGr(+iYwdgICq~)b7`ADgIN=f zSv7}g8S0go+e#XtavI7UUvV%KS(U_4_lVyq{FDQbPhr8en%Yy?qk!wNfNMQ-!DmUCK^dmHUh!xf0@^J3agmxhl&ed; z`6Tq1M1_Dn6xAwoe$L+p`>}6le~9=GS%Y#1l}xPCM? zQ=Qa#HnMvntD%=5ECsKKLG|UMwQ`ht2pK_B1M5D0N;ukH?&C`Beafn`A5BFlb=|lZ zFc~qF%gU5F$`$)22_r4JSWR}eqrNkt+F~~UV&pMQ+yF6-Qj&P!ZgwA^eoNweJHy^N z8HeA+Ut%i^V&vO?FYLLbHLx!z&wWU??eQk|S6!@y)t9Is_^u^2HD^zEYp+MxI3ue3 z13UfP<5|eU6D=-PImITFi+MbfQIyDVTA9u{wJ)yMGajE#B74#OAVX^=`&7%V8&YxL* zHN9_EDf>;zaFo3NRB~r9<}3kyFUQB7TlGemCVJj8hz=k>tMcgT^g>I%3BWOJj5DNjM zb2-J-m%1sPg+1zBwU-q!$1HM(VB2IWvxu4&^gnym=YmK`7YC(?&P!<5RJ4nv9f|Hv z7bW&ft3rXj>mii2Ls7`G6L7cGj#0RIpJ|23LQT#z21egdSQ&o}0t%@Al}VvBisz~) zIHl7*yW0gbq>A5=H%r|?%#~vEIErQ=mk;EMBzI-)^)u{9hFhYmzd(%bG&`F3>8{p@NT z@dH=rU5rL{Af^-xx%V?fJrmUTueS`JC{b#S5!S_7g?VU}6v7Ui^6d-j#Gd&prN^CK{b>rHsaqJ*JQ)_<^7KZw4?@C^I?FyYBE zRexiq{DeMUhv#U9rBk|a9|xL-D&31D44B^08SluLIH>3=E76xX-T^f&|ElGp$k(6D z-j~PKn|HLnSrcvT>`;cPOC$;msdHjGsE9Uu#X2EZ!9zf~+P^VWKd+SfgpPf78y73% zh(732H4i)?6eT@KC5#%kX&X|eqS+j~;0b?J5iJ^vK>-ntgGxzXD2wa6OZC;^!W3Y_ zTrRJd`a-Cx*2kS{v>9(Tv*Z7SDfy__Z8Hf7Gw(?C+V|{Ylj{nR0&_r`)Bcty`){J`V>=`QWTw+fu zdsp*3N$}7;;F{e>0T1FQC6697OKjZXPQRjpAgdX^E$il8JRkGyakFHl!$HuJK*tLw zznY$eclh)4 zlwGBlc`Kq*QGvTYt*YZf0NivlA@Y*xIi!J^$d2Z@`IuN&ijhHCzA~jlThvatu0piT zNE)D?2~j>5+$!{O!f{gWbvNcq$=x@O-BEPYx>AFpj_GsNz+hG0$2*+XPAZO_*T`)t z|2_XbIr_t!OH`n*t$TAj@sh<%A*k(bna+_I=RV;!cHEK1W?g zzBL;bM7XtPa05+#4Y*53MHpq^>p>va#_I;U$QvCURQ=0t;L*}BeC{oNQRcbWxY*S6 zJzktif8Hk$G$rWLspD;iwT>;^z3QdN{Bm3=uPpYE)fxi;L|gvRuJjR2_6AQLbcpQVRJ^H_Uj8qM=tqYvc( z9XPe}Y3%HgOjU89UP$4@o;07?ND1+?-Feiyg>d-0VOPeniz~gu8xS!>+iCnpms|>J zqNKz=-b$G1^v%&zZs|+x?>$D(cjk_oQG>`ccUqgv=e>yo%2@_>n^Cq37Uj@AD#X9Z zvswoeL+OOP|prwt|P*ffGO(T&2^rVRM_dT_hi?aY?d(Z*2W4GF=cjH+&9y z&=+S_`EcX2i3n$4r36FPppUB5`Es1wv>W$riT>T2zpowzt`J%Jz1d<_vqo^<8>IZj=q5M%AMpDsL9}(t z@}B2H(k&e~;_-XY2U-fnBN>{Wz_&9m@s3x3D$TtH@_Es@(}caR$Mf{|KK}o|TxL|g XXKp_KdK|g4*ZK7;CIx1RhT5>tkB literal 54834 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 Su1w^S+M0TQ7F@ph;C};%*8WQX From ee7f9c5675bcfbc05811f5699b5a7d9ed9767d3f Mon Sep 17 00:00:00 2001 From: stsdc Date: Tue, 18 Aug 2020 21:05:31 +0200 Subject: [PATCH 43/45] rm debug --- src/Views/SystemView/SystemNetworkView.vala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala index f8ed9402..89dd771d 100644 --- a/src/Views/SystemView/SystemNetworkView.vala +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -40,7 +40,6 @@ public class Monitor.SystemNetworkView : Gtk.Grid { public void update () { double up_bytes = network.get_bytes ()[0] / 2; double down_bytes = network.get_bytes ()[1] / 2; - debug ("%f %f", up_bytes, down_bytes); if (up_bytes >= 0 && down_bytes >= 0) { network_download_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (down_bytes.to_string ()))); network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (up_bytes.to_string ()))); From 0e7ee0cac711535ecb5b02567eb6cad639a9715a Mon Sep 17 00:00:00 2001 From: stsdc Date: Tue, 18 Aug 2020 21:06:01 +0200 Subject: [PATCH 44/45] format --- src/Views/SystemView/SystemNetworkView.vala | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Views/SystemView/SystemNetworkView.vala b/src/Views/SystemView/SystemNetworkView.vala index 89dd771d..a89a3f86 100644 --- a/src/Views/SystemView/SystemNetworkView.vala +++ b/src/Views/SystemView/SystemNetworkView.vala @@ -12,8 +12,6 @@ public class Monitor.SystemNetworkView : Gtk.Grid { set_vexpand (false); } - - public SystemNetworkView (Network _network) { network = _network; @@ -29,8 +27,8 @@ public class Monitor.SystemNetworkView : Gtk.Grid { labels_grid.row_spacing = 6; labels_grid.column_spacing = 6; labels_grid.margin = 6; - labels_grid.attach (network_download_label, 0, 0, 1, 1); - labels_grid.attach (network_upload_label, 1, 0, 1, 1); + labels_grid.attach (network_download_label, 0, 0, 1, 1); + labels_grid.attach (network_upload_label, 1, 0, 1, 1); attach (network_name_label, 0, 0, 1, 1); attach (labels_grid, 0, 1, 2, 2); @@ -43,7 +41,7 @@ public class Monitor.SystemNetworkView : Gtk.Grid { if (up_bytes >= 0 && down_bytes >= 0) { network_download_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (down_bytes.to_string ()))); network_upload_label.set_text (("%s/s").printf (Utils.HumanUnitFormatter.string_bytes_to_human (up_bytes.to_string ()))); - network_chart.update (0, up_bytes); + network_chart.update (0, up_bytes); network_chart.update (1, down_bytes); } } From e3074a858639573eeb659e0c535e8713433f0ea6 Mon Sep 17 00:00:00 2001 From: stsdc Date: Tue, 18 Aug 2020 21:14:33 +0200 Subject: [PATCH 45/45] bump version --- data/com.github.stsdc.monitor.appdata.xml.in | 9 +++++++++ meson.build | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/data/com.github.stsdc.monitor.appdata.xml.in b/data/com.github.stsdc.monitor.appdata.xml.in index bdf8725b..c2c49120 100644 --- a/data/com.github.stsdc.monitor.appdata.xml.in +++ b/data/com.github.stsdc.monitor.appdata.xml.in @@ -28,6 +28,15 @@ https://github.com/stsdc/monitor/issues + +​ +​

    +
  • Better System Tab
  • +
  • Update Portuguese translation (@rottenpants466)
  • +
  • Save last opened view (@ryonakano)
  • +
+​ +​
    diff --git a/meson.build b/meson.build index 17aa7927..fb04f056 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('com.github.stsdc.monitor', 'vala', 'c', version: '0.8.1') +project('com.github.stsdc.monitor', 'vala', 'c', version: '0.9.0') # these are Meson modules gnome = import('gnome')