[Xfce4-commits] [panel-plugins/xfce4-hardware-monitor-plugin] 06/18: Implement Generic Monitor
noreply at xfce.org
noreply at xfce.org
Tue Jun 28 21:33:28 CEST 2016
This is an automated email from the git hooks/post-receive script.
omegaphil pushed a commit to branch omegaphil/graph-disk-io
in repository panel-plugins/xfce4-hardware-monitor-plugin.
commit 16a0c6a23721c9e38e0a7a1c7e24839b7d7de36b
Author: OmegaPhil <OmegaPhil at startmail.com>
Date: Thu Jun 16 21:06:58 2016 +0100
Implement Generic Monitor
---
src/choose-monitor-window.cpp | 276 ++++++++++++++++++++++-
src/choose-monitor-window.hpp | 26 ++-
src/monitor-impls.cpp | 260 +++++++++++++++++++++-
src/monitor-impls.hpp | 48 +++-
src/ui.glade | 494 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1074 insertions(+), 30 deletions(-)
diff --git a/src/choose-monitor-window.cpp b/src/choose-monitor-window.cpp
index 501359c..e9041bc 100644
--- a/src/choose-monitor-window.cpp
+++ b/src/choose-monitor-window.cpp
@@ -62,6 +62,7 @@ ChooseMonitorWindow::ChooseMonitorWindow(XfcePanelPlugin* panel_applet_local,
ui->get_widget("network_load_radiobutton", network_load_radiobutton);
ui->get_widget("temperature_radiobutton", temperature_radiobutton);
ui->get_widget("fan_speed_radiobutton", fan_speed_radiobutton);
+ ui->get_widget("generic_radiobutton", generic_radiobutton);
ui->get_widget("cpu_usage_options", cpu_usage_options);
ui->get_widget("load_average_options", load_average_options);
@@ -113,6 +114,32 @@ ChooseMonitorWindow::ChooseMonitorWindow(XfcePanelPlugin* panel_applet_local,
ui->get_widget("fan_speed_combobox", fan_speed_combobox);
ui->get_widget("fan_speed_tag_entry", fan_speed_tag);
+ ui->get_widget("generic_box", generic_box);
+ ui->get_widget("generic_options", generic_options);
+ ui->get_widget("generic_file_path_entry", generic_file_path_entry);
+ ui->get_widget("generic_number_regex_hbox", generic_number_regex_hbox);
+ ui->get_widget("generic_read_all_contents_radiobutton",
+ generic_read_all_contents_radiobutton);
+ ui->get_widget("generic_extract_via_regex_radiobutton",
+ generic_extract_via_regex_radiobutton);
+ ui->get_widget("generic_regex_entry", generic_regex_entry);
+ ui->get_widget("generic_change_in_value_checkbutton",
+ generic_change_in_value_checkbutton);
+ ui->get_widget("generic_change_in_value_hbox", generic_change_in_value_hbox);
+ ui->get_widget("generic_change_in_value_positive_radiobutton",
+ generic_change_in_value_positive_radiobutton);
+ ui->get_widget("generic_change_in_value_negative_radiobutton",
+ generic_change_in_value_negative_radiobutton);
+ ui->get_widget("generic_change_in_value_both_radiobutton",
+ generic_change_in_value_both_radiobutton);
+ ui->get_widget("generic_data_source_name_long_entry",
+ generic_data_source_name_long_entry);
+ ui->get_widget("generic_data_source_name_short_entry",
+ generic_data_source_name_short_entry);
+ ui->get_widget("generic_units_long_entry", generic_units_long_entry);
+ ui->get_widget("generic_units_short_entry", generic_units_short_entry);
+ ui->get_widget("generic_tag_entry", generic_tag);
+
cpu_usage_radiobutton->signal_toggled()
.connect(sigc::mem_fun(*this, &ChooseMonitorWindow::
on_cpu_usage_radiobutton_toggled));
@@ -153,6 +180,18 @@ ChooseMonitorWindow::ChooseMonitorWindow(XfcePanelPlugin* panel_applet_local,
.connect(sigc::mem_fun(*this, &ChooseMonitorWindow::
on_fan_speed_radiobutton_toggled));
+ generic_radiobutton->signal_toggled()
+ .connect(sigc::mem_fun(*this, &ChooseMonitorWindow::
+ on_generic_radiobutton_toggled));
+
+ generic_extract_via_regex_radiobutton->signal_toggled()
+ .connect(sigc::mem_fun(*this, &ChooseMonitorWindow::
+ on_generic_extract_via_regex_radiobutton_toggled));
+
+ generic_change_in_value_checkbutton->signal_toggled()
+ .connect(sigc::mem_fun(*this, &ChooseMonitorWindow::
+ on_generic_change_in_value_checkbutton_toggled));
+
// Note 1 off to avoid counting from zero in the interface
cpu_no_spinbutton->set_range(1, CpuUsageMonitor::max_no_cpus);
@@ -358,6 +397,15 @@ Monitor *ChooseMonitorWindow::run(const Glib::ustring &mon_dir)
temperature_radiobutton->set_active();
temperature_tag->set_text(tag);
}
+
+ // TODO: When I start supporting it, why no fan stuff here?
+
+ else if (type == "generic")
+ {
+ device_notebook->set_current_page(4);
+ generic_radiobutton->set_active();
+ generic_tag->set_text(tag);
+ }
else
{
device_notebook->set_current_page(0);
@@ -488,10 +536,61 @@ Monitor *ChooseMonitorWindow::run(const Glib::ustring &mon_dir)
network_direction_combobox->set_active(0);
}
- int temperature_no = xfce_rc_read_int_entry(settings_ro,
- "temperature_no", 0);
+ // Fill in temperature info
+ if (xfce_rc_has_entry(settings_ro, "temperature_no"))
+ {
+ int temperature_no = xfce_rc_read_int_entry(settings_ro,
+ "temperature_no", 0);
+ temperature_combobox->set_active(temperature_no);
+ }
- temperature_combobox->set_active(temperature_no);
+ // Fill in generic info
+ if (xfce_rc_has_entry(settings_ro, "file_path"))
+ {
+ Glib::ustring file_path = xfce_rc_read_entry(settings_ro, "file_path",
+ ""),
+ regex_string = xfce_rc_read_entry(settings_ro, "regex", ""),
+ data_source_name_long = xfce_rc_read_entry(settings_ro,
+ "data_source_name_long", ""),
+ data_source_name_short = xfce_rc_read_entry(settings_ro,
+ "data_source_name_short", ""),
+ units_long = xfce_rc_read_entry(settings_ro, "units_long", ""),
+ units_short = xfce_rc_read_entry(settings_ro, "units_short", "");
+ bool value_from_contents = xfce_rc_read_bool_entry(settings_ro,
+ "value_from_contents",
+ false),
+ follow_change = xfce_rc_read_bool_entry(settings_ro, "follow_change",
+ false);
+ int direction = xfce_rc_read_int_entry(settings_ro,
+ "value_change_direction",
+ GenericMonitor::positive);
+
+ generic_file_path_entry->set_text(file_path);
+
+ if (!value_from_contents)
+ generic_extract_via_regex_radiobutton->set_active();
+
+ generic_regex_entry->set_text(regex_string);
+ generic_change_in_value_checkbutton->set_active(follow_change);
+
+ switch (direction)
+ {
+ case GenericMonitor::positive:
+ generic_change_in_value_positive_radiobutton->activate();
+ break;
+ case GenericMonitor::negative:
+ generic_change_in_value_negative_radiobutton->activate();
+ break;
+ case GenericMonitor::both:
+ generic_change_in_value_both_radiobutton->activate();
+ break;
+ }
+
+ generic_data_source_name_long_entry->set_text(data_source_name_long);
+ generic_data_source_name_short_entry->set_text(data_source_name_short);
+ generic_units_long_entry->set_text(units_long);
+ generic_units_short_entry->set_text(units_short);
+ }
xfce_rc_close(settings_ro);
}
@@ -683,6 +782,141 @@ Monitor *ChooseMonitorWindow::run(const Glib::ustring &mon_dir)
else if (fan_speed_radiobutton->get_active())
mon = new FanSpeedMonitor(fan_speed_combobox->get_active_row_number(),
fan_speed_tag->get_text());
+ else if (generic_radiobutton->get_active())
+ {
+ Glib::ustring file_path = generic_file_path_entry->get_text(),
+ regex_string = generic_regex_entry->get_text(),
+ data_source_name_long = generic_data_source_name_long_entry->get_text(),
+ data_source_name_short = generic_data_source_name_short_entry->get_text(),
+ units_long = generic_units_long_entry->get_text(),
+ units_short = generic_units_short_entry->get_text();
+ bool value_from_contents = generic_read_all_contents_radiobutton->get_active(),
+ follow_change = generic_change_in_value_checkbutton->get_active();
+ GenericMonitor::ValueChangeDirection dir;
+ if (generic_change_in_value_positive_radiobutton->get_active())
+ dir = GenericMonitor::positive;
+ else if (generic_change_in_value_negative_radiobutton->get_active())
+ dir = GenericMonitor::negative;
+ else if (generic_change_in_value_both_radiobutton->get_active())
+ dir = GenericMonitor::both;
+
+ // Making sure that the path passed is valid
+ if (!Glib::file_test(file_path, Glib::FileTest::FILE_TEST_EXISTS))
+ {
+ /* Making sure the user is OK with specifying a non-existent file
+ * (i.e. it may appear later) */
+ Glib::ustring msg = Glib::ustring::
+ compose(_("Specified file '%1' does not currently exist - do "
+ "you still want to proceed?"), file_path);
+
+ /* See helpers.hpp - tried to host a generic warning dialog
+ * implementation there but got endless include bullshit */
+ Gtk::MessageDialog d(msg, false, Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_YES_NO);
+ d.set_modal();
+ d.set_title(_("Generic Monitor"));
+ d.set_icon(window->get_icon());
+ if (d.run() != Gtk::RESPONSE_YES)
+ {
+ generic_file_path_entry->grab_focus();
+ response = Gtk::RESPONSE_HELP;
+ continue;
+ }
+ }
+
+ // Validating regex if necessary
+ if (!value_from_contents)
+ {
+ if (regex_string == "")
+ {
+ Glib::ustring msg = _("When 'number from regex' is specified, you "
+ "must provide a regex to use.");
+
+ /* See helpers.hpp - tried to host a generic warning dialog
+ * implementation there but got endless include bullshit */
+ Gtk::MessageDialog d(msg, false, Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_OK);
+ d.set_modal();
+ d.set_title(_("Generic Monitor"));
+ d.set_icon(window->get_icon());
+ d.run();
+ generic_regex_entry->grab_focus();
+ response = Gtk::RESPONSE_HELP;
+ continue;
+ }
+
+ Glib::RefPtr<Glib::Regex> regex;
+ try
+ {
+ regex = Glib::Regex::create(regex_string);
+ }
+ catch (Glib::Error &e)
+ {
+ /* Regex validation failed - informing the user - error message
+ * already includes the regex */
+ Glib::ustring msg = Glib::ustring::compose(
+ _("The regex provided is not a valid:\n\n%1"), e.what());
+
+ /* See helpers.hpp - tried to host a generic warning dialog
+ * implementation there but got endless include bullshit */
+ Gtk::MessageDialog d(msg, false, Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_OK);
+ d.set_modal();
+ d.set_title(_("Generic Monitor"));
+ d.set_icon(window->get_icon());
+ d.run();
+ generic_regex_entry->grab_focus();
+ response = Gtk::RESPONSE_HELP;
+ continue;
+ }
+
+ // Making sure there is at least one capture group
+ if (regex->get_capture_count() == 0)
+ {
+ Glib::ustring msg = _("Please ensure the regex provided has one "
+ "capture group to use to extract the number.");
+
+ /* See helpers.hpp - tried to host a generic warning dialog
+ * implementation there but got endless include bullshit */
+ Gtk::MessageDialog d(msg, false, Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_OK);
+ d.set_modal();
+ d.set_title(_("Generic Monitor"));
+ d.set_icon(window->get_icon());
+ d.run();
+ generic_regex_entry->grab_focus();
+ response = Gtk::RESPONSE_HELP;
+ continue;
+ }
+ }
+
+ // Ensuring mandatory fields have been filled in
+ if (data_source_name_long == "" || data_source_name_short == "")
+ {
+ Glib::ustring msg = _("Data source name (long and short forms) must be"
+ " specified to create this monitor.");
+
+ /* See helpers.hpp - tried to host a generic warning dialog
+ * implementation there but got endless include bullshit */
+ Gtk::MessageDialog d(msg, false, Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_OK);
+ d.set_modal();
+ d.set_title(_("Generic Monitor"));
+ d.set_icon(window->get_icon());
+ d.run();
+ if (data_source_name_long == "")
+ generic_data_source_name_long_entry->grab_focus();
+ else
+ generic_data_source_name_short_entry->grab_focus();
+ response = Gtk::RESPONSE_HELP;
+ continue;
+ }
+
+ mon = new GenericMonitor(file_path, value_from_contents, regex_string,
+ follow_change, dir, data_source_name_long,
+ data_source_name_short, units_long, units_short,
+ generic_tag->get_text());
+ }
return mon;
}
@@ -719,22 +953,16 @@ void ChooseMonitorWindow::on_disk_stats_radiobutton_toggled()
= disk_stats_radiobutton->get_active();
}
-void ChooseMonitorWindow::on_memory_usage_radiobutton_toggled()
-{
- memory_usage_options->property_sensitive()
- = memory_usage_radiobutton->get_active();
-}
-
void ChooseMonitorWindow::on_swap_usage_radiobutton_toggled()
{
swap_usage_options->property_sensitive()
= swap_usage_radiobutton->get_active();
}
-void ChooseMonitorWindow::on_fan_speed_radiobutton_toggled()
+void ChooseMonitorWindow::on_memory_usage_radiobutton_toggled()
{
- fan_speed_options->property_sensitive()
- = fan_speed_radiobutton->get_active();
+ memory_usage_options->property_sensitive()
+ = memory_usage_radiobutton->get_active();
}
/* Triggered when user edits a network interface name after revealing the
@@ -852,6 +1080,30 @@ void ChooseMonitorWindow::on_temperature_radiobutton_toggled()
= temperature_radiobutton->get_active();
}
+void ChooseMonitorWindow::on_fan_speed_radiobutton_toggled()
+{
+ fan_speed_options->property_sensitive()
+ = fan_speed_radiobutton->get_active();
+}
+
+void ChooseMonitorWindow::on_generic_radiobutton_toggled()
+{
+ generic_options->property_sensitive()
+ = generic_radiobutton->get_active();
+}
+
+void ChooseMonitorWindow::on_generic_extract_via_regex_radiobutton_toggled()
+{
+ generic_number_regex_hbox->property_sensitive()
+ = generic_extract_via_regex_radiobutton->get_active();
+}
+
+void ChooseMonitorWindow::on_generic_change_in_value_checkbutton_toggled()
+{
+ generic_change_in_value_hbox->property_sensitive()
+ = generic_change_in_value_checkbutton->get_active();
+}
+
bool ChooseMonitorWindow::on_closed(GdkEventAny *)
{
window->hide();
diff --git a/src/choose-monitor-window.hpp b/src/choose-monitor-window.hpp
index 05396c0..cb9b86a 100644
--- a/src/choose-monitor-window.hpp
+++ b/src/choose-monitor-window.hpp
@@ -69,7 +69,7 @@ private:
Gtk::RadioButton *cpu_usage_radiobutton, *memory_usage_radiobutton,
*swap_usage_radiobutton, *load_average_radiobutton, *disk_usage_radiobutton,
*disk_stats_radiobutton, *network_load_radiobutton, *temperature_radiobutton,
- *fan_speed_radiobutton;
+ *fan_speed_radiobutton, *generic_radiobutton;
Gtk::Box *cpu_usage_options, *load_average_options;
Gtk::RadioButton *all_cpus_radiobutton, *one_cpu_radiobutton;
@@ -95,6 +95,19 @@ private:
Gtk::ComboBox *temperature_combobox, *fan_speed_combobox;
Gtk::Entry *temperature_tag, *fan_speed_tag;
+ Gtk::Box *generic_box, *generic_options, *generic_change_in_value_hbox,
+ *generic_number_regex_hbox;
+ Gtk::Entry *generic_file_path_entry, *generic_regex_entry,
+ *generic_data_source_name_long_entry,
+ *generic_data_source_name_short_entry, *generic_units_long_entry,
+ *generic_units_short_entry, *generic_tag;
+ Gtk::CheckButton *generic_change_in_value_checkbutton;
+ Gtk::RadioButton *generic_read_all_contents_radiobutton,
+ *generic_extract_via_regex_radiobutton,
+ *generic_change_in_value_positive_radiobutton,
+ *generic_change_in_value_negative_radiobutton,
+ *generic_change_in_value_both_radiobutton;
+
XfcePanelPlugin* panel_applet;
// For disk statistics device name combobox
@@ -176,14 +189,17 @@ private:
void on_load_average_radiobutton_toggled();
void on_disk_usage_radiobutton_toggled();
void on_disk_stats_radiobutton_toggled();
- void on_memory_usage_radiobutton_toggled();
void on_swap_usage_radiobutton_toggled();
- void on_fan_speed_radiobutton_toggled();
- void on_network_load_radiobutton_toggled();
+ void on_memory_usage_radiobutton_toggled();
void on_network_interfaces_restore_defaults_button_clicked();
- void on_temperature_radiobutton_toggled();
void on_network_interface_name_edited(const Glib::ustring& path,
const Glib::ustring& new_text);
+ void on_network_load_radiobutton_toggled();
+ void on_temperature_radiobutton_toggled();
+ void on_fan_speed_radiobutton_toggled();
+ void on_generic_radiobutton_toggled();
+ void on_generic_extract_via_regex_radiobutton_toggled();
+ void on_generic_change_in_value_checkbutton_toggled();
bool on_closed(GdkEventAny *);
};
diff --git a/src/monitor-impls.cpp b/src/monitor-impls.cpp
index 510f4c2..1059bd2 100644
--- a/src/monitor-impls.cpp
+++ b/src/monitor-impls.cpp
@@ -20,8 +20,10 @@
*/
#include <algorithm>
+#include <cmath> // For fabs
#include <iomanip> // Needed for Precision helper
#include <iostream>
+#include <limits> // Used for sentinel value in Generic Monitor
#include <string>
#include <vector>
@@ -187,6 +189,7 @@ load_monitors(XfceRc *settings_ro, XfcePanelPlugin *panel_plugin)
"interface_direction", NetworkLoadMonitor::all_data);
// Converting direction setting into dedicated type
+ // TODO: I think I need to standardise my enum loading/dealing with code
NetworkLoadMonitor::Direction dir;
if (inter_direction == NetworkLoadMonitor::incoming_data)
@@ -218,6 +221,36 @@ load_monitors(XfceRc *settings_ro, XfcePanelPlugin *panel_plugin)
monitors.push_back(new FanSpeedMonitor(fan_no, tag));
}
+ else if (type == "generic")
+ {
+ // Fetching settings
+ Glib::ustring file_path = xfce_rc_read_entry(settings_ro, "file_path",
+ ""),
+ regex_string = xfce_rc_read_entry(settings_ro, "regex", ""),
+ data_source_name_long = xfce_rc_read_entry(settings_ro,
+ "data_source_name_long", ""),
+ data_source_name_short = xfce_rc_read_entry(settings_ro,
+ "data_source_name_short", ""),
+ units_long = xfce_rc_read_entry(settings_ro, "units_long", ""),
+ units_short = xfce_rc_read_entry(settings_ro, "units_short", "");
+ bool value_from_contents = xfce_rc_read_bool_entry(settings_ro,
+ "value_from_contents",
+ false),
+ follow_change = xfce_rc_read_bool_entry(settings_ro, "follow_change",
+ false);
+ GenericMonitor::ValueChangeDirection dir =
+ static_cast<GenericMonitor::ValueChangeDirection>(
+ xfce_rc_read_int_entry(settings_ro, "value_change_direction",
+ GenericMonitor::positive));
+
+ // Creating generic monitor
+ monitors.push_back(new GenericMonitor(file_path, value_from_contents,
+ regex_string, follow_change, dir,
+ data_source_name_long,
+ data_source_name_short, units_long,
+ units_short, tag));
+ }
+
// Saving the monitor's settings root
monitors.back()->set_settings_dir(settings_monitors[i]);
}
@@ -226,7 +259,7 @@ load_monitors(XfceRc *settings_ro, XfcePanelPlugin *panel_plugin)
g_strfreev(settings_monitors);
}
- // Always start with a CpuUsageMonitor - FIXME: use schema?
+ // Always start with a CpuUsageMonitor
if (monitors.empty())
monitors.push_back(new CpuUsageMonitor(""));
@@ -728,7 +761,7 @@ DiskStatsMonitor::DiskStatsMonitor(const Glib::ustring &device_name,
double DiskStatsMonitor::do_measure()
{
// Making sure stats file is available
- if (!stats_available())
+ if (!Glib::file_test(diskstats_path, Glib::FileTest::FILE_TEST_EXISTS))
{
std::cerr << Glib::ustring::compose(_("The file '%1' is not available - "
"unable to obtain %2 for device '%3'!"
@@ -835,15 +868,6 @@ void DiskStatsMonitor::save(XfceRc *settings_w)
xfce_rc_write_entry(settings_w, "tag", tag.c_str());
}
-bool DiskStatsMonitor::stats_available()
-{
- // Make sure file exists
- return Glib::file_test(diskstats_path, Glib::FileTest::FILE_TEST_EXISTS);
-
- /* The contents of the file will be validated as it is processed, so not
- * duplicating this here */
-}
-
std::map<Glib::ustring, std::vector<unsigned long int>>
DiskStatsMonitor::parse_disk_stats()
{
@@ -1952,3 +1976,217 @@ void FanSpeedMonitor::save(XfceRc *settings_w)
xfce_rc_write_entry(settings_w, "max", setting.c_str());
}
+
+//
+// class GenericMonitor
+//
+
+GenericMonitor::GenericMonitor(const Glib::ustring &file_path,
+ const bool value_from_contents,
+ const Glib::ustring ®ex_string,
+ const bool follow_change,
+ const ValueChangeDirection dir,
+ const Glib::ustring &data_source_name_long,
+ const Glib::ustring &data_source_name_short,
+ const Glib::ustring &units_long,
+ const Glib::ustring &units_short,
+ const Glib::ustring &tag_string)
+ : Monitor(tag_string), max_value(0),
+ previous_value(std::numeric_limits<double>::min()),
+ file_path(file_path), value_from_contents(value_from_contents),
+ follow_change(follow_change), dir(dir),
+ data_source_name_long(data_source_name_long),
+ data_source_name_short(data_source_name_short), units_long(units_long),
+ units_short(units_short)
+{
+ // Compiling regex if provided (at this stage its already been validated)
+ if (regex_string != "")
+ regex = Glib::Regex::create(regex_string);
+}
+
+double GenericMonitor::do_measure()
+{
+ // Making sure stats file is available
+ if (!Glib::file_test(file_path, Glib::FileTest::FILE_TEST_EXISTS))
+ {
+ std::cerr << Glib::ustring::compose(_("The file '%1' for the Generic Monitor"
+ " data source '%2' is not available!\n"),
+ file_path, data_source_name_long);
+ return 0;
+ }
+
+ // Attempting to read contents of provided file
+ Glib::ustring file_contents;
+ try
+ {
+ file_contents = Glib::file_get_contents(file_path);
+ }
+ catch (Glib::FileError const &e)
+ {
+ std::cerr << Glib::ustring::compose(_("Unable read the contents of '%1' for "
+ "the Generic Monitor data source '%2' "
+ "due to error '%3'\n"),
+ file_path, data_source_name_long,
+ e.what());
+ return 0;
+ }
+
+ // Removing trailing newline if present
+ if (file_contents.substr(file_contents.length() - 1,
+ file_contents.length() - 1) == "\n")
+ file_contents = file_contents.substr(0, file_contents.length() - 1);
+
+ // Obtaining number
+ double val;
+ std::stringstream data;
+ if (value_from_contents)
+ {
+ // Obtain number from the entire contents of the file
+ data.str(file_contents);
+ if (!(data >> val))
+ {
+ std::cerr << Glib::ustring::compose(_("Unable to convert data '%1' from file "
+ "'%2' associated with Generic Monitor "
+ "data source '%3' into a number to "
+ "process! Defaulting to 0\n"),
+ file_contents, file_path,
+ data_source_name_long);
+ return 0;
+ }
+ }
+ else
+ {
+ /* Obtain number via a regex - the regex has already been validated with one
+ * matching group */
+ Glib::MatchInfo match_info;
+ if (!regex->match(file_contents, match_info))
+ {
+ // Unable to extract the number - warning user
+ std::cerr << Glib::ustring::compose(_("Unable extract number from file "
+ "contents '%1' from '%2' associated "
+ "with Generic Monitor data source '%3'"
+ " using the regex '%4'! Defaulting to "
+ "0\n"), file_contents, file_path,
+ data_source_name_long,
+ regex->get_pattern());
+ return 0;
+ }
+
+ // Fetching matching group results and attempting to convert to number
+ data.str(match_info.fetch(0));
+ if (!(data >> val))
+ {
+ std::cerr << Glib::ustring::compose(_("Unable to convert data '%1' from file "
+ "'%2' associated with Generic Monitor "
+ "data source '%3' into a number to "
+ "process! Defaulting to 0\n"),
+ file_contents, file_path,
+ data_source_name_long);
+ return 0;
+ }
+ }
+
+ double return_value;
+ if (follow_change)
+ {
+ /* User has requested to diff the data to make a rate of change
+ * Dealing with the first value to be processed */
+ if (previous_value == std::numeric_limits<double>::min())
+ previous_value = val;
+
+ /* Returning desired stat, based on whether the user wants only positive
+ * changes, negative changes, or both reported (these are intended for views
+ * that don't have a negative axis) */
+ switch (dir)
+ {
+ case positive:
+ return_value = val - previous_value;
+ if (return_value <0)
+ return_value = 0;
+ break;
+
+ case negative:
+ return_value = previous_value - val;
+ if (return_value <0)
+ return_value = 0;
+ break;
+
+ case both:
+ return_value = fabs(val - previous_value);
+ }
+ previous_value = val;
+ }
+ else
+ return_value = val;
+
+ // TODO: How do negative values affect this?
+ /* Note - max_value is no longer used to determine the graph max for
+ * Curves - the actual maxima stored in the ValueHistories are used */
+ if (val != 0) // Reduce scale gradually
+ max_value = guint64(max_value * max_decay);
+
+ if (val > max_value)
+ max_value = guint64(val * 1.05);
+
+ // Debug code
+ /*std::cerr << Glib::ustring::compose("Generic Monitor '%1' data: %2, previous "
+ "data: %3\n", data_source_name_long, val,
+ previous_value);*/
+
+ return return_value;
+}
+
+double GenericMonitor::max()
+{
+ return max_value;
+}
+
+bool GenericMonitor::fixed_max()
+{
+ return false;
+}
+
+Glib::ustring GenericMonitor::format_value(double val, bool compact)
+{
+ return Glib::ustring::compose("%1%2", val,
+ (compact) ? units_short : units_long);
+}
+
+Glib::ustring GenericMonitor::get_name()
+{
+ return data_source_name_long;
+}
+
+
+Glib::ustring GenericMonitor::get_short_name()
+{
+ return data_source_name_short;
+}
+
+int GenericMonitor::update_interval()
+{
+ return 1000;
+}
+
+void GenericMonitor::save(XfceRc *settings_w)
+{
+ // Fetching assigned settings group
+ Glib::ustring directory = get_settings_dir();
+
+ // Saving settings
+ xfce_rc_set_group(settings_w, directory.c_str());
+ xfce_rc_write_entry(settings_w, "type", "generic");
+ xfce_rc_write_entry(settings_w, "file_path", file_path.c_str());
+ xfce_rc_write_bool_entry(settings_w, "value_from_contents", value_from_contents);
+ xfce_rc_write_entry(settings_w, "regex", regex->get_pattern().c_str());
+ xfce_rc_write_bool_entry(settings_w, "follow_change", follow_change);
+ xfce_rc_write_int_entry(settings_w, "value_change_direction", dir);
+ xfce_rc_write_entry(settings_w, "data_source_name_long",
+ data_source_name_long.c_str());
+ xfce_rc_write_entry(settings_w, "data_source_name_short",
+ data_source_name_short.c_str());
+ xfce_rc_write_entry(settings_w, "units_long", units_long.c_str());
+ xfce_rc_write_entry(settings_w, "units_short", units_short.c_str());
+ xfce_rc_write_entry(settings_w, "tag", tag.c_str());
+}
+
diff --git a/src/monitor-impls.hpp b/src/monitor-impls.hpp
index 89ed4bd..2c17ff7 100644
--- a/src/monitor-impls.hpp
+++ b/src/monitor-impls.hpp
@@ -29,6 +29,7 @@
#include <vector>
#include <glib/gtypes.h>
+#include <glibmm/regex.h>
#if HAVE_LIBSENSORS
#include <sensors/sensors.h>
@@ -184,13 +185,12 @@ public:
virtual double max();
virtual bool fixed_max();
- virtual Glib::ustring format_value(double val, bool compact= false);
+ virtual Glib::ustring format_value(double val, bool compact=false);
virtual Glib::ustring get_name();
virtual Glib::ustring get_short_name();
virtual int update_interval();
virtual void save(XfceRc *settings_w);
- static bool stats_available();
static std::vector<Glib::ustring> current_device_names();
static Glib::ustring stat_to_string(
const DiskStatsMonitor::Stat &stat, const bool short_ver);
@@ -357,6 +357,50 @@ private:
};
+class GenericMonitor: public Monitor
+{
+public:
+
+ // Used for the 'follow change in value' implementation setting
+ enum ValueChangeDirection {
+ positive,
+ negative,
+ both,
+ NUM_DIRECTIONS
+ };
+
+ GenericMonitor(const Glib::ustring &file_path,
+ const bool value_from_contents,
+ const Glib::ustring ®ex_string,
+ const bool follow_change,
+ const ValueChangeDirection dir,
+ const Glib::ustring &data_source_name_long,
+ const Glib::ustring &data_source_name_short,
+ const Glib::ustring &units_long,
+ const Glib::ustring &units_short,
+ const Glib::ustring &tag_string);
+
+ virtual double max();
+ virtual bool fixed_max();
+ virtual Glib::ustring format_value(double val, bool compact=false);
+ virtual Glib::ustring get_name();
+ virtual Glib::ustring get_short_name();
+ virtual int update_interval();
+ virtual void save(XfceRc *settings_w);
+
+private:
+ virtual double do_measure();
+
+ double max_value, previous_value;
+
+ Glib::ustring file_path, data_source_name_long,
+ data_source_name_short, units_long, units_short, tag;
+ bool value_from_contents, follow_change;
+ ValueChangeDirection dir;
+ Glib::RefPtr<Glib::Regex> regex;
+};
+
+
// a singleton for initializing the sensors library
class Sensors: noncopyable
{
diff --git a/src/ui.glade b/src/ui.glade
index c96a540..9a27b47 100644
--- a/src/ui.glade
+++ b/src/ui.glade
@@ -1375,6 +1375,500 @@ view</property>
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkVBox" id="generic_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkVBox" id="generic_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkRadioButton" id="generic_radiobutton">
+ <property name="label" translatable="yes">_Generic</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Data/numbers read from a user-defined file</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">cpu_usage_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="generic_options">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkVBox" id="generic_options_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="generic_file_path_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="file_path_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">File to read from:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_file_path_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Enter the path to the file to read a number from</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="generic_number_reading_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkRadioButton" id="generic_read_all_contents_radiobutton">
+ <property name="label" translatable="yes">Number from entire contents</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="generic_extract_via_regex_radiobutton">
+ <property name="label" translatable="yes">Number from regex</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">generic_read_all_contents_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="generic_number_regex_hbox">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="regex_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Regex to use:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_regex_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Regex to extract the number from the file contents with (must have one capture group for the number)</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="generic_change_in_value_checkbutton">
+ <property name="label" translatable="yes">Follow _change in value</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">When visualised, rather than plotting the data direct, the difference between the current and previous measurement will be used</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="generic_change_in_value_hbox">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkRadioButton" id="generic_change_in_value_positive_radiobutton">
+ <property name="label" translatable="yes">Positive change</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Return absolute difference between current value and previous value, when change is positive</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="generic_change_in_value_negative_radiobutton">
+ <property name="label" translatable="yes">Negative change</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Return absolute difference between current value and previous value, when change is negative</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">generic_change_in_value_positive_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="generic_change_in_value_both_radiobutton">
+ <property name="label" translatable="yes">Both</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Return absolute difference between current value and previous value in either case</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">generic_change_in_value_positive_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="data_source_name_long_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="data_source_name_long_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Data source name (long):</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_data_source_name_long_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">The full name of your data source</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="data_source_name_short_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="data_source_name_short_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Data source name (short):</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_data_source_name_short_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">A short version of your data source name for display in crampt areas</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="units_long_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="units_long_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Units (long):</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_units_long_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Units the data source is in</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="units_short_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="units_short_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Units (short):</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_units_short_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Units the data source is in for display in crampt areas</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="generic_tag_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="generic_tag_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Tag: </property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="generic_tag_entry">
+ <property name="width_request">80</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">Tag to display along with monitor data
+in the optional text overlay in a curve
+view</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">9</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">18</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="generic_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Generic</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">True</property>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list