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'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import os, errno, sys, re
|
import os, errno, sys, re, time
|
||||||
from locale import localeconv
|
from locale import localeconv
|
||||||
from collections import OrderedDict, namedtuple
|
from collections import OrderedDict, namedtuple
|
||||||
from polyglot.builtins import iteritems, itervalues, string_or_bytes
|
from polyglot.builtins import iteritems, itervalues, string_or_bytes
|
||||||
@ -426,3 +426,76 @@ def type_safe_sort_key_function(keyfunc=None):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
return key
|
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>
|
# License: GPL v3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
from collections import deque
|
|
||||||
from qt.core import (
|
from qt.core import (
|
||||||
QCheckBox, QDialog, QDialogButtonBox, QHBoxLayout, QIcon, QLabel, QPushButton,
|
QCheckBox, QDialog, QDialogButtonBox, QHBoxLayout, QIcon, QLabel, QPushButton,
|
||||||
QRadioButton, QVBoxLayout, QWidget, pyqtSignal
|
QRadioButton, QVBoxLayout, QWidget, pyqtSignal
|
||||||
@ -13,60 +11,12 @@ from qt.core import (
|
|||||||
from calibre import detect_ncpus
|
from calibre import detect_ncpus
|
||||||
from calibre.db.cache import Cache
|
from calibre.db.cache import Cache
|
||||||
from calibre.db.listeners import EventType
|
from calibre.db.listeners import EventType
|
||||||
|
from calibre.db.utils import IndexingProgress
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.gui2.fts.utils import get_db
|
from calibre.gui2.fts.utils import get_db
|
||||||
from calibre.gui2.jobs import human_readable_interval
|
|
||||||
from calibre.gui2.ui import get_gui
|
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):
|
class ScanProgress(QWidget):
|
||||||
|
|
||||||
switch_to_search_panel = pyqtSignal()
|
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.threaded_jobs import ThreadedJobServer, ThreadedJob
|
||||||
from calibre.gui2.widgets2 import Dialog
|
from calibre.gui2.widgets2 import Dialog
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser, ParseException
|
from calibre.utils.search_query_parser import SearchQueryParser, ParseException
|
||||||
|
from calibre.db.utils import human_readable_interval
|
||||||
from calibre.utils.icu import lower
|
from calibre.utils.icu import lower
|
||||||
from polyglot.queue import Empty, Queue
|
from polyglot.queue import Empty, Queue
|
||||||
|
|
||||||
@ -40,30 +41,6 @@ class AdaptSQP(SearchQueryParser):
|
|||||||
pass
|
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): # {{{
|
class JobManager(QAbstractTableModel, AdaptSQP): # {{{
|
||||||
|
|
||||||
job_added = pyqtSignal(int)
|
job_added = pyqtSignal(int)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user