NetworkInador/client-gtk/main.c

347 lines
11 KiB
C
Raw Normal View History

#include <gtk/gtk.h>
#include <linux/if_arp.h>
#include "ni-client.h"
#include "ni-interface.h"
#include "ni-window-interface.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;
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);
}
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);
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;
}