/*
 * Copyright (C) 2005 Alex Murray <pragmatine@gmail.com>
 *
 * 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
 */

/** Contain the functions for operating on the SensorsApplet structure
 *  (represents the applet itself, and its associated variables.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include <gnome.h>
#include <glib/gprintf.h>
#include "sensors-applet.h"
#include "active-sensor.h"
#include "sensors-applet-gconf.h"

/* use libsensors if available, otherwise manually find sensors */
#ifdef HAVE_LIBSENSORS
#include "libsensors-sensors-interface.h"
#endif

#include "mbmon-sensors-interface.h"
#include "smartctl-sensors-interface.h"
#include "prefs-dialog.h"
#include "about-dialog.h"

#define SENSORS_APPLET_MENU_FILE "SensorsApplet.xml"
#define DEFAULT_TIMEOUT 2000

/* callbacks for panel menu */
static void prefs_cb(BonoboUIComponent *uic,
		     SensorsApplet    *sensors_applet,
		     const gchar       *verbname) {
	if (sensors_applet->prefs_dialog) {
		gtk_window_present(GTK_WINDOW(sensors_applet->prefs_dialog));
		return;
	}
	prefs_dialog_open(sensors_applet);
}

static void about_cb(BonoboUIComponent *uic,
		     SensorsApplet    *sensors_applet,
		     const gchar       *verbname) {
#ifndef HAVE_GTK_26
	if (sensors_applet->about_dialog) {
		gtk_window_present(GTK_WINDOW(sensors_applet->about_dialog));
		return;
	}
#endif /* HAVE_GTK_26 */
	about_dialog_open(sensors_applet);
}

static void help_cb (BonoboUIComponent *uic, 
		     SensorsApplet *sensors_applet,
		     const gchar *verbname) {
	   GError *error = NULL;
	   
	   gnome_help_display(PACKAGE, NULL,
			      &error);

	   if (error) {
			 g_debug("Could not open help document: %s\n ",error->message);
			 g_error_free (error);
	   }
}

static void destroy_cb(GtkWidget *widget, SensorsApplet *sensors_applet) {
	/* destory sensors tree and dialogs and finally the applet */
	if (sensors_applet->timeout_id) {
		g_source_remove(sensors_applet->timeout_id);
	}

	if (sensors_applet->sensors != NULL) {
		gtk_tree_store_clear(sensors_applet->sensors);
	}

	if (sensors_applet->prefs_dialog != NULL) {
		gtk_widget_destroy(GTK_WIDGET(sensors_applet->prefs_dialog));
	}
	gtk_widget_destroy(GTK_WIDGET(sensors_applet->applet));

	g_free(sensors_applet);
	return;
}

static void change_background_cb(PanelApplet *applet, 
				 PanelAppletBackgroundType type,
				 GdkColor *color, 
				 GdkPixmap *pixmap, 
				 SensorsApplet *sensors_applet) {
	GtkRcStyle *rc_style;
	GtkStyle *style;

	g_assert(applet == sensors_applet->applet);

	/* reset style */
	gtk_widget_set_style(GTK_WIDGET(applet), NULL);
	rc_style = gtk_rc_style_new();
	gtk_widget_modify_style(GTK_WIDGET(applet), rc_style);
	gtk_rc_style_unref(rc_style);

	switch(type) {
	case PANEL_COLOR_BACKGROUND:
		gtk_widget_modify_bg(GTK_WIDGET(applet),
				     GTK_STATE_NORMAL, color);
		break;

	case PANEL_PIXMAP_BACKGROUND:
		style = gtk_style_copy(GTK_WIDGET(applet)->style);
		if (style->bg_pixmap[GTK_STATE_NORMAL]) {
			g_object_unref(style->bg_pixmap[GTK_STATE_NORMAL]);
		}
		style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref(pixmap);
		gtk_widget_set_style(GTK_WIDGET(applet), style);
		g_object_unref(style);
		break;

	case PANEL_NO_BACKGROUND:
		/* fall through */
	default:
		break;
	}
}

