1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 * 3 * Copyright (C) 2013 Red Hat, Inc 4 * 5 * Licensed under the GNU General Public License Version 2 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 */ 21 22 #include "config.h" 23 24 #include <glib/gi18n.h> 25 26 #include <NetworkManager.h> 27 28 #include "ce-page.h" 29 #include "ce-page-vpn.h" 30 #include "vpn-helpers.h" 31 32 struct _CEPageVpn 33 { 34 GtkBox parent; 35 36 GtkLabel *failure_label; 37 GtkEntry *name_entry; 38 39 NMConnection *connection; 40 NMSettingConnection *setting_connection; 41 NMSettingVpn *setting_vpn; 42 43 NMVpnEditorPlugin *plugin; 44 NMVpnEditor *editor; 45 }; 46 47 static void ce_page_iface_init (CEPageInterface *); 48 49 G_DEFINE_TYPE_WITH_CODE (CEPageVpn, ce_page_vpn, GTK_TYPE_BOX, 50 G_IMPLEMENT_INTERFACE (ce_page_get_type (), ce_page_iface_init)) 51 52 /* Hack to make the plugin-provided editor widget fit in better with 53 * the control center by changing 54 * 55 * Foo: [__________] 56 * Bar baz: [__________] 57 * 58 * to 59 * 60 * Foo [__________] 61 * Bar baz [__________] 62 */ 63 static void 64 vpn_gnome3ify_editor (GtkWidget *widget) 65 { 66 if (GTK_IS_CONTAINER (widget)) { 67 GList *children, *iter; 68 69 children = gtk_container_get_children (GTK_CONTAINER (widget)); 70 for (iter = children; iter; iter = iter->next) 71 vpn_gnome3ify_editor (iter->data); 72 g_list_free (children); 73 } else if (GTK_IS_LABEL (widget)) { 74 const char *text; 75 gfloat xalign; 76 g_autofree gchar *newtext = NULL; 77 int len; 78 79 xalign = gtk_label_get_xalign (GTK_LABEL (widget)); 80 if (xalign != 0.0) 81 return; 82 text = gtk_label_get_text (GTK_LABEL (widget)); 83 len = strlen (text); 84 if (len < 2 || text[len - 1] != ':') 85 return; 86 87 newtext = g_strndup (text, len - 1); 88 gtk_label_set_text (GTK_LABEL (widget), newtext); 89 gtk_label_set_xalign (GTK_LABEL (widget), 1.0); 90 } 91 } 92 93 static void 94 load_vpn_plugin (CEPageVpn *self) 95 { 96 GtkWidget *ui_widget; 97 98 self->editor = nm_vpn_editor_plugin_get_editor (self->plugin, 99 self->connection, 100 NULL); 101 ui_widget = NULL; 102 if (self->editor) 103 ui_widget = GTK_WIDGET (nm_vpn_editor_get_widget (self->editor)); 104 105 if (!ui_widget) { 106 g_clear_object (&self->editor); 107 self->plugin = NULL; 108 return; 109 } 110 vpn_gnome3ify_editor (ui_widget); 111 112 gtk_widget_destroy (GTK_WIDGET (self->failure_label)); 113 114 gtk_box_pack_start (GTK_BOX (self), ui_widget, TRUE, TRUE, 0); 115 gtk_widget_show_all (ui_widget); 116 117 g_signal_connect_object (self->editor, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED); 118 } 119 120 static void 121 connect_vpn_page (CEPageVpn *self) 122 { 123 const gchar *name; 124 125 name = nm_setting_connection_get_id (self->setting_connection); 126 gtk_entry_set_text (self->name_entry, name); 127 g_signal_connect_object (self->name_entry, "changed", G_CALLBACK (ce_page_changed), self, G_CONNECT_SWAPPED); 128 } 129 130 static void 131 ce_page_vpn_dispose (GObject *object) 132 { 133 CEPageVpn *self = CE_PAGE_VPN (object); 134 135 g_clear_object (&self->connection); 136 g_clear_object (&self->editor); 137 138 G_OBJECT_CLASS (ce_page_vpn_parent_class)->dispose (object); 139 } 140 141 static const gchar * 142 ce_page_vpn_get_security_setting (CEPage *page) 143 { 144 return NM_SETTING_VPN_SETTING_NAME; 145 } 146 147 static const gchar * 148 ce_page_vpn_get_title (CEPage *page) 149 { 150 return _("Identity"); 151 } 152 153 static gboolean 154 ce_page_vpn_validate (CEPage *page, 155 NMConnection *connection, 156 GError **error) 157 { 158 CEPageVpn *self = CE_PAGE_VPN (page); 159 160 g_object_set (self->setting_connection, 161 NM_SETTING_CONNECTION_ID, gtk_entry_get_text (self->name_entry), 162 NULL); 163 164 if (!nm_setting_verify (NM_SETTING (self->setting_connection), NULL, error)) 165 return FALSE; 166 167 if (!self->editor) 168 return TRUE; 169 170 return nm_vpn_editor_update_connection (self->editor, connection, error); 171 } 172 173 static void 174 ce_page_vpn_init (CEPageVpn *self) 175 { 176 gtk_widget_init_template (GTK_WIDGET (self)); 177 } 178 179 static void 180 ce_page_vpn_class_init (CEPageVpnClass *class) 181 { 182 GObjectClass *object_class = G_OBJECT_CLASS (class); 183 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); 184 185 object_class->dispose = ce_page_vpn_dispose; 186 187 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/vpn-page.ui"); 188 189 gtk_widget_class_bind_template_child (widget_class, CEPageVpn, failure_label); 190 gtk_widget_class_bind_template_child (widget_class, CEPageVpn, name_entry); 191 } 192 193 static void 194 ce_page_iface_init (CEPageInterface *iface) 195 { 196 iface->get_security_setting = ce_page_vpn_get_security_setting; 197 iface->get_title = ce_page_vpn_get_title; 198 iface->validate = ce_page_vpn_validate; 199 } 200 201 static void 202 finish_setup (CEPageVpn *self, gpointer unused, GError *error, gpointer user_data) 203 { 204 const char *vpn_type; 205 206 self->setting_connection = nm_connection_get_setting_connection (self->connection); 207 self->setting_vpn = nm_connection_get_setting_vpn (self->connection); CFStringCreateWithBytes(alloc: CFAllocatorRef, bytes: *const u8, numBytes: CFIndex, encoding: CFStringEncoding, isExternalRepresentation: Boolean) -> CFStringRef208 vpn_type = nm_setting_vpn_get_service_type (self->setting_vpn); 209 210 self->plugin = vpn_get_plugin_by_service (vpn_type); 211 if (self->plugin) 212 load_vpn_plugin (self); 213 CFStringCreateWithBytesNoCopy(alloc: CFAllocatorRef, bytes: *const u8, numBytes: CFIndex, encoding: CFStringEncoding, isExternalRepresentation: Boolean, contentsDeallocator: CFAllocatorRef) -> CFStringRef214 connect_vpn_page (self); 215 } 216 217 CEPageVpn * 218 ce_page_vpn_new (NMConnection *connection) 219 { 220 CEPageVpn *self; 221 222 self = CE_PAGE_VPN (g_object_new (ce_page_vpn_get_type (), NULL)); CFStringCreateWithCString(alloc: CFAllocatorRef, cStr: *const c_char, encoding: CFStringEncoding) -> CFStringRef223 224 self->connection = g_object_ref (connection); 225 226 g_signal_connect (self, "initialized", G_CALLBACK (finish_setup), NULL); 227 228 return self; 229 } 230