/*
 * Copyright (C) 2005-2009 Alex Murray <murray.alex@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
 */

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

#include <mate.h>
#include "sensor-config-dialog.h"
#include "sensors-applet.h"

#define SPINBUTTON_WIDTH_CHARS 8
#define VALUE_DECIMAL_PLACES 3

typedef struct {
        SensorsApplet *sensors_applet;

	GtkWidget *dialog;
        /* icon widgets */
        GtkLabel *icon_header, *icon_type_label;
        GtkComboBox *icon_type_combo_box;
        GtkAlignment *icon_type_combo_box_aligner;
        GtkCellRenderer *icon_renderer;

        /* Graph Color chooser */
        GtkColorButton *graph_color_button;
        GtkAlignment *graph_color_button_aligner;
        GtkLabel *graph_color_label, *graph_header;

        /* multiplier and offset widgets */
	GtkLabel *scale_header, *multiplier_label, *offset_label;
	GtkAlignment *multiplier_spinbutton_aligner, *offset_spinbutton_aligner;
	GtkAdjustment *multiplier_adjust, *offset_adjust;
	GtkSpinButton *multiplier_spinbutton, *offset_spinbutton;

        GtkLabel *limits_header;
        GtkLabel *low_value_label, *high_value_label;
	GtkAlignment *low_value_spinbutton_aligner, *high_value_spinbutton_aligner;
	GtkAdjustment *low_value_adjust, *high_value_adjust;
	GtkSpinButton *low_value_spinbutton, *high_value_spinbutton;

	/* alarm widgets */
        GtkLabel *alarm_header;
	GtkLabel *low_alarm_command_label, *high_alarm_command_label, *alarm_timeout_label;
	GtkAlignment *alarm_timeout_spinbutton_aligner;
	GtkAdjustment *alarm_timeout_adjust;
	GtkSpinButton *alarm_timeout_spinbutton;
	GtkTable *table;
	GtkAlignment *alarm_enable_aligner;
	GtkCheckButton *alarm_enable_checkbutton;
	GtkEntry *low_alarm_command_entry, *high_alarm_command_entry;

        GtkSizeGroup *size_group;
} SensorConfigDialog;

static void sensor_config_dialog_response(GtkDialog *dialog,
                                          gint response,
                                          gpointer data) {
        SensorConfigDialog *config_dialog;
        GError *error = NULL;

        config_dialog = (SensorConfigDialog *)data;

        switch (response) {
        case GTK_RESPONSE_HELP:
                g_debug("loading help in config dialog");
                gtk_show_uri(NULL,
			     "ghelp:sensors-applet?sensors-applet-sensors",
			     gtk_get_current_event_time(),
			     &error);
                
                if (error) {
                        g_debug("Could not open help document: %s ",error->message);
                        g_error_free (error);
                }
                break;
        default:
                g_debug("destroying config dialog");
                gtk_widget_destroy(GTK_WIDGET(dialog));
        }
}

static void sensor_config_dialog_multiplier_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	gdouble value;

	value = gtk_spin_button_get_value(spinbutton);
	
	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);

	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);
	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			    &iter,
			    MULTIPLIER_COLUMN, value,
			   -1);

	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_offset_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	gdouble value;

	value = gtk_spin_button_get_value(spinbutton);
	
	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);
	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);
	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			    &iter,
			    OFFSET_COLUMN, value,
			   -1);

	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_low_value_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	gdouble value;

	value = gtk_spin_button_get_value(spinbutton);
	
	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);
	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);

	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			    &iter,
			    LOW_VALUE_COLUMN, value,
			   -1);

	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_high_value_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	gdouble value;

	value = gtk_spin_button_get_value(spinbutton);
	
	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);
	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);

	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			    &iter,
			    HIGH_VALUE_COLUMN, value,
			   -1);

	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_alarm_toggled(GtkToggleButton *button, SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;

	gboolean value;
	value = gtk_toggle_button_get_active(button);

        /* update state of alarm widgets */
        gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->alarm_timeout_label), value);
        gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->alarm_timeout_spinbutton), value);
        gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->low_alarm_command_label), value);
        gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->low_alarm_command_entry), value);
        gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->high_alarm_command_label), value);
        gtk_widget_set_sensitive(GTK_WIDGET(config_dialog->high_alarm_command_entry), value);

	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);
	
	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);

	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			    &iter,
			    ALARM_ENABLE_COLUMN, value,
			   -1);

	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_alarm_timeout_changed(GtkSpinButton *spinbutton, SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	gint value;

	value = gtk_spin_button_get_value_as_int(spinbutton);
	
	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);
	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);

	sensors_applet_all_alarms_off(config_dialog->sensors_applet, path);
	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			    &iter,
			    ALARM_TIMEOUT_COLUMN, value,
			   -1);

	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_alarm_command_edited(GtkEntry *command_entry, SensorConfigDialog *config_dialog, NotifType notif_type) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	
	gchar *value;
	g_object_get(command_entry, "text", &value, NULL);

	gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);
	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);

	sensors_applet_alarm_off(config_dialog->sensors_applet, path, notif_type);

	gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			   &iter,
			   (notif_type == LOW_ALARM ? 
                            LOW_ALARM_COMMAND_COLUMN : HIGH_ALARM_COMMAND_COLUMN), 
                           value,
			   -1);
	g_free(value);
	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

