mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
move away from qprogressdialog
qprogressdialog has been the source of a number of problems in the past, and the most recent issue is that it's showing the progress dialog early, regardless of what the minimum duration is set to. since we're already using our own logic for deciding when to show the dialog, it's easier to move to a normal dialog box also prevent timers from firing while a progress dialog is visible, or if the refresh timer fires we end up with the same issue. https://anki.tenderapp.com/discussions/beta-testing/949-anki-stops-when-field-is-added
This commit is contained in:
parent
ab46a4530c
commit
5ad8f67f12
3 changed files with 105 additions and 34 deletions
|
@ -4,6 +4,7 @@
|
|||
|
||||
import time
|
||||
from aqt.qt import *
|
||||
import aqt.forms
|
||||
|
||||
# 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
|
||||
|
@ -51,14 +52,15 @@ class ProgressManager:
|
|||
self.app.processEvents(QEventLoop.ExcludeUserInputEvents)
|
||||
self.inDB = False
|
||||
|
||||
# DB-safe timers
|
||||
# Safer timers
|
||||
##########################################################################
|
||||
# QTimer may fire in processEvents(). We provide a custom timer which
|
||||
# automatically defers until the DB is not busy.
|
||||
# automatically defers until the DB is not busy, and avoids running
|
||||
# while a progress window is visible.
|
||||
|
||||
def timer(self, ms, func, repeat):
|
||||
def handler():
|
||||
if self.inDB:
|
||||
if self.inDB or self._levels:
|
||||
# retry in 100ms
|
||||
self.timer(100, func, False)
|
||||
else:
|
||||
|
@ -73,27 +75,31 @@ class ProgressManager:
|
|||
# Creating progress dialogs
|
||||
##########################################################################
|
||||
|
||||
class ProgressNoCancel(QProgressDialog):
|
||||
class ProgressDialog(QDialog):
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent)
|
||||
self.form = aqt.forms.progress.Ui_Dialog()
|
||||
self.form.setupUi(self)
|
||||
self._closingDown = False
|
||||
self.wantCancel = False
|
||||
|
||||
def cancel(self):
|
||||
self._closingDown = True
|
||||
self.close()
|
||||
|
||||
def closeEvent(self, evt):
|
||||
if self._closingDown:
|
||||
evt.accept()
|
||||
else:
|
||||
self.wantCancel = True
|
||||
evt.ignore()
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
if evt.key() == Qt.Key_Escape:
|
||||
evt.ignore()
|
||||
self.wantCancel = True
|
||||
|
||||
class ProgressCancellable(QProgressDialog):
|
||||
def __init__(self, *args, **kwargs):
|
||||
QProgressDialog.__init__(self, *args, **kwargs)
|
||||
self.ankiCancel = False
|
||||
def closeEvent(self, evt):
|
||||
# avoid standard Qt flag as we don't want to close until we're ready
|
||||
self.ankiCancel = True
|
||||
evt.ignore()
|
||||
def keyPressEvent(self, evt):
|
||||
if evt.key() == Qt.Key_Escape:
|
||||
evt.ignore()
|
||||
self.ankiCancel = True
|
||||
|
||||
def start(self, max=0, min=0, label=None, parent=None, immediate=False, cancellable=False):
|
||||
def start(self, max=0, min=0, label=None, parent=None, immediate=False):
|
||||
self._levels += 1
|
||||
if self._levels > 1:
|
||||
return
|
||||
|
@ -103,20 +109,13 @@ class ProgressManager:
|
|||
parent = self.mw
|
||||
|
||||
label = label or _("Processing...")
|
||||
if cancellable:
|
||||
klass = self.ProgressCancellable
|
||||
else:
|
||||
klass = self.ProgressNoCancel
|
||||
self._win = klass(label, "", min, max, parent)
|
||||
self._win = self.ProgressDialog(parent)
|
||||
self._win.form.progressBar.setMinimum(min)
|
||||
self._win.form.progressBar.setMaximum(max)
|
||||
self._win.form.label.setText(label)
|
||||
self._win.setWindowTitle("Anki")
|
||||
self._win.setCancelButton(None)
|
||||
self._win.setAutoClose(False)
|
||||
self._win.setAutoReset(False)
|
||||
self._win.setWindowModality(Qt.ApplicationModal)
|
||||
self._win.setMinimumWidth(300)
|
||||
# we need to manually manage minimum time to show, as qt gets confused
|
||||
# by the db handler
|
||||
self._win.setMinimumDuration(100000)
|
||||
if immediate:
|
||||
self._showWin()
|
||||
else:
|
||||
|
@ -137,10 +136,10 @@ class ProgressManager:
|
|||
self._maybeShow()
|
||||
elapsed = time.time() - self._lastUpdate
|
||||
if label:
|
||||
self._win.setLabelText(label)
|
||||
self._win.form.label.setText(label)
|
||||
if self._max and self._shown:
|
||||
self._counter = value or (self._counter+1)
|
||||
self._win.setValue(self._counter)
|
||||
self._win.form.progressBar.setValue(self._counter)
|
||||
if process and elapsed >= 0.2:
|
||||
self._updating = True
|
||||
self.app.processEvents(QEventLoop.ExcludeUserInputEvents)
|
||||
|
@ -172,6 +171,7 @@ class ProgressManager:
|
|||
def _showWin(self):
|
||||
self._shown = time.time()
|
||||
self._win.show()
|
||||
self._win.adjustSize()
|
||||
self._setBusy()
|
||||
|
||||
def _closeWin(self):
|
||||
|
@ -186,6 +186,7 @@ class ProgressManager:
|
|||
break
|
||||
self.app.processEvents(QEventLoop.ExcludeUserInputEvents)
|
||||
self._win.cancel()
|
||||
self._win = None
|
||||
self._unsetBusy()
|
||||
|
||||
def _setBusy(self):
|
||||
|
|
|
@ -46,12 +46,12 @@ class SyncManager(QObject):
|
|||
auth=auth, media=self.pm.profile['syncMedia'])
|
||||
t.event.connect(self.onEvent)
|
||||
self.label = _("Connecting...")
|
||||
prog = self.mw.progress.start(immediate=True, label=self.label, cancellable=True)
|
||||
prog = self.mw.progress.start(immediate=True, label=self.label)
|
||||
self.sentBytes = self.recvBytes = 0
|
||||
self._updateLabel()
|
||||
self.thread.start()
|
||||
while not self.thread.isFinished():
|
||||
if prog.ankiCancel:
|
||||
if prog.wantCancel:
|
||||
self.thread.flagAbort()
|
||||
# make sure we don't display 'upload success' msg
|
||||
self._didFullUp = False
|
||||
|
|
70
designer/progress.ui
Normal file
70
designer/progress.ui
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>310</width>
|
||||
<height>69</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in a new issue