完善下载页面按钮的功能

This commit is contained in:
RigoLigoRLC 2022-02-19 19:30:10 +08:00
parent 8f32141726
commit d33e28b024
10 changed files with 218 additions and 33 deletions

@ -163,8 +163,8 @@ namespace SpkUi
mBtnDownload = new QPushButton;
mBtnDownload->setText(tr("Download"));
mBtnInstall = new QPushButton;
mBtnInstall->setText(tr("Install"));
// mBtnInstall = new QPushButton;
// mBtnInstall->setText(tr("Install"));
mBtnUninstall = new QPushButton;
mBtnUninstall->setText(tr("Uninstall"));
@ -177,7 +177,7 @@ namespace SpkUi
mBottomBarLay->addStretch();
mBottomBarLay->addWidget(mBtnDownload);
mBottomBarLay->addWidget(mBtnInstall);
// mBottomBarLay->addWidget(mBtnInstall);
mBottomBarLay->addWidget(mBtnUninstall);
mBottomBarLay->addWidget(mBtnRequestUpdate);
mBottomBarLay->addWidget(mBtnReport);

@ -1,6 +1,8 @@
#include "page/spkpagedownloads.h"
#include "pkgs/spkpkgmgrbase.h"
#include "spkuimsg.h"
#include "spkutils.h"
SpkUi::SpkPageDownloads::SpkPageDownloads(QWidget *parent) :
@ -27,6 +29,8 @@ SpkUi::SpkPageDownloads::SpkPageDownloads(QWidget *parent) :
connect(mDownloadMgr, &SpkDownloadMgr::DownloadStopped,
this, &SpkPageDownloads::DownloadStopped, Qt::QueuedConnection);
connect(PKG, &SpkPkgMgrBase::ReportInstallResult,
this, &SpkPageDownloads::InstallationEnded);
}
SpkUi::SpkPageDownloads::~SpkPageDownloads()
@ -53,31 +57,24 @@ void SpkUi::SpkPageDownloads::AddDownloadTask(QString name, QString pkgName, QSt
// Add a new download entry into the UI
auto entry = new SpkDownloadEntry;
auto iconData = RES->CacheLookup(pkgName, SpkResource::ResourceType::AppIcon, 0);
auto id = mNextDownloadId;
QPixmap icon;
if(iconData.status != SpkResource::ResourceStatus::Ready || !icon.loadFromData(iconData.data))
icon.load(":/icons/broken-icon.svg");
entry->SetBasicInfo(name, icon);
entry->SetBasicInfo(name, icon, mDownloadMgr->GetDestFilePath(path));
entry->SetStatus(SpkDownloadEntry::Waiting);
auto id = mNextDownloadId;
entry->setProperty("entryId", id);
entry->setProperty("path", path);
mNextDownloadId++;
mEntries[id] = entry;
mLayEntries->addWidget(entry);
if(mCurrentStatus != Idle)
mWaitingDownloads.enqueue({ id, path }); // Queue download task for future
else
{
mCurrentStatus = Waiting;
if(!mDownloadMgr->StartNewDownload(path, id)) // Initiate a download task when idle
{
// If fails to start then try next one. Emitting this signal causes
// SpkPageDownloads::DownloadStopped to be activated and thus tries next item in queue
emit mDownloadMgr->DownloadStopped(SpkDownloadMgr::FailNoVaibleServer, id);
}
}
connect(entry, &SpkDownloadEntry::Action,
this, &SpkPageDownloads::EntryAction);
NewDownloadTask(id, path);
}
void SpkUi::SpkPageDownloads::DownloadStopped(SpkDownloadMgr::TaskResult status, int id)
@ -89,21 +86,34 @@ void SpkUi::SpkPageDownloads::DownloadStopped(SpkDownloadMgr::TaskResult status,
break;
case SpkDownloadMgr::FailCannotCreateFile:
mEntries[id]->SetStatus(SpkDownloadEntry::Failed,
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("Cannot create download file. Download failed."));
break;
case SpkDownloadMgr::FailNoVaibleServer:
mEntries[id]->SetStatus(SpkDownloadEntry::Failed,
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("Connection unstable or server failure. Download failed."));
break;
case SpkDownloadMgr::FailCancel:
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("This download was cancelled."));
break;
case SpkDownloadMgr::Fail:
mEntries[id]->SetStatus(SpkDownloadEntry::Failed,
mEntries[id]->SetStatus(SpkDownloadEntry::DownloadFailed,
tr("Unknown error. Download failed."));
break;
}
if(status == SpkDownloadMgr::Success)
SpkUiMessage::SendDesktopNotification(
tr("App \"%1\" downloaded, and ready to install.").arg(mEntries[id]->GetTaskName()));
else if(status != SpkDownloadMgr::FailCancel)
SpkUiMessage::SendDesktopNotification(
tr("Error occurred downloading \"%1\".").arg(mEntries[id]->GetTaskName()));
// Continue next download task
if(!mWaitingDownloads.isEmpty())
{
@ -116,3 +126,85 @@ void SpkUi::SpkPageDownloads::DownloadStopped(SpkDownloadMgr::TaskResult status,
mCurrentStatus = Idle;
}
}
void SpkUi::SpkPageDownloads::EntryAction(SpkDownloadEntry::EntryAction act)
{
SpkDownloadEntry *entry = static_cast<SpkDownloadEntry*>(sender());
auto id = entry->property("entryId").toInt();
switch(act)
{
case SpkDownloadEntry::AbortDownload:
mDownloadMgr->CancelCurrentDownload(); // Only one task at a time so simply abort download
break;
case SpkDownloadEntry::RetryDownload:
mLayEntries->removeWidget(entry); // Move to list tail
mLayEntries->addWidget(entry);
NewDownloadTask(id, entry->property("path").toString());
entry->SetStatus(SpkDownloadEntry::Waiting);
break;
case SpkDownloadEntry::StartInstall:
switch(PKG->ExecuteInstallation(entry->GetFilePath(), id))
{
case SpkPkgMgrBase::Succeeded:
entry->SetStatus(SpkDownloadEntry::Installing);
break;
case SpkPkgMgrBase::Failed:
entry->SetStatus(SpkDownloadEntry::InstallFailed,
tr("Failed to start installation."));
break;
default: break;
}
break;
case SpkDownloadEntry::RemoveEntry:
mLayEntries->removeWidget(entry);
mEntries.remove(id);
for(auto i = mWaitingDownloads.begin(); i != mWaitingDownloads.end(); i++)
{
if(i->first == id)
{
mWaitingDownloads.erase(i);
break;
}
}
entry->setVisible(false);
entry->deleteLater();
break;
}
}
void SpkUi::SpkPageDownloads::InstallationEnded(int id,
SpkPkgMgrBase::PkgInstallResult result,
int exitCode)
{
if(result == SpkPkgMgrBase::Succeeded)
{
mEntries[id]->SetStatus(SpkDownloadEntry::Installed);
}
else
{
mEntries[id]->SetStatus(SpkDownloadEntry::InstallFailed,
tr("Install failed, exit code: %1.").arg(exitCode));
}
}
void SpkUi::SpkPageDownloads::NewDownloadTask(int id, QString downloadPath)
{
if(mCurrentStatus != Idle)
mWaitingDownloads.enqueue({ id, downloadPath }); // Queue download task for future
else
{
mCurrentStatus = Waiting;
if(!mDownloadMgr->StartNewDownload(downloadPath, id)) // Initiate a download task when idle
{
// If fails to start then try next one. Emitting this signal causes
// SpkPageDownloads::DownloadStopped to be activated and thus tries next item in queue
emit mDownloadMgr->DownloadStopped(SpkDownloadMgr::FailNoVaibleServer, id);
}
}
}

