/* Data widgets linking/Same data
 *
 * Shows a form and a grid synchronized to display the same data and
 * optionally to have the same selected row.
 */

#include <libgnomedb/libgnomedb.h>

extern GdaDict *demo_dict;
static GtkWidget *window = NULL;

typedef struct {
	GdaDataModelIter *grid_iter;
	GdaDataModelIter *form_iter;
	gboolean          keep_sync;
} DemoData;

static void
restrict_default_served_by_field (GnomeDbDataWidget *data_widget, GdaDataModel *restrict_with, gint restrict_col)
{
	GdaDataModelIter *iter;
	GdaParameter *param;

	iter = gnome_db_data_widget_get_current_data (data_widget);
	param = gda_parameter_list_find_param (GDA_PARAMETER_LIST (iter), "SalesRep");

	g_assert (gda_parameter_restrict_values (param, restrict_with, restrict_col, NULL));
}

static void
iter_row_changed_cb (GdaDataModelIter *iter, gint row, DemoData *data)
{
        GdaDataModelIter *other;

        if (iter == data->grid_iter)
                other = data->form_iter;
        else
                other = data->grid_iter;

        if (data->keep_sync) {
		g_signal_handlers_block_by_func (other,
						 G_CALLBACK (iter_row_changed_cb),
						 data);
		gda_data_model_iter_set_at_row (other, row);
		g_signal_handlers_unblock_by_func (other,
						   G_CALLBACK (iter_row_changed_cb),
						   data);
		/* REM: other method would be to do:
                        GtkTreePath *path = gtk_tree_path_new_from_indices (row, -1);
                        gtk_tree_view_set_cursor (raw_grid, path, NULL, FALSE);
                        gtk_tree_path_free (path);
		*/
        }
}

static void
sync_selections_cb (GtkToggleButton *toggle, DemoData *data)
{
        data->keep_sync = gtk_toggle_button_get_active (toggle);
}