static void sensor_config_dialog_low_alarm_command_edited(GtkEntry *command_entry, SensorConfigDialog *config_dialog) {
        sensor_config_dialog_alarm_command_edited(command_entry,
                                                  config_dialog,
                                                  LOW_ALARM);
}

static void sensor_config_dialog_high_alarm_command_edited(GtkEntry *command_entry, SensorConfigDialog *config_dialog) {
        sensor_config_dialog_alarm_command_edited(command_entry,
                                                  config_dialog,
                                                  HIGH_ALARM);
}

static void sensor_config_dialog_icon_type_changed(GtkComboBox *icon_type_combo_box, 
                                                   SensorConfigDialog *config_dialog) {
        GtkTreeModel *icons_model;
        GtkTreeIter icons_iter;

	GtkTreeModel *model;
	GtkTreeIter iter;
        GtkTreePath *path;

        GdkPixbuf *new_icon;
        IconType icon_type;

        icons_model = gtk_combo_box_get_model(icon_type_combo_box);
        if (gtk_combo_box_get_active_iter(icon_type_combo_box,
                                          &icons_iter)) {
                
                gtk_tree_model_get(icons_model, &icons_iter,
                                   0, &new_icon,
                                   -1);
                                                  
                icon_type = gtk_combo_box_get_active(icon_type_combo_box);
                gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
                                                &model,
                                                &iter);

                path = gtk_tree_model_get_path(model, &iter);
                gtk_tree_store_set(config_dialog->sensors_applet->sensors,
                                   &iter,
                                   ICON_TYPE_COLUMN, icon_type,
                                   ICON_PIXBUF_COLUMN, new_icon,
                                   -1);
                g_object_unref(new_icon);
                sensors_applet_icon_changed(config_dialog->sensors_applet, path);
                gtk_tree_path_free(path);
        }
}

static void sensor_config_dialog_graph_color_set(GtkColorButton *color_button,
                                                 SensorConfigDialog *config_dialog) {
	GtkTreeModel *model;
	GtkTreePath *path;
	GtkTreeIter iter;
	GdkColor color;
        gchar *color_string;

        gtk_color_button_get_color(color_button,
                                   &color);

        color_string = g_strdup_printf("#%02X%02X%02X", color.red / 256, 
                                       color.green / 256, color.blue / 256);

        gtk_tree_selection_get_selected(config_dialog->sensors_applet->selection,
					&model,
					&iter);

        gtk_tree_store_set(config_dialog->sensors_applet->sensors,
			   &iter,
			   GRAPH_COLOR_COLUMN, color_string,
			   -1);

	g_free(color_string);

	path = gtk_tree_model_get_path(GTK_TREE_MODEL(config_dialog->sensors_applet->sensors),
				       &iter);
	sensors_applet_update_sensor(config_dialog->sensors_applet, path);
	gtk_tree_path_free(path);
}

