X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fpokey%2Finterface.c;h=706c5fab21fbd77ad8fcfabde77bcb0f64a535f2;hp=26eda41b0f3b47ee3ed1473fdbec1f17f6981786;hb=efa5148bc76effb440d807d653dda02de050fde0;hpb=17b308f0f0879c01f6864265af2e63595e965993 diff --git a/src/pokey/interface.c b/src/pokey/interface.c index 26eda41b..706c5fab 100644 --- a/src/pokey/interface.c +++ b/src/pokey/interface.c @@ -1,9 +1,35 @@ +/* + interface.c -- GTK+/GNOME interface functions + Copyright (C) 2002 Guus Sliepen , + 2002 Ivo Timmermans + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: interface.c,v 1.5 2002/05/02 11:50:07 zarq Exp $ +*/ + #include "config.h" +#include #include #include #include + +#define log mathlog #include +#undef log #include #include @@ -14,20 +40,33 @@ #include #include "node.h" +#include "connection.h" #include "edge.h" #include "interface.h" +#include "logging.h" +#include #include #include "system.h" -extern GladeXML *xml; +/* Node tree & main window stuff */ +static GladeXML *xml; +static GtkWidget *nodetree; +static GtkCTreeNode *hosts_ctn; -#ifdef MAXBUFSIZE -#undef MAXBUFSIZE -#endif -#define MAXBUFSIZE 1024 +/* Graph canvas stuff */ +static GladeXML *canvas_xml; + +static GnomeCanvasGroup *edge_group = NULL; + +static int canvas_width; +static int canvas_height; + +static GtkWidget *canvas = NULL; + +static int canvas_visible = 0; int build_graph = 0; @@ -48,44 +87,61 @@ double y[MAX_NODES]; double k[MAX_NODES][MAX_NODES]; double d[MAX_NODES][MAX_NODES]; double l[MAX_NODES][MAX_NODES]; -const double epsilon = 0.001; +static const double epsilon = 0.001; static int inited = 0; static int number_of_nodes = 0; -static GtkWidget *nodetree; -static GtkCTreeNode *subnets_ctn, *hosts_ctn, *conns_ctn; +static double canvas_zoom = 1.00; -static GnomeCanvasGroup *edge_group = NULL; -static int canvas_width; -static int canvas_height; +/* Log window stuff */ +#ifdef MAXBUFSIZE +#undef MAXBUFSIZE +#endif -static GtkWidget *canvas = NULL; +#define MAXBUFSIZE 1024 + +static int log_inited = 0; +static int follow_log = 1; + +static int keep_drawing = 1; + +static int log_visible = 0; +static GtkWidget *log_window = NULL; + + +void if_node_add(const char *hooktype, va_list ap); +void if_node_del(const char *hooktype, va_list ap); +void if_subnet_add(const char *hooktype, va_list ap); +void if_subnet_del(const char *hooktype, va_list ap); +void if_edge_add(const char *hooktype, va_list ap); +void if_edge_del(const char *hooktype, va_list ap); +void if_node_visible(const char *hooktype, va_list ap); +void if_node_invisible(const char *hooktype, va_list ap); + +void if_node_create(node_t *n); GtkWidget *create_canvas(void) { - GtkWidget *w; - - gtk_widget_push_visual(gdk_rgb_get_visual()); - gtk_widget_push_colormap(gdk_rgb_get_cmap()); - - canvas = gnome_canvas_new_aa(); - - gtk_widget_pop_visual(); - gtk_widget_pop_colormap(); - - gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), 0, 0, 500, 300); + canvas_xml = glade_xml_new(INTERFACE_FILE, "GraphWindow"); + if(!canvas_xml) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "GraphWindow"); + return NULL; + } - w = glade_xml_get_widget(xml, "scrolledwindow3"); - if(!w) + canvas = glade_xml_get_widget(xml, "canvas1"); + if(!canvas) { - fprintf(stderr, "Could not find widget `scrolledwindow3'\n"); + fprintf(stderr, "Could not find widget `canvas1'\n"); return NULL; } - gtk_container_add(GTK_CONTAINER(w), canvas); - gtk_widget_show_all(w); + + gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), 0.0, 0.0, 700, 500); canvas_width = 300.0; canvas_height = 500.0; @@ -93,71 +149,22 @@ GtkWidget *create_canvas(void) return canvas; } -int init_interface(void) +void log_gtk(int level, int priority, char *fmt, va_list ap) { - char *l[1]; - GtkArg p; - - if(!xml) - return -1; - - nodetree = glade_xml_get_widget(xml, "NodeTree"); - if(!nodetree) - { - fprintf(stderr, _("Could not find widget `NodeTree'\n")); - return -1; - } - - gtk_clist_freeze(GTK_CLIST(nodetree)); - - l[0] = _("Hosts"); - hosts_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), - NULL, NULL, l, 1, - NULL, NULL, NULL, NULL, - FALSE, TRUE); - l[0] = _("Subnets"); - subnets_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), - NULL, NULL, l, 1, - NULL, NULL, NULL, NULL, - FALSE, TRUE); - l[0] = _("Connections"); - conns_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), - NULL, NULL, l, 1, - NULL, NULL, NULL, NULL, - FALSE, TRUE); - - gtk_clist_thaw(GTK_CLIST(nodetree)); - - create_canvas(); - - return 0; -} - -void log_message(int severity, const char *fmt, ...) -{ - va_list args; char buffer1[MAXBUFSIZE]; char buffer2[MAXBUFSIZE]; - GtkWidget *w; int len; char *p; struct tm *tm; time_t t; - static int inited = 0; - if(!xml) - return; - - w = glade_xml_get_widget(xml, "Messages"); - if(!w) + if(!log_visible) return; /* Use vsnprintf instead of vasprintf: faster, no memory fragmentation, cleanup is automatic, and there is a limit on the input buffer anyway */ - va_start(args, fmt); - len = vsnprintf(buffer1, MAXBUFSIZE, fmt, args); - va_end(args); + len = vsnprintf(buffer1, MAXBUFSIZE, fmt, ap); buffer1[MAXBUFSIZE-1] = '\0'; if((p = strrchr(buffer1, '\n'))) @@ -181,16 +188,545 @@ void log_message(int severity, const char *fmt, ...) } } - gtk_text_freeze(GTK_TEXT(w)); + gtk_text_freeze(GTK_TEXT(log_window)); + + if(log_inited) + gtk_text_insert(GTK_TEXT(log_window), NULL, NULL, NULL, "\n", 1); + + gtk_text_insert(GTK_TEXT(log_window), NULL, &timecolor, NULL, buffer2, strlen(buffer2)); + gtk_text_insert(GTK_TEXT(log_window), NULL, NULL, NULL, buffer1, len); + gtk_text_thaw(GTK_TEXT(log_window)); + + log_inited = 1; + if(follow_log) +/* gtk_text_set_point(GTK_TEXT(w), -1); */ + gtk_editable_set_position(GTK_EDITABLE(log_window), gtk_text_get_length(GTK_TEXT(log_window))); +} + +void if_hostinfoclosebutton_clicked(GtkWidget *w, gpointer data) +{ + gtk_widget_destroy(GTK_WIDGET(data)); +} + +void update_hostinfo_dialog(GladeXML *x, node_t *n) +{ + GtkWidget *w; + char s[100]; + avl_node_t *avlnode; + char *l[1]; + + w = glade_xml_get_widget(x, "HostInfoNameEntry"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoNameEntry"); return; } + gtk_entry_set_text(GTK_ENTRY(w), n->name); + + w = glade_xml_get_widget(x, "HostInfoHostnameEntry"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoHostnameEntry"); return; } + gtk_entry_set_text(GTK_ENTRY(w), n->hostname); + + w = glade_xml_get_widget(x, "HostInfoPortEntry"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoPortEntry"); return; } +/* snprintf(s, sizeof(s)-1, "%hd", "0"); */ + gtk_entry_set_text(GTK_ENTRY(w), "port"); + + w = glade_xml_get_widget(x, "HostInfoVersionEntry"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoVersionEntry"); return; } + gtk_entry_set_text(GTK_ENTRY(w), n->name); + + w = glade_xml_get_widget(x, "HostInfoStatusEntry"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoStatusEntry"); return; } +/* snprintf(s, sizeof(s)-1, "%x", n->status); */ + gtk_entry_set_text(GTK_ENTRY(w), "0"); + + w = glade_xml_get_widget(x, "HostInfoActiveCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoActiveCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.active); + + w = glade_xml_get_widget(x, "HostInfoValidkeyCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoValidkeyCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.validkey); + + w = glade_xml_get_widget(x, "HostInfoWaitingforkeyCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoWaitingforkeyCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.waitingforkey); + + w = glade_xml_get_widget(x, "HostInfoVisitedCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoVisitedCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.visited); + + w = glade_xml_get_widget(x, "HostInfoReachableCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoReachableCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.reachable); + + w = glade_xml_get_widget(x, "HostInfoIndirectCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoIndirectCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.indirect); + + w = glade_xml_get_widget(x, "HostInfoVisibleCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoVisibleCheckbutton"); return; } +/* gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.visible); */ + + w = glade_xml_get_widget(x, "HostInfoTCPOnlyCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoTCPOnlyCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (n->options & OPTION_TCPONLY) != 0); + + w = glade_xml_get_widget(x, "HostInfoIndirectdataCheckbutton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoIndirectdataCheckbutton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (n->options & OPTION_INDIRECT) != 0); + +/* w = glade_xml_get_widget(x, "HostInfoWindow"); */ +/* if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoWindow"); return; } */ +/* glade_xml_signal_connect_data(x, "on_HostInfoCloseButton_clicked", if_hostinfoclosebutton_clicked, (gpointer)w); */ + w = glade_xml_get_widget(x, "HostConnectionsCList"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostConnectionsCList"); return; } + for(avlnode = n->edge_tree->head; avlnode; avlnode = avlnode->next) + { + if(((edge_t*)(avlnode->data))->to.node == n) + l[0] = ((edge_t*)(avlnode->data))->from.node->name; + else + l[0] = ((edge_t*)(avlnode->data))->to.node->name; + gtk_clist_append(GTK_CLIST(w), l); + } +} + +void on_preferences1_activate(GtkMenuItem *mi, gpointer data) +{ + GtkWidget *w; + GladeXML *x; + + x = glade_xml_new(INTERFACE_FILE, "PropertyBox"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "PropertyBox"); + return; + } + + w = glade_xml_get_widget(x, "PropertyBox"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "PropertyBox"); return; } + glade_xml_signal_autoconnect(x); +} + +void on_logcontext_clear_activate(GtkMenuItem *mi, gpointer data) +{ + gtk_editable_delete_text(GTK_EDITABLE(log_window), 0, -1); /* Delete from 0 to end of buffer */ + log_inited = 0; +} + +void on_logcontext_follow_activate(GtkMenuItem *mi, gpointer data) +{ + follow_log = !follow_log; +} + +void on_logcontext_close1_activate(GtkMenuItem *mi, gpointer data) +{ + +} + +void on_messages_button_press_event(GtkWidget *w, GdkEventButton *event, gpointer data) +{ + GladeXML *x; + GtkWidget *menu; + + if (event->button == 3) + { + x = glade_xml_new(INTERFACE_FILE, "LogContextMenu"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "LogContextMenu"); + return; + } + + menu = glade_xml_get_widget(x, "LogContextMenu"); + if(!menu) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "LogContextMenu"); return; } + + glade_xml_signal_connect_data(x, "on_logcontext_clear_activate", on_logcontext_clear_activate, (gpointer)x); + glade_xml_signal_connect_data(x, "on_logcontext_follow_activate", on_logcontext_follow_activate, (gpointer)x); + w = glade_xml_get_widget(x, "LogContextFollow"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "LogContextFollow"); return; } + GTK_CHECK_MENU_ITEM(w)->active = follow_log; + gnome_popup_menu_do_popup_modal(menu, NULL, NULL, event, NULL); + gtk_widget_destroy(menu); + } +} + +void shuffle_nodes(void) +{ + avl_node_t *avlnode; + double newx, newy; + + for(avlnode = node_tree->head; avlnode; avlnode = avlnode->next) + { + newx = ((double)random()) / ((double)RAND_MAX) * 500.0; + newy = ((double)random()) / ((double)RAND_MAX) * 300.0; + ((struct if_node_data*)((node_t *)(avlnode->data))->data)->x = newx; + ((struct if_node_data*)((node_t *)(avlnode->data))->data)->y = newy; + + if(!((struct if_node_data*)((node_t*)(avlnode->data)))->visible) + continue; + + x[((struct if_node_data*)((node_t*)(avlnode->data))->data)->id] = newx; + y[((struct if_node_data*)((node_t*)(avlnode->data))->data)->id] = newy; + } + inited = 0; + build_graph = 1; +} + +void on_canvascontext_shuffle_activate(GtkMenuItem *mi, gpointer data) +{ + shuffle_nodes(); +} + +void on_canvascontext_keep_drawing_activate(GtkMenuItem *mi, gpointer data) +{ + GtkWidget *w; + + keep_drawing = !keep_drawing; + + /* No need to fuss with the checkbox in the menu, because that is + transient. Do need to update the checkbox at the bottom of the + window though. */ + w = glade_xml_get_widget(canvas_xml, "KeepDrawingButton"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "KeepDrawingButton"); return; } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), keep_drawing); +} + +void on_canvascontext_minus50_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom *= 0.50; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_canvascontext_minus25_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom *= 0.75; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_canvascontext_minus10_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom *= 0.90; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_canvascontext_default_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom = 1.00; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), 1.00); +} + +void on_canvascontext_plus10_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom *= 1.10; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_canvascontext_plus25_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom *= 1.25; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_canvascontext_plus50_activate(GtkMenuItem *mi, gpointer data) +{ + canvas_zoom *= 1.50; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_canvas_button_press_event(GtkWidget *w, GdkEventButton *event, gpointer data) +{ + GladeXML *x; + GtkWidget *menu; + + if (event->button == 3) + { + x = glade_xml_new(INTERFACE_FILE, "CanvasContextMenu"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "CanvasContextMenu"); + return; + } + + menu = glade_xml_get_widget(x, "CanvasContextMenu"); + if(!menu) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "CanvasContextMenu"); return; } + + glade_xml_signal_autoconnect(x); + glade_xml_signal_connect_data(x, "on_canvascontext_shuffle_activate", on_canvascontext_shuffle_activate, (gpointer)x); + glade_xml_signal_connect_data(x, "on_canvascontext_keep_drawing_activate", on_canvascontext_keep_drawing_activate, (gpointer)x); + w = glade_xml_get_widget(x, "CanvasContextKeepDrawing"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "CanvasContextKeepDrawing"); return; } + GTK_CHECK_MENU_ITEM(w)->active = keep_drawing; + gnome_popup_menu_do_popup_modal(menu, NULL, NULL, event, NULL); + gtk_widget_destroy(menu); + } +} + +void on_nodetree_button_press_event(GtkWidget *w, GdkEventButton *event, gpointer data) +{ + GtkCTreeNode *node; + int row, col; + gpointer lt; + GladeXML *x; + + gtk_clist_get_selection_info(GTK_CLIST(w), event->x, event->y, + &row, &col); + + node = gtk_ctree_node_nth(GTK_CTREE(w), row); + if(node == NULL) + return; + lt = gtk_ctree_node_get_row_data(GTK_CTREE(w), node); + if(event->type == GDK_2BUTTON_PRESS && event->button == 1) + { + /* Double left click on an item */ + if(lt == NULL) + /* this is only a branch, double click wil (un)expand. */ + return; + + if(GTK_CTREE_ROW(node)->parent == hosts_ctn) + { + x = ((struct if_node_data*)(((node_t*)lt)->data))->hi_xml = glade_xml_new(INTERFACE_FILE, "HostInfoWindow"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "HostInfoWindow"); + return; + } + glade_xml_signal_autoconnect(x); + update_hostinfo_dialog(x, (node_t*)lt); + } + else + { + log(0, TLOG_ERROR, + "WHERE did you click?!"); + } + /* so now we have access to all the data we want. */ +/* gldap_show_details(lt); */ + return; + } +/* else */ +/* if (event->button == 3) */ +/* { */ +/* GtkWidget *temp_menu; */ +/* temp_menu = gnome_popup_menu_new(data); */ +/* gnome_popup_menu_do_popup_modal(temp_menu, NULL, NULL, event, NULL); */ +/* gtk_widget_destroy(temp_menu); */ +/* } */ +} + +void on_exit1_activate(GtkMenuItem *mi, gpointer data) +{ + close_network_connections(); + gtk_exit(0); +} + +void on_about1_activate(GtkMenuItem *mi, gpointer data) +{ + GladeXML *x; + x = glade_xml_new(INTERFACE_FILE, "AboutWindow"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "AboutWindow"); + return; + } + glade_xml_signal_autoconnect(x); +} + +void on_graph_window1_activate(GtkMenuItem *mi, gpointer data) +{ + int i; + avl_node_t *avlnode; + double newx, newy; + + canvas_xml = glade_xml_new(INTERFACE_FILE, "GraphWindow"); + if(canvas_xml == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "GraphWindow"); + return; + } + glade_xml_signal_autoconnect(canvas_xml); + canvas = glade_xml_get_widget(canvas_xml, "canvas1"); + if(canvas == NULL) { log(0, TLOG_ERROR, _("Could not find widget `%s'"), "canvas1"); return; } + + for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next) + { + node_t *n = (node_t*)(avlnode->data); + + if(!((struct if_node_data*)(n->data))->item) + if_node_create(n); + + if(!n->status.reachable) + continue; + + newx = 250.0 + 200.0 * sin(i / 10.0 * M_PI); + newy = 150.0 - 100.0 * cos(i / 10.0 * M_PI); + gnome_canvas_item_move(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item), newx - ((struct if_node_data*)(n->data))->x, newy - ((struct if_node_data*)(n->data))->y); + ((struct if_node_data*)(n->data))->x = newx; + ((struct if_node_data*)(n->data))->y = newy; + + ((struct if_node_data*)(n->data))->id = i; + + gnome_canvas_item_show(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); + gnome_canvas_update_now(GNOME_CANVAS(canvas)); + nodes[i] = n; + i++; + } + + number_of_nodes = i; + + inited = 0; + build_graph = 1; + canvas_visible = 1; +} + +void on_log_window1_activate(GtkMenuItem *mi, gpointer data) +{ + GladeXML *x; + GtkWidget *w; + + x = glade_xml_new(INTERFACE_FILE, "LogWindow"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "LogWindow"); + return; + } + log_window = glade_xml_get_widget(x, "Messages"); + if(!log_window) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "Messages"); + return; + } + w = glade_xml_get_widget(x, "DebugLevelSpinbutton"); + if(!w) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "DebugLevelSpinbutton"); + return; + } + gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), (float)debug_lvl); + + glade_xml_signal_autoconnect(x); + log_visible = 1; + log_add_hook(log_gtk); + log(0, TLOG_NOTICE, "Logging started.\n"); + +} + +void on_debug_level_changed(GtkSpinButton *sb, gpointer data) +{ + debug_lvl = gtk_spin_button_get_value_as_int(sb); +} + +void on_logwindow_close_clicked(GtkButton *b, gpointer data) +{ + GladeXML *x; + GtkWidget *w; + + x = glade_xml_new(INTERFACE_FILE, "LogWindow"); + if(x == NULL) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "LogWindow"); + return; + } + w = glade_xml_get_widget(x, "LogWindow"); + if(!w) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "LogWindow"); + return; + } + gtk_widget_destroy(w); +} + +void on_spinbutton2_changed(GtkSpinButton *sb, gpointer data) +{ + canvas_zoom = gtk_spin_button_get_value_as_float(sb) / 100.0; + gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); +} + +void on_checkbutton1_toggled(GtkCheckButton *cb, gpointer data) +{ + keep_drawing = !keep_drawing; +} - if(inited) - gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, "\n", 1); +void on_button19_clicked(GtkWidget *bt, GdkEventButton *ev, gpointer data) +{ + shuffle_nodes(); +} - gtk_text_insert(GTK_TEXT(w), NULL, &timecolor, NULL, buffer2, strlen(buffer2)); - gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, buffer1, len); - gtk_text_thaw(GTK_TEXT(w)); +void on_button18_clicked(GtkWidget *bt, GdkEventButton *ev, gpointer data) +{ + GtkWidget *w; - inited = 1; + w = glade_xml_get_widget(canvas_xml, "GraphWindow"); + if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "GraphWindow"); return; } + gtk_object_destroy(GTK_OBJECT(w)); + build_graph = 0; + canvas_visible = 0; +} + +int init_interface(void) +{ + char *l[1]; + + glade_gnome_init(); + + xml = glade_xml_new("pokey.glade", "AppWindow"); + + if(!xml) + { + log(0, TLOG_ERROR, + _("Something bad happened while creating the interface.\n")); + return -1; + } + + nodetree = glade_xml_get_widget(xml, "NodeTree"); + if(!nodetree) + { + log(0, TLOG_ERROR, + _("Could not find widget `%s'"), + "NodeTree"); + return -1; + } + + gtk_clist_freeze(GTK_CLIST(nodetree)); + l[0] = _("Hosts"); + hosts_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), + NULL, NULL, l, 1, + NULL, NULL, NULL, NULL, + FALSE, TRUE); + gtk_clist_thaw(GTK_CLIST(nodetree)); + + glade_xml_signal_autoconnect(xml); + + log_del_hook(log_default); + + add_hook("node-add", if_node_add); + add_hook("node-del", if_node_del); + add_hook("subnet-add", if_subnet_add); + add_hook("subnet-del", if_subnet_del); + add_hook("edge-add", if_edge_add); + add_hook("edge-del", if_edge_del); + add_hook("node-visible", if_node_visible); + add_hook("node-invisible", if_node_invisible); + + return 0; } static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) @@ -239,10 +775,10 @@ static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) gnome_canvas_item_ungrab(item, event->button.time); dragging = FALSE; n = (node_t *)gtk_object_get_user_data(GTK_OBJECT(item)); - n->x = item_x; - n->y = item_y; - x[n->id] = item_x; - y[n->id] = item_y; + ((struct if_node_data*)(n->data))->x = item_x; + ((struct if_node_data*)(n->data))->y = item_y; + x[((struct if_node_data*)(n->data))->id] = item_x; + y[((struct if_node_data*)(n->data))->id] = item_y; build_graph = 1; break; @@ -252,57 +788,212 @@ static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) return FALSE; } -GtkCTreeNode *if_node_add(node_t *n) +void if_node_create(node_t *n) { - char *l[1]; - GtkCTreeNode *ctn; + GnomeCanvasGroup *group; + + group = gnome_canvas_root(GNOME_CANVAS(canvas)); + group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(group, + gnome_canvas_group_get_type(), + "x", 0.0, + "y", 0.0, + NULL)); + + gnome_canvas_item_new(group, gnome_canvas_ellipse_get_type(), + "x1", -30.0, + "y1", -08.0, + "x2", 30.0, + "y2", 08.0, + "fill_color_rgba", 0x5f9ea080, + "outline_color", "black", + "width_pixels", 0, + NULL); + + gnome_canvas_item_new(group, + gnome_canvas_text_get_type(), + "x", 0.0, + "y", 0.0, + "text", n->name, + "anchor", GTK_ANCHOR_CENTER, + "fill_color", "white", + "font", "-*-verdana-medium-r-*-*-10-*-*-*-*-*-iso8859-1", + NULL); + + ((struct if_node_data*)(n->data))->item = GNOME_CANVAS_ITEM(group); + ((struct if_node_data*)(n->data))->x = ((struct if_node_data*)(n->data))->y = 0.0; + gtk_object_set_user_data(GTK_OBJECT(group), (gpointer)n); + + gtk_signal_connect(GTK_OBJECT(((struct if_node_data*)(n->data))->item), "event", (GtkSignalFunc) item_event, NULL); - if(!xml) - return NULL; + gnome_canvas_item_hide(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); +} - l[0] = n->name; - gtk_clist_freeze(GTK_CLIST(nodetree)); - n->host_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), - hosts_ctn, NULL, l, 1, - NULL, NULL, NULL, NULL, - FALSE, FALSE); - gtk_clist_thaw(GTK_CLIST(nodetree)); +void if_node_visible(const char *hooktype, va_list ap) +{ + int i; + avl_node_t *avlnode; + double newx, newy; + node_t *n = va_arg(ap, node_t*); + + if(!n->data) + return; + + if(!((struct if_node_data*)(n->data))->item) + /* No GnomeCanvasItem has been created for this node yet */ + return; + + if(((struct if_node_data*)(n->data))->visible) + /* This node is already shown */ + return; - if_graph_add_node(n); + ((struct if_node_data*)(n->data))->visible = 1; + newx = 250.0 + 200.0 * sin(number_of_nodes / 10.0 * M_PI); + newy = 150.0 - 100.0 * cos(number_of_nodes / 10.0 * M_PI); + gnome_canvas_item_move(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item), newx - ((struct if_node_data*)(n->data))->x, newy - ((struct if_node_data*)(n->data))->y); + ((struct if_node_data*)(n->data))->x = newx; + ((struct if_node_data*)(n->data))->y = newy; + + for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next, i++) + { + if(!((struct if_node_data*)(((node_t*)(avlnode->data))->data))->visible) + continue; + + nodes[i] = (node_t *)(avlnode->data); + ((struct if_node_data*)(nodes[i]->data))->id = i; + } + number_of_nodes = i; + + gnome_canvas_item_show(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); + gnome_canvas_update_now(GNOME_CANVAS(canvas)); + + /* (Re)start calculations */ inited = 0; build_graph = 1; +} + +void if_node_invisible(const char *hooktype, va_list ap) +{ + int i; + avl_node_t *avlnode; + node_t *n = va_arg(ap, node_t*); + + if(!((struct if_node_data*)(n->data))->item) + return; + + if(!((struct if_node_data*)(n->data))->visible) + /* This node is already invisible */ + return; + + ((struct if_node_data*)(n->data))->visible = 0; + + for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next, i++) + { + if(!((struct if_node_data*)((node_t*)(avlnode->data))->data)->visible) + continue; + + nodes[i] = (node_t *)(avlnode->data); + ((struct if_node_data*)(nodes[i]->data))->id = i; + } + number_of_nodes = i; + + gnome_canvas_item_hide(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); + gnome_canvas_update_now(GNOME_CANVAS(canvas)); - return ctn; + /* (Re)start calculations */ + inited = 0; + build_graph = 1; } -void if_node_del(node_t *n) +void if_node_add(const char *hooktype, va_list ap) { + node_t *n = va_arg(ap, node_t*); + char *l[1]; + struct if_node_data *nd; + + if(!xml) + return; + + nd = xmalloc_and_zero(sizeof(*nd)); + l[0] = n->name; gtk_clist_freeze(GTK_CLIST(nodetree)); - if(n->host_ctn) - gtk_ctree_remove_node(GTK_CTREE(nodetree), n->host_ctn); - if(n->conn_ctn) - gtk_ctree_remove_node(GTK_CTREE(nodetree), n->conn_ctn); - if(n->subnet_ctn) - gtk_ctree_remove_node(GTK_CTREE(nodetree), n->subnet_ctn); + nd->ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), + hosts_ctn, NULL, l, 1, + NULL, NULL, NULL, NULL, + FALSE, FALSE); gtk_clist_thaw(GTK_CLIST(nodetree)); + gtk_ctree_node_set_row_data(GTK_CTREE(nodetree), nd->ctn, n); + + n->data = (void*)nd; + + if(canvas_visible) + { + if_node_create(n); + if_node_visible(hooktype, ap); + } } -void if_subnet_add(subnet_t *subnet) +void if_node_del(const char *hooktype, va_list ap) +{ + node_t *n = va_arg(ap, node_t*); + struct if_node_data *nd; + + nd = (struct if_node_data*)(n->data); + if(nd &&nd->ctn) + { + gtk_clist_freeze(GTK_CLIST(nodetree)); + gtk_ctree_remove_node(GTK_CTREE(nodetree), nd->ctn); + gtk_clist_thaw(GTK_CLIST(nodetree)); + } + + if(canvas_visible) + { + if_node_invisible(hooktype, ap); + } + + free(nd); + n->data = NULL; +} + +void if_subnet_add(const char *hooktype, va_list ap) { char *l[1]; - + subnet_t *subnet = va_arg(ap, subnet_t*); + struct if_subnet_data *sd; + GtkCTreeNode *parent; + + sd = xmalloc_and_zero(sizeof(*sd)); l[0] = net2str(subnet); + parent = subnet->owner->data ? + ((struct if_subnet_data*)(subnet->owner->data))->ctn + : NULL; + gtk_clist_freeze(GTK_CLIST(nodetree)); - gtk_ctree_insert_node(GTK_CTREE(nodetree), - subnets_ctn, NULL, l, 1, - NULL, NULL, NULL, NULL, - TRUE, FALSE); + sd->ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), + parent, NULL, l, 1, + NULL, NULL, NULL, NULL, + TRUE, FALSE); gtk_clist_thaw(GTK_CLIST(nodetree)); + gtk_ctree_node_set_row_data(GTK_CTREE(nodetree), sd->ctn, subnet); + + subnet->data = (void*)sd; } -void if_subnet_del(subnet_t *subnet) +void if_subnet_del(const char *hooktype, va_list ap) { + subnet_t *subnet = va_arg(ap, subnet_t*); + struct if_subnet_data *sd; + + sd = (struct if_subnet_data*)(subnet->data); + if(sd && sd->ctn) + { + gtk_clist_freeze(GTK_CLIST(nodetree)); + gtk_ctree_remove_node(GTK_CTREE(nodetree), sd->ctn); + gtk_clist_thaw(GTK_CLIST(nodetree)); + } + + free(sd); + subnet->data = NULL; } void redraw_edges(void) @@ -311,6 +1002,7 @@ void redraw_edges(void) GnomeCanvasPoints *points; avl_node_t *avlnode; edge_t *e; + struct if_node_data *fd, *td; if(edge_group) gtk_object_destroy(GTK_OBJECT(edge_group)); @@ -324,140 +1016,60 @@ void redraw_edges(void) for(avlnode = edge_tree->head; avlnode; avlnode = avlnode->next) { -/* char s[12]; */ e = (edge_t *)avlnode->data; + fd = (struct if_node_data*)(e->from.node->data); + td = (struct if_node_data*)(e->to.node->data); + +/* if(!e->from.node->status.visible || */ +/* !e->to.node->status.visible) */ +/* /\* We shouldn't draw this line *\/ */ +/* continue; */ points = gnome_canvas_points_new(2); - points->coords[0] = e->from.node->x; - points->coords[1] = e->from.node->y; - points->coords[2] = e->to.node->x; - points->coords[3] = e->to.node->y; + points->coords[0] = fd->x; + points->coords[1] = fd->y; + points->coords[2] = td->x; + points->coords[3] = td->y; gnome_canvas_item_new(group, gnome_canvas_line_get_type(), "points", points, - "fill_color_rgba", 0xe080c0ff, + "fill_color_rgba", 0xe080c080, "width_pixels", 2, NULL); gnome_canvas_points_unref(points); -/* snprintf(s, sizeof(s) - 1, "%d", e->weight); */ -/* gnome_canvas_item_new(group, */ -/* gnome_canvas_text_get_type(), */ -/* "x", (e->from.node->x + e->to.node->x) / 2, */ -/* "y", (e->from.node->y + e->to.node->y) / 2, */ -/* "text", s, */ -/* "anchor", GTK_ANCHOR_CENTER, */ -/* "fill_color", "black", */ -/* "font", "-*-verdana-medium-r-*-*-8-*-*-*-*-*-iso8859-1", */ -/* /\* "font", "fixed", *\/ */ -/* NULL); */ } + gnome_canvas_update_now(GNOME_CANVAS(canvas)); + edge_group = group; } -void if_edge_add(edge_t *e) +void if_edge_add(const char *hooktype, va_list ap) { redraw_edges(); - if_graph_add_edge(e); + inited = 0; build_graph = 1; - } -void if_edge_del(edge_t *e) +void if_edge_del(const char *hooktype, va_list ap) { redraw_edges(); + inited = 0; build_graph = 1; - -} - -void if_graph_add_node(node_t *n) -{ - GnomeCanvasGroup *group; - double newx, newy; - - if(!canvas) - if(!create_canvas()) - return; - - group = gnome_canvas_root(GNOME_CANVAS(canvas)); - group = GNOME_CANVAS_GROUP(gnome_canvas_item_new(group, - gnome_canvas_group_get_type(), - "x", 0.0, - "y", 0.0, - NULL)); - - gnome_canvas_item_new(group, gnome_canvas_ellipse_get_type(), - "x1", -30.0, - "y1", -08.0, - "x2", 30.0, - "y2", 08.0, - "fill_color_rgba", 0x5f9ea0ff, - "outline_color", "black", - "width_pixels", 0, - NULL); - - gnome_canvas_item_new(group, - gnome_canvas_text_get_type(), - "x", 0.0, - "y", 0.0, - "text", n->name, - "anchor", GTK_ANCHOR_CENTER, - "fill_color", "white", - "font", "-*-verdana-medium-r-*-*-10-*-*-*-*-*-iso8859-1", -/* "font", "fixed", */ - NULL); - - n->item = GNOME_CANVAS_ITEM(group); - gtk_object_set_user_data(GTK_OBJECT(group), (gpointer)n); - - /* TODO: Use this to get more detailed info on a node (For example - popup a dialog with more info, select the node in the left - pane, whatever.) */ - gtk_signal_connect(GTK_OBJECT(n->item), "event", (GtkSignalFunc) item_event, NULL); - - newx = 250.0 + 200.0 * sin(number_of_nodes / 10.0 * M_PI); - newy = 150.0 - 100.0 * cos(number_of_nodes / 10.0 * M_PI); -/* newx = (double)random() / (double)RAND_MAX * 300.0 + 100.0; */ -/* newy = (double)random() / (double)RAND_MAX * 200.0 + 50.0; */ - gnome_canvas_item_move(GNOME_CANVAS_ITEM(n->item), newx, newy); - n->x = newx; - n->y = newy; - - x[number_of_nodes] = newx; - y[number_of_nodes] = newy; - nodes[number_of_nodes] = n; - n->id = number_of_nodes; - - number_of_nodes++; - - gnome_canvas_update_now(GNOME_CANVAS(canvas)); } void if_move_node(node_t *n, double dx, double dy) { double newx, newy; - newx = n->x + dx; - newy = n->y + dy; - gnome_canvas_item_move(GNOME_CANVAS_ITEM(n->item), newx - n->x, newy - n->y); - n->x = newx; - n->y = newy; -} - -void if_graph_add_edge(edge_t *e) -{ -/* e->from.node->ifn->nat++; */ -/* e->to.node->ifn->nat++; */ - -/* avl_insert(e->from.node->ifn->attractors, e->to.node); */ -/* avl_insert(e->to.node->ifn->attractors, e->from.node); */ - - redraw_edges(); - - build_graph = 1; + newx = ((struct if_node_data*)(n->data))->x + dx; + newy = ((struct if_node_data*)(n->data))->y + dy; + gnome_canvas_item_move(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item), newx - ((struct if_node_data*)(n->data))->x, newy - ((struct if_node_data*)(n->data))->y); + ((struct if_node_data*)(n->data))->x = newx; + ((struct if_node_data*)(n->data))->y = newy; } #define X_MARGIN 50.0 @@ -470,22 +1082,21 @@ void set_zooming(void) int i; double minx, miny, maxx, maxy; static double ominx = 0.0, ominy = 0.0, omaxx = 0.0, omaxy = 0.0; - double ppu, ppux, ppuy; minx = miny = maxx = maxy = 0.0; for(i = 0; i < number_of_nodes; i++) { - if(nodes[i]->x < minx) - minx = nodes[i]->x; + if(((struct if_node_data*)(nodes[i]->data))->x < minx) + minx = ((struct if_node_data*)(nodes[i]->data))->x; else - if(nodes[i]->x > maxx) - maxx = nodes[i]->x; + if(((struct if_node_data*)(nodes[i]->data))->x > maxx) + maxx = ((struct if_node_data*)(nodes[i]->data))->x; - if(nodes[i]->y < miny) - miny = nodes[i]->y; + if(((struct if_node_data*)(nodes[i]->data))->y < miny) + miny = ((struct if_node_data*)(nodes[i]->data))->y; else - if(nodes[i]->y > maxy) - maxy = nodes[i]->y; + if(((struct if_node_data*)(nodes[i]->data))->y > maxy) + maxy = ((struct if_node_data*)(nodes[i]->data))->y; } if(minx > ominx - X_MARGIN_BUFFER && ominx > minx) @@ -508,6 +1119,7 @@ void set_zooming(void) /* gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), ppu); */ gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), minx - X_MARGIN, miny - Y_MARGIN, maxx + X_MARGIN, maxy + Y_MARGIN); + gnome_canvas_update_now(GNOME_CANVAS(canvas)); } double calculate_delta_m(int m) @@ -564,11 +1176,21 @@ void if_build_graph(void) { int i, j, p, max_i; double delta_m, max_delta_m; - double dx, dy, s, L, max_d, old_x, old_y; + double dx, dy, s, L, min_d, old_x, old_y; edge_t *e; + if(!keep_drawing) + return; + if(!inited) { + for(i = 0; i < number_of_nodes; i++) + { + x[i] = ((struct if_node_data*)(nodes[i]->data))->x; + y[i] = ((struct if_node_data*)(nodes[i]->data))->y; + } + + /* Initialize Floyd */ for(i = 0; i < number_of_nodes; i++) { d[i][i] = 0.0; @@ -581,6 +1203,8 @@ void if_build_graph(void) d[i][j] = d[j][i] = INFINITY; } } + + /* Floyd's shortest path algorithm */ for(i = 0; i < number_of_nodes; i++) { for(j = 0; j < number_of_nodes; j++) @@ -605,19 +1229,19 @@ void if_build_graph(void) } } - max_d = 0.0; + min_d = INFINITY; for(i = 0; i < number_of_nodes; i++) for(j = i + 1; j < number_of_nodes; j++) - if(d[i][j] > max_d && d[i][j] < INFINITY) - max_d = d[i][j]; + if(d[i][j] < min_d && d[i][j] > 0.0) + min_d = d[i][j]; - L = 300.0 / log(max_d); + L = 5.0 / sqrt(min_d + 1.0); for(i = 0; i < number_of_nodes; i++) { for(j = i + 1; j < number_of_nodes; j++) { - d[i][j] = d[j][i] = log(d[i][j]+1.0); + d[i][j] = d[j][i] = sqrt(d[i][j]+1.0); l[i][j] = l[j][i] = L * d[i][j]; k[i][j] = k[j][i] = K / (d[i][j] * d[i][j]); } @@ -639,7 +1263,10 @@ void if_build_graph(void) } if(max_delta_m <= epsilon) - build_graph = 0; + { + fprintf(stderr, "Graph building is done; max_delta_m = %f\n", max_delta_m); + build_graph = 0; + } else { int iter = 0, maxiter = 20;