/* gnome-db-selector-private.h
 *
 * Copyright (C) 2004 Vivien Malerba
 *
 * 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
 */

#ifndef __GNOME_DB_SELECTOR_PRIVATE__
#define __GNOME_DB_SELECTOR_PRIVATE__

G_BEGIN_DECLS

/* 
 * Structure to define a "Module". A module is given a GtkTreeIter and manages to display data below that
 * iterator (the iter is allocated, and may be NULL if the module starts at the root of the GtkTreeModel).
 *
 * Modules are created either when the widget is initialized, or by other modules when objects are created
 * and must be displayed using a module by themselves.
 * 
 * The structure of a module is as follows:
 * - selector: points to the GnomeDbSelector widget itself
 * - iter: the top node of the module, or NULL if the module is alone
 * - fill_model: function called just after the module is created, to fill the GtkTreeModel
 * - free: function called right before freeing the module's structure
 * - col_name: returns the module's preferences for a given column's name
 * - obj_manager: function which can be called when an object is created to decide if some sub modules must be created
 * - model_store_data: function called to set specific columns' values (usually the module's contents management is written
 *   in a quite generic way and this function gets called whenever a row is inserted in the GtkTreeModel pr updated).
 * - parent_module: the parent module, or NULL if there is none
 * - sub_modules: the sub modules if applicable, or NULL
 * - mod_data: an extra handle to be used by the module itself, depends on each module.
 *
 * Rem: the obj_manager and model_store_data are not used by all of the modules.
 */
typedef struct _Module {
	GnomeDbSelector           *selector;
	GtkTreeIter          *iter;

	void                (*fill_model)       (struct _Module *module);
	void                (*free)             (struct _Module *module);
	const gchar        *(*col_name)         (struct _Module *module, guint colno);
	struct _Module     *(*obj_manager)      (struct _Module *module, GtkTreeIter *iter, GObject *added_obj);
	void                (*model_store_data) (struct _Module *module, GtkTreeIter *iter);

	/* modules hierarchy */
	struct _Module       *parent_module;
	GSList               *sub_modules;

	/* module's own private usage */
	gpointer              mod_data;
} Module;
#define MODULE(x) ((Module *) x)


struct _GnomeDbSelectorPriv
{
	GnomeDbDict       *dict;
	gulong        mode;
	gulong        columns;
	GObject      *ref_object;

	GtkTreeView  *treeview;
	gboolean      headers_visible;
	GtkTreeModel *model;   /* we pocess a reference on the object */

	GSList       *modules; /* list of Module structures */
	GObject      *selection;
};

/* columns names for the GtkTreeView */
enum
{
	NAME_COLUMN,
	OWNER_COLUMN, /* associated to GNOME_DB_SELECTOR_COLUMN_OWNER */
	DESCR_COLUMN, /*               GNOME_DB_SELECTOR_COLUMN_COMMENTS */
	EXTRA1_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_TYPE */
	EXTRA2_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_FIELD_LENGTH */
	EXTRA3_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_FIELD_NNUL */
	EXTRA4_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_FIELD_NNUL to tell if applicable */
	EXTRA5_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_FIELD_DEFAULT */
	EXTRA6_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_QFIELD_VALUE */
	EXTRA7_COLUMN,/*               GNOME_DB_SELECTOR_COLUMN_QFIELD_TYPE */
	EXTRA_END_COLUMN,/* marks the end of extra columns, contains nothing */
	OBJ_COLUMN,
	PIXBUF_COLUMN,
	CONTENTS_COLUMN,
	SUB_MODULE_COLUMN,
	ERROR_COLUMN,
	NUM_COLUMNS,
};

enum
{
	CONTENTS_TOP_CATEGORY,
	CONTENTS_GROUP_CATEGORY,
	CONTENTS_OBJECT
};



/*
 * Generic module model where objects are grouped by their gnome_db_base_get_name() value
 * The text which gets displayed
 */
typedef struct {
	GSList      *objects;
	GtkTreeIter *iter;
	GObject     *iter_obj;
	GdkPixbuf   *obj_pixbuf;
	
	GObject     *manager;
	gboolean     manager_weak_refed;
	gulong       manager_nullified_sig_id;

	GSList    *(*get_objects_list) (Module *module);
	gchar     *(*get_extended_name) (GObject *obj);
} ModNameGroupData;
#define GROUP_DATA(x) ((ModNameGroupData *)(x->mod_data))

void name_group_init_model_fill      (Module *module, GtkTreeModel *model);
void name_group_manager_nullified_cb (GObject *manager_obj, Module *module);
void name_group_manager_weak_notify  (Module *module, GObject *manager_obj);
void name_group_obj_added_cb         (GObject *manager_obj, GObject *added_obj, Module *module);
void name_group_obj_removed_cb       (GObject *manager_obj, GObject *removed_obj, Module *module);
void name_group_obj_updated_cb       (GObject *manager_obj, GObject *upd_obj, Module *module);
void name_group_update_started_cb    (GObject *manager_obj, Module *module);
void name_group_update_finished_cb   (GObject *manager_obj, Module *module);
void name_group_free_mod_data        (Module *module);

void name_group_do_add_obj           (Module *module, GObject *added_obj);
void name_group_do_remove_obj        (Module *module, GObject *removed_obj);
void name_group_do_update_obj        (Module *module, GObject *updated_obj);






/*
 * Generic module model where objects are listed directly in the order of the provided
 * list of objects
 */
typedef struct {
	GSList      *objects;
	GdkPixbuf   *fallback_obj_pixbuf;
	GHashTable  *pixbuf_hash; /* key = object class, value = a GdkPixbuf */
	
	GObject     *manager;
	gboolean     manager_weak_refed;

	GSList    *(*get_objects_list) (Module *module);
} ModFlatData;
#define FLAT_DATA(x) ((ModFlatData *)(x->mod_data))

void flat_init_model_fill       (Module *module, GtkTreeModel *model);
void flat_manager_weak_notify   (Module *module, GObject *manager_obj);
void flat_obj_added_cb          (GObject *manager_obj, GObject *added_obj, Module *module);
void flat_obj_removed_cb        (GObject *manager_obj, GObject *removed_obj, Module *module);
void flat_obj_updated_cb        (GObject *manager_obj, GObject *upd_obj, Module *module);
void flat_objs_order_changed_cb (GObject *manager_obj, Module *module);
void flat_free_mod_data         (Module *module);

void flat_do_add_obj            (Module *module, GObject *added_obj);
void flat_do_remove_obj         (Module *module, GObject *removed_obj);
void flat_do_update_obj         (Module *module, GObject *updated_obj);

G_END_DECLS

#endif