GtkWidget *
do_linked_grid_form (GtkWidget *do_widget)
{  
	if (!window) {
                GdaQuery *query;
		GtkWidget *vbox;
		GtkWidget *label;
		GtkWidget *cb;		
		GdaDataModel *cust_model, *sr_model;
		GtkWidget *form, *grid;
		GnomeDbRawGrid *raw_grid;
		GnomeDbRawForm *raw_form;
		GdaDataProxy *proxy;
		DemoData *data;

		data = g_new0 (DemoData, 1);
		
		window = gtk_dialog_new_with_buttons ("Linked grid and form on the same data",
						      GTK_WINDOW (do_widget),
						      0,
						      GTK_STOCK_CLOSE,
						      GTK_RESPONSE_NONE,
						      NULL);
		
		g_signal_connect (window, "response",
				  G_CALLBACK (gtk_widget_destroy), NULL);
		g_signal_connect (window, "destroy",
				  G_CALLBACK (gtk_widget_destroyed), &window);
		g_object_set_data_full (window, "demodata", data, g_free);
		
		vbox = gtk_vbox_new (FALSE, 5);
		gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
		gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
		
		label = gtk_label_new ("The following GnomeDbForm and GnomeDbGrid widgets\n"
				       "display data from the 'customers' and 'salesrep' tables.");
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
		
		/* create a data model for the customers */
                query = gda_query_new_from_sql (demo_dict, 
						"SELECT c.id, c.name, c.default_served_by as \"SalesRep\""
						"FROM customers c "
						"LEFT JOIN salesrep s ON (s.id=c.default_served_by)", NULL);
		cust_model = gda_data_model_query_new (query);
		g_object_unref (query);

		g_assert (gda_data_model_query_set_modification_query (GDA_DATA_MODEL_QUERY (cust_model),
								       "UPDATE customers set "
								       "id=##/*name:'+0' type:'gint'*/, "
								       "name=##/*name:'+1' type:gchararray*/, "
								       "default_served_by=##/*name:'+2' type:gint*/ "
								       "WHERE id=##/*name:'-0' type:gint*/", NULL));
		g_assert (gda_data_model_query_set_modification_query (GDA_DATA_MODEL_QUERY (cust_model),
								       "DELETE from customers "
								       "WHERE id=##/*name:'-0' type:gint*/", NULL));
		g_assert (gda_data_model_query_set_modification_query (GDA_DATA_MODEL_QUERY (cust_model),
								       "INSERT INTO customers (id, name, default_served_by) "
								       "values ("
								       "##/*name:'+0' type:gint*/, "
								       "##/*name:'+1' type:gchararray*/, "
								       "##/*name:'+2' type:gint*/)", NULL));
			  
		/* create a data model for the salesrep */
		query = gda_query_new_from_sql (demo_dict, "SELECT id, name FROM salesrep", NULL);
		sr_model = gda_data_model_query_new (query);
		g_object_unref (query);

		/* create grid widget */
		label = gtk_label_new ("<b>GnomeDbGrid:</b>");
		gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
		gtk_misc_set_alignment (GTK_MISC (label), 0., -1);
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
		gtk_widget_show (label);

		grid = gnome_db_grid_new (cust_model);
		gtk_box_pack_start (GTK_BOX (vbox), grid, TRUE, TRUE, 0);
		gtk_widget_show (grid);

		/* restrict the c.default_served_by field in the grid to be within the sr_model */
		g_object_get (G_OBJECT (grid), "raw_grid", &raw_grid, NULL);
		restrict_default_served_by_field (GNOME_DB_DATA_WIDGET (raw_grid), sr_model, 0);
		data->grid_iter = gnome_db_data_widget_get_current_data (GNOME_DB_DATA_WIDGET (raw_grid));
		g_signal_connect (data->grid_iter, "row_changed",
				  G_CALLBACK (iter_row_changed_cb), data);

		/* create form widget which uses the same data model as the grid */
		label = gtk_label_new ("<b>GnomeDbForm:</b>");
		gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
		gtk_misc_set_alignment (GTK_MISC (label), 0., -1);
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
		gtk_widget_show (label);

		proxy = gnome_db_data_widget_get_proxy (GNOME_DB_DATA_WIDGET (raw_grid));
		form = gnome_db_form_new (GDA_DATA_MODEL (proxy));
		gtk_box_pack_start (GTK_BOX (vbox), form, TRUE, TRUE, 0);
		gtk_widget_show (form);

		/* restrict the c.default_served_by field in the form to be within the sr_model */
		g_object_get (G_OBJECT (form), "raw_form", &raw_form, NULL);
		restrict_default_served_by_field (GNOME_DB_DATA_WIDGET (raw_form), sr_model, 0);
		data->form_iter = gnome_db_data_widget_get_current_data (GNOME_DB_DATA_WIDGET (raw_form));
		g_signal_connect (data->form_iter, "row_changed",
				  G_CALLBACK (iter_row_changed_cb), data);

		g_object_unref (cust_model);
		g_object_unref (sr_model);

		/* optional synchronization of the selections */
		label = gtk_label_new ("<b>Selected rows synchronization option:</b>\n"
				       "<small>Effective only at the next selected row change</small>");
		gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
		gtk_misc_set_alignment (GTK_MISC (label), 0., -1);
		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
		gtk_widget_show (label);
		
		cb = gtk_check_button_new_with_label ("Keep selected rows synchroniezd");
		gtk_box_pack_start (GTK_BOX (vbox), cb, FALSE, TRUE, 0);
		gtk_widget_show (cb);
		g_signal_connect (G_OBJECT (cb), "toggled",
				  G_CALLBACK (sync_selections_cb), data);
	}

	if (!GTK_WIDGET_VISIBLE (window))
		gtk_widget_show_all (window);
	else
		gtk_widget_destroy (window);

	return window;
}