void sensor_config_dialog_create(SensorsApplet *sensors_applet) {
	GtkTreeModel *model;
	GtkTreeIter iter;

        SensorConfigDialog *config_dialog;

        GtkListStore *icon_store;
        IconType count;
        GdkPixbuf *pixbuf;

        GdkColor graph_color;        
        gchar *sensor_label;
        gchar *header_text;
        
	/* instance variables for data */
	gdouble low_value, high_value, multiplier, offset;
	gboolean alarm_enable;
	gchar *low_alarm_command, *high_alarm_command;
	gint alarm_timeout;
        IconType icon_type;
        gchar *graph_color_string;

        config_dialog = g_new0(SensorConfigDialog, 1);
        config_dialog->sensors_applet = sensors_applet;

	gtk_tree_selection_get_selected(sensors_applet->selection,
					&model,
					&iter);
	/* get current values of alarm and its enable */
	gtk_tree_model_get(model, &iter,
			   LOW_VALUE_COLUMN, &low_value,
			   HIGH_VALUE_COLUMN, &high_value,
			   ALARM_ENABLE_COLUMN, &alarm_enable,
			   LOW_ALARM_COMMAND_COLUMN, &low_alarm_command,
                           HIGH_ALARM_COMMAND_COLUMN, &high_alarm_command,
			   ALARM_TIMEOUT_COLUMN, &alarm_timeout,
			   MULTIPLIER_COLUMN, &multiplier,
			   OFFSET_COLUMN, &offset,
                           ICON_TYPE_COLUMN, &icon_type,
                           GRAPH_COLOR_COLUMN, &graph_color_string,
                           LABEL_COLUMN, &sensor_label,
			   -1);
        header_text = g_strdup_printf("%s - %s", _("Sensor Properties"), sensor_label);

	config_dialog->dialog = gtk_dialog_new_with_buttons(header_text,
                                                            GTK_WINDOW(sensors_applet->prefs_dialog->dialog),
                                                            GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
                                                            GTK_STOCK_HELP,
                                                            GTK_RESPONSE_HELP,
                                                            GTK_STOCK_CLOSE,
                                                            GTK_RESPONSE_CLOSE,
                                                            NULL);
        
        g_free(header_text);
        g_free(sensor_label);

	g_object_set(config_dialog->dialog,
		     "border-width", 12,
		     NULL);
	
	g_signal_connect(config_dialog->dialog,
                         "response",
                         G_CALLBACK(sensor_config_dialog_response),
                         config_dialog);
	
	
        /* graph stuff */
        header_text = g_markup_printf_escaped("<b>%s</b>", _("Graph"));
        config_dialog->graph_header = g_object_new(GTK_TYPE_LABEL,
                                   "use-markup", TRUE,
                                   "label", header_text,
                                   "xalign", 0.0,
                                   NULL);
        g_free(header_text);


        gdk_color_parse(graph_color_string,
                        &graph_color);
        
        config_dialog->graph_color_button = GTK_COLOR_BUTTON(gtk_color_button_new_with_color(&graph_color));
	config_dialog->graph_color_button_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
                                                  "child", config_dialog->graph_color_button,
                                                   "xalign", 0.0,
                                                   "xscale", 0.0,
                                                   NULL);

        gtk_color_button_set_title(config_dialog->graph_color_button, _("Graph Color"));
        
        config_dialog->graph_color_label = g_object_new(GTK_TYPE_LABEL,
                                         "label", _("Graph _color"),
					"mnemonic-widget", config_dialog->graph_color_button,
					"use-underline", TRUE,
					"xalign", 0.0,
					NULL);

	g_signal_connect(config_dialog->graph_color_button, "color-set", 
                         G_CALLBACK(sensor_config_dialog_graph_color_set), 
                         config_dialog);

        /* icon stuff */
        header_text = g_markup_printf_escaped("<b>%s</b>", _("Icon"));
        config_dialog->icon_header = g_object_new(GTK_TYPE_LABEL,
                                   "use-markup", TRUE,
                                   "label", header_text,
                                   "xalign", 0.0,
                                   NULL);
        g_free(header_text);

        /* icon type */
        icon_store = gtk_list_store_new(1, GDK_TYPE_PIXBUF);

        /* populate list with icons */
        for (count = CPU_ICON; count < NUM_ICONS; count++) {
                pixbuf = sensors_applet_load_icon(count);
                if (pixbuf) {
                        gtk_list_store_insert(icon_store, &iter, count);
                        gtk_list_store_set(icon_store, &iter,
                                           0, pixbuf,
                                           -1);
                        /* let list hold icons */
                        g_object_unref(pixbuf);
                }
        }
        
        config_dialog->icon_type_combo_box = GTK_COMBO_BOX(gtk_combo_box_new_with_model(GTK_TREE_MODEL(icon_store)));

	config_dialog->icon_type_combo_box_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
                                                   "child", config_dialog->icon_type_combo_box,
                                                   "xalign", 0.0,
                                                   "xscale", 0.0,
                                                   NULL);

        config_dialog->icon_renderer = gtk_cell_renderer_pixbuf_new();
        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(config_dialog->icon_type_combo_box),
                                   GTK_CELL_RENDERER(config_dialog->icon_renderer),
                                   FALSE);

        gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(config_dialog->icon_type_combo_box),
                                      GTK_CELL_RENDERER(config_dialog->icon_renderer),
                                      "pixbuf", 0);

        gtk_combo_box_set_active(config_dialog->icon_type_combo_box,
                                 icon_type);

	g_signal_connect(config_dialog->icon_type_combo_box, "changed", 
                         G_CALLBACK(sensor_config_dialog_icon_type_changed), 
                         config_dialog);


        
        config_dialog->icon_type_label = g_object_new(GTK_TYPE_LABEL,
 					"label", _("Sensor _icon"),
					"mnemonic-widget", config_dialog->icon_type_combo_box,
					"use-underline", TRUE,
					"xalign", 0.0,
					NULL);

        header_text = g_markup_printf_escaped("<b>%s</b>", _("Scaling Parameters"));
        config_dialog->scale_header = g_object_new(GTK_TYPE_LABEL,
                                   "use-markup", TRUE,
                                   "label", header_text,
                                   "xalign", 0.0,
                                   NULL);
        g_free(header_text);

	/* do multiplier and offset widgets */
	config_dialog->multiplier_adjust = g_object_new(GTK_TYPE_ADJUSTMENT,
			      "value", 1.0,
			      "lower", 0.001,
			      "upper", 1000.0,
			      "step-increment", 0.1,
			      "page-increment", 1.0,
			      "page-size", 1.0,
			      NULL);

	
	config_dialog->multiplier_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON,
					     "adjustment", config_dialog->multiplier_adjust,
					     "digits", VALUE_DECIMAL_PLACES,
					     "value", multiplier,
					     "width-chars", SPINBUTTON_WIDTH_CHARS,
					     NULL);

	config_dialog->multiplier_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
						     "child", config_dialog->multiplier_spinbutton,
						     "xalign", 0.0,
						     "xscale", 0.0,
						     NULL);

	config_dialog->multiplier_label = g_object_new(GTK_TYPE_LABEL,
                                                       "label", _("Sensor value _multiplier"),
                                                       "mnemonic-widget", config_dialog->multiplier_spinbutton,
                                                       "use-underline", TRUE,
                                                       "xalign", 0.0,
                                                       NULL);
	
	
	g_signal_connect(config_dialog->multiplier_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_multiplier_changed), config_dialog);
	

	config_dialog->offset_adjust = g_object_new(GTK_TYPE_ADJUSTMENT,
				     "value", 0.0,
				     "lower", -1000.000,
				     "upper", 1000.000,
				     "step-increment", 0.01,
				     "page-increment", 1.0,
				     "page-size", 1.0,
				     NULL);

	config_dialog->offset_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON,
					 "adjustment", config_dialog->offset_adjust,
					 "digits", VALUE_DECIMAL_PLACES,
					 "value", (gdouble)offset,
					 "width-chars", SPINBUTTON_WIDTH_CHARS,
					 NULL);
	
	config_dialog->offset_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
						 "child", config_dialog->offset_spinbutton,
						 "xalign", 0.0,
						 "xscale", 0.0,
						 NULL);

	config_dialog->offset_label = g_object_new(GTK_TYPE_LABEL,
				    "label", _("Sensor value _offset"),
				    "mnemonic-widget", config_dialog->offset_spinbutton,
				    "use-underline", TRUE,
				    "xalign", 0.0,
				    NULL);

	g_signal_connect(config_dialog->offset_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_offset_changed), config_dialog);


        /* now do alarm widgets */
        header_text = g_markup_printf_escaped("<b>%s</b>", _("Sensor Limits"));
        config_dialog->limits_header = g_object_new(GTK_TYPE_LABEL,
                                                    "use-markup", TRUE,
                                                    "label", header_text,
                                                    "xalign", 0.0,
                                                    NULL);
        g_free(header_text);

	config_dialog->low_value_adjust = g_object_new(GTK_TYPE_ADJUSTMENT,
                                        "value", 0.0,
                                        "lower", -100000.0,
                                        "upper", 100000.0,
                                        "step-increment", 1.0,
                                        "page-increment", 10.0,
                                        "page-size", 100.0,
                                        NULL);

	
	config_dialog->low_value_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON,
                                                           "adjustment", config_dialog->low_value_adjust,
                                                           "digits", VALUE_DECIMAL_PLACES,
                                                           "value", low_value,
                                                           "width-chars", SPINBUTTON_WIDTH_CHARS,

					      NULL);
	
	config_dialog->low_value_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
					  "child", config_dialog->low_value_spinbutton,
					  "xalign", 0.0,
					  "xscale", 0.0,
					  NULL);

	config_dialog->low_value_label = g_object_new(GTK_TYPE_LABEL,
                                                      "label", _("Sensor _low value"),
                                                      "mnemonic-widget", config_dialog->low_value_spinbutton,
                                                      "use-underline", TRUE,
                                                      "xalign", 0.0,

					 NULL);

	
	g_signal_connect(config_dialog->low_value_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_low_value_changed), config_dialog);

	config_dialog->high_value_adjust = g_object_new(GTK_TYPE_ADJUSTMENT,
			      "value", 0.0,
			      "lower", -100000.0,
			      "upper", 100000.0,
			      "step-increment", 1.0,
			      "page-increment", 10.0,
			      "page-size", 100.0,
			      NULL);

	
	config_dialog->high_value_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON,
                                                            "adjustment", config_dialog->high_value_adjust,
                                                            "digits", VALUE_DECIMAL_PLACES,
                                                            "value", high_value,
                                                            "width-chars", SPINBUTTON_WIDTH_CHARS,

                                                            NULL);
	
	config_dialog->high_value_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
                                                                    "child", config_dialog->high_value_spinbutton,
                                                                    "xalign", 0.0,
                                                                    "xscale", 0.0,
                                                                    NULL);
        
	config_dialog->high_value_label = g_object_new(GTK_TYPE_LABEL,
                                                       "label", _("Sensor _high value"),
                                                       "mnemonic-widget", config_dialog->high_value_spinbutton,
                                                       "use-underline", TRUE,
                                                       "xalign", 0.0,

                                                       NULL);
        
	
	g_signal_connect(config_dialog->high_value_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_high_value_changed), config_dialog);
	

        header_text = g_markup_printf_escaped("<b>%s</b>", _("Alarm"));
        config_dialog->alarm_header = g_object_new(GTK_TYPE_LABEL,
                                   "use-markup", TRUE,
                                   "label", header_text,
                                   "xalign", 0.0,
                                   NULL);
        g_free(header_text);

	config_dialog->alarm_timeout_adjust = g_object_new(GTK_TYPE_ADJUSTMENT,
					    "value", 0.0,
					    "lower", 0.0,
					    "upper", 10000.0,
					    "step-increment", 1.0,
					    "page-increment", 10.0,
					    "page-size", 100.0,
					    NULL);

	config_dialog->alarm_timeout_spinbutton = g_object_new(GTK_TYPE_SPIN_BUTTON,
                                                               "adjustment", config_dialog->alarm_timeout_adjust,
                                                               "digits", 0,
                                                               "value", (gdouble)alarm_timeout,
                                                               "width-chars", SPINBUTTON_WIDTH_CHARS,
                                                               "sensitive", alarm_enable,

						NULL);
	config_dialog->alarm_timeout_spinbutton_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
							"child", config_dialog->alarm_timeout_spinbutton,
							"xalign", 0.0,
							"xscale", 0.0,
							NULL);
	
	config_dialog->alarm_timeout_label = g_object_new(GTK_TYPE_LABEL,
                                                          "label", _("Alarm _repeat interval (secs)"),
                                                          "mnemonic-widget", config_dialog->alarm_timeout_spinbutton,
                                                          
                                                          "use-underline", TRUE,
                                                          "xalign", 0.0,
                                                          "sensitive", alarm_enable,
                                                          NULL);

	g_signal_connect(config_dialog->alarm_timeout_spinbutton, "value-changed", G_CALLBACK(sensor_config_dialog_alarm_timeout_changed), config_dialog);

	config_dialog->low_alarm_command_entry = g_object_new(GTK_TYPE_ENTRY,
                                                              "text", low_alarm_command,
                                                              "width-chars", 25,
                                                              "sensitive", alarm_enable,
                                                              NULL);

	g_free(low_alarm_command);

	config_dialog->low_alarm_command_label = g_object_new(GTK_TYPE_LABEL,
                                                          "use-underline", TRUE,
                                                          "label", _("Lo_w alarm command"),
                                                          "mnemonic-widget", config_dialog->low_alarm_command_entry,
                                                          "xalign", 0.0,
                                                          "sensitive", alarm_enable,

                                                          NULL);

	g_signal_connect(config_dialog->low_alarm_command_entry,
			 "changed",
			 G_CALLBACK(sensor_config_dialog_low_alarm_command_edited),
			 config_dialog);

	config_dialog->high_alarm_command_entry = g_object_new(GTK_TYPE_ENTRY,
                                                              "text", high_alarm_command,
                                                              "width-chars", 25,
                                                              "sensitive", alarm_enable,
                                                              NULL);

	g_free(high_alarm_command);

	config_dialog->high_alarm_command_label = g_object_new(GTK_TYPE_LABEL,
                                                          "use-underline", TRUE,
                                                          "label", _("Hi_gh alarm command"),
                                                          "mnemonic-widget", config_dialog->high_alarm_command_entry,
                                                          "xalign", 0.0,
                                                          "sensitive", alarm_enable,

                                                          NULL);

	g_signal_connect(config_dialog->high_alarm_command_entry,
			 "changed",
			 G_CALLBACK(sensor_config_dialog_high_alarm_command_edited),
			 config_dialog);

	config_dialog->alarm_enable_checkbutton = g_object_new(GTK_TYPE_CHECK_BUTTON,
						"use-underline", TRUE,
						"label", _("_Enable alarm"),
						"active", alarm_enable,
						"xalign", 0.0,
						NULL);
	
	config_dialog->alarm_enable_aligner = g_object_new(GTK_TYPE_ALIGNMENT,
					    "child", config_dialog->alarm_enable_checkbutton,
					    "xalign", 0.0,
					    "xscale", 0.0,
					    NULL);

	g_signal_connect(config_dialog->alarm_enable_checkbutton, "toggled", G_CALLBACK(sensor_config_dialog_alarm_toggled), config_dialog);
	


        config_dialog->size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->multiplier_spinbutton));
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->offset_spinbutton));
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->low_value_spinbutton));
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->high_value_spinbutton));
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->alarm_timeout_spinbutton));
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->icon_type_combo_box));
        gtk_size_group_add_widget(config_dialog->size_group,
                                  GTK_WIDGET(config_dialog->graph_color_button));
        g_object_unref(config_dialog->size_group);

	config_dialog->table = g_object_new(GTK_TYPE_TABLE,
			     "column-spacing", 5,
			     "homogeneous", FALSE,
			     "n-columns", 3,
			     "n-rows", 15,
                             "row-spacing", 6,
                             "column-spacing", 12,
			     NULL);


        gtk_table_attach_defaults(config_dialog->table,
                                  GTK_WIDGET(config_dialog->scale_header),
                                  0, 2,
                                  0, 1);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->multiplier_label),
				  1, 2,
				  1, 2);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->multiplier_spinbutton_aligner),
				  2, 3,
				  1, 2);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->offset_label),
				  1, 2,
				  2, 3);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->offset_spinbutton_aligner),
				  2, 3,
				  2, 3);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->limits_header),
				  0, 2,
				  3, 4);

	/* now pack alarm widgets */
        gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->low_value_label),
				  1, 2,
				  4, 5);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->low_value_spinbutton_aligner),
				  2, 3,
				  4, 5);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->high_value_label),
				  1, 2,
				  5, 6);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->high_value_spinbutton_aligner),
				  2, 3,
				  5, 6);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->alarm_header),
				  0, 2,
				  6, 7);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->alarm_enable_aligner),
				  1, 2,
				  7, 8);	

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->alarm_timeout_label),
				  1, 2,
				  8, 9);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->alarm_timeout_spinbutton_aligner),
				  2, 3,
				  8, 9);
	
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->low_alarm_command_label),
				  1, 2,
				  9, 10);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->low_alarm_command_entry),
				  2, 3,
				  9, 10);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->high_alarm_command_label),
				  1, 2,
				  10, 11);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->high_alarm_command_entry),
				  2, 3,
				  10, 11);

        gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->icon_header),
				  0, 2,
				  11, 12);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->icon_type_label),
				  1, 2,
				  12, 13);
	
        gtk_table_attach_defaults(config_dialog->table,
                                  GTK_WIDGET(config_dialog->icon_type_combo_box_aligner),
                                  2, 3,
                                  12, 13);
        
	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->graph_header),
				  0, 2,
				  13, 14);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->graph_color_label),
				  1, 2,
				  14, 15);

	gtk_table_attach_defaults(config_dialog->table,
				  GTK_WIDGET(config_dialog->graph_color_button_aligner),
				  2, 3,
				  14, 15);

	gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(config_dialog->dialog)->vbox), GTK_WIDGET(config_dialog->table));
	gtk_widget_show_all(config_dialog->dialog);

}