~ubuntu-branches/ubuntu/utopic/network-manager-applet/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/git_fix_some_leaks_80ef61b.patch/src/libnm-gtk/nm-mobile-wizard.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2012-11-19 14:46:29 UTC
  • mfrom: (1.2.31)
  • Revision ID: package-import@ubuntu.com-20121119144629-5423hii02a4vrh2n
Tags: 0.9.6.2+git201211052130.2d666bc-0ubuntu1
* upstream snapshot 2012-11-05 21:30:03 (GMT)
  + 2d666bc7aa6f0b731d131319b36f07b0f2bdce16
* debian/patches/git_fix_some_leaks_80ef61b.patch,
  debian/patches/git_indicate_hspa+_lte_tech_dbe3b12.patch,
  debian/patches/git_mac_addr_string_leakage_6dae878.patch: dropped, included
  in upstream tarball.
* debian/patches/lp328572-dxteam-connect-text.patch: refreshed.
* debian/patches/lp330571_dxteam_wired_connect_text.patch: refreshed.
* debian/patches/lp337960_dxteam_notification_icon_names.diff,
  debian/patches/lp337960_dxteam_notification_icon_names_part2-images.diff:
  disabled patches, they don't seem to be used (the icons don't match up with
  what is currently observable on the desktop). Let's see if someone screams.
* debian/patches/applet-wifi-menu-before-vpn.patch: refreshed.
* debian/patches/lp830178_adhoc_ip6_ignore.patch: refreshed.
* debian/patches/lp829673_gconf_hide_applet.patch: refreshed.
* debian/patches/nm-applet-use-indicator.patch: refreshed.
* debian/patches/hide_policy_items_env_var.patch: refreshed.
* debian/patches/applet_adhoc_use_wpa_rsn_part1.patch: refreshed.
* debian/patches/lp341684_device_sensitive_disconnect_notify.patch:
  refreshed.
* debian/patches/lp460144_correctly_update_notification.patch: refreshed.
* debian/patches/make_menu_items_insensitive_based_on_permissions.patch:
  refreshed.
* debian/control:
  - add gobject-introspection to Build-Depends.
  - add gudev-dev to Build-Depends.
  - bump network-manager and libnm-* Build-Depends and Depends to require
    at least 0.9.6.0+git201211131441.e9e2c56-0ubuntu1.
* debian/rules:
  - use autogen.sh with dh_autoreconf instead of calling intltoolize and
    gtkdocize manually.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
 
/* NetworkManager Connection editor -- Connection editor for NetworkManager
3
 
 *
4
 
 * Dan Williams <dcbw@redhat.com>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License along
17
 
 * with this program; if not, write to the Free Software Foundation, Inc.,
18
 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 
 *
20
 
 * (C) Copyright 2008 - 2012 Red Hat, Inc.
21
 
 */
22
 
 
23
 
#include "config.h"
24
 
 
25
 
#include <stdlib.h>
26
 
#include <ctype.h>
27
 
 
28
 
#include <glib.h>
29
 
#include <glib/gi18n.h>
30
 
 
31
 
#include <gtk/gtk.h>
32
 
 
33
 
#include <NetworkManager.h>
34
 
#include <nm-setting-gsm.h>
35
 
#include <nm-setting-cdma.h>
36
 
#include <nm-client.h>
37
 
#include <nm-device-modem.h>
38
 
 
39
 
#include "nm-mobile-wizard.h"
40
 
#include "nmn-mobile-providers.h"
41
 
#include "utils.h"
42
 
 
43
 
#define DEVICE_TAG "device"
44
 
#define TYPE_TAG "setting-type"
45
 
 
46
 
static char *get_selected_country (NMAMobileWizard *self, gboolean *unlisted);
47
 
static NmnMobileProvider *get_selected_provider (NMAMobileWizard *self);
48
 
static NmnMobileAccessMethodType get_provider_unlisted_type (NMAMobileWizard *self);
49
 
static NmnMobileAccessMethod *get_selected_method (NMAMobileWizard *self, gboolean *manual);
50
 
 
51
 
struct NMAMobileWizard {
52
 
        GtkWidget *assistant;
53
 
        NMAMobileWizardCallback callback;
54
 
        gpointer user_data;
55
 
        GHashTable *providers;
56
 
        GHashTable *country_codes;
57
 
        NmnMobileAccessMethodType method_type;
58
 
        gboolean initial_method_type;
59
 
        gboolean will_connect_after;
60
 
 
61
 
        /* Intro page */
62
 
        GtkWidget *dev_combo;
63
 
        GtkTreeStore *dev_store;
64
 
        char *dev_desc;
65
 
        NMClient *client;
66
 
 
67
 
        /* Country page */
68
 
        guint32 country_idx;
69
 
        const char *country;
70
 
        GtkWidget *country_page;
71
 
        GtkWidget *country_view;
72
 
        GtkTreeStore *country_store;
73
 
        GtkTreeModelSort *country_sort;
74
 
        guint32 country_focus_id;
75
 
 
76
 
        /* Providers page */
77
 
        guint32 providers_idx;
78
 
        GtkWidget *providers_page;
79
 
        GtkWidget *providers_view;
80
 
        GtkTreeStore *providers_store;
81
 
        GtkTreeModelSort *providers_sort;
82
 
        guint32 providers_focus_id;
83
 
        GtkWidget *providers_view_radio;
84
 
 
85
 
        GtkWidget *provider_unlisted_radio;
86
 
        GtkWidget *provider_unlisted_entry;
87
 
        GtkWidget *provider_unlisted_type_combo;
88
 
 
89
 
        gboolean provider_only_cdma;
90
 
 
91
 
        /* Plan page */
92
 
        guint32 plan_idx;
93
 
        GtkWidget *plan_page;
94
 
        GtkWidget *plan_combo;
95
 
        GtkTreeStore *plan_store;
96
 
        guint32 plan_focus_id;
97
 
 
98
 
        GtkWidget *plan_unlisted_entry;
99
 
 
100
 
        /* Confirm page */
101
 
        GtkWidget *confirm_page;
102
 
        GtkWidget *confirm_provider;
103
 
        GtkWidget *confirm_plan;
104
 
        GtkWidget *confirm_apn;
105
 
        GtkWidget *confirm_plan_label;
106
 
        GtkWidget *confirm_device;
107
 
        GtkWidget *confirm_device_label;
108
 
        guint32 confirm_idx;
109
 
};
110
 
 
111
 
static void
112
 
assistant_closed (GtkButton *button, gpointer user_data)
113
 
{
114
 
        NMAMobileWizard *self = user_data;
115
 
        NmnMobileProvider *provider;
116
 
        NmnMobileAccessMethod *method;
117
 
        NMAMobileWizardAccessMethod *wiz_method;
118
 
        NmnMobileAccessMethodType method_type = self->method_type;
119
 
 
120
 
        wiz_method = g_malloc0 (sizeof (NMAMobileWizardAccessMethod));
121
 
 
122
 
        provider = get_selected_provider (self);
123
 
        if (!provider) {
124
 
                if (method_type == NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN)
125
 
                        method_type = get_provider_unlisted_type (self);
126
 
 
127
 
                wiz_method->provider_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->provider_unlisted_entry)));
128
 
                if (method_type == NMN_MOBILE_ACCESS_METHOD_TYPE_GSM)
129
 
                        wiz_method->gsm_apn = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->plan_unlisted_entry)));
130
 
        } else {
131
 
                gboolean manual = FALSE;
132
 
 
133
 
                wiz_method->provider_name = g_strdup (provider->name);
134
 
                method = get_selected_method (self, &manual);
135
 
                if (method) {
136
 
                        if (method->name)
137
 
                                wiz_method->plan_name = g_strdup (method->name);
138
 
                        method_type = method->type;
139
 
                        if (method_type == NMN_MOBILE_ACCESS_METHOD_TYPE_GSM)
140
 
                                wiz_method->gsm_apn = g_strdup (method->gsm_apn);
141
 
                        wiz_method->username = method->username ? g_strdup (method->username) : NULL;
142
 
                        wiz_method->password = method->password ? g_strdup (method->password) : NULL;
143
 
                } else {
144
 
                        if (self->provider_only_cdma) {
145
 
                                method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA;
146
 
                                /* Take username and password from the first (only) method for CDMA only provider */
147
 
                                if (provider->methods) {
148
 
                                        method = provider->methods->data;
149
 
                                        wiz_method->username = method->username ? g_strdup (method->username) : NULL;
150
 
                                        wiz_method->password = method->password ? g_strdup (method->password) : NULL;
151
 
                                }
152
 
                        }
153
 
                        else {
154
 
                                method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_GSM;
155
 
                                wiz_method->gsm_apn = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->plan_unlisted_entry)));
156
 
                        }
157
 
                }
158
 
        }
159
 
 
160
 
        switch (method_type) {
161
 
        case NMN_MOBILE_ACCESS_METHOD_TYPE_GSM:
162
 
                wiz_method->devtype = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
163
 
                break;
164
 
        case NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA:
165
 
                wiz_method->devtype = NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO;
166
 
                break;
167
 
        default:
168
 
                g_assert_not_reached ();
169
 
                break;
170
 
        }
171
 
 
172
 
        (*(self->callback)) (self, FALSE, wiz_method, self->user_data);
173
 
 
174
 
        g_free (wiz_method->provider_name);
175
 
        g_free (wiz_method->plan_name);
176
 
        g_free (wiz_method->username);
177
 
        g_free (wiz_method->password);
178
 
        g_free (wiz_method->gsm_apn);
179
 
        g_free (wiz_method);
180
 
}
181
 
 
182
 
static void
183
 
assistant_cancel (GtkButton *button, gpointer user_data)
184
 
