4
""" wicd-curses. (curses/urwid-based) console interface to wicd
6
Provides a console UI for wicd, so that people with broken X servers can
7
at least get a network connection. Or those who don't like using X and/or GTK.
11
# Copyright (C) 2008-2009 Andrew Psaltis
13
# This program is free software; you can redistribute it and/or modify
14
# it under the terms of the GNU General Public License as published by
15
# the Free Software Foundation; either version 2 of the License, or
16
# (at your option) any later version.
18
# This program is distributed in the hope that it will be useful,
19
# but WITHOUT ANY WARRANTY; without even the implied warranty of
20
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
# GNU General Public License for more details.
23
# You should have received a copy of the GNU General Public License
24
# along with this program; if not, write to the Free Software
25
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
29
This contains/will contain A LOT of code from the other parts of wicd.
31
This is probably due to the fact that I did not really know what I was doing
32
when I started writing this. It works, so I guess that's all that matters.
34
Comments, criticisms, patches, bug reports all welcome!
36
# Filter out a confusing urwid warning in python 2.6.
37
# This is valid as of urwid version 0.9.8.4
39
warnings.filterwarnings("ignore","The popen2 module is deprecated. Use the subprocess module.")
43
# DBus communication stuff
44
from dbus import DBusException
45
from dbus import version as dbus_version
46
# It took me a while to figure out that I have to use this.
49
# Other important wicd-related stuff
50
from wicd import wpath
52
from wicd import dbusmanager
54
# Internal Python stuff
56
from time import sleep, strftime, ctime
58
# Curses UIs for other stuff
59
from curses_misc import *
60
from prefs_curses import PrefsDialog
61
import netentry_curses
63
from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog,AdvancedSettingsDialog
65
from optparse import OptionParser
68
# Stuff about getting the script configurer running
69
#from grp import getgrgid
70
#from os import getgroups,system
73
#import logging.handler
75
CURSES_REV=wpath.curses_revision
77
# Fix strings in wicd-curses
78
from wicd.translations import language
79
for i in language.keys():
80
language[i] = language[i].decode('utf8')
82
########################################
84
########################################
86
def wrap_exceptions(func):
87
def wrapper(*args, **kargs):
89
return func(*args, **kargs)
90
except KeyboardInterrupt:
91
#gobject.source_remove(redraw_tag)
94
print >> sys.stderr, "\n"+language['terminated']
99
print >> sys.stderr,"\n"+language['dbus_fail']
103
#if 'loop' in locals():
107
# Print out standard notification:
108
print >> sys.stderr, "\n" + language['exception']
109
# Flush the buffer so that the notification is always above the
112
# Raise the exception
115
wrapper.__name__ = func.__name__
116
wrapper.__module__ = func.__module__
117
wrapper.__dict__ = func.__dict__
118
wrapper.__doc__ = func.__doc__
121
########################################
122
##### SUPPORT FUNCTIONS
123
########################################
125
# Look familiar? These two functions are clones of functions found in wicd's
126
# gui.py file, except that now set_status is a function passed to them.
128
def check_for_wired(wired_ip,set_status):
129
""" Determine if wired is active, and if yes, set the status. """
130
if wired_ip and wired.CheckPluggedIn():
131
set_status(language['connected_to_wired'].replace('$A',wired_ip))
137
def check_for_wireless(iwconfig, wireless_ip, set_status):
138
""" Determine if wireless is active, and if yes, set the status. """
142
network = wireless.GetCurrentNetwork(iwconfig)
146
network = unicode(network)
147
if daemon.GetSignalDisplayType() == 0:
148
strength = wireless.GetCurrentSignalStrength(iwconfig)
150
strength = wireless.GetCurrentDBMStrength(iwconfig)
154
strength = str(strength)
155
ip = str(wireless_ip)
156
set_status(language['connected_to_wireless'].replace
157
('$A', network).replace
158
('$B', daemon.FormatSignalForPrinting(strength)).replace
163
# Generate the list of networks.
164
# Mostly borrowed/stolen from wpa_cli, since I had no clue what all of those
165
# DBUS interfaces do. :P
166
# Whatever calls this must be exception-wrapped if it is run if the UI is up
167
def gen_network_list():
168
wiredL = wired.GetWiredProfileList()
170
# This one makes a list of NetLabels
171
for network_id in range(0, wireless.GetNumberOfNetworks()):
172
is_active = wireless.GetCurrentSignalStrength("") != 0 and wireless.GetCurrentNetworkID(wireless.GetIwconfig())==network_id and wireless.GetWirelessIP('') != None
174
label = NetLabel(network_id,is_active)
176
return (wiredL,wlessL)
178
def about_dialog(body):
179
# This looks A LOT better when it is actually displayed. I promise :-).
180
# The ASCII Art "Wicd" was made from the "smslant" font on one of those
181
# online ASCII big text generators.
183
('green'," /// \\\\\\")," _ ___ __\n",
184
('green'," /// \\\\\\")," | | /| / (_)______/ /\n",
185
('green'," /// \\\\\\")," | |/ |/ / / __/ _ / \n",
186
('green',"/|| // \\\\ ||\\")," |__/|__/_/\__/\_,_/ \n",
187
('green',"||| ||"),"(|^|)",('green',"|| |||"),
188
" ($VERSION) \n".replace("$VERSION",daemon.Hello()),
190
('green',"\\|| \\\\")," |+| ",('green',"// ||/ \n"),
191
('green'," \\\\\\")," |+| ",('green',"///")," http://wicd.net\n",
192
('green'," \\\\\\")," |+| ",('green',"///")," ",language["brought_to_you"],"\n",
193
('green'," \\\\\\")," |+| ",('green',"///")," Adam Blackburn\n",
194
" ___|+|___ Dan O'Reilly\n",
195
" |---------| Andrew Psaltis\n",
196
"-----------------------------------------------------"]
197
about = TextDialog(theText,16,55,header=('header','About Wicd'))
200
# Modeled after htop's help
201
def help_dialog(body):
202
textT = urwid.Text(('header','wicd-curses help'),'right')
203
textSH = urwid.Text(['This is ',('blue','wicd-curses-'+CURSES_REV),' using wicd ',unicode(daemon.Hello()),'\n'])
206
"For more detailed help, consult the wicd-curses(8) man page.\n",
207
('bold','->'),' and ',('bold','<-')," are the right and left arrows respectively.\n"])
210
('bold',' H h ?'),": Display this help dialog\n",
211
('bold','enter C'),": Connect to selected network\n",
212
('bold',' D'),": Disconnect from all networks\n",
213
('bold',' ESC'),": Stop a connection in progress\n",
214
('bold',' F5 R'),": Refresh network list\n",
215
('bold',' P'),": Prefrences dialog\n",
218
('bold',' I'),": Scan for hidden networks\n",
219
('bold',' S'),": Select scripts\n",
220
('bold',' O'),": Set up Ad-hoc network\n",
221
('bold',' ->'),": Configure selected network\n",
222
('bold',' A'),": Display 'about' dialog\n",
223
('bold',' F8 q Q'),": Quit wicd-curses\n",
225
textF = urwid.Text('Press any key to return.')
227
# textJ = urwid.Text(('important','Nobody expects the Spanish Inquisition!'))
229
blank = urwid.Text('')
231
cols = urwid.Columns([text1,text2])
232
pile = urwid.Pile([textH,cols])
233
fill = urwid.Filler(pile)
234
frame = urwid.Frame(fill,header=urwid.Pile([textT,textSH]),footer=textF)
235
dim = ui.get_cols_rows()
237
ui.draw_screen(dim, frame.render(dim, True))
239
keys = ui.get_input()
240
# Don't stop because someone let go of the mouse on the frame
241
mouse_release = False
243
if urwid.is_mouse_event(k) and k[0] == "mouse release":
248
if 'window resize' in keys:
249
dim = ui.get_cols_rows()
253
def run_configscript(parent,netname,nettype):
254
configfile = wpath.etc+netname+'-settings.conf'
255
if nettype != 'wired':
259
if nettype == 'wired':
262
profname = wireless.GetWirelessProperty( int(netname),'bssid')
264
language['cannot_edit_scripts_1'].replace('$A',configfile).replace('$B',header),
265
"\n\n["+profname+"]\n\n",
266
# Translation needs to be changed to accomidate this text below.
267
"""You can also configure the wireless networks by looking for the "[<ESSID>]" field in the config file.
269
Once there, you can adjust (or add) the "beforescript", "afterscript", "predisconnectscript" and "postdisconnectscript" variables as needed, to change the preconnect, postconnect, predisconnect and postdisconnect scripts respectively. Note that you will be specifying the full path to the scripts - not the actual script contents. You will need to add/edit the script contents separately. Refer to the wicd manual page for more information."""]
270
dialog = TextDialog(theText,20,80)
271
dialog.run(ui,parent)
272
# This code works with many distributions, but not all of them. So, to
273
# limit complications, it has been deactivated. If you want to run it,
274
# be my guest. Be sure to deactivate the above stuff first.
278
argv = netname + ' ' +nettype
280
#cmd = '/usr/lib/configscript_curses.py '+argv
281
cmd = wpath.lib+'configscript_curses.py '+argv
282
# Check whether we can sudo. Hopefully this is complete
284
for i in getgroups():
285
glist.append(getgrgid(i)[0])
290
elif 'admin' in glist or 'wheel' in glist or 'sudo' in glist:
298
print "Calling command: " + precmd + precmdargv + cmd + postcmd
300
system(precmd+precmdargv+cmd+postcmd)
301
raw_input("Press enter!")
305
def gen_list_header():
306
if daemon.GetSignalDisplayType() == 0:
307
# Allocate 25 cols for the ESSID name
310
# Need 3 more to accomodate dBm strings
312
return 'C %s %*s %9s %17s %6s %s' % ('STR ',essidgap,'ESSID','ENCRYPT','BSSID','MODE','CHNL')
314
########################################
315
##### URWID SUPPORT CLASSES
316
########################################
318
# Wireless network label
319
class NetLabel(urwid.WidgetWrap):
320
def __init__(self, id, is_active):
321
# Pick which strength measure to use based on what the daemon says
322
# gap allocates more space to the first module
323
if daemon.GetSignalDisplayType() == 0:
325
gap = 4 # Allow for 100%
327
strenstr = 'strength'
328
gap = 7 # -XX dbm = 7
330
# All of that network property stuff
331
self.stren = daemon.FormatSignalForPrinting(
332
str(wireless.GetWirelessProperty(id, strenstr)))
333
self.essid = wireless.GetWirelessProperty(id, 'essid')
334
self.bssid = wireless.GetWirelessProperty(id, 'bssid')
336
if wireless.GetWirelessProperty(id, 'encryption'):
337
self.encrypt = wireless.GetWirelessProperty(id,'encryption_method')
339
self.encrypt = language['unsecured']
341
self.mode = wireless.GetWirelessProperty(id, 'mode') # Master, Ad-Hoc
342
self.channel = wireless.GetWirelessProperty(id, 'channel')
343
theString = ' %-*s %25s %9s %17s %6s %4s' % (gap,
344
self.stren,self.essid,self.encrypt,self.bssid,self.mode,self.channel)
346
theString = '>'+theString[1:]
347
w = urwid.AttrWrap(SelText(theString),'connected','connected focus')
349
w = urwid.AttrWrap(SelText(theString),'body','focus')
351
self.__super.__init__(w)
352
def selectable(self):
354
def keypress(self,size,key):
355
return self._w.keypress(size,key)
357
wireless.ConnectWireless(self.id)
359
class WiredComboBox(ComboBox):
361
list : the list of wired network profiles. The rest is self-explanitory.
363
def __init__(self,list):
364
self.ADD_PROFILE = '---'+language["add_new_profile"]+'---'
365
self.__super.__init__(use_enter=False)
368
def set_list(self,list):
372
is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None
374
theString = '%4s %25s' % (id, profile)
375
# Tag if no wireless IP present, and wired one is
377
theString = '>'+theString[1:]
379
wiredL.append(theString)
381
wiredL.append(self.ADD_PROFILE)
383
self.attrs = ('connected','editnfc')
384
self.focus_attr = 'connected focus'
386
self.attrs = ('body','editnfc')
387
self.focus_attr = 'focus'
389
if self.theList != []:
390
wired.ReadWiredNetworkProfile(self.get_selected_profile())
392
def keypress(self,size,key):
393
prev_focus = self.get_focus()[1]
394
key = ComboBox.keypress(self,size,key)
396
if self.get_focus()[1] == len(self.list)-1:
397
dialog = InputDialog(('header',language["add_new_wired_profile"]),7,30)
398
exitcode,name = dialog.run(ui,self.parent)
402
error(ui,self.parent,'Invalid profile name')
403
self.set_focus(prev_focus)
406
wired.CreateWiredNetworkProfile(name,False)
407
self.set_list(wired.GetWiredProfileList())
408
self.rebuild_combobox()
409
self.set_focus(prev_focus)
411
wired.ReadWiredNetworkProfile(self.get_selected_profile())
413
if len(self.theList) == 1:
414
error(self.ui,self.parent,language["no_delete_last_profile"])
416
wired.DeleteWiredNetworkProfile(self.get_selected_profile())
417
# Return to the top of the list if something is deleted.
419
if wired.GetDefaultWiredNetwork() != None:
420
self.set_focus(self.theList.index(wired.GetDefaultWiredNetwork()))
423
self.set_focus(prev_focus)
424
self.set_list(wired.GetWiredProfileList())
425
self.rebuild_combobox()
427
dialog = InputDialog(('header',language["rename_wired_profile"]),7,30,
428
edit_text=unicode(self.get_selected_profile()))
429
exitcode,name = dialog.run(ui,self.parent)
431
# Save the new one, then kill the old one
432
wired.SaveWiredNetworkProfile(name)
433
wired.DeleteWiredNetworkProfile(self.get_selected_profile())
434
self.set_list(wired.GetWiredProfileList())
435
self.set_focus(self.theList.index(name))
436
self.rebuild_combobox()
439
def get_selected_profile(self):
440
"""Get the selected wired profile"""
441
loc = self.get_focus()[1]
442
return self.theList[loc]
444
# Dialog2 that initiates an Ad-Hoc network connection
445
class AdHocDialog(Dialog2):
447
essid_t = language['essid']
448
ip_t = language['ip']
449
channel_t = language['channel']
450
key_t = " " + language['key']
451
use_ics_t = language['use_ics']
452
use_encrypt_t = language['use_wep_encryption']
454
self.essid_edit = DynEdit(essid_t)
455
self.ip_edit = DynEdit(ip_t)
456
self.channel_edit = DynIntEdit(channel_t)
457
self.key_edit = DynEdit(key_t,sensitive=False)
459
self.use_ics_chkb = urwid.CheckBox(use_ics_t)
460
self.use_encrypt_chkb = urwid.CheckBox(use_encrypt_t,
461
on_state_change=self.encrypt_callback)
463
blank = urwid.Text('')
466
self.essid_edit.set_edit_text("My_Adhoc_Network")
467
self.ip_edit.set_edit_text("169.254.12.10")
468
self.channel_edit.set_edit_text("3")
470
l = [self.essid_edit,self.ip_edit,self.channel_edit,blank,
471
self.use_ics_chkb,self.use_encrypt_chkb,self.key_edit]
472
body = urwid.ListBox(l)
474
header = ('header',language['create_adhoc_network'])
475
Dialog2.__init__(self, header, 15, 50, body)
476
self.add_buttons([('OK',1),('Cancel',-1)])
477
self.frame.set_focus('body')
479
def encrypt_callback(self,chkbox,new_state,user_info=None):
480
self.key_edit.set_sensitive(new_state)
482
def unhandled_key(self, size, k):
483
if k in ('up','page up'):
484
self.frame.set_focus('body')
485
if k in ('down','page down'):
486
self.frame.set_focus('footer')
488
# pass enter to the "ok" button
489
self.frame.set_focus('footer')
490
self.buttons.set_focus(0)
491
self.view.keypress( size, k )
492
def on_exit(self,exitcode):
493
data = ( self.essid_edit.get_edit_text(),
494
self.ip_edit.get_edit_text().strip(),
495
self.channel_edit.get_edit_text(),
496
self.use_ics_chkb.get_state(),
497
self.use_encrypt_chkb.get_state(),
498
self.key_edit.get_edit_text())
499
return exitcode, data
501
########################################
502
##### APPLICATION INTERFACE CLASS
503
########################################
506
"""The UI itself, all glory belongs to it!"""
509
self.size = ui.get_cols_rows()
510
# Happy screen saying that you can't do anything because we're scanning
512
self.screen_locker = urwid.Filler(urwid.Text(('important',language['scanning_stand_by']), align='center'))
513
self.no_wlan = urwid.Filler(urwid.Text(('important',language['no_wireless_networks_found']), align='center'))
514
self.TITLE = language['wicd_curses']
518
header = urwid.AttrWrap(urwid.Text(self.TITLE,align='right'), 'header')
519
self.wiredH=urwid.Filler(urwid.Text("Wired Network(s)"))
520
self.list_header=urwid.AttrWrap(urwid.Text(gen_list_header()),'listbar')
521
self.wlessH=NSelListBox([urwid.Text("Wireless Network(s)"),self.list_header])
523
# Init this earlier to make update_status happy
524
self.update_tag = None
526
# FIXME: This should be two variables
527
self.focusloc = [1,0]
529
# These are empty to make sure that things go my way.
530
wiredL,wlessL = [],[]
535
self.wiredCB = urwid.Filler(WiredComboBox(wiredL))
536
self.wlessLB = urwid.ListBox(wlessL)
537
self.update_netlist(force_check=True,firstrun=True)
539
# Keymappings proposed by nanotube in #wicd
542
('right','Config',None),
544
('C' ,'Connect',None),
545
('D' ,'Disconn',None),
546
('R' ,'Refresh',None),
548
('I' ,'Hidden',None),
550
('Q' ,'Quit',loop.quit)
553
self.primaryCols = OptCols(keys,self.handle_keys)
554
self.status_label = urwid.AttrWrap(urwid.Text(''),'important')
555
self.footer2 = urwid.Columns([self.status_label])
556
self.footerList = urwid.Pile([self.primaryCols,self.footer2])
558
self.frame = urwid.Frame(self.thePile,
560
footer=self.footerList)
561
self.wiredCB.get_body().build_combobox(self.frame,ui,3)
563
# Init the other columns used in the program
564
self.init_other_optcols()
566
self.frame.set_body(self.thePile)
568
self.prev_state = False
569
self.connecting = False
570
self.screen_locked = False
571
self.do_diag_lock = False #Whether the screen is locked beneath a dialog
572
self.diag_type = 'none' # The type of dialog that is up
573
self.scanning = False
579
#self.max_wait = ui.max_wait
581
def doScan(self, sync=False):
585
def init_other_optcols(self):
586
# The "tabbed" preferences dialog
587
self.prefCols = OptCols( [ ('f10','OK'),
588
('page up','Tab Left',),
589
('page down', 'Tab Right'),
590
('esc','Cancel') ], self.handle_keys)
591
self.confCols = OptCols( [ ('f10','OK'),
592
('esc','Cancel') ],self.handle_keys)
594
# Does what it says it does
595
def lock_screen(self):
596
if self.diag_type == 'pref':
597
self.do_diag_lock = True
599
self.frame.set_body(self.screen_locker)
600
self.screen_locked = True
603
def unlock_screen(self):
604
if self.do_diag_lock:
605
self.do_diag_lock = False
607
self.update_netlist(force_check=True)
609
self.frame.set_body(self.thePile)
610
self.screen_locked = False
613
def raise_hidden_network_dialog(self):
614
dialog = InputDialog(('header',language["select_hidden_essid"]),7,30,language['scan'])
615
exitcode,hidden = dialog.run(ui,self.frame)
617
# That dialog will sit there for a while if I don't get rid of it
619
wireless.SetHiddenNetworkESSID(misc.noneToString(hidden))
621
wireless.SetHiddenNetworkESSID("")
623
def update_focusloc(self):
624
# Location of last known focus is remapped to current location.
625
# This might need to be cleaned up later.
627
if self.thePile.get_focus() == self.wiredCB:
628
wlessorwired = self.WIRED_IDX
629
where = self.thePile.get_focus().get_body().get_focus()[1]
630
else: #self.thePile.get_focus() == self.wlessLB :
631
wlessorwired = self.WLESS_IDX
632
if self.wlessLB == self.no_wlan:
635
where = self.thePile.get_focus().get_focus()[1]
636
#where = self.wlessLB.get_focus()[1]
637
self.focusloc = [wlessorwired,where]
639
# Be clunky until I get to a later stage of development.
640
# Update the list of networks. Usually called by DBus.
642
def update_netlist(self,state=None, x=None, force_check=False,firstrun=False):
643
# Don't even try to do this if we are running a dialog
646
# Run focus-collecting code if we are not running this for the first
649
self.update_focusloc()
650
self.list_header.set_text(gen_list_header())
651
""" Updates the overall network list."""
653
state, x = daemon.GetConnectionStatus()
654
if force_check or self.prev_state != state:
655
wiredL,wlessL = gen_network_list()
657
self.wiredCB.get_body().set_list(wiredL)
658
self.wiredCB.get_body().build_combobox(self.frame,ui,3)
660
if self.wlessLB == self.no_wlan:
661
self.wlessLB = urwid.ListBox(wlessL)
663
self.wlessLB.body = urwid.SimpleListWalker(wlessL)
665
self.wlessLB = self.no_wlan
666
if daemon.GetAlwaysShowWiredInterface() or wired.CheckPluggedIn():
667
self.thePile = urwid.Pile([('fixed',1,self.wiredH),
668
('fixed',1,self.wiredCB),
669
('fixed',2,self.wlessH),
672
self.frame.body = self.thePile
674
self.thePile.set_focus(self.focusloc[0])
675
if self.focusloc[0] == self.WIRED_IDX:
676
self.thePile.get_focus().get_body().set_focus(self.focusloc[1])
678
if self.wlessLB != self.no_wlan:
679
self.thePile.get_focus().set_focus(self.focusloc[1])
681
self.thePile.set_focus(self.wiredCB)
683
self.thePile = urwid.Pile([('fixed',2,self.wlessH),self.wlessLB] )
685
self.frame.body = self.thePile
686
if self.focusloc[1] == None:
688
if self.wlessLB != self.no_wlan:
689
self.wlessLB.set_focus(self.focusloc[1])
691
self.prev_state = state
695
if wired.GetDefaultWiredNetwork() != None:
696
self.wiredCB.get_body().set_focus(wired.GetWiredProfileList().index(wired.GetDefaultWiredNetwork()))
698
# Update the footer/status bar
701
def update_status(self):
702
wired_connecting = wired.CheckIfWiredConnecting()
703
wireless_connecting = wireless.CheckIfWirelessConnecting()
704
self.connecting = wired_connecting or wireless_connecting
706
fast = not daemon.NeedsExternalCalls()
708
if not self.conn_status:
709
self.conn_status = True
710
gobject.timeout_add(250,self.set_connecting_status,fast)
713
if check_for_wired(wired.GetWiredIP(''),self.set_status):
716
iwconfig = wireless.GetIwconfig()
719
if check_for_wireless(iwconfig, wireless.GetWirelessIP(""),
723
self.set_status(language['not_connected'])
727
def set_connecting_status(self,fast):
728
wired_connecting = wired.CheckIfWiredConnecting()
729
wireless_connecting = wireless.CheckIfWirelessConnecting()
730
if wireless_connecting:
732
iwconfig = wireless.GetIwconfig()
735
# set_status is rigged to return false when it is not
736
# connecting to anything, so this should work.
737
return self.set_status(wireless.GetCurrentNetwork(iwconfig) +
739
language[str(wireless.CheckWirelessConnectingMessage())],
742
return self.set_status( language['wired_network'] +
744
language[str(wired.CheckWiredConnectingMessage())],
747
self.conn_status=False
750
# Cheap little indicator stating that we are actually connecting
751
twirl = ['|','/','-','\\']
752
tcount = 0 # Counter for said indicator
753
def set_status(self,text,from_idle=False):
754
# Set the status text, usually called by the update_status method
755
# from_idle : a check to see if we are being called directly from the
757
# If we are being called as the result of trying to connect to
758
# something, and we aren't connecting to something, return False
760
if from_idle and not self.connecting:
762
self.conn_status=False
765
# If we are connecting and being called from the idle function, spin
767
if from_idle and self.connecting:
768
# This is probably the wrong way to do this, but it works for now.
770
toAppend=self.twirl[self.tcount % 4]
771
self.status_label.set_text(text+' '+toAppend)
775
def dbus_scan_finished(self):
776
# I'm pretty sure that I'll need this later.
777
#if not self.connecting:
778
# gobject.idle_add(self.refresh_networks, None, False, None)
780
self.scanning = False
782
def dbus_scan_started(self):
784
if self.diag_type == 'conf':
785
self.restore_primary()
788
def restore_primary(self):
789
self.diag_type = 'none'
790
if self.do_diag_lock or self.scanning:
791
self.frame.set_body(self.screen_locker)
792
self.do_diag_lock = False
794
self.frame.set_body(self.thePile)
796
self.frame.set_footer(urwid.Pile([self.primaryCols,self.footer2]))
799
def handle_keys(self,keys):
802
if "f8" in keys or 'Q' in keys or 'q' in keys:
805
if "f5" in keys or 'R' in keys:
809
# Disconnect from all networks.
811
self.update_netlist()
813
if not self.scanning:
814
focus = self.thePile.get_focus()
815
self.frame.set_footer(urwid.Pile([self.confCols,self.footer2]))
816
if focus == self.wiredCB:
817
self.diag = WiredSettingsDialog(self.wiredCB.get_body().get_selected_profile())
818
self.frame.set_body(self.diag)
820
# wireless list only other option
821
wid,pos = self.thePile.get_focus().get_focus()
822
self.diag = WirelessSettingsDialog(pos,self.frame)
823
self.diag.ready_widgets(ui,self.frame)
824
self.frame.set_body(self.diag)
825
self.diag_type = 'conf'
826
if "enter" in keys or 'C' in keys:
827
if not self.scanning:
828
focus = self.frame.body.get_focus()
829
if focus == self.wiredCB:
831
self.connect("wired",0)
833
# wless list only other option, if it is around
834
if self.wlessLB != self.no_wlan:
835
wid,pos = self.thePile.get_focus().get_focus()
836
self.connect("wireless",pos)
838
# Force disconnect here if connection in progress
840
daemon.CancelConnect()
841
# Prevents automatic reconnecting if that option is enabled
842
daemon.SetForcedDisconnect(True)
845
self.pref = PrefsDialog(self.frame,(0,1),ui,
846
dbusmanager.get_dbus_ifaces())
847
self.pref.load_settings()
848
self.pref.ready_widgets(ui,self.frame)
849
self.frame.set_footer(urwid.Pile([self.prefCols,self.footer2]))
850
self.diag = self.pref
851
self.diag_type = 'pref'
852
self.frame.set_body(self.diag)
853
# Halt here, keypress gets passed to the dialog otherwise
856
about_dialog(self.frame)
858
self.raise_hidden_network_dialog()
859
if "H" in keys or 'h' in keys or '?' in keys:
860
# FIXME I shouldn't need this, OptCols messes up this one
863
help_dialog(self.frame)
865
focus = self.thePile.get_focus()
866
if focus == self.wiredCB:
868
netname = self.wiredCB.get_body().get_selected_profile()
871
netname = str(self.wlessLB.get_focus()[1])
872
run_configscript(self.frame,netname,nettype)
874
exitcode,data = AdHocDialog().run(ui,self.frame)
875
#data = (essid,ip,channel,use_ics,use_encrypt,key_edit)
877
wireless.CreateAdHocNetwork(data[0],
884
if urwid.is_mouse_event(k):
885
event, button, col, row = k
886
self.frame.mouse_event( self.size,
887
event, button, col, row,
890
k = self.frame.keypress(self.size,k)
892
if k == 'esc' or k == 'q' or k == 'Q':
893
self.restore_primary()
896
self.diag.save_settings()
897
self.restore_primary()
899
if k == "window resize":
900
self.size = ui.get_cols_rows()
903
def call_update_ui(self,source,cb_condition):
909
def update_ui(self,from_key=False):
913
input_data = ui.get_input_nonblocking()
914
# Resolve any "alarms" in the waiting
915
self.handle_keys(input_data[1])
918
canvas = self.frame.render( (self.size),True )
919
ui.draw_screen((self.size),canvas)
921
if self.update_tag != None:
922
gobject.source_remove(self.update_tag)
926
def connect(self, nettype, networkid, networkentry=None):
927
""" Initiates the connection process in the daemon. """
928
if nettype == "wireless":
929
wireless.ConnectWireless(networkid)
930
elif nettype == "wired":
934
########################################
935
##### INITIALIZATION FUNCTIONS
936
########################################
941
misc.RenameProcess('wicd-curses')
943
import urwid.raw_display
944
ui = urwid.raw_display.Screen()
947
# dlogger = logging.getLogger("Debug")
948
# dlogger.setLevel(logging.DEBUG)
949
# dlogger.debug("wicd-curses debug logging started")
951
# Default Color scheme.
952
# Other potential color schemes can be found at:
953
# http://excess.org/urwid/wiki/RecommendedPalette
955
# Thanks to nanotube on #wicd for helping with this
956
ui.register_palette([
957
('body','default','default'),
958
('focus','black','light gray'),
959
('header','light blue','default'),
960
('important','light red','default'),
961
('connected','dark green','default'),
962
('connected focus','black','dark green'),
963
('editcp', 'default', 'default', 'standout'),
964
('editbx', 'light gray', 'dark blue'),
965
('editfc', 'white','dark blue', 'bold'),
966
('editnfc','brown','default','bold'),
967
('tab active','dark green','light gray'),
968
('infobar','light gray','dark blue'),
969
('listbar','light blue','default'),
970
# Simple colors around text
971
('green','dark green','default'),
972
('blue','light blue','default'),
973
('red','dark red','default'),
974
('bold','white','black','bold')])
975
# This is a wrapper around a function that calls another a function that
976
# is a wrapper around a infinite loop. Fun.
977
urwid.set_encoding('utf8')
983
loop = gobject.MainLoop()
985
ui.set_mouse_tracking()
988
# Connect signals and whatnot to UI screen control functions
989
bus.add_signal_receiver(app.dbus_scan_finished, 'SendEndScanSignal',
990
'org.wicd.daemon.wireless')
991
bus.add_signal_receiver(app.dbus_scan_started, 'SendStartScanSignal',
992
'org.wicd.daemon.wireless')
993
# I've left this commented out many times.
994
bus.add_signal_receiver(app.update_netlist, 'StatusChanged',
996
# Update the connection status on the bottom every 2 s.
997
gobject.timeout_add(2000,app.update_status)
999
# Get input file descriptors and add callbacks to the ui-updating function
1000
fds = ui.get_input_descriptors()
1002
gobject.io_add_watch(fd, gobject.IO_IN,app.call_update_ui)
1006
# Mostly borrowed from gui.py
1007
def setup_dbus(force=True):
1008
global bus, daemon, wireless, wired
1010
dbusmanager.connect_to_dbus()
1011
except DBusException:
1012
print >> sys.stderr, language['cannot_connect_to_daemon']
1013
bus = dbusmanager.get_bus()
1014
dbus_ifaces = dbusmanager.get_dbus_ifaces()
1015
daemon = dbus_ifaces['daemon']
1016
wireless = dbus_ifaces['wireless']
1017
wired = dbus_ifaces['wired']
1019
netentry_curses.dbus_init(dbus_ifaces)
1024
########################################
1025
##### MAIN ENTRY POINT
1026
########################################
1027
if __name__ == '__main__':
1029
parser = OptionParser(version="wicd-curses-%s (using wicd %s)" % (CURSES_REV,daemon.Hello()))
1030
except Exception, e:
1031
if "DBus.Error.AccessDenied" in e.get_dbus_name():
1032
print language['access_denied_wc'].replace('$A','\033[1;34m'+wpath.wicd_group+'\033[0m')
1036
#parser.add_option("-d", "--debug",action="store_true"
1037
# ,dest='debug',help="enable logging of wicd-curses (currently does nothing)")
1038
(options,args) = parser.parse_args()