gramps/src/ProgressDialog.py
2007-12-16 15:28:33 +00:00

197 lines
6.0 KiB
Python

"""
This module provides a progess dialog for displaying the status of
long running operations.
"""
import gtk
class _GtkProgressBar(gtk.VBox):
"""This widget displays the progress bar and labels for a progress
indicator. It provides an interface to updating the progress bar.
"""
def __init__(self, long_op_status):
"""@param long_op_status: the status of the operation.
@type long_op_status: L{gen.utils.LongOpStatus}
"""
gtk.VBox.__init__(self)
msg = long_op_status.get_msg()
self._old_val = -1
self._lbl = gtk.Label(msg)
self._lbl.set_use_markup(True)
#self.set_border_width(24)
self._pbar = gtk.ProgressBar()
self._hbox = gtk.HBox()
# Only display the cancel button is the operation
# can be canceled.
if long_op_status.can_cancel():
self._cancel = gtk.Button(stock=gtk.STOCK_CANCEL)
self._cancel.connect("clicked",
lambda x: long_op_status.cancel())
self._cancel.show()
self._hbox.pack_end(self._cancel)
self._hbox.pack_start(self._pbar)
self.pack_start(self._lbl, expand=False, fill=False)
self.pack_start(self._hbox, expand=False, fill=False)
self._pbar_max = (long_op_status.get_total_steps()/
long_op_status.get_interval())
self._pbar_index = 0.0
self._pbar.set_fraction(((100/float(long_op_status.get_total_steps())*
float(long_op_status.get_interval())))/
100.0)
if msg != '':
self._lbl.show()
self._pbar.show()
self._hbox.show()
def step(self):
"""Move the progress bar on a step.
"""
self._pbar_index = self._pbar_index + 1.0
if self._pbar_index > self._pbar_max:
self._pbar_index = self._pbar_max
try:
val = int(100*self._pbar_index/self._pbar_max)
except ZeroDivisionError:
val = 0
if val != self._old_val:
self._pbar.set_text("%d%%" % val)
self._pbar.set_fraction(val/100.0)
self._pbar.old_val = val
class GtkProgressDialog(gtk.Dialog):
"""A gtk window to display the status of a long running
process."""
def __init__(self, window_params, title):
"""@param title: The title to display on the top of the window.
@type title: string
"""
gtk.Dialog.__init__(self, *window_params)
self.connect('delete_event', self._warn)
self.set_has_separator(False)
self.set_title(title)
#self.set_resize_mode(gtk.RESIZE_IMMEDIATE)
#self.show()
self._progress_bars = []
def add(self, long_op_status):
"""Add a new status object to the progress dialog.
@param long_op_status: the status object.
@type long_op_status: L{gen.utils.LongOpStatus}
@return: a key that can be used as the L{pbar_idx}
to the other methods.
@rtype: int
"""
pbar = _GtkProgressBar(long_op_status)
self.vbox.pack_start(pbar, expand=False, fill=False)
pbar.show()
self.resize_children()
self._process_events()
self._progress_bars.append(pbar)
return len(self._progress_bars)-1
def remove(self, pbar_idx):
"""Remove the specified status object from the progress dialog.
@param pbar_idx: the index as returned from L{add}
@type pbar_idx: int
"""
pbar = self._progress_bars[pbar_idx]
self.vbox.remove(pbar)
del self._progress_bars[pbar_idx]
def step(self, pbar_idx):
"""Click the progress bar over to the next value. Be paranoid
and insure that it doesn't go over 100%.
@param pbar_idx: the index as returned from L{add}
@type pbar_idx: int
"""
if pbar_idx < len(self._progress_bars):
self._progress_bars[pbar_idx].step()
self._process_events()
def _process_events(self):
while gtk.events_pending():
gtk.main_iteration()
def show(self):
"""Show the dialog and process any events.
"""
gtk.Dialog.show(self)
self._process_events()
def hide(self):
"""Hide the dialog and process any events.
"""
gtk.Dialog.hide(self)
self._process_events()
def _warn(self, x, y):
return True
def close(self):
self.destroy()
if __name__ == '__main__':
import time
from gen.utils import LongOpStatus, ProgressMonitor
def test(a, b):
d = ProgressMonitor(GtkProgressDialog)
s = LongOpStatus("Doing very long operation", 100, 10)
d.add_op(s)
for i in xrange(0, 99):
time.sleep(0.1)
if i == 30:
t = LongOpStatus("doing a shorter one", 100, 10,
can_cancel=True)
d.add_op(t)
for j in xrange(0, 99):
if t.should_cancel():
break
time.sleep(0.1)
t.heartbeat()
t.end()
if i == 60:
t = LongOpStatus("doing another shorter one", 100, 10)
d.add_op(t)
for j in xrange(0, 99):
time.sleep(0.1)
t.heartbeat()
t.end()
s.heartbeat()
s.end()
w = gtk.Window(gtk.WINDOW_TOPLEVEL)
w.connect('destroy', gtk.main_quit)
button = gtk.Button("Test")
button.connect("clicked", test, None)
w.add(button)
button.show()
w.show()
gtk.main()
print 'done'