{
185
 
        NMAMobileWizard *self = user_data;
186
 
 
187
 
        (*(self->callback)) (self, TRUE, NULL, self->user_data);
188
 
}
189
 
 
190
 
/**********************************************************/
191
 
/* Confirm page */
192
 
/**********************************************************/
193
 
 
194
 
static void
195
 
confirm_setup (NMAMobileWizard *self)
196
 
{
197
 
        GtkWidget *vbox, *label, *alignment, *pbox;
198
 
 
199
 
#if GTK_CHECK_VERSION(3,1,6)
200
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
201
 
#else
202
 
        vbox = gtk_vbox_new (FALSE, 6);
203
 
#endif
204
 
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
205
 
        label = gtk_label_new (_("Your mobile broadband connection is configured with the following settings:"));
206
 
        gtk_widget_set_size_request (label, 500, -1);
207
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
208
 
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
209
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 6);
210
 
 
211
 
        /* Device */
212
 
        self->confirm_device_label = gtk_label_new (_("Your Device:"));
213
 
        gtk_misc_set_alignment (GTK_MISC (self->confirm_device_label), 0, 0.5);
214
 
        gtk_box_pack_start (GTK_BOX (vbox), self->confirm_device_label, FALSE, FALSE, 0);
215
 
 
216
 
        alignment = gtk_alignment_new (0, 0.5, 0, 0);
217
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 12, 25, 0);
218
 
        self->confirm_device = gtk_label_new (NULL);
219
 
        gtk_container_add (GTK_CONTAINER (alignment), self->confirm_device);
220
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
221
 
 
222
 
        /* Provider */
223
 
        label = gtk_label_new (_("Your Provider:"));
224
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
225
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
226
 
 
227
 
        alignment = gtk_alignment_new (0, 0.5, 0, 0);
228
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 12, 25, 0);
229
 
        self->confirm_provider = gtk_label_new (NULL);
230
 
        gtk_container_add (GTK_CONTAINER (alignment), self->confirm_provider);
231
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
232
 
 
233
 
        /* Plan and APN */
234
 
        self->confirm_plan_label = gtk_label_new (_("Your Plan:"));
235
 
        gtk_misc_set_alignment (GTK_MISC (self->confirm_plan_label), 0, 0.5);
236
 
        gtk_box_pack_start (GTK_BOX (vbox), self->confirm_plan_label, FALSE, FALSE, 0);
237
 
 
238
 
        alignment = gtk_alignment_new (0, 0.5, 0, 0);
239
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 25, 0);
240
 
#if GTK_CHECK_VERSION(3,1,6)
241
 
        pbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
242
 
#else
243
 
        pbox = gtk_vbox_new (FALSE, 0);
244
 
#endif
245
 
        gtk_container_add (GTK_CONTAINER (alignment), pbox);
246
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
247
 
 
248
 
        self->confirm_plan = gtk_label_new (NULL);
249
 
        gtk_misc_set_alignment (GTK_MISC (self->confirm_plan), 0, 0.5);
250
 
        gtk_box_pack_start (GTK_BOX (pbox), self->confirm_plan, FALSE, FALSE, 0);
251
 
 
252
 
        self->confirm_apn = gtk_label_new (NULL);
253
 
        gtk_misc_set_alignment (GTK_MISC (self->confirm_apn), 0, 0.5);
254
 
        gtk_misc_set_padding (GTK_MISC (self->confirm_apn), 0, 6);
255
 
        gtk_box_pack_start (GTK_BOX (pbox), self->confirm_apn, FALSE, FALSE, 0);
256
 
 
257
 
        if (self->will_connect_after) {
258
 
                alignment = gtk_alignment_new (0, 0.5, 1, 0);
259
 
                label = gtk_label_new (_("A connection will now be made to your mobile broadband provider using the settings you selected.  If the connection fails or you cannot access network resources, double-check your settings.  To modify your mobile broadband connection settings, choose \"Network Connections\" from the System >> Preferences menu."));
260
 
                gtk_widget_set_size_request (label, 500, -1);
261
 
                gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
262
 
                gtk_misc_set_padding (GTK_MISC (label), 0, 6);
263
 
                gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
264
 
                gtk_container_add (GTK_CONTAINER (alignment), label);
265
 
                gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 6);
266
 
        }
267
 
 
268
 
        gtk_widget_show_all (vbox);
269
 
        self->confirm_idx = gtk_assistant_append_page (GTK_ASSISTANT (self->assistant), vbox);
270
 
        gtk_assistant_set_page_title (GTK_ASSISTANT (self->assistant),
271
 
                                      vbox, _("Confirm Mobile Broadband Settings"));
272
 
 
273
 
        gtk_assistant_set_page_complete (GTK_ASSISTANT (self->assistant), vbox, TRUE);
274
 
        gtk_assistant_set_page_type (GTK_ASSISTANT (self->assistant), vbox, GTK_ASSISTANT_PAGE_CONFIRM);
275
 
 
276
 
        self->confirm_page = vbox;
277
 
}
278
 
 
279
 
static void
280
 
confirm_prepare (NMAMobileWizard *self)
281
 
{
282
 
        NmnMobileProvider *provider = NULL;
283
 
        NmnMobileAccessMethod *method = NULL;
284
 
        char *country = NULL;
285
 
        gboolean manual = FALSE;
286
 
        GString *str;
287
 
 
288
 
        country = get_selected_country (self, NULL);
289
 
        provider = get_selected_provider (self);
290
 
        if (provider)
291
 
                method = get_selected_method (self, &manual);
292
 
 
293
 
        /* Provider */
294
 
        str = g_string_new (NULL);
295
 
        if (provider)
296
 
                g_string_append (str, provider->name);
297
 
        else {
298
 
                const char *unlisted_provider;
299
 
 
300
 
                unlisted_provider = gtk_entry_get_text (GTK_ENTRY (self->provider_unlisted_entry));
301
 
                g_string_append (str, unlisted_provider);
302
 
        }
303
 
 
304
 
        if (country)
305
 
                g_string_append_printf (str, ", %s", country);
306
 
        gtk_label_set_text (GTK_LABEL (self->confirm_provider), str->str);
307
 
        g_string_free (str, TRUE);
308
 
 
309
 
        if (self->dev_desc)
310
 
                gtk_label_set_text (GTK_LABEL (self->confirm_device), self->dev_desc);
311
 
        else {
312
 
                gtk_widget_hide (self->confirm_device_label);
313
 
                gtk_widget_hide (self->confirm_device);
314
 
        }
315
 
 
316
 
        if (self->provider_only_cdma) {
317
 
                gtk_widget_hide (self->confirm_plan_label);
318
 
                gtk_widget_hide (self->confirm_plan);
319
 
                gtk_widget_hide (self->confirm_apn);
320
 
        } else {
321
 
                const char *apn = NULL;
322
 
 
323
 
                /* Plan */
324
 
                gtk_widget_show (self->confirm_plan_label);
325
 
                gtk_widget_show (self->confirm_plan);
326
 
                gtk_widget_show (self->confirm_apn);
327
 
 
328
 
                if (method) {
329
 
                        gtk_label_set_text (GTK_LABEL (self->confirm_plan), method->name);
330
 
                        apn = method->gsm_apn;
331
 
                } else {
332
 
                        gtk_label_set_text (GTK_LABEL (self->confirm_plan), _("Unlisted"));
333
 
                        apn = gtk_entry_get_text (GTK_ENTRY (self->plan_unlisted_entry));
334
 
                }
335
 
 
336
 
                str = g_string_new (NULL);
337
 
                g_string_append_printf (str, "<span color=\"#999999\">APN: %s</span>", apn);
338
 
                gtk_label_set_markup (GTK_LABEL (self->confirm_apn), str->str);
339
 
                g_string_free (str, TRUE);
340
 
        }
341
 
}
342
 
 
343
 
/**********************************************************/
344
 
/* Plan page */
345
 
/**********************************************************/
346
 
 
347
 
#define PLAN_COL_NAME 0
348
 
#define PLAN_COL_METHOD 1
349
 
#define PLAN_COL_MANUAL 2
350
 
 
351
 
static NmnMobileAccessMethod *
352
 
get_selected_method (NMAMobileWizard *self, gboolean *manual)
353
 
{
354
 
        GtkTreeModel *model;
355
 
        NmnMobileAccessMethod *method = NULL;
356
 
        GtkTreeIter iter;
357
 
        gboolean is_manual = FALSE;
358
 
 
359
 
        if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->plan_combo), &iter))
360
 
                return NULL;
361
 
 
362
 
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->plan_combo));
363
 
        if (!model)
364
 
                return NULL;
365
 
 
366
 
        gtk_tree_model_get (model, &iter,
367
 
                            PLAN_COL_METHOD, &method,
368
 
                            PLAN_COL_MANUAL, &is_manual,
369
 
                            -1);
370
 
        if (is_manual) {
371
 
                if (manual)
372
 
                        *manual = is_manual;
373
 
                if (method)
374
 
                        nmn_mobile_access_method_unref (method);
375
 
                method = NULL;
376
 
        }
377
 
 
378
 
        return method;
379
 
}
380
 
 
381
 
static void
382
 
plan_update_complete (NMAMobileWizard *self)
383
 
{
384
 
        GtkAssistant *assistant = GTK_ASSISTANT (self->assistant);
385
 
        gboolean is_manual = FALSE;
386
 
        NmnMobileAccessMethod *method;
387
 
 
388
 
        method = get_selected_method (self, &is_manual);
389
 
        if (method) {
390
 
                gtk_assistant_set_page_complete (assistant, self->plan_page, TRUE);
391
 
                nmn_mobile_access_method_unref (method);
392
 
        } else {
393
 
                const char *manual_apn;
394
 
 
395
 
                manual_apn = gtk_entry_get_text (GTK_ENTRY (self->plan_unlisted_entry));
396
 
                gtk_assistant_set_page_complete (assistant, self->plan_page,
397
 
                                                 (manual_apn && strlen (manual_apn)));
398
 
        }
399
 
}
400
 
 
401
 