static const BonoboUIVerb sensors_applet_menu_verbs[] = {
	BONOBO_UI_UNSAFE_VERB("Preferences", prefs_cb),
	BONOBO_UI_UNSAFE_VERB ("Help", help_cb),
	BONOBO_UI_UNSAFE_VERB("About", about_cb),
	BONOBO_UI_VERB_END
};


/* functions to be called by the different sensors intefaces */
void sensors_applet_register_sensors_interface(SensorsApplet *sensors_applet,
					       SensorInterface interface,
					       GetSensorValueFunction get_sensor_value_function) {
	sensors_applet->get_sensor_value[interface] = get_sensor_value_function;
}


   
  

gboolean sensors_applet_add_sensor_full_details(SensorsApplet *sensors_applet,
						const gchar *path, 
						const gchar *id, 
						const gchar *label, 
						SensorInterface interface, 
						SensorType type, 
						gboolean enable,
						gdouble alarm_value,
						AlarmType alarm_type,
						gboolean alarm_enable,
						const gchar *alarm_command,
						gint alarm_timeout,
						gdouble multiplier,
						gdouble offset,
						const gchar *icon_filename) {

					       
	GtkTreeIter interfaces_iter, sensors_iter;
	gboolean not_empty_tree;

	/* assign to UNUSED to ensure we dont accidently match an
	 * interface that doesnt actually exist */
	guint node_interface = UNUSED;
	gboolean not_end_of_interfaces = TRUE, interface_exists = FALSE;
	gboolean not_end_of_sensors = TRUE;
	gchar *sensor_id;
	GdkPixbuf *icon;
	GError *error = NULL;
	GtkTreePath *tree_path;
	GtkTreeRowReference *row;
	ActiveSensor *active_sensor;

	g_assert(sensors_applet != NULL);

	/* assume tree is not empty */
	not_empty_tree = TRUE;


	if (NULL == sensors_applet->sensors) {

		sensors_applet->sensors = gtk_tree_store_new(N_COLUMNS, 
							     G_TYPE_STRING, /* path */
							     G_TYPE_STRING, /* id */
							     G_TYPE_STRING, /* label */
							     G_TYPE_UINT, /* interface */
							     G_TYPE_UINT, /* sensor
									   * type */
							     G_TYPE_BOOLEAN, /* enable */
							     G_TYPE_BOOLEAN, /* visible */
							     G_TYPE_DOUBLE, /* alarm value */
							     G_TYPE_UINT, /* alarm type */
							     G_TYPE_BOOLEAN, /* alarm enable */
							     G_TYPE_STRING, /* alarm command */ 
							     G_TYPE_UINT, /* alarm timeout */
							     G_TYPE_DOUBLE, /* multiplier */
							     G_TYPE_DOUBLE, /* offset */
							     G_TYPE_STRING, /* icon filename */
							     GDK_TYPE_PIXBUF); /* icon pixbuf */
		      
		 
		g_debug("Sensor tree created.\n");

		/* we know tree is actually empty since we just created it */
		not_empty_tree = FALSE;
	}
	
	/* search sensor tree for the parent interface to place this
	 * sensor under */
	for (not_empty_tree = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter); not_empty_tree && not_end_of_interfaces && !interface_exists; not_end_of_interfaces = gtk_tree_model_iter_next(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter)) {
		gtk_tree_model_get(GTK_TREE_MODEL(sensors_applet->sensors), &interfaces_iter,
				   INTERFACE_COLUMN, &node_interface,
				   -1);
		if (interface == node_interface) {
			/* found interface in tree */
			interface_exists = TRUE;

			/* now see if this actual sensor already
			 * exists within this interface - don't want
			 * to add duplicates */
			/* see if have children */
			for (not_end_of_sensors = 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,
						   ID_COLUMN, &sensor_id,
						   -1);
				if (g_ascii_strcasecmp(sensor_id, id) == 0) {
					/* sensor already exists so
					 * dont add a second time */
					g_debug("sensor already exists in tree, not adding a second time: %s\n", sensor_id);
					g_free(sensor_id);
					return FALSE;
				}
				g_free(sensor_id);
			}
							    
			break;
		}
	}


	if (!interface_exists) {
		/* wasn't able to find interface root node so create it */
		gtk_tree_store_append(sensors_applet->sensors,
				      &interfaces_iter,
				      NULL);
		
		gtk_tree_store_set(sensors_applet->sensors,
				   &interfaces_iter,
				   ID_COLUMN, sensor_interface[interface],
				   INTERFACE_COLUMN, interface,
				   VISIBLE_COLUMN, FALSE,
				   -1);
		
	}

	/* try to load the icon */
	g_debug("loading icon %s\n", icon_filename);
	icon = gdk_pixbuf_new_from_file_at_size(icon_filename, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE, &error);
	if (error) {
		 g_warning ("Could not load icon: %s\nTrying with default icon.\n", error->message);
		 g_error_free(error);
		 error = NULL;

		 /* try again with default name */
		 icon_filename = SENSORS_APPLET_ICON;
		 icon = gdk_pixbuf_new_from_file_at_size(icon_filename, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE, &error);
		 if (error) {
			 g_warning ("Could not load icon: %s\n", error->message);
			 g_error_free(error);
			 error = NULL;
			 return;
		 }
	}

	
	/* then add sensor as a child under interface node - ie assume
	 * we either found it or created it - the inteface node that
	 * is */

	/* for now just add sensors all in a single list */
	gtk_tree_store_append(sensors_applet->sensors,
			      &sensors_iter,
			      &interfaces_iter);
	
	gtk_tree_store_set(sensors_applet->sensors,
			   &sensors_iter,
			   PATH_COLUMN, path,
			   ID_COLUMN, id,
			   LABEL_COLUMN, label,
			   INTERFACE_COLUMN, interface,
			   SENSOR_TYPE_COLUMN, type,
			   ENABLE_COLUMN, enable,
			   VISIBLE_COLUMN, TRUE,
			   ALARM_VALUE_COLUMN, alarm_value,
			   ALARM_TYPE_COLUMN, alarm_type,
			   ALARM_ENABLE_COLUMN, alarm_enable,
			   ALARM_COMMAND_COLUMN, alarm_command,
			   ALARM_TIMEOUT_COLUMN, alarm_timeout,
			   MULTIPLIER_COLUMN, multiplier,
			   OFFSET_COLUMN, offset,
			   ICON_FILENAME_COLUMN, icon_filename,
			   ICON_PIXBUF_COLUMN, icon,
			   -1);

	/* remove reference to icon as tree now has ref */
	g_object_unref(icon);

	/* create the active sensor */
	if (enable) {
		tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(sensors_applet->sensors), &sensors_iter);
		sensors_applet_sensor_enabled(sensors_applet,
					      tree_path);
		gtk_tree_path_free(tree_path);
	}

}	


