/* GAdmin-Rsync - An easy to use GTK+ frontend for the rsync backup client and server.
 * Copyright (C) 2007-2011 Magnus Loef <magnus-swe@telia.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 3 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/



#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "widgets.h"
#include "gettext.h"
#include "create_rsync_tab.h"
#include "populate_rsync_tab.h"
#include "show_info.h"
#include "make_settings_checkbuttons.h"
#include "make_settings_spinbuttons.h"
#include "make_settings_entries.h"
#include "make_settings_combos.h"
#include "make_settings_labels.h"
#include "make_settings_hseparators.h"
#include "save_backup_settings.h"
#include "commands.h"
#include "cron_functions.h"
#include "backup_menu.h"
#include "show_log.h"


#define EXPAND_USER_SECTION FALSE
#define EXPAND_USER_SETTINGS_SECTION TRUE

extern gchar *global_settings_dir;
extern gchar *global_backup_name;

/* Used to see if the backup combo changed */
extern gulong backup_combo_changed_signal;


/* Change cell text in a treeview */
void cell_edited(GtkCellRendererText *cell,
		        gchar *path_string,
			   gchar *new_text,
			  struct w *widgets)
{
    GtkTreeIter iter;
    GtkTreePath *path=NULL;

    int column = (int) g_object_get_data(G_OBJECT(cell), "column");

    path = gtk_tree_path_new_from_string(path_string);

    gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->backup_store), &iter, path);

    if( path!=NULL )
      gtk_tree_path_free(path);

    gtk_list_store_set(GTK_LIST_STORE(widgets->backup_store), &iter, column, new_text, -1);
}


/* Change cell toggle value in a treeview */
void treeview_toggle_button_clicked(GtkCellRendererToggle *cell_renderer, gchar *path, struct w *widgets)
{
    GtkTreePath *treepath;
    GtkTreeIter iter;
    gboolean val;
    treepath = gtk_tree_path_new_from_string(path);
    GtkTreeModel *model;
    int col_num;
    
    col_num = (int) g_object_get_data(G_OBJECT(cell_renderer), "column");
    
    gtk_tree_model_get_iter(GTK_TREE_MODEL(widgets->backup_store), &iter, treepath);
    model = gtk_tree_view_get_model(GTK_TREE_VIEW(widgets->backup_treeview));

    /* Toggle it to the opposite checked state */
    gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, col_num, &val, -1);
    if( val )
	gtk_list_store_set(widgets->backup_store, &iter, col_num, FALSE, -1);
    else
	gtk_list_store_set(widgets->backup_store, &iter, col_num, TRUE, -1);

    gtk_tree_path_free(treepath);
}


/* Deletes the selected row from the treeview */
void del_treeview_row(struct w *widgets)
{
    GtkTreeSelection *selection;
    GtkTreeModel *model;
    GtkTreeIter iter;
    gboolean val, edit=0;
    GtkTreePath *path;

    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widgets->backup_treeview));
    if( selection )
    {
	val = gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selection), &model, &iter);

	if( gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), &iter) )
	  gtk_list_store_remove(widgets->backup_store, &iter);

	path = gtk_tree_path_new_first();

	if( path )
	  gtk_tree_view_set_cursor(GTK_TREE_VIEW(widgets->backup_treeview), path, NULL, edit);

	gtk_tree_path_free(path);
    }
}


/* New backup name selected */
void backup_name_combo_changed(struct w *widgets)
{
    int i = 0;

    /* Clear schedule days combo boxes */
    for(i=0; i<8; i++)
      gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->schedule_check_button[i]), FALSE);

    /* Clear schedule time combo box */
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widgets->schedule_check_button[8]), FALSE);

    /* Set schedule spinbuttons to default time */
    for(i=0; i<2; i++)
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(widgets->schedule_spin_button[i]), 1);


    populate_rsync_tab(widgets);
}


/* Creates a new backup (settings file) and selects it.
   Then shows the create_backup_menu() backup type selection */
