Make IndexingProgress useable outside the GUI modules

This commit is contained in:
Kovid Goyal 2022-08-06 13:13:23 +05:30
parent 86d180be4c
commit 81bf05e10b
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 76 additions and 76 deletions

View File

@ -4,7 +4,7 @@
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import os, errno, sys, re
import os, errno, sys, re, time
from locale import localeconv
from collections import OrderedDict, namedtuple
from polyglot.builtins import iteritems, itervalues, string_or_bytes
@ -426,3 +426,76 @@ def type_safe_sort_key_function(keyfunc=None):
return ans
return key
def human_readable_interval(secs):
secs = int(secs)
days = secs // 86400
hours = secs // 3600 % 24
minutes = secs // 60 % 60
seconds = secs % 60
parts = []
if days > 0:
parts.append(_('{} days').format(days))
if hours > 0:
parts.append(_('{} hours').format(hours))
elif hours > 0:
parts.append(_('{} hours').format(hours))
if minutes > 0:
parts.append(_('{} minutes').format(minutes))
elif minutes > 0:
parts.append(_('{} minutes').format(minutes))
if secs > 0:
parts.append(_('{} seconds').format(seconds))
elif secs > 0:
parts.append(_('{} seconds').format(seconds))
return ' '.join(parts)
class IndexingProgress:
def __init__(self):
self.left = self.total = -1
self.clear_rate_information()
def __repr__(self):
return f'IndexingProgress(left={self.left}, total={self.total})'
def clear_rate_information(self):
from collections import deque
self.done_events = deque()
def update(self, left, total):
changed = (left, total) != (self.left, self.total)
if changed:
done_num = self.left - left
if done_num > 0 and self.left > -1: # initial event will have self.left == -1
self.done_events.append((done_num, time.monotonic()))
if len(self.done_events) > 50:
self.done_events.popleft()
self.left, self.total = left, total
return changed
@property
def complete(self):
return not self.left or not self.total
@property
def almost_complete(self):
return self.complete or (self.left / self.total) < 0.1
@property
def time_left(self):
if self.left < 2:
return _('almost done')
if len(self.done_events) < 5:
return _('calculating time left')
try:
start_time = self.done_events[0][1]
end_time = self.done_events[-1][1]
num_done = sum(x[0] for x in self.done_events) - self.done_events[0][0]
rate = num_done / max(0.1, end_time - start_time)
seconds_left = self.left / rate
return _('~{} left').format(human_readable_interval(seconds_left))
except Exception:
return _('calculating time left')

View File

@ -3,8 +3,6 @@
# License: GPL v3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
import os
import time
from collections import deque
from qt.core import (
QCheckBox, QDialog, QDialogButtonBox, QHBoxLayout, QIcon, QLabel, QPushButton,
QRadioButton, QVBoxLayout, QWidget, pyqtSignal
@ -13,60 +11,12 @@ from qt.core import (
from calibre import detect_ncpus
from calibre.db.cache import Cache
from calibre.db.listeners import EventType
from calibre.db.utils import IndexingProgress
from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.gui2.fts.utils import get_db
from calibre.gui2.jobs import human_readable_interval
from calibre.gui2.ui import get_gui
class IndexingProgress:
def __init__(self):
self.left = self.total = -1
self.clear_rate_information()
def __repr__(self):
return f'IndexingProgress(left={self.left}, total={self.total})'
def clear_rate_information(self):
self.done_events = deque()
def update(self, left, total):
changed = (left, total) != (self.left, self.total)
if changed:
done_num = self.left - left
if done_num > 0 and self.left > -1: # initial event will have self.left == -1
self.done_events.append((done_num, time.monotonic()))
if len(self.done_events) > 50:
self.done_events.popleft()
self.left, self.total = left, total
return changed
@property
def complete(self):
return not self.left or not self.total
@property
def almost_complete(self):
return self.complete or (self.left / self.total) < 0.1
@property
def time_left(self):
if self.left < 2:
return _('almost done')
if len(self.done_events) < 5:
return _('calculating time left')
try:
start_time = self.done_events[0][1]
end_time = self.done_events[-1][1]
num_done = sum(x[0] for x in self.done_events) - self.done_events[0][0]
rate = num_done / max(0.1, end_time - start_time)
seconds_left = self.left / rate
return _('~{} left').format(human_readable_interval(seconds_left))
except Exception:
return _('calculating time left')
class ScanProgress(QWidget):
switch_to_search_panel = pyqtSignal()

View File

@ -30,6 +30,7 @@ from calibre.gui2.progress_indicator import ProgressIndicator
from calibre.gui2.threaded_jobs import ThreadedJobServer, ThreadedJob
from calibre.gui2.widgets2 import Dialog
from calibre.utils.search_query_parser import SearchQueryParser, ParseException
from calibre.db.utils import human_readable_interval
from calibre.utils.icu import lower
from polyglot.queue import Empty, Queue
@ -40,30 +41,6 @@ class AdaptSQP(SearchQueryParser):
pass
def human_readable_interval(secs):
secs = int(secs)
days = secs // 86400
hours = secs // 3600 % 24
minutes = secs // 60 % 60
seconds = secs % 60
parts = []
if days > 0:
parts.append(_('{} days').format(days))
if hours > 0:
parts.append(_('{} hours').format(hours))
elif hours > 0:
parts.append(_('{} hours').format(hours))
if minutes > 0:
parts.append(_('{} minutes').format(minutes))
elif minutes > 0:
parts.append(_('{} minutes').format(minutes))
if secs > 0:
parts.append(_('{} seconds').format(seconds))
elif secs > 0:
parts.append(_('{} seconds').format(seconds))
return ' '.join(parts)
class JobManager(QAbstractTableModel, AdaptSQP): # {{{
job_added = pyqtSignal(int)