static ActiveSensor *sensors_applet_find_active_sensor(SensorsApplet *sensors_applet,
							GtkTreePath *path) {
	GtkTreePath *sensor_tree_path;
	GList *current_sensor;
	
	for (current_sensor = sensors_applet->active_sensors; current_sensor != NULL; current_sensor = g_list_next(current_sensor)) {
		sensor_tree_path = gtk_tree_row_reference_get_path(((ActiveSensor *)(current_sensor->data))->sensor_row);

		if (gtk_tree_path_compare(path, sensor_tree_path) == 0) {
			g_debug("found AS...\n");
			return ((ActiveSensor *)(current_sensor->data));
		}
	}
	return NULL;
}
	
	
/* path should be the full path to a file representing the sensor (eg
 * /dev/hda or /sys/devices/platform/i2c-0/0-0290/temp1_input) */
gboolean sensors_applet_add_sensor(SensorsApplet *sensors_applet,
				   const gchar *path, 
				   const gchar *id, 
				   const gchar *label, 
				   SensorInterface interface, 
				   gboolean enable,
				   SensorType type,
				   const gchar *icon_filename) {
	
	g_assert(sensors_applet != NULL);
	if (icon_filename == NULL) {
		icon_filename = SENSORS_APPLET_ICON;
	}

	return sensors_applet_add_sensor_full_details(sensors_applet,
						      path,
						      id,
						      label,
						      interface,
						      type,
						      enable,
						      0.0,
						      ALARM_WHEN_VALUE_GREATER_THAN_THRESHOLD,
						      FALSE,
						      "",
						      0,
						      1.0,
						      0.0,
						      icon_filename);
} 

	
	