void create_new_backup(struct w *widgets)
{
    FILE *fp;
    int i = 0;
    gchar *info, *utf8, *conf_file;

    G_CONST_RETURN gchar *backup_name = gtk_entry_get_text(GTK_ENTRY(widgets->new_backup_entry));
    if( backup_name == NULL || strlen(backup_name) < 3 )
    {
        info = g_strdup_printf(_("The backup name is too short.\n"));
        show_info(info);
        g_free(info);
	return;
    }

    /* Fixme: Some chars cannot be used in the backup name. */
    for(i=0; backup_name[i]!='\0'; i++)
    {
	if( backup_name[i]=='/'  || backup_name[i]=='\r'
	||  backup_name[i]=='\n' || backup_name[i]=='\t' )
	{
    	    info = g_strdup_printf(_("The backup name contains special chars that cannot be used.\n"));
    	    show_info(info);
    	    g_free(info);
	    return;	
	}
    
    }

    /* Create a new backup settings file */
    conf_file = g_strdup_printf("%s/%s", global_settings_dir, backup_name);

    /* If the backup exists, tell the user and return */
    if( file_exists(conf_file) )
    {
        info = g_strdup_printf(_("A backup with this name already exists.\nChoose another backup name and try again.\n"));
        show_info(info);
        g_free(info);
        g_free(conf_file);
	return;
    }

    /* Write the new settings file */
    if((fp=fopen(conf_file, "w+"))==NULL)
    {
        info = g_strdup_printf(_("Error: Can not write backup settings here:\n%s\n"), conf_file);
        show_info(info);
        g_free(info);
        g_free(conf_file);
        return;
    }
    fclose(fp);
    g_free(conf_file);

    /* Switch to this backup name */
    global_backup_name = g_strdup_printf("%s", backup_name);

    /* Put this new backup name first in the combo and select it */
    utf8 = g_locale_to_utf8(backup_name, strlen(backup_name), NULL, NULL, NULL);
    gtk_combo_box_prepend_text(GTK_COMBO_BOX(widgets->rsync_set_combo[0]), utf8);
    gtk_combo_box_set_active(GTK_COMBO_BOX(widgets->rsync_set_combo[0]), 0);
    if( utf8!=NULL )
      g_free(utf8);

    populate_rsync_tab(widgets);

    gtk_widget_destroy(widgets->new_backup_window);

    /* Show backup type menu selection */    
    show_backup_menu(widgets);
}


/* Deletes the selected backup, schedule and logs then repopulates the gui */
void delete_backup(struct w *widgets)
{
    gchar *info, *conf_file, *script_file, *log_file;

    conf_file = g_strdup_printf("%s/%s", global_settings_dir, global_backup_name);

    if( global_backup_name == NULL || strlen(global_backup_name) < 1 )
    {
        info = g_strdup_printf(_("Backup name too short, backup not deleted\n"));
        show_info(info);
        g_free(info);
        g_free(conf_file);
        return;
    }

    /* Delete the settings file */
    if( conf_file!=NULL )
    {
	unlink(conf_file);
	g_free(conf_file);
    }

    /* Delete the schedule script if any */
    script_file = mk_backup_script_path(global_backup_name);
    if( script_file!=NULL && strstr(script_file, "gadmin-rsync") )
      unlink(script_file);

    /* Delete the cron line if any */
    if( script_file!=NULL && strstr(script_file, "gadmin-rsync") )
      del_cron(script_file);

    if( script_file!=NULL )
      g_free(script_file);

    /* Delete backup at shutdown link if any */
    script_file = mk_backup_at_shutdown_script_path(global_backup_name);
    remove_from_system_shutdown(global_backup_name);
    if( script_file!=NULL )
      g_free(script_file);

    /* Delete the log file if any */
    log_file = mk_log_path(global_backup_name);
    if( log_file!=NULL && strstr(log_file, "gadmin-rsync") )
      unlink(log_file);

    if( log_file!=NULL )
      g_free(log_file);

    /* Delete the extended log file if any */
    log_file = mk_extended_log_path(global_backup_name);
    if( log_file!=NULL && strstr(log_file, "gadmin-rsync") )
      unlink(log_file);

    if( log_file!=NULL )
      g_free(log_file);

    /* Clear the "backup name" combo. Block its signal first. */
    g_signal_handler_block(GTK_WIDGET(widgets->rsync_set_combo[0]), backup_combo_changed_signal);

    GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(widgets->rsync_set_combo[0]));
    gtk_list_store_clear(GTK_LIST_STORE(model));

    /* Unblock its signal */
    g_signal_handler_unblock(GTK_WIDGET(widgets->rsync_set_combo[0]), backup_combo_changed_signal);

    /* Delete the logs */

    populate_rsync_tab(widgets);
}


