/*
**  $Id: network_list.c,v 1.11 2000/07/23 00:55:29 remlali Exp $
**  GXSNMP -- An SNMP management application
**
**  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, Cambridge, MA 02139, USA.
**
**  Host list UI specific functions
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <gnome.h>
#include "dbapi.h"
#include "gxsnmp/gxsnmp_dbapi.h"
#include "network_list.h"
#include "network_dialog.h"
#include "main.h"
#include "gxsnmp_map.h"
#include "gxsnmp_window.h"

#include "debug.h"

extern gxsnmp *app_info;

/****************************************************************************
 * Static data 
 ***************************************************************************/
#define NETWORK_CLIST_COLUMNS 3
static gchar *network_clist_titles[] = {
  N_("Name"), N_("Description"), N_("Last Modification")
};
static gint  network_clist_title_widths[] = { 15, 25, 10 };

/****************************************************************************
 * Forward declarations and callback functions  
 ***************************************************************************/
static void      network_list_class_init  (GXsnmp_network_listClass  *klass);
static void      network_list_init        (GXsnmp_network_list       *dialog);
static void      list_refresh_cb          (G_sqldb_table             *table,
                                           gpointer                   row,
                                           G_sqldb_cb_type            type,
                                           gpointer                   data);
static void      list_refresh_row         (GXsnmp_network_list       *dialog,
                                           DB_network                *dbn);
static void      list_delete_cb           (GtkWidget                 *widget,
                                           gpointer                   data);
static void      list_edit_cb             (GtkWidget                 *widget,
                                           gpointer                   data);
static void      list_add_cb              (GtkWidget                 *widget,
                                           gpointer                   data);
static void      list_dialog_cb           (GnomeDialog               *dialog,
					   gint                       button,
                                           gpointer                   data);
static void      list_select_row_cb       (GtkWidget                 *widget,
                                           gint                       row,
                                           gint                       column,
                                           GdkEventButton            *event,
                                           gpointer                   data);
/****************************************************************************
 * gxsnmp_network_list_get_type()
 ***************************************************************************/
GtkType
gxsnmp_network_list_get_type ()
{
  static GtkType list_type = 0;
  D_FUNC_START;
  if (!list_type)
    {
      GtkTypeInfo list_info = 
      {
	"GXsnmp_network_list",
	sizeof (GXsnmp_network_list),
	sizeof (GXsnmp_network_listClass),
	(GtkClassInitFunc) network_list_class_init,
	(GtkObjectInitFunc) network_list_init,
	/* reserved 1 */ NULL,
	/* reserved 2 */ NULL,
	(GtkClassInitFunc) NULL,
      };
      d_print (DEBUG_TRACE, "registering new widget type.\n");
      list_type =gtk_type_unique(gnome_dialog_get_type(), &list_info);
    }
  D_FUNC_END;
  return list_type;
}
/****************************************************************************
 * Class init
 ***************************************************************************/
static void
network_list_class_init (GXsnmp_network_listClass *klass)
{
  d_print (DEBUG_TRACE, "\n");
}
/****************************************************************************
 * Widget init
 ***************************************************************************/
