~matttbe/wicd/ubuntu_python27

« back to all changes in this revision

Viewing changes to .pc/11-fix_gui_showing_from_tray.patch/gtk/gui.py

  • Committer: Bazaar Package Importer
  • Author(s): David Paleino
  • Date: 2010-03-05 18:12:51 UTC
  • mfrom: (8.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100305181251-0fcsn0sty5oy8wlq
Tags: 1.7.0+ds1-2
Fix RC bug: daemon doesn't start anymore because copy.deepcopy()
fails with the iniparse object, coming from 20-use_iniparse.patch.
Bug 568326 reopened. (Closes: #572599)

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
            for ent in [entry.txt_dns_1, entry.txt_dns_2, entry.txt_dns_3]:
 
602
                opt_entlist.append(ent)
 
603
        
 
604
        # Required entries.
 
605
        for lblent in req_entlist:
 
606
            lblent.set_text(lblent.get_text().strip())
 
607
            if not misc.IsValidIP(lblent.get_text()):
 
608
                error(self.window, language['invalid_address'].
 
609
                                    replace('$A', lblent.label.get_label()))
 
610
                return False
 
611
        
 
612
        # Optional entries, only check for validity if they're entered.
 
613
        for lblent in opt_entlist:
 
614
            lblent.set_text(lblent.get_text().strip())
 
615
            if lblent.get_text() and not misc.IsValidIP(lblent.get_text()):
 
616
                error(self.window, language['invalid_address'].
 
617
                                    replace('$A', lblent.label.get_label()))
 
618
                return False
 
619
 
 
620
        # Now save the settings.
 
621
        if nettype == "wireless":
 
622
            if not networkentry.save_wireless_settings(networkid):
 
623
                return False
 
624
 
 
625
        elif nettype == "wired":
 
626
            if not networkentry.save_wired_settings():
 
627
                return False
 
628
            
 
629
        return True
 
630
 
 
631
    def edit_advanced(self, widget, ttype, networkid, networkentry):
 
632
        """ Display the advanced settings dialog.
 
633
        
 
634
        Displays the advanced settings dialog and saves any changes made.
 
635
        If errors occur in the settings, an error message will be displayed
 
636
        and the user won't be able to save the changes until the errors
 
637
        are fixed.
 
638
        
 
639
        """
 
640
        dialog = networkentry.advanced_dialog
 
641
        dialog.set_values()
 
642
        dialog.show_all()
 
643
        while True:
 
644
            if self.run_settings_dialog(dialog, ttype, networkid, networkentry):
 
645
                break
 
646
        dialog.hide()
 
647
        
 
648
    def run_settings_dialog(self, dialog, nettype, networkid, networkentry):
 
649
        """ Runs the settings dialog.
 
650
        
 
651
        Runs the settings dialog and returns True if settings are saved
 
652
        successfully, and false otherwise.
 
653
        
 
654
        """
 
655
        result = dialog.run()
 
656
        if result == gtk.RESPONSE_ACCEPT:
 
657
            if self.save_settings(nettype, networkid, networkentry):
 
658
                return True
 
659
            else:
 
660
                return False
 
661
        return True
 
662
    
 
663
    def check_encryption_valid(self, networkid, entry):
 
664
        """ Make sure that encryption settings are properly filled in. """
 
665
        # Make sure no entries are left blank
 
666
        if entry.chkbox_encryption.get_active():
 
667
            encryption_info = entry.encryption_info
 
668
            for entry_info in encryption_info.itervalues():
 
669
                if entry_info[0].entry.get_text() == "" and \
 
670
                   entry_info[1] == 'required':
 
671
                    error(self.window, "%s (%s)" % (language['encrypt_info_missing'], 
 
672
                                             entry_info[0].label.get_label())
 
673
                          )
 
674
                    return False
 
675
        # Make sure the checkbox is checked when it should be
 
676
        elif not entry.chkbox_encryption.get_active() and \
 
677
             wireless.GetWirelessProperty(networkid, "encryption"):
 
678
            error(self.window, language['enable_encryption'])
 
679
            return False
 
680
        return True
 
681
 
 
682
    def _wait_for_connect_thread_start(self):
 
683
        self.wTree.get_widget("progressbar").pulse()
 
684
        if not self._connect_thread_started:
 
685
            return True
 
686
        else:
 
687
            misc.timeout_add(2, self.update_statusbar)
 
688
            self.update_statusbar()
 
689
            return False
 
690
        
 
691
    def connect(self, widget, nettype, networkid, networkentry):
 
692
        """ Initiates the connection process in the daemon. """
 
693
        def handler(*args):
 
694
            self._connect_thread_started = True
 
695
 
 
696
        def setup_interface_for_connection():
 
697
            cancel_button = self.wTree.get_widget("cancel_button")
 
698
            cancel_button.set_sensitive(True)
 
699
            self.all_network_list.set_sensitive(False)
 
700
            if self.statusID:
 
701
                gobject.idle_add(self.status_bar.remove, 1, self.statusID)
 
702
            gobject.idle_add(self.set_status, language["disconnecting_active"])
 
703
            gobject.idle_add(self.status_area.show_all)
 
704
            self.wait_for_events()
 
705
            self._connect_thread_started = False
 
706
 
 
707
        if nettype == "wireless":
 
708
            if not self.check_encryption_valid(networkid,
 
709
                                               networkentry.advanced_dialog):
 
710
                self.edit_advanced(None, nettype, networkid, networkentry)
 
711
                return False
 
712
            setup_interface_for_connection()
 
713
            wireless.ConnectWireless(networkid, reply_handler=handler,
 
714
                                     error_handler=handler)
 
715
        elif nettype == "wired":
 
716
            setup_interface_for_connection()
 
717
            wired.ConnectWired(reply_handler=handler, error_handler=handler)
 
718
        
 
719
        gobject.source_remove(self.update_cb)
 
720
        misc.timeout_add(100, self._wait_for_connect_thread_start, milli=True)
 
721
        
 
722
    def disconnect(self, widget, nettype, networkid, networkentry):
 
723
        """ Disconnects from the given network.
 
724
        
 
725
        Keyword arguments:
 
726
        widget -- The disconnect button that was pressed.
 
727
        event -- unused
 
728
        nettype -- "wired" or "wireless", depending on the network entry type.
 
729
        networkid -- unused
 
730
        networkentry -- The NetworkEntry containing the disconnect button.
 
731
        
 
732
        """
 
733
        def handler(*args):
 
734
            gobject.idle_add(self.all_network_list.set_sensitive, True)
 
735
            gobject.idle_add(self.network_list.set_sensitive, True)
 
736
            
 
737
        widget.hide()
 
738
        networkentry.connect_button.show()
 
739
        daemon.SetForcedDisconnect(True)
 
740
        self.network_list.set_sensitive(False)
 
741
        if nettype == "wired":
 
742
            wired.DisconnectWired(reply_handler=handler, error_handler=handler)
 
743
        else:
 
744
            wireless.DisconnectWireless(reply_handler=handler, 
 
745
                                        error_handler=handler)
 
746
        
 
747
    def wait_for_events(self, amt=0):
 
748
        """ Wait for any pending gtk events to finish before moving on. 
 
749
 
 
750
        Keyword arguments:
 
751
        amt -- a number specifying the number of ms to wait before checking
 
752
               for pending events.
 
753
        
 
754
        """
 
755
        time.sleep(amt)
 
756
        while gtk.events_pending():
 
757
            gtk.main_iteration()
 
758
 
 
759
    def exit(self, widget=None, event=None):
 
760
        """ Hide the wicd GUI.
 
761
 
 
762
        This method hides the wicd GUI and writes the current window size
 
763
        to disc for later use.  This method normally does NOT actually 
 
764
        destroy the GUI, it just hides it.
 
765
 
 
766
        """
 
767
        self.window.hide()
 
768
        gobject.source_remove(self.update_cb)
 
769
        bus.remove_signal_receiver(self._do_statusbar_update, 'StatusChanged',
 
770
                                   'org.wicd.daemon')
 
771
        [width, height] = self.window.get_size()
 
772
        try:
 
773
            daemon.WriteWindowSize(width, height, "main")
 
774
            daemon.SetGUIOpen(False)
 
775
        except DBusException:
 
776
            pass
 
777
 
 
778
        if self.standalone:
 
779
            sys.exit(0)
 
780
 
 
781
        self.is_visible = False
 
782
        return True
 
783
 
 
784
    def show_win(self):
 
785
        """ Brings the GUI out of the hidden state. 
 
786
        
 
787
        Method to show the wicd GUI, alert the daemon that it is open,
 
788
        and refresh the network list.
 
789
        
 
790
        """
 
791
        self.window.present()
 
792
        self.wait_for_events()
 
793
        self.is_visible = True
 
794
        daemon.SetGUIOpen(True)
 
795
        self.wait_for_events(0.1)
 
796
        gobject.idle_add(self.refresh_clicked)
 
797
        self._do_statusbar_update(*daemon.GetConnectionStatus())
 
798
        bus.add_signal_receiver(self._do_statusbar_update, 'StatusChanged',
 
799
                                'org.wicd.daemon')
 
800
        self.update_cb = misc.timeout_add(2, self.update_statusbar)
 
801
 
 
802
 
 
803
if __name__ == '__main__':
 
804
    setup_dbus()
 
805
    app = appGui(standalone=True)
 
806
    mainloop = gobject.MainLoop()
 
807
    mainloop.run()