/* internal helper functions for updating display etc*/


/* should be called as a g_container_foreach at the start of
 * pack_display if ythe table already exists to remove but keep alive
 * all children of the table before repacking it */
static void sensors_applet_pack_display_empty_table_cb(GtkWidget *widget,
						   gpointer data) {
	GtkContainer *container = GTK_CONTAINER(data);

	/* ref then remove widget */
	g_object_ref(widget);
	gtk_container_remove(container, widget);
}

/* should be called as a g_container_foreach at the end of
 * pack_display to unref any of the old children that we have readdded
 * to the table to stop reference creep from the g_object_ref called
 * on each child at the start of pack labels */
static void sensors_applet_pack_display_cleanup_refs_cb(GtkWidget *widget,
							gpointer data) {
						  
	GList *old_children = (GList *)data;
	if (g_list_find(old_children, widget)) {
		g_object_unref(widget);
	}
}
						 
static void sensors_applet_pack_display(SensorsApplet *sensors_applet) {
	/* note the if () around each widget is to ensure we only
	 * operate on those that actually exist */
	static GtkLabel *no_sensors_enabled_label = NULL;
	gint num_active_sensors = 0, num_sensors_per_group, cols, rows, i, j;
	GList *old_table_children = NULL;

	GList *current_sensor;

	gint display_mode;

	num_active_sensors = g_list_length(sensors_applet->active_sensors);
	display_mode = panel_applet_gconf_get_int(sensors_applet->applet, DISPLAY_MODE, NULL);

	num_sensors_per_group = panel_applet_gconf_get_int(sensors_applet->applet, NUM_SENSORS, NULL);

	if (panel_applet_get_orient(sensors_applet->applet) == PANEL_APPLET_ORIENT_UP || panel_applet_get_orient(sensors_applet->applet) == PANEL_APPLET_ORIENT_DOWN) {
		/* if oriented horizontally, want as many
		   sensors per column as user has defined, then
		   enough columns to hold all the values */
		rows = num_sensors_per_group;
		cols = num_active_sensors / num_sensors_per_group;
		while (rows * cols < num_active_sensors || cols == 0) {
			cols++;
		}
		
	} else {
		/* if oriented vertically, want as many
		   sensors per row as user has defined, then
		   enough rows to hold all the labels */
		cols = num_sensors_per_group;
		rows = num_active_sensors / num_sensors_per_group;
		while (rows * cols < num_active_sensors || rows == 0) {
			rows++;
		}
		
	}

	/* if displaying labels need to modify number of rows / colums
	   to accomodate this */
	 if (display_mode != DISPLAY_NONE) {
		 if (panel_applet_gconf_get_bool(sensors_applet->applet, LABELS_INLINE, NULL)) {
			 /* to display labels next to values need twice
			    as many columns */
			 cols *= 2;
		 } else {
			 /* to display labels above values, we need
			  * twice as many rows as without */
			 rows *= 2;
		 }
	 }	 

	if (sensors_applet->table == NULL) {
		/* create table and add to applet */
		sensors_applet->table = gtk_table_new(rows, cols, FALSE);
		gtk_table_set_col_spacings(GTK_TABLE(sensors_applet->table), 3);
		gtk_table_set_row_spacings(GTK_TABLE(sensors_applet->table), 0);
		gtk_container_add(GTK_CONTAINER(sensors_applet->applet), sensors_applet->table);
	} else {
		/* remove all children if table already exists so we can start
		 * again */
		/* save a list of the old children for later */
		old_table_children = gtk_container_get_children(GTK_CONTAINER(sensors_applet->table));

		gtk_container_foreach(GTK_CONTAINER(sensors_applet->table),
				      sensors_applet_pack_display_empty_table_cb,
				      sensors_applet->table);

		/* then resize table */
		gtk_table_resize(GTK_TABLE(sensors_applet->table), rows, cols);
	}
	
	/* if no active sensors, display a label to this effect and return */
	if (num_active_sensors == 0) {
		if (no_sensors_enabled_label == NULL) {
			no_sensors_enabled_label = g_object_new(GTK_TYPE_LABEL,
								"label", _("No sensors enabled!"),
								NULL);
		}
		gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table),
					  GTK_WIDGET(no_sensors_enabled_label),
					  0, 1,
					  0, 1);

	}

	/* pack icons / labels and values into table */
	current_sensor = sensors_applet->active_sensors;

	/* if showing labels need to pack these first */
	if (display_mode != DISPLAY_NONE) {
		/* loop through columns */
		for (i = 0; current_sensor != NULL && i < cols; /* increments depends on how we lay them out - see below */) {
		
			/* loop through rows in a column */
			for (j = 0; current_sensor && j < rows; /* see bottom of for loop*/) {
				/* attach label / icon at this point */
				if (display_mode == DISPLAY_ICON) {
					if (((ActiveSensor *)(current_sensor->data))->icon) {
						gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table),
									  GTK_WIDGET(((ActiveSensor *)(current_sensor->data))->icon),
									  i, i + 1,
									  j, j + 1);
					}
				} else {
					if (((ActiveSensor *)(current_sensor->data))->label) {
						gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table),
									  GTK_WIDGET(((ActiveSensor *)(current_sensor->data))->label),
									  i, i + 1,
									  j, j + 1);
					}				
				}
				/* now attach sensor value to either
				   row below or column next to */
				if (panel_applet_gconf_get_bool(sensors_applet->applet, LABELS_INLINE, NULL)) { 
					/* left align labels */
					if (((ActiveSensor *)(current_sensor->data))->icon) {
						gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->icon), 0.0, 0.5);
					}
					if (((ActiveSensor *)(current_sensor->data))->label) {
						gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->label), 0.0, 0.5); 	 
					}
					if (((ActiveSensor *)(current_sensor->data))->value) {
						gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->value), 0.0, 0.5);
					}
 

					 /* place value next to label */
					if (((ActiveSensor *)(current_sensor->data))->value) {
						gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table),
									  GTK_WIDGET(((ActiveSensor *)(current_sensor->data))->value),
									  i + 1, i + 2,
									  j, j + 1);
					}
					j++;
				} else { /* place value below label */
					/* center align labels */ 	 
					if (((ActiveSensor *)(current_sensor->data))->icon) {
						gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->icon), 0.5, 0.5);
					}
					if (((ActiveSensor *)(current_sensor->data))->label) {
						gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->label), 0.5, 0.5);
					}
					if (((ActiveSensor *)(current_sensor->data))->value) {
						gtk_misc_set_alignment(GTK_MISC(((ActiveSensor *)(current_sensor->data))->value), 0.5, 0.5); 	 
					}
 
					if (((ActiveSensor *)(current_sensor->data))->value) {
						gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table),
									  GTK_WIDGET(((ActiveSensor *)(current_sensor->data))->value),
									  i, i + 1,
									  j + 1, j + 2);
					}
					j += 2;
				}
				current_sensor = g_list_next(current_sensor);

			} /* end row loop */
			/* now increment column index as needed */
			if (panel_applet_gconf_get_bool(sensors_applet->applet, LABELS_INLINE, NULL)) { /* place value next to label */
				i += 2;
			} else {
				i++;
			}
			
			
		} /* end column loop	*/

		
	} else { /* not showing labels or icons so just pack values */
		for (i = 0; current_sensor != NULL && i < cols; ++i) {
			for (j = 0; current_sensor!= NULL && j < rows; ++j) {
				if (((ActiveSensor *)(current_sensor->data))->value) {
					gtk_table_attach_defaults(GTK_TABLE(sensors_applet->table),
								  GTK_WIDGET(((ActiveSensor *)(current_sensor->data))->value),
								  i, i + 1,
								  j, j + 1);
				}

				current_sensor = g_list_next(current_sensor);
			}
		}
		
	}
	if (old_table_children != NULL) {
		gtk_container_foreach(GTK_CONTAINER(sensors_applet->table),
				      sensors_applet_pack_display_cleanup_refs_cb,
				      old_table_children);
		g_list_free(old_table_children);
	}
	gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet));

} 	    

