PyGTK: ShutdownLater [update]
Shutdown, reboot, hibernate or suspend your computer later!
GTK GUI which lets the user choose between shutdown, reboot, hibernate or suspend
after a specified amount of time.
Runs on UPower-DBus calls, which surpasses the need for root access.
Working on Ubuntu 10.04, ArchLinux 2009.08 (Maybe other GTK, DBus, DeviceKit systems too).
Version 1.1 released:
- gnome-desktop 2.30 fixes (Ubuntu 10.04 compatible).

Configuration

Running
Code below or here
#!/usr/bin/env python # -*- coding: utf-8 -*- # # GTK GUI which executes shutdown, reboot, hibernate or suspend after a given time. # DBus, UPower and ConsoleKit handles the stuff under the hood. # If the methodes are allowed, no root access is required. # # Version: 1.1 # Requires: gnome-desktop 2.30 # # NOTE: UPower-Suspend/Hibernate do not give a reply through dbus. This programm # does ignore that, but if you try to suspend/hibernate after a wake up # it takes about 20sec till the non existing reply gets recognized. # TODO: Check if dbus requests are allowed (CanStop(), CanRestart()). # Support older backends (Hal, DeviceKit-Power, SessionManager). # # Version History: # 1.0 - Initial Release # 1.1 - Gnome-Desktop 2.30 fixes: UPower replaces DeviceKit-Power, # ConsoleKit replaces SessionManager # # Copyright (C) 2010 wag@wag-net.ch # # 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 3 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, see <http://www.gnu.org/licenses/>. import gtk, gobject, dbus, dbus.mainloop.glib gobject.threads_init() dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) class C_ShutdownLater(): def __init__(self): self.loop = gobject.MainLoop() self.do = "shutdown" self.win_conf() def win_conf(self): """Create configuration window""" win = gtk.Window(gtk.WINDOW_TOPLEVEL) win.connect("destroy", self.quit) win.set_title("ShutdownLater") win.set_border_width(20) # Box, Table vb_main = gtk.VBox(False, 0) win.add(vb_main) t_rb = gtk.Table(2, 2, False) win.set_geometry_hints(t_rb, min_width=200, min_height=70) t_rb.set_row_spacings(5) t_rb.set_col_spacings(5) f_rb = gtk.Frame(" Initiate : ") f_rb.set_border_width(4) f_rb.add(t_rb) vb_main.pack_start(f_rb) # RadioButtons rb_shutdown = gtk.RadioButton(None, "Shutdown") rb_shutdown.set_border_width(5) rb_shutdown.connect("toggled", self.rb_callback, "shutdown") t_rb.attach(rb_shutdown, 0, 1, 0, 1) rb_reboot = gtk.RadioButton(rb_shutdown, "Reboot") rb_reboot.set_border_width(5) rb_reboot.connect("toggled", self.rb_callback, "reboot") t_rb.attach(rb_reboot, 1, 2, 0, 1) rb_hibernate = gtk.RadioButton(rb_shutdown, "Hibernate") rb_hibernate.set_border_width(5) rb_hibernate.connect("toggled", self.rb_callback, "hibernate") t_rb.attach(rb_hibernate, 0, 1, 1, 2) rb_suspend = gtk.RadioButton(rb_shutdown, "Suspend") rb_suspend.set_border_width(5) rb_suspend.connect("toggled", self.rb_callback, "suspend") t_rb.attach(rb_suspend, 1, 2, 1, 2) # Table, Labels t_sp = gtk.Table(3, 2, False) t_sp.set_row_spacings(10) t_sp.set_col_spacings(10) f_sp = gtk.Frame(" After : ") f_sp.set_border_width(4) f_sp.add(t_sp) vb_main.pack_start(f_sp) l_h = gtk.Label("Hours") l_h.set_padding(3, 3) t_sp.attach(l_h, 0, 1, 0, 1) l_m = gtk.Label("Minutes") t_sp.attach(l_m, 1, 2, 0, 1) l_s = gtk.Label("Seconds") t_sp.attach(l_s, 2, 3, 0, 1) # SpinBoxes sp_h_adj = gtk.Adjustment(0, 0, 999, 1, 10, 0) self.sp_h = gtk.SpinButton(sp_h_adj, 1, 0) self.sp_h.set_numeric(True) self.sp_h.set_size_request(50, 27) t_sp.attach(self.sp_h, 0, 1, 1, 2, False) sp_m_adj = gtk.Adjustment(0, 0, 59, 1, 10, 0) self.sp_m = gtk.SpinButton(sp_m_adj, 1, 0) self.sp_m.set_numeric(True) self.sp_m.set_size_request(45, 27) t_sp.attach(self.sp_m, 1, 2, 1, 2, False) sp_s_adj = gtk.Adjustment(0, 0, 59, 1, 10, 0) self.sp_s = gtk.SpinButton(sp_s_adj, 1, 0) self.sp_s.set_numeric(True) self.sp_s.set_size_request(45, 27) t_sp.attach(self.sp_s, 2, 3, 1, 2, False) # Table, Buttons t_b = gtk.Table(2, 1, False) t_b.set_row_spacings(10) t_b.set_col_spacings(10) vb_main.pack_start(t_b) b_start = gtk.Button("Start") b_start.set_border_width(4) t_b.attach(b_start, 0, 1, 0, 1) b_start.connect("clicked", self.start, win) b_quit = gtk.Button(" Quit ") b_quit.set_border_width(4) t_b.attach(b_quit, 1, 2, 0, 1) b_quit.connect("clicked", self.quit) win.show_all() gtk.main() def win_run(self, main): """Create running window""" win_conf = main win = gtk.Window(gtk.WINDOW_TOPLEVEL) win.connect("destroy", self.cancel, win_conf, win) win.set_title("ShutdownLater") win.set_border_width(20) # Box, ProgBar vb_main = gtk.VBox(False, 0) win.add(vb_main) pb_adj = gtk.Adjustment(1, 0, 1, 1, 5, 0) self.pb_time = gtk.ProgressBar(pb_adj) self.pb_time.set_size_request(200, 30) af_pb = gtk.Frame(" %s in : " % self.do.capitalize()) af_pb.set_border_width(4) af_pb.add(self.pb_time) vb_main.pack_start(af_pb) # Table, Buttons t_b = gtk.Table(2, 1, False) t_b.set_row_spacings(10) t_b.set_col_spacings(10) vb_main.pack_start(t_b) b_pause = gtk.ToggleButton("Pause") b_pause.set_border_width(4) t_b.attach(b_pause, 0, 1, 0, 1) b_pause.connect("toggled", self.pause) b_cancel = gtk.Button("Cancel") b_cancel.set_border_width(4) t_b.attach(b_cancel, 1, 2, 0, 1) b_cancel.connect("clicked", self.cancel, win_conf, win) win.show_all() def quit(self, data=None): self.loop.quit() gtk.main_quit() def start(self, widget, data): """Start choosen process""" win_conf = data # Get spinbutton values as int, calculate total and current time h = self.sp_h.get_value_as_int() m = self.sp_m.get_value_as_int() s = self.sp_s.get_value_as_int() self.t_total = (h*3600)+(m*60)+s self.t_current = (h*3600)+(m*60)+s # Hide main window and show run window win_conf.hide() self.win_run(data) self.timer(h, m, s) def rb_callback(self, widget, data=None): """Set do variable from user input""" if widget.get_active(): self.do = data def pause(self, widget): """Pause process""" # Kill or start timer if self.t_current != 0: if widget.get_active(): gobject.source_remove(self.g_id) else: self.g_id = gobject.timeout_add(1000, self.count) def cancel(self, widget, win_conf, win_run): """Cancel process""" # Remove timer, destroy run window, show main window again gobject.source_remove(self.g_id) win_run.destroy() win_conf.show() def timer(self, h, m, s): """Call counter every second""" self.pb_time.set_text("%02i:%02i:%02i" % (h, m, s)) self.g_id = gobject.timeout_add(1000, self.count) def count(self): """Countdown and rewrite progressbar""" # Countdown, calculate and update if self.t_current != 0: self.t_current -= 1 pb_percent = float(self.t_current)/float(self.t_total) pb_h = self.t_current/3600 pb_m = self.t_current%3600/60 pb_s = self.t_current%3600%60 self.pb_time.set_fraction(pb_percent) self.pb_time.set_text("%02i:%02i:%02i" % (pb_h, pb_m, pb_s)) # Again, and again, and again... return True else: self.initiate() def initiate(self): """Send dbus messages""" # Shutdown with ConsoleKit if self.do == 'shutdown': bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager') iface = dbus.Interface(proxy, 'org.freedesktop.ConsoleKit.Manager') iface.Stop() # Reboot with ConsoleKit elif self.do == 'reboot': bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager') iface = dbus.Interface(proxy, 'org.freedesktop.ConsoleKit.Manager') iface.Restart() # Hibernate with UPower elif self.do == 'hibernate': bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.UPower', '/org/freedesktop/UPower') iface = dbus.Interface(proxy, 'org.freedesktop.UPower') iface.Hibernate(ignore_reply=True) # Suspend with UPower elif self.do == 'suspend': bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.UPower', '/org/freedesktop/UPower') iface = dbus.Interface(proxy, 'org.freedesktop.UPower') iface.Suspend(ignore_reply=True) self.loop.run() sdl = C_ShutdownLater()
#1 — Comment by Mark — 25 January 2010 - 06:19
I love it! Thanks!
#2 — Comment by jeremy — 10 May 2010 - 17:35
Thank you sooooo much. I’ve been looking for just this functionality. Well done !