From 32bb2038499b2c3b98595ec37586daa9539877d9 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Fri, 9 Jan 2009 23:58:14 -0500 Subject: [PATCH 01/14] Initial crack at reworking GUI some more. --- wicd/netentry.py | 337 +++++++++++++++++++++++++++-------------------- 1 file changed, 195 insertions(+), 142 deletions(-) diff --git a/wicd/netentry.py b/wicd/netentry.py index 1d793bf..54c8f9f 100644 --- a/wicd/netentry.py +++ b/wicd/netentry.py @@ -41,6 +41,11 @@ class SmallLabel(gtk.Label): def __init__(self, text=''): gtk.Label.__init__(self, text) self.set_size_request(50, -1) + +class LeftAlignedLabel(gtk.Label): + def __init__(self, label=None): + gtk.Label.__init__(self, label) + self.set_alignment(0.0, 0.5) class LabelEntry(gtk.HBox): """ A label on the left with a textbox on the right. """ @@ -126,6 +131,19 @@ class AdvancedSettingsDialog(gtk.Dialog): self.hbox_dns.pack_start(self.chkbox_static_dns) self.hbox_dns.pack_start(self.chkbox_global_dns) + # Set up the script settings button + self.script_button = gtk.Button() + script_image = gtk.Image() + script_image.set_from_stock(gtk.STOCK_EXECUTE, 4) + script_image.set_padding(4, 0) + #self.script_button.set_alignment(.5, .5) + self.script_button.set_image(script_image) + self.script_button.set_label(language['scripts']) + + self.button_hbox = gtk.HBox(False, 2) + self.button_hbox.pack_start(self.script_button, fill=False, expand=False) + self.button_hbox.show() + assert(isinstance(self.vbox, gtk.VBox)) self.vbox.pack_start(self.chkbox_static_ip, fill=False, expand=False) self.vbox.pack_start(self.txt_ip, fill=False, expand=False) @@ -137,6 +155,7 @@ class AdvancedSettingsDialog(gtk.Dialog): self.vbox.pack_start(self.txt_dns_1, fill=False, expand=False) self.vbox.pack_start(self.txt_dns_2, fill=False, expand=False) self.vbox.pack_start(self.txt_dns_3, fill=False, expand=False) + self.vbox.pack_end(self.button_hbox, fill=False, expand=False, padding=5) # Connect the events to the actions @@ -277,12 +296,27 @@ class WiredSettingsDialog(AdvancedSettingsDialog): """ Build the wired settings dialog. """ AdvancedSettingsDialog.__init__(self) self.des = self.connect("destroy", self.destroy_called) + self.script_button.connect("button-press-event", self.edit_scripts) self.prof_name = name def set_net_prop(self, option, value): """ Sets the given option to the given value for this network. """ wired.SetWiredProperty(option, value) + def edit_scripts(self, widget=None, event=None): + """ Launch the script editting dialog. """ + profile = self.combo_profile_names.get_active_text() + cmdend = [os.path.join(wpath.lib, "configscript.py"), profile, "wired"] + if os.getuid() != 0: + cmdbase = misc.get_sudo_cmd(language['scripts_need_pass']) + if not cmdbase: + error(None, language["no_sudo_prog"]) + return + cmdbase.extend(cmdend) + misc.LaunchAndWait(cmdbase) + else: + misc.LaunchAndWait(cmdend) + def set_values(self): """ Fill in the Gtk.Entry objects with the correct values. """ self.txt_ip.set_text(self.format_entry("ip")) @@ -330,6 +364,11 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.combo_encryption.set_sensitive(False) self.encrypt_types = misc.LoadEncryptionMethods() + information_button = gtk.Button(stock=gtk.STOCK_INFO) + self.button_hbox.pack_start(information_button, False, False) + information_button.connect('clicked', lambda *a, **k: WirelessInformationDialog(networkID)) + information_button.show() + # Build the encryption menu activeID = -1 # Set the menu to this item when we are done for x, enc_type in enumerate(self.encrypt_types): @@ -354,6 +393,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): # Connect signals. self.chkbox_encryption.connect("toggled", self.toggle_encryption) self.combo_encryption.connect("changed", self.change_encrypt_method) + self.script_button.connect("button-press-event", self.edit_scripts) self.des = self.connect("destroy", self.destroy_called) def destroy_called(self, *args): @@ -363,6 +403,20 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.destroy() del self + def edit_scripts(self, widget=None, event=None): + """ Launch the script editting dialog. """ + cmdend = [os.path.join(wpath.lib, "configscript.py"), + str(self.networkID), "wireless"] + if os.getuid() != 0: + cmdbase = misc.get_sudo_cmd(language['scripts_need_pass']) + if not cmdbase: + error(None, language["no_sudo_prog"]) + return + cmdbase.extend(cmdend) + misc.LaunchAndWait(cmdbase) + else: + misc.LaunchAndWait(cmdend) + def set_net_prop(self, option, value): """ Sets the given option to the given value for this network. """ wireless.SetWirelessProperty(self.networkID, option, value) @@ -479,7 +533,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): box.entry.set_text(noneToBlankString( wireless.GetWirelessProperty(self.networkID, opts[x][1]))) - self.vbox_encrypt_info.show_all() + self.vbox_encrypt_info.show_all() class NetworkEntry(gtk.HBox): @@ -499,18 +553,17 @@ class NetworkEntry(gtk.HBox): self.pack_start(self.image, False, False) # Create an HBox to hold the buttons - self.buttons_hbox = gtk.HBox(False, 3) - self.buttons_hbox.set_border_width(5) + self.buttons_hbox = gtk.HBox(False, 6) # Set up the Connect button self.connect_button = gtk.Button(stock=gtk.STOCK_CONNECT) self.connect_hbox = gtk.HBox(False, 2) - self.buttons_hbox.pack_start(self.connect_button, False, False) + self.connect_hbox.pack_start(self.connect_button, False, False) self.connect_hbox.show() # Set up the Disconnect button self.disconnect_button = gtk.Button(stock=gtk.STOCK_DISCONNECT) - self.buttons_hbox.pack_start(self.disconnect_button, False, False) + self.connect_hbox.pack_start(self.disconnect_button, False, False) # Create a label to hold the name of the entry self.name_label = gtk.Label() @@ -530,27 +583,18 @@ class NetworkEntry(gtk.HBox): self.advanced_button.set_label(language['advanced_settings']) self.advanced_button.set_image(self.advanced_image) - # Set up the script settings button - self.script_button = gtk.Button() - self.script_image = gtk.Image() - self.script_image.set_from_stock(gtk.STOCK_EXECUTE, 4) - self.script_image.set_padding(4, 0) - self.script_button.set_alignment(.5, .5) - self.script_button.set_image(self.script_image) - self.script_button.set_label(language['scripts']) - - self.buttons_hbox.pack_start(self.script_button, False, False) + #self.buttons_hbox.pack_start(self.script_button, False, False) + self.buttons_hbox.pack_start(self.connect_hbox, False, False) self.buttons_hbox.pack_start(self.advanced_button, False, False) self.vbox_top = gtk.VBox(False, 0) - self.vbox_top.pack_end(self.buttons_hbox, False, False) + #self.vbox_top.pack_end(self.buttons_hbox, False, False) + #self.vbox_top.pack_end(self.connect_hbox, False, False) - aligner = gtk.Alignment(xscale=1.0) - aligner.add(self.vbox_top) - aligner.set_padding(0, 0, 15, 0) + self.expander_vbox.pack_start(self.name_label) - self.expander_vbox.pack_start(aligner) - self.expander_vbox.pack_start(self.connect_hbox, False, False) + self.expander_vbox.pack_start(self.vbox_top) + self.expander_vbox.pack_start(self.buttons_hbox) def destroy_called(self, *args): """ Clean up everything. """ @@ -651,20 +695,6 @@ class WiredNetworkEntry(NetworkEntry): def save_wired_settings(self): """ Save wired network settings. """ return self.advanced_dialog.save_settings() - - def edit_scripts(self, widget=None, event=None): - """ Launch the script editting dialog. """ - profile = self.combo_profile_names.get_active_text() - cmdend = [os.path.join(wpath.lib, "configscript.py"), profile, "wired"] - if os.getuid() != 0: - cmdbase = misc.get_sudo_cmd(language['scripts_need_pass']) - if not cmdbase: - error(None, language["no_sudo_prog"]) - return - cmdbase.extend(cmdend) - misc.LaunchAndWait(cmdbase) - else: - misc.LaunchAndWait(cmdend) def check_enable(self): """ Disable objects if the profile list is empty. """ @@ -767,47 +797,20 @@ class WirelessNetworkEntry(NetworkEntry): self.networkID = networkID self.image.set_padding(0, 0) - self.image.set_alignment(.5, 0) + self.image.set_alignment(.5, .5) self.image.set_size_request(60, -1) + self.image.show() #self.image.set_from_icon_name("network-wired", 6) self.essid = noneToBlankString(wireless.GetWirelessProperty(networkID, "essid")) + self.name_label.set_markup(self._escape(self.essid)) print "ESSID : " + self.essid - # Make the combo box. - self.lbl_strength = gtk.Label() - self.lbl_strength.set_alignment(0, 0.5) - self.lbl_encryption = gtk.Label() - self.lbl_encryption.set_alignment(0, 0.5) - self.lbl_mac = gtk.Label() - self.lbl_mac.set_alignment(0, 0.5) - self.lbl_channel = gtk.Label() - self.lbl_channel.set_alignment(0, 0.5) - self.lbl_mode = gtk.Label() - self.lbl_mode.set_alignment(0, 0.5) - self.hbox_status = gtk.HBox(False, 5) self.chkbox_autoconnect = gtk.CheckButton(language['automatic_connect']) - # Set the values of the network info labels. self.set_signal_strength(wireless.GetWirelessProperty(networkID, 'quality'), wireless.GetWirelessProperty(networkID, 'strength')) - self.set_mac_address(wireless.GetWirelessProperty(networkID, 'bssid')) - self.set_mode(wireless.GetWirelessProperty(networkID, 'mode')) - self.set_channel(wireless.GetWirelessProperty(networkID, 'channel')) - self.set_encryption(wireless.GetWirelessProperty(networkID, - 'encryption'), - wireless.GetWirelessProperty(networkID, - 'encryption_method')) - - self.name_label.set_markup(self._escape(self.essid)) - - information_button = gtk.Button(stock=gtk.STOCK_INFO) - - self.buttons_hbox.pack_start(information_button, False, False) - - information_button.connect('clicked', self.show_info_dialog) - # Add the wireless network specific parts to the NetworkEntry # VBox objects. self.vbox_top.pack_start(self.chkbox_autoconnect, False, False) @@ -819,53 +822,13 @@ class WirelessNetworkEntry(NetworkEntry): self.chkbox_autoconnect.set_active(False) # Connect signals. - self.chkbox_autoconnect.connect("toggled", self.update_autoconnect) - self.script_button.connect("button-press-event", self.edit_scripts) + self.chkbox_autoconnect.connect("toggled", self.update_autoconnect) # Show everything self.show_all() self.advanced_dialog = WirelessSettingsDialog(networkID) self.wifides = self.connect("destroy", self.destroy_called) - - def show_info_dialog(self, button=None): - dialog = gtk.Dialog() - - dialog.set_title('Network Information') - - vbox = dialog.vbox - - table = gtk.Table(5, 2) - table.set_col_spacings(4) - vbox.pack_start(table) - - class LeftAlignedLabel(gtk.Label): - def __init__(self, label=None): - gtk.Label.__init__(self, label) - self.set_alignment(0.0, 0.5) - - # Pack the network status HBox. - table.attach(LeftAlignedLabel('Signal strength'), 0, 1, 0, 1) - table.attach(self.lbl_strength, 1, 2, 0, 1) - - table.attach(LeftAlignedLabel('Encryption type'), 0, 1, 1, 2) - table.attach(self.lbl_encryption, 1, 2, 1, 2) - - table.attach(LeftAlignedLabel('Access point address'), 0, 1, 2, 3) - table.attach(self.lbl_mac, 1, 2, 2, 3) - - table.attach(LeftAlignedLabel('Mode'), 0, 1, 3, 4) - table.attach(self.lbl_mode, 1, 2, 3, 4) - - table.attach(LeftAlignedLabel('Channel'), 0, 1, 4, 5) - table.attach(self.lbl_channel, 1, 2, 4, 5) - - vbox.show_all() - - dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) - - dialog.run() - dialog.destroy() - + def _escape(self, val): """ Escapes special characters so they're displayed correctly. """ return val.replace("&", "&").replace("<", "<").\ @@ -874,7 +837,14 @@ class WirelessNetworkEntry(NetworkEntry): def save_wireless_settings(self, networkid): """ Save wireless network settings. """ return self.advanced_dialog.save_settings(networkid) - + + def update_autoconnect(self, widget=None): + """ Called when the autoconnect checkbox is toggled. """ + wireless.SetWirelessProperty(self.networkID, "automatic", + noneToString(self.chkbox_autoconnect. + get_active())) + wireless.SaveWirelessNetworkProperty(self.networkID, "automatic") + def destroy_called(self, *args): """ Clean up everything. """ self.disconnect(self.wifides) @@ -883,7 +853,19 @@ class WirelessNetworkEntry(NetworkEntry): super(WirelessNetworkEntry, self).destroy_called() self.destroy() del self - + + def update_connect_button(self, state, apbssid): + """ Update the connection/disconnect button for this entry. """ + if not apbssid: + apbssid = wireless.GetApBssid() + if state == misc.WIRELESS and \ + apbssid == wireless.GetWirelessProperty(self.networkID, "bssid"): + self.disconnect_button.show() + self.connect_button.hide() + else: + self.disconnect_button.hide() + self.connect_button.show() + def set_signal_strength(self, strength, dbm_strength): """ Set the signal strength displayed in the WirelessNetworkEntry. """ if strength is not None: @@ -922,21 +904,113 @@ class WirelessNetworkEntry(NetworkEntry): signal_img = 'signal-25.png' ending = "%" disp_strength = str(strength) - self.image.set_from_file(wpath.images + signal_img) - self.lbl_strength.set_label(disp_strength + ending) + self.image.show() + + def format_entry(self, networkid, label): + """ Helper method for fetching/formatting wireless properties. """ + return noneToBlankString(wireless.GetWirelessProperty(networkid, label)) + - def update_connect_button(self, state, apbssid): - """ Update the connection/disconnect button for this entry. """ - if not apbssid: - apbssid = wireless.GetApBssid() - if state == misc.WIRELESS and \ - apbssid == wireless.GetWirelessProperty(self.networkID, "bssid"): - self.disconnect_button.show() - self.connect_button.hide() +class WirelessInformationDialog(gtk.Dialog): + def __init__(self, networkID): + gtk.Dialog.__init__(self) + + # Make the combo box. + self.lbl_strength = gtk.Label() + self.lbl_strength.set_alignment(0, 0.5) + self.lbl_encryption = gtk.Label() + self.lbl_encryption.set_alignment(0, 0.5) + self.lbl_mac = gtk.Label() + self.lbl_mac.set_alignment(0, 0.5) + self.lbl_channel = gtk.Label() + self.lbl_channel.set_alignment(0, 0.5) + self.lbl_mode = gtk.Label() + self.lbl_mode.set_alignment(0, 0.5) + self.hbox_status = gtk.HBox(False, 5) + + # Set the values of the network info labels. + self.set_signal_strength(wireless.GetWirelessProperty(networkID, + 'quality'), + wireless.GetWirelessProperty(networkID, + 'strength')) + self.set_mac_address(wireless.GetWirelessProperty(networkID, 'bssid')) + self.set_mode(wireless.GetWirelessProperty(networkID, 'mode')) + self.set_channel(wireless.GetWirelessProperty(networkID, 'channel')) + self.set_encryption(wireless.GetWirelessProperty(networkID, + 'encryption'), + wireless.GetWirelessProperty(networkID, + 'encryption_method')) + + self.set_title('Network Information') + vbox = self.vbox + self.set_has_separator(False) + table = gtk.Table(5, 2) + table.set_col_spacings(12) + vbox.pack_start(table) + + # Pack the network status HBox. + table.attach(LeftAlignedLabel('Signal strength'), 0, 1, 0, 1) + table.attach(self.lbl_strength, 1, 2, 0, 1) + + table.attach(LeftAlignedLabel('Encryption type'), 0, 1, 1, 2) + table.attach(self.lbl_encryption, 1, 2, 1, 2) + + table.attach(LeftAlignedLabel('Access point address'), 0, 1, 2, 3) + table.attach(self.lbl_mac, 1, 2, 2, 3) + + table.attach(LeftAlignedLabel('Mode'), 0, 1, 3, 4) + table.attach(self.lbl_mode, 1, 2, 3, 4) + + table.attach(LeftAlignedLabel('Channel'), 0, 1, 4, 5) + table.attach(self.lbl_channel, 1, 2, 4, 5) + + vbox.show_all() + + self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) + self.show() + self.run() + self.destroy() + + def set_signal_strength(self, strength, dbm_strength): + """ Set the signal strength displayed in the WirelessNetworkEntry. """ + if strength is not None: + strength = int(strength) else: - self.disconnect_button.hide() - self.connect_button.show() + strength = -1 + if dbm_strength is not None: + dbm_strength = int(dbm_strength) + else: + dbm_strength = -100 + display_type = daemon.GetSignalDisplayType() + if daemon.GetWPADriver() == 'ralink legacy' or display_type == 1: + # Use the -xx dBm signal strength to display a signal icon + # I'm not sure how accurately the dBm strength is being + # "converted" to strength bars, so suggestions from people + # for a better way would be welcome. + if dbm_strength >= -60: + signal_img = 'signal-100.png' + elif dbm_strength >= -70: + signal_img = 'signal-75.png' + elif dbm_strength >= -80: + signal_img = 'signal-50.png' + else: + signal_img = 'signal-25.png' + ending = "dBm" + disp_strength = str(dbm_strength) + else: + # Uses normal link quality, should be fine in most cases + if strength > 75: + signal_img = 'signal-100.png' + elif strength > 50: + signal_img = 'signal-75.png' + elif strength > 25: + signal_img = 'signal-50.png' + else: + signal_img = 'signal-25.png' + ending = "%" + disp_strength = str(strength) + self.lbl_strength.set_label(disp_strength + ending) def set_mac_address(self, address): """ Set the MAC address for the WirelessNetworkEntry. """ @@ -962,24 +1036,3 @@ class WirelessNetworkEntry(NetworkEntry): def format_entry(self, networkid, label): """ Helper method for fetching/formatting wireless properties. """ return noneToBlankString(wireless.GetWirelessProperty(networkid, label)) - - def edit_scripts(self, widget=None, event=None): - """ Launch the script editting dialog. """ - cmdend = [os.path.join(wpath.lib, "configscript.py"), - str(self.networkID), "wireless"] - if os.getuid() != 0: - cmdbase = misc.get_sudo_cmd(language['scripts_need_pass']) - if not cmdbase: - error(None, language["no_sudo_prog"]) - return - cmdbase.extend(cmdend) - misc.LaunchAndWait(cmdbase) - else: - misc.LaunchAndWait(cmdend) - - def update_autoconnect(self, widget=None): - """ Called when the autoconnect checkbox is toggled. """ - wireless.SetWirelessProperty(self.networkID, "automatic", - noneToString(self.chkbox_autoconnect. - get_active())) - wireless.SaveWirelessNetworkProperty(self.networkID, "automatic") From 2358357f1df73803d7bd0812858629889b79f7d0 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Thu, 15 Jan 2009 00:56:02 -0500 Subject: [PATCH 02/14] Fix bug where be-ioctl scans always reported channels as 1. Tweak the UI a little bit. Add debugging output when forced_disconnect gets enabled. --- wicd/backends/be-ioctl.py | 2 +- wicd/misc.py | 2 +- wicd/netentry.py | 15 +++++++++++---- wicd/wicd-daemon.py | 2 ++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/wicd/backends/be-ioctl.py b/wicd/backends/be-ioctl.py index b7b4555..b261449 100644 --- a/wicd/backends/be-ioctl.py +++ b/wicd/backends/be-ioctl.py @@ -316,7 +316,7 @@ class WirelessInterface(Interface, wnettools.BaseWirelessInterface): ap['hidden'] = False if cell["channel"]: - ap["channel"] = True + ap["channel"] = cell["channel"] else: ap["channel"] = self._FreqToChannel(cell["frequency"]) diff --git a/wicd/misc.py b/wicd/misc.py index e412cdc..595b171 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -435,7 +435,7 @@ def get_language_list_gui(): language['use_static_ip'] = _('Use Static IPs') language['use_static_dns'] = _('Use Static DNS') language['use_encryption'] = _('Use Encryption') - language['advanced_settings'] = _('Advanced Settings') + language['advanced_settings'] = _('Properties') language['wired_network'] = _('Wired Network') language['wired_network_instructions'] = _('To connect to a wired network,' ' you must create a network profile. To create a network profile, type a' diff --git a/wicd/netentry.py b/wicd/netentry.py index ed4eaba..68d9509 100644 --- a/wicd/netentry.py +++ b/wicd/netentry.py @@ -804,6 +804,7 @@ class WirelessNetworkEntry(NetworkEntry): "essid")) self.lbl_strength = GreyLabel() self.lbl_encryption = GreyLabel() + self.lbl_channel = GreyLabel() print "ESSID : " + self.essid self.chkbox_autoconnect = gtk.CheckButton(language['automatic_connect']) @@ -816,11 +817,13 @@ class WirelessNetworkEntry(NetworkEntry): 'encryption'), wireless.GetWirelessProperty(networkID, 'encryption_method')) + self.set_channel(wireless.GetWirelessProperty(networkID, 'channel')) self.name_label.set_use_markup(True) - self.name_label.set_label("%s %s %s" % (self._escape(self.essid), - self.lbl_strength.get_label(), - self.lbl_encryption.get_label() - ) + self.name_label.set_label("%s %s %s %s" % (self._escape(self.essid), + self.lbl_strength.get_label(), + self.lbl_encryption.get_label(), + self.lbl_channel.get_label(), + ) ) # Add the wireless network specific parts to the NetworkEntry # VBox objects. @@ -927,6 +930,10 @@ class WirelessNetworkEntry(NetworkEntry): self.lbl_encryption.set_label(language['secured']) if not on: self.lbl_encryption.set_label(language['unsecured']) + + def set_channel(self, channel): + """ Set the channel value for the WirelessNetworkEntry. """ + self.lbl_channel.set_label(language['channel'] + ' ' + str(channel)) def format_entry(self, networkid, label): """ Helper method for fetching/formatting wireless properties. """ diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index e762598..223ed46 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -91,6 +91,7 @@ class WicdDaemon(dbus.service.Object): self.vpn_session = None self.gui_open = False self.suspended = False + self.debug_mode = False self.connection_state = misc.NOT_CONNECTED self.connection_info = [""] self.auto_connecting = False @@ -421,6 +422,7 @@ class WicdDaemon(dbus.service.Object): started. """ + if self.debug_mode and value: print "Forced disconnect on" self.forced_disconnect = bool(value) self.wireless_bus.SetForcedDisconnect(bool(value)) self.wired_bus.SetForcedDisconnect(bool(value)) From 514facb4aa512b8dd8bd0223266a5f16d8177a5c Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Thu, 15 Jan 2009 01:21:54 -0500 Subject: [PATCH 03/14] Tweak default window sizes --- wicd/gui.py | 6 ++++-- wicd/prefs.py | 6 ++++-- wicd/wicd-daemon.py | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/wicd/gui.py b/wicd/gui.py index 58aefc6..b1a3065 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -241,8 +241,10 @@ class appGui(object): if width > -1 and height > -1: self.window.resize(int(width), int(height)) else: - self.window.resize(gtk.gdk.screen_width() / 3, - gtk.gdk.screen_height() / 2) + width = int(gtk.gdk.screen_width() / 2) + if width > 530: + width = 530 + self.window.resize(width, int(gtk.gdk.screen_height() / 1.7)) dic = { "refresh_clicked" : self.refresh_clicked, "quit_clicked" : self.exit, diff --git a/wicd/prefs.py b/wicd/prefs.py index 717cdfa..29f5c12 100644 --- a/wicd/prefs.py +++ b/wicd/prefs.py @@ -254,8 +254,10 @@ class PreferencesDialog(object): if width > -1 and height > -1: self.dialog.resize(int(width), int(height)) else: - self.dialog.resize(gtk.gdk.screen_width() / 3, - gtk.gdk.screen_height() / 2) + width = int(gtk.gdk.screen_width() / 2.4) + if width > 450: + width = 450 + self.dialog.resize(width, int(gtk.gdk.screen_height() / 2)) self.wiredcheckbox = setup_label("pref_always_check", 'wired_always_on') diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index 223ed46..b12e0e4 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -632,13 +632,13 @@ class WicdDaemon(dbus.service.Object): """ if win_name == "main": - default_width = 605 - default_height = 400 + default_width = -1 + default_height = -1 width_str = "window_width" height_str = "window_height" else: - default_width = 125 - default_height = 500 + default_width = -1 + default_height = -1 width_str = "pref_width" height_str = "pref_height" From fcf01b12b3cf3034714176cbfd261bb6905a7c04 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Thu, 15 Jan 2009 01:22:40 -0500 Subject: [PATCH 04/14] Use dbusmanager in autoconnect.py --- wicd/autoconnect.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/wicd/autoconnect.py b/wicd/autoconnect.py index 787aae5..a8443cd 100755 --- a/wicd/autoconnect.py +++ b/wicd/autoconnect.py @@ -17,6 +17,8 @@ # along with this program. If not, see . # +from wicd import dbusmanager + import dbus import time import gobject @@ -29,9 +31,9 @@ else: DBusGMainLoop(set_as_default=True) try: - bus = dbus.SystemBus() - proxy_obj = bus.get_object('org.wicd.daemon', '/org/wicd/daemon') - daemon = dbus.Interface(proxy_obj, 'org.wicd.daemon') + dbusmanager.connect_to_dbus() + daemon = dbusmanager.get_interface('daemon') + wireless = dbusmanager.get_interface('wireless') except Exception, e: print>>sys.stderr, "Exception caught: %s" % str(e) print>>sys.stderr, 'Could not connect to daemon.' @@ -46,10 +48,10 @@ def error_handler(*args): if __name__ == '__main__': try: - time.sleep(3) + time.sleep(2) + wireless.Scan() daemon.SetSuspend(False) if not daemon.CheckIfConnecting(): - daemon.SetForcedDisconnect(False) daemon.AutoConnect(True, reply_handler=handler, error_handler=handler) except Exception, e: print>>sys.stderr, "Exception caught: %s" % str(e) From 6e9eb1cd65a73154a52ee1ec8e0035df64d44093 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Thu, 15 Jan 2009 21:46:35 -0500 Subject: [PATCH 05/14] curses/wicd-curses.py: ListBox focus-maintaining code completely debugged --- curses/wicd-curses.py | 64 +++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 53c896f..212a178 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -104,6 +104,7 @@ class wrap_exceptions: # Zap the screen ui.stop() # Print out standard notification: + print "\nEXCEPTION!" print "Please report this to the maintainer and/or file a bug report with the backtrace below:" print redraw_tag @@ -400,7 +401,6 @@ class appGUI(): self.screen_locked = False #self.always_show_wired = daemon.GetAlwaysShowWiredInterface() - self.pref = None self.update_status() @@ -432,24 +432,24 @@ class appGUI(): # Location of last known focus is remapped to current location. # This might need to be cleaned up later. - if self.thePile.get_focus() is self.wiredCB: + #self.set_status(str(self.frame.get_body().get_focus())+ ' '+ str(self.wiredCB)) + if self.thePile.get_focus() == self.wiredCB: wlessorwired = self.WIRED_IDX - else : - wlessorwired = self.WLESS_IDX - if self.thePile.get_focus() == self.no_wlan: - where = 0 - elif self.thePile.get_focus() == self.wiredCB: where = self.thePile.get_focus().get_body().get_focus()[1] - else: - where = self.thePile.get_focus().get_focus()[1] - + else:#self.thePile.get_focus() == self.wlessLB : + wlessorwired = self.WLESS_IDX + if self.wlessLB == self.no_wlan: + where = None + else: + where = self.frame.get_body().get_focus().get_focus()[1] + #where = self.wlessLB.get_focus()[1] self.focusloc = (wlessorwired,where) - # Be clunky until I get to a later stage of development. # Update the list of networks. Usually called by DBus. # TODO: Preserve current focus when updating the list. @wrap_exceptions() def update_netlist(self,state=None, x=None, force_check=False,firstrun=False): + # Run focus-collecting code if we are not running this for the first time if not firstrun: self.update_focusloc() """ Updates the overall network list.""" @@ -462,31 +462,42 @@ class appGUI(): self.wiredCB.get_body().set_list(wiredL) self.wiredCB.get_body().build_combobox(self.frame,ui,3) if len(wlessL) != 0: - self.wlessLB = urwid.ListBox(wlessL) - #self.wlessLB.body = urwid.SimpleListWalker(wlessL) + if self.wlessLB == self.no_wlan: + self.wlessLB = urwid.ListBox(wlessL) + else: + self.wlessLB.body = urwid.SimpleListWalker(wlessL) else: self.wlessLB = self.no_wlan - #self.wlessLB.body = urwid.SimpleListWalker([self.no_wlan]) if daemon.GetAlwaysShowWiredInterface() or wired.CheckPluggedIn(): #if daemon.GetAlwaysShowWiredInterface(): + #if firstrun: self.thePile = urwid.Pile([('fixed',1,self.wiredH), ('fixed',1,self.wiredCB), ('fixed',1,self.wlessH), self.wlessLB] ) + if not firstrun: + self.frame.body = self.thePile #self.focusloc = (self.thePile.get_focus(), # self.thePile.get_focus().get_focus()[1]) self.thePile.set_focus(self.focusloc[0]) if self.focusloc[0] == self.WIRED_IDX: self.thePile.get_focus().get_body().set_focus(self.focusloc[1]) else: - self.thePile.get_focus().set_focus(self.focusloc[1]) + if self.wlessLB is not self.no_wlan: + self.thePile.get_focus().set_focus(self.focusloc[1]) + else: + self.thePile.set_focus(self.wiredCB) else: self.thePile = urwid.Pile([('fixed',1,self.wlessH),self.wlessLB] ) - self.frame.body = self.thePile - if self.focusloc[0] == self.wlessLB: - self.wlessLB.set_focus(self.focusloc[1]) + if not firstrun: + self.frame.body = self.thePile + #if self.focusloc[0] == self.wlessLB: + self.wlessLB.set_focus(self.focusloc[1]) + #self.thePile.get_focus().set_focus(self.focusloc[1]) #self.always_show_wired = not self.always_show_wired self.prev_state = state + if not firstrun: + self.update_ui() # Update the footer/status bar @wrap_exceptions() @@ -529,6 +540,7 @@ class appGUI(): return True else: self.set_status(language['not_connected']) + self.update_ui() return True @@ -542,6 +554,8 @@ class appGUI(): # something, and we aren't connecting to something, return False # immediately. if from_idle and not self.connecting: + self.update_netlist() + self.update_ui() return False toAppend = '' # If we are connecting and being called from the idle function, spin @@ -558,12 +572,15 @@ class appGUI(): # Not necessary in the end, but I will be using footer1 for stuff in # the long run, so I might as well put something there. incr = 0 + @wrap_exceptions() def idle_incr(self): - theText = "" + theText = " " + #if self.special != None: + # theText += self.special if self.connecting: - theText = "-- Connecting -- Press ESC to cancel " + theText += "-- Connecting -- Press ESC to cancel " quit_note = "-- Press F8 or Q to quit." - self.footer1 = urwid.Text(str(self.incr) + ' '+theText+quit_note) + self.footer1 = urwid.Text(str(self.incr) + theText+quit_note,wrap='clip') self.incr+=1 return True @@ -612,8 +629,9 @@ class appGUI(): # Guess what! I actually need to put this here, else I'll have tons of # references to self.frame lying around. ^_^ if "enter" in keys: - focus = self.thePile.get_focus() - if focus is self.wiredCB: + focus = self.frame.body.get_focus() + if focus == self.wiredCB: + self.special = focus self.connect("wired",0) else: # wless list only other option From 75219d78c47cbfc11f4b5ef27c9894c250e6f9d2 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Sat, 17 Jan 2009 12:58:02 -0500 Subject: [PATCH 06/14] Fix bug where encryption keys with non-ascii characters caused crashes. Only write settings being saved if debug mode is on. Clear keys entered through the GUI when the encryption checkbox is disabled. --- wicd/configmanager.py | 18 +++++++++++------- wicd/misc.py | 2 +- wicd/netentry.py | 7 +++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/wicd/configmanager.py b/wicd/configmanager.py index 6630773..c95b911 100644 --- a/wicd/configmanager.py +++ b/wicd/configmanager.py @@ -26,14 +26,15 @@ reusable for other purposes as well. from ConfigParser import RawConfigParser -from wicd.misc import stringToNone, Noneify +from wicd.misc import stringToNone, Noneify, to_unicode class ConfigManager(RawConfigParser): """ A class that can be used to manage a given configuration file. """ - def __init__(self, path): + def __init__(self, path, debug=False): RawConfigParser.__init__(self) self.config_file = path + self.debug = debug self.read(path) def __repr__(self): @@ -57,8 +58,9 @@ class ConfigManager(RawConfigParser): """ if not self.has_section(section): self.add_section(section) - - RawConfigParser.set(self, section, str(option), str(value)) + if isinstance(value, basestring): + value = to_unicode(value) + RawConfigParser.set(self, section, str(option), value) if save: self.write() @@ -80,11 +82,13 @@ class ConfigManager(RawConfigParser): if self.has_option(section, option): ret = RawConfigParser.get(self, section, option) if default: - print ''.join(['found ', option, ' in configuration ', ret]) + if self.debug: + print ''.join(['found ', option, ' in configuration ', + str(ret)]) else: if default != "__None__": - print ''.join(['did not find ', option, - ' in configuration, setting default ', str(default)]) + if self.debug: + print 'did not find %s in configuration, setting default %s' % (option, str(default)) self.set(section, option, str(default), save=True) ret = default else: diff --git a/wicd/misc.py b/wicd/misc.py index 595b171..5f7f928 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -318,7 +318,7 @@ def get_gettext(): def to_unicode(x): """ Attempts to convert a string to utf-8. """ # If this is a unicode string, encode it and return - if type(x) not in [unicode, str]: + if not isinstance(x, basestring): return x if isinstance(x, unicode): return x.encode('utf-8') diff --git a/wicd/netentry.py b/wicd/netentry.py index 68d9509..e000e93 100644 --- a/wicd/netentry.py +++ b/wicd/netentry.py @@ -471,17 +471,16 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): if encryption_info[x].get_text() == "": error(self, language['encrypt_info_missing']) return False - self.set_net_prop(x, noneToString(encryption_info[x]. - get_text())) + self.set_net_prop(x, noneToString(encryption_info[x].get_text())) elif not self.chkbox_encryption.get_active() and \ wireless.GetWirelessProperty(networkid, "encryption"): error(self, language['enable_encryption']) return False else: - print 'encryption is ' + str(wireless.GetWirelessProperty(networkid, - "encryption")) print "no encryption specified..." self.set_net_prop("enctype", "None") + for x in self.encryption_info: + self.set_net_prop(x, "") AdvancedSettingsDialog.save_settings(self) if self.chkbox_global_settings.get_active(): From be30004f0f59bb4ca7cf14a0879a1600ef1d4808 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Sat, 17 Jan 2009 15:13:53 -0500 Subject: [PATCH 07/14] Wired network control support is now more-or-less complete curses/curses_misc.py: Made set_focus() actually set the focus Added ability for combobox to rebuild itself curses/netentry_curses: Added WiredSettingsDialog. Sometimes, the "Defaultness" of the network takes a little while to show up in the dialog. Don't know why yet. Reorganized some of the AdvancedSettingsDialog code curses/wicd-curses.py: Reactivated WiredComboBox Added support for WiredSettingsDialog Added ability to create and delete wired network profiles Fixed bug where the program could crash on the end of scanning networks if timing is slightly off Display the screen locker immediately after initiating a scan curses/README,TODO: Wired network support is complete in/man=wicd-curses.8.in: Wired network support is now complete Added revision information to the bottom of the man page --- curses/README | 4 +- curses/TODO | 1 - curses/curses_misc.py | 15 +++++- curses/netentry_curses.py | 99 ++++++++++++++++++++++++++++++------- curses/wicd-curses.py | 95 +++++++++++++++++++++-------------- in/man=wicd-curses.8.in | 10 ++-- in/other=WHEREAREMYFILES.in | 10 ++-- 7 files changed, 167 insertions(+), 67 deletions(-) diff --git a/curses/README b/curses/README index 01cec1f..cfda201 100644 --- a/curses/README +++ b/curses/README @@ -22,11 +22,11 @@ D : disconnect from all active networks ESC : if connecting to a network, stop doing so ENTER : Attempt connection to selected network P : Display preferences dialog -C : Display network configuration for selected network (only works for - wireless at the moment) +C : Display network configuration for selected network A : Display "About" dialog I : Raise the "Scan for hidden networks" dialog H : Raise help dialog +delete : Delete selected wired network profile (from the wired ComboBox) IN DIALOGS (Meta usually is "Alt"): ESC or Q: Quit dialog without saving information (if present) diff --git a/curses/TODO b/curses/TODO index 22a63c9..129fe2f 100644 --- a/curses/TODO +++ b/curses/TODO @@ -1,6 +1,5 @@ Things to do (in no particular order): -* Make a network config dialog for wired interfaces * Implement a keyhandler function for the overall frame * Make keystrokes customizable * Make color schemes customizable diff --git a/curses/curses_misc.py b/curses/curses_misc.py index e79a74c..9cd0346 100644 --- a/curses/curses_misc.py +++ b/curses/curses_misc.py @@ -295,17 +295,28 @@ class ComboBox(urwid.WidgetWrap): self.use_enter = use_enter # The Focus self.focus = focus + # The callback and friends self.callback = callback self.user_args = user_args + + # Widget references to simplify some things + self.body = None + self.ui = None + self.row = None def set_list(self,list): self.list = list def set_focus(self,index): self.focus = index + self.cbox.set_w(SelText(self.list[index]+' vvv')) + def rebuild_combobox(self): + self.build_combobox(self.body,self.ui,self.row) def build_combobox(self,body,ui,row): str,trash = self.label.get_text() + + self.cbox = DynWrap(SelText([self.list[self.focus]+' vvv']),attrs=self.attrs,focus_attr=self.focus_attr) if str != '': w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1) @@ -319,6 +330,7 @@ class ComboBox(urwid.WidgetWrap): self.set_w(w) self.body = body self.ui = ui + self.row = row # If we press space or enter, be a combo box! def keypress(self,size,key): @@ -331,7 +343,8 @@ class ComboBox(urwid.WidgetWrap): raise ComboBoxException('ComboBox must be built before use!') retval = self.overlay.show(self.ui,self.body) if retval != None: - self.cbox.set_w(SelText(retval+' vvv')) + self.set_focus(self.list.index(retval)) + #self.cbox.set_w(SelText(retval+' vvv')) if self.callback != None: self.callback(self,self.overlay._listbox.get_focus()[1],self.user_args) return self._w.keypress(size,key) diff --git a/curses/netentry_curses.py b/curses/netentry_curses.py index 09fa7f8..4274625 100644 --- a/curses/netentry_curses.py +++ b/curses/netentry_curses.py @@ -136,7 +136,7 @@ class AdvancedSettingsDialog(urwid.WidgetWrap): self.global_dns_cb.set_sensitive(new_state) # use_global_dns_cb is DynWrapped if checkb == self.global_dns_cb.get_w(): - for w in [ self.dns_dom_edit,self.search_dom_edit, + for w in [self.dns_dom_edit,self.search_dom_edit, self.dns1,self.dns2,self.dns3 ]: w.set_sensitive(not new_state) @@ -174,31 +174,93 @@ class AdvancedSettingsDialog(urwid.WidgetWrap): self.set_net_prop("dns2", '') self.set_net_prop("dns3", '') + def prerun(self,ui,dim,display): + pass def run(self,ui,dim,display): + self.ui = ui + self.parent = display width,height = ui.get_cols_rows() - overlay = urwid.Overlay(self, display, ('fixed left', 0),width + self.overlay = urwid.Overlay(self, display, ('fixed left', 0),width , ('fixed top',1), height-3) + self.prerun(ui,dim,display) #self.ready_comboboxes(ui,overlay) keys = True while True: if keys: - ui.draw_screen(dim, overlay.render(dim, True)) + ui.draw_screen(dim, self.overlay.render(dim, True)) keys = ui.get_input() + for k in keys: + #Send key to underlying widget: + if urwid.is_mouse_event(k): + event, button, col, row = k + self.overlay.mouse_event( dim, + event, button, col, row, + focus=True) + self.overlay.keypress(dim, k) if "window resize" in keys: dim = ui.get_cols_rows() if "esc" in keys or 'Q' in keys: return False - for k in keys: - #Send key to underlying widget: - overlay.keypress(dim, k) - # Check if buttons are pressed. - #if self.CANCEL_PRESSED: - # return False - #if self.OK_PRESSED or 'meta enter' in keys: - # return True + if "meta enter" in keys or self.OK_PRESSED: + self.OK_PRESSED = False + if self.save_settings(): + return True + if self.CANCEL_PRESSED: + return False + +class WiredSettingsDialog(AdvancedSettingsDialog): + def __init__(self,name): + global wired, daemon + AdvancedSettingsDialog.__init__(self) + self.set_default = urwid.CheckBox(language['default_wired']) + #self.cur_default = + # Add widgets to listbox + self._w.body.body.append(self.set_default) + self._w.body.body.append(self.button_cols) + + self.prof_name = name + self._w.header = urwid.Text( ('header',">Configuring preferences for wired profile \"%s\"" % self.prof_name),align='right' ) + + self.set_values() + def set_net_prop(self,option,value): + wired.SetWiredProperty(option,value) + def set_values(self): + self.ip_edit.set_edit_text(self.format_entry("ip")) + self.netmask_edit.set_edit_text(self.format_entry("netmask")) + self.gateway_edit.set_edit_text(self.format_entry("gateway")) + + self.global_dns_cb.set_state(bool(wired.GetWiredProperty('use_global_dns'))) + self.static_dns_cb.set_state(bool(wired.GetWiredProperty('use_static_dns'))) + + self.dns1.set_edit_text(self.format_entry( "dns1")) + self.dns2.set_edit_text(self.format_entry( "dns2")) + self.dns3.set_edit_text(self.format_entry( "dns3")) + self.dns_dom_edit.set_edit_text(self.format_entry("dns_domain")) + self.search_dom_edit.set_edit_text(self.format_entry("search_domain")) + + self.set_default.set_state(to_bool(wired.GetWiredProperty("default"))) + + def save_settings(self): + AdvancedSettingsDialog.save_settings(self) + if self.set_default.get_state(): + wired.UnsetWiredDefault() + print self.set_default.get_state() + if self.set_default.get_state(): + bool = True + else: + bool = False + wired.SetWiredProperty("default",bool) + wired.SaveWiredNetworkProfile(self.prof_name) + return True + + def format_entry(self, label): + """ Helper method to fetch and format wired properties. """ + return noneToBlankString(wired.GetWiredProperty(label)) + def prerun(self,ui,dim,display): + pass ######################################## @@ -257,6 +319,13 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.global_settings_chkbox.set_state(bool(wireless.GetWirelessProperty(networkID ,'use_settings_globally'))) + # Throw the encryption stuff into a list + list = [] + for x, enc_type in enumerate(self.encrypt_types): + list.append(enc_type[0]) + self.encryption_combo.set_list(list) + + self.change_encrypt_method() activeID = -1 # Set the menu to this item when we are done user_enctype = wireless.GetWirelessProperty(networkID, "enctype") for x, enc_type in enumerate(self.encrypt_types): @@ -270,12 +339,6 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): #self.lbox_encrypt_info.set_sensitive(True) else: self.encryption_combo.set_focus(0) - # Throw the encryption stuff into a list - list = [] - for x, enc_type in enumerate(self.encrypt_types): - list.append(enc_type[0]) - self.encryption_combo.set_list(list) - self.change_encrypt_method() def set_net_prop(self, option, value): """ Sets the given option to the given value for this network. """ @@ -363,7 +426,7 @@ class WirelessSettingsDialog(AdvancedSettingsDialog): self.overlay = urwid.Overlay(self, display, ('fixed left', 0),width , ('fixed top',1), height-3) self.encryption_combo.build_combobox(self.overlay,ui,14) - #self.change_encrypt_method() + self.change_encrypt_method() #self._w.body.body.append(self.pile_encrypt) keys = True diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 212a178..279aa32 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -56,7 +56,7 @@ from time import sleep from curses_misc import SelText,ComboBox,TextDialog,InputDialog from prefs_curses import PrefsDialog import netentry_curses -from netentry_curses import WirelessSettingsDialog, error +from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog,error language = misc.get_language_list_gui() @@ -181,10 +181,10 @@ def gen_network_list(): id = 0 wiredL = [] - is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None + #is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None # This one makes a list of strings to put in a combo box. - for profile in wired.GetWiredProfileList(): - theString = '%4s %25s' % (id, profile) + #for profile in wired.GetWiredProfileList(): + #theString = '%4s %25s' % (id, profile) #### THIS IS wired.blah() in experimental #print config.GetLastUsedWiredNetwork() # Tag if no wireless IP present, and wired one is @@ -195,9 +195,9 @@ def gen_network_list(): # 'connected focus')) #else: #wiredL.append(urwid.AttrWrap(SelText(theString),'body','focus')) - wiredL.append(theString) - id+=1 - + #wiredL.append(theString) + #id+=1 + wiredL = wired.GetWiredProfileList() wlessL = [] # This one makes a list of NetLabels for network_id in range(0, wireless.GetNumberOfNetworks()): @@ -298,10 +298,16 @@ class WiredComboBox(ComboBox): """ list : the list of wired network profiles. The rest is self-explanitory. """ - def init(self,list): + def __init__(self,list): + self.ADD_PROFILE = '---Add a new profile---' + self.__super.__init__(use_enter=False) + self.set_list(list) + #self.set_focus(self.theList.index(wired.GetDefaultProfile())) + + def set_list(self,list): self.theList = list - id = 0 - wiredL = [] + id=0 + wiredL=[] is_active = wireless.GetWirelessIP('') == None and wired.GetWiredIP('') != None for profile in list: theString = '%4s %25s' % (id, profile) @@ -317,11 +323,37 @@ class WiredComboBox(ComboBox): # wiredL.append(urwid.AttrWrap(SelText(theString),'body','focus')) wiredL.append(theString) id+=1 - self.__super.__init__(list=wiredL,use_enter=False) - self.set_focus(theList.index(wired.GetDefaultWiredProfile())) + wiredL.append(self.ADD_PROFILE) + if is_active: + self.attrs = ('connected','editnfc') + self.focus_attr = 'connected focus' + else : + self.attrs = ('body','editnfc') + self.focus_attr = 'focus' + self.list = wiredL + if self.theList != []: + wired.ReadWiredNetworkProfile(self.get_selected_profile()) def keypress(self,size,key): - self.__super.keypress(size,key) + prev_focus = self.get_focus()[1] + key = self.__super.keypress(size,key) + if self.get_focus()[1] == len(self.list)-1: + dialog = InputDialog(('header',"Add new wired profile"),7,30) + + exitcode,name = dialog.run(ui,self.body) + if exitcode == 0: + wired.CreateWiredNetworkProfile(name,False) + self.set_list(wired.GetWiredProfileList()) + self.rebuild_combobox() + self.set_focus(prev_focus) + self.overlay._listbox.set_focus(prev_focus) + else: + wired.ReadWiredNetworkProfile(self.get_selected_profile()) + if key == 'delete': + wired.DeleteWiredNetworkProfile(self.get_selected_profile()) + self.set_list(wired.GetWiredProfileList()) + self.rebuild_combobox() + return key #if key == 'C': # Configure the network # pass @@ -332,11 +364,9 @@ class WiredComboBox(ComboBox): # self.connect() #return key - def connect(self): - wired.ConnectWired() def get_selected_profile(self): """Get the selected wired profile""" - return self.theList[self._w.get_selected()[1]] + return self.theList[self.get_focus()[1]] ######################################## ##### APPLICATION INTERFACE CLASS @@ -370,7 +400,7 @@ class appGUI(): wiredL,wlessL = [],[]# = gen_network_list() self.frame = None - self.wiredCB = urwid.Filler(ComboBox(list=wiredL,use_enter=False)) + self.wiredCB = urwid.Filler(WiredComboBox(wiredL)) self.wlessLB = urwid.ListBox(wlessL) self.update_netlist(force_check=True,firstrun=True) @@ -411,11 +441,12 @@ class appGUI(): def lock_screen(self): self.frame.set_body(self.screen_locker) self.screen_locked = True + self.update_ui() def unlock_screen(self): + self.update_netlist(force_check=True) self.frame.set_body(self.thePile) self.screen_locked = False - self.update_netlist(force_check=True) self.update_ui() def raise_hidden_network_dialog(self): @@ -436,12 +467,12 @@ class appGUI(): if self.thePile.get_focus() == self.wiredCB: wlessorwired = self.WIRED_IDX where = self.thePile.get_focus().get_body().get_focus()[1] - else:#self.thePile.get_focus() == self.wlessLB : + else: #self.thePile.get_focus() == self.wlessLB : wlessorwired = self.WLESS_IDX if self.wlessLB == self.no_wlan: where = None else: - where = self.frame.get_body().get_focus().get_focus()[1] + where = self.thePile.get_focus().get_focus()[1] #where = self.wlessLB.get_focus()[1] self.focusloc = (wlessorwired,where) # Be clunky until I get to a later stage of development. @@ -498,6 +529,9 @@ class appGUI(): self.prev_state = state if not firstrun: self.update_ui() + if firstrun: + if wired.GetDefaultWiredNetwork() != None: + self.wiredCB.get_body().set_focus(wired.GetWiredProfileList().index(wired.GetDefaultWiredNetwork())) # Update the footer/status bar @wrap_exceptions() @@ -591,16 +625,11 @@ class appGUI(): #if not self.connecting: # gobject.idle_add(self.refresh_networks, None, False, None) self.unlock_screen() - # I'm hoping that this will resolve Adam's problem with the screen lock - # remaining onscreen until a key is pressed. It goes away perfectly well - # here. - self.update_ui() # Same, same, same, same, same, same #@wrap_exceptions() def dbus_scan_started(self): self.lock_screen() - self.update_ui() # Redraw the screen @wrap_exceptions() @@ -621,6 +650,7 @@ class appGUI(): loop.quit() return False if "f5" in keys: + self.lock_screen() wireless.Scan() if "D" in keys: # Disconnect from all networks. @@ -656,7 +686,8 @@ class appGUI(): if "C" in keys: focus = self.thePile.get_focus() if focus == self.wiredCB: - pass + WiredSettingsDialog(self.wiredCB.get_body(). + get_selected_profile()).run(ui,self.size,self.frame) else: # wireless list only other option wid,pos = self.thePile.get_focus().get_focus() @@ -677,18 +708,6 @@ class appGUI(): self.size = ui.get_cols_rows() continue self.frame.keypress( self.size, k ) - - if " " in keys: - focus = self.thePile.get_focus() - if focus == self.wiredCB: - #self.set_status('space pressed on wiredCB!') - wid,pos = self.wiredCB.get_body().get_focus() - text,attr = wid.get_text() - wired.ReadWiredNetworkProfile(text) - # Make sure our internal reference to the combobox matches the - # one found in the pile. - #self.wiredCB = self.thePile.get_focus() - return True # TODO: Update this to use the networkentry stuff def connect(self, nettype, networkid, networkentry=None): diff --git a/in/man=wicd-curses.8.in b/in/man=wicd-curses.8.in index 090b042..2d6a921 100644 --- a/in/man=wicd-curses.8.in +++ b/in/man=wicd-curses.8.in @@ -1,4 +1,5 @@ -.TH WICD-CURSES "8" "January 2009" "wicd-curses" +.\" First revision was r203 +.TH WICD-CURSES "8" "January 2009" "wicd-curses-r247" .SH NAME .B wicd-curses \- curses-based wicd(8) controller @@ -39,11 +40,14 @@ Bring up hidden network scanning dialog .TP .BR H Bring up a rather simplistic help dialog. Of course, it mentions this man page first. :-) -.PP -The following is a work in progress and might not be fully functional as of yet. +.\".PP +.\"The following is a work in progress and might not be fully functional as of yet. .TP .BR C Bring up network configuration controller for the selected network +.TP +.BR delete +Delete the selected wired network profile (from the wired combo box at the top) .PP The following are not implemented yet: .TP diff --git a/in/other=WHEREAREMYFILES.in b/in/other=WHEREAREMYFILES.in index 61363e9..cec81a3 100644 --- a/in/other=WHEREAREMYFILES.in +++ b/in/other=WHEREAREMYFILES.in @@ -1,8 +1,10 @@ -If you are reading this, you are probably wondering why your Wicd configuration -files are not here. What follows is a summary of the folders that wicd uses. +WHERE ARE MY FILES?! -For a more detailed (and complete) description what is in each directory, consult the -man pages for wicd(8) and wicd-curses(8). +If you are reading this, you are probably wondering why your Wicd configuration +files are not here. What follows is a summary of the folders that Wicd uses. + +For a more detailed (and complete) description what is in each directory, +consult the man pages for wicd(8) and wicd-curses(8). ~/.wicd User-dependent configuration files, only used by wicd-curses From ce64ce0aa2c98dbeffc8395766e6fd774900bdc8 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Sat, 17 Jan 2009 20:10:10 -0500 Subject: [PATCH 08/14] curses/configscript_curses.py: ADDED. Script configurator. More or less done. curses/wicd-curses.py: Added suport for the script configurator curses/README, in/man=wicd-curses.8.in: Script configurator now active setup.py: Install configscript_curses.py with the rest of the stuff --- curses/README | 2 + curses/configscript_curses.py | 139 ++++++++++++++++++++++++++++++++++ curses/curses_misc.py | 5 ++ curses/wicd-curses.py | 47 +++++++++++- in/man=wicd-curses.8.in | 4 +- setup.py | 1 + 6 files changed, 195 insertions(+), 3 deletions(-) create mode 100755 curses/configscript_curses.py diff --git a/curses/README b/curses/README index cfda201..a9cc12b 100644 --- a/curses/README +++ b/curses/README @@ -26,6 +26,8 @@ C : Display network configuration for selected network A : Display "About" dialog I : Raise the "Scan for hidden networks" dialog H : Raise help dialog +S : Configure scripts (calls an external program, requires superuser + privileges delete : Delete selected wired network profile (from the wired ComboBox) IN DIALOGS (Meta usually is "Alt"): diff --git a/curses/configscript_curses.py b/curses/configscript_curses.py new file mode 100755 index 0000000..e0c4b8e --- /dev/null +++ b/curses/configscript_curses.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python + +"""configscript_curses.py +Kind of like configscript.py, except writtwn using urwid. + +Also recycles a lot of configscript.py, too. :-) +""" + +# Copyright (C) 2009 Andrew Psaltis + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +from wicd import misc +import configscript +from configscript import write_scripts,get_script_info,get_val,none_to_blank,blank_to_none + +import urwid +import urwid.curses_display +import sys +import os + +_ = misc.get_gettext() + +language = {} +language['configure_scripts'] = _("Configure Scripts") +language['before_script'] = _("Pre-connection Script") +language['after_script'] = _("Post-connection Script") +language['disconnect_script'] = _("Disconnection Script") + +def main(argv): + global ui,frame + if len(argv) < 2: + print 'Network id to configure is missing, aborting.' + sys.exit(1) + + ui = urwid.curses_display.Screen() + ui.register_palette( [ + ('body','default','default'), + ('focus','dark magenta','light gray'), + ('editcp', 'default', 'default', 'standout'), + ('editbx', 'light gray', 'dark blue'), + ('editfc', 'white','dark blue', 'bold')] ) + + network = argv[1] + network_type = argv[2] + + script_info = get_script_info(network, network_type) + + blank = urwid.Text('') + pre_entry_t = ('body',language['before_script']+': ') + post_entry_t = ('body',language['after_script']+': ') + disconnect_entry_t = ('body',language['disconnect_script']+': ') + + global pre_entry,post_entry,disconnect_entry + pre_entry = urwid.AttrWrap(urwid.Edit(pre_entry_t, + none_to_blank(script_info.get('pre_entry'))),'editbx','editfc' ) + post_entry = urwid.AttrWrap(urwid.Edit(post_entry_t, + none_to_blank(script_info.get('post_entry'))),'editbx','editfc' ) + + disconnect_entry = urwid.AttrWrap(urwid.Edit(disconnect_entry_t, + none_to_blank(script_info.get('disconnect_entry'))),'editbx','editfc' ) + + # The buttons + ok_button = urwid.AttrWrap(urwid.Button('OK',ok_callback),'body','focus') + cancel_button = urwid.AttrWrap(urwid.Button('Cancel',cancel_callback),'body','focus') + + button_cols = urwid.Columns([ok_button,cancel_button],dividechars=1) + + lbox = urwid.Pile([('fixed',2,urwid.Filler(pre_entry)), + #('fixed',urwid.Filler(blank),1), + ('fixed',2,urwid.Filler(post_entry)), + ('fixed',2,urwid.Filler(disconnect_entry)), + #blank,blank,blank,blank,blank, + urwid.Filler(button_cols,'bottom') + ]) + frame = urwid.Frame(lbox) + result = ui.run_wrapper(run) + + if result == True: + script_info["pre_entry"] = blank_to_none(pre_entry.get_edit_text()) + script_info["post_entry"] = blank_to_none(post_entry.get_edit_text()) + script_info["disconnect_entry"] = blank_to_none(disconnect_entry.get_edit_text()) + write_scripts(network, network_type, script_info) + +OK_PRESSED = False +CANCEL_PRESSED = False +def ok_callback(button_object,user_data=None): + global OK_PRESSED + OK_PRESSED = True +def cancel_callback(button_object,user_data=None): + global CANCEL_PRESSED + CANCEL_PRESSED = True +def run(): + dim = ui.get_cols_rows() + ui.set_mouse_tracking() + + keys = True + while True: + if keys: + ui.draw_screen(dim, frame.render(dim, True)) + keys = ui.get_input() + + if "window resize" in keys: + dim = ui.get_cols_rows() + if "esc" in keys or 'Q' in keys: + return False + for k in keys: + #Send key to underlying widget: + if urwid.is_mouse_event(k): + event, button, col, row = k + frame.mouse_event( dim, + event, button, col, row, + focus=True) + else: + frame.keypress(dim, k) + # Check if buttons are pressed. + if CANCEL_PRESSED: + return False + if OK_PRESSED or 'meta enter' in keys: + return True + +if __name__ == '__main__': + if os.getuid() != 0: + print "Root privileges are required to configure scripts. Exiting." + sys.exit(0) + main(sys.argv) diff --git a/curses/curses_misc.py b/curses/curses_misc.py index 9cd0346..97b0eae 100644 --- a/curses/curses_misc.py +++ b/curses/curses_misc.py @@ -483,3 +483,8 @@ class InputDialog(Dialog2): def on_exit(self, exitcode): return exitcode, self.edit.get_edit_text() + +# Pile that has an edit and a label saying that the file at the path specified +# does not exist +#class FileGuessEdit(urwid.WidgetWrap): +# def __init__(self,caption='', diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 279aa32..12427ee 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -45,7 +45,8 @@ from dbus import version as dbus_version import gobject # Other important wicd-related stuff -import wicd.misc as misc +from wicd import wpath +from wicd import misc from wicd import dbusmanager # Internal Python stuff @@ -58,6 +59,10 @@ from prefs_curses import PrefsDialog import netentry_curses from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog,error +# Stuff about getting the script configurer running +from grp import getgrgid +from os import getgroups,system + language = misc.get_language_list_gui() ######################################## @@ -245,6 +250,36 @@ def help_dialog(body): help = TextDialog(theText,15,62,header=('header',"Wicd-Curses Help")) help.run(ui,body) +def run_configscript(netname,nettype): + loop.quit() + ui.stop() + argv = netname + ' ' +nettype + + #cmd = '/usr/lib/configscript_curses.py '+argv + cmd = wpath.lib+'configscript_curses.py '+argv + # Check whether we can sudo. Hopefully this is complete + glist = [] + for i in getgroups(): + glist.append(getgrgid(i)[0]) + if 'root' in glist: + precmd = '' + precmdargv = '' + postcmd = '' + elif 'admin' in glist or 'wheel' in glist: + precmd = 'sudo' + precmdargv = '' + postcmd = '' + else: + precmd = 'su' + precmdargv = ' -c "' + postcmd = '"' + print "Calling command: " + precmd + precmdargv + cmd + postcmd + sys.stdout.flush() + system(precmd+precmdargv+cmd+postcmd) + raw_input("Press enter!") + main() + + ######################################## ##### URWID SUPPORT CLASSES ######################################## @@ -698,6 +733,16 @@ class appGUI(): self.raise_hidden_network_dialog() if "H" in keys: help_dialog(self.frame) + if "S" in keys: + focus = self.thePile.get_focus() + if focus == self.wiredCB: + nettype = 'wired' + netname = self.wiredCB.get_body().get_selected_profile() + else: + nettype = 'wireless' + netname = str(self.wiredLB.get_focus()[1]) + run_configscript(netname,nettype) + for k in keys: if urwid.is_mouse_event(k): event, button, col, row = k diff --git a/in/man=wicd-curses.8.in b/in/man=wicd-curses.8.in index 2d6a921..67bacb2 100644 --- a/in/man=wicd-curses.8.in +++ b/in/man=wicd-curses.8.in @@ -48,8 +48,8 @@ Bring up network configuration controller for the selected network .TP .BR delete Delete the selected wired network profile (from the wired combo box at the top) -.PP -The following are not implemented yet: +.\".PP +.\"The following are not implemented yet: .TP .BR S Bring up the script selector for the selected network (requires superuser privileges) diff --git a/setup.py b/setup.py index 31d21bb..49fb036 100755 --- a/setup.py +++ b/setup.py @@ -409,6 +409,7 @@ try: data.append(( wpath.lib, ['curses/prefs_curses.py'])) data.append(( wpath.lib, ['curses/wicd-curses.py'])) data.append(( wpath.lib, ['curses/netentry_curses.py'])) + data.append(( wpath.lib, ['curses/configscript_curses.py'])) data.append(( wpath.bin, ['scripts/wicd-curses'])) if not wpath.no_install_man: data.append(( wpath.mandir + 'man8/', ['man/wicd-curses.8'])) From ea4ab09984de3ad220dc1e80bc15b97a3ac475fb Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Mon, 19 Jan 2009 01:06:57 -0500 Subject: [PATCH 09/14] Fix ttls template Add a guiutils module for gui-related functions/classes that are used in multiple modules. Replace os.access with os.path.exists Make the static gateway entry optional. Don't auto-connect/reconnect when the gui is open. Fix bug that would keep the gui from working if the wired network entry was displayed. --- encryption/templates/ttls | 4 +- setup.py | 27 +++++----- wicd/configmanager.py | 3 +- wicd/dbusmanager.py | 1 + wicd/gui.py | 107 ++++++-------------------------------- wicd/misc.py | 4 +- wicd/monitor.py | 20 +++---- wicd/netentry.py | 79 +--------------------------- wicd/networking.py | 5 +- wicd/prefs.py | 8 --- wicd/wicd-client.py | 21 +++++--- wicd/wicd-daemon.py | 7 ++- wicd/wnettools.py | 9 ++-- 13 files changed, 78 insertions(+), 217 deletions(-) diff --git a/encryption/templates/ttls b/encryption/templates/ttls index 65db422..002a92b 100644 --- a/encryption/templates/ttls +++ b/encryption/templates/ttls @@ -1,7 +1,7 @@ name = TTLS with WEP author = Adam Blackburn version = 1 -require anonymous_identity *Anonymous_Identity identity *Identity password *Password auth *Authentication +require identity *Identity password *Password auth *Authentication ----- ctrl_interface=/var/run/wpa_supplicant network={ @@ -9,7 +9,7 @@ network={ scan_ssid=$_SCAN eap=TTLS key_mgmt=IEEE8021X - identity="$_USERNAME" + identity="$_IDENTITY" password="$_PASSWORD" phase2="auth=$_AUTH" } diff --git a/setup.py b/setup.py index 65ee989..3235238 100755 --- a/setup.py +++ b/setup.py @@ -123,32 +123,32 @@ class configure(Command): self.distro_detect_failed = False self.initfile = 'init/default/wicd' - if os.access('/etc/redhat-release', os.F_OK): + if os.path.exists('/etc/redhat-release'): self.init = '/etc/rc.d/init.d/' self.initfile = 'init/redhat/wicd' - elif os.access('/etc/SuSE-release', os.F_OK): + elif os.path.exists('/etc/SuSE-release'): self.init = '/etc/init.d/' self.initfile = 'init/suse/wicd' - elif os.access('/etc/fedora-release', os.F_OK): + elif os.path.exists('/etc/fedora-release'): self.init = '/etc/rc.d/init.d/' self.initfile = 'init/redhat/wicd' - elif os.access('/etc/gentoo-release', os.F_OK): + elif os.path.exists('/etc/gentoo-release'): self.init = '/etc/init.d/' self.initfile = 'init/gentoo/wicd' - elif os.access('/etc/debian_version', os.F_OK): + elif os.path.exists('/etc/debian_version'): self.init = '/etc/init.d/' self.initfile = 'init/debian/wicd' - elif os.access('/etc/arch-release', os.F_OK): + elif os.path.exists('/etc/arch-release'): self.init = '/etc/rc.d/' self.initfile = 'init/arch/wicd' - elif os.access('/etc/slackware-version', os.F_OK) or \ - os.access('/etc/slamd64-version', os.F_OK): + elif os.path.exists('/etc/slackware-version') or \ + os.path.exists('/etc/slamd64-version'): self.init = '/etc/rc.d/' self.initfile = 'init/slackware/rc.wicd' self.docdir = '/usr/doc/wicd-%s' % VERSION_NUM self.mandir = '/usr/man/' self.no_install_acpi = True - elif os.access('/etc/pld-release', os.F_OK): + elif os.path.exists('/etc/pld-release'): self.init = '/etc/rc.d/init.d/' self.initfile = 'init/pld/wicd' else: @@ -174,7 +174,7 @@ class configure(Command): if len(pmutils_candidate) == 0 or returncode != 0 or not os.path.isabs(pmutils_candidate): raise ValueError else: - self.pmutils = pmutils_candidate + self.pmutils = pmutils_candidate except (OSError, ValueError): pass # use our default @@ -185,7 +185,7 @@ class configure(Command): if len(kdedir_candidate) == 0 or returncode != 0 or not os.path.isabs(kdedir_candidate): raise ValueError else: - self.kdedir = kdedir_candidate + '/share/autostart' + self.kdedir = kdedir_candidate + '/share/autostart' except (OSError, ValueError): # If kde-config isn't present or returns an error, then we can # assume that kde isn't installed on the user's system @@ -454,7 +454,10 @@ connect at startup to any preferred network within range. url="http://wicd.net", license="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html", ## scripts=['configscript.py', 'autoconnect.py', 'gui.py', 'wicd.py', 'daemon.py', 'suspend.py', 'monitor.py'], - py_modules=['wicd.networking', 'wicd.misc', 'wicd.gui', 'wicd.wnettools', 'wicd.wpath', 'wicd.prefs', 'wicd.netentry', 'wicd.dbusmanager', 'wicd.logfile', 'wicd.backend', 'wicd.configmanager'], ext_modules=[iwscan_ext, wpactrl_ext], + py_modules=['wicd.networking', 'wicd.misc', 'wicd.gui', 'wicd.wnettools', 'wicd.wpath', + 'wicd.prefs', 'wicd.netentry', 'wicd.dbusmanager', 'wicd.logfile', 'wicd.backend', + 'wicd.configmanager', 'wicd.guiutil'], + ext_modules=[iwscan_ext, wpactrl_ext], data_files=data ) ##print "Running post-install configuration..." diff --git a/wicd/configmanager.py b/wicd/configmanager.py index c95b911..b636678 100644 --- a/wicd/configmanager.py +++ b/wicd/configmanager.py @@ -87,8 +87,7 @@ class ConfigManager(RawConfigParser): str(ret)]) else: if default != "__None__": - if self.debug: - print 'did not find %s in configuration, setting default %s' % (option, str(default)) + print 'did not find %s in configuration, setting default %s' % (option, str(default)) self.set(section, option, str(default), save=True) ret = default else: diff --git a/wicd/dbusmanager.py b/wicd/dbusmanager.py index 0063f64..0c25b6c 100644 --- a/wicd/dbusmanager.py +++ b/wicd/dbusmanager.py @@ -24,6 +24,7 @@ A module for managing wicd's dbus interfaces. # import dbus +from dbus import DBusException if getattr(dbus, "version", (0, 0, 0)) < (0, 80, 0): import dbus.glib else: diff --git a/wicd/gui.py b/wicd/gui.py index b1a3065..b630d15 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -40,6 +40,7 @@ from wicd import dbusmanager from wicd.misc import noneToString from wicd.netentry import WiredNetworkEntry, WirelessNetworkEntry from wicd.prefs import PreferencesDialog +from wicd.guiutil import error, GreyLabel, LabelEntry, SmallLabel if __name__ == '__main__': wpath.chdir(__file__) @@ -87,92 +88,6 @@ def handle_no_dbus(from_tray=False): error(None, language['lost_dbus'], block=False) return False -def error(parent, message, block=True): - """ Shows an error dialog """ - def delete_event(dialog, id): - dialog.destroy() - dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, - gtk.BUTTONS_OK) - dialog.set_markup(message) - if not block: - dialog.present() - dialog.connect("response", delete_event) - else: - dialog.run() - dialog.destroy() - -def alert(parent, message): - """ Shows an warning dialog """ - dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, - gtk.BUTTONS_OK) - dialog.set_markup(message) - dialog.present() - dialog.connect("response", lambda *args: dialog.destroy()) - -def dummy(x=None):pass - -######################################## -##### GTK EXTENSION CLASSES -######################################## - -class SmallLabel(gtk.Label): - def __init__(self, text=''): - gtk.Label.__init__(self, text) - self.set_size_request(50, -1) - -class LabelEntry(gtk.HBox): - """ A label on the left with a textbox on the right. """ - def __init__(self,text): - gtk.HBox.__init__(self) - self.entry = gtk.Entry() - self.entry.set_size_request(200, -1) - self.label = SmallLabel() - self.label.set_text(text) - self.label.set_size_request(170, -1) - self.pack_start(self.label, fill=False, expand=False) - self.pack_start(self.entry, fill=False, expand=False) - self.label.show() - self.entry.show() - self.entry.connect('focus-out-event', self.hide_characters) - self.entry.connect('focus-in-event', self.show_characters) - self.auto_hide_text = False - self.show() - - def set_text(self, text): - # For compatibility... - self.entry.set_text(text) - - def get_text(self): - return self.entry.get_text() - - def set_auto_hidden(self, value): - self.entry.set_visibility(False) - self.auto_hide_text = value - - def show_characters(self, widget=None, event=None): - # When the box has focus, show the characters - if self.auto_hide_text and widget: - self.entry.set_visibility(True) - - def set_sensitive(self, value): - self.entry.set_sensitive(value) - self.label.set_sensitive(value) - - def hide_characters(self, widget=None, event=None): - # When the box looses focus, hide them - if self.auto_hide_text and widget: - self.entry.set_visibility(False) - - -class GreyLabel(gtk.Label): - """ Creates a grey gtk.Label. """ - def __init__(self): - gtk.Label.__init__(self) - - def set_label(self, text): - self.set_markup("" + text + "") - self.set_alignment(0, 0) - class WiredProfileChooser: """ Class for displaying the wired profile chooser. """ @@ -291,6 +206,7 @@ class appGui(object): self.wait_for_events(0.2) self.window.connect('delete_event', self.exit) self.window.connect('key-release-event', self.key_event) + daemon.SetGUIOpen(True) bus.add_signal_receiver(self.dbus_scan_finished, 'SendEndScanSignal', 'org.wicd.daemon.wireless') bus.add_signal_receiver(self.dbus_scan_started, 'SendStartScanSignal', @@ -649,21 +565,30 @@ class appGui(object): # First make sure all the Addresses entered are valid. if entry.chkbox_static_ip.get_active(): - entlist = [ent for ent in [entry.txt_ip, entry.txt_netmask, - entry.txt_gateway]] + req_entlist = [entry.txt_ip, enty.txt_netmask] + opt_entlist = [entry.txt_gateway] if entry.chkbox_static_dns.get_active() and \ not entry.chkbox_global_dns.get_active(): - entlist.append(entry.txt_dns_1) + req_entlist.append(entry.txt_dns_1) # Only append additional dns entries if they're entered. for ent in [entry.txt_dns_2, entry.txt_dns_3]: if ent.get_text() != "": - entlist.append(ent) - for lblent in entlist: + opt_entlist.append(ent) + + # Required entries. + for lblent in req_entlist: if not misc.IsValidIP(lblent.get_text()): error(self.window, language['invalid_address']. replace('$A', lblent.label.get_label())) return False + + # Optional entries, only check for validity if they're entered. + for lblent in opt_entlist: + if lblent.get_text() and not misc.IsValidIP(lblent.get_text()): + error(self.window, language['invalid_address']. + replace('$A', lblent.label.get_label())) + return False # Now save the settings. if nettype == "wireless": diff --git a/wicd/misc.py b/wicd/misc.py index 5f7f928..30b473a 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -399,7 +399,7 @@ def choose_sudo_prog(): for p in env_path: paths.extend([p + '/gksudo', p + "/gksu", p + '/ktsuss']) for path in paths: - if os.access(path, os.F_OK): + if os.path.exists(path): return path return None @@ -414,7 +414,7 @@ def find_path(cmd): """ paths = os.getenv("PATH", default="/usr/bin:/usr/local/bin").split(':') for path in paths: - if os.access(os.path.join(path, cmd), os.F_OK): + if os.path.exists(os.path.join(path, cmd)): return os.path.join(path, cmd) return None diff --git a/wicd/monitor.py b/wicd/monitor.py index 0256932..47fe3b5 100755 --- a/wicd/monitor.py +++ b/wicd/monitor.py @@ -268,16 +268,16 @@ class ConnectionStatus(object): error_handler=err_handle) self.reconnecting = False - def rescan_networks(self): - """ Calls a wireless scan. """ - try: - if daemon.GetSuspend() or daemon.CheckIfConnecting(): - return True - wireless.Scan() - except dbus.exceptions.DBusException, e: - print 'dbus exception while attempting rescan: %s' % str(e) - finally: - return True + #def rescan_networks(self): + # """ Calls a wireless scan. """ + # try: + # if daemon.GetSuspend() or daemon.CheckIfConnecting(): + # return True + # wireless.Scan() + # except dbus.exceptions.DBusException, e: + # print 'dbus exception while attempting rescan: %s' % str(e) + # finally: + # return True def reply_handle(): """ Just a dummy function needed for asynchronous dbus calls. """ diff --git a/wicd/netentry.py b/wicd/netentry.py index e000e93..4474b99 100644 --- a/wicd/netentry.py +++ b/wicd/netentry.py @@ -19,8 +19,9 @@ import gtk import os import misc -from misc import noneToString, stringToNone, noneToBlankString, to_bool import wpath +from misc import noneToString, stringToNone, noneToBlankString, to_bool +from guiutil import error, SmallLabel, LabelEntry, GreyLabel, LeftAlignedLabel language = misc.get_language_list_gui() @@ -28,78 +29,6 @@ language = misc.get_language_list_gui() daemon = None wired = None wireless = None - -def error(parent, message): - """ Shows an error dialog """ - dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, - gtk.BUTTONS_OK) - dialog.set_markup(message) - dialog.run() - dialog.destroy() - -class SmallLabel(gtk.Label): - def __init__(self, text=''): - gtk.Label.__init__(self, text) - self.set_size_request(50, -1) - -class LeftAlignedLabel(gtk.Label): - def __init__(self, label=None): - gtk.Label.__init__(self, label) - self.set_alignment(0.0, 0.5) - -class LabelEntry(gtk.HBox): - """ A label on the left with a textbox on the right. """ - def __init__(self, text): - gtk.HBox.__init__(self) - self.entry = gtk.Entry() - self.entry.set_size_request(200, -1) - self.label = SmallLabel() - self.label.set_text(text) - self.label.set_size_request(170, -1) - self.pack_start(self.label, fill=False, expand=False) - self.pack_start(self.entry, fill=False, expand=False) - self.label.show() - self.entry.show() - self.entry.connect('focus-out-event', self.hide_characters) - self.entry.connect('focus-in-event', self.show_characters) - self.auto_hide_text = False - self.show() - - def set_text(self, text): - # For compatibility... - self.entry.set_text(text) - - def get_text(self): - return self.entry.get_text() - - def set_auto_hidden(self, value): - self.entry.set_visibility(False) - self.auto_hide_text = value - - def show_characters(self, widget=None, event=None): - # When the box has focus, show the characters - if self.auto_hide_text and widget: - self.entry.set_visibility(True) - - def set_sensitive(self, value): - self.entry.set_sensitive(value) - self.label.set_sensitive(value) - - def hide_characters(self, widget=None, event=None): - # When the box looses focus, hide them - if self.auto_hide_text and widget: - self.entry.set_visibility(False) - - -class GreyLabel(gtk.Label): - """ Creates a grey gtk.Label. """ - def __init__(self): - gtk.Label.__init__(self) - - def set_label(self, text): - self.set_markup("" + text + "") - self.set_alignment(0, 0) - class AdvancedSettingsDialog(gtk.Dialog): def __init__(self): @@ -651,7 +580,6 @@ class WiredNetworkEntry(NetworkEntry): self.chkbox_default_profile.connect("toggled", self.toggle_default_profile) self.combo_profile_names.connect("changed", self.change_profile) - self.script_button.connect("button-press-event", self.edit_scripts) # Toggle the default profile checkbox to the correct state. if to_bool(wired.GetWiredProperty("default")): @@ -701,7 +629,6 @@ class WiredNetworkEntry(NetworkEntry): self.button_delete.set_sensitive(False) self.connect_button.set_sensitive(False) self.advanced_button.set_sensitive(False) - self.script_button.set_sensitive(False) def update_connect_button(self, state, apbssid=None): """ Update the connection/disconnect button for this entry. """ @@ -730,7 +657,6 @@ class WiredNetworkEntry(NetworkEntry): self.button_delete.set_sensitive(True) self.connect_button.set_sensitive(True) self.advanced_button.set_sensitive(True) - self.script_button.set_sensitive(True) def remove_profile(self, widget): """ Remove a profile from the profile list. """ @@ -748,7 +674,6 @@ class WiredNetworkEntry(NetworkEntry): if self.is_full_gui: self.button_delete.set_sensitive(False) self.advanced_button.set_sensitive(False) - self.script_button.set_sensitive(False) self.connect_button.set_sensitive(False) else: self.profile_help.hide() diff --git a/wicd/networking.py b/wicd/networking.py index a0a8d58..dcecce8 100644 --- a/wicd/networking.py +++ b/wicd/networking.py @@ -393,8 +393,9 @@ class ConnectThread(threading.Thread): self.SetStatus('setting_static_ip') print 'Setting static IP : ' + self.network['ip'] iface.SetAddress(self.network['ip'], self.network['netmask']) - print 'Setting default gateway : ' + self.network['gateway'] - iface.SetDefaultRoute(self.network['gateway']) + if self.network.get('gateway'): + print 'Setting default gateway : ' + self.network['gateway'] + iface.SetDefaultRoute(self.network['gateway']) else: # Run dhcp... self.SetStatus('running_dhcp') diff --git a/wicd/prefs.py b/wicd/prefs.py index 29f5c12..b5779fb 100644 --- a/wicd/prefs.py +++ b/wicd/prefs.py @@ -40,14 +40,6 @@ wired = None language = misc.get_language_list_gui() -def alert(parent, message): - """ Shows an alert dialog """ - dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, - gtk.BUTTONS_OK) - dialog.set_markup(message) - dialog.run() - dialog.destroy() - class PreferencesDialog(object): """ Class for handling the wicd preferences dialog window. """ def __init__(self, wTree, dbus): diff --git a/wicd/wicd-client.py b/wicd/wicd-client.py index a74429a..b751965 100755 --- a/wicd/wicd-client.py +++ b/wicd/wicd-client.py @@ -43,13 +43,14 @@ import getopt import os import pango import time -from dbus import DBusException +import atexit # Wicd specific imports from wicd import wpath from wicd import misc from wicd import gui from wicd import dbusmanager +from wicd.guiutil import error ICON_AVAIL = True USE_EGG = False @@ -364,7 +365,7 @@ class TrayIcon(object): if DBUS_AVAIL: self.toggle_wicd_gui() else: - # gui.error(None, language["daemon_unavailable"]) + # error(None, language["daemon_unavailable"]) pass def on_quit(self, widget=None): @@ -652,8 +653,8 @@ def setup_dbus(force=True): misc.PromptToStartDaemon() try: dbusmanager.connect_to_dbus() - except DBusException: - gui.error(None, "Could not connect to wicd's D-Bus interface. " + + except dbusmanager.DBusException: + error(None, "Could not connect to wicd's D-Bus interface. " + "Check the wicd log for error messages.") return False else: @@ -669,12 +670,19 @@ def setup_dbus(force=True): return True +def on_exit(): + if DBUS_AVAIL: + try: + daemon.SetGUIOpen(False) + except dbusmanager.DBusException: + pass + def handle_no_dbus(): global DBUS_AVAIL DBUS_AVAIL = False gui.handle_no_dbus(from_tray=True) print "Wicd daemon is shutting down!" - gui.error(None, language['lost_dbus'], block=False) + error(None, language['lost_dbus'], block=False) return False def main(argv): @@ -709,7 +717,8 @@ def main(argv): print 'Loading...' setup_dbus() - + atexit.register(on_exit) + if not use_tray or not ICON_AVAIL: the_gui = gui.appGui(standalone=True) mainloop = gobject.MainLoop() diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index b12e0e4..8087c87 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -320,6 +320,10 @@ class WicdDaemon(dbus.service.Object): fails it tries a wireless connection. """ + # We don't want to rescan/connect if the gui is open. + if self.gui_open: + return + if fresh: self.wireless_bus.Scan() if self.wired_bus.CheckPluggedIn(): @@ -401,7 +405,8 @@ class WicdDaemon(dbus.service.Object): def ShouldAutoReconnect(self): """ Returns True if it's the right time to try autoreconnecting. """ if self.GetAutoReconnect() and not self.CheckIfConnecting() and \ - not self.GetForcedDisconnect() and not self.auto_connecting: + not self.GetForcedDisconnect() and not self.auto_connecting and \ + not self.gui_open: return True else: return False diff --git a/wicd/wnettools.py b/wicd/wnettools.py index 1df4398..0cea30e 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -33,6 +33,7 @@ class WirelessInterface() -- Control a wireless network interface. import os import re +import random from string import maketrans, translate, punctuation import wpath @@ -138,8 +139,8 @@ def NeedsExternalCalls(): def IsValidWpaSuppDriver(driver): """ Returns True if given string is a valid wpa_supplicant driver. """ - output = misc.Run(["wpa_supplicant", "-D%s" % driver, "-iwlan9", - "-c/etc/zzzzzzzz.confzzz"]) + output = misc.Run(["wpa_supplicant", "-D%s" % driver, "-iolan19", + "-c/etc/abcd%sdefzz.zconfz" % random.randint(1, 1000)]) if re.match("Unsupported driver", output): return False else: @@ -195,7 +196,7 @@ class BaseInterface(object): paths = ['/sbin/', '/usr/sbin/', '/bin/', '/usr/bin/', '/usr/local/sbin/', '/usr/local/bin/'] for path in paths: - if os.access("%s%s" % (path, client), os.F_OK): + if os.path.exists("%s%s" % (path, client)): return "%s%s" % (path, client) if self.verbose: print "WARNING: No path found for %s" % (client) @@ -416,7 +417,7 @@ class BaseInterface(object): pipe -- stdout pipe to the dhcpcd process. Returns: - 'success' if succesful', an error code string otherwise. + 'success' if succesful, an error code string otherwise. """ dhcpcd_complete = False From 87539f75e7fa8cc050fd739b9afa712591d9a999 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Mon, 19 Jan 2009 23:37:35 -0500 Subject: [PATCH 10/14] Fix bug that was keeping DHCP release from working. --- wicd/wnettools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wicd/wnettools.py b/wicd/wnettools.py index 0cea30e..0a4235f 100644 --- a/wicd/wnettools.py +++ b/wicd/wnettools.py @@ -476,7 +476,8 @@ class BaseInterface(object): def ReleaseDHCP(self): """ Release the DHCP lease for this interface. """ if not self.iface: return False - cmd = self.DHCP_RELEASE + " " + self.iface + " 2>/dev/null" + cmd = self.DHCP_RELEASE + " " + self.iface + if self.verbose: print cmd misc.Run(cmd) def FlushRoutes(self): From 1269bcd0483a10c0dd5c31d428b445c950153a78 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Mon, 19 Jan 2009 23:45:05 -0500 Subject: [PATCH 11/14] Fix a few typos in the option gateway code. --- wicd/gui.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wicd/gui.py b/wicd/gui.py index b630d15..b0a2687 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -561,11 +561,12 @@ class appGui(object): def save_settings(self, nettype, networkid, networkentry): """ Verifies and saves the settings for the network entry. """ entry = networkentry.advanced_dialog - entlist = [] + opt_entlist = [] + req_entlist = [] # First make sure all the Addresses entered are valid. if entry.chkbox_static_ip.get_active(): - req_entlist = [entry.txt_ip, enty.txt_netmask] + req_entlist = [entry.txt_ip, entry.txt_netmask] opt_entlist = [entry.txt_gateway] if entry.chkbox_static_dns.get_active() and \ From f6d7579859833d69f682bb1a62c07a780fb4ebd5 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Tue, 20 Jan 2009 00:32:56 -0500 Subject: [PATCH 12/14] Add support for writing config data with whitespace kept intact. Propgate debug setting to the ConfigManager instances. Don't write essid key sections to the config file if we're not actually using them. --- wicd/configmanager.py | 14 ++++++++++++-- wicd/wicd-daemon.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/wicd/configmanager.py b/wicd/configmanager.py index b636678..29d4320 100644 --- a/wicd/configmanager.py +++ b/wicd/configmanager.py @@ -31,10 +31,11 @@ from wicd.misc import stringToNone, Noneify, to_unicode class ConfigManager(RawConfigParser): """ A class that can be used to manage a given configuration file. """ - def __init__(self, path, debug=False): + def __init__(self, path, debug=False, mark_whitespace="`'`"): RawConfigParser.__init__(self) self.config_file = path self.debug = debug + self.mrk_ws = mark_whitespace self.read(path) def __repr__(self): @@ -60,6 +61,9 @@ class ConfigManager(RawConfigParser): self.add_section(section) if isinstance(value, basestring): value = to_unicode(value) + if value.startswith(' ') or value.endswith(' '): + value = "%(ws)s%(value)s%(ws)s" % {"value" : value, + "ws" : self.mrk_ws} RawConfigParser.set(self, section, str(option), value) if save: self.write() @@ -77,10 +81,16 @@ class ConfigManager(RawConfigParser): """ if not self.has_section(section): - self.add_section(section) + if default != "__None__": + self.add_section(section) + else: + return None if self.has_option(section, option): ret = RawConfigParser.get(self, section, option) + if (isinstance(ret, basestring) and ret.startswith(self.mrk_ws) + and ret.endswith(self.mrk_ws)): + ret = ret[3:-3] if default: if self.debug: print ''.join(['found ', option, ' in configuration ', diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index 8087c87..8fb98bb 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -91,7 +91,7 @@ class WicdDaemon(dbus.service.Object): self.vpn_session = None self.gui_open = False self.suspended = False - self.debug_mode = False + self._debug_mode = False self.connection_state = misc.NOT_CONNECTED self.connection_info = [""] self.auto_connecting = False @@ -123,6 +123,13 @@ class WicdDaemon(dbus.service.Object): self.SetForcedDisconnect(True) print "--no-autoconnect detected, not autoconnecting..." + def get_debug_mode(self): + return self._debug_mode + def set_debug_mode(self, mode): + self._debug_mode = mode + self.config.debug = mode + debug_mode = property(get_debug_mode, set_debug_mode) + @dbus.service.method('org.wicd.daemon') def Hello(self): """ Returns the version number. @@ -874,10 +881,18 @@ class WirelessDaemon(dbus.service.Object): self.hidden_essid = None self.daemon = daemon self.wifi = wifi - self.debug_mode = debug + self._debug_mode = debug self.forced_disconnect = False self.config = ConfigManager(os.path.join(wpath.etc, - "wireless-settings.conf")) + "wireless-settings.conf"), + debug=debug) + + def get_debug_mode(self): + return self._debug_mode + def set_debug_mode(self, mode): + self._debug_mode = mode + self.config.debug = mode + debug_mode = property(get_debug_mode, set_debug_mode) @dbus.service.method('org.wicd.daemon.wireless') def SetHiddenNetworkESSID(self, essid): @@ -1223,11 +1238,19 @@ class WiredDaemon(dbus.service.Object): object_path="/org/wicd/daemon/wired") self.daemon = daemon self.wired = wired - self.debug_mode = debug + self._debug_mode = debug self.forced_disconnect = False self.WiredNetwork = {} self.config = ConfigManager(os.path.join(wpath.etc, - "wired-settings.conf")) + "wired-settings.conf"), + debug=debug) + + def get_debug_mode(self): + return self._debug_mode + def set_debug_mode(self, mode): + self._debug_mode = mode + self.config.debug = mode + debug_mode = property(get_debug_mode, set_debug_mode) @dbus.service.method('org.wicd.daemon.wired') def GetWiredIP(self, ifconfig=""): From a25693d1abd7b4478f3ad483e83efaabeb4f9894 Mon Sep 17 00:00:00 2001 From: Andrew Psaltis Date: Tue, 20 Jan 2009 23:41:44 -0500 Subject: [PATCH 13/14] curses/curses_misc.py: Added support for setting the text in the input dialog Changed "body" to "parent" in ComboBox. set_focus() unconditionally sets the focus now Moved error() to this file. It fits better here, anyway. Reverted TextDialog to its previous state curses/netentry_curses.py: Moved error() to curses_misc.py curses/wicd-curses.py: "Deimplemented" the script configurator, at the suggestion of various folks #wicd, and replaced it with a simple instructions dialog. My original code is still there, just commented out. Added support for renaming wired network profiles (F2 when over the combo box) Fixed various issues caused when deleting wired network profiles. Refactored the help/about dialogs to support the old TextDialog curses/README, in/man=wicd-curses.8.in: Script configurator has been "changed" --- curses/README | 4 +- curses/curses_misc.py | 35 ++++++++----- curses/netentry_curses.py | 9 +--- curses/wicd-curses.py | 106 ++++++++++++++++++++++++++------------ in/man=wicd-curses.8.in | 13 +++-- 5 files changed, 109 insertions(+), 58 deletions(-) diff --git a/curses/README b/curses/README index a9cc12b..afe8d66 100644 --- a/curses/README +++ b/curses/README @@ -26,9 +26,9 @@ C : Display network configuration for selected network A : Display "About" dialog I : Raise the "Scan for hidden networks" dialog H : Raise help dialog -S : Configure scripts (calls an external program, requires superuser - privileges +S : Provide instructions for configuring scripts delete : Delete selected wired network profile (from the wired ComboBox) +F2 : Rename selected wired network profile (from the wired ComboBox) IN DIALOGS (Meta usually is "Alt"): ESC or Q: Quit dialog without saving information (if present) diff --git a/curses/curses_misc.py b/curses/curses_misc.py index 97b0eae..0dfc374 100644 --- a/curses/curses_misc.py +++ b/curses/curses_misc.py @@ -24,6 +24,15 @@ wicd-curses. import urwid +# Uses code that is towards the bottom +def error(ui,parent,message): + """Shows an error dialog (or something that resembles one)""" + # /\ + # /!!\ + # /____\ + dialog = TextDialog(message,6,40,('important',"ERROR")) + return dialog.run(ui,parent) + # My savior. :-) # Although I could have made this myself pretty easily, just want to give credit where # its due. @@ -301,7 +310,7 @@ class ComboBox(urwid.WidgetWrap): self.user_args = user_args # Widget references to simplify some things - self.body = None + self.parent = None self.ui = None self.row = None def set_list(self,list): @@ -310,25 +319,27 @@ class ComboBox(urwid.WidgetWrap): def set_focus(self,index): self.focus = index self.cbox.set_w(SelText(self.list[index]+' vvv')) + if self.overlay: + self.overlay._listbox.set_focus(index) def rebuild_combobox(self): - self.build_combobox(self.body,self.ui,self.row) - def build_combobox(self,body,ui,row): + self.build_combobox(self.parent,self.ui,self.row) + def build_combobox(self,parent,ui,row): str,trash = self.label.get_text() self.cbox = DynWrap(SelText([self.list[self.focus]+' vvv']),attrs=self.attrs,focus_attr=self.focus_attr) if str != '': w = urwid.Columns([('fixed',len(str),self.label),self.cbox],dividechars=1) - self.overlay = self.ComboSpace(self.list,body,ui,self.focus, + self.overlay = self.ComboSpace(self.list,parent,ui,self.focus, pos=(len(str)+1,row)) else: w = urwid.Columns([self.cbox]) - self.overlay = self.ComboSpace(self.list,body,ui,self.focus, + self.overlay = self.ComboSpace(self.list,parent,ui,self.focus, pos=(0,row)) self.set_w(w) - self.body = body + self.parent = parent self.ui = ui self.row = row @@ -341,7 +352,7 @@ class ComboBox(urwid.WidgetWrap): # Die if the user didn't prepare the combobox overlay if self.overlay == None: raise ComboBoxException('ComboBox must be built before use!') - retval = self.overlay.show(self.ui,self.body) + retval = self.overlay.show(self.ui,self.parent) if retval != None: self.set_focus(self.list.index(retval)) #self.cbox.set_w(SelText(retval+' vvv')) @@ -444,9 +455,9 @@ class Dialog2(urwid.WidgetWrap): # Simple dialog with text in it and "OK" class TextDialog(Dialog2): def __init__(self, text, height, width, header=None,align='left'): - l = [] - for line in text: - l.append( urwid.Text( line,align=align)) + l = [urwid.Text(text)] + #for line in text: + # l.append( urwid.Text( line,align=align)) body = urwid.ListBox(l) body = urwid.AttrWrap(body, 'body') @@ -461,8 +472,8 @@ class TextDialog(Dialog2): self.frame.set_focus('footer') class InputDialog(Dialog2): - def __init__(self, text, height, width,ok_name='OK'): - self.edit = urwid.Edit(wrap='clip') + def __init__(self, text, height, width,ok_name='OK',edit_text=''): + self.edit = urwid.Edit(wrap='clip',edit_text=edit_text) body = urwid.ListBox([self.edit]) body = urwid.AttrWrap(body, 'editbx','editfc') diff --git a/curses/netentry_curses.py b/curses/netentry_curses.py index 4274625..8141664 100644 --- a/curses/netentry_curses.py +++ b/curses/netentry_curses.py @@ -22,17 +22,10 @@ # MA 02110-1301, USA. import urwid -from curses_misc import TextDialog,DynWrap,MaskingEdit,ComboBox +from curses_misc import TextDialog,DynWrap,MaskingEdit,ComboBox,error import wicd.misc as misc from wicd.misc import noneToString, stringToNone, noneToBlankString, to_bool -def error(ui,parent,message): - """Shows an error dialog (or something that resembles one)""" - # /\ - # /!!\ - # /____\ - dialog = TextDialog(message,40,6,('important',"ERROR")) - return dialog.run(ui,parent) language = misc.get_language_list_gui() diff --git a/curses/wicd-curses.py b/curses/wicd-curses.py index 12427ee..9f7e201 100644 --- a/curses/wicd-curses.py +++ b/curses/wicd-curses.py @@ -54,10 +54,10 @@ import sys from time import sleep # Curses UIs for other stuff -from curses_misc import SelText,ComboBox,TextDialog,InputDialog +from curses_misc import SelText,ComboBox,TextDialog,InputDialog,error from prefs_curses import PrefsDialog import netentry_curses -from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog,error +from netentry_curses import WirelessSettingsDialog, WiredSettingsDialog # Stuff about getting the script configurer running from grp import getgrgid @@ -217,40 +217,59 @@ def about_dialog(body): # The ASCII Art "Wicd" was made from the "smslant" font on one of those # online ASCII big text generators. theText = [ -[('green'," /// \\\\\\")," _ ___ __"], -[('green'," /// \\\\\\")," | | /| / (_)______/ /"], -[('green'," /// \\\\\\")," | |/ |/ / / __/ _ / "], -[('green',"/|| // \\\\ ||\\")," |__/|__/_/\__/\_,_/ "], -[('green',"||| ||"),"(|^|)",('green',"|| |||"), -" ($VERSION) ".replace("$VERSION",daemon.Hello())], +('green'," /// \\\\\\")," _ ___ __\n", +('green'," /// \\\\\\")," | | /| / (_)______/ /\n", +('green'," /// \\\\\\")," | |/ |/ / / __/ _ / \n", +('green',"/|| // \\\\ ||\\")," |__/|__/_/\__/\_,_/ \n", +('green',"||| ||"),"(|^|)",('green',"|| |||"), +" ($VERSION) \n".replace("$VERSION",daemon.Hello()), -[('green',"\\|| \\\\")," |+| ",('green',"// ||/ ")], -[('green'," \\\\\\")," |+| ",('green',"///")," http://wicd.net"], -[('green'," \\\\\\")," |+| ",('green',"///")," Brought to you by:"], -[('green'," \\\\\\")," |+| ",('green',"///")," Adam Blackburn (wicd)"], -" ___|+|___ Dan O'Reilly (wicd)", -" |---------| Andrew Psaltis (this ui)", +('green',"\\|| \\\\")," |+| ",('green',"// ||/ \n"), +('green'," \\\\\\")," |+| ",('green',"///")," http://wicd.net\n", +('green'," \\\\\\")," |+| ",('green',"///")," Brought to you by:\n", +('green'," \\\\\\")," |+| ",('green',"///")," Adam Blackburn (wicd)\n", +" ___|+|___ Dan O'Reilly (wicd)\n", +" |---------| Andrew Psaltis (this ui)\n", "-----------------------------------------------------"] about = TextDialog(theText,16,55,header=('header','About Wicd')) about.run(ui,body) def help_dialog(body): theText = [ -"For more detailed help, consult the wicd-curses(8) man page.", -"", "All controls are case sensitive", -[('bold','H')," Display this help dialog"], -[('bold','enter')," Connect to selected network"], -[('bold','D')," Disconnect from all networks"], -[('bold','ESC')," Stop a network connection in progress"], -[('bold','F5')," or ", ('bold','R')," Refresh network list"], -[('bold','P')," Prefrences dialog"], -[('bold','I')," Scan for hidden networks"], -[('bold','S')," Select scripts"] +"For more detailed help, consult the wicd-curses(8) man page.\n", +"\n", "All controls are case sensitive\n", +('bold','H')," Display this help dialog\n", +('bold','enter')," Connect to selected network\n", +('bold','D')," Disconnect from all networks\n", +('bold','ESC')," Stop a network connection in progress\n", +('bold','F5')," or ", ('bold','R')," Refresh network list\n", +('bold','P')," Prefrences dialog\n", +('bold','I')," Scan for hidden networks\n", +('bold','S')," Select scripts\n" ] help = TextDialog(theText,15,62,header=('header',"Wicd-Curses Help")) help.run(ui,body) -def run_configscript(netname,nettype): +def run_configscript(parent,netname,nettype): + configfile = wpath.etc+netname+'-settings.conf' + header = 'profile' if nettype == 'wired' else 'BSSID' + profname = netname if nettype == 'wired' else wireless.GetWirelessProperty( + netname,'bssid') + + theText = [ + """To avoid various complications, wicd-curses does not support directly editing the scripts directly. However, you can edit them manually. First, (as root)", open the "%s" config file, and look for the section labeled by the %s in question. In this case, this is: + +[%s] + +Once here, you can adjust (or add) the "beforescript", "afterscript", and "disconnectscript" variables as needed, to change the preconnect, postconnect, and disconnect scripts respectively. + +Alternatively, you can configure the wireless networks by ESSID, by looking for the "[]" field in the config file.""" % (configfile,header,profname)] + dialog = TextDialog(theText,16,80) + dialog.run(ui,parent) + # This code works with many distributions, but not all of them. So, to + # limit complications, it has been deactivated. If you want to run it, + # be my guest. Be sure to deactivate the above stuff first. + """ loop.quit() ui.stop() argv = netname + ' ' +nettype @@ -265,7 +284,7 @@ def run_configscript(netname,nettype): precmd = '' precmdargv = '' postcmd = '' - elif 'admin' in glist or 'wheel' in glist: + elif 'admin' in glist or 'wheel' in glist or 'sudo' in glist: precmd = 'sudo' precmdargv = '' postcmd = '' @@ -278,7 +297,7 @@ def run_configscript(netname,nettype): system(precmd+precmdargv+cmd+postcmd) raw_input("Press enter!") main() - + """ ######################################## ##### URWID SUPPORT CLASSES @@ -369,25 +388,47 @@ class WiredComboBox(ComboBox): if self.theList != []: wired.ReadWiredNetworkProfile(self.get_selected_profile()) + #def rebuild_combobox(self): + # pass def keypress(self,size,key): prev_focus = self.get_focus()[1] key = self.__super.keypress(size,key) if self.get_focus()[1] == len(self.list)-1: dialog = InputDialog(('header',"Add new wired profile"),7,30) - exitcode,name = dialog.run(ui,self.body) + exitcode,name = dialog.run(ui,self.parent) if exitcode == 0: wired.CreateWiredNetworkProfile(name,False) self.set_list(wired.GetWiredProfileList()) self.rebuild_combobox() self.set_focus(prev_focus) - self.overlay._listbox.set_focus(prev_focus) else: wired.ReadWiredNetworkProfile(self.get_selected_profile()) if key == 'delete': + if len(self.theList) == 1: + error(self.ui,self.parent,"Cannot delete the last wired profile. Try renaming it ('F2')") + return key wired.DeleteWiredNetworkProfile(self.get_selected_profile()) + # Return to the top of the list if something is deleted. + + if wired.GetDefaultWiredNetwork() != None: + self.set_focus(self.theList.index(wired.GetDefaultWiredNetwork())) + else: + prev_focus -= 1 + self.set_focus(prev_focus) self.set_list(wired.GetWiredProfileList()) self.rebuild_combobox() + if key == 'f2': + dialog = InputDialog(('header',"Rename wired profile"),7,30, + edit_text=unicode(self.get_selected_profile())) + exitcode,name = dialog.run(ui,self.parent) + if exitcode == 0: + # Save the new one, then kill the old one + wired.SaveWiredNetworkProfile(name) + wired.DeleteWiredNetworkProfile(self.get_selected_profile()) + self.set_list(wired.GetWiredProfileList()) + self.set_focus(self.theList.index(name)) + self.rebuild_combobox() return key #if key == 'C': # Configure the network @@ -401,7 +442,8 @@ class WiredComboBox(ComboBox): def get_selected_profile(self): """Get the selected wired profile""" - return self.theList[self.get_focus()[1]] + loc = self.get_focus()[1] + return self.theList[loc] ######################################## ##### APPLICATION INTERFACE CLASS @@ -684,7 +726,7 @@ class appGUI(): if "f8" in keys or 'Q' in keys: loop.quit() return False - if "f5" in keys: + if "f5" in keys or 'R' in keys: self.lock_screen() wireless.Scan() if "D" in keys: @@ -741,7 +783,7 @@ class appGUI(): else: nettype = 'wireless' netname = str(self.wiredLB.get_focus()[1]) - run_configscript(netname,nettype) + run_configscript(self.frame,netname,nettype) for k in keys: if urwid.is_mouse_event(k): diff --git a/in/man=wicd-curses.8.in b/in/man=wicd-curses.8.in index 67bacb2..944452f 100644 --- a/in/man=wicd-curses.8.in +++ b/in/man=wicd-curses.8.in @@ -1,5 +1,5 @@ .\" First revision was r203 -.TH WICD-CURSES "8" "January 2009" "wicd-curses-r247" +.TH WICD-CURSES "8" "January 2009" "wicd-curses-r250" .SH NAME .B wicd-curses \- curses-based wicd(8) controller @@ -47,13 +47,18 @@ Bring up a rather simplistic help dialog. Of course, it mentions this man page Bring up network configuration controller for the selected network .TP .BR delete -Delete the selected wired network profile (from the wired combo box at the top) +Delete the selected wired network profile (from the wired network combo box at the top) +.TP +.BR F2 +Rename the selected wired network profile (from the wired network combo box at the top) .\".PP .\"The following are not implemented yet: .TP .BR S -Bring up the script selector for the selected network (requires superuser privileges) -.SH "FILES" +.\"Bring up the script selector for the selected network (requires superuser privileges) +Bring up instructions on how to edit the scripts. I have implemented a way to do this in the interface itself, but making it function with all Linux distros would be difficult. Since you are reading this, you should know how to do what I suggest. ;-) + +".SH "FILES" These are not used yet. .TP .I ~/.wicd/WHEREAREMYFILES From 33a08b696eda759e2a2b66d60d250705997ac156 Mon Sep 17 00:00:00 2001 From: Dan O'Reilly Date: Tue, 20 Jan 2009 23:55:43 -0500 Subject: [PATCH 14/14] Add missing guiutil module --- wicd/guiutil.py | 111 ++++++++++++++++++++++++++++++++++++++++++++ wicd/wicd-daemon.py | 19 ++++++++ 2 files changed, 130 insertions(+) create mode 100644 wicd/guiutil.py diff --git a/wicd/guiutil.py b/wicd/guiutil.py new file mode 100644 index 0000000..e84c753 --- /dev/null +++ b/wicd/guiutil.py @@ -0,0 +1,111 @@ +""" guiutil - A collection of commonly used gtk/gui functions and classes. """ +# +# Copyright (C) 2007 - 2008 Adam Blackburn +# Copyright (C) 2007 - 2008 Dan O'Reilly +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License Version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import gtk + +def error(parent, message, block=True): + """ Shows an error dialog. """ + def delete_event(dialog, id): + dialog.destroy() + dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, + gtk.BUTTONS_OK) + dialog.set_markup(message) + if not block: + dialog.present() + dialog.connect("response", delete_event) + else: + dialog.run() + dialog.destroy() + +def alert(parent, message, block=True): + """ Shows an warning dialog. """ + def delete_event(dialog, id): + dialog.destroy() + dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, + gtk.BUTTONS_OK) + dialog.set_markup(message) + if not block: + dialog.present() + dialog.connect("response", delete_event) + else: + dialog.run() + dialog.destroy() + + +class SmallLabel(gtk.Label): + def __init__(self, text=''): + gtk.Label.__init__(self, text) + self.set_size_request(50, -1) + +class LeftAlignedLabel(gtk.Label): + def __init__(self, label=None): + gtk.Label.__init__(self, label) + self.set_alignment(0.0, 0.5) + +class LabelEntry(gtk.HBox): + """ A label on the left with a textbox on the right. """ + def __init__(self,text): + gtk.HBox.__init__(self) + self.entry = gtk.Entry() + self.entry.set_size_request(200, -1) + self.label = SmallLabel() + self.label.set_text(text) + self.label.set_size_request(170, -1) + self.pack_start(self.label, fill=False, expand=False) + self.pack_start(self.entry, fill=False, expand=False) + self.label.show() + self.entry.show() + self.entry.connect('focus-out-event', self.hide_characters) + self.entry.connect('focus-in-event', self.show_characters) + self.auto_hide_text = False + self.show() + + def set_text(self, text): + # For compatibility... + self.entry.set_text(text) + + def get_text(self): + return self.entry.get_text() + + def set_auto_hidden(self, value): + self.entry.set_visibility(False) + self.auto_hide_text = value + + def show_characters(self, widget=None, event=None): + # When the box has focus, show the characters + if self.auto_hide_text and widget: + self.entry.set_visibility(True) + + def set_sensitive(self, value): + self.entry.set_sensitive(value) + self.label.set_sensitive(value) + + def hide_characters(self, widget=None, event=None): + # When the box looses focus, hide them + if self.auto_hide_text and widget: + self.entry.set_visibility(False) + + +class GreyLabel(gtk.Label): + """ Creates a grey gtk.Label. """ + def __init__(self): + gtk.Label.__init__(self) + + def set_label(self, text): + self.set_markup("" + text + "") + self.set_alignment(0, 0) diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index 8fb98bb..06638c2 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -95,6 +95,7 @@ class WicdDaemon(dbus.service.Object): self.connection_state = misc.NOT_CONNECTED self.connection_info = [""] self.auto_connecting = False + self.prefer_wired = False self.dhcp_client = 0 self.link_detect_tool = 0 self.flush_tool = 0 @@ -506,7 +507,23 @@ class WicdDaemon(dbus.service.Object): def GetWiredAutoConnectMethod(self): """ Returns the wired autoconnect method. """ return int(self.wired_connect_mode) + + + @dbus.service.method('org.wicd.dameon') + def GetPreferWiredNetwork(self): + """ Returns True if wired network preference is set. + If this is True, wicd will switch from a wireless connection + to a wired one if an ethernet connection is available. + + """ + return self.prefer_wired + + @dbus.service.method('org.wicd.daemon') + def SetPreferWiredNetwork(self, value): + """ Sets the prefer_wired state. """ + self.prefer_wired = value + @dbus.service.method('org.wicd.daemon') def SetConnectionStatus(self, state, info): """ Sets the connection status. @@ -837,6 +854,8 @@ class WicdDaemon(dbus.service.Object): self.SetLinkDetectionTool(app_conf.get("Settings", "link_detect_tool", default=0)) self.SetFlushTool(app_conf.get("Settings", "flush_tool", default=0)) + self.SetPreferWiredNetwork(app_conf.get("Settings", "prefer_wired", + default=False)) app_conf.write() if os.path.isfile(wireless_conf):