static void
402
 
plan_combo_changed (NMAMobileWizard *self)
403
 
{
404
 
        NmnMobileAccessMethod *method = NULL;
405
 
        gboolean is_manual = FALSE;
406
 
 
407
 
        method = get_selected_method (self, &is_manual);
408
 
        if (method) {
409
 
                gtk_entry_set_text (GTK_ENTRY (self->plan_unlisted_entry), method->gsm_apn);
410
 
                gtk_widget_set_sensitive (self->plan_unlisted_entry, FALSE);
411
 
        } else {
412
 
                gtk_entry_set_text (GTK_ENTRY (self->plan_unlisted_entry), "");
413
 
                gtk_widget_set_sensitive (self->plan_unlisted_entry, TRUE);
414
 
                gtk_widget_grab_focus (self->plan_unlisted_entry);
415
 
        }
416
 
 
417
 
        if (method)
418
 
                nmn_mobile_access_method_unref (method);
419
 
 
420
 
        plan_update_complete (self);
421
 
}
422
 
 
423
 
static gboolean
424
 
plan_row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
425
 
{
426
 
        NmnMobileAccessMethod *method = NULL;
427
 
        gboolean is_manual = FALSE;
428
 
        gboolean draw_separator = FALSE;
429
 
 
430
 
        gtk_tree_model_get (model, iter,
431
 
                            PLAN_COL_METHOD, &method,
432
 
                            PLAN_COL_MANUAL, &is_manual,
433
 
                            -1);
434
 
        if (!method && !is_manual)
435
 
                draw_separator = TRUE;
436
 
        if (method)
437
 
                nmn_mobile_access_method_unref (method);
438
 
        return draw_separator;
439
 
}
440
 
 
441
 
static void
442
 
apn_filter_cb (GtkEntry *   entry,
443
 
               const gchar *text,
444
 
               gint         length,
445
 
               gint *       position,
446
 
               gpointer     user_data)
447
 
{
448
 
        GtkEditable *editable = GTK_EDITABLE (entry);
449
 
        int i, count = 0;
450
 
        gchar *result = g_new0 (gchar, length);
451
 
 
452
 
        for (i = 0; i < length; i++) {
453
 
                if (   isalnum (text[i])
454
 
                    || (text[i] == '.')
455
 
                    || (text[i] == '_')
456
 
                    || (text[i] == '-'))
457
 
                        result[count++] = text[i];
458
 
        }
459
 
 
460
 
        if (count > 0) {
461
 
                g_signal_handlers_block_by_func (G_OBJECT (editable),
462
 
                                                 G_CALLBACK (apn_filter_cb),
463
 
                                                 user_data);
464
 
                gtk_editable_insert_text (editable, result, count, position);
465
 
                g_signal_handlers_unblock_by_func (G_OBJECT (editable),
466
 
                                                   G_CALLBACK (apn_filter_cb),
467
 
                                                   user_data);
468
 
        }
469
 
 
470
 
        g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
471
 
        g_free (result);
472
 
}
473
 
 
474
 
static void
475
 
plan_setup (NMAMobileWizard *self)
476
 
{
477
 
        GtkWidget *vbox, *label, *alignment, *hbox, *image;
478
 
        GtkCellRenderer *renderer;
479
 
 
480
 
#if GTK_CHECK_VERSION(3,1,6)
481
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
482
 
#else
483
 
        vbox = gtk_vbox_new (FALSE, 6);
484
 
#endif
485
 
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
486
 
 
487
 
        label = gtk_label_new_with_mnemonic (_("_Select your plan:"));
488
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
489
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
490
 
 
491
 
        self->plan_store = gtk_tree_store_new (3, G_TYPE_STRING, NMN_TYPE_MOBILE_ACCESS_METHOD, G_TYPE_BOOLEAN);
492
 
 
493
 
        self->plan_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (self->plan_store));
494
 
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->plan_combo);
495
 
        gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (self->plan_combo),
496
 
                                              plan_row_separator_func,
497
 
                                              NULL,
498
 
                                              NULL);
499
 
 
500
 
        renderer = gtk_cell_renderer_text_new ();
501
 
        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->plan_combo), renderer, TRUE);
502
 
        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self->plan_combo), renderer, "text", PLAN_COL_NAME);
503
 
 
504
 
        g_signal_connect_swapped (self->plan_combo, "changed", G_CALLBACK (plan_combo_changed), self);
505
 
 
506
 
        alignment = gtk_alignment_new (0, 0.5, 0.5, 0);
507
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 12, 0, 0);
508
 
        gtk_container_add (GTK_CONTAINER (alignment), self->plan_combo);
509
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
510
 
 
511
 
        label = gtk_label_new_with_mnemonic (_("Selected plan _APN (Access Point Name):"));
512
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
513
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
514
 
 
515
 
        self->plan_unlisted_entry = gtk_entry_new ();
516
 
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->plan_unlisted_entry);
517
 
        gtk_entry_set_max_length (GTK_ENTRY (self->plan_unlisted_entry), 64);
518
 
        g_signal_connect (self->plan_unlisted_entry, "insert-text", G_CALLBACK (apn_filter_cb), self);
519
 
        g_signal_connect_swapped (self->plan_unlisted_entry, "changed", G_CALLBACK (plan_update_complete), self);
520
 
 
521
 
        alignment = gtk_alignment_new (0, 0.5, 0.5, 0);
522
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 24, 0, 0);
523
 
        gtk_container_add (GTK_CONTAINER (alignment), self->plan_unlisted_entry);
524
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
525
 
 
526
 
#if GTK_CHECK_VERSION(3,1,6)
527
 
        hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
528
 
#else
529
 
        hbox = gtk_hbox_new (FALSE, 6);
530
 
#endif
531
 
        image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
532
 
        gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
533
 
        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
534
 
 
535
 
        label = gtk_label_new (_("Warning: Selecting an incorrect plan may result in billing issues for your broadband account or may prevent connectivity.\n\nIf you are unsure of your plan please ask your provider for your plan's APN."));
536
 
        gtk_widget_set_size_request (label, 500, -1);
537
 
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
538
 
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
539
 
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
540
 
 
541
 
        self->plan_idx = gtk_assistant_append_page (GTK_ASSISTANT (self->assistant), vbox);
542
 
        gtk_assistant_set_page_title (GTK_ASSISTANT (self->assistant), vbox, _("Choose your Billing Plan"));
543
 
        gtk_assistant_set_page_type (GTK_ASSISTANT (self->assistant), vbox, GTK_ASSISTANT_PAGE_CONTENT);
544
 
        gtk_widget_show_all (vbox);
545
 
 
546
 
        self->plan_page = vbox;
547
 
}
548
 
 
549
 
static void
550
 
plan_prepare (NMAMobileWizard *self)
551
 
{
552
 
        NmnMobileProvider *provider;
553
 
        GtkTreeIter method_iter;
554
 
 
555
 
        gtk_tree_store_clear (self->plan_store);
556
 
 
557
 
        provider = get_selected_provider (self);
558
 
        if (provider) {
559
 
                GSList *iter;
560
 
                guint32 count = 0;
561
 
 
562
 
                for (iter = provider->methods; iter; iter = g_slist_next (iter)) {
563
 
                        NmnMobileAccessMethod *method = iter->data;
564
 
 
565
 
                        if (   (self->method_type != NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN)
566
 
                            && (method->type != self->method_type))
567
 
                                continue;
568
 
 
569
 
                        gtk_tree_store_append (GTK_TREE_STORE (self->plan_store), &method_iter, NULL);
570
 
                        gtk_tree_store_set (GTK_TREE_STORE (self->plan_store),
571
 
                                            &method_iter,
572
 
                                            PLAN_COL_NAME,
573
 
                                            method->name,
574
 
                                            PLAN_COL_METHOD,
575
 
                                            method,
576
 
                                            -1);
577
 
                        count++;
578
 
                }
579
 
 
580
 
                /* Draw the separator */
581
 
                if (count)
582
 
                        gtk_tree_store_append (GTK_TREE_STORE (self->plan_store), &method_iter, NULL);
583
 
        }
584
 
 
585
 
        /* Add the "My plan is not listed..." item */
586
 
        gtk_tree_store_append (GTK_TREE_STORE (self->plan_store), &method_iter, NULL);
587
 
        gtk_tree_store_set (GTK_TREE_STORE (self->plan_store),
588
 
                            &method_iter,
589
 
                            PLAN_COL_NAME,
590
 
                            _("My plan is not listed..."),
591
 
                            PLAN_COL_MANUAL,
592
 
                            TRUE,
593
 
                            -1);
594
 
 
595
 
        /* Select the first item by default if nothing is yet selected */
596
 
        if (gtk_combo_box_get_active (GTK_COMBO_BOX (self->plan_combo)) < 0)
597
 
                gtk_combo_box_set_active (GTK_COMBO_BOX (self->plan_combo), 0);
598
 
 
599
 
        plan_combo_changed (self);
600
 
}
601
 
 
602
 
/**********************************************************/
603
 
/* Providers page */
604
 
/**********************************************************/
605
 
 
606
 
#define PROVIDER_COL_NAME 0
607
 
#define PROVIDER_COL_PROVIDER 1
608
 
 
609
 
static gboolean
610
 
providers_search_func (GtkTreeModel *model,
611
 
                       gint column,
612
 
                       const char *key,
613
 
                       GtkTreeIter *iter,
614
 
                       gpointer search_data)
