More work on progress monitor.
svn: r8142
This commit is contained in:
parent
e197638418
commit
625fbee200
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
2007-02-17 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
|
||||
* src/ViewManager.py: add progress monitor
|
||||
* src/GrampsDb/_GrampsDbBase.py: add get_length to cursors
|
||||
* src/GrampsDb/_LongOpStatus.py: add __del__ method
|
||||
* src/GrampsDb/_ProgressMonitor.py: add class params
|
||||
* src/GrampsDb/_GrampsInMemDB.py: add get_length to cursors
|
||||
* src/GrampsDb/_CursorIterator.py: use get_length methods
|
||||
* src/GrampsDb/_GrampsBSDDB.py: add get_length to cursors
|
||||
* src/DisplayState.py: add progress monitor
|
||||
* src/DisplayModels/_PeopleModel.py: use LongOpStatus
|
||||
* src/ProgressDialog.py: fix show method
|
||||
|
||||
2007-02-17 Brian Matherly <brian@gramps-project.org>
|
||||
* src/ReportBase/_Report.py: remove unused progress bar functions
|
||||
|
||||
|
@ -65,6 +65,7 @@ import DateHandler
|
||||
import ToolTips
|
||||
import GrampsLocale
|
||||
import Config
|
||||
from GrampsDb import LongOpStatus
|
||||
from Filters import SearchFilter, ExactSearchFilter
|
||||
from Lru import LRU
|
||||
|
||||
@ -321,10 +322,11 @@ class PeopleModel(gtk.GenericTreeModel):
|
||||
|
||||
self.mapper.clear_sort_names()
|
||||
|
||||
cursor = self.db.get_person_cursor()
|
||||
node = cursor.first()
|
||||
#cursor = self.db.get_person_cursor()
|
||||
#node = cursor.first()
|
||||
|
||||
while node:
|
||||
#while node:
|
||||
for node in self.db.get_person_cursor_iter():
|
||||
handle, d = node
|
||||
if not (handle in skip or (dfilter and not dfilter.match(handle))):
|
||||
name_data = d[PeopleModel._NAME_COL]
|
||||
@ -333,8 +335,8 @@ class PeopleModel(gtk.GenericTreeModel):
|
||||
sorted_name = nsn(name_data)
|
||||
|
||||
self.mapper.assign_sort_name(handle, sorted_name, group_name)
|
||||
node = cursor.next()
|
||||
cursor.close()
|
||||
#node = cursor.next()
|
||||
#cursor.close()
|
||||
|
||||
def _build_filter_sub(self,dfilter, skip):
|
||||
|
||||
@ -348,7 +350,13 @@ class PeopleModel(gtk.GenericTreeModel):
|
||||
|
||||
self.mapper.clear_sort_names()
|
||||
|
||||
status = LongOpStatus(msg="Loading People",
|
||||
total_steps=len(handle_list),
|
||||
interval=len(handle_list)/10)
|
||||
self.db.emit('long-op-start', (status,))
|
||||
|
||||
for handle in handle_list:
|
||||
status.heartbeat()
|
||||
d = self.db.get_raw_person_data(handle)
|
||||
if not (handle in skip or (dfilter and not dfilter.match(handle))):
|
||||
name_data = d[PeopleModel._NAME_COL]
|
||||
@ -358,6 +366,8 @@ class PeopleModel(gtk.GenericTreeModel):
|
||||
|
||||
self.mapper.assign_sort_name(handle, sorted_name, group_name)
|
||||
|
||||
status.end()
|
||||
|
||||
def calculate_data(self, dfilter=None, skip=[]):
|
||||
"""
|
||||
Calculates the new path to node values for the model.
|
||||
|
@ -260,10 +260,12 @@ class DisplayState(GrampsDb.GrampsDBCallback):
|
||||
'plugins-reloaded' : (list,list),
|
||||
}
|
||||
|
||||
def __init__(self, window, status, progress, warnbtn, uimanager):
|
||||
def __init__(self, window, status, progress, warnbtn, uimanager,
|
||||
progress_monitor):
|
||||
|
||||
self.busy = False
|
||||
self.uimanager = uimanager
|
||||
self.progress_monitor = progress_monitor
|
||||
self.window = window
|
||||
GrampsDb.GrampsDBCallback.__init__(self)
|
||||
self.status = status
|
||||
@ -290,6 +292,7 @@ class DisplayState(GrampsDb.GrampsDBCallback):
|
||||
def db_changed(self, db):
|
||||
from PluginUtils import _PluginMgr
|
||||
self.relationship = _PluginMgr.relationship_class(db)
|
||||
db.connect('long-op-start', self.progress_monitor.add_op)
|
||||
|
||||
def display_relationship(self,dbstate):
|
||||
default_person = dbstate.db.get_default_person()
|
||||
|
@ -2,41 +2,41 @@ from _LongOpStatus import LongOpStatus
|
||||
|
||||
class CursorIterator(object):
|
||||
|
||||
def __init__(self,db,cursor):
|
||||
self._db = db
|
||||
self._cursor = cursor
|
||||
#self._status = LongOpStatus(total_steps=cursor.get_length(),interval=10)
|
||||
self._status = LongOpStatus()
|
||||
def __init__(self, db, cursor, msg=""):
|
||||
self._db = db
|
||||
self._cursor = cursor
|
||||
self._status = LongOpStatus(total_steps=cursor.get_length(), interval=10)
|
||||
#self._status = LongOpStatus(msg=msg)
|
||||
|
||||
def __iter__(self):
|
||||
try:
|
||||
# Emit start signal
|
||||
self._db.emit('long-op-start',(self._status,))
|
||||
|
||||
first = self._cursor.first()
|
||||
if first:
|
||||
yield first
|
||||
|
||||
next = self._cursor.next()
|
||||
while next:
|
||||
yield next
|
||||
|
||||
# check for cancel
|
||||
#if self._status.should_cancel():
|
||||
# raise GrampsDbUserCancel
|
||||
|
||||
# emit heartbeat
|
||||
self._status.heartbeat()
|
||||
next = self._cursor.next()
|
||||
|
||||
# emit stop signal
|
||||
self._status.end()
|
||||
self._cursor.close()
|
||||
raise StopIteration
|
||||
except:
|
||||
# Not allowed to use 'finally' because we
|
||||
# yeild inside the try clause.
|
||||
self._cursor.close()
|
||||
self._status_end()
|
||||
raise
|
||||
try:
|
||||
# Emit start signal
|
||||
self._db.emit('long-op-start', (self._status,))
|
||||
|
||||
first = self._cursor.first()
|
||||
if first:
|
||||
yield first
|
||||
|
||||
next = self._cursor.next()
|
||||
while next:
|
||||
yield next
|
||||
|
||||
# check for cancel
|
||||
#if self._status.should_cancel():
|
||||
# raise GrampsDbUserCancel
|
||||
|
||||
# emit heartbeat
|
||||
self._status.heartbeat()
|
||||
next = self._cursor.next()
|
||||
|
||||
# emit stop signal
|
||||
self._status.end()
|
||||
self._cursor.close()
|
||||
raise StopIteration
|
||||
except:
|
||||
# Not allowed to use 'finally' because we
|
||||
# yeild inside the try clause.
|
||||
self._cursor.close()
|
||||
self._status.end()
|
||||
raise
|
||||
|
||||
|
@ -75,6 +75,7 @@ class GrampsBSDDBCursor(GrampsCursor):
|
||||
|
||||
def __init__(self,source,txn=None):
|
||||
self.cursor = source.db.cursor(txn)
|
||||
self.source = source
|
||||
|
||||
def first(self):
|
||||
d = self.cursor.first()
|
||||
@ -93,11 +94,15 @@ class GrampsBSDDBCursor(GrampsCursor):
|
||||
|
||||
def delete(self):
|
||||
self.cursor.delete()
|
||||
|
||||
def get_length(self):
|
||||
return self.source.stat()['ndata']
|
||||
|
||||
class GrampsBSDDBAssocCursor(GrampsCursor):
|
||||
|
||||
def __init__(self,source,txn=None):
|
||||
self.cursor = source.cursor(txn)
|
||||
self.source = source
|
||||
|
||||
def first(self):
|
||||
d = self.cursor.first()
|
||||
@ -116,6 +121,9 @@ class GrampsBSDDBAssocCursor(GrampsCursor):
|
||||
|
||||
def delete(self):
|
||||
self.cursor.delete()
|
||||
|
||||
def get_length(self):
|
||||
return self.source.stat()['ndata']
|
||||
|
||||
class GrampsBSDDBDupCursor(GrampsBSDDBAssocCursor):
|
||||
"""Cursor that includes handling for duplicate keys"""
|
||||
|
@ -132,6 +132,14 @@ class GrampsCursor:
|
||||
finished using the cursor, freeing up the cursor's resources.
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_length(self):
|
||||
"""
|
||||
Returns the number of records in the table referenced by the
|
||||
cursor
|
||||
"""
|
||||
raise NotImplementedError, \
|
||||
"get_length must be implemented by all subclasses of GrampsCursor"
|
||||
|
||||
class GrampsDbBookmarks:
|
||||
def __init__(self, default = []):
|
||||
@ -346,44 +354,44 @@ class GrampsDbBase(GrampsDBCallback):
|
||||
def get_person_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_person_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_person_cursor())
|
||||
def get_person_cursor_iter(self, msg=_("Processing Person records")):
|
||||
return CursorIterator(self, self.get_person_cursor(), msg)
|
||||
|
||||
def get_family_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_family_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_family_cursor())
|
||||
def get_family_cursor_iter(self, msg=_("Processing Family records")):
|
||||
return CursorIterator(self, self.get_family_cursor(), msg)
|
||||
|
||||
def get_event_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_event_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_event_cursor())
|
||||
def get_event_cursor_iter(self, msg=_("Processing Event records")):
|
||||
return CursorIterator(self, self.get_event_cursor(), msg)
|
||||
|
||||
def get_place_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_place_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_place_cursor())
|
||||
def get_place_cursor_iter(self, msg=_("Processing Place records")):
|
||||
return CursorIterator(self, self.get_place_cursor(), msg)
|
||||
|
||||
def get_source_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_source_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_source_cursor())
|
||||
def get_source_cursor_iter(self, msg=_("Processing Source records")):
|
||||
return CursorIterator(self, self.get_source_cursor(), msg)
|
||||
|
||||
def get_media_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_media_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_media_cursor())
|
||||
def get_media_cursor_iter(self, msg=_("Processing Media records")):
|
||||
return CursorIterator(self, self.get_media_cursor(), msg)
|
||||
|
||||
def get_repository_cursor(self):
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def get_repository_cursor_iter(self):
|
||||
return CursorIterator(self,self.get_repository_cursor())
|
||||
def get_repository_cursor_iter(self, msg=_("Processing Repository records")):
|
||||
return CursorIterator(self, self.get_repository_cursor(), msg)
|
||||
|
||||
def open_undodb(self):
|
||||
if not self.readonly:
|
||||
|
@ -63,6 +63,9 @@ class GrampsInMemCursor(GrampsCursor):
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
def get_length(self):
|
||||
return len(self.src_map)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@ -91,7 +91,12 @@ class LongOpStatus(GrampsDBCallback):
|
||||
self._countdown = interval
|
||||
self._secs_left = 0
|
||||
self._start = time.time()
|
||||
self._running = True
|
||||
|
||||
def __del__(self):
|
||||
if self._running:
|
||||
self.emit('op-end')
|
||||
|
||||
def heartbeat(self):
|
||||
"""This should be called for each step in the operation. It will
|
||||
emit a 'op-heartbeat' every 'interval' steps. It recalcuates the
|
||||
@ -128,6 +133,7 @@ class LongOpStatus(GrampsDBCallback):
|
||||
"""End the operation. Causes the 'op-end' signal to be emitted.
|
||||
"""
|
||||
self.emit('op-end')
|
||||
self._running = False
|
||||
|
||||
def should_cancel(self):
|
||||
"""Returns true of the user has asked for the operation to be cancelled.
|
||||
|
@ -2,6 +2,10 @@
|
||||
This module provides a progess dialog for displaying the status of
|
||||
long running operations.
|
||||
"""
|
||||
import logging
|
||||
log = logging.getLogger(".GrampsDb")
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
class _StatusObjectFacade(object):
|
||||
"""This provides a simple structure for recording the information
|
||||
@ -36,15 +40,27 @@ class ProgressMonitor(object):
|
||||
|
||||
__default_popup_time = 5 # seconds
|
||||
|
||||
def __init__(self, dialog_class, popup_time = None):
|
||||
def __init__(self, dialog_class, dialog_class_params=(),
|
||||
title=_("Progress Information"),
|
||||
popup_time = None):
|
||||
"""
|
||||
@param dialog_class: A class used to display the progress dialog.
|
||||
@type dialog_class: L{_GtkProgressDialog} or the same interface.
|
||||
|
||||
@param dialog_class_params: A tuple that will be used as the initial
|
||||
arguments to the dialog_class, this might be used for passing in
|
||||
a parent window handle.
|
||||
@type dialog_class_params: tuple
|
||||
|
||||
@param title: The title of the progress dialog
|
||||
@type title: string
|
||||
|
||||
@param popup_time: number of seconds to wait before popup.
|
||||
@type popup_time: int
|
||||
"""
|
||||
self._dialog_class = dialog_class
|
||||
self._dialog_class_params = dialog_class_params
|
||||
self._title = title
|
||||
self._popup_time = popup_time
|
||||
|
||||
if self._popup_time == None:
|
||||
@ -55,8 +71,10 @@ class ProgressMonitor(object):
|
||||
|
||||
def _get_dlg(self):
|
||||
if self._dlg == None:
|
||||
self._dlg = self._dialog_class("Long running operation.")
|
||||
self._dlg.show()
|
||||
self._dlg = self._dialog_class(self._dialog_class_params,
|
||||
self._title)
|
||||
|
||||
self._dlg.show()
|
||||
|
||||
return self._dlg
|
||||
|
||||
@ -66,6 +84,8 @@ class ProgressMonitor(object):
|
||||
@param op_status: the status object.
|
||||
@type op_status: L{GrampsDb.LongOpStatus}
|
||||
"""
|
||||
|
||||
log.debug("adding op to Progress Monitor")
|
||||
facade = _StatusObjectFacade(op_status)
|
||||
self._status_stack.append(facade)
|
||||
idx = len(self._status_stack)-1
|
||||
@ -84,6 +104,8 @@ class ProgressMonitor(object):
|
||||
# check the estimated time to complete to see if we need
|
||||
# to pop up a progress dialog.
|
||||
|
||||
log.debug("heartbeat in ProgressMonitor")
|
||||
|
||||
facade = self._status_stack[idx]
|
||||
|
||||
if facade.status_obj.estimated_secs_to_complete() > self._popup_time:
|
||||
@ -100,6 +122,8 @@ class ProgressMonitor(object):
|
||||
def _end(self, idx):
|
||||
# hide any progress dialog
|
||||
# remove the status object from the stack
|
||||
|
||||
log.debug("received end in ProgressMonitor")
|
||||
facade = self._status_stack[idx]
|
||||
if facade.active:
|
||||
dlg = self._get_dlg()
|
||||
@ -119,7 +143,7 @@ if __name__ == '__main__':
|
||||
from GrampsDb import LongOpStatus
|
||||
|
||||
def test(a,b):
|
||||
d = ProgressDialog(_GtkProgressDialog)
|
||||
d = ProgressDialog(_GtkProgressDialog, "Test Progress")
|
||||
|
||||
s = LongOpStatus("Doing very long operation", 100, 10)
|
||||
|
||||
|
@ -43,8 +43,8 @@ class _GtkProgressBar(gtk.VBox):
|
||||
self._pbar_max = (long_op_status.get_total_steps()/
|
||||
long_op_status.get_interval())
|
||||
self._pbar_index = 0.0
|
||||
self._pbar.set_fraction((float(long_op_status.get_total_steps())/
|
||||
(float(long_op_status.get_interval())))/
|
||||
self._pbar.set_fraction(((100/float(long_op_status.get_total_steps())*
|
||||
float(long_op_status.get_interval())))/
|
||||
100.0)
|
||||
|
||||
if msg != '':
|
||||
@ -70,15 +70,15 @@ class _GtkProgressBar(gtk.VBox):
|
||||
self._pbar.set_fraction(val/100.0)
|
||||
self._pbar.old_val = val
|
||||
|
||||
class _GtkProgressDialog(gtk.Dialog):
|
||||
class GtkProgressDialog(gtk.Dialog):
|
||||
"""A gtk window to display the status of a long running
|
||||
process."""
|
||||
|
||||
def __init__(self, title):
|
||||
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)
|
||||
gtk.Dialog.__init__(self, *window_params)
|
||||
self.connect('delete_event', self._warn)
|
||||
self.set_has_separator(False)
|
||||
self.set_title(title)
|
||||
@ -162,7 +162,7 @@ if __name__ == '__main__':
|
||||
from GrampsDb import LongOpStatus, ProgressMonitor
|
||||
|
||||
def test(a,b):
|
||||
d = ProgressMonitor(_GtkProgressDialog)
|
||||
d = ProgressMonitor(GtkProgressDialog)
|
||||
|
||||
s = LongOpStatus("Doing very long operation", 100, 10)
|
||||
|
||||
|
@ -78,6 +78,8 @@ import GrampsWidgets
|
||||
import UndoHistory
|
||||
from DbLoader import DbLoader
|
||||
import GrampsDisplay
|
||||
from GrampsDb import ProgressMonitor
|
||||
import ProgressDialog
|
||||
|
||||
def show_url(dialog,link,user_data):
|
||||
GrampsDisplay.url(link)
|
||||
@ -245,6 +247,8 @@ class ViewManager:
|
||||
vbox.pack_start(self.menubar, False)
|
||||
vbox.pack_start(self.toolbar, False)
|
||||
vbox.add(hbox)
|
||||
self.progress_monitor = ProgressMonitor(ProgressDialog.GtkProgressDialog,
|
||||
("",self.window))
|
||||
self.progress = gtk.ProgressBar()
|
||||
self.progress.set_size_request(100, -1)
|
||||
self.progress.hide()
|
||||
@ -262,7 +266,7 @@ class ViewManager:
|
||||
|
||||
self.uistate = DisplayState.DisplayState(
|
||||
self.window, self.statusbar, self.progress, self.warnbtn,
|
||||
self.uimanager)
|
||||
self.uimanager, self.progress_monitor)
|
||||
self.state.connect('database-changed', self.uistate.db_changed)
|
||||
|
||||
toolbar = self.uimanager.get_widget('/ToolBar')
|
||||
|
Loading…
Reference in New Issue
Block a user