drop the DB progress handler code

This code was an awful hack to provide some semblance of UI
responsiveness while executing DB statements on the main thread.
Instead, we can just run DB statements in a background thread now,
keeping the UI responsive.
This commit is contained in:
Damien Elmes 2020-03-06 13:21:24 +10:00
parent 90d4d62c48
commit 0f38514ad7
4 changed files with 6 additions and 46 deletions

View file

@ -9,10 +9,6 @@ import anki
# fixme: col.close()/col.reopen() & journal_mode=delete # fixme: col.close()/col.reopen() & journal_mode=delete
# fixme: setAutocommit()
# fixme: transaction/lock handling
# fixme: progress
# DBValue is actually Union[str, int, float, None], but if defined # DBValue is actually Union[str, int, float, None], but if defined
# that way, every call site needs to do a type check prior to using # that way, every call site needs to do a type check prior to using
# the return values. # the return values.

View file

@ -391,15 +391,12 @@ class StatusDelegate(QItemDelegate):
self.model = model self.model = model
def paint(self, painter, option, index): def paint(self, painter, option, index):
self.browser.mw.progress.blockUpdates = True
try: try:
c = self.model.getCard(index) c = self.model.getCard(index)
except: except:
# in the the middle of a reset; return nothing so this row is not # in the the middle of a reset; return nothing so this row is not
# rendered until we have a chance to reset the model # rendered until we have a chance to reset the model
return return
finally:
self.browser.mw.progress.blockUpdates = True
if self.model.isRTL(index): if self.model.isRTL(index):
option.direction = Qt.RightToLeft option.direction = Qt.RightToLeft

View file

@ -463,7 +463,6 @@ close the profile or restart Anki."""
self.col = Collection(cpath) self.col = Collection(cpath)
self.setEnabled(True) self.setEnabled(True)
self.progress.setupDB(self.col.db)
self.maybeEnableUndo() self.maybeEnableUndo()
self.moveToState("deckBrowser") self.moveToState("deckBrowser")
return True return True
@ -1531,7 +1530,6 @@ Please ensure a profile is open and Anki is not busy, then try again."""
gc.disable() gc.disable()
def doGC(self) -> None: def doGC(self) -> None:
assert not self.progress.inDB
gc.collect() gc.collect()
# Crash log # Crash log

View file

@ -11,10 +11,6 @@ import aqt.forms
from anki.lang import _ from anki.lang import _
from aqt.qt import * from aqt.qt import *
# fixme: if mw->subwindow opens a progress dialog with mw as the parent, mw
# gets raised on finish on compiz. perhaps we should be using the progress
# dialog as the parent?
# Progress info # Progress info
########################################################################## ##########################################################################
@ -29,44 +25,14 @@ class ProgressManager:
self._win = None self._win = None
self._levels = 0 self._levels = 0
# SQLite progress handler
##########################################################################
def setupDB(self, db):
"Install a handler in the current DB."
self.lastDbProgress = 0
self.inDB = False
# db.set_progress_handler(self._dbProgress, 10000)
def _dbProgress(self):
"Called from SQLite."
# do nothing if we don't have a progress window
if not self._win:
return
# make sure we're not executing too frequently
if (time.time() - self.lastDbProgress) < 0.01:
return
self.lastDbProgress = time.time()
# and we're in the main thread
if not self.mw.inMainThread():
return
# ensure timers don't fire
self.inDB = True
# handle GUI events
if not self.blockUpdates:
self._maybeShow()
self.app.processEvents(QEventLoop.ExcludeUserInputEvents)
self.inDB = False
# Safer timers # Safer timers
########################################################################## ##########################################################################
# QTimer may fire in processEvents(). We provide a custom timer which # A custom timer which avoids firing while a progress dialog is active
# automatically defers until the DB is not busy, and avoids running # (likely due to some long-running DB operation)
# while a progress window is visible.
def timer(self, ms, func, repeat, requiresCollection=True): def timer(self, ms, func, repeat, requiresCollection=True):
def handler(): def handler():
if self.inDB or self._levels: if self._levels:
# retry in 100ms # retry in 100ms
self.timer(100, func, False, requiresCollection) self.timer(100, func, False, requiresCollection)
elif not self.mw.col and requiresCollection: elif not self.mw.col and requiresCollection:
@ -123,6 +89,9 @@ class ProgressManager:
def update(self, label=None, value=None, process=True, maybeShow=True): def update(self, label=None, value=None, process=True, maybeShow=True):
# print self._min, self._counter, self._max, label, time.time() - self._lastTime # print self._min, self._counter, self._max, label, time.time() - self._lastTime
if not self.mw.inMainThread():
print("progress.update() called on wrong thread")
return
if self._updating: if self._updating:
return return
if maybeShow: if maybeShow: