NetworkInador/client-gtk/ni-window-interface.c

762 lines
30 KiB
C

/*
* ni-window-interface.c
* This file is part of NetworkInador
*
* Copyright (C) 2021 - Gatuno
*
* NetworkInador 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.
*
* NetworkInador 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 NetworkInador; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/if_addr.h>
#include <linux/if.h>
#include "ni-window-interface.h"
#include "ni-client.h"
#include "ni-interface.h"
#include "ni-ip.h"
#include "ni-ip-add-dialog.h"
struct _NIWindowInterfacePrivate {
NIInterface *ni_interface;
GtkWidget *vbox, *notebook;
GtkWidget *vbox_ipv4, *vbox_ipv6, *vbox_info;
GtkWidget *info_name, *info_updown, *info_mtu;
GtkWidget *button_name_apply, *button_name_revert;
GtkWidget *button_mtu_apply, *button_mtu_revert;
GtkWidget *button_up, *button_down;
GtkListStore *ipv4_store, *ipv6_store;
GtkWidget *del_ipv4_button, *del_ipv6_button;
GtkWidget *tree_ipv4, *tree_ipv6;
};
enum {
PROP_NI_INTERFACE = 1,
N_PROPERTIES
};
enum {
IP_STORE_COL_MAIN_IP,
IP_STORE_COL_BROADCAST,
IP_STORE_COL_OBJECT,
NUM_IP_STORE_COLS
};
static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface, NIIP *ni_ip);
void ni_window_interface_update_state_from_flags (NIWindowInterface *window_iface);
static void ni_window_interface_name_cancel_cb (GtkWidget *widget, gpointer data);
static void ni_window_interface_mtu_cancel_cb (GtkWidget *widget, gpointer data);
G_DEFINE_TYPE_WITH_PRIVATE (NIWindowInterface, ni_window_interface, GTK_TYPE_WINDOW)
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
#if 0
static GObject *ni_interface_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) {
GObject *obj;
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
NIInterface *ni_interface;
obj = parent_class->constructor (type, n_construct_properties, construct_properties);
ni_interface = NI_INTERFACE (obj);
{
int g;
for (g = 0; g < n_construct_properties; g++) {
GParamSpec *pspec = construct_properties[g].pspec;
GValue *value = construct_properties[g].value;
/* Manejar el valor */
if (strcmp (g_param_spec_get_name (pspec), "index") == 0) {
printf ("Estableciendo sobre el constructor, el index\n");
ni_interface->priv->index = g_value_get_uint (value);
ni_interface_check_and_connect_signal (ni_interface);
} else if (strcmp (g_param_spec_get_name (pspec), "ni-client") == 0) {
ni_interface->priv->ni_client = NI_CLIENT (g_value_get_object (value));
}
}
}
return obj;
}
#endif
static gboolean ni_window_interface_delete_event (GtkWidget *widget, GdkEventAny *event) {
/* Restaurar la caja original del nombre de la interfaz, si está cambiada */
ni_window_interface_name_cancel_cb (NULL, widget);
ni_window_interface_mtu_cancel_cb (NULL, widget);
return gtk_widget_hide_on_delete (widget);
}
static void has_ip_selected_v4_cb (GtkTreeSelection *selection, gpointer user_data) {
NIWindowInterface *window_iface = (NIWindowInterface *) user_data;
if (gtk_tree_selection_count_selected_rows (selection) > 0) {
gtk_widget_set_sensitive (window_iface->priv->del_ipv4_button, TRUE);
} else {
gtk_widget_set_sensitive (window_iface->priv->del_ipv4_button, FALSE);
}
}
static void has_ip_selected_v6_cb (GtkTreeSelection *selection, gpointer user_data) {
NIWindowInterface *window_iface = (NIWindowInterface *) user_data;
if (gtk_tree_selection_count_selected_rows (selection) > 0) {
gtk_widget_set_sensitive (window_iface->priv->del_ipv6_button, TRUE);
} else {
gtk_widget_set_sensitive (window_iface->priv->del_ipv6_button, FALSE);
}
}
static void ni_window_interface_addr_button_add_cb (GtkWidget *widget, int family, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
GtkWidget *dialog;
gint response;
NIClient *ni_client;
struct_addr addr, p2p_addr;
int prefix;
gboolean has_p2p;
uint32_t flags = 0;
dialog = ni_ip_add_dialog_new (family);
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window_iface));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if (response == GTK_RESPONSE_OK) {
/* Mandar la ip al network-inador */
ni_client = ni_interface_get_client (window_iface->priv->ni_interface);
ni_ip_add_dialog_get_address (NI_IP_ADD_DIALOG (dialog), &addr, &prefix);
has_p2p = ni_ip_add_dialog_has_p2p_address (NI_IP_ADD_DIALOG (dialog));
if (has_p2p) {
memcpy (&p2p_addr, &addr, sizeof (p2p_addr));
ni_ip_add_dialog_get_p2p_address (NI_IP_ADD_DIALOG (dialog), &addr);
}
flags |= IFA_F_PERMANENT;
if (ni_ip_add_dialog_get_noprefix (NI_IP_ADD_DIALOG (dialog))) {
flags |= IFA_F_NOPREFIXROUTE;
}
//void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int family, int prefix, struct_addr *addr, uint32_t flags, unsigned char scope, int has_local, struct_addr *local_addr, int has_brd, struct_addr *brd_addr) {
ni_client_ask_ip_new (ni_client, window_iface->priv->ni_interface, family, prefix, &addr, flags, 0, has_p2p, (has_p2p ? &p2p_addr : NULL), FALSE, NULL);
}
gtk_widget_destroy (dialog);
}
static void ni_window_interface_addr_button_del_cb (GtkWidget *widget, int family, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
NIIP *ni_ip;
if (family == AF_INET) {
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window_iface->priv->tree_ipv4));
} else if (family == AF_INET6) {
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window_iface->priv->tree_ipv6));
}
gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, IP_STORE_COL_OBJECT, &ni_ip, -1);
ni_client_ask_ip_delete (ni_interface_get_client (window_iface->priv->ni_interface), window_iface->priv->ni_interface, ni_ip);
}
static void ni_window_interface_addr_v4_button_add_cb (GtkWidget *widget, gpointer data) {
ni_window_interface_addr_button_add_cb (widget, AF_INET, data);
}
static void ni_window_interface_addr_v6_button_add_cb (GtkWidget *widget, gpointer data) {
ni_window_interface_addr_button_add_cb (widget, AF_INET6, data);
}
static void ni_window_interface_addr_v4_button_del_cb (GtkWidget *widget, gpointer data) {
ni_window_interface_addr_button_del_cb (widget, AF_INET, data);
}
static void ni_window_interface_addr_v6_button_del_cb (GtkWidget *widget, gpointer data) {
ni_window_interface_addr_button_del_cb (widget, AF_INET6, data);
}
/* Evento cuando cambian el nombre de la interfaz en el entry */
static void ni_window_interface_name_edit_cb (GtkEditable *editable, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
const gchar *original_name = ni_interface_get_name (window_iface->priv->ni_interface);
const gchar *current_name = gtk_entry_get_text (GTK_ENTRY (window_iface->priv->info_name));
if (current_name[0] == 0) {
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, TRUE);
} else if (strcmp (original_name, current_name) == 0) {
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, FALSE);
} else {
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, TRUE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, TRUE);
}
}
static void ni_window_interface_name_cancel_cb (GtkWidget *widget, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
gtk_entry_set_text (GTK_ENTRY (window_iface->priv->info_name), ni_interface_get_name (window_iface->priv->ni_interface));
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, FALSE);
}
static void ni_window_interface_name_apply_cb (GtkWidget *widget, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
const gchar *new_name;
if (gtk_widget_get_sensitive (window_iface->priv->button_name_apply) == FALSE) {
return;
}
new_name = gtk_entry_get_text (GTK_ENTRY (window_iface->priv->info_name));
ni_interface_set_name (window_iface->priv->ni_interface, new_name);
/* TODO: Activar el ícono de "cargando" en el entry
gtk_entry_set_icon_from_gicon (GTK_ENTRY (window_iface->priv->info_name), GTK_ENTRY_ICON_SECONDARY, */
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, FALSE);
}
/* Eventos cuando cambian el mtu */
static void ni_window_interface_mtu_edit_cb (GtkSpinButton *spin, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
guint original_mtu = ni_interface_get_mtu (window_iface->priv->ni_interface);
guint new_mtu = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (window_iface->priv->info_mtu));
if (new_mtu == 0) {
gtk_widget_set_sensitive (window_iface->priv->button_mtu_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_mtu_revert, TRUE);
} else if (new_mtu == original_mtu) {
gtk_widget_set_sensitive (window_iface->priv->button_mtu_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_mtu_revert, FALSE);
} else {
gtk_widget_set_sensitive (window_iface->priv->button_mtu_apply, TRUE);
gtk_widget_set_sensitive (window_iface->priv->button_mtu_revert, TRUE);
}
}
static void ni_window_interface_mtu_cancel_cb (GtkWidget *widget, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
gtk_spin_button_set_value (GTK_SPIN_BUTTON (window_iface->priv->info_mtu), ni_interface_get_mtu (window_iface->priv->ni_interface));
gtk_widget_set_sensitive (window_iface->priv->button_mtu_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_mtu_revert, FALSE);
}
static void ni_window_interface_mtu_apply_cb (GtkWidget *widget, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
guint new_mtu;
if (gtk_widget_get_sensitive (window_iface->priv->button_mtu_apply) == FALSE) {
return;
}
new_mtu = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (window_iface->priv->info_mtu));
ni_interface_set_mtu (window_iface->priv->ni_interface, new_mtu);
/* TODO: Activar el ícono de "cargando" en el entry
gtk_entry_set_icon_from_gicon (GTK_ENTRY (window_iface->priv->info_name), GTK_ENTRY_ICON_SECONDARY, */
gtk_widget_set_sensitive (window_iface->priv->button_mtu_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_mtu_revert, FALSE);
}
static void ni_window_interface_down_cb (GtkWidget *widget, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
ni_interface_set_down (window_iface->priv->ni_interface);
}
static void ni_window_interface_up_cb (GtkWidget *widget, gpointer data) {
NIWindowInterface *window_iface = (NIWindowInterface *) data;
ni_interface_set_up (window_iface->priv->ni_interface);
}
/* Eventos que vienen del network-inador */
static void ni_window_interface_addr_added_cb (NIWindowInterface *window_iface, NIIP *ni_ip) {
GtkTreeIter iter;
char buffer[256], ip[128], local[128];
guint prefix, family, family_size;
family = ni_ip_get_family (ni_ip);
inet_ntop (family, ni_ip_get_addr (ni_ip), ip, sizeof (ip));
prefix = ni_ip_get_prefix (ni_ip);
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
if (ni_ip_has_local (ni_ip) &&
memcmp (ni_ip_get_local_addr (ni_ip), ni_ip_get_addr (ni_ip), family_size) != 0) {
inet_ntop (family, ni_ip_get_local_addr (ni_ip), local, sizeof (local));
snprintf (buffer, sizeof (buffer), "%s peer %s/%u", local, ip, prefix);
} else {
snprintf (buffer, sizeof (buffer), "%s/%u", ip, prefix);
}
if (family == AF_INET) {
gtk_list_store_insert (window_iface->priv->ipv4_store, &iter, -1);
gtk_list_store_set (window_iface->priv->ipv4_store, &iter, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
} else if (family == AF_INET6) {
gtk_list_store_insert (window_iface->priv->ipv6_store, &iter, -1);
gtk_list_store_set (window_iface->priv->ipv6_store, &iter, IP_STORE_COL_MAIN_IP, buffer, IP_STORE_COL_OBJECT, ni_ip, -1);
}
}
static void ni_window_interface_new_ip_cb (NIInterface *ni_interface, NIIP *ni_ip, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
ni_window_interface_addr_added_cb (window_iface, ni_ip);
}
static void ni_window_interface_delete_ip_cb (NIInterface *ni_interface, NIIP *ni_ip, gpointer data) {
GtkTreeIter iter;
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
gboolean has;
guint family;
GtkListStore *p;
void *iter_obj;
family = ni_ip_get_family (ni_ip);
if (family == AF_INET) {
p = window_iface->priv->ipv4_store;
} else if (family == AF_INET6) {
p = window_iface->priv->ipv6_store;
}
has = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (p), &iter);
while (has) {
gtk_tree_model_get (GTK_TREE_MODEL (p), &iter, IP_STORE_COL_OBJECT, &iter_obj, -1);
if (iter_obj == ni_ip) {
/* Eliminar este objeto */
gtk_list_store_remove (p, &iter);
return;
}
has = gtk_tree_model_iter_next (GTK_TREE_MODEL (p), &iter);
}
}
static void ni_window_interface_changed_name_cb (GObject *object, GParamSpec *sp, gpointer data) {
NIInterface *ni_interface = NI_INTERFACE (object);
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
gchar *name;
/* Cambiar el título */
name = g_strdup_printf ("Interfaz %s", ni_interface_get_name (window_iface->priv->ni_interface));
gtk_window_set_title (GTK_WINDOW (window_iface), name);
/* Cambiar la label que corresponde al nombre */
gtk_entry_set_text (GTK_ENTRY (window_iface->priv->info_name), ni_interface_get_name (window_iface->priv->ni_interface));
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, FALSE);
g_free (name);
}
static void ni_window_interface_changed_flags_cb (GObject *object, GParamSpec *sp, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
ni_window_interface_update_state_from_flags (window_iface);
}
void ni_window_interface_update_state_from_flags (NIWindowInterface *window_iface) {
guint flags;
/* Recuperar las flags */
flags = ni_interface_get_flags (window_iface->priv->ni_interface);
if (flags & IFF_UP) {
gtk_widget_set_sensitive (window_iface->priv->info_name, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_apply, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_name_revert, FALSE);
gtk_entry_set_text (GTK_ENTRY (window_iface->priv->info_name), ni_interface_get_name (window_iface->priv->ni_interface));
gtk_label_set_text (GTK_LABEL (window_iface->priv->info_updown), "UP");
} else {
gtk_widget_set_sensitive (window_iface->priv->info_name, TRUE);
gtk_label_set_text (GTK_LABEL (window_iface->priv->info_updown), "DOWN");
}
}
/* Construcción del objeto */
static void ni_window_interface_constructed (GObject *obj) {
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (obj);
const GList *ip_list, *g;
NIIP *ni_ip;
gchar *name;
guint flags;
parent_class->constructed (obj);
if (window_iface->priv->ni_interface == NULL) return;
/* Cambiar el título */
name = g_strdup_printf ("Interfaz %s", ni_interface_get_name (window_iface->priv->ni_interface));
gtk_window_set_title (GTK_WINDOW (obj), name);
g_free (name);
/* TODO: Recorrer las ips, y procesar la información */
ip_list = ni_interface_get_ip_list (window_iface->priv->ni_interface);
for (g = ip_list; g != NULL; g = g->next) {
ni_ip = (NIIP *) g->data;
ni_window_interface_addr_added_cb (window_iface, ni_ip);
}
/* Conectar la señal de IP agregada y la señal de IP eliminada */
g_signal_connect (window_iface->priv->ni_interface, "new-ip", G_CALLBACK (ni_window_interface_new_ip_cb), window_iface);
g_signal_connect (window_iface->priv->ni_interface, "delete-ip", G_CALLBACK (ni_window_interface_delete_ip_cb), window_iface);
g_signal_connect (window_iface->priv->ni_interface, "notify::name", G_CALLBACK (ni_window_interface_changed_name_cb), window_iface);
g_signal_connect (window_iface->priv->ni_interface, "notify::flags", G_CALLBACK (ni_window_interface_changed_flags_cb), window_iface);
gtk_entry_set_text (GTK_ENTRY (window_iface->priv->info_name), ni_interface_get_name (window_iface->priv->ni_interface));
gtk_spin_button_set_value (GTK_SPIN_BUTTON (window_iface->priv->info_mtu), ni_interface_get_mtu(window_iface->priv->ni_interface));
ni_window_interface_update_state_from_flags (window_iface);
}
static void ni_window_interface_dispose (GObject *obj) {
NIWindowInterface *window_iface;
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
window_iface = NI_WINDOW_INTERFACE (obj);
g_object_unref (window_iface->priv->ni_interface);
window_iface->priv->ni_interface = NULL;
parent_class->dispose (obj);
}
#if 0
static void ni_window_interface_finalize (GObject *obj) {
NIWindowInterface *window_iface;
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
window_iface = NI_WINDOW_INTERFACE (obj);
/* Nada que hacer, por el momento */
parent_class->finalize (obj);
}
#endif
static void ni_window_interface_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (object);
g_return_if_fail (NI_IS_WINDOW_INTERFACE (object));
switch (prop_id) {
case PROP_NI_INTERFACE:
window_iface->priv->ni_interface = NI_INTERFACE (g_value_get_object (value));
g_object_ref (window_iface->priv->ni_interface);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void ni_window_interface_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (object);
g_return_if_fail (NI_IS_WINDOW_INTERFACE (object));
switch (prop_id) {
case PROP_NI_INTERFACE:
g_value_set_object (value, window_iface->priv->ni_interface);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void ni_window_interface_class_init (NIWindowInterfaceClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->set_property = ni_window_interface_set_property;
object_class->get_property = ni_window_interface_get_property;
object_class->constructed = ni_window_interface_constructed;
object_class->dispose = ni_window_interface_dispose;
widget_class->delete_event = ni_window_interface_delete_event;
obj_properties[PROP_NI_INTERFACE] = g_param_spec_object (
"ni-interface",
"Network Inador Client Interface",
"The interface object",
NI_TYPE_INTERFACE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
}
GtkWidget *ni_window_interface_create_tree (GtkListStore *store, GtkWidget **tree) {
GtkWidget *scrolled;
GtkAdjustment *h, *v;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
*tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree));
v = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree));
scrolled = gtk_scrolled_window_new (h, v);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Dirección", renderer, "text", IP_STORE_COL_MAIN_IP, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column);
gtk_container_add (GTK_CONTAINER (scrolled), *tree);
return scrolled;
}
static void ni_window_interface_init (NIWindowInterface *window_iface) {
NIWindowInterfacePrivate *priv = ni_window_interface_get_instance_private (window_iface);
window_iface->priv = priv;
GtkWindow *window = GTK_WINDOW (window_iface);
GtkWidget *hbox, *label, *button, *image;
GtkWidget *vbox, *scrolled, *vbox2;
GtkTreeSelection *selection;
GtkSizeGroup *size_l;
/* initialize all public and private members to reasonable default values.
* They are all automatically initialized to 0 to begin with. */
priv->ni_interface = NULL;
gtk_window_set_title (window, "Interfaz");
priv->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), priv->vbox);
priv->notebook = gtk_notebook_new ();
gtk_box_pack_start (GTK_BOX (priv->vbox), priv->notebook, TRUE, TRUE, 0);
/* Página de la información general de la interfaz */
priv->vbox_info = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
label = gtk_label_new ("Info");
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->vbox_info, label);
gtk_container_set_border_width (GTK_CONTAINER (priv->vbox_info), 5);
size_l = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
/* Poner las labels de información de la propia interfaz */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start (GTK_BOX (priv->vbox_info), hbox, FALSE, FALSE, 0);
label = gtk_label_new ("Interfaz name:");
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_size_group_add_widget (size_l, label);
priv->button_name_revert = gtk_button_new_from_icon_name ("view-refresh", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_sensitive (priv->button_name_revert, FALSE);
g_signal_connect (priv->button_name_revert, "clicked", G_CALLBACK (ni_window_interface_name_cancel_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_name_revert, FALSE, FALSE, 0);
priv->button_name_apply = gtk_button_new_from_icon_name ("document-save", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_sensitive (priv->button_name_apply, FALSE);
g_signal_connect (priv->button_name_apply, "clicked", G_CALLBACK (ni_window_interface_name_apply_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_name_apply, FALSE, FALSE, 0);
priv->info_name = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (priv->info_name), "<Desconocido>");
gtk_widget_set_sensitive (priv->info_name, FALSE);
g_signal_connect (priv->info_name, "changed", G_CALLBACK (ni_window_interface_name_edit_cb), window_iface);
g_signal_connect (priv->info_name, "activate", G_CALLBACK (ni_window_interface_name_apply_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->info_name, TRUE, TRUE, 0);
/* La botonera del MTU */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start (GTK_BOX (priv->vbox_info), hbox, FALSE, FALSE, 0);
label = gtk_label_new ("MTU:");
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_size_group_add_widget (size_l, label);
priv->button_mtu_revert = gtk_button_new_from_icon_name ("view-refresh", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_sensitive (priv->button_mtu_revert, FALSE);
g_signal_connect (priv->button_mtu_revert, "clicked", G_CALLBACK (ni_window_interface_mtu_cancel_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_mtu_revert, FALSE, FALSE, 0);
priv->button_mtu_apply = gtk_button_new_from_icon_name ("document-save", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_sensitive (priv->button_mtu_apply, FALSE);
g_signal_connect (priv->button_mtu_apply, "clicked", G_CALLBACK (ni_window_interface_mtu_apply_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_mtu_apply, FALSE, FALSE, 0);
/* TODO: Revisar el minimo y máximo del MTU */
priv->info_mtu = gtk_spin_button_new_with_range (1200, 9000, 10);
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (priv->info_mtu), 0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->info_mtu), 0);
g_signal_connect (priv->info_mtu, "value-changed", G_CALLBACK (ni_window_interface_mtu_edit_cb), window_iface);
g_signal_connect (priv->info_mtu, "activate", G_CALLBACK (ni_window_interface_mtu_apply_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->info_mtu, TRUE, TRUE, 0);
/* Las banderas de la intefaz */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start (GTK_BOX (priv->vbox_info), hbox, FALSE, FALSE, 0);
label = gtk_label_new ("Estado:");
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_size_group_add_widget (size_l, label);
priv->button_down = gtk_button_new_from_icon_name ("go-down", GTK_ICON_SIZE_BUTTON);
g_signal_connect (priv->button_down, "clicked", G_CALLBACK (ni_window_interface_down_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_down, FALSE, FALSE, 0);
priv->button_up = gtk_button_new_from_icon_name ("go-up", GTK_ICON_SIZE_BUTTON);
g_signal_connect (priv->button_up, "clicked", G_CALLBACK (ni_window_interface_up_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_up, FALSE, FALSE, 0);
priv->info_updown = gtk_label_new ("");
gtk_box_pack_end (GTK_BOX (hbox), priv->info_updown, FALSE, FALSE, 0);
/* Página de IPv4 */
priv->vbox_ipv4 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
label = gtk_label_new ("IPv4");
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->vbox_ipv4, label);
gtk_container_set_border_width (GTK_CONTAINER (priv->vbox_ipv4), 5);
/* Preparar el list store */
priv->ipv4_store = gtk_list_store_new (NUM_IP_STORE_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_box_pack_start (GTK_BOX (priv->vbox_ipv4), vbox, TRUE, TRUE, 5);
label = gtk_label_new ("Direcciones:");
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
scrolled = ni_window_interface_create_tree (priv->ipv4_store, &priv->tree_ipv4);
gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 0);
/* Botonera del tree view */
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
button = gtk_button_new_from_icon_name ("list-add", GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
g_signal_connect (button, "clicked", G_CALLBACK (ni_window_interface_addr_v4_button_add_cb), window_iface);
priv->del_ipv4_button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_box_pack_start (GTK_BOX (vbox2), priv->del_ipv4_button, FALSE, FALSE, 0);
g_signal_connect (priv->del_ipv4_button, "clicked", G_CALLBACK (ni_window_interface_addr_v4_button_del_cb), window_iface);
gtk_widget_set_sensitive (priv->del_ipv4_button, FALSE);
/* Conectar la señal de cambio de selección del tree view */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_ipv4));
g_signal_connect (selection, "changed", G_CALLBACK (has_ip_selected_v4_cb), window_iface);
/* Página de IPv6 */
priv->vbox_ipv6 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
label = gtk_label_new ("IPv6");
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->vbox_ipv6, label);
gtk_container_set_border_width (GTK_CONTAINER (priv->vbox_ipv6), 5);
/* Preparar el list store */
priv->ipv6_store = gtk_list_store_new (NUM_IP_STORE_COLS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_box_pack_start (GTK_BOX (priv->vbox_ipv6), vbox, TRUE, TRUE, 5);
label = gtk_label_new ("Direcciones:");
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
scrolled = ni_window_interface_create_tree (priv->ipv6_store, &priv->tree_ipv6);
gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 0);
/* Botonera del tree view */
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
button = gtk_button_new_from_icon_name ("list-add", GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
g_signal_connect (button, "clicked", G_CALLBACK (ni_window_interface_addr_v6_button_add_cb), window_iface);
priv->del_ipv6_button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_LARGE_TOOLBAR);
gtk_box_pack_start (GTK_BOX (vbox2), priv->del_ipv6_button, FALSE, FALSE, 0);
g_signal_connect (priv->del_ipv6_button, "clicked", G_CALLBACK (ni_window_interface_addr_v6_button_del_cb), window_iface);
gtk_widget_set_sensitive (priv->del_ipv6_button, FALSE);
/* Conectar la señal de cambio de selección del tree view */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_ipv6));
g_signal_connect (selection, "changed", G_CALLBACK (has_ip_selected_v6_cb), window_iface);
/* La botonera inferior */
hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
gtk_box_pack_start (GTK_BOX (priv->vbox), hbox, FALSE, FALSE, 0);
/* El boton de cerrar */
button = gtk_button_new_with_label ("Cerrar");
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_hide_on_delete), window);
image = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_BUTTON);
gtk_button_set_image (GTK_BUTTON (button), image);
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_widget_show_all (priv->vbox);
}
GtkWidget* ni_window_interface_new (NIInterface *ni_interface) {
NIWindowInterface *window_iface;
window_iface = g_object_new (NI_TYPE_WINDOW_INTERFACE, "type", GTK_WINDOW_TOPLEVEL, "ni-interface", ni_interface, NULL);
return GTK_WIDGET (window_iface);
}