Skip to content

Commit

Permalink
Download stats and pause, resume functions
Browse files Browse the repository at this point in the history
Revamped download function as per design guidelines.
While downloading, it shows download speed and completed length along with button to pause
When paused, it shows the button to resume download or cancel it.
  • Loading branch information
juuz0 committed Jun 26, 2023
1 parent 5de39bb commit c6a950e
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 26 deletions.
70 changes: 55 additions & 15 deletions src/contentmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ ContentManager::ContentManager(Library* library, kiwix::Downloader* downloader,
treeView->setWordWrap(true);
treeView->resizeColumnToContents(4);
treeView->setColumnWidth(0, 80);
treeView->setColumnWidth(5, 120);
// TODO: set width for all columns based on viewport

setCurrentLanguage(QLocale().name().split("_").at(0));
Expand Down Expand Up @@ -90,6 +91,25 @@ void ContentManager::onCustomContextMenu(const QPoint &point)
QAction menuDeleteBook("Delete book", this);
QAction menuOpenBook("Open book", this);
QAction menuDownloadBook("Download book", this);
QAction menuPauseBook("Pause download", this);
QAction menuResumeBook("Resume download", this);
QAction menuCancelBook("Cancel download", this);

if (bookNode->isDownloading()) {
if (bookNode->getDownloadInfo().paused) {
contextMenu.addAction(&menuResumeBook);
} else {
contextMenu.addAction(&menuPauseBook);
}
contextMenu.addAction(&menuCancelBook);
} else {
if (m_local) {
contextMenu.addAction(&menuOpenBook);
contextMenu.addAction(&menuDeleteBook);
}
else
contextMenu.addAction(&menuDownloadBook);
}

connect(&menuDeleteBook, &QAction::triggered, [=]() {
eraseBook(id);
Expand All @@ -99,14 +119,17 @@ void ContentManager::onCustomContextMenu(const QPoint &point)
openBook(id);
});
connect(&menuDownloadBook, &QAction::triggered, [=]() {
downloadBook(id);
downloadBook(id, index);
});
connect(&menuPauseBook, &QAction::triggered, [=]() {
pauseBook(id, index);
});
connect(&menuCancelBook, &QAction::triggered, [=]() {
cancelBook(id, index);
});
connect(&menuResumeBook, &QAction::triggered, [=]() {
resumeBook(id, index);
});

if (m_local)
contextMenu.addAction(&menuOpenBook);
else
contextMenu.addAction(&menuDownloadBook);
contextMenu.addAction(&menuDeleteBook);

if (index.isValid()) {
contextMenu.exec(mp_view->getView()->viewport()->mapToGlobal(point));
Expand Down Expand Up @@ -315,6 +338,13 @@ QMap<QString, QVariant> ContentManager::updateDownloadInfos(QString id, const QS
}
#undef ADD_V

QString ContentManager::downloadBook(const QString &id, QModelIndex index)
{
emit managerModel->startDownload(index);
return downloadBook(id);
}


QString ContentManager::downloadBook(const QString &id)
{
if (!mp_downloader)
Expand Down Expand Up @@ -348,14 +378,6 @@ QString ContentManager::downloadBook(const QString &id)
bookCopy.setDownloadId(download->getDid());
mp_library->addBookToLibrary(bookCopy);
mp_library->save();
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [=](){
auto downloadInfos = updateDownloadInfos(id, {"status"});
if (!downloadInfos["status"].isValid()) {
timer->stop();
}
});
timer->start(1000);
emit(oneBookChanged(id));
return QString::fromStdString(download->getDid());
}
Expand Down Expand Up @@ -390,6 +412,12 @@ void ContentManager::eraseBook(const QString& id)
KiwixApp::instance()->getSettingsManager()->deleteSettings(id);
}

void ContentManager::pauseBook(const QString& id, QModelIndex index)
{
pauseBook(id);
emit managerModel->pauseDownload(index);
}

