# -*- coding: utf-8 -*- """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . @author: mkaay """ from PyQt4.QtCore import * from PyQt4.QtGui import * from time import sleep, time def formatSpeed(speed): speed = int(speed) steps = 0 sizes = ["B/s", "KiB/s", "MiB/s", "GiB/s"] while speed > 1000: speed /= 1024.0 steps += 1 return "%.2f %s" % (speed, sizes[steps]) class OverviewModel(QAbstractListModel): PackageName = 10 Progress = 11 PartsFinished = 12 Parts = 13 ETA = 14 Speed = 15 CurrentSize = 16 MaxSize = 17 Status = 18 def __init__(self, view, connector): QAbstractListModel.__init__(self) self.packages = [] def queueChanged(self): #dirty.. self.beginResetModel() self.packages = [] def partsFinished(p): f = 0 for c in p.children: if c.data["status"] == 0: f += 1 return f def maxSize(p): ms = 0 cs = 0 for c in p.children: try: s = c.data["downloading"]["size"] except: s = c.data["size"] if c.data["downloading"]: cs += s - c.data["downloading"]["bleft"] elif self.queue.getProgress(c, False) == 100: cs += s ms += s return ms, cs def getProgress(p): for c in p.children: if c.data["status"] == 13: return _("Unpacking"), int(c.data["progress"]) return _("Downloading"), self.queue.getProgress(p) d = self.queue._data for p in d: status, progress = getProgress(p) maxsize, currentsize = maxSize(p) speed = self.queue.getSpeed(p) if speed: eta = (maxsize - (maxsize * (progress/100.0)))/speed else: eta = 0 if not speed and not progress: status = _("Queued") info = { OverviewModel.PackageName: p.data["name"], OverviewModel.Progress: progress, OverviewModel.PartsFinished: partsFinished(p), OverviewModel.Parts: len(p.children), OverviewModel.ETA: int(eta), OverviewModel.Speed: speed, OverviewModel.CurrentSize: currentsize, OverviewModel.MaxSize: maxsize, OverviewModel.Status: status, } self.packages.append(info) self.endResetModel() def headerData(self, section, orientation, role=Qt.DisplayRole): return QVariant(_("Package")) def rowCount(self, parent=QModelIndex()): return len(self.packages) def data(self, index, role=Qt.DisplayRole): if role in [OverviewModel.PackageName, OverviewModel.Progress, OverviewModel.PartsFinished, OverviewModel.Parts, OverviewModel.ETA, OverviewModel.Speed, OverviewModel.CurrentSize, OverviewModel.MaxSize, OverviewModel.Status]: return QVariant(self.packages[index.row()][role]) return QVariant() class OverviewView(QListView): def __init__(self, connector): QListView.__init__(self) self.setModel(OverviewModel(self, connector)) self.setAlternatingRowColors(True) self.delegate = OverviewDelegate(self) self.setItemDelegate(self.delegate) class OverviewDelegate(QItemDelegate): def __init__(self, parent): QItemDelegate.__init__(self, parent) self.parent = parent self.model = parent.model() def paint(self, painter, option, index): option.rect.setHeight(59+16) option.rect.setWidth(self.parent.width()-20) #if option.state & QStyle.State_Selected: # painter.fillRect(option.rect, option.palette.color(QPalette.Highlight)) packagename = index.data(OverviewModel.PackageName).toString() partsf = index.data(OverviewModel.PartsFinished).toString() parts = index.data(OverviewModel.Parts).toString() eta = int(index.data(OverviewModel.ETA).toString()) speed = index.data(OverviewModel.Speed).toString() or 0 progress = int(index.data(OverviewModel.Progress).toString()) currentSize = int(index.data(OverviewModel.CurrentSize).toString()) maxSize = int(index.data(OverviewModel.MaxSize).toString()) status = index.data(OverviewModel.Status).toString() def formatEta(seconds): if seconds <= 0: return "" hours, seconds = divmod(seconds, 3600) minutes, seconds = divmod(seconds, 60) return _("ETA: ") + "%.2i:%.2i:%.2i" % (hours, minutes, seconds) statusline = QString(_("Parts: ") + "%s/%s" % (partsf, parts)) if partsf == parts: speedline = _("Finished") elif not status == _("Downloading"): speedline = QString(status) else: speedline = QString(formatEta(eta) + " " + _("Speed: %s") % formatSpeed(speed)) def formatSize(size): from math import ceil kbytes = size/1024 if kbytes >= 1024: if kbytes/1024 >= 1024: size = "%s GiB" % round(float(ceil(kbytes))/1024/1024, 2) else: size = "%s MiB" % round(float(ceil(kbytes))/1024, 2) else: size = "%s KiB" % kbytes return size if progress in (0,100): sizeline = QString(_("Size:") + "%s" % formatSize(maxSize)) else: sizeline = QString(_("Size:") + "%s / %s" % (formatSize(currentSize), formatSize(maxSize))) f = painter.font() f.setPointSize(12) f.setBold(True) painter.setFont(f) r = option.rect.adjusted(4, 4, -4, -4) painter.drawText(r.left(), r.top(), r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, packagename) newr = painter.boundingRect(r.left(), r.top(), r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, packagename) f.setPointSize(10) f.setBold(False) painter.setFont(f) painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, statusline) painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignHCenter, sizeline) painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignRight, speedline) newr = painter.boundingRect(r.left(), newr.bottom()+2, r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, statusline) newr.setTop(newr.bottom()+8) newr.setBottom(newr.top()+20) newr.setRight(self.parent.width()-25) f.setPointSize(10) painter.setFont(f) opts = QStyleOptionProgressBarV2() opts.maximum = 100 opts.minimum = 0 opts.progress = progress opts.rect = newr opts.textVisible = True opts.textAlignment = Qt.AlignCenter opts.text = QString.number(opts.progress) + "%" QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) def sizeHint(self, option, index): return QSize(self.parent.width()-22, 59+16)