mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make IndexingProgress useable outside the GUI modules
This commit is contained in:
parent
86d180be4c
commit
81bf05e10b
@ -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')
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user