mirror of
https://gitee.com/spark-store-project/spark-store
synced 2025-12-14 21:02:04 +08:00
Temporary commit
This commit is contained in:
@@ -56,7 +56,12 @@ namespace SpkUi
|
||||
|
||||
void SpkPageAppDetails::SetWebsiteLink(QString url)
|
||||
{
|
||||
mWebsite->setText(QString("<a href=\"%1\">%1</a>").arg(url));
|
||||
mWebsite->setText(QString("<a href=\"%1\">%2</a>").arg(url, tr("Website link")));
|
||||
}
|
||||
|
||||
void SpkPageAppDetails::SetPackagePath(QString url)
|
||||
{
|
||||
mPkgPath = url;
|
||||
}
|
||||
|
||||
SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent)
|
||||
@@ -65,16 +70,20 @@ namespace SpkUi
|
||||
mMainArea->setWidgetResizable(true);
|
||||
mMainArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
mLay4MainArea = new QVBoxLayout(this);
|
||||
mLay4MainArea->addWidget(mMainArea);
|
||||
mMainLay = new QVBoxLayout(this);
|
||||
mMainLay->addWidget(mMainArea);
|
||||
|
||||
mMainLay = new QVBoxLayout(mMainArea);
|
||||
mMainLay->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
mBottomBar = new QWidget;
|
||||
mMainLay->addWidget(mBottomBar);
|
||||
|
||||
mDetailsLay = new QVBoxLayout(mMainArea);
|
||||
mDetailsLay->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
|
||||
mAppIcon = new QLabel;
|
||||
|
||||
mAppTitle = new QLabel;
|
||||
mAppTitle->setObjectName("styDetTitle");
|
||||
mAppTitle->setWordWrap(true);
|
||||
|
||||
mAppDescription = new QLabel;
|
||||
mAppDescription->setObjectName("styDetDesc");
|
||||
@@ -87,9 +96,11 @@ namespace SpkUi
|
||||
mAppShortDesc->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||
mAppShortDesc->setMinimumWidth(100);
|
||||
mVersion = new QLabel;
|
||||
mVersion->setWordWrap(true);
|
||||
mWebsite = new QLabel;
|
||||
mPkgName = new QLabel;
|
||||
mPkgName->setObjectName("styDetPkg");
|
||||
mPkgName->setWordWrap(true);
|
||||
|
||||
mTitleLay = new QVBoxLayout;
|
||||
mTitleLay->setAlignment(Qt::AlignTop);
|
||||
@@ -132,18 +143,49 @@ namespace SpkUi
|
||||
// mDetailWidget->setLayout(mDetailLay);
|
||||
// mDetailWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
|
||||
mMainLay->setAlignment(Qt::AlignTop);
|
||||
mMainLay->addWidget(mIconTitleWidget);
|
||||
mMainLay->addLayout(mDetailLay);
|
||||
mMainLay->addWidget(mAppDescription);
|
||||
mDetailsLay->setAlignment(Qt::AlignTop);
|
||||
mDetailsLay->addWidget(mIconTitleWidget);
|
||||
mDetailsLay->addLayout(mDetailLay);
|
||||
mDetailsLay->addWidget(mAppDescription);
|
||||
// mMainLay->addStretch();
|
||||
mWid4MainArea = new QWidget;
|
||||
mWid4MainArea->setLayout(mMainLay);
|
||||
mWid4MainArea->setLayout(mDetailsLay);
|
||||
|
||||
mMainArea->setWidget(mWid4MainArea);
|
||||
|
||||
mWebsite->setTextFormat(Qt::RichText);
|
||||
mWebsite->setOpenExternalLinks(true);
|
||||
|
||||
// Bottom bar buttons
|
||||
mBottomBarLay = new QHBoxLayout;
|
||||
mBottomBar->setLayout(mBottomBarLay);
|
||||
|
||||
mBtnDownload = new QPushButton;
|
||||
mBtnDownload->setText(tr("Download"));
|
||||
|
||||
mBtnInstall = new QPushButton;
|
||||
mBtnInstall->setText(tr("Install"));
|
||||
|
||||
mBtnUninstall = new QPushButton;
|
||||
mBtnUninstall->setText(tr("Uninstall"));
|
||||
|
||||
mBtnRequestUpdate = new QPushButton;
|
||||
mBtnRequestUpdate->setText(tr("Request Update"));
|
||||
|
||||
mBtnReport = new QPushButton;
|
||||
mBtnReport->setText(tr("Report"));
|
||||
|
||||
mBottomBarLay->addStretch();
|
||||
mBottomBarLay->addWidget(mBtnDownload);
|
||||
mBottomBarLay->addWidget(mBtnInstall);
|
||||
mBottomBarLay->addWidget(mBtnUninstall);
|
||||
mBottomBarLay->addWidget(mBtnRequestUpdate);
|
||||
mBottomBarLay->addWidget(mBtnReport);
|
||||
|
||||
connect(mBtnDownload, &QPushButton::clicked,
|
||||
[=](){ emit RequestDownload(mAppTitle->text(), mPkgName->text(),
|
||||
"/store/chat/icalingua/icalingua_2.4.4-Deus-non-vult_amd64.deb");
|
||||
});
|
||||
}
|
||||
|
||||
void SpkPageAppDetails::ResourceAcquisitionFinished(int id, ResourceResult result)
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace SpkUi
|
||||
|
||||
auto iconRes = RES->RequestResource(id, pkgName, SpkResource::ResourceType::AppIcon,
|
||||
iconUrl, 0);
|
||||
// TODO: cache scaled icons
|
||||
QPixmap icon;
|
||||
if(iconRes.status == SpkResource::ResourceStatus::Ready)
|
||||
{
|
||||
@@ -80,7 +79,6 @@ namespace SpkUi
|
||||
RES->PurgeCachedResource(pkgName, SpkResource::ResourceType::AppIcon, 0);
|
||||
}
|
||||
}
|
||||
//TODO: [TEST] prepare icons for loading entries
|
||||
else
|
||||
item->SetIcon(*mLoadingIcon);
|
||||
|
||||
|
||||
@@ -15,7 +15,18 @@ SpkUi::SpkPageDownloads::SpkPageDownloads(QWidget *parent) :
|
||||
mScrollArea->setWidget(mScrollWidget);
|
||||
mScrollArea->setWidgetResizable(true);
|
||||
mMainLay->addWidget(mScrollArea);
|
||||
mMainLay->addStretch();
|
||||
setLayout(mMainLay);
|
||||
|
||||
mDownloadMgr = new SpkDownloadMgr(this);
|
||||
connect(mDownloadMgr, &SpkDownloadMgr::DownloadProgressed,
|
||||
this, &SpkPageDownloads::DownloadProgress);
|
||||
|
||||
mNextDownloadId = 0;
|
||||
mCurrentStatus = Idle;
|
||||
|
||||
connect(mDownloadMgr, &SpkDownloadMgr::DownloadStopped,
|
||||
this, &SpkPageDownloads::DownloadStopped);
|
||||
}
|
||||
|
||||
SpkUi::SpkPageDownloads::~SpkPageDownloads()
|
||||
@@ -25,13 +36,80 @@ SpkUi::SpkPageDownloads::~SpkPageDownloads()
|
||||
|
||||
void SpkUi::SpkPageDownloads::DownloadProgress(qint64 downloadedBytes, qint64 totalBytes, int id)
|
||||
{
|
||||
// TODO
|
||||
if(!totalBytes)
|
||||
return;
|
||||
|
||||
if(mCurrentStatus == Waiting && totalBytes)
|
||||
{
|
||||
mCurrentStatus = Downloading;
|
||||
mEntries[id]->SetTotalBytes(totalBytes);
|
||||
mEntries[id]->SetStatus(SpkDownloadEntry::Downloading);
|
||||
}
|
||||
mEntries[id]->Progress(downloadedBytes);
|
||||
}
|
||||
|
||||
void SpkUi::SpkPageDownloads::AddDownloadTask(QString name, QString pkgName, QString path)
|
||||
{
|
||||
// Add a new download entry into the UI
|
||||
auto entry = new SpkDownloadEntry;
|
||||
auto iconData = RES->CacheLookup(pkgName, SpkResource::ResourceType::AppIcon, 0);
|
||||
QPixmap icon;
|
||||
if(iconData.status != SpkResource::ResourceStatus::Ready || !icon.loadFromData(iconData.data))
|
||||
icon.load(":/icons/broken-icon.svg");
|
||||
entry->SetBasicInfo(name, icon);
|
||||
entry->SetStatus(SpkDownloadEntry::Waiting);
|
||||
|
||||
mEntries[mNextDownloadId] = entry;
|
||||
mLayEntries->addWidget(entry);
|
||||
|
||||
if(mCurrentStatus != Idle)
|
||||
mWaitingDownloads.enqueue({ mNextDownloadId, path }); // Queue download task for future
|
||||
else
|
||||
{
|
||||
if(!mDownloadMgr->StartNewDownload(path, mNextDownloadId)) // Initiate a download task when idle
|
||||
emit mDownloadMgr->DownloadStopped(SpkDownloadMgr::FailNoVaibleServer, mNextDownloadId);
|
||||
else
|
||||
{
|
||||
mCurrentStatus = Waiting;
|
||||
}
|
||||
}
|
||||
|
||||
mNextDownloadId++;
|
||||
}
|
||||
|
||||
void SpkUi::SpkPageDownloads::DownloadStopped(SpkDownloadMgr::TaskResult status, int id)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
case SpkDownloadMgr::Success:
|
||||
mEntries[id]->SetStatus(SpkDownloadEntry::ToBeInstalled);
|
||||
break;
|
||||
|
||||
case SpkDownloadMgr::FailCannotCreateFile:
|
||||
mEntries[id]->SetStatus(SpkDownloadEntry::Failed,
|
||||
tr("Cannot create download file. Download failed."));
|
||||
break;
|
||||
|
||||
case SpkDownloadMgr::FailNoVaibleServer:
|
||||
mEntries[id]->SetStatus(SpkDownloadEntry::Failed,
|
||||
tr("Connection unstable or server failure. Download failed."));
|
||||
break;
|
||||
|
||||
case SpkDownloadMgr::Fail:
|
||||
mEntries[id]->SetStatus(SpkDownloadEntry::Failed,
|
||||
tr("Unknown error. Download failed."));
|
||||
break;
|
||||
}
|
||||
|
||||
// Continue next download task
|
||||
if(!mWaitingDownloads.isEmpty())
|
||||
{
|
||||
auto nextTask = mWaitingDownloads.dequeue();
|
||||
mDownloadMgr->StartNewDownload(nextTask.second, nextTask.first);
|
||||
mCurrentStatus = Waiting;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentStatus = Idle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#include "spkdownloadentry.h"
|
||||
#include "spklogging.h"
|
||||
#include "spkutils.h"
|
||||
#include <QDebug>
|
||||
|
||||
constexpr QSize SpkDownloadEntry::IconSize;
|
||||
|
||||
@@ -37,6 +39,8 @@ SpkDownloadEntry::SpkDownloadEntry(QWidget *parent)
|
||||
mLayMain->addWidget(mBtnDelete);
|
||||
|
||||
setLayout(mLayMain);
|
||||
|
||||
mLastReportTime = QTime::currentTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,13 +49,20 @@ SpkDownloadEntry::~SpkDownloadEntry()
|
||||
// TODO
|
||||
}
|
||||
|
||||
void SpkDownloadEntry::SetTotalBytes(qint64 total)
|
||||
{
|
||||
mTotalBytes = total;
|
||||
mReadableTotalSize = SpkUtils::BytesToSize(total);
|
||||
mLastReportTime = QTime::currentTime();
|
||||
}
|
||||
|
||||
void SpkDownloadEntry::SetBasicInfo(QString name, QPixmap icon)
|
||||
{
|
||||
mAppName->setText(name);
|
||||
mIcon->setPixmap(icon.scaled(IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
void SpkDownloadEntry::SetStatus(DownloadEntryStatus status)
|
||||
void SpkDownloadEntry::SetStatus(DownloadEntryStatus status, QString msg)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
@@ -73,7 +84,7 @@ void SpkDownloadEntry::SetStatus(DownloadEntryStatus status)
|
||||
break;
|
||||
|
||||
case Failed:
|
||||
mMessage->setText(tr("Download Failed"));
|
||||
mMessage->setText(msg);
|
||||
mProgress->setVisible(false);
|
||||
break;
|
||||
|
||||
@@ -95,7 +106,7 @@ void SpkDownloadEntry::SetStatus(DownloadEntryStatus status)
|
||||
break;
|
||||
|
||||
case InstallFailed:
|
||||
mMessage->setText(tr("Install Failed"));
|
||||
mMessage->setText(msg.isEmpty() ? tr("Install Failed") : msg);
|
||||
mLoading->End();
|
||||
mLoading->setVisible(false);
|
||||
break;
|
||||
@@ -105,7 +116,22 @@ void SpkDownloadEntry::SetStatus(DownloadEntryStatus status)
|
||||
}
|
||||
}
|
||||
|
||||
void SpkDownloadEntry::SetProgress(int p)
|
||||
void SpkDownloadEntry::Progress(qint64 bytes)
|
||||
{
|
||||
mProgress->setValue(p);
|
||||
auto now = QTime::currentTime();
|
||||
auto msecDiff = mLastReportTime.msecsTo(now);
|
||||
|
||||
if(msecDiff != 0)
|
||||
{
|
||||
auto bytesPerSec = (bytes - mDownloadedBytes) / (msecDiff / 1000.0);
|
||||
qDebug() << "Bytes" << bytes - mDownloadedBytes
|
||||
<< "MsDiff" << msecDiff / 1000.0
|
||||
<< "Bytes-Per-Seg" << bytesPerSec;
|
||||
auto speedSize = SpkUtils::BytesToSize(static_cast<size_t>(bytesPerSec));
|
||||
mMessage->setText(QString("%1/%2(%3/s)")
|
||||
.arg(SpkUtils::BytesToSize(bytes), mReadableTotalSize, speedSize));
|
||||
}
|
||||
mDownloadedBytes = bytes;
|
||||
mProgress->setValue(static_cast<int>(((double)bytes) / mTotalBytes * 1000));
|
||||
mLastReportTime = now;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,9 @@ void SpkMainWindow::SwitchToPage(SpkUi::SpkStackedPages page)
|
||||
auto tryActivate = qobject_cast<SpkPageBase *>(ui->Pager->currentWidget());
|
||||
if(tryActivate)
|
||||
tryActivate->Activated();
|
||||
|
||||
ui->BtnBack->setVisible(page == SpkUi::SpkStackedPages::PgAppDetails);
|
||||
ui->BtnBack->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,9 +92,11 @@ void SpkMainWindow::RefreshCategoryData()
|
||||
void SpkMainWindow::CategoryDataReceived()
|
||||
{
|
||||
QJsonValue retval;
|
||||
if(!SpkUtils::VerifyReplyJson(mCategoryGetReply, retval) || !retval.isArray())
|
||||
auto verify = SpkUtils::VerifyReplyJson(mCategoryGetReply, retval);
|
||||
if(verify || !retval.isArray())
|
||||
{
|
||||
sErr(tr("Failed to load categories!"));
|
||||
sErr(tr("Failed to load categories! Type=%1 Code=%2").arg(retval.type()).arg(verify));
|
||||
sNotify(tr("Cannot load categories! Type: %1 Code: %2").arg(retval.type()).arg(verify));
|
||||
// TODO: Switch to an error page
|
||||
return;
|
||||
}
|
||||
@@ -119,9 +124,11 @@ void SpkMainWindow::EnterCategoryList(int aCategoryId, int aPage)
|
||||
void SpkMainWindow::CategoryListDataReceived()
|
||||
{
|
||||
QJsonValue retval;
|
||||
if(!SpkUtils::VerifyReplyJson(mCategoryAppListGetReply, retval) || !retval.isObject())
|
||||
int verify = SpkUtils::VerifyReplyJson(mCategoryAppListGetReply, retval);
|
||||
if(verify || !retval.isObject())
|
||||
{
|
||||
sErrPop(tr("Failed to load app list of category! Type of retval: %1.").arg(retval.type()));
|
||||
sErr(tr("Failed to load app list of category! Type=%1 Code=%2").arg(retval.type()).arg(verify));
|
||||
sNotify(tr("Failed to load app list of category! Type: %1 Code: %2").arg(retval.type()).arg(verify));
|
||||
return;
|
||||
}
|
||||
SwitchToPage(SpkUi::PgAppList);
|
||||
@@ -149,9 +156,11 @@ void SpkMainWindow::SearchKeyword(QString aKeyword, int aPage)
|
||||
void SpkMainWindow::SearchDataReceived()
|
||||
{
|
||||
QJsonValue retval;
|
||||
if(!SpkUtils::VerifyReplyJson(mCategoryAppListGetReply, retval) || !retval.isObject())
|
||||
auto verify = SpkUtils::VerifyReplyJson(mCategoryAppListGetReply, retval);
|
||||
if(verify || !retval.isObject())
|
||||
{
|
||||
sErrPop(tr("Failed to search keyword! Type of retval: %1.").arg(retval.type()));
|
||||
sErr(tr("Failed to search keyword! Type=%1 Code=%2").arg(retval.type()).arg(verify));
|
||||
sNotify(tr("Failed to search keyword! Type: %1 Code: %2").arg(retval.type()).arg(verify));
|
||||
return;
|
||||
}
|
||||
SwitchToPage(SpkUi::PgAppList);
|
||||
@@ -233,9 +242,11 @@ void SpkMainWindow::EnterAppDetails(int aAppId)
|
||||
void SpkMainWindow::AppDetailsDataReceived()
|
||||
{
|
||||
QJsonValue retval;
|
||||
if(!SpkUtils::VerifyReplyJson(mAppDetailsGetReply, retval) || !retval.isObject())
|
||||
auto verify = SpkUtils::VerifyReplyJson(mAppDetailsGetReply, retval);
|
||||
if(verify || !retval.isObject())
|
||||
{
|
||||
sErrPop(tr("Failed to open app details page! Type of retval: %1.").arg(retval.type()));
|
||||
sErr(tr("Failed to open app details page! Type=%1 Code=%2").arg(retval.type()).arg(verify));
|
||||
sNotify(tr("Failed to open app details page! Type: %1 Code: %2").arg(retval.type()).arg(verify));
|
||||
return;
|
||||
}
|
||||
SwitchToPage(SpkUi::PgAppList);
|
||||
@@ -245,7 +256,8 @@ void SpkMainWindow::AppDetailsDataReceived()
|
||||
|
||||
void SpkMainWindow::PopulateAppDetails(QJsonObject appDetails)
|
||||
{
|
||||
QString pkgName, author, contributor, site, iconPath, arch, version, details, shortDesc, name;
|
||||
QString pkgName, author, contributor, site, iconPath, arch, version, details, shortDesc, name,
|
||||
pkgPath;
|
||||
QStringList screenshots, tags;
|
||||
int packageSize;
|
||||
static auto err =
|
||||
@@ -280,6 +292,8 @@ void SpkMainWindow::PopulateAppDetails(QJsonObject appDetails)
|
||||
arch = appDetails.value("arch").toString();
|
||||
if(appDetails.contains("size") && appDetails.value("size").isDouble())
|
||||
packageSize = appDetails.value("size").toInt();
|
||||
if(appDetails.contains("deb_url") && appDetails.value("deb_url").isString())
|
||||
pkgPath = appDetails.value("deb_url").toString();
|
||||
|
||||
QJsonArray imgs;
|
||||
if(appDetails.contains("img_urls") && appDetails.value("img_urls").isArray())
|
||||
@@ -310,6 +324,7 @@ void SpkMainWindow::PopulateAppDetails(QJsonObject appDetails)
|
||||
w->mArch->SetValue(arch);
|
||||
w->mSize->SetValue(SpkUtils::BytesToSize(packageSize));
|
||||
w->mVersion->setText(version);
|
||||
w->SetPackagePath(pkgPath);
|
||||
SwitchToPage(SpkUi::PgAppDetails);
|
||||
ui->AppDetailsItem->setHidden(false);
|
||||
ui->CategoryWidget->setCurrentItem(ui->AppDetailsItem);
|
||||
@@ -345,6 +360,8 @@ void SpkMainWindow::Initialize()
|
||||
connect(SpkUi::DtkPlugin, &SpkDtkPlugin::DarkLightThemeChanged,
|
||||
this, &SpkMainWindow::ReloadThemedUiIcons);
|
||||
}
|
||||
connect(ui->PageAppDetails, &SpkUi::SpkPageAppDetails::RequestDownload,
|
||||
ui->PageDownloads, &SpkUi::SpkPageDownloads::AddDownloadTask);
|
||||
|
||||
// Register themed button icons
|
||||
// mThemedUiIconReferences.append({ ui->BtnSettings, "settings" });
|
||||
@@ -417,6 +434,11 @@ SpkUi::SpkMainWidget::SpkMainWidget(QWidget *parent) : QFrame(parent)
|
||||
BtnDayNight->setFixedSize({ 40, 40 });
|
||||
BtnDayNight->SetIcon(QIcon(":/icons/daynight.svg"), QSize(20, 20));
|
||||
|
||||
BtnBack = new SpkIconButton(this);
|
||||
BtnBack->setFixedSize({ 40, 40 });
|
||||
BtnBack->SetIcon(QIcon(":/icons/back.svg"), QSize(20, 20));
|
||||
BtnBack->setVisible(false);
|
||||
|
||||
HLaySideTop->addWidget(StoreIcon);
|
||||
HLaySideTop->addStretch();
|
||||
HLaySideTop->addWidget(BtnDayNight);
|
||||
@@ -510,8 +532,14 @@ SpkUi::SpkMainWidget::SpkMainWidget(QWidget *parent) : QFrame(parent)
|
||||
SearchEdit->setFixedWidth(static_cast<int>(250 * v) + 30);
|
||||
});
|
||||
connect(ActClearSearchBar, &QAction::triggered, [=](){ SearchEdit->clear(); });
|
||||
connect(BtnBack, &QPushButton::clicked,
|
||||
[=](){
|
||||
SidebarMgr->GoBack();
|
||||
BtnBack->setEnabled(false);
|
||||
});
|
||||
|
||||
auto space = TitleBar->GetUserSpace();
|
||||
space->addWidget(BtnBack);
|
||||
space->addWidget(SearchEdit);
|
||||
space->addStretch();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user