Refinements to ProgressMeter and ProgressMonitor for cancelling

svn: r13720
This commit is contained in:
Doug Blank 2009-12-06 01:16:17 +00:00
parent e091da41de
commit ca061d3607
2 changed files with 63 additions and 16 deletions

View File

@ -101,11 +101,12 @@ class GtkProgressDialog(gtk.Dialog):
self.vbox.pack_start(pbar, expand=False, fill=False) self.vbox.pack_start(pbar, expand=False, fill=False)
pbar.show() pbar.show()
# this seems to cause an infinite loop:
self.resize_children() #self.resize_children()
self._process_events()
self._progress_bars.append(pbar) self._progress_bars.append(pbar)
# This is a bad idea; could cause deletes while adding:
#self._process_events()
return len(self._progress_bars)-1 return len(self._progress_bars)-1
def remove(self, pbar_idx): def remove(self, pbar_idx):
@ -114,9 +115,10 @@ class GtkProgressDialog(gtk.Dialog):
:param pbar_idx: the index as returned from L{add} :param pbar_idx: the index as returned from L{add}
:type pbar_idx: int :type pbar_idx: int
""" """
pbar = self._progress_bars[pbar_idx] if pbar_idx is not None:
self.vbox.remove(pbar) pbar = self._progress_bars[pbar_idx]
del self._progress_bars[pbar_idx] self.vbox.remove(pbar)
del self._progress_bars[pbar_idx]
def step(self, pbar_idx): def step(self, pbar_idx):
"""Click the progress bar over to the next value. Be paranoid """Click the progress bar over to the next value. Be paranoid
@ -158,31 +160,41 @@ if __name__ == '__main__':
def test(a, b): def test(a, b):
d = ProgressMonitor(GtkProgressDialog) d = ProgressMonitor(GtkProgressDialog)
s = LongOpStatus("Doing very long operation", 100, 10) s = LongOpStatus("Doing very long operation", 100, 10, can_cancel=True)
d.add_op(s) d.add_op(s)
for i in xrange(0, 99): for i in xrange(0, 99):
if s.should_cancel():
break
time.sleep(0.1) time.sleep(0.1)
if i == 30: if i == 30:
t = LongOpStatus("doing a shorter one", 100, 10, t = LongOpStatus("doing a shorter one", 100, 10,
can_cancel=True) can_cancel=True)
d.add_op(t) d.add_op(t)
for j in xrange(0, 99): for j in xrange(0, 99):
if s.should_cancel():
t.cancel()
break
if t.should_cancel(): if t.should_cancel():
break break
time.sleep(0.1) time.sleep(0.1)
t.heartbeat() t.heartbeat()
t.end() if not t.was_cancelled():
t.end()
if i == 60: if i == 60:
t = LongOpStatus("doing another shorter one", 100, 10) t = LongOpStatus("doing another shorter one", 100, 10)
d.add_op(t) d.add_op(t)
for j in xrange(0, 99): for j in xrange(0, 99):
if s.should_cancel():
t.cancel()
break
time.sleep(0.1) time.sleep(0.1)
t.heartbeat() t.heartbeat()
t.end() t.end()
s.heartbeat() s.heartbeat()
s.end() if not s.was_cancelled():
s.end()
w = gtk.Window(gtk.WINDOW_TOPLEVEL) w = gtk.Window(gtk.WINDOW_TOPLEVEL)
w.connect('destroy', gtk.main_quit) w.connect('destroy', gtk.main_quit)

View File

@ -88,7 +88,8 @@ class ProgressMeter(object):
MODE_FRACTION = 0 MODE_FRACTION = 0
MODE_ACTIVITY = 1 MODE_ACTIVITY = 1
def __init__(self, title, header=''): def __init__(self, title, header='', can_cancel=False,
cancel_callback=None):
""" """
Specify the title and the current pass header. Specify the title and the current pass header.
""" """
@ -97,9 +98,18 @@ class ProgressMeter(object):
self.__pbar_max = 100.0 self.__pbar_max = 100.0
self.__pbar_index = 0.0 self.__pbar_index = 0.0
self.__old_val = -1 self.__old_val = -1
self.__can_cancel = can_cancel
self.__cancelled = False
if cancel_callback:
self.__cancel_callback = cancel_callback
else:
self.__cancel_callback = self.handle_cancel
self.__dialog = gtk.Dialog() self.__dialog = gtk.Dialog()
self.__dialog.connect('delete_event', self.__warn) if self.__can_cancel:
self.__dialog.connect('delete_event', self.__cancel_callback)
else:
self.__dialog.connect('delete_event', self.__warn)
self.__dialog.set_has_separator(False) self.__dialog.set_has_separator(False)
self.__dialog.set_title(title) self.__dialog.set_title(title)
self.__dialog.set_border_width(12) self.__dialog.set_border_width(12)
@ -117,11 +127,32 @@ class ProgressMeter(object):
self.__pbar = gtk.ProgressBar() self.__pbar = gtk.ProgressBar()
self.__dialog.vbox.add(self.__pbar) self.__dialog.vbox.add(self.__pbar)
if self.__can_cancel:
self.__dialog.set_size_request(350, 170)
self.__cancel_button = gtk.Button(stock=gtk.STOCK_CANCEL)
self.__cancel_button.connect('clicked', self.__cancel_callback)
self.__dialog.vbox.add(self.__cancel_button)
self.__dialog.show_all() self.__dialog.show_all()
if header == '': if header == '':
self.__lbl.hide() self.__lbl.hide()
def handle_cancel(self, *args, **kwargs):
"""
Default cancel handler (if enabled).
"""
self.__cancel_button.set_sensitive(False)
self.__lbl.set_label(_("Cancelling..."))
self.__cancelled = True
def get_cancelled(self):
"""
Returns cancelled setting. True if progress meter has been
cancelled.
"""
return self.__cancelled
def set_pass(self, header="", total=100, mode=MODE_FRACTION): def set_pass(self, header="", total=100, mode=MODE_FRACTION):
""" """
Reset for another pass. Provide a new header and define number Reset for another pass. Provide a new header and define number
@ -132,11 +163,13 @@ class ProgressMeter(object):
self.__pbar_max = total self.__pbar_max = total
self.__pbar_index = 0.0 self.__pbar_index = 0.0
self.__lbl.set_text(header) # If it is cancelling, don't overwite that message:
if header == '': if not self.__cancelled:
self.__lbl.hide() self.__lbl.set_text(header)
else: if header == '':
self.__lbl.show() self.__lbl.hide()
else:
self.__lbl.show()
if self.__mode is ProgressMeter.MODE_FRACTION: if self.__mode is ProgressMeter.MODE_FRACTION:
self.__pbar.set_fraction(0.0) self.__pbar.set_fraction(0.0)
@ -171,6 +204,8 @@ class ProgressMeter(object):
while gtk.events_pending(): while gtk.events_pending():
gtk.main_iteration() gtk.main_iteration()
return self.__cancelled
def set_header(self, text): def set_header(self, text):
self.__lbl.set_text(text) self.__lbl.set_text(text)
while gtk.events_pending(): while gtk.events_pending():