void sensors_applet_display_layout_changed(SensorsApplet *sensors_applet) {
	sensors_applet_pack_display(sensors_applet);
}

void sensors_applet_alarm_off(SensorsApplet *sensors_applet, GtkTreePath *path) {
	ActiveSensor *active_sensor;

	if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet,
							       path)) != NULL) {
		active_sensor_alarm_off(active_sensor,
					path);
	}
}
				
void sensors_applet_sensor_enabled(SensorsApplet *sensors_applet,
				   GtkTreePath *path) {
	ActiveSensor *active_sensor;

	g_debug("creating new active sensor\n");
	g_assert(sensors_applet != NULL);
	g_assert(path != NULL);

	active_sensor = g_new0(ActiveSensor, 1);
	active_sensor->sensor_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(sensors_applet->sensors),
							       path);
	active_sensor->alarm_timeout_id = -1;
	
	/* keep list sorted */
	sensors_applet->active_sensors = g_list_insert_sorted(sensors_applet->active_sensors, active_sensor, (GCompareFunc)active_sensor_compare);
	
	active_sensor_update(active_sensor, sensors_applet);

	sensors_applet_pack_display(sensors_applet);
}

void sensors_applet_sensor_disabled(SensorsApplet *sensors_applet,
				    GtkTreePath *path) {

	GtkTreeModel *model;
	ActiveSensor *active_sensor;

	g_assert(sensors_applet != NULL);
	g_assert(path != NULL);

	if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet,
							       path)) != NULL) {
		g_debug("Destroying active sensor...\n");
		
		g_debug("-- removing from list...\n");
		sensors_applet->active_sensors = g_list_remove(sensors_applet->active_sensors,
			      active_sensor);
		g_debug("-- repacking display....\n");
		sensors_applet_pack_display(sensors_applet);

		/* destroy the current_sensor */
		g_debug("-- destroying active sensor label...\n");
		gtk_object_destroy(GTK_OBJECT(active_sensor->label));
		g_debug("-- destroying active sensor icon...\n");
		gtk_object_destroy(GTK_OBJECT(active_sensor->icon));
		g_debug("-- destroying active sensor value...\n");
		gtk_object_destroy(GTK_OBJECT(active_sensor->value));
		if (active_sensor->alarm_timeout_id >= 0) {
			active_sensor_alarm_off(active_sensor);
		}
		g_free(active_sensor);
	}
}


