~ubuntu-branches/ubuntu/saucy/wicd/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/09-allow_empty_DNS.patch/gtk/gui.py

  • Committer: Bazaar Package Importer
  • Author(s): David Paleino
  • Date: 2010-03-04 10:59:30 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100304105930-jihcz2fn8e77uqbb
Tags: 1.7.0+ds1-1
* New repacked tarball, contains translations .po files
  (Closes: #572352)
* debian/bug-control added, let's add more info to the bugreports!
* debian/control:
  - debhelper dependency bumped to >= 7.2.3~, to use dh_bugfiles
  - added dependency on python-iniparse to wicd-daemon
* debian/rules:
  - make dh_bugfiles act on all packages
  - add get-orig-source target, to build a package containing the
    .po files
* debian/patches/:
  - 20-use_iniparse.patch added, uses python-iniparse instead of
    standard library's ConfigParser (Closes: #568326)
  - 21-fix_ESSID_setting.patch added, use correct command to set
    ESSID's (useful when a network is named "off" or "any")
    (Closes: #571100)
  - 22-fix_deprecation.patch added, fixes some deprecated usage of
    gtk.Statusbar (Closes: #571314)
* debian/watch updated to mangle Debian version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
""" gui -- The main wicd GUI module.
 
4
 
 
5
Module containing the code for the main wicd GUI.
 
6
 
 
7
"""
 
8
 
 
9
#
 
10
#   Copyright (C) 2007-2009 Adam Blackburn
 
11
#   Copyright (C) 2007-2009 Dan O'Reilly
 
12
#
 
13
#   This program is free software; you can redistribute it and/or modify
 
14
#   it under the terms of the GNU General Public License Version 2 as
 
15
#   published by the Free Software Foundation.
 
16
#
 
17
#   This program is distributed in the hope that it will be useful,
 
18
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
#   GNU General Public License for more details.
 
21
#
 
22
#   You should have received a copy of the GNU General Public License
 
23
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
24
#
 
25
 
 
26
import os
 
27
import sys
 
28
import time
 
29
import gobject
 
30
import pango
 
31
import gtk
 
32
import gtk.glade
 
33
from itertools import chain
 
34
from dbus import DBusException
 
35
 
 
36
from wicd import misc
 
37
from wicd import wpath
 
38
from wicd import dbusmanager
 
39
from wicd.misc import noneToString
 
40
import prefs
 
41
from prefs import PreferencesDialog
 
42
import netentry
 
43
from netentry import WiredNetworkEntry, WirelessNetworkEntry
 
44
from guiutil import error, LabelEntry
 
45
from wicd.translations import language
 
46
 
 
47
if __name__ == '__main__':
 
48
    wpath.chdir(__file__)
 
49
 
 
50
proxy_obj = daemon = wireless = wired = bus = None
 
51
DBUS_AVAIL = False
 
52
 
 
53
def setup_dbus(force=True):
 
54
    global bus, daemon, wireless, wired, DBUS_AVAIL
 
55
    try:
 
56
        dbusmanager.connect_to_dbus()
 
57
    except DBusException:
 
58
        if force:
 
59
            print "Can't connect to the daemon, trying to start it automatically..."
 
60
            if not misc.PromptToStartDaemon():
 
61
                print "Failed to find a graphical sudo program, cannot continue."
 
62
                return False
 
63
            try:
 
64
                dbusmanager.connect_to_dbus()
 
65
            except DBusException:
 
66
                error(None, "Could not connect to wicd's D-Bus interface.  " +
 
67
                      "Check the wicd log for error messages.")
 
68
                return False
 
69
        else:  
 
70
            return False
 
71
    prefs.setup_dbus()
 
72
    netentry.setup_dbus()
 
73
    bus = dbusmanager.get_bus()
 
74
    dbus_ifaces = dbusmanager.get_dbus_ifaces()
 
75
    daemon = dbus_ifaces['daemon']
 
76
    wireless = dbus_ifaces['wireless']
 
77
    wired = dbus_ifaces['wired']
 
78
    DBUS_AVAIL = True
 
79
    
 
80
    return True
 
81
 
 
82
def handle_no_dbus(from_tray=False):
 
83
    global DBUS_AVAIL
 
84
    DBUS_AVAIL = False
 
85
    if from_tray: return False
 
86
    print "Wicd daemon is shutting down!"
 
87
    error(None, language['lost_dbus'], block=False)
 
88
    return False
 
89
 
 
90
        
 
91
class WiredProfileChooser:
 
92
    """ Class for displaying the wired profile chooser. """
 
93
    def __init__(self):
 
94
        """ Initializes and runs the wired profile chooser. """
 
95
        # Import and init WiredNetworkEntry to steal some of the
 
96
        # functions and widgets it uses.
 
97
        wired_net_entry = WiredNetworkEntry()
 
98
 
 
99
        dialog = gtk.Dialog(title = language['wired_network_found'],
 
100
                            flags = gtk.DIALOG_MODAL,
 
101
                            buttons = (gtk.STOCK_CONNECT, 1,
 
102
                                       gtk.STOCK_CANCEL, 2))
 
103
        dialog.set_has_separator(False)
 
104
        dialog.set_size_request(400, 150)
 
105
        instruct_label = gtk.Label(language['choose_wired_profile'] + ':\n')
 
106
        stoppopcheckbox = gtk.CheckButton(language['stop_showing_chooser'])
 
107
 
 
108
        wired_net_entry.is_full_gui = False
 
109
        instruct_label.set_alignment(0, 0)
 
110
        stoppopcheckbox.set_active(False)
 
111
 
 
112
        # Remove widgets that were added to the normal WiredNetworkEntry
 
113
        # so that they can be added to the pop-up wizard.
 
114
        wired_net_entry.vbox_top.remove(wired_net_entry.hbox_temp)
 
115
        wired_net_entry.vbox_top.remove(wired_net_entry.profile_help)
 
116
 
 
117
        dialog.vbox.pack_start(instruct_label, fill=False, expand=False)
 
118
        dialog.vbox.pack_start(wired_net_entry.profile_help, False, False)
 
119
        dialog.vbox.pack_start(wired_net_entry.hbox_temp, False, False)
 
120
        dialog.vbox.pack_start(stoppopcheckbox, False, False)
 
121
        dialog.show_all()
 
122
 
 
123
        wired_profiles = wired_net_entry.combo_profile_names
 
124
        wired_net_entry.profile_help.hide()
 
125
        if wired_net_entry.profile_list != None:
 
126
            wired_profiles.set_active(0)
 
127
            print "wired profiles found"
 
128
        else:
 
129
            print "no wired profiles found"
 
130
            wired_net_entry.profile_help.show()
 
131
 
 
132
        response = dialog.run()
 
133
        if response == 1:
 
134
            print 'reading profile ', wired_profiles.get_active_text()
 
135
            wired.ReadWiredNetworkProfile(wired_profiles.get_active_text())
 
136
            wired.ConnectWired()
 
137
        else:
 
138
            if stoppopcheckbox.get_active():
 
139
                daemon.SetForcedDisconnect(True)
 
140
        dialog.destroy()
 
141
 
 
142
 
 
143
class appGui(object):
 
144
    """ The main wicd GUI class. """
 
145
    def __init__(self, standalone=False, tray=None):
 
146
        """ Initializes everything needed for the GUI. """
 
147
        setup_dbus()
 
148
 
 
149
        self.tray = tray
 
150
 
 
151
        gladefile = os.path.join(wpath.gtk, "wicd.glade")
 
152
        self.wTree = gtk.glade.XML(gladefile)
 
153
        self.window = self.wTree.get_widget("window1")
 
154
        self.window.set_icon_name("wicd-gtk")
 
155
        size = daemon.ReadWindowSize("main")
 
156
        width = size[0]
 
157
        height = size[1]
 
158
        if width > -1 and height > -1:
 
159
            self.window.resize(int(width), int(height))
 
160
        else:
 
161
            width = int(gtk.gdk.screen_width() / 2)
 
162
            if width > 530:
 
163
                width = 530
 
164
            self.window.resize(width, int(gtk.gdk.screen_height() / 1.7))
 
165
 
 
166
        dic = { "refresh_clicked" : self.refresh_clicked, 
 
167
                "quit_clicked" : self.exit, 
 
168
                "disconnect_clicked" : self.disconnect_all,
 
169
                "main_exit" : self.exit, 
 
170
                "cancel_clicked" : self.cancel_connect,
 
171
                "hidden_clicked" : self.connect_hidden,
 
172
                "preferences_clicked" : self.settings_dialog,
 
173
                "about_clicked" : self.about_dialog,
 
174
                "create_adhoc_clicked" : self.create_adhoc_network,
 
175
                }
 
176
        self.wTree.signal_autoconnect(dic)
 
177
 
 
178
        # Set some strings in the GUI - they may be translated
 
179
        label_instruct = self.wTree.get_widget("label_instructions")
 
180
        label_instruct.set_label(language['select_a_network'])
 
181
 
 
182
        probar = self.wTree.get_widget("progressbar")
 
183
        probar.set_text(language['connecting'])
 
184
        
 
185
        self.all_network_list = self.wTree.get_widget("network_list_vbox")
 
186
        self.all_network_list.show_all()
 
187
        self.wired_network_box = gtk.VBox(False, 0)
 
188
        self.wired_network_box.show_all()
 
189
        self.network_list = gtk.VBox(False, 0)
 
190
        self.all_network_list.pack_start(self.wired_network_box, False, False)
 
191
        self.all_network_list.pack_start(self.network_list, True, True)
 
192
        self.network_list.show_all()
 
193
        self.status_area = self.wTree.get_widget("connecting_hbox")
 
194
        self.status_bar = self.wTree.get_widget("statusbar")
 
195
        menu = self.wTree.get_widget("menu1")
 
196
 
 
197
        self.status_area.hide_all()
 
198
 
 
199
        if os.path.exists(os.path.join(wpath.images, "wicd.png")):
 
200
            self.window.set_icon_from_file(os.path.join(wpath.images, "wicd.png"))
 
201
        self.statusID = None
 
202
        self.first_dialog_load = True
 
203
        self.is_visible = True
 
204
        self.pulse_active = False
 
205
        self.pref = None
 
206
        self.standalone = standalone
 
207
        self.wpadrivercombo = None
 
208
        self.connecting = False
 
209
        self.refreshing = False
 
210
        self.prev_state = None
 
211
        self.update_cb = None
 
212
        self.network_list.set_sensitive(False)
 
213
        label = gtk.Label("%s..." % language['scanning'])
 
214
        self.network_list.pack_start(label)
 
215
        label.show()
 
216
        self.wait_for_events(0.2)
 
217
        self.window.connect('delete_event', self.exit)
 
218
        self.window.connect('key-release-event', self.key_event)
 
219
        daemon.SetGUIOpen(True)
 
220
        bus.add_signal_receiver(self.dbus_scan_finished, 'SendEndScanSignal',
 
221
                        'org.wicd.daemon.wireless')
 
222
        bus.add_signal_receiver(self.dbus_scan_started, 'SendStartScanSignal',
 
223
                        'org.wicd.daemon.wireless')
 
224
        bus.add_signal_receiver(self.update_connect_buttons, 'StatusChanged',
 
225
                        'org.wicd.daemon')
 
226
        bus.add_signal_receiver(self.handle_connection_results,
 
227
                                'ConnectResultsSent', 'org.wicd.daemon')
 
228
        bus.add_signal_receiver(lambda: setup_dbus(force=False), 
 
229
                                "DaemonStarting", "org.wicd.daemon")
 
230
        bus.add_signal_receiver(self._do_statusbar_update, 'StatusChanged',
 
231
                                'org.wicd.daemon')
 
232
        if standalone:
 
233
            bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", 
 
234
                                    "org.wicd.daemon")
 
235
            
 
236
        self._do_statusbar_update(*daemon.GetConnectionStatus())
 
237
        self.wait_for_events(0.1)
 
238
        self.update_cb = misc.timeout_add(2, self.update_statusbar)
 
239
        self.refresh_clicked()
 
240
        
 
241
    def handle_connection_results(self, results):
 
242
        if results not in ['Success', 'aborted'] and self.is_visible:
 
243
            error(self.window, language[results], block=False)
 
244
 
 
245
    def create_adhoc_network(self, widget=None):
 
246
        """ Shows a dialog that creates a new adhoc network. """
 
247
        print "Starting the Ad-Hoc Network Creation Process..."
 
248
        dialog = gtk.Dialog(title = language['create_adhoc_network'],
 
249
                            flags = gtk.DIALOG_MODAL,
 
250
                            buttons=(gtk.STOCK_CANCEL, 2, gtk.STOCK_OK, 1))
 
251
        dialog.set_has_separator(False)
 
252
        dialog.set_size_request(400, -1)
 
253
        self.chkbox_use_encryption = gtk.CheckButton(language['use_wep_encryption'])
 
254
        self.chkbox_use_encryption.set_active(False)
 
255
        ip_entry = LabelEntry(language['ip'] + ':')
 
256
        essid_entry = LabelEntry(language['essid'] + ':')
 
257
        channel_entry = LabelEntry(language['channel'] + ':')
 
258
        self.key_entry = LabelEntry(language['key'] + ':')
 
259
        self.key_entry.set_auto_hidden(True)
 
260
        self.key_entry.set_sensitive(False)
 
261
 
 
262
        chkbox_use_ics = gtk.CheckButton(language['use_ics'])
 
263
 
 
264
        self.chkbox_use_encryption.connect("toggled",
 
265
                                           self.toggle_encrypt_check)
 
266
        channel_entry.entry.set_text('3')
 
267
        essid_entry.entry.set_text('My_Adhoc_Network')
 
268
        ip_entry.entry.set_text('169.254.12.10')  # Just a random IP
 
269
 
 
270
        vbox_ah = gtk.VBox(False, 0)
 
271
        self.wired_network_box = gtk.VBox(False, 0)
 
272
        vbox_ah.pack_start(self.chkbox_use_encryption, False, False)
 
273
        vbox_ah.pack_start(self.key_entry, False, False)
 
274
        vbox_ah.show()
 
275
        dialog.vbox.pack_start(essid_entry)
 
276
        dialog.vbox.pack_start(ip_entry)
 
277
        dialog.vbox.pack_start(channel_entry)
 
278
        dialog.vbox.pack_start(chkbox_use_ics)
 
279
        dialog.vbox.pack_start(vbox_ah)
 
280
        dialog.vbox.set_spacing(5)
 
281
        dialog.show_all()
 
282
        response = dialog.run()
 
283
        if response == 1:
 
284
            wireless.CreateAdHocNetwork(essid_entry.entry.get_text(),
 
285
                                        channel_entry.entry.get_text(),
 
286
                                        ip_entry.entry.get_text().strip(),
 
287
                                        "WEP",
 
288
                                        self.key_entry.entry.get_text(),
 
289
                                        self.chkbox_use_encryption.get_active(),
 
290
                                        False) #chkbox_use_ics.get_active())
 
291
        dialog.destroy()
 
292
 
 
293
    def toggle_encrypt_check(self, widget=None):
 
294
        """ Toggles the encryption key entry box for the ad-hoc dialog. """
 
295
        self.key_entry.set_sensitive(self.chkbox_use_encryption.get_active())
 
296
 
 
297
    def disconnect_all(self, widget=None):
 
298
        """ Disconnects from any active network. """
 
299
        def handler(*args):
 
300
            gobject.idle_add(self.all_network_list.set_sensitive, True)
 
301
         
 
302
        self.all_network_list.set_sensitive(False)
 
303
        daemon.Disconnect(reply_handler=handler, error_handler=handler)
 
304
 
 
305
    def about_dialog(self, widget, event=None):
 
306
        """ Displays an about dialog. """
 
307
        dialog = gtk.AboutDialog()
 
308
        dialog.set_name("Wicd")
 
309
        dialog.set_version(daemon.Hello())
 
310
        dialog.set_authors([ "Adam Blackburn", "Dan O'Reilly", "Andrew Psaltis" ])
 
311
        dialog.set_website("http://wicd.sourceforge.net")
 
312
        dialog.run()
 
313
        dialog.destroy()
 
314
        
 
315
    def key_event (self, widget, event=None):
 
316
        """ Handle key-release-events. """
 
317
        if event.state & gtk.gdk.CONTROL_MASK and \
 
318
           gtk.gdk.keyval_name(event.keyval) in ["w", "q"]:
 
319
            self.exit()
 
320
    
 
321
    def settings_dialog(self, widget, event=None):
 
322
        """ Displays a general settings dialog. """
 
323
        if not self.pref:
 
324
            self.pref = PreferencesDialog(self, self.wTree)
 
325
        else:
 
326
            self.pref.load_preferences_diag()
 
327
        if self.pref.run() == 1:
 
328
            self.pref.save_results()
 
329
        self.pref.hide()
 
330
 
 
331
    def connect_hidden(self, widget):
 
332
        """ Prompts the user for a hidden network, then scans for it. """
 
333
        dialog = gtk.Dialog(title=language['hidden_network'],
 
334
                            flags=gtk.DIALOG_MODAL,
 
335
                            buttons=(gtk.STOCK_CONNECT, 1, gtk.STOCK_CANCEL, 2))
 
336
        dialog.set_has_separator(False)
 
337
        lbl = gtk.Label(language['hidden_network_essid'])
 
338
        textbox = gtk.Entry()
 
339
        dialog.vbox.pack_start(lbl)
 
340
        dialog.vbox.pack_start(textbox)
 
341
        dialog.show_all()
 
342
        button = dialog.run()
 
343
        if button == 1:
 
344
            answer = textbox.get_text()
 
345
            dialog.destroy()
 
346
            self.refresh_networks(None, True, answer)
 
347
        else:
 
348
            dialog.destroy()
 
349
 
 
350
    def cancel_connect(self, widget):
 
351
        """ Alerts the daemon to cancel the connection process. """
 
352
        #should cancel a connection if there
 
353
        #is one in progress
 
354
        cancel_button = self.wTree.get_widget("cancel_button")
 
355
        cancel_button.set_sensitive(False)
 
356
        daemon.CancelConnect()
 
357
        # Prevents automatic reconnecting if that option is enabled
 
358
        daemon.SetForcedDisconnect(True)
 
359
 
 
360
    def pulse_progress_bar(self):
 
361
        """ Pulses the progress bar while connecting to a network. """
 
362
        if not self.pulse_active:
 
363
            return False
 
364
        if not self.is_visible:
 
365
            return True
 
366
        try:
 
367
            gobject.idle_add(self.wTree.get_widget("progressbar").pulse)
 
368
        except:
 
369
            pass
 
370
        return True
 
371
 
 
372
    def update_statusbar(self):
 
373
        """ Triggers a status update in wicd-monitor. """
 
374
        if not self.is_visible:
 
375
            return True
 
376
        
 
377
        daemon.UpdateState()
 
378
        if self.connecting:
 
379
            # If we're connecting, don't wait for the monitor to send
 
380
            # us a signal, since it won't until the connection is made.
 
381
            self._do_statusbar_update(*daemon.GetConnectionStatus())
 
382
        return True
 
383
    
 
384
    def _do_statusbar_update(self, state, info):
 
385
        if not self.is_visible:
 
386
            return True
 
387
        
 
388
        if state == misc.WIRED:
 
389
            return self.set_wired_state(info)
 
390
        elif state == misc.WIRELESS:
 
391
            return self.set_wireless_state(info)
 
392
        elif state == misc.CONNECTING:
 
393
            return self.set_connecting_state(info)
 
394
        elif state in (misc.SUSPENDED, misc.NOT_CONNECTED):
 
395
            return self.set_not_connected_state(info)
 
396
        return True
 
397
        
 
398
    def set_wired_state(self, info):
 
399
        if self.connecting:
 
400
            # Adjust our state from connecting->connected.
 
401
            self._set_not_connecting_state()
 
402
        self.set_status(language['connected_to_wired'].replace('$A', info[0]))
 
403
        return True
 
404
    
 
405
    def set_wireless_state(self, info):
 
406
        if self.connecting:
 
407
            # Adjust our state from connecting->connected.
 
408
            self._set_not_connecting_state()
 
409
        self.set_status(language['connected_to_wireless'].replace
 
410
                        ('$A', info[1]).replace
 
411
                        ('$B', daemon.FormatSignalForPrinting(info[2])).replace
 
412
                        ('$C', info[0]))
 
413
        return True
 
414
        
 
415
    def set_not_connected_state(self, info):
 
416
        if self.connecting:
 
417
            # Adjust our state from connecting->not-connected.
 
418
            self._set_not_connecting_state()
 
419
        self.set_status(language['not_connected'])
 
420
        return True
 
421
        
 
422
    def _set_not_connecting_state(self):
 
423
        if self.connecting:
 
424
            if self.update_cb:
 
425
                gobject.source_remove(self.update_cb)
 
426
            self.update_cb = misc.timeout_add(2, self.update_statusbar)
 
427
            self.connecting = False
 
428
        if self.pulse_active:
 
429
            self.pulse_active = False
 
430
            gobject.idle_add(self.all_network_list.set_sensitive, True)
 
431
            gobject.idle_add(self.status_area.hide_all)
 
432
        if self.statusID:
 
433
            gobject.idle_add(self.status_bar.remove, 1, self.statusID)
 
434
    
 
435
    def set_connecting_state(self, info):
 
436
        if not self.connecting:
 
437
            if self.update_cb:
 
438
                gobject.source_remove(self.update_cb)
 
439
            self.update_cb = misc.timeout_add(500, self.update_statusbar, 
 
440
                                              milli=True)
 
441
            self.connecting = True
 
442
        if not self.pulse_active:
 
443
            self.pulse_active = True
 
444
            misc.timeout_add(100, self.pulse_progress_bar, milli=True)
 
445
            gobject.idle_add(self.all_network_list.set_sensitive, False)
 
446
            gobject.idle_add(self.status_area.show_all)
 
447
        if self.statusID:
 
448
            gobject.idle_add(self.status_bar.remove, 1, self.statusID)
 
449
        if info[0] == "wireless":
 
450
            gobject.idle_add(self.set_status, str(info[1]) + ': ' +
 
451
                   language[str(wireless.CheckWirelessConnectingMessage())])
 
452
        elif info[0] == "wired":
 
453
            gobject.idle_add(self.set_status, language['wired_network'] + ': ' +
 
454
                         language[str(wired.CheckWiredConnectingMessage())])
 
455
        return True
 
456
        
 
457
    def update_connect_buttons(self, state=None, x=None, force_check=False):
 
458
        """ Updates the connect/disconnect buttons for each network entry.
 
459
 
 
460
        If force_check is given, update the buttons even if the
 
461
        current network state is the same as the previous.
 
462
        
 
463
        """
 
464
        if not DBUS_AVAIL: return
 
465
        if not state:
 
466
            state, x = daemon.GetConnectionStatus()
 
467
        
 
468
        if self.prev_state != state or force_check:
 
469
            apbssid = wireless.GetApBssid()
 
470
            for entry in chain(self.network_list, self.wired_network_box):
 
471
                if hasattr(entry, "update_connect_button"):
 
472
                    entry.update_connect_button(state, apbssid)
 
473
        self.prev_state = state
 
474
    
 
475
    def set_status(self, msg):
 
476
        """ Sets the status bar message for the GUI. """
 
477
        self.statusID = self.status_bar.push(1, msg)
 
478
        
 
479
    def dbus_scan_finished(self):
 
480
        """ Calls for a non-fresh update of the gui window.
 
481
        
 
482
        This method is called after a wireless scan is completed.
 
483
        
 
484
        """
 
485
        if not DBUS_AVAIL: return
 
486
        gobject.idle_add(self.refresh_networks, None, False, None)
 
487
            
 
488
    def dbus_scan_started(self):
 
489
        """ Called when a wireless scan starts. """
 
490
        if not DBUS_AVAIL: return
 
491
        self.network_list.set_sensitive(False)
 
492
 
 
493
    def _remove_items_from_vbox(self, vbox):
 
494
        for z in vbox:
 
495
            vbox.remove(z)
 
496
            z.destroy()
 
497
            del z
 
498
 
 
499
    
 
500
    def refresh_clicked(self, widget=None):
 
501
        """ Kick off an asynchronous wireless scan. """
 
502
        if not DBUS_AVAIL or self.connecting: return
 
503
        self.refreshing = True
 
504
 
 
505
        # Remove stuff already in there.
 
506
        self._remove_items_from_vbox(self.wired_network_box)
 
507
        self._remove_items_from_vbox(self.network_list)
 
508
        label = gtk.Label("%s..." % language['scanning'])
 
509
        self.network_list.pack_start(label)
 
510
        self.network_list.show_all()
 
511
        if wired.CheckPluggedIn() or daemon.GetAlwaysShowWiredInterface():
 
512
            printLine = True  # In this case we print a separator.
 
513
            wirednet = WiredNetworkEntry()
 
514
            self.wired_network_box.pack_start(wirednet, False, False)
 
515
            wirednet.connect_button.connect("clicked", self.connect,
 
516
                                           "wired", 0, wirednet)
 
517
            wirednet.disconnect_button.connect("clicked", self.disconnect,
 
518
                                               "wired", 0, wirednet)
 
519
            wirednet.advanced_button.connect("clicked",
 
520
                                             self.edit_advanced, "wired", 0, 
 
521
                                             wirednet)
 
522
            state, x = daemon.GetConnectionStatus()
 
523
            wirednet.update_connect_button(state)
 
524
 
 
525
            self._wired_showing = True
 
526
        else:
 
527
            self._wired_showing = False
 
528
 
 
529
        wireless.Scan(False)
 
530
 
 
531
    def refresh_networks(self, widget=None, fresh=True, hidden=None):
 
532
        """ Refreshes the network list.
 
533
        
 
534
        If fresh=True, scans for wireless networks and displays the results.
 
535
        If a ethernet connection is available, or the user has chosen to,
 
536
        displays a Wired Network entry as well.
 
537
        If hidden isn't None, will scan for networks after running
 
538
        iwconfig <wireless interface> essid <hidden>.
 
539
        
 
540
        """
 
541
        if fresh:
 
542
            if hidden:
 
543
                wireless.SetHiddenNetworkESSID(noneToString(hidden))
 
544
            self.refresh_clicked()
 
545
            return
 
546
        print "refreshing..."
 
547
        self.network_list.set_sensitive(False)
 
548
        self._remove_items_from_vbox(self.network_list)
 
549
        self.wait_for_events()
 
550
        printLine = False  # We don't print a separator by default.
 
551
        if self._wired_showing:
 
552
            printLine = True
 
553
        num_networks = wireless.GetNumberOfNetworks()
 
554
        instruct_label = self.wTree.get_widget("label_instructions")
 
555
        if num_networks > 0:
 
556
            instruct_label.show()
 
557
            for x in range(0, num_networks):
 
558
                if printLine:
 
559
                    sep = gtk.HSeparator()
 
560
                    self.network_list.pack_start(sep, padding=10, fill=False,
 
561
                                                 expand=False)
 
562
                    sep.show()
 
563
                else:
 
564
                    printLine = True
 
565
                tempnet = WirelessNetworkEntry(x)
 
566
                self.network_list.pack_start(tempnet, False, False)
 
567
                tempnet.connect_button.connect("clicked",
 
568
                                               self.connect, "wireless", x,
 
569
                                               tempnet)
 
570
                tempnet.disconnect_button.connect("clicked",
 
571
                                                  self.disconnect, "wireless",
 
572
                                                  x, tempnet)
 
573
                tempnet.advanced_button.connect("clicked",
 
574
                                                self.edit_advanced, "wireless",
 
575
                                                x, tempnet)
 
576
        else:
 
577
            instruct_label.hide()
 
578
            if wireless.GetKillSwitchEnabled():
 
579
                label = gtk.Label(language['killswitch_enabled'] + ".")
 
580
            else:
 
581
                label = gtk.Label(language['no_wireless_networks_found'])
 
582
            self.network_list.pack_start(label)
 
583
            label.show()
 
584
        self.update_connect_buttons(force_check=True)
 
585
        self.network_list.set_sensitive(True)
 
586
        self.refreshing = False
 
587
 
 
588
    def save_settings(self, nettype, networkid, networkentry):
 
589
        """ Verifies and saves the settings for the network entry. """
 
590
        entry = networkentry.advanced_dialog
 
591
        opt_entlist = []
 
592
        req_entlist = []
 
593
        
 
594
        # First make sure all the Addresses entered are valid.
 
595
        if entry.chkbox_static_ip.get_active():
 
596
            req_entlist = [entry.txt_ip, entry.txt_netmask]
 
597
            opt_entlist = [entry.txt_gateway]
 
598
                
 
599
        if entry.chkbox_static_dns.get_active() and \
 
600
           not entry.chkbox_global_dns.get_active():
 
601
            req_entlist.append(entry.txt_dns_1)
 
602
            # Only append additional dns entries if they're entered.
 
603
            for ent in [entry.txt_dns_2, entry.txt_dns_3]:
 
604
                if ent.get_text() != "":
 
605
                    opt_entlist.append(ent)
 
606
        
 
607
        # Required entries.
 
608
        for lblent in req_entlist:
 
609
            lblent.set_text(lblent.get_text().strip())
 
610
            if not misc.IsValidIP(lblent.get_text()):
 
611
                error(self.window, language['invalid_address'].
 
612
                                    replace('$A', lblent.label.get_label()))
 
613
                return False
 
614
        
 
615
        # Optional entries, only check for validity if they're entered.
 
616
        for lblent in opt_entlist:
 
617
            lblent.set_text(lblent.get_text().strip())
 
618
            if lblent.get_text() and not misc.IsValidIP(lblent.get_text()):
 
619
                error(self.window, language['invalid_address'].
 
620
                                    replace('$A', lblent.label.get_label()))
 
621
                return False
 
622
 
 
623
        # Now save the settings.
 
624
        if nettype == "wireless":
 
625
            if not networkentry.save_wireless_settings(networkid):
 
626
                return False
 
627
 
 
628
        elif nettype == "wired":
 
629
            if not networkentry.save_wired_settings():
 
630
                return False
 
631
            
 
632
        return True
 
633
 
 
634
    def edit_advanced(self, widget, ttype, networkid, networkentry):
 
635
        """ Display the advanced settings dialog.
 
636
        
 
637
        Displays the advanced settings dialog and saves any changes made.
 
638
        If errors occur in the settings, an error message will be displayed
 
639
        and the user won't be able to save the changes until the errors
 
640
        are fixed.
 
641
        
 
642
        """
 
643
        dialog = networkentry.advanced_dialog
 
644
        dialog.set_values()
 
645
        dialog.show_all()
 
646
        while True:
 
647
            if self.run_settings_dialog(dialog, ttype, networkid, networkentry):
 
648
                break
 
649
        dialog.hide()
 
650
        
 
651
    def run_settings_dialog(self, dialog, nettype, networkid, networkentry):
 
652
        """ Runs the settings dialog.
 
653
        
 
654
        Runs the settings dialog and returns True if settings are saved
 
655
        successfully, and false otherwise.
 
656
        
 
657
        """
 
658
        result = dialog.run()
 
659
        if result == gtk.RESPONSE_ACCEPT:
 
660
            if self.save_settings(nettype, networkid, networkentry):
 
661
                return True
 
662
            else:
 
663
                return False
 
664
        return True
 
665
    
 
666
    def check_encryption_valid(self, networkid, entry):
 
667
        """ Make sure that encryption settings are properly filled in. """
 
668
        # Make sure no entries are left blank
 
669
        if entry.chkbox_encryption.get_active():
 
670
            encryption_info = entry.encryption_info
 
671
            for entry_info in encryption_info.itervalues():
 
672
                if entry_info[0].entry.get_text() == "" and \
 
673
                   entry_info[1] == 'required':
 
674
                    error(self.window, "%s (%s)" % (language['encrypt_info_missing'], 
 
675
                                             entry_info[0].label.get_label())
 
676
                          )
 
677
                    return False
 
678
        # Make sure the checkbox is checked when it should be
 
679
        elif not entry.chkbox_encryption.get_active() and \
 
680
             wireless.GetWirelessProperty(networkid, "encryption"):
 
681
            error(self.window, language['enable_encryption'])
 
682
            return False
 
683
        return True
 
684
 
 
685
    def _wait_for_connect_thread_start(self):
 
686
        self.wTree.get_widget("progressbar").pulse()
 
687
        if not self._connect_thread_started:
 
688
            return True
 
689
        else:
 
690
            misc.timeout_add(2, self.update_statusbar)
 
691
            self.update_statusbar()
 
692
            return False
 
693
        
 
694
    def connect(self, widget, nettype, networkid, networkentry):
 
695
        """ Initiates the connection process in the daemon. """
 
696
        def handler(*args):
 
697
            self._connect_thread_started = True
 
698
 
 
699
        def setup_interface_for_connection():
 
700
            cancel_button = self.wTree.get_widget("cancel_button")
 
701
            cancel_button.set_sensitive(True)
 
702
            self.all_network_list.set_sensitive(False)
 
703
            if self.statusID:
 
704
                gobject.idle_add(self.status_bar.remove, 1, self.statusID)
 
705
            gobject.idle_add(self.set_status, language["disconnecting_active"])
 
706
            gobject.idle_add(self.status_area.show_all)
 
707
            self.wait_for_events()
 
708
            self._connect_thread_started = False
 
709
 
 
710
        if nettype == "wireless":
 
711
            if not self.check_encryption_valid(networkid,
 
712
                                               networkentry.advanced_dialog):
 
713
                self.edit_advanced(None, nettype, networkid, networkentry)
 
714
                return False
 
715
            setup_interface_for_connection()
 
716
            wireless.ConnectWireless(networkid, reply_handler=handler,
 
717
                                     error_handler=handler)
 
718
        elif nettype == "wired":
 
719
            setup_interface_for_connection()
 
720
            wired.ConnectWired(reply_handler=handler, error_handler=handler)
 
721
        
 
722
        gobject.source_remove(self.update_cb)
 
723
        misc.timeout_add(100, self._wait_for_connect_thread_start, milli=True)
 
724
        
 
725
    def disconnect(self, widget, nettype, networkid, networkentry):
 
726
        """ Disconnects from the given network.
 
727
        
 
728
        Keyword arguments:
 
729
        widget -- The disconnect button that was pressed.
 
730
        event -- unused
 
731
        nettype -- "wired" or "wireless", depending on the network entry type.
 
732
        networkid -- unused
 
733
        networkentry -- The NetworkEntry containing the disconnect button.
 
734
        
 
735
        """
 
736
        def handler(*args):
 
737
            gobject.idle_add(self.all_network_list.set_sensitive, True)
 
738
            gobject.idle_add(self.network_list.set_sensitive, True)
 
739
            
 
740
        widget.hide()
 
741
        networkentry.connect_button.show()
 
742
        daemon.SetForcedDisconnect(True)
 
743
        self.network_list.set_sensitive(False)
 
744
        if nettype == "wired":
 
745
            wired.DisconnectWired(reply_handler=handler, error_handler=handler)
 
746
        else:
 
747
            wireless.DisconnectWireless(reply_handler=handler, 
 
748
                                        error_handler=handler)
 
749
        
 
750
    def wait_for_events(self, amt=0):
 
751
        """ Wait for any pending gtk events to finish before moving on. 
 
752
 
 
753
        Keyword arguments:
 
754
        amt -- a number specifying the number of ms to wait before checking
 
755
               for pending events.
 
756
        
 
757
        """
 
758
        time.sleep(amt)
 
759
        while gtk.events_pending():
 
760
            gtk.main_iteration()
 
761
 
 
762
    def exit(self, widget=None, event=None):
 
763
        """ Hide the wicd GUI.
 
764
 
 
765
        This method hides the wicd GUI and writes the current window size
 
766
        to disc for later use.  This method normally does NOT actually 
 
767
        destroy the GUI, it just hides it.
 
768
 
 
769
        """
 
770
        self.window.hide()
 
771
        gobject.source_remove(self.update_cb)
 
772
        bus.remove_signal_receiver(self._do_statusbar_update, 'StatusChanged',
 
773
                                   'org.wicd.daemon')
 
774
        [width, height] = self.window.get_size()
 
775
        try:
 
776
            daemon.WriteWindowSize(width, height, "main")
 
777
            daemon.SetGUIOpen(False)
 
778
        except DBusException:
 
779
            pass
 
780
 
 
781
        if self.standalone:
 
782
            sys.exit(0)
 
783
 
 
784
        self.is_visible = False
 
785
        return True
 
786
 
 
787
    def show_win(self):
 
788
        """ Brings the GUI out of the hidden state. 
 
789
        
 
790
        Method to show the wicd GUI, alert the daemon that it is open,
 
791
        and refresh the network list.
 
792
        
 
793
        """
 
794
        self.window.present()
 
795
        self.wait_for_events()
 
796
        self.is_visible = True
 
797
        daemon.SetGUIOpen(True)
 
798
        self.wait_for_events(0.1)
 
799
        gobject.idle_add(self.refresh_clicked)
 
800
        self._do_statusbar_update(*daemon.GetConnectionStatus())
 
801
        bus.add_signal_receiver(self._do_statusbar_update, 'StatusChanged',
 
802
                                'org.wicd.daemon')
 
803
        self.update_cb = misc.timeout_add(2, self.update_statusbar)
 
804
 
 
805
 
 
806
if __name__ == '__main__':
 
807
    setup_dbus()
 
808
    app = appGui(standalone=True)
 
809
    mainloop = gobject.MainLoop()
 
810
    mainloop.run()