/* Shows a window with a backup name entry */
void create_new_backup_window(struct w *widgets)
{
    GtkWidget *vbox;
    gchar *info;

    /* Create the new backup window */
    widgets->new_backup_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(widgets->new_backup_window), GTK_WIN_POS_CENTER);
    gtk_widget_set_size_request(widgets->new_backup_window, 600, 200);
    /* Set window information */
    info = g_strdup_printf("Gadmin-Rsync %s - Create new backup", VERSION);
    gtk_window_set_title(GTK_WINDOW(widgets->new_backup_window), info);
    g_free(info);

    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(widgets->new_backup_window), vbox);

    /* Backup name entry inside a table and frame */
    GtkWidget *frame = gtk_frame_new(_("New Backup settings:"));
    GtkWidget *table = gtk_table_new(1, 2, FALSE);
    gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 1);
    gtk_container_add(GTK_CONTAINER(frame), table);

    widgets->new_backup_entry = make_entry_with_label(GTK_TABLE(table), _(" The name of the new backup: "), 0,1,0,1, 300);

    /* Apply and cancel buttons */
    GtkWidget *hbuttonbox = gtk_hbutton_box_new();
    gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_SPREAD);

    GtkWidget *cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
    gtk_container_add(GTK_CONTAINER(hbuttonbox), cancel_button);
    g_signal_connect_swapped(G_OBJECT(cancel_button), "clicked", 
             G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(widgets->new_backup_window));

    GtkWidget *apply_button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
    gtk_container_add(GTK_CONTAINER(hbuttonbox), apply_button);
    g_signal_connect_swapped(G_OBJECT(apply_button), "clicked", 
                               G_CALLBACK(create_new_backup), widgets);

    gtk_widget_show_all(widgets->new_backup_window);
}