615
 
{
616
 
        gboolean unmatched = TRUE;
617
 
        char *provider = NULL;
618
 
 
619
 
        if (!key)
620
 
                return TRUE;
621
 
 
622
 
        gtk_tree_model_get (model, iter, column, &provider, -1);
623
 
        if (!provider)
624
 
                return TRUE;
625
 
 
626
 
        unmatched = !!g_ascii_strncasecmp (provider, key, strlen (key));
627
 
        g_free (provider);
628
 
        return unmatched;
629
 
}
630
 
 
631
 
static NmnMobileProvider *
632
 
get_selected_provider (NMAMobileWizard *self)
633
 
{
634
 
        GtkTreeSelection *selection;
635
 
        GtkTreeModel *model = NULL;
636
 
        GtkTreeIter iter;
637
 
        NmnMobileProvider *provider = NULL;
638
 
 
639
 
        if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->providers_view_radio)))
640
 
                return NULL;
641
 
 
642
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->providers_view));
643
 
        g_assert (selection);
644
 
 
645
 
        if (!gtk_tree_selection_get_selected (GTK_TREE_SELECTION (selection), &model, &iter))
646
 
                return NULL;
647
 
 
648
 
        gtk_tree_model_get (model, &iter, PROVIDER_COL_PROVIDER, &provider, -1);
649
 
        return provider;
650
 
}
651
 
 
652
 
static void
653
 
providers_update_complete (NMAMobileWizard *self)
654
 
{
655
 
        GtkAssistant *assistant = GTK_ASSISTANT (self->assistant);
656
 
        gboolean use_view;
657
 
 
658
 
        use_view = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->providers_view_radio));
659
 
        if (use_view) {
660
 
                NmnMobileProvider *provider;
661
 
 
662
 
                provider = get_selected_provider (self);
663
 
                gtk_assistant_set_page_complete (assistant, self->providers_page, !!provider);
664
 
                if (provider)
665
 
                        nmn_mobile_provider_unref (provider);
666
 
        } else {
667
 
                const char *manual_provider;
668
 
 
669
 
                manual_provider = gtk_entry_get_text (GTK_ENTRY (self->provider_unlisted_entry));
670
 
                gtk_assistant_set_page_complete (assistant, self->providers_page,
671
 
                                                 (manual_provider && strlen (manual_provider)));
672
 
        }
673
 
}
674
 
 
675
 
static gboolean
676
 
focus_providers_view (gpointer user_data)
677
 
{
678
 
        NMAMobileWizard *self = user_data;
679
 
 
680
 
        self->providers_focus_id = 0;
681
 
        gtk_widget_grab_focus (self->providers_view);
682
 
        return FALSE;
683
 
}
684
 
 
685
 
static gboolean
686
 
focus_provider_unlisted_entry (gpointer user_data)
687
 
{
688
 
        NMAMobileWizard *self = user_data;
689
 
 
690
 
        self->providers_focus_id = 0;
691
 
        gtk_widget_grab_focus (self->provider_unlisted_entry);
692
 
        return FALSE;
693
 
}
694
 
 
695
 
static void
696
 
providers_radio_toggled (GtkToggleButton *button, gpointer user_data)
697
 
{
698
 
        NMAMobileWizard *self = user_data;
699
 
        gboolean use_view;
700
 
 
701
 
        use_view = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->providers_view_radio));
702
 
        if (use_view) {
703
 
                if (!self->providers_focus_id)
704
 
                        self->providers_focus_id = g_idle_add (focus_providers_view, self);
705
 
                gtk_widget_set_sensitive (self->providers_view, TRUE);
706
 
                gtk_widget_set_sensitive (self->provider_unlisted_entry, FALSE);
707
 
                gtk_widget_set_sensitive (self->provider_unlisted_type_combo, FALSE);
708
 
        } else {
709
 
                if (!self->providers_focus_id)
710
 
                        self->providers_focus_id = g_idle_add (focus_provider_unlisted_entry, self);
711
 
                gtk_widget_set_sensitive (self->providers_view, FALSE);
712
 
                gtk_widget_set_sensitive (self->provider_unlisted_entry, TRUE);
713
 
                gtk_widget_set_sensitive (self->provider_unlisted_type_combo, TRUE);
714
 
        }
715
 
 
716
 
        providers_update_complete (self);
717
 
}
718
 
 
719
 
static NmnMobileAccessMethodType
720
 
get_provider_unlisted_type (NMAMobileWizard *self)
721
 
{
722
 
        switch (gtk_combo_box_get_active (GTK_COMBO_BOX (self->provider_unlisted_type_combo))) {
723
 
        case 0:
724
 
                return NMN_MOBILE_ACCESS_METHOD_TYPE_GSM;
725
 
        case 1:
726
 
                return NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA;
727
 
        default:
728
 
                return NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN;
729
 
        }
730
 
}
731
 
 
732
 
static void
733
 
providers_setup (NMAMobileWizard *self)
734
 
{
735
 
        GtkWidget *vbox, *scroll, *alignment, *unlisted_table, *label;
736
 
        GtkCellRenderer *renderer;
737
 
        GtkTreeViewColumn *column;
738
 
        GtkTreeSelection *selection;
739
 
 
740
 
#if GTK_CHECK_VERSION(3,1,6)
741
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
742
 
#else
743
 
        vbox = gtk_vbox_new (FALSE, 6);
744
 
#endif
745
 
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
746
 
 
747
 
        self->providers_view_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Select your provider from a _list:"));
748
 
        g_signal_connect (self->providers_view_radio, "toggled", G_CALLBACK (providers_radio_toggled), self);
749
 
        gtk_box_pack_start (GTK_BOX (vbox), self->providers_view_radio, FALSE, TRUE, 0);
750
 
 
751
 
        self->providers_store = gtk_tree_store_new (2, G_TYPE_STRING, NMN_TYPE_MOBILE_PROVIDER);
752
 
 
753
 
        self->providers_sort = GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (self->providers_store)));
754
 
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->providers_sort),
755
 
                                              PROVIDER_COL_NAME, GTK_SORT_ASCENDING);
756
 
 
757
 
        self->providers_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (self->providers_sort));
758
 
 
759
 
        renderer = gtk_cell_renderer_text_new ();
760
 
        column = gtk_tree_view_column_new_with_attributes (_("Provider"),
761
 
                                                           renderer,
762
 
                                                           "text", PROVIDER_COL_NAME,
763
 
                                                           NULL);
764
 
        gtk_tree_view_append_column (GTK_TREE_VIEW (self->providers_view), column);
765
 
        gtk_tree_view_column_set_clickable (column, TRUE);
766
 
 
767
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->providers_view));
768
 
        g_assert (selection);
769
 
        g_signal_connect_swapped (selection, "changed", G_CALLBACK (providers_update_complete), self);
770
 
 
771
 
        scroll = gtk_scrolled_window_new (NULL, NULL);
772
 
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
773
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
774
 
                                        GTK_POLICY_NEVER,
775
 
                                        GTK_POLICY_AUTOMATIC);
776
 
        gtk_widget_set_size_request (scroll, -1, 140);
777
 
        gtk_container_add (GTK_CONTAINER (scroll), self->providers_view);
778
 
 
779
 
        alignment = gtk_alignment_new (0, 0, 1, 1);
780
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 12, 25, 0);
781
 
        gtk_container_add (GTK_CONTAINER (alignment), scroll);
782
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, TRUE, TRUE, 0);
783
 
 
784
 
        self->provider_unlisted_radio = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (self->providers_view_radio),
785
 
                                                    _("I can't find my provider and I wish to enter it _manually:"));
786
 
        g_signal_connect (self->providers_view_radio, "toggled", G_CALLBACK (providers_radio_toggled), self);
787
 
        gtk_box_pack_start (GTK_BOX (vbox), self->provider_unlisted_radio, FALSE, TRUE, 0);
788
 
 
789
 
        alignment = gtk_alignment_new (0, 0, 0, 0);
790
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 15, 0);
791
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
792
 
 
793
 
        unlisted_table = gtk_table_new (2, 2, FALSE);
794
 
        gtk_container_add (GTK_CONTAINER (alignment), unlisted_table);
795
 
 
796
 
        label = gtk_label_new (_("Provider:"));
797
 
        gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
798
 
        gtk_table_attach (GTK_TABLE (unlisted_table), label, 0, 1, 0, 1, 0, 0, 6, 6);
799
 
 
800
 
        self->provider_unlisted_entry = gtk_entry_new ();
801
 
        gtk_entry_set_width_chars (GTK_ENTRY (self->provider_unlisted_entry), 40);
802
 
        g_signal_connect_swapped (self->provider_unlisted_entry, "changed", G_CALLBACK (providers_update_complete), self);
803
 
 
804
 
        alignment = gtk_alignment_new (0, 0.5, 0.66, 0);
805
 
        gtk_container_add (GTK_CONTAINER (alignment), self->provider_unlisted_entry);
806
 
        gtk_table_attach (GTK_TABLE (unlisted_table), alignment,
807
 
                          1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 6, 6);
808
 
 
809
 
#if GTK_CHECK_VERSION(2,23,0)
810
 
        self->provider_unlisted_type_combo = gtk_combo_box_text_new ();
811
 
#else
812
 
        self->provider_unlisted_type_combo = gtk_combo_box_new_text ();
813
 
#endif
814
 
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->provider_unlisted_type_combo);
815
 
#if GTK_CHECK_VERSION(2,23,0)
816
 
        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->provider_unlisted_type_combo),
817
 
#else
818
 
        gtk_combo_box_append_text (GTK_COMBO_BOX (self->provider_unlisted_type_combo),
819
 
#endif
820
 
                                   _("My provider uses GSM technology (GPRS, EDGE, UMTS, HSPA)"));