static void
network_list_init (GXsnmp_network_list *dialog)
{
  GtkWidget *hbox;
  GtkWidget *vbox;
  GtkWidget *edit;
  GtkWidget *add;
  GtkWidget *delete;
  gint      i, c_width, c_height;
  gint      z;

  D_FUNC_START;
  hbox = gtk_hbox_new (FALSE, 2);
  gtk_box_pack_start (GTK_BOX (GNOME_DIALOG(dialog)->vbox), 
		      hbox, TRUE, TRUE, 0);
  c_width  = gdk_string_width (hbox->style->font, "xW") / 2;
  c_height = hbox->style->font->ascent +
	     hbox->style->font->descent;
  vbox = gtk_vbox_new (FALSE, 2);
  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  dialog->scrolled = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->scrolled),
				  GTK_POLICY_AUTOMATIC,
				  GTK_POLICY_ALWAYS);
  gtk_box_pack_start (GTK_BOX (vbox), dialog->scrolled, TRUE, TRUE, 0);
  dialog->clist = gtk_clist_new_with_titles(NETWORK_CLIST_COLUMNS, 
					    network_clist_titles);
  gtk_clist_set_selection_mode (GTK_CLIST (dialog->clist),
				GTK_SELECTION_BROWSE);
  gtk_clist_column_titles_passive (GTK_CLIST (dialog->clist));
  z = 0;
  for (i = 0; i < NETWORK_CLIST_COLUMNS; i++)
    {
      z += network_clist_title_widths[i] + 4;
      gtk_clist_set_column_width (GTK_CLIST (dialog->clist), i,
				  c_width * network_clist_title_widths[i]);
    }
  gtk_widget_set_usize (vbox, (z * c_width) + 10, c_height * 20);
  gtk_container_add (GTK_CONTAINER (dialog->scrolled), dialog->clist);

  vbox = gtk_vbutton_box_new ();
  gtk_button_box_set_layout (GTK_BUTTON_BOX (vbox), GTK_BUTTONBOX_START);
  gtk_button_box_set_child_size (GTK_BUTTON_BOX (vbox), 50, 20);
  gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);

  delete = gtk_button_new_with_label (_("Delete network"));
  gtk_box_pack_end (GTK_BOX (vbox), delete, FALSE, FALSE, 0);
  edit = gtk_button_new_with_label (_("Edit network"));
  gtk_box_pack_end (GTK_BOX (vbox), edit, FALSE, FALSE, 0);
  add = gtk_button_new_with_label (_("Add network"));
  gtk_box_pack_end (GTK_BOX (vbox), add, FALSE, FALSE, 0);
  /* Signals */
  gtk_signal_connect (GTK_OBJECT (delete), "clicked", 
		      GTK_SIGNAL_FUNC(list_delete_cb), dialog);
  gtk_signal_connect (GTK_OBJECT (edit), "clicked", 
		      GTK_SIGNAL_FUNC(list_edit_cb), dialog);
  gtk_signal_connect (GTK_OBJECT (add), "clicked", 
		      GTK_SIGNAL_FUNC(list_add_cb), dialog);
  gtk_signal_connect (GTK_OBJECT (dialog->clist), "select_row",
		      GTK_SIGNAL_FUNC(list_select_row_cb), dialog);
  /* Show the whole mess */
  gtk_widget_show_all (hbox);
  /* Append buttons for close and help */
  gnome_dialog_append_buttons (GNOME_DIALOG (dialog),
                               GNOME_STOCK_BUTTON_CLOSE,
                               GNOME_STOCK_BUTTON_HELP,
                               NULL);
  gtk_signal_connect (GTK_OBJECT(dialog), "clicked",
		      GTK_SIGNAL_FUNC(list_dialog_cb), NULL);
  D_FUNC_END;
}
/****************************************************************************
 * Callback function to refresh the entire widget contents.
 ***************************************************************************/