@ -40,6 +40,11 @@ SpkDownloadEntry::SpkDownloadEntry(QWidget *parent)
setLayout(mLayMain);
connect(mBtnActions, &QPushButton::clicked, this, &SpkDownloadEntry::ActionButton);
connect(mBtnDelete, &QPushButton::clicked, this, &SpkDownloadEntry::DeleteButton);
mStatus = Invalid;
mLastReportTime = QTime::currentTime();
}
@ -56,14 +61,16 @@ void SpkDownloadEntry::SetTotalBytes(qint64 total)
mLastReportTime = QTime::currentTime();
}
void SpkDownloadEntry::SetBasicInfo(QString name, QPixmap icon)
void SpkDownloadEntry::SetBasicInfo(QString name, QPixmap icon, QString filePath)
{
mAppName->setText(name);
mIcon->setPixmap(icon.scaled(IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
mFilePath = filePath;
}
void SpkDownloadEntry::SetStatus(DownloadEntryStatus status, QString msg)
{
mStatus = status;
switch(status)
{
case Waiting:
@ -71,31 +78,36 @@ void SpkDownloadEntry::SetStatus(DownloadEntryStatus status, QString msg)
mProgress->setVisible(false);
mBtnActions->setVisible(false);
mBtnDelete->setVisible(true);
mBtnDelete->setText(tr("Cancel"));
break;
case Downloading:
mMessage->setText(tr(""));
mProgress->setVisible(true);
mBtnActions->setVisible(true);
mBtnActions->setVisible(false);
break;
case Paused:
mMessage->setText(tr("Paused"));
break;
case Failed:
case DownloadFailed:
mMessage->setText(msg);
mProgress->setVisible(false);
mBtnActions->setVisible(true);
mBtnActions->setText(tr("Retry"));
break;
case ToBeInstalled:
mMessage->setText(tr("Download Finished"));
mProgress->setVisible(false);
mBtnActions->setVisible(true);
mBtnDelete->setVisible(false);
mBtnActions->setText(tr("Install"));
break;
case Installing:
mMessage->setText("");
mProgress->setVisible(false);
mBtnActions->setVisible(false);
mBtnDelete->setVisible(false);
mLoading->setVisible(true);
mLoading->Begin();
@ -103,12 +115,18 @@ void SpkDownloadEntry::SetStatus(DownloadEntryStatus status, QString msg)
mMessage->setText(tr("Installed"));
mLoading->End();
mLoading->setVisible(false);
mBtnDelete->setVisible(true);
mBtnDelete->setText(tr("Delete"));
break;
case InstallFailed:
mMessage->setText(msg.isEmpty() ? tr("Install Failed") : msg);
mLoading->End();
mLoading->setVisible(false);
mBtnActions->setVisible(true);
mBtnActions->setText(tr("Install"));
mBtnDelete->setVisible(true);
mBtnDelete->setText(tr("Cancel"));
break;
case Invalid:
@ -135,3 +153,42 @@ void SpkDownloadEntry::Progress(qint64 bytes)
mProgress->setValue(static_cast<int>(((double)bytes) / mTotalBytes * 1000));
mLastReportTime = now;
}
void SpkDownloadEntry::ActionButton()
{
switch(mStatus)
{
case DownloadFailed:
emit Action(RetryDownload);
break;
case ToBeInstalled:
case InstallFailed:
emit Action(StartInstall);
break;
default:
break;
}
}
void SpkDownloadEntry::DeleteButton()
{
switch(mStatus)
{
case Waiting:
case DownloadFailed:
case Installed:
case InstallFailed:
case ToBeInstalled:
emit Action(RemoveEntry);
break;
case Downloading:
emit Action(AbortDownload);
break;
default:
break;
}
}

@ -4,6 +4,7 @@
#include "spkdownload.h"
#include "spkdownloadentry.h"
#include "page/spkpagebase.h"
#include "pkgs/spkpkgmgrbase.h"
namespace SpkUi
{
@ -22,7 +23,7 @@ namespace SpkUi
SpkDownloadMgr *mDownloadMgr;
QMap<uint, SpkDownloadEntry*> mEntries;
uint mNextDownloadId;
QQueue<QPair<uint, QString>> mWaitingDownloads;
QQueue<QPair<int, QString>> mWaitingDownloads;
enum { Idle, Waiting, Downloading } mCurrentStatus;
// UI
@ -33,6 +34,11 @@ namespace SpkUi
private slots:
void DownloadProgress(qint64 downloadedBytes, qint64 totalBytes, int id);
void DownloadStopped(SpkDownloadMgr::TaskResult status, int id);
void EntryAction(SpkDownloadEntry::EntryAction);
void InstallationEnded(int id, SpkPkgMgrBase::PkgInstallResult, int exitCode);
private:
void NewDownloadTask(int id, QString downloadPath);
};
}

@ -27,6 +27,7 @@ class SpkDownloadMgr : public QObject
FailCannotCreateFile, ///< Failed because destination file cannot be created
FailNoVaibleServer, ///< Failed because no server provides file size or download stalled on
///< all of them
FailCancel, ///< User has cancelled the task
Fail
};
@ -67,6 +68,8 @@ class SpkDownloadMgr : public QObject
*/
static RemoteFileInfo GetRemoteFileInfo(QUrl url);
QString GetDestFilePath(QString downloadPath);
private:
QList<QString> mServers; ///< Multithreaded download

@ -26,8 +26,7 @@ class SpkDownloadEntry : public QWidget
Invalid = -1,
Waiting,
Downloading,
Paused,
Failed,
DownloadFailed,
ToBeInstalled,
Installing,
Installed,
@ -35,9 +34,23 @@ class SpkDownloadEntry : public QWidget
};
void SetTotalBytes(qint64 total);
void SetBasicInfo(QString name, QPixmap icon);
void SetBasicInfo(QString name, QPixmap icon, QString filePath);
void SetStatus(DownloadEntryStatus status, QString msg = "");
void Progress(qint64 bytes);
QString GetTaskName() { return mAppName->text(); }
QString GetFilePath() { return mFilePath; }
enum EntryAction
{
AbortDownload,
RetryDownload,
StartInstall,
RemoveEntry
};
private slots:
void ActionButton();
void DeleteButton();
private:
QLabel *mIcon, *mMessage;
@ -54,4 +67,11 @@ class SpkDownloadEntry : public QWidget
qint64 mTotalBytes, mDownloadedBytes;
QTime mLastReportTime;
QString mReadableTotalSize;
QString mFilePath;
DownloadEntryStatus mStatus;
signals:
void Action(EntryAction);
};