void ContentManager::pauseBook(const QString& id)
{
if (!mp_downloader) {
Expand All @@ -401,6 +429,12 @@ void ContentManager::pauseBook(const QString& id)
download->pauseDownload();
}

void ContentManager::resumeBook(const QString& id, QModelIndex index)
{
resumeBook(id);
emit managerModel->resumeDownload(index);
}

void ContentManager::resumeBook(const QString& id)
{
if (!mp_downloader) {
Expand All @@ -412,6 +446,12 @@ void ContentManager::resumeBook(const QString& id)
download->resumeDownload();
}

void ContentManager::cancelBook(const QString& id, QModelIndex index)
{
cancelBook(id);
emit managerModel->cancelDownload(index);
}

void ContentManager::cancelBook(const QString& id)
{
if (!mp_downloader) {
Expand Down
4 changes: 4 additions & 0 deletions src/contentmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public slots:
void openBook(const QString& id);
QMap<QString, QVariant> updateDownloadInfos(QString id, const QStringList& keys);
QString downloadBook(const QString& id);
QString downloadBook(const QString& id, QModelIndex index);
void updateLibrary();
void setSearch(const QString& search);
void setSortBy(const QString& sortBy, const bool sortOrderAsc);
Expand All @@ -70,6 +71,9 @@ public slots:
void pauseBook(const QString& id);
void resumeBook(const QString& id);
void cancelBook(const QString& id);
void pauseBook(const QString& id, QModelIndex index);
void resumeBook(const QString& id, QModelIndex index);
void cancelBook(const QString& id, QModelIndex index);
void onCustomContextMenu(const QPoint &point);
};

Expand Down
156 changes: 147 additions & 9 deletions src/contentmanagerdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,127 @@ ContentManagerDelegate::ContentManagerDelegate(QObject *parent)
"margin: 4px;");
}

void createPauseSymbol(QPainter *painter, int x, int y)
{
QPen pen;
pen.setWidth(3);
QPainterPath path;
x += 12.5;
y += 10;
pen.setColor("#3366cc");
path.moveTo(x, y);
path.lineTo(x, y + 10);
painter->strokePath(path, pen);
path.moveTo(x + 5, y);
path.lineTo(x + 5, y + 10);
painter->strokePath(path, pen);
}

void createResumeSymbol(QPainter *painter, int x, int y)
{
QPen pen;
pen.setWidth(3);
QPainterPath path;
x += 12.5;
y += 8;
pen.setColor("#3366cc");
path.moveTo(x, y);
path.lineTo(x, y + 15);
path.lineTo(x + 10, y + 8);
path.lineTo(x, y);
painter->setRenderHint(QPainter::Antialiasing);
painter->strokePath(path, pen);
}

void createArc(QPainter *painter, int startAngle, int spanAngle, QRect rectangle, QPen pen)
{
painter->setRenderHint(QPainter::Antialiasing);
int arcX = rectangle.x();
int arcY = rectangle.y();
int arcW = rectangle.width();
int arcH = rectangle.height();
QPainterPath path;
path.moveTo(arcX + arcW, arcY + arcH/2);
path.arcTo(rectangle, startAngle, spanAngle);
painter->strokePath(path, pen);
}

void createCancelSymbol(QPainter *painter, int x, int y, int w, int h)
{
QPen p;
p.setWidth(3);
p.setColor("#dd3333");
QRect r(x, y, w, h);
createArc(painter, 0, 360, r, p);
painter->setPen(p);
QRect nRect(x, y, w, h);
auto oldFont = painter->font();
auto bFont = oldFont;
bFont.setBold(true);
painter->setFont(bFont);
painter->drawText(nRect, Qt::AlignCenter | Qt::AlignJustify, "X");
painter->setFont(oldFont);
}

void createDownloadStats(QPainter *painter, QRect box, QString downloadSpeed, QString completedLength)
{
QPen pen;
int x = box.x();
int y = box.y();
int w = box.width();
int h = box.height();
pen.setColor("#666666");
painter->setPen(pen);
auto oldFont = painter->font();
painter->setFont(QFont("Selawik", 8));
QRect nRect(x - 10, y - 10, w, h);
painter->drawText(nRect,Qt::AlignCenter | Qt::AlignJustify, downloadSpeed);
QRect fRect(x - 10, y + 10, w, h);
painter->drawText(fRect,Qt::AlignCenter | Qt::AlignJustify, completedLength);
painter->setFont(oldFont);
}

void showDownloadProgress(QPainter *painter, QRect box, DownloadInfo downloadInfo)
{
int x,y,w,h;
x = box.left();
y = box.top();
w = box.width();
h = box.height();

int arcX = x + w/2 + 20;
int arcY = y + 20;
int arcW = w - 90;
int arcH = h - 40;

double progress = (double) (downloadInfo.progress) / 100;
progress = -progress;
auto completedLength = downloadInfo.completedLength;
auto downloadSpeed = downloadInfo.downloadSpeed;

if (downloadInfo.paused) {
createResumeSymbol(painter, arcX, arcY);
createCancelSymbol(painter, x + w/2 - 20, arcY, arcW, arcH);
} else {
createPauseSymbol(painter, arcX, arcY);
createDownloadStats(painter, box, downloadSpeed, completedLength);
}

QPen pen;
pen.setWidth(3);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing);

QRect rectangle(arcX, arcY, arcW, arcH);

pen.setColor("#eaecf0");
createArc(painter, 0, 360, rectangle, pen);

int startAngle = 0;
int spanAngle = progress * 360;
pen.setColor("#3366cc");
createArc(painter, startAngle, spanAngle, rectangle, pen);
}