821
 
#if GTK_CHECK_VERSION(2,23,0)
822
 
        gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->provider_unlisted_type_combo),
823
 
#else
824
 
        gtk_combo_box_append_text (GTK_COMBO_BOX (self->provider_unlisted_type_combo),
825
 
#endif
826
 
                                   _("My provider uses CDMA technology (1xRTT, EVDO)"));
827
 
        gtk_combo_box_set_active (GTK_COMBO_BOX (self->provider_unlisted_type_combo), 0);
828
 
 
829
 
        gtk_table_attach (GTK_TABLE (unlisted_table), self->provider_unlisted_type_combo,
830
 
                          1, 2, 1, 2, 0, 0, 6, 6);
831
 
 
832
 
        /* Only show the CDMA/GSM combo if we don't know the device type */
833
 
        if (self->method_type != NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN)
834
 
                gtk_widget_hide (self->provider_unlisted_type_combo);
835
 
 
836
 
        self->providers_idx = gtk_assistant_append_page (GTK_ASSISTANT (self->assistant), vbox);
837
 
        gtk_assistant_set_page_title (GTK_ASSISTANT (self->assistant), vbox, _("Choose your Provider"));
838
 
        gtk_assistant_set_page_type (GTK_ASSISTANT (self->assistant), vbox, GTK_ASSISTANT_PAGE_CONTENT);
839
 
        gtk_widget_show_all (vbox);
840
 
 
841
 
        self->providers_page = vbox;
842
 
}
843
 
 
844
 
static void
845
 
providers_prepare (NMAMobileWizard *self)
846
 
{
847
 
        GtkTreeSelection *selection;
848
 
        GSList *providers, *piter;
849
 
        char *country;
850
 
 
851
 
        gtk_tree_store_clear (self->providers_store);
852
 
 
853
 
        country = get_selected_country (self, NULL);
854
 
        if (!country) {
855
 
                /* Unlisted country */
856
 
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->provider_unlisted_radio), TRUE);
857
 
                gtk_widget_set_sensitive (GTK_WIDGET (self->providers_view_radio), FALSE);
858
 
                goto done;
859
 
        }
860
 
        gtk_widget_set_sensitive (GTK_WIDGET (self->providers_view_radio), TRUE);
861
 
 
862
 
        providers = g_hash_table_lookup (self->providers, country);
863
 
        g_free (country);
864
 
 
865
 
        for (piter = providers; piter; piter = g_slist_next (piter)) {
866
 
                NmnMobileProvider *provider = piter->data;
867
 
                GtkTreeIter provider_iter;
868
 
 
869
 
                /* Ignore providers that don't match the current device type */
870
 
                if (self->method_type != NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN) {
871
 
                        GSList *miter;
872
 
                        guint32 count = 0;
873
 
 
874
 
                        for (miter = provider->methods; miter; miter = g_slist_next (miter)) {
875
 
                                NmnMobileAccessMethod *method = miter->data;
876
 
 
877
 
                                if (self->method_type == method->type)
878
 
                                        count++;
879
 
                        }
880
 
 
881
 
                        if (!count)
882
 
                                continue;
883
 
                }
884
 
 
885
 
                gtk_tree_store_append (GTK_TREE_STORE (self->providers_store), &provider_iter, NULL);
886
 
                gtk_tree_store_set (GTK_TREE_STORE (self->providers_store),
887
 
                                    &provider_iter,
888
 
                                    PROVIDER_COL_NAME,
889
 
                                    provider->name,
890
 
                                    PROVIDER_COL_PROVIDER,
891
 
                                    provider,
892
 
                                    -1);
893
 
        }
894
 
 
895
 
        g_object_set (G_OBJECT (self->providers_view), "enable-search", TRUE, NULL);
896
 
 
897
 
        gtk_tree_view_set_search_column (GTK_TREE_VIEW (self->providers_view), PROVIDER_COL_NAME);
898
 
        gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (self->providers_view),
899
 
                                             providers_search_func, self, NULL);
900
 
 
901
 
        /* If no row has focus yet, focus the first row so that the user can start
902
 
         * incremental search without clicking.
903
 
         */
904
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->providers_view));
905
 
        g_assert (selection);
906
 
        if (!gtk_tree_selection_count_selected_rows (selection)) {
907
 
                GtkTreeIter first_iter;
908
 
                GtkTreePath *first_path;
909
 
 
910
 
                if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->providers_sort), &first_iter)) {
911
 
                        first_path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->providers_sort), &first_iter);
912
 
                        if (first_path) {
913
 
                                gtk_tree_selection_select_path (selection, first_path);
914
 
                                gtk_tree_path_free (first_path);
915
 
                        }
916
 
                }
917
 
        }
918
 
 
919
 
done:
920
 
        providers_radio_toggled (NULL, self);
921
 
 
922
 
        /* Initial completeness state */
923
 
        providers_update_complete (self);
924
 
 
925
 
        /* If there's already a selected device, hide the GSM/CDMA radios */
926
 
        if (self->method_type != NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN)
927
 
                gtk_widget_hide (self->provider_unlisted_type_combo);
928
 
        else
929
 
                gtk_widget_show (self->provider_unlisted_type_combo);
930
 
}
931
 
 
932
 
/**********************************************************/
933
 
/* Country page */
934
 
/**********************************************************/
935
 
 
936
 
static gboolean
937
 
country_search_func (GtkTreeModel *model,
938
 
                     gint column,
939
 
                     const char *key,
940
 
                     GtkTreeIter *iter,
941
 
                     gpointer search_data)
942
 
{
943
 
        gboolean unmatched = TRUE;
944
 
        char *country = NULL;
945
 
 
946
 
        if (!key)
947
 
                return TRUE;
948
 
 
949
 
        gtk_tree_model_get (model, iter, column, &country, -1);
950
 
        if (!country)
951
 
                return TRUE;
952
 
 
953
 
        unmatched = !!g_ascii_strncasecmp (country, key, strlen (key));
954
 
        g_free (country);
955
 
        return unmatched;
956
 
}
957
 
 
958
 
static void
959
 
add_one_country (gpointer key, gpointer value, gpointer user_data)
960
 
{
961
 
        NMAMobileWizard *self = user_data;
962
 
        GtkTreeIter country_iter;
963
 
        GtkTreePath *country_path, *country_view_path;
964
 
 
965
 
        g_assert (key);
966
 
 
967
 
        gtk_tree_store_append (GTK_TREE_STORE (self->country_store), &country_iter, NULL);
968
 
        gtk_tree_store_set (GTK_TREE_STORE (self->country_store), &country_iter, 0, key, -1);
969
 
 
970
 
        /* If this country is the same country as the user's current locale,
971
 
         * select it by default.
972
 
         */
973
 
        if (!self->country || g_ascii_strcasecmp (self->country, key))
974
 
                return;
975
 
 
976
 
        country_path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->country_store), &country_iter);
977
 
        if (!country_path)
978
 
                return;
979
 
 
980
 
        country_view_path = gtk_tree_model_sort_convert_child_path_to_path (self->country_sort, country_path);
981
 
        if (country_view_path) {
982
 
                GtkTreeSelection *selection;
983
 
 
984
 
                gtk_tree_view_expand_row (GTK_TREE_VIEW (self->country_view), country_view_path, TRUE);
985
 
 
986
 
                selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->country_view));
987
 
                g_assert (selection);
988
 
                gtk_tree_selection_select_path (selection, country_view_path);
989
 
                gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (self->country_view),
990
 
                                              country_view_path, NULL, TRUE, 0, 0);
991
 
                gtk_tree_path_free (country_view_path);
992
 
        }
993
 
        gtk_tree_path_free (country_path);
994
 
}
995
 
 
996
 
static char *
997
 
get_selected_country (NMAMobileWizard *self, gboolean *out_unlisted)
998
 
{
999
 
        GtkTreeSelection *selection;
1000
 
        GtkTreeModel *model = NULL;
1001
 
        GtkTreeIter iter;
1002
 
        char *country = NULL;
1003
 
        gboolean unlisted = FALSE;
1004
 
 
1005
 
        if (!self->country_codes)
1006
 
                return NULL;
1007
 
 
1008
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->country_view));
1009
 
        g_assert (selection);
1010
 
 
1011
 
        if (gtk_tree_selection_get_selected (GTK_TREE_SELECTION (selection), &model, &iter)) {
1012
 
                gtk_tree_model_get (model, &iter, 0, &country, 1, &unlisted, -1);
1013
 
                if (unlisted) {
1014
 
                        g_free (country);
1015
 
                        country = NULL;
1016
 
                        if (out_unlisted)
1017
 
                                *out_unlisted = unlisted;
1018
 
                }
1019
 
        }
1020
 
 
1021
 
        return country;
1022
 
}
1023
 
 
1024
 
static void
1025
 
country_update_complete (NMAMobileWizard *self)
1026
 
{
1027
 
        char *country = NULL;
1028
 
        gboolean unlisted = FALSE;
1029
 
 
1030
 
        country = get_selected_country (self, &unlisted);
1031
 
        gtk_assistant_set_page_complete (GTK_ASSISTANT (self->assistant),
1032
 
                                         self->country_page,
1033
 
                                         (!!country || unlisted));
1034
 
        g_free (country);
1035
 
}
1036
 
 
1037
 
static gint
1038
 
country_sort_func (GtkTreeModel *model,
1039
 
                   GtkTreeIter *a,
1040
 
                   GtkTreeIter *b,
1041
 
                   gpointer user_data)
1042
 