void sensors_applet_update_sensor(SensorsApplet *sensors_applet,
				  GtkTreePath *path) {
	ActiveSensor *active_sensor;

	g_assert(sensors_applet != NULL);
	g_assert(path != NULL);

	if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet,
							       path)) != NULL) {
		active_sensor_update(active_sensor, 
				     sensors_applet);
	}
}
 
void sensors_applet_icon_changed(SensorsApplet *sensors_applet,
				 GtkTreePath *path) {
	ActiveSensor *active_sensor;
	
	g_assert(sensors_applet != NULL);
	g_assert(path != NULL);
	
	if ((active_sensor = sensors_applet_find_active_sensor(sensors_applet,
							       path)) != NULL) {
		active_sensor_icon_changed(active_sensor,
					   sensors_applet);
	}
}
/**
 * Cycle thru ActiveSensors and update them all
 */
void sensors_applet_update_active_sensors(SensorsApplet *sensors_applet) {
	gchar *tooltip;
	unsigned long int num_active_sensors;
     
	g_assert(sensors_applet != NULL);
	g_assert(sensors_applet->active_sensors != NULL);
	
	num_active_sensors = (unsigned long int)g_list_length(sensors_applet->active_sensors);

	g_list_foreach(sensors_applet->active_sensors,
		       (GFunc)active_sensor_update,
		       sensors_applet);

	tooltip = g_strdup_printf("%s\n%d %s",
				  _("Sensors Applet"),
				  num_active_sensors,
				  ngettext(_("sensor enabled"), 
					   _("sensors enabled"),
					   num_active_sensors));
	gtk_tooltips_set_tip(sensors_applet->tooltips, GTK_WIDGET(sensors_applet->applet), tooltip, "");
	g_free(tooltip);

	return;
	
}