void create_rsync_tab(struct w *widgets)
{
    GtkWidget *user_settings_treeview_hbox;
    GtkWidget *directory_scrolled_window;
    GtkCellRenderer *src_cell_renderer, *dst_cell_renderer;
    GtkCellRenderer *src_host_cell_renderer, *dst_host_cell_renderer;
    GtkCellRenderer *include_cell_renderer, *exclude_cell_renderer;
    GtkCellRenderer *incl_backup_cell_renderer, *delete_dest_cell_renderer;
    GtkCellRenderer *user_cell_renderer, *port_cell_renderer, *priv_key_path_cell_renderer;
    GtkTreeViewColumn *col[11];
    int colnr=0;
    int a=0, b=1;
    GtkWidget *frame;
    gchar *utf8=NULL;
    GtkTooltips *tooltips;
    tooltips = gtk_tooltips_new();

    /* Create the scrolled window with a frame and a table */
    user_settings_treeview_hbox = gtk_hbox_new(TRUE, 0);
    gtk_box_pack_start(GTK_BOX(widgets->notebook_vbox1), user_settings_treeview_hbox, EXPAND_USER_SETTINGS_SECTION, TRUE, 0);

    widgets->user_settings_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
    gtk_box_pack_start(GTK_BOX(user_settings_treeview_hbox), widgets->user_settings_scrolled_window, TRUE, TRUE, 0);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widgets->user_settings_scrolled_window), 
						    GTK_POLICY_NEVER, 
						    GTK_POLICY_ALWAYS);
    /* Must set a larger size or it wont scroll */
    gtk_widget_set_size_request(widgets->user_settings_scrolled_window, -1, 100);

    /* The main vbox */
    widgets->user_settings_vbox = gtk_vbox_new(FALSE, 0);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(widgets->user_settings_scrolled_window), widgets->user_settings_vbox);

    /* Create the directory treeview in the user settings scrolled window */
    directory_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_box_pack_start(GTK_BOX(widgets->user_settings_vbox), directory_scrolled_window, FALSE, FALSE, 0);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(directory_scrolled_window), 
						    GTK_POLICY_AUTOMATIC, 
						    GTK_POLICY_ALWAYS);
    /* Must set a larger size or it wont scroll */
    gtk_widget_set_size_request(directory_scrolled_window, -1, 120);

    /* 11 columns */
    widgets->backup_store = gtk_list_store_new(11, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
						   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
						   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING,
						   G_TYPE_STRING, G_TYPE_STRING);

    widgets->backup_treeview = gtk_tree_view_new();
    gtk_tree_view_set_model(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_MODEL(widgets->backup_store));

    gtk_container_add(GTK_CONTAINER(directory_scrolled_window), widgets->backup_treeview);
    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(widgets->backup_treeview), TRUE);


    /* A hbuttonbox below the treeview */
    GtkWidget *hbuttonbox1;
    hbuttonbox1 = gtk_hbutton_box_new();
    gtk_box_pack_start(GTK_BOX(widgets->user_settings_vbox), hbuttonbox1, FALSE, FALSE, 0);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox1), GTK_BUTTONBOX_SPREAD);

    /* Add backup data button */
    GtkWidget *add_backup_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, add_backup_button, _("Add data to this backup."), NULL);
    GtkWidget *alignment62 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(add_backup_button), alignment62);
    GtkWidget *hbox60 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment62), hbox60);
    GtkWidget *image52 = gtk_image_new_from_stock("gtk-add", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox60), image52, FALSE, FALSE, 0);
    GtkWidget *label230 = gtk_label_new_with_mnemonic(_("Add backup data"));
    gtk_box_pack_start(GTK_BOX(hbox60), label230, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label230), GTK_JUSTIFY_LEFT);
    /* The add file or directory signal hookup */
    g_signal_connect_swapped(add_backup_button, "clicked",
                    	     G_CALLBACK(show_backup_menu), widgets);
    gtk_box_pack_start(GTK_BOX(hbuttonbox1), add_backup_button, TRUE, TRUE, 0);


    /* Remove data selection button */
    GtkWidget *del_backup_row_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, del_backup_row_button, _("Remove selection from backup."), NULL);
    GtkWidget *alignment64 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(del_backup_row_button), alignment64);
    GtkWidget *hbox64 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment64), hbox64);
    GtkWidget *image56 = gtk_image_new_from_stock("gtk-delete", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox64), image56, FALSE, FALSE, 0);
    GtkWidget *label234 = gtk_label_new_with_mnemonic(_("Remove selected data"));
    gtk_box_pack_start(GTK_BOX(hbox64), label234, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label234), GTK_JUSTIFY_LEFT);
    /* Remove data selection signal hookup */
    g_signal_connect_swapped(del_backup_row_button, "clicked",
                    	     G_CALLBACK(del_treeview_row), widgets);
    gtk_box_pack_start(GTK_BOX(hbuttonbox1), del_backup_row_button, TRUE, TRUE, 0);


    /* Setup the treeview cells to be editable or clickable */
    src_host_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(src_host_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(src_host_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    src_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(src_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(src_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    dst_host_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(dst_host_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(dst_host_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    dst_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(dst_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(dst_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    include_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(include_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(include_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    exclude_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(exclude_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(exclude_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    incl_backup_cell_renderer = gtk_cell_renderer_toggle_new();
    g_object_set(incl_backup_cell_renderer, "activatable", TRUE, NULL);
    g_signal_connect(incl_backup_cell_renderer, "toggled",  
		      G_CALLBACK(treeview_toggle_button_clicked), widgets);

    delete_dest_cell_renderer = gtk_cell_renderer_toggle_new();
    g_object_set(delete_dest_cell_renderer, "activatable", TRUE, NULL);
    g_signal_connect(delete_dest_cell_renderer, "toggled",  
		      G_CALLBACK(treeview_toggle_button_clicked), widgets);

    user_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(user_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(user_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    port_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(port_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(port_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);

    priv_key_path_cell_renderer = gtk_cell_renderer_text_new();
    g_object_set(priv_key_path_cell_renderer, "editable", TRUE, NULL);
    g_signal_connect(priv_key_path_cell_renderer, "edited",  
		      G_CALLBACK(cell_edited), widgets);


    colnr  = 0;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Source server"), src_host_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Source directory or file"), src_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Destination server"), dst_host_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Destination directory or file"), dst_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Include pattern"), include_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Exclude pattern"), exclude_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Include in backup"), incl_backup_cell_renderer, "active", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Delete destination files that does not exist in source"), delete_dest_cell_renderer, "active", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Remote username"), user_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Remote port"), port_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;

    col[colnr] = gtk_tree_view_column_new_with_attributes(_("Private key for remote server"), priv_key_path_cell_renderer, "text", colnr, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(widgets->backup_treeview), GTK_TREE_VIEW_COLUMN(col[colnr]));
    colnr++;


    g_object_set_data(G_OBJECT(src_host_cell_renderer), "column", (void*)(0));
    g_object_set_data(G_OBJECT(src_cell_renderer), "column", (void*)(1));
    g_object_set_data(G_OBJECT(dst_host_cell_renderer), "column", (void*)(2));
    g_object_set_data(G_OBJECT(dst_cell_renderer), "column", (void*)(3));
    g_object_set_data(G_OBJECT(include_cell_renderer), "column", (void*)(4));
    g_object_set_data(G_OBJECT(exclude_cell_renderer), "column", (void*)(5));
    /* 6 and 7 is for the togglebuttons */
    g_object_set_data(G_OBJECT(incl_backup_cell_renderer), "column", (void*)(6));
    g_object_set_data(G_OBJECT(delete_dest_cell_renderer), "column", (void*)(7));

    g_object_set_data(G_OBJECT(user_cell_renderer), "column", (void*)(8));
    g_object_set_data(G_OBJECT(port_cell_renderer), "column", (void*)(9));
    g_object_set_data(G_OBJECT(priv_key_path_cell_renderer), "column", (void*)(10));


    /* Add a settings frame in a table */
    frame = gtk_frame_new("");

    /* A table with NUM settings and 2 columns FIXME, Count */
    widgets->usr_set_table = gtk_table_new(NUM_USERTAB_ENTRIES+NUM_USERTAB_SPINBUTTONS+NUM_USERTAB_CHECKBUTTONS+NUM_USERTAB_COMBOS, 2, FALSE);
    gtk_box_pack_start(GTK_BOX(widgets->user_settings_vbox), frame, TRUE, TRUE, 1);
    gtk_container_add(GTK_CONTAINER(frame), widgets->usr_set_table);

    /* Spacer label */
    make_3columns_label(GTK_TABLE(widgets->usr_set_table), "", 0, 1, a, b);
    a++; b++;


    /* The settings... */

    /* "Delete selected backup" button */
    GtkWidget *del_backup_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, del_backup_button, _("Delete the selected backup."), NULL);
    GtkWidget *alignment40 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(del_backup_button), alignment40);
    GtkWidget *hbox40 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment40), hbox40);
    GtkWidget *image21 = gtk_image_new_from_stock("gtk-delete", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox40), image21, FALSE, FALSE, 0);
    GtkWidget *label221 = gtk_label_new_with_mnemonic(_("Delete selected backup"));
    gtk_box_pack_start(GTK_BOX(hbox40), label221, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label221), GTK_JUSTIFY_LEFT);

    /* Delete selected backup signal hookup */
    g_signal_connect_swapped(del_backup_button, "clicked",
            	        G_CALLBACK(delete_backup), widgets);

    /* Selected backup combo */
    utf8 = g_locale_to_utf8(_(" Selected backup: "), -1, NULL, NULL, NULL);
    widgets->rsync_set_combo[0] = make_label_combo_button(GTK_TABLE(widgets->usr_set_table), del_backup_button, utf8, 0,1,a,b, 350);

    /* Callback for combo changed. */
    backup_combo_changed_signal = g_signal_connect_swapped(widgets->rsync_set_combo[0], "changed",
    		    				    G_CALLBACK(backup_name_combo_changed), widgets);

    a++; b++;


    /* Spacer label */
    make_3columns_label(GTK_TABLE(widgets->usr_set_table), "", 0, 1, a, b);
    a++; b++;

    GtkWidget *hbuttonbox2;
    hbuttonbox2 = gtk_hbutton_box_new();
    gtk_table_attach(GTK_TABLE(widgets->usr_set_table), hbuttonbox2, 0, 3, a, b, FALSE, FALSE, 2, 2);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox2), GTK_BUTTONBOX_SPREAD);

    /* "Create new backup" button */
    GtkWidget *create_new_backup_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, create_new_backup_button, _("Create a new backup."), NULL);
    GtkWidget *alignment52 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(create_new_backup_button), alignment52);
    GtkWidget *hbox50 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment52), hbox50);
    GtkWidget *image51 = gtk_image_new_from_stock("gtk-add", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox50), image51, FALSE, FALSE, 0);

    GtkWidget *label220 = gtk_label_new_with_mnemonic(_("Create new backup"));
    gtk_box_pack_start(GTK_BOX(hbox50), label220, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label220), GTK_JUSTIFY_LEFT);
    gtk_box_pack_start(GTK_BOX(hbuttonbox2), create_new_backup_button, FALSE, FALSE, 0);
    /* The create new backup signal hookup */
    g_signal_connect_swapped(create_new_backup_button, "clicked",
                    	     G_CALLBACK(create_new_backup_window), widgets);


    /* Save backup button */
    GtkWidget *save_backup_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, save_backup_button, _("Save this backup."), NULL);
    GtkWidget *alignment68 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(save_backup_button), alignment68);
    GtkWidget *hbox68 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment68), hbox68);
    GtkWidget *image58 = gtk_image_new_from_stock("gtk-refresh", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox68), image58, FALSE, FALSE, 0);

    GtkWidget *label238 = gtk_label_new_with_mnemonic(_("Save backup"));
    gtk_box_pack_start(GTK_BOX(hbox68), label238, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label238), GTK_JUSTIFY_LEFT);
    gtk_box_pack_start(GTK_BOX(hbuttonbox2), save_backup_button, FALSE, FALSE, 0);
    /* Save backup button signal hookup */
    g_signal_connect_swapped(save_backup_button, "clicked",
                    	     G_CALLBACK(save_backup_settings), widgets);
    a++; b++;


    /* Show log button */
    GtkWidget *log_backup_button = gtk_button_new();
    gtk_tooltips_set_tip(tooltips, log_backup_button, _("Show log for the selected backup."), NULL);
    GtkWidget *alignment28 = gtk_alignment_new(0.5, 0.5, 0, 0);
    gtk_container_add(GTK_CONTAINER(log_backup_button), alignment28);
    GtkWidget *hbox28 = gtk_hbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(alignment28), hbox28);
    GtkWidget *image28 = gtk_image_new_from_stock("gtk-find", GTK_ICON_SIZE_BUTTON);
    gtk_box_pack_start(GTK_BOX(hbox28), image28, FALSE, FALSE, 0);

    GtkWidget *label28 = gtk_label_new_with_mnemonic(_("Show backup log"));
    gtk_box_pack_start(GTK_BOX(hbox28), label28, FALSE, FALSE, 0);
    gtk_label_set_justify(GTK_LABEL(label28), GTK_JUSTIFY_LEFT);
    gtk_box_pack_start(GTK_BOX(hbuttonbox2), log_backup_button, FALSE, FALSE, 0);
    /* Show log button signal hookup */
    g_signal_connect_swapped(log_backup_button, "clicked",
                    	     G_CALLBACK(show_log_window), widgets);
    a++; b++;

    /* Spacer label */
    make_3columns_label(GTK_TABLE(widgets->usr_set_table), "", 0, 1, a, b);
    a++; b++;

    /* CRON Time schedule settings */
    widgets->schedule_check_button[0] = make_3columns_label_spin(GTK_TABLE(widgets->usr_set_table),
    _("Schedule this backup to run at specific times: "), 0, 1, a, b);
    a++; b++;

    /* Hseparator */
    make_3columns_hseparator(GTK_TABLE(widgets->usr_set_table), 0, 1, a, b);
    a++; b++;

    /* Schedule (Month day = 1-31) */
    widgets->schedule_spin_button[0] = make_shortleft_spinbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
    _("Month day"), 0, 1, a, b, 20, 1, 31);

    gtk_tooltips_set_tip(tooltips, widgets->schedule_spin_button[0],
    _("The backup will run on the specified day of the month.\nUncheck any weekdays to have a monthly backup."), NULL);
    a++; b++;

    /* Any month day (*) */
    widgets->schedule_check_button[1] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
    _("Not monthly: "), 0, 1, a, b);

    gtk_tooltips_set_tip(tooltips, widgets->schedule_check_button[1],
    _("If selected, the backup will run on the specified days and times instead of once a month."), NULL);
    a++; b++;

    /* Hseparator */
    make_3columns_hseparator(GTK_TABLE(widgets->usr_set_table), 0, 1, a, b);
    a++; b++;

    /* Schedule days */
    widgets->schedule_check_button[2] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Monday: "), 0, 1, a, b);
    a++; b++;
    widgets->schedule_check_button[3] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Tuesday: "), 0, 1, a, b);
    a++; b++;
    widgets->schedule_check_button[4] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Wednesday: "), 0, 1, a, b);
    a++; b++;
    widgets->schedule_check_button[5] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Thursday: "), 0, 1, a, b);
    a++; b++;
    widgets->schedule_check_button[6] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Friday: "), 0, 1, a, b);
    a++; b++;
    widgets->schedule_check_button[7] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Saturday: "), 0, 1, a, b);
    a++; b++;
    widgets->schedule_check_button[8] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Sunday: "), 0, 1, a, b);
    a++; b++;

    /* Hseparator */
    make_3columns_hseparator(GTK_TABLE(widgets->usr_set_table), 0, 1, a, b);
    a++; b++;

    /* Schedule hour   (0-23) */
    widgets->schedule_spin_button[1] = make_shortleft_spinbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
    									     _("Hour"), 0, 1, a, b, 20, 0, 23);
    a++; b++;

    /* Every hour   (*) */
    widgets->schedule_check_button[9] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Every hour: "), 0, 1, a, b);
    a++; b++;

    /* Hseparator */
    make_3columns_hseparator(GTK_TABLE(widgets->usr_set_table), 0, 1, a, b);
    a++; b++;				

    /* Schedule minute (0-59) */
    widgets->schedule_spin_button[2] = make_shortleft_spinbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
									   _("Minute"), 0, 1, a, b, 20, 0, 59);
    a++; b++;

    /* Every minute (*) */
    widgets->schedule_check_button[10] = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Every minute: "), 0, 1, a, b);
    a++; b++;

    /* Hseparator */
    make_3columns_hseparator(GTK_TABLE(widgets->usr_set_table), 0, 1, a, b);
    a++; b++;


    /* Spacer label */
    make_3columns_label(GTK_TABLE(widgets->usr_set_table), "", 0, 1, a, b);
    a++; b++;

    /* Backup at shutdown [x] */
    widgets->backup_at_shutdown_check_button = make_checkbutton_with_label(GTK_TABLE(widgets->usr_set_table), 
                                                                            _("Backup at shutdown: "), 0, 1, a, b);
    a++; b++;


    /* Hseparator */
//    make_3columns_hseparator(GTK_TABLE(widgets->usr_set_table), 0, 1, a, b);
//    a++; b++;

    // Pre for dumping databases, post for cleaning up etc...
    // Pre command  ( Commands to run before the source is backed up. )
    // Post command ( Commands to run after the backup. )

    if( utf8!=NULL )
      g_free(utf8);

    gtk_widget_show_all(widgets->main_window);
}
