Batch download redrawings/updates.
This commit is contained in:
parent
4a4856c176
commit
1e5e6a63a5
@ -49,6 +49,11 @@ ModelRole = usertypes.enum('ModelRole', ['item'], start=Qt.UserRole,
|
|||||||
RetryInfo = collections.namedtuple('RetryInfo', ['request', 'manager'])
|
RetryInfo = collections.namedtuple('RetryInfo', ['request', 'manager'])
|
||||||
|
|
||||||
|
|
||||||
|
# All REFRESH_INTERVAL milliseconds, speeds will be recalculated and downloads
|
||||||
|
# redrawn.
|
||||||
|
REFRESH_INTERVAL = 500
|
||||||
|
|
||||||
|
|
||||||
def _download_dir():
|
def _download_dir():
|
||||||
"""Get the download directory to use."""
|
"""Get the download directory to use."""
|
||||||
directory = config.get('storage', 'download-directory')
|
directory = config.get('storage', 'download-directory')
|
||||||
@ -80,7 +85,6 @@ class DownloadItemStats(QObject):
|
|||||||
"""Statistics (bytes done, total bytes, time, etc.) about a download.
|
"""Statistics (bytes done, total bytes, time, etc.) about a download.
|
||||||
|
|
||||||
Class attributes:
|
Class attributes:
|
||||||
SPEED_REFRESH_INTERVAL: How often to refresh the speed, in msec.
|
|
||||||
SPEED_AVG_WINDOW: How many seconds of speed data to average to
|
SPEED_AVG_WINDOW: How many seconds of speed data to average to
|
||||||
estimate the remaining time.
|
estimate the remaining time.
|
||||||
|
|
||||||
@ -93,37 +97,29 @@ class DownloadItemStats(QObject):
|
|||||||
the speed the last time.
|
the speed the last time.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
SPEED_REFRESH_INTERVAL = 500
|
|
||||||
SPEED_AVG_WINDOW = 30
|
SPEED_AVG_WINDOW = 30
|
||||||
|
|
||||||
updated = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.total = None
|
self.total = None
|
||||||
self.done = 0
|
self.done = 0
|
||||||
self.speed = 0
|
self.speed = 0
|
||||||
self._last_done = 0
|
self._last_done = 0
|
||||||
samples = int(self.SPEED_AVG_WINDOW *
|
samples = int(self.SPEED_AVG_WINDOW * (1000 / REFRESH_INTERVAL))
|
||||||
(1000 / self.SPEED_REFRESH_INTERVAL))
|
|
||||||
self._speed_avg = collections.deque(maxlen=samples)
|
self._speed_avg = collections.deque(maxlen=samples)
|
||||||
self.timer = usertypes.Timer(self, 'speed_refresh')
|
|
||||||
self.timer.timeout.connect(self._update_speed)
|
|
||||||
self.timer.setInterval(self.SPEED_REFRESH_INTERVAL)
|
|
||||||
self.timer.start()
|
|
||||||
|
|
||||||
@pyqtSlot()
|
def update_speed(self):
|
||||||
def _update_speed(self):
|
"""Recalculate the current download speed.
|
||||||
"""Recalculate the current download speed."""
|
|
||||||
|
The caller needs to guarantee this is called all REFRESH_INTERVAL ms.
|
||||||
|
"""
|
||||||
delta = self.done - self._last_done
|
delta = self.done - self._last_done
|
||||||
self.speed = delta * 1000 / self.SPEED_REFRESH_INTERVAL
|
self.speed = delta * 1000 / REFRESH_INTERVAL
|
||||||
self._speed_avg.append(self.speed)
|
self._speed_avg.append(self.speed)
|
||||||
self._last_done = self.done
|
self._last_done = self.done
|
||||||
self.updated.emit()
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
"""Set the download stats as finished."""
|
"""Set the download stats as finished."""
|
||||||
self.timer.stop()
|
|
||||||
self.done = self.total
|
self.done = self.total
|
||||||
|
|
||||||
def percentage(self):
|
def percentage(self):
|
||||||
@ -230,7 +226,6 @@ class DownloadItem(QObject):
|
|||||||
self.retry_info = None
|
self.retry_info = None
|
||||||
self.done = False
|
self.done = False
|
||||||
self.stats = DownloadItemStats(self)
|
self.stats = DownloadItemStats(self)
|
||||||
self.stats.updated.connect(self.data_changed)
|
|
||||||
self.index = 0
|
self.index = 0
|
||||||
self.autoclose = True
|
self.autoclose = True
|
||||||
self.reply = None
|
self.reply = None
|
||||||
@ -616,6 +611,9 @@ class DownloadManager(QAbstractListModel):
|
|||||||
self.questions = []
|
self.questions = []
|
||||||
self._networkmanager = networkmanager.NetworkManager(
|
self._networkmanager = networkmanager.NetworkManager(
|
||||||
win_id, None, self)
|
win_id, None, self)
|
||||||
|
self._update_timer = usertypes.Timer(self, 'download-update')
|
||||||
|
self._update_timer.timeout.connect(self.update_gui)
|
||||||
|
self._update_timer.setInterval(REFRESH_INTERVAL)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return utils.get_repr(self, downloads=len(self.downloads))
|
return utils.get_repr(self, downloads=len(self.downloads))
|
||||||
@ -630,6 +628,14 @@ class DownloadManager(QAbstractListModel):
|
|||||||
self.questions.append(q)
|
self.questions.append(q)
|
||||||
return q
|
return q
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def update_gui(self):
|
||||||
|
"""Periodical GUI update of all items."""
|
||||||
|
assert self.downloads
|
||||||
|
for dl in self.downloads:
|
||||||
|
dl.stats.update_speed()
|
||||||
|
self.dataChanged.emit(self.index(0), self.last_index())
|
||||||
|
|
||||||
@pyqtSlot('QUrl', 'QWebPage')
|
@pyqtSlot('QUrl', 'QWebPage')
|
||||||
def get(self, url, page=None, fileobj=None, filename=None,
|
def get(self, url, page=None, fileobj=None, filename=None,
|
||||||
auto_remove=False):
|
auto_remove=False):
|
||||||
@ -768,6 +774,9 @@ class DownloadManager(QAbstractListModel):
|
|||||||
self.downloads.append(download)
|
self.downloads.append(download)
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
|
if not self._update_timer.isActive():
|
||||||
|
self._update_timer.start()
|
||||||
|
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
download.set_filename(filename)
|
download.set_filename(filename)
|
||||||
elif fileobj is not None:
|
elif fileobj is not None:
|
||||||
@ -963,6 +972,8 @@ class DownloadManager(QAbstractListModel):
|
|||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
download.deleteLater()
|
download.deleteLater()
|
||||||
self.update_indexes()
|
self.update_indexes()
|
||||||
|
if not self.downloads:
|
||||||
|
self._update_timer.stop()
|
||||||
|
|
||||||
def remove_items(self, downloads):
|
def remove_items(self, downloads):
|
||||||
"""Remove an iterable of downloads."""
|
"""Remove an iterable of downloads."""
|
||||||
@ -991,6 +1002,8 @@ class DownloadManager(QAbstractListModel):
|
|||||||
else:
|
else:
|
||||||
download.deleteLater()
|
download.deleteLater()
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
|
if not self.downloads:
|
||||||
|
self._update_timer.stop()
|
||||||
|
|
||||||
def update_indexes(self):
|
def update_indexes(self):
|
||||||
"""Update indexes of all DownloadItems."""
|
"""Update indexes of all DownloadItems."""
|
||||||
|
Loading…
Reference in New Issue
Block a user