@ -82,6 +82,7 @@ namespace SpkUi
void GoBack()
{
emit SwitchToCategory(mLastCategoryPage, 0);
mCategoryWidget->currentItem()->setSelected(false);
mLastCategoryItem->setSelected(true);
}

@ -13,6 +13,7 @@
#define STORE (SpkStore::Instance)
#define CFG (SpkStore::Instance->mCfg)
#define RES (SpkResource::Instance)
#define PKG (SpkPkgMgrBase::Instance())
namespace SpkUtils
{

@ -71,6 +71,11 @@ SpkDownloadMgr::RemoteFileInfo SpkDownloadMgr::GetRemoteFileInfo(QUrl url)
return ret;
}
QString SpkDownloadMgr::GetDestFilePath(QString downloadPath)
{
return mDestFolder + '/' + SpkUtils::CutFileName(downloadPath);
}
void SpkDownloadMgr::SetDestinationFolder(QString path)
{
QDir dir(path);
@ -122,7 +127,7 @@ bool SpkDownloadMgr::StartNewDownload(QString path, int downloadId)
sErr(tr("SpkDownloadMgr: Download directory %1 cannot be created.").arg(mDestFolder));
return false;
}
mDestFile.setFileName(mDestFolder + '/' + SpkUtils::CutFileName(path));
mDestFile.setFileName(GetDestFilePath(path));
if(!mDestFile.open(QFile::ReadWrite))
{
sNotify(tr("Cannot write to destination file, download cannot start."));

@ -34,7 +34,7 @@ void SpkUiMessage::SendStoreNotification(QString s)
void SpkUiMessage::SetDesktopNotifyTimeout(int ms)
{
if(!_notify)
_notify = notify_notification_new("", "", "");
return;
notify_notification_set_timeout(_notify, ms);
mTimeoutDesktop = ms;
}