diff --git a/data/wicd.glade b/data/wicd.glade index 40d2ca3..a5eea9f 100644 --- a/data/wicd.glade +++ b/data/wicd.glade @@ -1,6 +1,6 @@ - + 450 @@ -36,107 +36,33 @@ True True - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - network_menu - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Create Ad-Hoc Network + Create an ad-hoc network True - + - + True gtk-add - 1 - + True - Enable/Disable Interfaces + Enter a hidden network to try to locate. + Find a hidden network True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - Enable Wired Interface - True - - - - True - gtk-yes - - - - - - - True - Enable Wireless Interface - True - - - - True - gtk-yes - - - - - - - True - Disable Wired Interface - True - - - - True - gtk-stop - - - - - - - True - Disable Wireless Interface - True - - - - True - gtk-stop - - - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Hidden Network - True - + - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - network-wireless + wicd @@ -468,7 +394,6 @@ Preferences 125 560 - . GDK_WINDOW_TYPE_HINT_DIALOG diff --git a/wicd/gui.py b/wicd/gui.py index 6b69fea..261ed1b 100644 --- a/wicd/gui.py +++ b/wicd/gui.py @@ -52,29 +52,54 @@ except: proxy_obj = daemon = wireless = wired = bus = None language = misc.get_language_list_gui() +DBUS_AVAIL = False -def setup_dbus(): - global bus, daemon, wireless, wired - +def setup_dbus(force=True): + global bus, daemon, wireless, wired, DBUS_AVAIL try: dbusmanager.connect_to_dbus() except DBusException: - print "Can't connect to the daemon, trying to start it automatically..." - misc.PromptToStartDaemon() - try: - dbusmanager.connect_to_dbus() - except DBusException: - error(None, "Could not connect to wicd's D-Bus interface. " + - "Make sure the daemon is started.") - sys.exit(1) - + if force: + print "Can't connect to the daemon, trying to start it automatically..." + misc.PromptToStartDaemon() + try: + dbusmanager.connect_to_dbus() + except DBusException: + error(None, "Could not connect to wicd's D-Bus interface. " + + "Check the wicd log for error messages.") + return False + else: + return False bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() daemon = dbus_ifaces['daemon'] wireless = dbus_ifaces['wireless'] wired = dbus_ifaces['wired'] + DBUS_AVAIL = True return True + +def handle_no_dbus(from_tray=False): + global DBUS_AVAIL + DBUS_AVAIL = False + if from_tray: return False + print "Wicd daemon is shutting down!" + error(None, "The wicd daemon has shut down, the UI will not function properly until it is restarted.") + _wait_for_dbus() + return False + +@misc.threaded +def _wait_for_dbus(): + global DBUS_AVAIL + while True: + time.sleep(10) + print "Trying to reconnect.." + if not setup_dbus(force=False): + print "Failed to reconnect to the daemon." + else: + print "Successfully reconnected to the daemon." + DBUS_AVAIL = True + return def error(parent, message): """ Shows an error dialog """ @@ -215,7 +240,7 @@ class appGui(object): """ Initializes everything needed for the GUI. """ setup_dbus() - gladefile = wpath.share + "wicd.glade" + gladefile = os.path.join(wpath.share, "wicd.glade") self.wTree = gtk.glade.XML(gladefile) self.window = self.wTree.get_widget("window1") size = daemon.ReadWindowSize("main") @@ -232,10 +257,10 @@ class appGui(object): "disconnect_clicked" : self.disconnect_all, "main_exit" : self.exit, "cancel_clicked" : self.cancel_connect, - "connect_clicked" : self.connect_hidden, + "hidden_clicked" : self.connect_hidden, "preferences_clicked" : self.settings_dialog, "about_clicked" : self.about_dialog, - "create_adhoc_network_button_button" : self.create_adhoc_network, + "create_adhoc_clicked" : self.create_adhoc_network, } self.wTree.signal_autoconnect(dic) @@ -253,8 +278,8 @@ class appGui(object): self.status_area.hide_all() - if os.path.exists(wpath.images + "wicd.png"): - self.window.set_icon_from_file(wpath.images + "wicd.png") + if os.path.exists(os.path.join(wpath.images, "wicd.png")): + self.window.set_icon_from_file(os.path.join(wpath.images, "wicd.png")) self.statusID = None self.first_dialog_load = True self.is_visible = True @@ -277,7 +302,9 @@ class appGui(object): 'org.wicd.daemon.wireless') bus.add_signal_receiver(self.update_connect_buttons, 'StatusChanged', 'org.wicd.daemon') - bus.add_signal_receiver(setup_dbus, "DaemonClosing", "org.wicd.daemon") + if standalone: + bus.add_signal_receiver(handle_no_dbus, "DaemonClosing", + "org.wicd.daemon") try: gobject.timeout_add_seconds(1, self.update_statusbar) except: @@ -465,6 +492,7 @@ class appGui(object): current network state is the same as the previous. """ + if not DBUS_AVAIL: return if not state: state, x = daemon.GetConnectionStatus() @@ -520,15 +548,18 @@ class appGui(object): This method is called after a wireless scan is completed. """ + if not DBUS_AVAIL: return if not self.connecting: gobject.idle_add(self.refresh_networks, None, False, None) def dbus_scan_started(self): """ Called when a wireless scan starts. """ + if not DBUS_AVAIL: return self.network_list.set_sensitive(False) def refresh_clicked(self, widget=None): """ Kick off an asynchronous wireless scan. """ + if not DBUS_AVAIL: return self.refreshing = True wireless.Scan(reply_handler=None, error_handler=None) diff --git a/wicd/misc.py b/wicd/misc.py index 2c46ec1..a3c01e2 100644 --- a/wicd/misc.py +++ b/wicd/misc.py @@ -69,7 +69,7 @@ def Run(cmd, include_stderr=False, return_pipe=False): one output string from the command. """ - if type(cmd) is not list: + if not isinstance(cmd, list): cmd = to_unicode(str(cmd)) cmd = cmd.split() if include_stderr: @@ -82,8 +82,12 @@ def Run(cmd, include_stderr=False, return_pipe=False): tmpenv = os.environ.copy() tmpenv["LC_ALL"] = "C" tmpenv["LANG"] = "C" - f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, cwd='/', - env=tmpenv) + try: + f = Popen(cmd, shell=False, stdout=PIPE, stderr=err, close_fds=fds, + cwd='/', env=tmpenv) + except OSError, e: + print "Running command %s failed: %s" % (str(cmd), str(e)) + return "" if return_pipe: return f.stdout @@ -383,7 +387,7 @@ def find_path(cmd): the file can not be found. """ - paths = os.getenv("PATH", default=["/usr/bin", "/usr/local/bin"]).split(':') + 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): return os.path.join(path, cmd) @@ -531,6 +535,7 @@ def get_language_list_tray(): language['cannot_start_daemon'] = _("Unable to connect to wicd daemon DBus interface." + \ "This typically means there was a problem starting the daemon." + \ "Check the wicd log for more info") + language['no_daemon_tooltip'] = _("Wicd daemon unreachable") return language def noneToBlankString(text): diff --git a/wicd/prefs.py b/wicd/prefs.py index e4761c0..23f18db 100644 --- a/wicd/prefs.py +++ b/wicd/prefs.py @@ -29,6 +29,7 @@ import gobject import pango from wicd import misc +from wicd import wpath from wicd.misc import checkboxTextboxToggle, noneToBlankString daemon = None @@ -78,6 +79,8 @@ class PreferencesDialog(object): self.dialog = self.wTree.get_widget("pref_dialog") self.dialog.set_title(language['preferences']) + if os.path.exists(os.path.join(wpath.images, "wicd.png")): + self.dialog.set_icon_from_file(os.path.join(wpath.images, "wicd.png")) size = daemon.ReadWindowSize("pref") width = size[0] height = size[1] diff --git a/wicd/wicd-client.py b/wicd/wicd-client.py index c403141..96d484c 100755 --- a/wicd/wicd-client.py +++ b/wicd/wicd-client.py @@ -59,7 +59,7 @@ if not hasattr(gtk, "StatusIcon"): import egg.trayicon USE_EGG = True except ImportError: - print 'Unable to load tray icon: Missing egg.trayicon module.' + print 'Unable to load tray icon: Missing both egg.trayicon and gtk.StatusIcon modules.' ICON_AVAIL = False misc.RenameProcess("wicd-client") @@ -125,7 +125,11 @@ class TrayIcon(object): self.max_snd_gain = 10000 self.max_rcv_gain = 10000 self.animate = animate - self.update_tray_icon() + if DBUS_AVAIL: + self.update_tray_icon() + else: + handle_no_dbus() + self.set_not_connected_state() def wired_profile_chooser(self): """ Launch the wired profile chooser. """ @@ -135,7 +139,7 @@ class TrayIcon(object): def set_wired_state(self, info): """ Sets the icon info for a wired state. """ wired_ip = info[0] - self.tr.set_from_file(wpath.images + "wired.png") + self.tr.set_from_file(os.path.join(wpath.images, "wired.png")) self.tr.set_tooltip(language['connected_to_wired'].replace('$A', wired_ip)) @@ -165,12 +169,14 @@ class TrayIcon(object): cur_network = info[1] self.tr.set_tooltip(language['connecting'] + " to " + cur_network + "...") - self.tr.set_from_file(wpath.images + "no-signal.png") + self.tr.set_from_file(os.path.join(wpath.images, "no-signal.png")) - def set_not_connected_state(self, info): + def set_not_connected_state(self, info=None): """ Set the icon info for the not connected state. """ self.tr.set_from_file(wpath.images + "no-signal.png") - if wireless.GetKillSwitchEnabled(): + if not DBUS_AVAIL: + status = language['no_daemon_tooltip'] + elif wireless.GetKillSwitchEnabled(): status = (language['not_connected'] + " (" + language['killswitch_enabled'] + ")") else: @@ -179,7 +185,7 @@ class TrayIcon(object): def update_tray_icon(self, state=None, info=None): """ Updates the tray icon and current connection status. """ - if not self.use_tray: return False + if not self.use_tray or not DBUS_AVAIL: return False if not state or not info: [state, info] = daemon.GetConnectionStatus() @@ -342,22 +348,15 @@ class TrayIcon(object): def tray_scan_started(self): """ Callback for when a wireless scan is started. """ + if not DBUS_AVAIL: return self._is_scanning = True self.init_network_menu() def tray_scan_ended(self): """ Callback for when a wireless scan finishes. """ + if not DBUS_AVAIL: return self._is_scanning = False self.populate_network_menu() - - def dbus_lost(self): - """ Callback for when the daemon is going down. """ - global DBUS_AVAIL - print "The daemon is going down!!" - DBUS_AVAIL = False - time.sleep(1) - while not setup_dbus(): - time.sleep(20) def on_activate(self, data=None): """ Opens the wicd GUI. """ @@ -474,6 +473,9 @@ class TrayIcon(object): net_menuitem = self.manager.get_widget("/Menubar/Menu/Connect/") submenu = net_menuitem.get_submenu() self._clear_menu(submenu) + if not DBUS_AVAIL: + net_menuitem.show() + return is_connecting = daemon.CheckIfConnecting() num_networks = wireless.GetNumberOfNetworks() @@ -638,26 +640,57 @@ Arguments: \t-a\t--no-animate\tRun the tray without network traffic tray animations. """ -def setup_dbus(): - global daemon, wireless, wired, DBUS_AVAIL +def setup_dbus(force=True): + global bus, daemon, wireless, wired, DBUS_AVAIL try: dbusmanager.connect_to_dbus() except DBusException: - print "Can't connect to the daemon, trying to start it automatically..." - misc.PromptToStartDaemon() - try: - dbusmanager.connect_to_dbus() - except DBusException: - gui.error(None, language['cannot_start_daemon']) - sys.exit(1) + if force: + print "Can't connect to the daemon, trying to start it automatically..." + misc.PromptToStartDaemon() + try: + dbusmanager.connect_to_dbus() + except DBusException: + gui.error(None, "Could not connect to wicd's D-Bus interface. " + + "Check the wicd log for error messages.") + return False + else: + return False + + bus = dbusmanager.get_bus() dbus_ifaces = dbusmanager.get_dbus_ifaces() daemon = dbus_ifaces['daemon'] wireless = dbus_ifaces['wireless'] wired = dbus_ifaces['wired'] DBUS_AVAIL = True + return True +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, "The wicd daemon has shut down, the UI will not function " + + "properly until it is restarted.") + _wait_for_dbus() + return False + +@misc.threaded +def _wait_for_dbus(): + global DBUS_AVAIL + while True: + time.sleep(10) + print "Trying to reconnect.." + if not setup_dbus(force=False): + print "Failed to reconnect to the daemon." + else: + print "Successfully reconnected to the daemon." + gui.setup_dbus(force=False) + DBUS_AVAIL = True + return + def main(argv): """ The main frontend program. @@ -702,7 +735,7 @@ def main(argv): # Check to see if wired profile chooser was called before icon # was launched (typically happens on startup or daemon restart). - if daemon.GetNeedWiredProfileChooser(): + if DBUS_AVAIL and daemon.GetNeedWiredProfileChooser(): daemon.SetNeedWiredProfileChooser(False) tray_icon.icon_info.wired_profile_chooser() @@ -715,7 +748,7 @@ def main(argv): 'org.wicd.daemon.wireless') bus.add_signal_receiver(tray_icon.tr.tray_scan_started, 'SendStartScanSignal', 'org.wicd.daemon.wireless') - bus.add_signal_receiver(tray_icon.tr.dbus_lost, + bus.add_signal_receiver(lambda: handle_no_dbus() or tray_icon.icon_info.set_not_connected_state(), "DaemonClosing", 'org.wicd.daemon') print 'Done.' mainloop = gobject.MainLoop() diff --git a/wicd/wicd-daemon.py b/wicd/wicd-daemon.py index 87b6ab3..5d3ee1b 100644 --- a/wicd/wicd-daemon.py +++ b/wicd/wicd-daemon.py @@ -1540,10 +1540,11 @@ def main(argv): daemon = WicdDaemon(wicd_bus, auto_connect=auto_connect) gobject.threads_init() if not no_poll: - (child_pid, x, x, x) = gobject.spawn_async(["/usr/bin/python", "-O", - wpath.lib + "monitor.py"], - flags=gobject.SPAWN_CHILD_INHERITS_STDIN) - signal.signal(signal.SIGTERM, sigterm_caught) + (child_pid, x, x, x) = gobject.spawn_async( + [misc.find_path("python"), "-O", os.path.join(wpath.lib, "monitor.py")], + flags=gobject.SPAWN_CHILD_INHERITS_STDIN + ) + signal.signal(signal.SIGTERM, sigterm_caught) # Enter the main loop mainloop = gobject.MainLoop() @@ -1557,8 +1558,9 @@ def main(argv): def sigterm_caught(sig=None, frame=None): """ Called when a SIGTERM is caught, kills monitor.py before exiting. """ global child_pid - print 'Daemon going down, killing wicd-monitor...' - os.kill(child_pid, signal.SIGTERM) + if child_pid: + print 'Daemon going down, killing wicd-monitor...' + os.kill(child_pid, signal.SIGTERM) print 'Removing PID file...' if os.path.exists(wpath.pidfile): os.remove(wpath.pidfile)