{
1043
 
        char *a_str = NULL, *b_str = NULL;
1044
 
        gboolean a_def = FALSE, b_def = FALSE;
1045
 
        gint ret = 0;
1046
 
 
1047
 
        gtk_tree_model_get (model, a, 0, &a_str, 1, &a_def, -1);
1048
 
        gtk_tree_model_get (model, b, 0, &b_str, 1, &b_def, -1);
1049
 
 
1050
 
        if (a_def) {
1051
 
                ret = -1;
1052
 
                goto out;
1053
 
        } else if (b_def) {
1054
 
                ret = 1;
1055
 
                goto out;
1056
 
        }
1057
 
 
1058
 
        if (a_str && !b_str)
1059
 
                ret = -1;
1060
 
        else if (!a_str && b_str)
1061
 
                ret = 1;
1062
 
        else if (!a_str && !b_str)
1063
 
                ret = 0;
1064
 
        else
1065
 
                ret = g_utf8_collate (a_str, b_str);
1066
 
 
1067
 
out:
1068
 
        g_free (a_str);
1069
 
        g_free (b_str);
1070
 
        return ret;
1071
 
}
1072
 
 
1073
 
static void
1074
 
country_setup (NMAMobileWizard *self)
1075
 
{
1076
 
        GtkWidget *vbox, *label, *scroll, *alignment;
1077
 
        GtkCellRenderer *renderer;
1078
 
        GtkTreeViewColumn *column;
1079
 
        GtkTreeSelection *selection;
1080
 
        GtkTreeIter unlisted_iter;
1081
 
 
1082
 
#if GTK_CHECK_VERSION(3,1,6)
1083
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1084
 
#else
1085
 
        vbox = gtk_vbox_new (FALSE, 6);
1086
 
#endif
1087
 
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
1088
 
        label = gtk_label_new (_("Country or Region List:"));
1089
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1090
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
1091
 
 
1092
 
        self->country_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
1093
 
 
1094
 
        self->country_sort = GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (self->country_store)));
1095
 
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->country_sort), 0, GTK_SORT_ASCENDING);
1096
 
 
1097
 
        self->country_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (self->country_sort));
1098
 
 
1099
 
        renderer = gtk_cell_renderer_text_new ();
1100
 
        column = gtk_tree_view_column_new_with_attributes (_("Country or region"), renderer, "text", 0, NULL);
1101
 
        gtk_tree_view_append_column (GTK_TREE_VIEW (self->country_view), column);
1102
 
        gtk_tree_view_column_set_clickable (column, TRUE);
1103
 
 
1104
 
        /* My country is not listed... */
1105
 
        gtk_tree_store_append (GTK_TREE_STORE (self->country_store), &unlisted_iter, NULL);
1106
 
        gtk_tree_store_set (GTK_TREE_STORE (self->country_store), &unlisted_iter,
1107
 
                            0, _("My country is not listed"),
1108
 
                            1, TRUE,
1109
 
                            -1);
1110
 
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (self->country_sort),
1111
 
                                         0,
1112
 
                                         country_sort_func,
1113
 
                                         NULL,
1114
 
                                         NULL);
1115
 
 
1116
 
        /* Add the rest of the providers */
1117
 
        if (self->providers)
1118
 
                g_hash_table_foreach (self->providers, add_one_country, self);
1119
 
        g_object_set (G_OBJECT (self->country_view), "enable-search", TRUE, NULL);
1120
 
 
1121
 
        /* If no row has focus yet, focus the first row so that the user can start
1122
 
         * incremental search without clicking.
1123
 
         */
1124
 
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->country_view));
1125
 
        g_assert (selection);
1126
 
        if (!gtk_tree_selection_count_selected_rows (selection)) {
1127
 
                GtkTreeIter first_iter;
1128
 
                GtkTreePath *first_path;
1129
 
 
1130
 
                if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->country_sort), &first_iter)) {
1131
 
                        first_path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->country_sort), &first_iter);
1132
 
                        if (first_path) {
1133
 
                                gtk_tree_selection_select_path (selection, first_path);
1134
 
                                gtk_tree_path_free (first_path);
1135
 
                        }
1136
 
                }
1137
 
        }
1138
 
 
1139
 
        g_signal_connect_swapped (selection, "changed", G_CALLBACK (country_update_complete), self);
1140
 
 
1141
 
        scroll = gtk_scrolled_window_new (NULL, NULL);
1142
 
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
1143
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
1144
 
                                        GTK_POLICY_NEVER,
1145
 
                                        GTK_POLICY_AUTOMATIC);
1146
 
        gtk_container_add (GTK_CONTAINER (scroll), self->country_view);
1147
 
 
1148
 
        alignment = gtk_alignment_new (0, 0, 1, 1);
1149
 
        gtk_container_add (GTK_CONTAINER (alignment), scroll);
1150
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, TRUE, TRUE, 6);
1151
 
 
1152
 
        self->country_idx = gtk_assistant_append_page (GTK_ASSISTANT (self->assistant), vbox);
1153
 
        gtk_assistant_set_page_title (GTK_ASSISTANT (self->assistant), vbox, _("Choose your Provider's Country or Region"));
1154
 
        gtk_assistant_set_page_type (GTK_ASSISTANT (self->assistant), vbox, GTK_ASSISTANT_PAGE_CONTENT);
1155
 
        gtk_assistant_set_page_complete (GTK_ASSISTANT (self->assistant), vbox, TRUE);
1156
 
        gtk_widget_show_all (vbox);
1157
 
 
1158
 
        self->country_page = vbox;
1159
 
 
1160
 
        /* Initial completeness state */
1161
 
        country_update_complete (self);
1162
 
}
1163
 
 
1164
 
static gboolean
1165
 
focus_country_view (gpointer user_data)
1166
 
{
1167
 
        NMAMobileWizard *self = user_data;
1168
 
 
1169
 
        self->country_focus_id = 0;
1170
 
        gtk_widget_grab_focus (self->country_view);
1171
 
        return FALSE;
1172
 
}
1173
 
 
1174
 
static void
1175
 
country_prepare (NMAMobileWizard *self)
1176
 
{
1177
 
        gtk_tree_view_set_search_column (GTK_TREE_VIEW (self->country_view), 0);
1178
 
        gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (self->country_view), country_search_func, self, NULL);
1179
 
 
1180
 
        if (!self->country_focus_id)
1181
 
                self->country_focus_id = g_idle_add (focus_country_view, self);
1182
 
 
1183
 
        country_update_complete (self);
1184
 
}
1185
 
 
1186
 
/**********************************************************/
1187
 
/* Intro page */
1188
 
/**********************************************************/
1189
 
 
1190
 
#define INTRO_COL_NAME 0
1191
 
#define INTRO_COL_DEVICE 1
1192
 
#define INTRO_COL_SEPARATOR 2
1193
 
 
1194
 
static gboolean
1195
 
__intro_device_added (NMAMobileWizard *self, NMDevice *device, gboolean select_it)
1196
 
{
1197
 
        GtkTreeIter iter;
1198
 
        const char *desc = utils_get_device_description (device);
1199
 
        NMDeviceModemCapabilities caps;
1200
 
 
1201
 
        if (!NM_IS_DEVICE_MODEM (device))
1202
 
                return FALSE;
1203
 
 
1204
 
        caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
1205
 
        if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) {
1206
 
                if (!desc)
1207
 
                        desc = _("Installed GSM device");
1208
 
        } else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
1209
 
                if (!desc)
1210
 
                        desc = _("Installed CDMA device");
1211
 
        } else
1212
 
                return FALSE;
1213
 
 
1214
 
        gtk_tree_store_append (GTK_TREE_STORE (self->dev_store), &iter, NULL);
1215
 
        gtk_tree_store_set (GTK_TREE_STORE (self->dev_store),
1216
 
                            &iter,
1217
 
                            INTRO_COL_NAME, desc,
1218
 
                            INTRO_COL_DEVICE, device,
1219
 
                            -1);
1220
 
 
1221
 
        /* Select the device just added */
1222
 
        if (select_it)
1223
 
                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self->dev_combo), &iter);
1224
 
 
1225
 
        gtk_widget_set_sensitive (self->dev_combo, TRUE);
1226
 
        return TRUE;
1227
 
}
1228
 
 
1229
 
static void
1230
 
intro_device_added_cb (NMClient *client, NMDevice *device, NMAMobileWizard *self)
1231
 
{
1232
 
        __intro_device_added (self, device, TRUE);
1233
 
}
1234
 
 
1235
 
static void
1236
 
intro_device_removed_cb (NMClient *client, NMDevice *device, NMAMobileWizard *self)
1237
 
{
1238
 
        GtkTreeIter iter;
1239
 
        gboolean have_device = FALSE, removed = FALSE;
1240
 
 
1241
 
        if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->dev_store), &iter))
1242
 
                return;
1243
 
 
1244
 
        do {
1245
 
                NMDevice *candidate = NULL;
1246
 
 
1247
 
                gtk_tree_model_get (GTK_TREE_MODEL (self->dev_store), &iter,
1248
 
                                    INTRO_COL_DEVICE, &candidate, -1);
1249
 
                if (candidate) {
1250
 
                        if (candidate == device) {
1251
 
                                gtk_tree_store_remove (GTK_TREE_STORE (self->dev_store), &iter);
1252
 
                                removed = TRUE;
1253
 
                        }
1254
 
                        g_object_unref (candidate);
1255
 
                }
1256
 
        } while (!removed && gtk_tree_model_iter_next (GTK_TREE_MODEL (self->dev_store), &iter));
1257
 
 
1258
 
        /* There's already a selected device item; nothing more to do */
1259
 
        if (gtk_combo_box_get_active (GTK_COMBO_BOX (self->dev_combo)) > 1)
1260
 
                return;
1261
 
 
1262
 
        /* If there are no more devices, select the "Any" item and disable the
1263
 
         * combo box.  If there is no selected item and there is at least one device
1264
 
         * item, select the first one.
1265
 
         */