void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Expand All @@ -35,8 +156,6 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem
const auto id = node->getBookId();
const auto book = KiwixApp::instance()->getLibrary()->getBookById(id);
if(KiwixApp::instance()->getContentManager()->getBookInfos(id, {"downloadId"})["downloadId"] != "") {
button.text = "Downloading";
button.state = QStyle::State_ReadOnly;
} else {
button.text = gt("open");
}
Expand All @@ -50,7 +169,13 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem
return;
}
if (index.column() == 5) {
baseButton->style()->drawControl( QStyle::CE_PushButton, &button, painter, baseButton.data());
if (node->isDownloading()) {
auto downloadInfo = node->getDownloadInfo();
showDownloadProgress(painter, r, downloadInfo);
}
else {
baseButton->style()->drawControl( QStyle::CE_PushButton, &button, painter, baseButton.data());
}
return;
} else if (index.column() == 0) {
const auto icon = index.data().value<QIcon>();
Expand Down Expand Up @@ -82,13 +207,26 @@ bool ContentManagerDelegate::editorEvent(QEvent *event, QAbstractItemModel *mode
const auto id = node->getBookId();

if(index.column() == 5 && clickX > x && clickX < x + w )
if( clickY > y && clickY < y + h && KiwixApp::instance()->getContentManager()->getBookInfos(id, {"downloadId"})["downloadId"] == "")
if( clickY > y && clickY < y + h)
{
try {
const auto book = KiwixApp::instance()->getLibrary()->getBookById(id);
KiwixApp::instance()->getContentManager()->openBook(id);
} catch (std::out_of_range& e) {
KiwixApp::instance()->getContentManager()->downloadBook(id);
if (node->isDownloading())
{
if (node->getDownloadInfo().paused) {
if (clickX < (x + w/2)) {
KiwixApp::instance()->getContentManager()->cancelBook(id, index);
} else {
KiwixApp::instance()->getContentManager()->resumeBook(id, index);
}
} else {
KiwixApp::instance()->getContentManager()->pauseBook(id, index);
}
} else {
try {
const auto book = KiwixApp::instance()->getLibrary()->getBookById(id);
KiwixApp::instance()->getContentManager()->openBook(id);
} catch (std::out_of_range& e) {
KiwixApp::instance()->getContentManager()->downloadBook(id, index);
}
}
}
}
Expand Down
Loading

0 comments on commit c6a950e

Please sign in to comment.