/* * ni-interface-chooser-dialog.c * This file is part of Network Inador * * Copyright (C) 2021 - Gatuno * * Network Inador 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. * * Network Inador 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 Network Inador; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "ni-interface-chooser-dialog.h" #include "ni-client.h" #include "ni-interface.h" #include "ni-interface-filter.h" #include "network-inador-link-types.h" enum { COL_INTERFACE_CHOOSER_NAME, COL_INTERFACE_CHOOSER_SENSITIVE, COL_INTERFACE_CHOOSER_INDEX, NUM_INTERFACE_CHOOSER_COLS }; struct _NIInterfaceChooserDialogPrivate { NIClient *ni_client; int order; gboolean group; GtkListStore *store; GtkWidget *combo; GtkWidget *button_add; NIInterfaceFilter *filter; }; enum { PROP_ORDER = 1, PROP_GROUP, PROP_NI_CLIENT, N_PROPERTIES }; G_DEFINE_TYPE_WITH_PRIVATE (NIInterfaceChooserDialog, ni_interface_chooser_dialog, GTK_TYPE_DIALOG) static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; #if 0 static void ni_ip_add_dialog_update_response (NIInterfaceChooserDialog *dialog) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_p2p)) && dialog->priv->valid_p2p_ip == FALSE) { gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); return; } if (dialog->priv->valid_main_ip == FALSE) { gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE); return; } gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE); } #endif static void ni_interface_chooser_dialog_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NIInterfaceChooserDialog *dialog = NI_INTERFACE_CHOOSER_DIALOG (object); g_return_if_fail (NI_IS_INTERFACE_CHOOSER_DIALOG (object)); switch (prop_id) { case PROP_ORDER: dialog->priv->order = g_value_get_uint (value); break; case PROP_GROUP: dialog->priv->group = g_value_get_boolean (value); break; case PROP_NI_CLIENT: dialog->priv->ni_client = NI_CLIENT (g_value_get_object (value)); g_object_ref (dialog->priv->ni_client); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ni_interface_chooser_dialog_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NIInterfaceChooserDialog *dialog = NI_INTERFACE_CHOOSER_DIALOG (object); g_return_if_fail (NI_IS_INTERFACE_CHOOSER_DIALOG (object)); switch (prop_id) { case PROP_ORDER: g_value_set_uint (value, dialog->priv->order); break; case PROP_GROUP: g_value_set_boolean (value, dialog->priv->group); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static gint ni_interface_chooser_order_by_name (NIInterface *a, NIInterface *b) { return g_strcmp0 (ni_interface_get_name (a), ni_interface_get_name (b)); } static gint ni_interface_chooser_order_by_index (NIInterface *a, NIInterface *b) { return ni_interface_get_index (a) - ni_interface_get_index (b); } static gint ni_interface_chooser_order_by_type (NIInterface *a, NIInterface *b) { guint at, bt; at = ni_interface_get_iface_type (a); bt = ni_interface_get_iface_type (b); if (at == bt) { return ni_interface_chooser_order_by_name (a, b); } else if (at < bt) { return -1; } else { return 1; } } static const char * ni_interface_chooser_guess_interface_type (guint type) { if (type == NI_LINK_TYPE_ETHERNET) { return "Redes cableadas"; } else if (type == NI_LINK_TYPE_WIFI) { return "Redes inalámbricas"; } else if (type == NI_LINK_TYPE_DUMMY || type == NI_LINK_TYPE_LOOPBACK) { return "Loopback y otros tipos"; } else if (type == NI_LINK_TYPE_BRIDGE) { return "Puentes"; } return "Otros"; } static void ni_interface_chooser_refilter_all (NIInterfaceChooserDialog *dialog) { GList *all_interfaces, *g; NIInterface *interface; guint last_type = 0, iface_type, index, master, previous_index, c; const gchar *name; GtkTreeIter iter; NIInterfaceFilterInfo filter_info; previous_index = -1; if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->combo), &iter)) { gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->store), &iter, COL_INTERFACE_CHOOSER_INDEX, &previous_index, -1); } gtk_list_store_clear (dialog->priv->store); all_interfaces = ni_client_get_list_interfaces (dialog->priv->ni_client); /* Aplicar el ordenamiento primero */ switch (dialog->priv->order) { case NI_INTERFACE_CHOOSER_ORDER_INDEX: all_interfaces = g_list_sort (all_interfaces, (GCompareFunc) ni_interface_chooser_order_by_index); break; case NI_INTERFACE_CHOOSER_ORDER_NAME: all_interfaces = g_list_sort (all_interfaces, (GCompareFunc) ni_interface_chooser_order_by_name); break; case NI_INTERFACE_CHOOSER_ORDER_TYPE: all_interfaces = g_list_sort (all_interfaces, (GCompareFunc) ni_interface_chooser_order_by_type); break; } c = 0; for (g = all_interfaces; g != NULL; g = g->next) { interface = (NIInterface *) g->data; iface_type = ni_interface_get_iface_type (interface); index = ni_interface_get_index (interface); name = ni_interface_get_name (interface); master = ni_interface_get_master (interface); /* Ejecutar el filtro */ if (dialog->priv->filter != NULL) { filter_info.index = index; filter_info.name = name; filter_info.type = iface_type; filter_info.master = master; if (ni_interface_filter_filter (dialog->priv->filter, &filter_info) == FALSE) continue; } if (dialog->priv->group && last_type != iface_type) { /* Crear el item dummy nulo */ gtk_list_store_append (dialog->priv->store, &iter); gtk_list_store_set (dialog->priv->store, &iter, COL_INTERFACE_CHOOSER_NAME, ni_interface_chooser_guess_interface_type (iface_type), COL_INTERFACE_CHOOSER_SENSITIVE, FALSE, COL_INTERFACE_CHOOSER_INDEX, 0, -1); last_type = iface_type; continue; } gtk_list_store_append (dialog->priv->store, &iter); gtk_list_store_set (dialog->priv->store, &iter, COL_INTERFACE_CHOOSER_NAME, name, COL_INTERFACE_CHOOSER_SENSITIVE, TRUE, COL_INTERFACE_CHOOSER_INDEX, index, -1); c++; if (previous_index != -1 && index == previous_index) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->combo), &iter); } } if (previous_index == -1 && gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->priv->combo)) == -1 && c > 0) { gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->combo), 0); } } void ni_interface_chooser_dialog_set_filter (NIInterfaceChooserDialog *dialog, NIInterfaceFilter *filter) { NIInterfaceFilter *old_filter; g_return_if_fail (NI_IS_INTERFACE_CHOOSER_DIALOG (dialog)); g_return_if_fail (filter == NULL || NI_IS_INTERFACE_FILTER (filter)); if (filter) { g_object_ref (filter); } old_filter = dialog->priv->filter; dialog->priv->filter = filter; if (old_filter) { g_object_unref (old_filter); } ni_interface_chooser_refilter_all (dialog); } static void ni_interface_chooser_dialog_changed_interface_cb (NIClient *ni_client, NIInterface *iface, gpointer data) { NIInterfaceChooserDialog *dialog = NI_INTERFACE_CHOOSER_DIALOG (data); ni_interface_chooser_refilter_all (dialog); } /* Construcción del objeto */ static void ni_interface_chooser_dialog_constructed (GObject *obj) { GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_DIALOG)); NIInterfaceChooserDialog *dialog = NI_INTERFACE_CHOOSER_DIALOG (obj); const GList *tmp_list, *g; NIInterface *ni_interface; gchar *name; guint flags; parent_class->constructed (obj); if (dialog->priv->ni_client == NULL) return; /* Conectar la señal de IP agregada y la señal de IP eliminada */ g_signal_connect (dialog->priv->ni_client, "new-interface", G_CALLBACK (ni_interface_chooser_dialog_changed_interface_cb), dialog); g_signal_connect (dialog->priv->ni_client, "delete-interface", G_CALLBACK (ni_interface_chooser_dialog_changed_interface_cb), dialog); ni_interface_chooser_refilter_all (dialog); } static void ni_interface_chooser_dialog_dispose (GObject *obj) { NIInterfaceChooserDialog *dialog; GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_DIALOG)); dialog = NI_INTERFACE_CHOOSER_DIALOG (obj); if (dialog->priv->ni_client != NULL) { g_object_unref (dialog->priv->ni_client); dialog->priv->ni_client = NULL; } if (dialog->priv->filter != NULL) { g_object_unref (dialog->priv->filter); dialog->priv->filter = NULL; } parent_class->dispose (obj); } static void ni_interface_chooser_dialog_class_init (NIInterfaceChooserDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass); object_class->set_property = ni_interface_chooser_dialog_set_property; object_class->get_property = ni_interface_chooser_dialog_get_property; object_class->constructed = ni_interface_chooser_dialog_constructed; object_class->dispose = ni_interface_chooser_dialog_dispose; obj_properties[PROP_ORDER] = g_param_spec_uint ( "order", "Order of the interfaces", "Order to show the interfaces", 0, 10, NI_INTERFACE_CHOOSER_ORDER_INDEX, G_PARAM_READWRITE); obj_properties[PROP_GROUP] = g_param_spec_boolean ( "group", "Group or not the interfaces", "If interfaces should be grouped on dialog", FALSE, G_PARAM_READWRITE); obj_properties[PROP_NI_CLIENT] = g_param_spec_object ( "ni-client", "Network Inador Client", "The client object", NI_TYPE_CLIENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties); } static void ni_interface_chooser_dialog_init (NIInterfaceChooserDialog *dialog) { NIInterfaceChooserDialogPrivate *priv = ni_interface_chooser_dialog_get_instance_private (dialog); GtkWidget *image; GtkWidget *vbox, *expander; GtkWidget *container, *label, *hbox; GtkCellRenderer *render; dialog->priv = priv; priv->order = NI_INTERFACE_CHOOSER_ORDER_INDEX; priv->group = FALSE; priv->ni_client = NULL; priv->filter = NULL; gtk_window_set_title (GTK_WINDOW (dialog), "Elija una interfaz"); gtk_dialog_add_button (GTK_DIALOG (dialog), "Cancelar", GTK_RESPONSE_CANCEL); priv->button_add = gtk_dialog_add_button (GTK_DIALOG (dialog), "Seleccionar", GTK_RESPONSE_OK); container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); gtk_box_pack_start (GTK_BOX (container), vbox, TRUE, TRUE, 0); label = gtk_label_new ("Seleccione una interfaz:"); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 5); /* Preparar el store box */ priv->store = gtk_list_store_new (NUM_INTERFACE_CHOOSER_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT); priv->combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->store)); render = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->combo), render, TRUE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->combo), render, "markup", COL_INTERFACE_CHOOSER_NAME, "sensitive", COL_INTERFACE_CHOOSER_SENSITIVE, NULL); gtk_box_pack_start (GTK_BOX (vbox), priv->combo, FALSE, FALSE, 5); gtk_widget_show_all (container); } guint ni_interface_chooser_dialog_get_index (NIInterfaceChooserDialog *dialog) { GtkTreeIter iter; guint index; if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->combo), &iter) == FALSE) { return 0; } gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->store), &iter, COL_INTERFACE_CHOOSER_INDEX, &index, -1); return index; } GtkWidget* ni_interface_chooser_dialog_new (NIClient *ni_client) { NIInterfaceChooserDialog *dialog; dialog = g_object_new (NI_TYPE_INTERFACE_CHOOSER_DIALOG, "ni-client", ni_client, NULL); return GTK_WIDGET (dialog); }