static void sensors_applet_write_defaults_to_gconf(SensorsApplet *sensors_applet) {
	panel_applet_gconf_set_bool(sensors_applet->applet, FARENHEIT, FALSE, NULL);
	panel_applet_gconf_set_int(sensors_applet->applet, NUM_SENSORS, 1, NULL);
	panel_applet_gconf_set_int(sensors_applet->applet, DISPLAY_MODE, DISPLAY_LABEL, NULL);
	panel_applet_gconf_set_bool(sensors_applet->applet, LABELS_INLINE, TRUE, NULL);
	panel_applet_gconf_set_bool(sensors_applet->applet, SHOW_UNITS, TRUE, NULL);
	panel_applet_gconf_set_int(sensors_applet->applet, TIMEOUT, DEFAULT_TIMEOUT, NULL);
	panel_applet_gconf_set_int(sensors_applet->applet, FONT_SIZE, MEDIUM, NULL);
	panel_applet_gconf_set_bool(sensors_applet->applet, IS_SETUP, FALSE, NULL);

}

static void sensors_applet_setup_sensors_interfaces(SensorsApplet *sensors_applet) {
#ifdef HAVE_LIBSENSORS
	libsensors_sensors_interface_init(sensors_applet);
#endif
	mbmon_sensors_interface_init(sensors_applet);
	smartctl_sensors_interface_init(sensors_applet);
}


void sensors_applet_init(SensorsApplet *sensors_applet) {
	
	g_assert(sensors_applet);
	g_assert(sensors_applet->applet);

	panel_applet_set_flags(sensors_applet->applet, PANEL_APPLET_EXPAND_MINOR);
	panel_applet_setup_menu_from_file(sensors_applet->applet,
					  DATADIR,
					  SENSORS_APPLET_MENU_FILE,
					  NULL,
					  sensors_applet_menu_verbs,
					  sensors_applet);

	g_signal_connect(sensors_applet->applet, 
			 "change_background",
			 G_CALLBACK(change_background_cb), 
			 sensors_applet);

	g_signal_connect(sensors_applet->applet, "destroy",
			 G_CALLBACK(destroy_cb),
			 sensors_applet);

		
	/* if not setup, write defaults to gconf */
	if (!panel_applet_gconf_get_bool(sensors_applet->applet, IS_SETUP, NULL)) {
		sensors_applet_write_defaults_to_gconf(sensors_applet);
	} else {
		/* setup sensors from stored gconf values */
		sensors_applet_gconf_setup_sensors(sensors_applet);
		g_debug("done setting up from gconf\n");
	}
	/* now do any setup needed manually */
	sensors_applet_setup_sensors_interfaces(sensors_applet);

		
	/* should have created sensors tree above, but if have
	   not was because we couldn't find any sensors */
	if (NULL == sensors_applet->sensors) {
		GtkWidget *label;	
		label = gtk_label_new(_("No sensors found!"));
		gtk_container_add(GTK_CONTAINER(sensors_applet->applet), label);
		gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet));
		return;
	}
	

	sensors_applet->tooltips = gtk_tooltips_new();
	gtk_tooltips_set_tip(sensors_applet->tooltips, GTK_WIDGET(sensors_applet->applet), _("Sensors Applet"), "");
	sensors_applet_update_active_sensors(sensors_applet);
	sensors_applet_pack_display(sensors_applet);

	sensors_applet->timeout_id = g_timeout_add(panel_applet_gconf_get_int(sensors_applet->applet, TIMEOUT, NULL), (GSourceFunc)sensors_applet_update_active_sensors, sensors_applet);

	gtk_widget_show_all(GTK_WIDGET(sensors_applet->applet));
}





syntax highlighted by Code2HTML, v. 0.9.1