source: trunk/athena/bin/bugme/bugme @ 25643

Revision 25643, 6.2 KB checked in by jdreed, 12 years ago (diff)
In bugme: * .present() the window every 10 seconds (Trac: #386)
  • Property svn:executable set to *
Line 
1#!/usr/bin/python -Wall
2
3import gtk
4import gtk.glade
5import gobject
6import time
7import os
8import sys
9from optparse import OptionParser
10
11class BugMe:
12    def __init__(self):
13        # Time limit in seconds  (600)
14        self.timeLimit = 600
15        # First warn the user when this many seconds remain (120)
16        self.firstWarn = 120
17        # How often to warn initially (secs)
18        self.warnInterval = 60
19        # How often to warn after time has expired (secs)
20        self.annoyInterval = 30
21        # Hard time limit; user will be killed after this time
22        self.killTime = self.timeLimit * 1.5
23        if options.debugMode:
24            self.timeLimit = 120
25            self.firstWarn = 90
26            self.warnInterval = 30
27            self.annoyInterval = 10
28            self.killTime = 180
29        # (foreground, background)
30        self.colors = ('black', 'white')
31        try:
32            self.xml = gtk.glade.XML(options.gladeFile)
33        except:
34            print "Failed to create GladeXML object."
35            # Kill the child
36            os.kill(pid, 9)
37            sys.exit(255)
38        self.startTime = int(time.time())
39        self.timerWindow = self.xml.get_widget('TimerWindow')
40        self.timerWindow.connect("visibility_notify_event",
41                                 self.visibility_event_handler)
42        self.timerWindow.set_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)
43        self.nagDialog = self.xml.get_widget('NagDialog')
44        self.nagLabel = self.xml.get_widget('NagLabel')
45        self.elapsed_label = self.xml.get_widget('ElapsedLabel')
46        self.elapsed_label.set_markup("<span font_desc=\"50\">00:00</span>")
47        self.timer = gobject.timeout_add(1000, self.updateTimer)
48        self.xml.signal_autoconnect(self)
49        # 26 px should allow room for top panel
50        self.timerWindow.move(0,26)
51        self.timerWindow.show_all()
52        self.nextWarn = self.startTime + (self.timeLimit - self.firstWarn)
53        self.timeExpired = False
54        self.timerWindow.modify_bg(gtk.STATE_NORMAL,
55                                   gtk.gdk.color_parse(self.colors[1]))
56
57
58    def updateTimer(self):
59        if pid == os.waitpid(pid, os.WNOHANG)[0]:
60            sys.exit(0)
61        now = int(time.time())
62        elapsed = now - self.startTime
63        elapsedTime = (elapsed / 60, elapsed % 60)
64        self.elapsed_label.set_markup("<span foreground=\"%s\" background=\"%s\" font_desc=\"50\">%02d:%02d</span>" % (self.colors + elapsedTime))
65        self.timerWindow.modify_bg(gtk.STATE_NORMAL,
66                                   gtk.gdk.color_parse(self.colors[1]))
67        if elapsed >= self.timeLimit:
68            self.colors = ('white', 'red')
69            self.warnInterval = self.annoyInterval
70            self.timeExpired = True
71        if now >= self.nextWarn:
72            if elapsed < self.timeLimit:
73                self.colors = ('black', 'orange')
74            self.nextWarn = now + self.warnInterval
75            self.nag(((self.timeLimit - elapsed) / 60,
76                      (self.timeLimit - elapsed) % 60))
77        if options.killMode and elapsed >= self.killTime:
78            # The user has outstayed their welcome, nuke their session
79            print "Quitting."
80            sys.exit(0)
81
82        # It's a little odd to put this here, but it doesn't work in
83        # __init__; see comments in Trac #386
84        self.timerWindow.set_keep_above(True)
85        # And the above code doesn't work if the user has an "Always
86        # On Top" window above it.  The following does, and bugme lives
87        # up to its name:
88        if elapsed % 10 == 0:
89            self.timerWindow.present()
90        return True
91
92    def nag(self, remainingTime):
93        if self.timeExpired:
94            msg="Please log out immediately."
95            if options.killMode:
96                msg += "\n\nYour session will be terminated in %d seconds." % (self.killTime - (int(time.time()) - self.startTime))
97            self.nagLabel.set_markup("<span font_desc=\"20\">"+msg+"</span>")
98        else:
99            seconds = "%d second%s" % (remainingTime[1],
100                                       remainingTime[1] != 1 and 's' or '')
101            minutes = "%d minute%s" % (remainingTime[0],
102                                       remainingTime[0] != 1 and 's' or '')
103            if remainingTime[0] < 1:
104                remaining = seconds
105            elif remainingTime[1] == 0:
106                remaining = minutes
107            else:
108                remaining = "%s, %s" % (minutes, seconds)
109            self.nagLabel.set_markup("<span font_desc=\"20\">You have %s remaining\nin this session.</span>" % (remaining))
110
111        self.nagDialog.show()
112
113    def on_dialog_response(self, dialog, response_id):
114        if response_id == gtk.RESPONSE_CLOSE:
115            sys.exit(0)
116        elif response_id == gtk.RESPONSE_OK:
117            self.nagDialog.hide()
118
119    def visibility_event_handler(self, widget, event):
120        if event.state != gtk.gdk.VISIBILITY_UNOBSCURED:
121            self.timerWindow.present()
122        return True
123
124
125if __name__ == '__main__':
126    parser = OptionParser(usage="%prog [--debug] progname [args]",
127                          version="%prog 0.1")
128    parser.disable_interspersed_args()
129    parser.add_option("--debug",
130                     action="store_true", dest="debugMode", default=False,
131                     help="Enable debug mode (time limit of 2 minutes)")
132    parser.add_option("--fatal",
133                     action="store_true", dest="killMode", default=False,
134                     help="Kill the user session after 1.5 times the time limit.")
135    parser.add_option("--glade", action="store", type="string",
136                      dest="gladeFile",
137                      default="/usr/share/bugme/bugme.glade",
138                      help="Specify an alternate Glade file for debugging")
139    (options, args) = parser.parse_args()
140    if not os.access(options.gladeFile, os.R_OK):
141        print 'error: Unable to read glade file "' + gladeFile + '"'
142        sys.exit(255)
143    if len(args) < 1:
144        parser.error("'progname' is required")
145    pid = os.fork()
146    if not pid:
147        os.putenv('ATHENA_QUICK', '1')
148        try:
149            os.execvp(args[0], args)
150        except:
151            print "error: Could not execvp(%s,%s)" % (args[0], args)
152    else:
153        BugMe()
154        gtk.main()
Note: See TracBrowser for help on using the repository browser.