1266
 
        if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->dev_store), &iter))
1267
 
                return;
1268
 
 
1269
 
        do {
1270
 
                NMDevice *candidate = NULL;
1271
 
 
1272
 
                gtk_tree_model_get (GTK_TREE_MODEL (self->dev_store), &iter,
1273
 
                                    INTRO_COL_DEVICE, &candidate, -1);
1274
 
                if (candidate) {
1275
 
                        have_device = TRUE;
1276
 
                        g_object_unref (candidate);
1277
 
                }
1278
 
        } while (!have_device && gtk_tree_model_iter_next (GTK_TREE_MODEL (self->dev_store), &iter));
1279
 
 
1280
 
        if (have_device) {
1281
 
                /* Iter should point to the last device item in the combo */
1282
 
                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self->dev_combo), &iter);
1283
 
        } else {
1284
 
                gtk_combo_box_set_active (GTK_COMBO_BOX (self->dev_combo), 0);
1285
 
                gtk_widget_set_sensitive (self->dev_combo, FALSE);
1286
 
        }
1287
 
}
1288
 
 
1289
 
static void
1290
 
intro_add_initial_devices (NMAMobileWizard *self)
1291
 
{
1292
 
        const GPtrArray *devices;
1293
 
        gboolean selected_first = FALSE;
1294
 
        int i;
1295
 
 
1296
 
        devices = nm_client_get_devices (self->client);
1297
 
        for (i = 0; devices && (i < devices->len); i++) {
1298
 
                if (__intro_device_added (self, g_ptr_array_index (devices, i), !selected_first)) {
1299
 
                        if (selected_first == FALSE)
1300
 
                                selected_first = TRUE;
1301
 
                }
1302
 
        }
1303
 
 
1304
 
        /* Otherwise the "Any device" item */
1305
 
        if (!selected_first) {
1306
 
                /* Select the first device item by default */
1307
 
                gtk_combo_box_set_active (GTK_COMBO_BOX (self->dev_combo), 0);
1308
 
                gtk_widget_set_sensitive (self->dev_combo, FALSE);
1309
 
        }
1310
 
}
1311
 
 
1312
 
static void
1313
 
intro_remove_all_devices (NMAMobileWizard *self)
1314
 
{
1315
 
        gtk_tree_store_clear (self->dev_store);
1316
 
 
1317
 
        /* Select the "Any device" item */
1318
 
        gtk_combo_box_set_active (GTK_COMBO_BOX (self->dev_combo), 0);
1319
 
        gtk_widget_set_sensitive (self->dev_combo, FALSE);
1320
 
}
1321
 
 
1322
 
static void
1323
 
intro_manager_running_cb (NMClient *client, GParamSpec *pspec, NMAMobileWizard *self)
1324
 
{
1325
 
        if (nm_client_get_manager_running (client))
1326
 
                intro_add_initial_devices (self);
1327
 
        else
1328
 
                intro_remove_all_devices (self);
1329
 
}
1330
 
 
1331
 
static gboolean
1332
 
intro_row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
1333
 
{
1334
 
        gboolean separator = FALSE;
1335
 
        gtk_tree_model_get (model, iter, INTRO_COL_SEPARATOR, &separator, -1);
1336
 
        return separator;
1337
 
}
1338
 
 
1339
 
static void
1340
 
intro_combo_changed (NMAMobileWizard *self)
1341
 
{
1342
 
        GtkTreeIter iter;
1343
 
        NMDevice *selected = NULL;
1344
 
        NMDeviceModemCapabilities caps;
1345
 
 
1346
 
        g_free (self->dev_desc);
1347
 
        self->dev_desc = NULL;
1348
 
 
1349
 
        if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->dev_combo), &iter))
1350
 
                return;
1351
 
 
1352
 
        gtk_tree_model_get (GTK_TREE_MODEL (self->dev_store), &iter,
1353
 
                            INTRO_COL_DEVICE, &selected, -1);
1354
 
        if (selected) {
1355
 
                self->dev_desc = g_strdup (utils_get_device_description (selected));
1356
 
                caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (selected));
1357
 
                if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS)
1358
 
                        self->method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_GSM;
1359
 
                else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)
1360
 
                        self->method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA;
1361
 
                else
1362
 
                        g_warning ("%s: unknown modem capabilities 0x%X", __func__, caps);
1363
 
 
1364
 
                g_object_unref (selected);
1365
 
        }
1366
 
}
1367
 
 
1368
 
static void
1369
 
intro_setup (NMAMobileWizard *self)
1370
 
{
1371
 
        GtkWidget *vbox, *label, *alignment, *info_vbox;
1372
 
        GtkCellRenderer *renderer;
1373
 
        char *s;
1374
 
 
1375
 
#if GTK_CHECK_VERSION(3,1,6)
1376
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1377
 
#else
1378
 
        vbox = gtk_vbox_new (FALSE, 6);
1379
 
#endif
1380
 
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
1381
 
 
1382
 
        label = gtk_label_new (_("This assistant helps you easily set up a mobile broadband connection to a cellular (3G) network."));
1383
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1384
 
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1385
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 6);
1386
 
 
1387
 
        label = gtk_label_new (_("You will need the following information:"));
1388
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1389
 
        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1390
 
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 6);
1391
 
 
1392
 
        alignment = gtk_alignment_new (0, 0, 1, 0);
1393
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 25, 25, 0);
1394
 
#if GTK_CHECK_VERSION(3,1,6)
1395
 
        info_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1396
 
#else
1397
 
        info_vbox = gtk_vbox_new (FALSE, 6);
1398
 
#endif
1399
 
        gtk_container_add (GTK_CONTAINER (alignment), info_vbox);
1400
 
        gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 6);
1401
 
 
1402
 
        s = g_strdup_printf ("• %s", _("Your broadband provider's name"));
1403
 
        label = gtk_label_new (s);
1404
 
        g_free (s);
1405
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1406
 
        gtk_box_pack_start (GTK_BOX (info_vbox), label, FALSE, TRUE, 0);
1407
 
 
1408
 
        s = g_strdup_printf ("• %s", _("Your broadband billing plan name"));
1409
 
        label = gtk_label_new (s);
1410
 
        g_free (s);
1411
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1412
 
        gtk_box_pack_start (GTK_BOX (info_vbox), label, FALSE, TRUE, 0);
1413
 
 
1414
 
        s = g_strdup_printf ("• %s", _("(in some cases) Your broadband billing plan APN (Access Point Name)"));
1415
 
        label = gtk_label_new (s);
1416
 
        g_free (s);
1417
 
        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1418
 
        gtk_box_pack_start (GTK_BOX (info_vbox), label, FALSE, TRUE, 0);
1419
 
 
1420
 
        /* Device combo; only built if the wizard's caller didn't pass one in */
1421
 
        if (!self->initial_method_type) {
1422
 
                GtkTreeIter iter;
1423
 
 
1424
 
                self->client = nm_client_new ();
1425
 
                g_signal_connect (self->client, "device-added",
1426
 
                                  G_CALLBACK (intro_device_added_cb), self);
1427
 
                g_signal_connect (self->client, "device-removed",
1428
 
                                  G_CALLBACK (intro_device_removed_cb), self);
1429
 
                g_signal_connect (self->client, "notify::manager-running",
1430
 
                                  G_CALLBACK (intro_manager_running_cb), self);
1431
 
 
1432
 
                self->dev_store = gtk_tree_store_new (3, G_TYPE_STRING, NM_TYPE_DEVICE, G_TYPE_BOOLEAN);
1433
 
                self->dev_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (self->dev_store));
1434
 
                gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (self->dev_combo),
1435
 
                                                      intro_row_separator_func, NULL, NULL);
1436
 
 
1437
 
                renderer = gtk_cell_renderer_text_new ();
1438
 
                gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self->dev_combo), renderer, TRUE);
1439
 
                gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self->dev_combo), renderer, "text", INTRO_COL_NAME);
1440
 
 
1441
 
                label = gtk_label_new_with_mnemonic (_("Create a connection for _this mobile broadband device:"));
1442
 
                gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->dev_combo);
1443
 
                gtk_misc_set_alignment (GTK_MISC (label), 0, 1);
1444
 
                gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1445
 
 
1446
 
                alignment = gtk_alignment_new (0, 0, 0.5, 0);
1447
 
                gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 25, 0);
1448
 
                gtk_container_add (GTK_CONTAINER (alignment), self->dev_combo);
1449
 
                gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
1450
 
 
1451
 
                g_signal_connect_swapped (self->dev_combo, "changed", G_CALLBACK (intro_combo_changed), self);
1452
 
 
1453
 
                /* Any device */
1454
 
                gtk_tree_store_append (GTK_TREE_STORE (self->dev_store), &iter, NULL);
1455
 
                gtk_tree_store_set (GTK_TREE_STORE (self->dev_store), &iter,
1456
 
                                    INTRO_COL_NAME, _("Any device"), -1);
1457
 
 
1458
 
                /* Separator */
1459
 
                gtk_tree_store_append (GTK_TREE_STORE (self->dev_store), &iter, NULL);
1460
 
                gtk_tree_store_set (GTK_TREE_STORE (self->dev_store), &iter,
1461
 
                                    INTRO_COL_SEPARATOR, TRUE, -1);
1462
 
 
1463
 
                intro_add_initial_devices (self);
1464
 
        }
1465
 
 
1466
 
        gtk_widget_show_all (vbox);
1467
 
        gtk_assistant_append_page (GTK_ASSISTANT (self->assistant), vbox);
1468
 
        gtk_assistant_set_page_title (GTK_ASSISTANT (self->assistant),
1469
 
                                      vbox, _("Set up a Mobile Broadband Connection"));
