#include #include #include "ni-client.h" #include "ni-interface.h" #include "ni-window-interface.h" #include "ni-window-route.h" #include "../src/link-types.h" enum { COL_IFACE_OBJECT, COL_IFACE_INDEX, COL_IFACE_NAME, COL_IFACE_ICON, COL_IFACE_WINDOW, NUM_COLS_IFACE, }; enum { INTERFACES_GROUP_ETHERNET, INTERFACES_GROUP_WIFI, INTERFACES_GROUP_BRIDGES, INTERFACES_GROUP_OTHER, INTERFACES_GROUP_LOOP_DUMMY, NUM_INTERFACES_GROUP }; typedef struct { int group_type; GtkWidget *vbox; GtkWidget *label; GtkWidget *iconview; GtkWidget *scrolled; GtkTreeModel *model_filter; } UINetworkType; const char *group_names[NUM_INTERFACES_GROUP] = { "Redes cableadas", "Redes inalámbricas", "Puentes", "Otros", "Loopback y otros tipos" }; GtkListStore *interfaces_store; NIClient *ni_client; GtkWidget *ventana; GtkWidget *main_vbox, *network_vbox; GtkWidget *empty_label = NULL; GHashTable *network_blocks_list; GtkWidget *create_bridge_menu; GtkWidget *route_v4_menu, *route_v6_menu; GtkWidget *route_v4_window = NULL, *route_v6_window = NULL; static void click_interface_cb (GtkIconView *iconview, GtkTreePath *path, gpointer data) { UINetworkType *network_block = (UINetworkType *) data; GtkTreeIter iter, real_iter; GtkWidget *ventana; NIInterface *ni_interface; gtk_tree_model_get_iter (GTK_TREE_MODEL (network_block->model_filter), &iter, path); gtk_tree_model_get (GTK_TREE_MODEL (network_block->model_filter), &iter, COL_IFACE_OBJECT, &ni_interface, COL_IFACE_WINDOW, &ventana, -1); if (ventana == NULL) { ventana = ni_window_interface_new (ni_interface); gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (network_block->model_filter), &real_iter, &iter); gtk_list_store_set (interfaces_store, &real_iter, COL_IFACE_WINDOW, ventana, -1); } gtk_widget_show (ventana); } static void click_open_route_table_v4 (GtkWidget *widget, gpointer data) { if (route_v4_window == NULL) { route_v4_window = ni_window_route_new (ni_client, AF_INET); } gtk_widget_show (route_v4_window); } static void click_open_route_table_v6 (GtkWidget *widget, gpointer data) { if (route_v6_window == NULL) { route_v6_window = ni_window_route_new (ni_client, AF_INET6); } gtk_widget_show (route_v6_window); } int guess_interface_type (NIInterface *ni_interface) { guint type; type = ni_interface_get_iface_type (ni_interface); if (type == NI_LINK_TYPE_ETHERNET) { return INTERFACES_GROUP_ETHERNET; } else if (type == NI_LINK_TYPE_WIFI) { return INTERFACES_GROUP_WIFI; } else if (type == NI_LINK_TYPE_DUMMY || type == NI_LINK_TYPE_LOOPBACK) { return INTERFACES_GROUP_LOOP_DUMMY; } else if (type == NI_LINK_TYPE_BRIDGE) { return INTERFACES_GROUP_BRIDGES; } return INTERFACES_GROUP_OTHER; } gboolean network_block_model_filter_by_type (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { NIInterface *ni_interface; const gchar *iface_type; UINetworkType *network_block = (UINetworkType *) data; gtk_tree_model_get (model, iter, COL_IFACE_OBJECT, &ni_interface, -1); if (ni_interface == NULL) { return FALSE; } //iface_type = ni_interface_get_iface_type (ni_interface); if (guess_interface_type (ni_interface) == network_block->group_type) { return TRUE; } return FALSE; } UINetworkType * create_block_list (int type) { UINetworkType *network_block; int g, pos; if (g_hash_table_size (network_blocks_list) == 0) { /* Eliminar la etiqueta */ gtk_widget_destroy (empty_label); } network_block = g_new0 (UINetworkType, 1); network_block->group_type = type; network_block->model_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (interfaces_store), NULL); printf ("Para el group type: %i, el model_filter: %p\n", type, network_block->model_filter); gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (network_block->model_filter), network_block_model_filter_by_type, network_block, NULL); network_block->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); gtk_box_pack_start (GTK_BOX (network_vbox), network_block->vbox, FALSE, FALSE, 5); /* Reordenar los grupos presentes, dentro del vbox */ pos = 0; for (g = 0; g < NUM_INTERFACES_GROUP && g < type; g++) { if (g_hash_table_lookup (network_blocks_list, GINT_TO_POINTER (g)) != NULL) { pos++; } } gtk_box_reorder_child (GTK_BOX (network_vbox), network_block->vbox, pos); network_block->label = gtk_label_new (group_names [type]); gtk_box_pack_start (GTK_BOX (network_block->vbox), network_block->label, FALSE, FALSE, 0); network_block->iconview = gtk_icon_view_new_with_model (network_block->model_filter); g_signal_connect (network_block->iconview, "item-activated", G_CALLBACK (click_interface_cb), network_block); gtk_icon_view_set_text_column (GTK_ICON_VIEW (network_block->iconview), COL_IFACE_NAME); gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (network_block->iconview), COL_IFACE_ICON); //gtk_icon_view_set_columns (GTK_ICON_VIEW (network_block->iconview), 1000); gtk_icon_view_set_reorderable (GTK_ICON_VIEW (network_block->iconview), FALSE); network_block->scrolled = gtk_scrolled_window_new ( gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (network_block->iconview)), gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (network_block->iconview))); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (network_block->scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (network_block->scrolled), network_block->iconview); gtk_box_pack_start (GTK_BOX (network_block->vbox), network_block->scrolled, FALSE, FALSE, 0); gtk_widget_show_all (network_block->vbox); return network_block; } gboolean locate_interface_from_store (GtkListStore *store, GtkTreeIter *iter, guint index) { gboolean has; guint index_data; has = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter); while (has) { gtk_tree_model_get (GTK_TREE_MODEL (interfaces_store), iter, COL_IFACE_INDEX, &index_data, -1); if (index == index_data) { return TRUE; } has = gtk_tree_model_iter_next (GTK_TREE_MODEL (interfaces_store), iter); } return FALSE; } static void interface_changed_name_cb (GObject *object, GParamSpec *sp, gpointer data) { NIInterface *ni_interface = NI_INTERFACE (object); guint index; GtkTreeIter iter; index = ni_interface_get_index (ni_interface); if (locate_interface_from_store (interfaces_store, &iter, index)) { gtk_list_store_set (interfaces_store, &iter, COL_IFACE_NAME, ni_interface_get_name (ni_interface), -1); } } void new_interface_cb (NIClient *ni_client, NIInterface *ni_interface, gpointer data) { guint index; UINetworkType *network_block; int type; GdkPixbuf *icon; GtkTreeIter iter; type = guess_interface_type (ni_interface); network_block = g_hash_table_lookup (network_blocks_list, GINT_TO_POINTER (type)); if (network_block == NULL) { /* El bloque está vacio, pedir crearlo */ network_block = create_block_list (type); g_hash_table_insert (network_blocks_list, GINT_TO_POINTER (type), network_block); } if (type == INTERFACES_GROUP_ETHERNET) { icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "network-wired", 32, 0, NULL); } else { icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "network-wired", 32, 0, NULL); } gtk_list_store_insert (interfaces_store, &iter, -1); gtk_list_store_set (interfaces_store, &iter, COL_IFACE_OBJECT, ni_interface, COL_IFACE_INDEX, ni_interface_get_index (ni_interface), COL_IFACE_NAME, ni_interface_get_name (ni_interface), COL_IFACE_ICON, icon, COL_IFACE_WINDOW, NULL, -1); g_signal_connect (ni_interface, "notify::name", G_CALLBACK (interface_changed_name_cb), NULL); g_object_unref (icon); } void delete_interface_cb (NIClient *ni_client, NIInterface *ni_interface, gpointer data) { GtkWidget *ventana; GtkTreeIter iter; if (locate_interface_from_store (interfaces_store, &iter, ni_interface_get_index (ni_interface))) { gtk_tree_model_get (GTK_TREE_MODEL (interfaces_store), &iter, COL_IFACE_WINDOW, &ventana, -1); /* Eliminar este objeto */ if (ventana != NULL) { gtk_widget_destroy (ventana); } gtk_list_store_remove (interfaces_store, &iter); } } void create_bridge_cb (GtkWidget *menu_item, gpointer data) { static GtkWidget *dialog = NULL; GtkWidget *content; GtkWidget *label, *entry; guint res; gchar *name; if (dialog != NULL) { gtk_window_present (GTK_WINDOW (dialog)); return; } dialog = gtk_message_dialog_new (GTK_WINDOW (ventana), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, "Nombre del nuevo bridge"); content = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog)); entry = gtk_entry_new (); gtk_entry_set_text (GTK_ENTRY (entry), "br0"); gtk_box_pack_start (GTK_BOX (content), entry, FALSE, FALSE, 0); gtk_widget_show (entry); res = gtk_dialog_run (GTK_DIALOG (dialog)); if (res == GTK_RESPONSE_OK) { name = gtk_entry_get_text (GTK_ENTRY (entry)); if (name != NULL && name[0] != 0) { ni_client_ask_create_bridge (ni_client, name); } } gtk_widget_destroy (dialog); dialog = NULL; } void cerrar_ventana_cb (GtkWidget *ventana, gpointer data) { g_object_unref (ni_client); gtk_main_quit (); } int main (int argc, char *argv[]) { gboolean connected; GtkWidget *label, *scrolled; GtkWidget *menu_bar, *menu, *menu_item; GtkWidget *icon; gtk_init (&argc, &argv); ni_client = ni_client_new (); connected = ni_client_connect (ni_client); g_signal_connect (ni_client, "new-interface", G_CALLBACK (new_interface_cb), NULL); g_signal_connect (ni_client, "delete-interface", G_CALLBACK (delete_interface_cb), NULL); interfaces_store = gtk_list_store_new (NUM_COLS_IFACE, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER); network_blocks_list = g_hash_table_new (g_direct_hash, g_direct_equal); ventana = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (ventana), "Interfaces"); gtk_window_set_default_size (GTK_WINDOW (ventana), 640, 480); g_signal_connect (ventana, "destroy", G_CALLBACK (cerrar_ventana_cb), NULL); main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); gtk_container_add (GTK_CONTAINER (ventana), main_vbox); menu_bar = gtk_menu_bar_new (); gtk_box_pack_start (GTK_BOX (main_vbox), menu_bar, FALSE, FALSE, 0); menu_item = gtk_menu_item_new_with_mnemonic ("_Interfaces"); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item); menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu); create_bridge_menu = gtk_image_menu_item_new_with_mnemonic ("Crear _bridge"); if (connected == FALSE) { gtk_widget_set_sensitive (create_bridge_menu, FALSE); } icon = gtk_image_new_from_icon_name ("list-add", GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (create_bridge_menu), icon); gtk_menu_shell_append (GTK_MENU_SHELL (menu), create_bridge_menu); gtk_widget_show_all (create_bridge_menu); g_signal_connect (create_bridge_menu, "activate", G_CALLBACK (create_bridge_cb), NULL); gtk_widget_show_all (menu); /* Menú de las tablas de ruteo */ menu_item = gtk_menu_item_new_with_mnemonic ("Tablas de _ruteo"); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menu_item); menu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu); /* La tabla de ruteo de IPv4 */ route_v4_menu = gtk_image_menu_item_new_with_mnemonic ("Tabla de IPv_4"); if (connected == FALSE) { gtk_widget_set_sensitive (route_v4_menu, FALSE); } gtk_menu_shell_append (GTK_MENU_SHELL (menu), route_v4_menu); g_signal_connect (route_v4_menu, "activate", G_CALLBACK (click_open_route_table_v4), NULL); /* La tabla de ruteo de IPv6 */ route_v6_menu = gtk_image_menu_item_new_with_mnemonic ("Tabla de IPv_6"); if (connected == FALSE) { gtk_widget_set_sensitive (route_v6_menu, FALSE); } gtk_menu_shell_append (GTK_MENU_SHELL (menu), route_v6_menu); g_signal_connect (route_v6_menu, "activate", G_CALLBACK (click_open_route_table_v6), NULL); gtk_widget_show_all (menu); /* El resto de la interfaz */ scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); gtk_box_pack_start (GTK_BOX (main_vbox), scrolled, TRUE, TRUE, 0); network_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_widget_set_size_request (network_vbox, 260, -1); gtk_container_add (GTK_CONTAINER (scrolled), network_vbox); if (connected == FALSE) { empty_label = gtk_label_new ("El servicio del network inador no está corriendo\n"); } else { empty_label = gtk_label_new ("Recuperando información...\n"); } gtk_box_pack_start (GTK_BOX (network_vbox), empty_label, TRUE, TRUE, 0); gtk_widget_show_all (ventana); gtk_main (); return 0; }