static void
list_refresh_cb (G_sqldb_table *table, gpointer row, G_sqldb_cb_type type,
		 gpointer data)
{
  GXsnmp_network_list  *dialog;
  GtkCList             *clist;
  GList                *gl;
  D_FUNC_START;
  g_return_if_fail (data != NULL);
  dialog = GXSNMP_NETWORK_LIST (data);
  clist  = GTK_CLIST (dialog->clist);
  g_return_if_fail (clist != NULL);
  g_return_if_fail (GTK_IS_CLIST (clist));
  gtk_clist_freeze (clist);
  gtk_clist_clear (clist);
  gtk_signal_handler_block_by_data (GTK_OBJECT (clist), dialog);
  gl = g_sqldb_table_list (network_sqldb);
  while (gl)
    {
      if (gl->data)
	list_refresh_row (dialog, (DB_network *)gl->data);
      gl = gl->next;
    }
  gl = g_sqldb_table_list (network_sqldb);
  if (gl)
    dialog->selected_network = (DB_network *)gl->data;
  gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), dialog);
  gtk_clist_thaw (clist);
  D_FUNC_END;
}
static void
list_refresh_row (GXsnmp_network_list *dialog, DB_network *dbn)
{
  GtkCList  *clist;
  gchar     *entry[3];
  gint      row;
  D_FUNC_START;
  if (!dbn)
    {
      g_warning ("list_refresh_row: bogus dbn handle...");
      D_FUNC_END;
      return;
    }
  clist = GTK_CLIST (dialog->clist);
  if (!(GTK_IS_CLIST (clist)) )
    {
      g_warning ("list_refresh_row: invaild clist pointer");
      D_FUNC_END;
      return;
    }
  entry[0] = dbn->name;
  entry[1] = dbn->description;
  entry[2] = dbn->modified;
  row = gtk_clist_append (clist, entry);
  gtk_clist_set_row_data (clist, row, GINT_TO_POINTER (dbn->rowid));
  D_FUNC_END;
}
static void
list_delete_cb (GtkWidget *widget, gpointer data)
{
  GXsnmp_map          *map_canvas;
  GXsnmp_network_list *dialog;
  DB_network          *dbn;
  GtkWidget           *dialog_widget;
  D_FUNC_START;
  g_return_if_fail (data != NULL);
  g_return_if_fail (GXSNMP_IS_NETWORK_LIST(data));
  dialog = GXSNMP_NETWORK_LIST (data);
  dbn    = dialog->selected_network;
  g_return_if_fail (dbn != NULL);
  network_delete(dbn);
  network_destroy(dbn);
  D_FUNC_END;
}
static void
list_edit_cb (GtkWidget *widget, gpointer data)
{
  GXsnmp_map          *map_canvas;
  GXsnmp_network_list *dialog;
  DB_network          *dbn;
  GtkWidget           *dialog_widget;
  D_FUNC_START;
  g_return_if_fail (data != NULL);
  g_return_if_fail (GXSNMP_IS_NETWORK_LIST(data));
  dialog = GXSNMP_NETWORK_LIST (data);
  dbn    = dialog->selected_network;
  if (!gxsnmp_dialog_check ("edit_network", dbn))
    {
      d_print (DEBUG_TRACE, "Editing network %s\n", dbn->name);
      map_canvas = gxsnmp_window_get_current_map
		     (GXSNMP_WINDOW (app_info->window));
      if (map_canvas)
	{
	  dialog_widget = gxsnmp_network_dialog_new (dbn, 
						     map_canvas->x1,
						     map_canvas->y1);
	}
      else
	{
	  d_print (DEBUG_TRACE, "no map canvas, set x/y coordinates "
                                "accordingly.\n");
	  dialog_widget = gxsnmp_network_dialog_new (dbn, 
						     0,
						     0);
	}
      if (dialog_widget)
	gxsnmp_dialog_add (dialog_widget, "edit_network", dbn,
			   g_strdup_printf ("Edit network '%s'", dbn->name));
    }
  D_FUNC_END;
}
static void
list_add_cb (GtkWidget * widget, gpointer data)
{
  GXsnmp_map * map_canvas;
  gchar      * timestamp;
  GtkWidget  * dialog_widget;
  D_FUNC_START;
  if (gxsnmp_dialog_check ("add_network", NULL)) /* Dialog already open? */
    {
      g_warning ("Add one network at a time only please.");
      D_FUNC_END;
      return;                                    /* Yes - One at a time only */
    }
  timestamp = db_timestamp ();
  map_canvas = gxsnmp_window_get_current_map
				(GXSNMP_WINDOW (app_info->window));
  if (map_canvas)
    {
      dialog_widget = gxsnmp_network_dialog_new (NULL, 
						 map_canvas->x1,
						 map_canvas->y1);
    }
  else
    {
      dialog_widget = gxsnmp_network_dialog_new (NULL,
						 0, 
						 0);
    }

  if (dialog_widget)
    gxsnmp_dialog_add (dialog_widget, "add_network", NULL,
                       g_strdup ("Add a new network"));
  D_FUNC_END;
}
static void
list_dialog_cb (GnomeDialog *dialog, gint button, gpointer data)
{
  gchar   *tmp;
  D_FUNC_START;
  if (button == 0)
    {
      gnome_dialog_close (GNOME_DIALOG (dialog));
    }
  else if (button == 1)
    {
      tmp = gnome_help_file_find_file ("gxsnmp", "network-list.html");
      if (tmp)
	{
	  gnome_help_goto (0, tmp);
	  g_free (tmp);
	}
    }
  D_FUNC_END;
}
static void
list_select_row_cb (GtkWidget *widget, gint row, gint column,
		    GdkEventButton *event, gpointer data)
{
  GXsnmp_network_list *dialog;
  GtkCList            *clist;
  guint                rowid;
  DB_network          *dbn;
  D_FUNC_START;
  g_return_if_fail (data != NULL);
  dialog = GXSNMP_NETWORK_LIST (data);
  clist  = GTK_CLIST(widget);
  rowid = GPOINTER_TO_INT (gtk_clist_get_row_data (clist, row));
  if (rowid)
    {
      /* assignement intended */
      if ( !(dbn = g_sqldb_row_find (network_sqldb, "_rowid", &rowid)) )
	{
	  g_warning ("list_select_row_cb: unable to locate network with "
		     "the rowid %d.", rowid);
	  dialog->selected_network = NULL;
	  D_FUNC_END;
	  return;
	}
      dialog->selected_network = dbn;
    }
  else dialog->selected_network = NULL;
  D_FUNC_END;
}
/****************************************************************************
 * Public API
 ***************************************************************************/
GtkWidget *
gxsnmp_network_list_new (gpointer data)
{
  GXsnmp_network_list  *dialog;
  D_FUNC_START;
  dialog = gtk_type_new (gxsnmp_network_list_get_type ());
  list_refresh_cb (network_sqldb, NULL, G_SQLDB_CB_UPDATE, dialog);
  D_FUNC_END;
  return GTK_WIDGET (dialog);
}

/* EOF */