1470
 
 
1471
 
        gtk_assistant_set_page_complete (GTK_ASSISTANT (self->assistant), vbox, TRUE);
1472
 
        gtk_assistant_set_page_type (GTK_ASSISTANT (self->assistant), vbox, GTK_ASSISTANT_PAGE_INTRO);
1473
 
}
1474
 
 
1475
 
/**********************************************************/
1476
 
/* General assistant stuff */
1477
 
/**********************************************************/
1478
 
 
1479
 
static void
1480
 
remove_provider_focus_idle (NMAMobileWizard *self)
1481
 
{
1482
 
        if (self->providers_focus_id) {
1483
 
                g_source_remove (self->providers_focus_id);
1484
 
                self->providers_focus_id = 0;
1485
 
        }
1486
 
}
1487
 
 
1488
 
static void
1489
 
remove_country_focus_idle (NMAMobileWizard *self)
1490
 
{
1491
 
        if (self->country_focus_id) {
1492
 
                g_source_remove (self->country_focus_id);
1493
 
                self->country_focus_id = 0;
1494
 
        }
1495
 
}
1496
 
 
1497
 
static void
1498
 
assistant_prepare (GtkAssistant *assistant, GtkWidget *page, gpointer user_data)
1499
 
{
1500
 
        NMAMobileWizard *self = user_data;
1501
 
 
1502
 
        if (page != self->providers_page)
1503
 
                remove_provider_focus_idle (self);
1504
 
        if (page != self->country_page)
1505
 
                remove_country_focus_idle (self);
1506
 
 
1507
 
        if (page == self->country_page)
1508
 
                country_prepare (self);
1509
 
        else if (page == self->providers_page)
1510
 
                providers_prepare (self);
1511
 
        else if (page == self->plan_page)
1512
 
                plan_prepare (self);
1513
 
        else if (page == self->confirm_page)
1514
 
                confirm_prepare (self);
1515
 
}
1516
 
 
1517
 
static gint
1518
 
forward_func (gint current_page, gpointer user_data)
1519
 
{
1520
 
        NMAMobileWizard *self = user_data;
1521
 
 
1522
 
        if (current_page == self->providers_idx) {
1523
 
                NmnMobileAccessMethodType method_type = self->method_type;
1524
 
 
1525
 
                /* If the provider is unlisted, we can skip ahead of the user's
1526
 
                 * access technology is CDMA.
1527
 
                 */
1528
 
                if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->provider_unlisted_radio))) {
1529
 
                        if (method_type == NMN_MOBILE_ACCESS_METHOD_TYPE_UNKNOWN)
1530
 
                                method_type = get_provider_unlisted_type (self);
1531
 
                } else {
1532
 
                        /* Or, if the provider is only CDMA, then we can also skip ahead */
1533
 
                        NmnMobileProvider *provider;
1534
 
                        GSList *iter;
1535
 
                        gboolean gsm = FALSE, cdma = FALSE;
1536
 
 
1537
 
                        provider = get_selected_provider (self);
1538
 
                        if (provider) {
1539
 
                                for (iter = provider->methods; iter; iter = g_slist_next (iter)) {
1540
 
                                        NmnMobileAccessMethod *method = iter->data;
1541
 
 
1542
 
                                        if (method->type == NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA)
1543
 
                                                cdma = TRUE;
1544
 
                                        else if (method->type == NMN_MOBILE_ACCESS_METHOD_TYPE_GSM)
1545
 
                                                gsm = TRUE;
1546
 
                                }
1547
 
                                nmn_mobile_provider_unref (provider);
1548
 
 
1549
 
                                if (cdma && !gsm)
1550
 
                                        method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA;
1551
 
                        }
1552
 
                }
1553
 
 
1554
 
                /* Skip to the confirm page if we know its CDMA */
1555
 
                if (method_type == NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA) {
1556
 
                        self->provider_only_cdma = TRUE;
1557
 
                        return self->confirm_idx;
1558
 
                } else
1559
 
                        self->provider_only_cdma = FALSE;
1560
 
        }
1561
 
 
1562
 
        return current_page + 1;
1563
 
}
1564
 
 
1565
 
static char *
1566
 
get_country_from_locale (void)
1567
 
{
1568
 
        char *p, *m, *cc, *lang;
1569
 
 
1570
 
        lang = getenv ("LC_ALL");
1571
 
        if (!lang)
1572
 
                lang = getenv ("LANG");
1573
 
        if (!lang)
1574
 
                return NULL;
1575
 
 
1576
 
        p = strchr (lang, '_');
1577
 
        if (!p || !strlen (p)) {
1578
 
                g_free (p);
1579
 
                return NULL;
1580
 
        }
1581
 
 
1582
 
        p = cc = g_strdup (++p);
1583
 
        m = strchr (cc, '.');
1584
 
        if (m)
1585
 
                *m = '\0';
1586
 
 
1587
 
        while (*p) {
1588
 
                *p = g_ascii_toupper (*p);
1589
 
                p++;
1590
 
        }
1591
 
 
1592
 
        return cc;
1593
 
}
1594
 
 
1595
 
NMAMobileWizard *
1596
 
nma_mobile_wizard_new (GtkWindow *parent,
1597
 
                   GtkWindowGroup *window_group,
1598
 
                   NMDeviceModemCapabilities modem_caps,
1599
 
                   gboolean will_connect_after,
1600
 
                   NMAMobileWizardCallback cb,
1601
 
                   gpointer user_data)
1602
 
{
1603
 
        NMAMobileWizard *self;
1604
 
        char *cc;
1605
 
 
1606
 
        self = g_malloc0 (sizeof (NMAMobileWizard));
1607
 
        g_return_val_if_fail (self != NULL, NULL);
1608
 
 
1609
 
        self->providers = nmn_mobile_providers_parse (&(self->country_codes));
1610
 
        if (!self->providers || !self->country_codes) {
1611
 
                nma_mobile_wizard_destroy (self);
1612
 
                return NULL;
1613
 
        }
1614
 
 
1615
 
        cc = get_country_from_locale ();
1616
 
        if (cc)
1617
 
                self->country = g_hash_table_lookup (self->country_codes, cc);
1618
 
        g_free (cc);
1619
 
 
1620
 
        self->will_connect_after = will_connect_after;
1621
 
        self->callback = cb;
1622
 
        self->user_data = user_data;
1623
 
        if (modem_caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS)
1624
 
                self->method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_GSM;
1625
 
        else if (modem_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)
1626
 
                self->method_type = NMN_MOBILE_ACCESS_METHOD_TYPE_CDMA;
1627
 
        if (self->method_type)
1628
 
                self->initial_method_type = TRUE;  /* Skip device selection */
1629
 
 
1630
 
        self->assistant = gtk_assistant_new ();
1631
 
        gtk_assistant_set_forward_page_func (GTK_ASSISTANT (self->assistant),
1632
 
                                             forward_func, self, NULL);
1633
 
        gtk_window_set_title (GTK_WINDOW (self->assistant), _("New Mobile Broadband Connection"));
1634
 
        gtk_window_set_position (GTK_WINDOW (self->assistant), GTK_WIN_POS_CENTER_ALWAYS);
1635
 
 
1636
 
        intro_setup (self);
1637
 
        country_setup (self);
1638
 
        providers_setup (self);
1639
 
        plan_setup (self);
1640
 
        confirm_setup (self);
1641
 
 
1642
 
        g_signal_connect (self->assistant, "close", G_CALLBACK (assistant_closed), self);
1643
 
        g_signal_connect (self->assistant, "cancel", G_CALLBACK (assistant_cancel), self);
1644
 
        g_signal_connect (self->assistant, "prepare", G_CALLBACK (assistant_prepare), self);
1645
 
 
1646
 
        /* Run the wizard */
1647
 
        if (parent)
1648
 
                gtk_window_set_transient_for (GTK_WINDOW (self->assistant), parent);
1649
 
        gtk_window_set_modal (GTK_WINDOW (self->assistant), TRUE);
1650
 
        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (self->assistant), TRUE);
1651
 
        gtk_window_set_type_hint (GTK_WINDOW (self->assistant), GDK_WINDOW_TYPE_HINT_DIALOG);
1652
 
 
1653
 
        if (window_group)
1654
 
                gtk_window_group_add_window (window_group, GTK_WINDOW (self->assistant));
1655
 
 
1656
 
        return self;
1657
 
}
1658
 
 
1659
 
void
1660
 
nma_mobile_wizard_present (NMAMobileWizard *self)
1661
 
{
1662
 
        g_return_if_fail (self != NULL);
1663
 
 
1664
 
        gtk_window_present (GTK_WINDOW (self->assistant));
1665
 
        gtk_widget_show_all (self->assistant);
1666
 
}
1667
 
 
1668
 
void
1669
 
nma_mobile_wizard_destroy (NMAMobileWizard *self)
1670
 
{
1671
 
        g_return_if_fail (self != NULL);
1672
 
 
1673
 
        g_free (self->dev_desc);
1674
 
 
1675
 
        if (self->assistant) {
1676
 
                gtk_widget_hide (self->assistant);
1677
 
                gtk_widget_destroy (self->assistant);
1678
 
        }
1679
 
 
1680
 
        if (self->client)
1681
 
                g_object_unref (self->client);
1682
 
 
1683
 
        remove_provider_focus_idle (self);
1684
 
        remove_country_focus_idle (self);
1685
 
 
1686
 
        if (self->providers)
1687
 
                g_hash_table_destroy (self->providers);
1688
 
 
1689
 
        if (self->country_codes)
1690
 
                g_hash_table_destroy (self->country_codes);
1691
 
 
1692
 
        g_free (self);
1693
 
}
1694
 
 
1695