/* * Copyright (C) 2005-2009 Alex Murray * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include "sensors-applet.h" #include "sensors-applet-mateconf.h" #define DEFAULT_TIMEOUT 2000 #define DEFAULT_GRAPH_SIZE 42 static const gchar * const compatible_versions[] = { PACKAGE_VERSION, /* always list current version */ "2.2.6", "2.2.5", "2.2.4", "2.2.3", "2.2.2", }; #define NUM_COMPATIBLE_VERSIONS G_N_ELEMENTS(compatible_versions) typedef enum { SENSORS_APPLET_MATECONF_ERROR = 0, SENSORS_APPLET_VERSION_ERROR, } SensorsAppletMateConfError; static const gchar * const error_titles[] = { N_("An error occurred loading the stored sensors data"), N_("Incompatible sensors configuration found") }; static const gchar * const error_messages[] = { N_("An error has occurred when loading the stored sensors data. " "The default values will be used to recover from this error."), N_("Unfortunately the previous configuration for MATE Sensors Applet " "is not compatible with this version. The existing sensors data " "will be overwritten with the default values for this new version.") }; /* function to be called if an error occurs when loading values from mateconf */ static void sensors_applet_mateconf_error_occurred(SensorsAppletMateConfError error) { GtkWidget *dialog; gchar *markup; g_debug("Error occurred: %s", error_titles[error]); markup = g_markup_printf_escaped("%s\n\n%s", _(error_titles[error]), _(error_messages[error])); dialog = gtk_message_dialog_new_with_markup(NULL, /* no parent window */ GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", markup); g_free(markup); /* runs dialog as modal and doesn't return until user clicks * button */ gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(GTK_WIDGET(dialog)); } static void sensors_applet_mateconf_set_defaults(SensorsApplet *sensors_applet) { mate_panel_applet_mateconf_set_int(sensors_applet->applet, DISPLAY_MODE, DISPLAY_ICON_WITH_VALUE, NULL); mate_panel_applet_mateconf_set_int(sensors_applet->applet, LAYOUT_MODE, VALUE_BESIDE_LABEL, NULL); mate_panel_applet_mateconf_set_int(sensors_applet->applet, TEMPERATURE_SCALE, CELSIUS, NULL); mate_panel_applet_mateconf_set_int(sensors_applet->applet, TIMEOUT, DEFAULT_TIMEOUT, NULL); mate_panel_applet_mateconf_set_int(sensors_applet->applet, GRAPH_SIZE, DEFAULT_GRAPH_SIZE, NULL); #ifdef HAVE_LIBMATENOTIFY mate_panel_applet_mateconf_set_bool(sensors_applet->applet, DISPLAY_NOTIFICATIONS, TRUE, NULL); #endif mate_panel_applet_mateconf_set_bool(sensors_applet->applet, IS_SETUP, FALSE, NULL); } /** * Returns TRUE is old_version is one of the compatible versions */ static gboolean sensors_applet_mateconf_is_compatible(const gchar *old_version) { guint i; for (i = 0; i < NUM_COMPATIBLE_VERSIONS; i++) { if (g_ascii_strcasecmp(old_version, compatible_versions[i]) == 0) { return TRUE; } } return FALSE; } void sensors_applet_mateconf_setup(SensorsApplet *sensors_applet) { gboolean setup = FALSE; gchar *old_version; GError *error = NULL; /* need to convert old num_samples value to new GRAPH_SIZE * parameter */ gint num_samples; if ((num_samples = mate_panel_applet_mateconf_get_int(sensors_applet->applet, "num_samples", NULL))) { g_debug("Convering old num_samples value %d into graph_size", num_samples); mate_panel_applet_mateconf_set_int(sensors_applet->applet, GRAPH_SIZE, (num_samples + GRAPH_FRAME_EXTRA_WIDTH), NULL); /* reset num_samples to zero */ mate_panel_applet_mateconf_set_int(sensors_applet->applet, "num_samples", 0, NULL); } /* convert old alarm_commands to high and low if exist */ GSList *alarm_commands; if ((alarm_commands = mate_panel_applet_mateconf_get_list(sensors_applet->applet, "alarm_commands", MATECONF_VALUE_STRING, NULL))) { g_debug("Converting old alarm commands to new high and low commands"); mate_panel_applet_mateconf_set_list(sensors_applet->applet, LOW_ALARM_COMMANDS, MATECONF_VALUE_STRING, alarm_commands, NULL); mate_panel_applet_mateconf_set_list(sensors_applet->applet, HIGH_ALARM_COMMANDS, MATECONF_VALUE_STRING, alarm_commands, NULL); /* reset old list to null */ mate_panel_applet_mateconf_set_list(sensors_applet->applet, "alarm_commands", MATECONF_VALUE_STRING, NULL, NULL); g_slist_foreach(alarm_commands, (GFunc)g_free, NULL); g_slist_free(alarm_commands); } setup = mate_panel_applet_mateconf_get_bool(sensors_applet->applet, IS_SETUP, &error); if (error) { g_debug("Previous configuration not found: %s, setting up manually", error->message); g_error_free(error); error = NULL; setup = FALSE; } if (setup) { /* see if setup version matches */ old_version = mate_panel_applet_mateconf_get_string(sensors_applet->applet, SENSORS_APPLET_VERSION, &error); /* if versions don't match or there is no saved * version string then need to overwrite old config */ if (error) { g_debug("Error getting old version string: %s", error->message); g_error_free(error); error = NULL; old_version = NULL; } if (old_version) { if (sensors_applet_mateconf_is_compatible(old_version)) { /* previously setup and versions match so use * old values */ g_debug("MateConf data is compatible. Trying to set up sensors from mateconf data"); if (sensors_applet_mateconf_setup_sensors(sensors_applet)) { g_debug("done setting up from mateconf"); } else { g_debug("Setting mateconf defaults only"); sensors_applet_mateconf_set_defaults(sensors_applet); } g_free(old_version); return; } g_free(old_version); } sensors_applet_notify(sensors_applet, MATECONF_READ_ERROR); sensors_applet_mateconf_error_occurred(SENSORS_APPLET_VERSION_ERROR); } /* use defaults */ g_debug("Setting mateconf defaults only"); sensors_applet_mateconf_set_defaults(sensors_applet); } enum { PATHS_INDEX = 0, IDS_INDEX, LABELS_INDEX, INTERFACES_INDEX, SENSOR_TYPES_INDEX, ENABLES_INDEX, LOW_VALUES_INDEX, HIGH_VALUES_INDEX, ALARM_ENABLES_INDEX, LOW_ALARM_COMMANDS_INDEX, HIGH_ALARM_COMMANDS_INDEX, ALARM_TIMEOUTS_INDEX, MULTIPLIERS_INDEX, OFFSETS_INDEX, ICON_TYPES_INDEX, GRAPH_COLORS_INDEX, NUM_KEYS }; const gchar * const keys[NUM_KEYS] = { PATHS, IDS, LABELS, INTERFACES, SENSOR_TYPES, ENABLES, LOW_VALUES, HIGH_VALUES, ALARM_ENABLES, LOW_ALARM_COMMANDS, HIGH_ALARM_COMMANDS, ALARM_TIMEOUTS, MULTIPLIERS, OFFSETS, ICON_TYPES, GRAPH_COLORS, }; /* MUST CORRESPOND TO ABOVE KEYS */ const MateConfValueType key_types[NUM_KEYS] = { MATECONF_VALUE_STRING, /* PATHS */ MATECONF_VALUE_STRING, /* IDS, */ MATECONF_VALUE_STRING, /* LABELS */ MATECONF_VALUE_STRING, /* INTERFACES, */ MATECONF_VALUE_INT, /* SENSOR_TYPES, */ MATECONF_VALUE_BOOL, /* ENABLES, */ MATECONF_VALUE_INT, /* LOW_VALUES, */ MATECONF_VALUE_INT, /* HIGH_VALUES, */ MATECONF_VALUE_BOOL, /* ALARM_ENABLES, */ MATECONF_VALUE_STRING, /* LOW_ALARM_COMMANDS, */ MATECONF_VALUE_STRING, /* HIGH_ALARM_COMMANDS, */ MATECONF_VALUE_INT, /* ALARM_TIMEOUTS, */ MATECONF_VALUE_INT, /* MULTIPLIERS, */ MATECONF_VALUE_INT, /* OFFSETS, */ MATECONF_VALUE_INT, /* ICON_TYPES, */ MATECONF_VALUE_STRING /* GRAPH_COLORS, */ }; void sensors_applet_mateconf_set_current_to_lists(GSList *current[], GSList *lists[], int len) { for (len--; len >= 0; len--) { current[len] = lists[len]; } } int sensors_applet_mateconf_current_not_null(GSList *current[], int len) { for (len--; len >= 0; len--) { if (NULL == current[len]) { return FALSE; } } return TRUE; } void sensors_applet_mateconf_current_get_next(GSList *current[], int len) { for (len--; len >= 0; len--) { current[len] = g_slist_next(current[len]); } } void sensors_applet_mateconf_free_lists(GSList *lists[], int len) { for (len--; len >= 0; len--) { if (key_types[len] == MATECONF_VALUE_STRING) { g_slist_foreach(lists[len], (GFunc)g_free, NULL); } g_slist_free(lists[len]); } } /* gets called if are already setup so we don't have to manually go through and find sensors etc again */ gboolean sensors_applet_mateconf_setup_sensors(SensorsApplet *sensors_applet) { /* everything gets stored except alarm timeout indexes, which we set to -1, and visible which we set to false for all parent nodes and true for all child nodes */ int i; GSList *lists[NUM_KEYS] = {NULL}; GSList *current[NUM_KEYS] = {NULL}; GError *error = NULL; for (i = 0; i < NUM_KEYS; i++) { lists[i] = mate_panel_applet_mateconf_get_list(sensors_applet->applet, keys[i], key_types[i], &error); if (error || NULL == lists[i]) { sensors_applet_notify(sensors_applet, MATECONF_READ_ERROR); sensors_applet_mateconf_error_occurred(SENSORS_APPLET_MATECONF_ERROR); if (error) { g_error_free(error); } return FALSE; } } for (sensors_applet_mateconf_set_current_to_lists(current, lists, NUM_KEYS); sensors_applet_mateconf_current_not_null(current, NUM_KEYS); sensors_applet_mateconf_current_get_next(current, NUM_KEYS)) { g_debug("trying to add sensor from mateconf data: %s\n", (gchar *)(current[IDS_INDEX]->data)); /* need to ensure correct order */ sensors_applet_add_sensor(sensors_applet, (gchar *)(current[PATHS_INDEX]->data), (gchar *)(current[IDS_INDEX]->data), (gchar *)(current[LABELS_INDEX]->data), (gchar *)(current[INTERFACES_INDEX]->data), GPOINTER_TO_UINT(current[SENSOR_TYPES_INDEX]->data), GPOINTER_TO_INT(current[ENABLES_INDEX]->data), (gdouble)(GPOINTER_TO_INT(current[LOW_VALUES_INDEX]->data) / 1000.0), (gdouble)(GPOINTER_TO_INT(current[HIGH_VALUES_INDEX]->data) / 1000.0), GPOINTER_TO_INT(current[ALARM_ENABLES_INDEX]->data), (gchar *)(current[LOW_ALARM_COMMANDS_INDEX]->data), (gchar *)(current[HIGH_ALARM_COMMANDS_INDEX]->data), GPOINTER_TO_INT(current[ALARM_TIMEOUTS_INDEX]->data), (gdouble)(GPOINTER_TO_INT(current[MULTIPLIERS_INDEX]->data) / 1000.0), (gdouble)(GPOINTER_TO_INT(current[OFFSETS_INDEX]->data) / 1000.0), (SensorType)GPOINTER_TO_UINT(current[ICON_TYPES_INDEX]->data), (gchar *)(current[GRAPH_COLORS_INDEX]->data) ); } sensors_applet_mateconf_free_lists(lists, NUM_KEYS); return TRUE; } gboolean sensors_applet_mateconf_save_sensors(SensorsApplet *sensors_applet) { /* write everything to mateconf except VISIBLE and ALARM_TIMEOUT_INDEX */ /* for stepping through GtkTreeStore data structure */ GtkTreeIter interfaces_iter, sensors_iter; gboolean not_end_of_interfaces = TRUE, not_end_of_sensors = TRUE; /* make sure all are initialized to null - since list of * intializers is horter than number of element, rest get set * to 0 (ie NULL) */ GSList *lists[NUM_KEYS] = {NULL}; int i; gchar *current_path, *current_id, *current_label, *current_interface, *current_low_alarm_command, *current_high_alarm_command, *current_graph_color; gboolean current_enable, current_alarm_enable; gdouble current_low_value, current_high_value, current_multiplier, current_offset; guint current_alarm_timeout, current_sensor_type, current_icon_type; GError *error = NULL; /* now step through the GtkTreeStore sensors to find which sensors are enabled */ for (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter); not_end_of_interfaces; not_end_of_interfaces = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter)) { // store a mateconf key for this interface gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter, ID_COLUMN, ¤t_id, -1); mate_panel_applet_mateconf_set_bool(sensors_applet->applet, current_id, TRUE, NULL); g_free(current_id); /* reset sensors sentinel */ not_end_of_sensors = TRUE; for (gtk_tree_model_iter_children(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter, &interfaces_iter); not_end_of_sensors; not_end_of_sensors = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter)) { gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter, PATH_COLUMN, ¤t_path, ID_COLUMN, ¤t_id, LABEL_COLUMN, ¤t_label, INTERFACE_COLUMN, ¤t_interface, SENSOR_TYPE_COLUMN, ¤t_sensor_type, ENABLE_COLUMN, ¤t_enable, LOW_VALUE_COLUMN, ¤t_low_value, HIGH_VALUE_COLUMN, ¤t_high_value, ALARM_ENABLE_COLUMN, ¤t_alarm_enable, LOW_ALARM_COMMAND_COLUMN, ¤t_low_alarm_command, HIGH_ALARM_COMMAND_COLUMN, ¤t_high_alarm_command, ALARM_TIMEOUT_COLUMN, ¤t_alarm_timeout, MULTIPLIER_COLUMN, ¤t_multiplier, OFFSET_COLUMN, ¤t_offset, ICON_TYPE_COLUMN, ¤t_icon_type, GRAPH_COLOR_COLUMN, ¤t_graph_color, -1); /* prepend values as this is faster then just reverse list when finished */ lists[PATHS_INDEX] = g_slist_prepend(lists[PATHS_INDEX], current_path); lists[IDS_INDEX] = g_slist_prepend(lists[IDS_INDEX], current_id); lists[LABELS_INDEX] = g_slist_prepend(lists[LABELS_INDEX], current_label); lists[INTERFACES_INDEX] = g_slist_prepend(lists[INTERFACES_INDEX], current_interface); lists[ENABLES_INDEX] = g_slist_prepend(lists[ENABLES_INDEX], GINT_TO_POINTER(current_enable)); lists[LOW_VALUES_INDEX] = g_slist_prepend(lists[LOW_VALUES_INDEX], GINT_TO_POINTER((gint)(current_low_value * 1000))); lists[HIGH_VALUES_INDEX] = g_slist_prepend(lists[HIGH_VALUES_INDEX], GINT_TO_POINTER((gint)(current_high_value * 1000))); lists[ALARM_ENABLES_INDEX] = g_slist_prepend(lists[ALARM_ENABLES_INDEX], GINT_TO_POINTER(current_alarm_enable)); lists[LOW_ALARM_COMMANDS_INDEX] = g_slist_prepend(lists[LOW_ALARM_COMMANDS_INDEX], current_low_alarm_command); lists[HIGH_ALARM_COMMANDS_INDEX] = g_slist_prepend(lists[HIGH_ALARM_COMMANDS_INDEX], current_high_alarm_command); lists[ALARM_TIMEOUTS_INDEX] = g_slist_prepend(lists[ALARM_TIMEOUTS_INDEX], GINT_TO_POINTER(current_alarm_timeout)); lists[SENSOR_TYPES_INDEX] = g_slist_prepend(lists[SENSOR_TYPES_INDEX], GUINT_TO_POINTER(current_sensor_type)); lists[MULTIPLIERS_INDEX] = g_slist_prepend(lists[MULTIPLIERS_INDEX], GINT_TO_POINTER((gint)(current_multiplier * 1000))); lists[OFFSETS_INDEX] = g_slist_prepend(lists[OFFSETS_INDEX], GINT_TO_POINTER((gint)(current_offset * 1000))); lists[ICON_TYPES_INDEX] = g_slist_prepend(lists[ICON_TYPES_INDEX], GUINT_TO_POINTER(current_icon_type)); lists[GRAPH_COLORS_INDEX] = g_slist_prepend(lists[GRAPH_COLORS_INDEX], current_graph_color); } } /* keep lists in original order */ for (i = 0; i < NUM_KEYS; i++) { if (lists[i] != NULL) { lists[i] = g_slist_reverse(lists[i]); mate_panel_applet_mateconf_set_list(sensors_applet->applet, keys[i], key_types[i], lists[i], &error); if (error) { sensors_applet_notify(sensors_applet, MATECONF_WRITE_ERROR); g_error_free(error); return FALSE; } } else { g_debug("list %s is NULL", keys[i]); } } sensors_applet_mateconf_free_lists(lists, NUM_KEYS); /* store current version to identify config data */ mate_panel_applet_mateconf_set_string(sensors_applet->applet, SENSORS_APPLET_VERSION, PACKAGE_VERSION, &error); return TRUE; }