static gboolean validate (CEPage *page, NMConnection *connection, GError **error) { if (!ui_to_setting (CE_PAGE_IP4 (page))) return FALSE; return nm_setting_verify (NM_SETTING (CE_PAGE_IP4 (page)->setting), NULL, error); }
static void change_method_combo (CEPage *page, gboolean is_hotspot) { CEPageIP4 *self = CE_PAGE_IP4 (page); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); /* Store previous active method */ if (get_method_sensitivity (page, IP4_METHOD_AUTO)) priv->normal_method_idx = gtk_combo_box_get_active (priv->method); else priv->hotspot_method_idx = gtk_combo_box_get_active (priv->method); /* Set active method */ if (is_hotspot) { if (priv->hotspot_method_idx == -1) { int method = IP4_METHOD_SHARED; if (g_strcmp0 (nm_setting_ip_config_get_method (priv->setting), NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) method = IP4_METHOD_DISABLED; gtk_combo_box_set_active (priv->method, method); } else gtk_combo_box_set_active (priv->method, priv->hotspot_method_idx); } else { if (priv->normal_method_idx != -1) gtk_combo_box_set_active (priv->method, priv->normal_method_idx); } toggle_method_sensitivity (page, IP4_METHOD_AUTO, !is_hotspot); toggle_method_sensitivity (page, IP4_METHOD_AUTO_ADDRESSES, !is_hotspot); toggle_method_sensitivity (page, IP4_METHOD_MANUAL, !is_hotspot); toggle_method_sensitivity (page, IP4_METHOD_LINK_LOCAL, !is_hotspot); }
static gboolean tree_view_button_pressed_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); /* last_edited can be set e.g. when we get here by clicking an cell while * editing another cell. GTK3 issue neither editing-canceled nor editing-done * for cell renderer. Thus the previous cell value isn't saved. Store it now. */ if (priv->last_edited && priv->last_path) { GtkTreeIter iter; GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (priv->addr_list)); GtkTreePath *last_treepath = gtk_tree_path_new_from_string (priv->last_path); gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, last_treepath); gtk_list_store_set (store, &iter, priv->last_column, priv->last_edited, -1); gtk_tree_path_free (last_treepath); g_free (priv->last_edited); priv->last_edited = NULL; g_free (priv->last_path); priv->last_path = NULL; priv->last_column = -1; } /* Ignore double clicks events. (They are issued after the single clicks, see GdkEventButton) */ if (event->type == GDK_2BUTTON_PRESS) return TRUE; gtk_widget_grab_focus (GTK_WIDGET (priv->addr_list)); return FALSE; }
static void cell_editing_canceled (GtkCellRenderer *renderer, gpointer user_data) { CEPageIP4 *self; CEPageIP4Private *priv; GtkTreeModel *model = NULL; GtkTreeSelection *selection; GtkTreeIter iter; guint32 column; /* user_data disposed? */ if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (renderer), "ce-page-not-valid"))) return; self = CE_PAGE_IP4 (user_data); priv = CE_PAGE_IP4_GET_PRIVATE (self); if (priv->last_edited) { selection = gtk_tree_view_get_selection (priv->addr_list); if (gtk_tree_selection_get_selected (selection, &model, &iter)) { column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (renderer), "column")); gtk_list_store_set (GTK_LIST_STORE (model), &iter, column, priv->last_edited, -1); } g_free (priv->last_edited); priv->last_edited = NULL; ce_page_changed (CE_PAGE (self)); } g_free (priv->last_path); priv->last_path = NULL; priv->last_column = -1; }
static void cell_edited (GtkCellRendererText *cell, const gchar *path_string, const gchar *new_text, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (priv->addr_list)); GtkTreePath *path = gtk_tree_path_new_from_string (path_string); GtkTreeIter iter; guint32 column; GtkTreeViewColumn *next_col; column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cell), "column")); gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path); gtk_list_store_set (store, &iter, column, new_text, -1); /* Move focus to the next column */ column = (column >= COL_LAST) ? 0 : column + 1; next_col = gtk_tree_view_get_column (priv->addr_list, column); gtk_tree_view_set_cursor_on_cell (priv->addr_list, path, next_col, priv->addr_cells[column], TRUE); gtk_widget_grab_focus (GTK_WIDGET (priv->addr_list)); gtk_tree_path_free (path); ce_page_changed (CE_PAGE (self)); }
static gboolean ce_page_validate_v (CEPage *page, NMConnection *connection, GError **error) { CEPageIP4 *self = CE_PAGE_IP4 (page); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); if (!ui_to_setting (self, error)) return FALSE; return nm_setting_verify (NM_SETTING (priv->setting), NULL, error); }
static void routes_dialog_response_cb (GtkWidget *dialog, gint response, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); if (response == GTK_RESPONSE_OK) ip4_routes_dialog_update_setting (dialog, priv->setting); routes_dialog_close_cb (dialog, NULL); }
static void toggle_method_sensitivity (CEPage *page, int column, gboolean sensitive) { CEPageIP4 *self = CE_PAGE_IP4 (page); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); GtkTreeModel *model = GTK_TREE_MODEL (priv->method_store); GtkTreeIter iter; if (get_iter_for_method (model, column, &iter)) gtk_list_store_set (priv->method_store, &iter, METHOD_COL_ENABLED, sensitive, -1); }
CEPage * ce_page_ip4_new (NMConnection *connection, GtkWindow *parent_window, GError **error) { CEPageIP4 *self; CEPageIP4Private *priv; CEPage *parent; NMSettingConnection *s_con; self = CE_PAGE_IP4 (g_object_new (CE_TYPE_PAGE_IP4, CE_PAGE_CONNECTION, connection, CE_PAGE_PARENT_WINDOW, parent_window, NULL)); parent = CE_PAGE (self); parent->xml = glade_xml_new (GLADEDIR "/ce-page-ip4.glade", "IP4Page", NULL); if (!parent->xml) { g_set_error (error, 0, 0, "%s", _("Could not load IPv4 user interface.")); g_object_unref (self); return NULL; } parent->page = glade_xml_get_widget (parent->xml, "IP4Page"); if (!parent->page) { g_set_error (error, 0, 0, "%s", _("Could not load IPv4 user interface.")); g_object_unref (self); return NULL; } g_object_ref_sink (parent->page); parent->title = g_strdup (_("IPv4 Settings")); ip4_private_init (self, connection); priv = CE_PAGE_IP4_GET_PRIVATE (self); priv->window_group = gtk_window_group_new (); s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); g_assert (s_con); priv->connection_id = g_strdup (nm_setting_connection_get_id (s_con)); priv->setting = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); if (!priv->setting) { priv->setting = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ()); nm_connection_add_setting (connection, NM_SETTING (priv->setting)); } g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL); if (!ce_page_initialize (parent, NULL, error)) { g_object_unref (self); return NULL; } return CE_PAGE (self); }
static void delete_text_cb (GtkEditable *editable, gint start_pos, gint end_pos, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); /* Keep last_edited up-to-date */ g_free (priv->last_edited); priv->last_edited = gtk_editable_get_chars (editable, 0, -1); }
static gboolean get_method_sensitivity (CEPage *page, int column) { CEPageIP4 *self = CE_PAGE_IP4 (page); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); GtkTreeModel *model = GTK_TREE_MODEL (priv->method_store); GtkTreeIter iter; gboolean sensitive = FALSE; if (get_iter_for_method (model, column, &iter)) gtk_tree_model_get (GTK_TREE_MODEL (priv->method_store), &iter, METHOD_COL_ENABLED, &sensitive, -1); return sensitive; }
static void dispose (GObject *object) { CEPageIP4 *self = CE_PAGE_IP4 (object); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); if (priv->window_group) g_object_unref (priv->window_group); g_free (priv->connection_id); G_OBJECT_CLASS (ce_page_ip4_parent_class)->dispose (object); }
static void cell_editing_started (GtkCellRenderer *cell, GtkCellEditable *editable, const gchar *path, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); GtkTreeModel *model; GtkTreeIter iter; AddressLineInfo *info; if (!GTK_IS_ENTRY (editable)) { g_warning ("%s: Unexpected cell editable type.", __func__); return; } /* Initialize last_path and last_column, last_edited is initialized when the cell is edited */ g_free (priv->last_edited); priv->last_edited = NULL; g_free (priv->last_path); priv->last_path = g_strdup (path); priv->last_column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cell), "column")); /* Set up the entry filter */ g_signal_connect (G_OBJECT (editable), "insert-text", (GCallback) ip_address_filter_cb, user_data); g_signal_connect_after (G_OBJECT (editable), "delete-text", (GCallback) delete_text_cb, user_data); /* Set up handler for IP verifying and changing cell background */ model = gtk_tree_view_get_model (priv->addr_list); gtk_tree_model_get_iter_from_string (model, &iter, priv->last_path); info = g_slice_new0 (AddressLineInfo); info->model = model; info->iter = iter; info->column = priv->last_column; g_signal_connect_data (G_OBJECT (editable), "changed", (GCallback) cell_changed_cb, info, (GClosureNotify) address_line_info_destroy, 0); /* Set up key pressed handler - need to handle Tab key */ g_signal_connect (G_OBJECT (editable), "key-press-event", (GCallback) key_pressed_cb, cell); }
static void dispose (GObject *object) { CEPageIP4 *self = CE_PAGE_IP4 (object); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); int i; g_clear_object (&priv->window_group); /* Mark CEPageIP4 object as invalid; store this indication to cells to be usable in callbacks */ for (i = 0; i <= COL_LAST; i++) g_object_set_data (G_OBJECT (priv->addr_cells[i]), "ce-page-not-valid", GUINT_TO_POINTER (1)); g_clear_pointer (&priv->connection_id, g_free); G_OBJECT_CLASS (ce_page_ip4_parent_class)->dispose (object); }
CEPage * ce_page_ip4_new (NMConnectionEditor *editor, NMConnection *connection, GtkWindow *parent_window, NMClient *client, const char **out_secrets_setting_name, GError **error) { CEPageIP4 *self; CEPageIP4Private *priv; NMSettingConnection *s_con; self = CE_PAGE_IP4 (ce_page_new (CE_TYPE_PAGE_IP4, editor, connection, parent_window, client, UIDIR "/ce-page-ip4.ui", "IP4Page", _("IPv4 Settings"))); if (!self) { g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("Could not load IPv4 user interface.")); return NULL; } ip4_private_init (self, connection); priv = CE_PAGE_IP4_GET_PRIVATE (self); priv->window_group = gtk_window_group_new (); s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); priv->connection_id = g_strdup (nm_setting_connection_get_id (s_con)); priv->setting = nm_connection_get_setting_ip4_config (connection); g_assert (priv->setting); g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL); return CE_PAGE (self); }
static void ip_address_filter_cb (GtkEditable *editable, gchar *text, gint length, gint *position, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); gboolean changed; changed = utils_filter_editable_on_insert_text (editable, text, length, position, user_data, utils_char_is_ascii_ip4_address, ip_address_filter_cb); if (changed) { g_free (priv->last_edited); priv->last_edited = gtk_editable_get_chars (editable, 0, -1); } }
static void routes_button_clicked_cb (GtkWidget *button, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); GtkWidget *dialog, *toplevel; gboolean automatic = FALSE; const char *method; char *tmp; toplevel = gtk_widget_get_toplevel (CE_PAGE (self)->page); g_return_if_fail (GTK_WIDGET_TOPLEVEL (toplevel)); method = nm_setting_ip4_config_get_method (priv->setting); if (!method || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) automatic = TRUE; dialog = ip4_routes_dialog_new (priv->setting, automatic); if (!dialog) { g_warning ("%s: failed to create the routes dialog!", __func__); return; } gtk_window_group_add_window (priv->window_group, GTK_WINDOW (dialog)); if (!priv->window_added) { gtk_window_group_add_window (priv->window_group, GTK_WINDOW (toplevel)); priv->window_added = TRUE; } gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel)); tmp = g_strdup_printf (_("Editing IPv4 routes for %s"), priv->connection_id); gtk_window_set_title (GTK_WINDOW (dialog), tmp); g_free (tmp); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (routes_dialog_response_cb), self); g_signal_connect (G_OBJECT (dialog), "close", G_CALLBACK (routes_dialog_close_cb), self); gtk_widget_show_all (dialog); }
static void cell_edited (GtkCellRendererText *cell, const gchar *path_string, const gchar *new_text, gpointer user_data) { CEPageIP4 *self = CE_PAGE_IP4 (user_data); CEPageIP4Private *priv = CE_PAGE_IP4_GET_PRIVATE (self); GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (priv->addr_list)); GtkTreePath *path = gtk_tree_path_new_from_string (path_string); GtkTreeIter iter; guint32 column; GtkTreeViewColumn *next_col; GtkCellRenderer *next_cell; gboolean can_cycle; int direction, tmp; /* Free auxiliary stuff */ g_free (priv->last_edited); priv->last_edited = NULL; g_free (priv->last_path); priv->last_path = NULL; priv->last_column = -1; column = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (cell), "column")); gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path); gtk_list_store_set (store, &iter, column, new_text, -1); /* Try to autodetect the prefix from the given address if we can */ if (column == COL_ADDRESS && new_text && strlen (new_text)) { char *prefix = NULL; const char *guess_prefix = NULL; gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &iter, path_string); gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, COL_PREFIX, &prefix, -1); if (!prefix || !strlen (prefix)) { if (!strncmp ("10.", new_text, 3)) guess_prefix = "8"; else if (!strncmp ("172.16.", new_text, 7)) guess_prefix = "16"; else if (!strncmp ("192.168.", new_text, 8)) guess_prefix = "24"; if (guess_prefix) gtk_list_store_set (store, &iter, COL_PREFIX, guess_prefix, -1); } g_free (prefix); } /* Move focus to the next/previous column */ can_cycle = g_object_get_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG) == NULL; direction = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), DIRECTION_TAG)); g_object_set_data (G_OBJECT (cell), DIRECTION_TAG, NULL); g_object_set_data (G_OBJECT (cell), DO_NOT_CYCLE_TAG, NULL); if (direction == 0) /* Move forward by default */ direction = 1; tmp = column + direction; if (can_cycle) column = tmp < 0 ? COL_LAST : tmp > COL_LAST ? 0 : tmp; else column = tmp; next_col = gtk_tree_view_get_column (priv->addr_list, column); next_cell = column <= COL_LAST ? priv->addr_cells[column] : NULL; gtk_tree_view_set_cursor_on_cell (priv->addr_list, path, next_col, next_cell, TRUE); gtk_tree_path_free (path); ce_page_changed (CE_PAGE (self)); }