#
# Window with progress bars in :-,
#
import gtk
import threading
class ProgressOutput(gtk.HBox):
def __init__(self, progress_win, user):
gtk.HBox.__init__(self)
self.bar = gtk.ProgressBar()
self.pack_start(self.bar)
self.bar.show()
self.bar.set_fraction(0.0)
self.bar.set_text("")
#button = gtk.Button(_("Abort"))
#self.pack_start(button)
#button.connect("clicked", self.set_abort)
#button.show()
self.progress_win = progress_win
self.lock = threading.Lock()
# Update these thingy periodically
self.log_messages = []
self.bar_message = None
self.bar_position = None
self.done = 0
self.enabled = None
self.do_abort = 0
user.timeout_add (self.timeout_update)
def abort(self):
return self.do_abort
def set_abort(self, _button=None):
print "Attempt progress abort"
self.do_abort = 1
def timeout_update(self, user):
self.lock.acquire()
# Bar greyed out
if self.enabled != None:
self.bar.set_sensitive(self.enabled)
self.enabled = None
# Print pending log messages
while len(self.log_messages) != 0:
self.progress_win.msg_print(self.log_messages[0])
del self.log_messages[0]
if self.bar_position != None:
self.bar.set_fraction(self.bar_position)
self.bar_position = None
if self.bar_message != None:
self.bar.set_text(self.bar_message)
self.bar_message = None
if self.done == 1:
# No more update() calls
user.timeout_remove (self.timeout_update)
self.lock.release()
def log_msg(self, msg):
self.lock.acquire()
self.log_messages.append(msg)
self.lock.release()
def bar_msg(self, msg):
self.lock.acquire()
self.bar_message = msg
self.lock.release()
def bar_pos(self, pos):
self.lock.acquire()
self.bar_position = pos
self.lock.release()
def bar_enable(self, toggle):
self.lock.acquire()
self.enabled = toggle
self.lock.release()
def finished(self):
# call when you're finished using this progressbar
self.lock.acquire()
self.done = 1
self.lock.release()
class ProgressWin:
def silence_output(self, _a=None):
# If threads continue to write stuff to the window
# after the user has closed it we segfault. Prevent this.
# There is probably a good way... like
# window->dont_let_user_close_me = 1...
self.window_closed = 1
def toggle_text(self, _a):
if self.text_hidden == 1:
self.swin.show()
self.text_hidden = 0
else:
self.swin.hide()
self.text_hidden = 1
# window should contract
self.win.queue_resize()
def close(self, _a=None):
self.silence_output()
self.win.destroy()
def __init__(self, title, user, hidetext=None, parent_win=None):
"""
Set hidetext to the desired label of button to
show/hide text widget.
"""
self.user = user
self.win = gtk.Dialog()
self.win.set_title(title)
self.win.connect("destroy", self.silence_output)
if parent_win:
self.win.set_transient_for (parent_win)
self.win.vbox.set_spacing(5)
self.win.vbox.set_border_width(5)
self.window_closed = 0
self.win.action_area.set_border_width(0)
button_box = gtk.HBox(spacing=5)
self.win.action_area.pack_start(button_box)
button_box.show()
self.close_button = gtk.Button(stock="gtk-close")
self.close_button.connect("clicked", self.close)
button_box.pack_end(self.close_button, expand=False)
self.close_button.show()
self.swin = gtk.ScrolledWindow()
self.swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.swin.set_shadow_type(gtk.SHADOW_IN)
self.win.vbox.pack_end(self.swin)
if hidetext == None:
self.swin.show()
self.text_hidden = 0
else:
self.details_button = gtk.Button(" "+hidetext+" ")
self.details_button.connect("clicked", self.toggle_text)
button_box.pack_end(self.details_button, expand=False)
self.details_button.show()
self.text_hidden = 1
self.textview = gtk.TextView()
self.textview.set_editable(False)
self.textview.show()
self.swin.add(self.textview)
self.win.show()
# XXX Strange bug(?) in gtk makes first line default colour
# and therefore possibly invisible.
self.msg_print("")
def msg_print(self, message):
"""
Push a message onto the gtk.Text object.
"""
textbuffer = self.textview.get_buffer()
iter = textbuffer.get_end_iter()
if not self.window_closed:
textbuffer.insert(iter, message+"\n")
def get_progress_bar(self, thread=None):
"""
Returns a progress bar object. access it as you
would normally and .destroy() it when done.
If thread!=None a box will be available to
kill the thread, too.
This doesn't work. Threads can't be killed :-(
"""
bar = ProgressOutput(self, self.user)
self.win.vbox.pack_start(bar, expand=False)
bar.show()
return bar
syntax highlighted by Code2HTML, v. 0.9.1