mirror of
https://gitee.com/spark-store-project/spark-store
synced 2025-12-13 20:32:05 +08:00
添加应用详情页面
This commit is contained in:
@@ -75,6 +75,7 @@ set(SOURCE_FILES
|
|||||||
inc/page/spkpagebase.h gui/page/spkpagebase.cpp
|
inc/page/spkpagebase.h gui/page/spkpagebase.cpp
|
||||||
inc/page/spkpageuitest.h gui/page/spkpageuitest.cpp
|
inc/page/spkpageuitest.h gui/page/spkpageuitest.cpp
|
||||||
inc/page/spkpageapplist.h gui/page/spkpageapplist.cpp
|
inc/page/spkpageapplist.h gui/page/spkpageapplist.cpp
|
||||||
|
inc/page/spkpageappdetails.h gui/page/spkpageappdetails.cpp
|
||||||
|
|
||||||
inc/spkstore.h src/spkstore.cpp
|
inc/spkstore.h src/spkstore.cpp
|
||||||
inc/spkuimsg.h src/spkuimsg.cpp
|
inc/spkuimsg.h src/spkuimsg.cpp
|
||||||
|
|||||||
@@ -40,4 +40,13 @@ C++ 规范要求的和第三方库有较大差异的除外。例如,`SpkUiMess
|
|||||||
如非第三方代码,一般以 `Spk` 前缀标明。
|
如非第三方代码,一般以 `Spk` 前缀标明。
|
||||||
实现 UI 的类都应归于 `SpkUi` 命名空间。
|
实现 UI 的类都应归于 `SpkUi` 命名空间。
|
||||||
|
|
||||||
|
## 类定义
|
||||||
|
|
||||||
|
### 一般规则
|
||||||
|
|
||||||
|
Qt 类的 `Q_OBJECT` 应置于类定义最顶端。
|
||||||
|
`public` ,`protected` 和 `private` 等标签中只应该包含一类成员,
|
||||||
|
如单个 `public` 标签内只能包含方法,或成员。
|
||||||
|
信号、槽等不得与普通方法混合。
|
||||||
|
|
||||||
<!--TODO-->
|
<!--TODO-->
|
||||||
182
gui/page/spkpageappdetails.cpp
Normal file
182
gui/page/spkpageappdetails.cpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
#include "page/spkpageappdetails.h"
|
||||||
|
#include "spkutils.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace SpkUi
|
||||||
|
{
|
||||||
|
constexpr QSize SpkPageAppDetails::IconSize;
|
||||||
|
|
||||||
|
void SpkPageAppDetails::LoadAppResources(QString aPkgName, QString aIcon, QStringList aScreenshots,
|
||||||
|
QStringList aTags)
|
||||||
|
{
|
||||||
|
QPixmap pic;
|
||||||
|
|
||||||
|
// Load icon
|
||||||
|
auto res = RES->RequestResource(0, aPkgName, SpkResource::ResourceType::AppIcon, aIcon);
|
||||||
|
if(res.status == SpkResource::ResourceStatus::Ready)
|
||||||
|
{
|
||||||
|
if(pic.loadFromData(res.data))
|
||||||
|
mAppIcon->setPixmap(pic.scaled(IconSize,
|
||||||
|
Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mAppIcon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(SpkAppItem::IconSize_));
|
||||||
|
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppIcon, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load screenshots
|
||||||
|
if(aScreenshots.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int shotId = 0;
|
||||||
|
for(auto &i : aScreenshots)
|
||||||
|
{
|
||||||
|
shotId++;
|
||||||
|
res = RES->RequestResource(shotId, aPkgName, SpkResource::ResourceType::AppScreenshot, aIcon,
|
||||||
|
shotId);
|
||||||
|
if(res.status == SpkResource::ResourceStatus::Ready)
|
||||||
|
{
|
||||||
|
if(pic.loadFromData(res.data))
|
||||||
|
;// TODO
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// mAppIcon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(SpkAppItem::IconSize_));
|
||||||
|
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppScreenshot, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: tags
|
||||||
|
}
|
||||||
|
|
||||||
|
SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent)
|
||||||
|
{
|
||||||
|
mMainArea = new QScrollArea;
|
||||||
|
mMainArea->setWidgetResizable(true);
|
||||||
|
mMainArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
|
||||||
|
mLay4MainArea = new QVBoxLayout(this);
|
||||||
|
mLay4MainArea->addWidget(mMainArea);
|
||||||
|
|
||||||
|
mMainLay = new QVBoxLayout(mMainArea);
|
||||||
|
mMainLay->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||||
|
|
||||||
|
mAppIcon = new QLabel;
|
||||||
|
|
||||||
|
mAppTitle = new QLabel;
|
||||||
|
mAppTitle->setObjectName("styDetTitle");
|
||||||
|
|
||||||
|
mAppDescription = new QLabel;
|
||||||
|
mAppDescription->setObjectName("styDetDesc");
|
||||||
|
mAppDescription->setWordWrap(true);
|
||||||
|
mAppShortDesc = new QLabel;
|
||||||
|
mAppShortDesc->setObjectName("styDetDesc");
|
||||||
|
mAppShortDesc->setWordWrap(true);
|
||||||
|
// NOTE: Seems Qt have trouble dealing with wrapped text here. Removing the following operations
|
||||||
|
// to mAppShortDesc will result in broken layout. Very possible that it's a Qt bug.
|
||||||
|
mAppShortDesc->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||||
|
mAppShortDesc->setMinimumWidth(100);
|
||||||
|
mVersion = new QLabel;
|
||||||
|
mPkgName = new QLabel;
|
||||||
|
mPkgName->setObjectName("styDetPkg");
|
||||||
|
|
||||||
|
mTitleLay = new QVBoxLayout;
|
||||||
|
mTitleLay->setAlignment(Qt::AlignTop);
|
||||||
|
mTitleLay->addWidget(mAppTitle);
|
||||||
|
mTitleLay->addWidget(mVersion);
|
||||||
|
mTitleLay->addWidget(mAppShortDesc);
|
||||||
|
mTitleLay->addWidget(mPkgName);
|
||||||
|
mTitleLay->setSpacing(0);
|
||||||
|
|
||||||
|
mIconTitleLay = new QHBoxLayout;
|
||||||
|
mIconTitleLay->setAlignment(Qt::AlignLeft);
|
||||||
|
mIconTitleLay->addWidget(mAppIcon);
|
||||||
|
mIconTitleLay->addSpacing(15);
|
||||||
|
mIconTitleLay->addLayout(mTitleLay);
|
||||||
|
|
||||||
|
mIconTitleWidget = new QWidget;
|
||||||
|
mIconTitleWidget->setLayout(mIconTitleLay);
|
||||||
|
|
||||||
|
mAuthor = new SpkDetailEntry;
|
||||||
|
mAuthor->SetTitle(tr("Author"));
|
||||||
|
mContributor = new SpkDetailEntry;
|
||||||
|
mContributor->SetTitle(tr("Contributor"));
|
||||||
|
mSite = new SpkDetailEntry;
|
||||||
|
mSite->SetTitle(tr("Website"));
|
||||||
|
mArch = new SpkDetailEntry;
|
||||||
|
mArch->SetTitle(tr("Architecture"));
|
||||||
|
mSize = new SpkDetailEntry;
|
||||||
|
mSize->SetTitle(tr("Size"));
|
||||||
|
|
||||||
|
mDetailLay = new SpkStretchLayout;
|
||||||
|
mDetailLay->setSpacing(12);
|
||||||
|
mDetailLay->addWidget(mAuthor);
|
||||||
|
mDetailLay->addWidget(mContributor);
|
||||||
|
mDetailLay->addWidget(mSize);
|
||||||
|
mDetailLay->addWidget(mArch);
|
||||||
|
mDetailLay->addWidget(mSite);
|
||||||
|
|
||||||
|
// mDetailWidget = new QWidget;
|
||||||
|
// mDetailWidget->setLayout(mDetailLay);
|
||||||
|
// mDetailWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||||
|
|
||||||
|
mMainLay->setAlignment(Qt::AlignTop);
|
||||||
|
mMainLay->addWidget(mIconTitleWidget);
|
||||||
|
mMainLay->addLayout(mDetailLay);
|
||||||
|
mMainLay->addWidget(mAppDescription);
|
||||||
|
// mMainLay->addStretch();
|
||||||
|
mWid4MainArea = new QWidget;
|
||||||
|
mWid4MainArea->setLayout(mMainLay);
|
||||||
|
|
||||||
|
mMainArea->setWidget(mWid4MainArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpkPageAppDetails::ResourceAcquisitionFinished(int id, ResourceResult result)
|
||||||
|
{
|
||||||
|
QPixmap icon;
|
||||||
|
if(!id)
|
||||||
|
{
|
||||||
|
// id == 0, icon
|
||||||
|
if(result.status == SpkResource::ResourceStatus::Ready)
|
||||||
|
{
|
||||||
|
if(icon.loadFromData(result.data))
|
||||||
|
mAppIcon->setPixmap(icon.scaled(SpkAppItem::IconSize_,
|
||||||
|
Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation));
|
||||||
|
else
|
||||||
|
mAppIcon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(SpkAppItem::IconSize_));
|
||||||
|
}
|
||||||
|
else if(result.status == SpkResource::ResourceStatus::Failed)
|
||||||
|
{
|
||||||
|
mAppIcon->setPixmap(QIcon::fromTheme("dialog-error").pixmap(SpkAppItem::IconSize_));
|
||||||
|
RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: screenshots
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpkPageAppDetails::Activated()
|
||||||
|
{
|
||||||
|
RES->Acquire(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpkDetailEntry::SpkDetailEntry(QWidget *parent) : QWidget(parent)
|
||||||
|
{
|
||||||
|
setLayout(&mLay);
|
||||||
|
mLay.addWidget(&mTitle);
|
||||||
|
mLay.addWidget(&mField);
|
||||||
|
mTitle.setAlignment(Qt::AlignLeft);
|
||||||
|
mField.setAlignment(Qt::AlignRight);
|
||||||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
setMinimumWidth(300);
|
||||||
|
setAutoFillBackground(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,6 +53,7 @@ namespace SpkUi
|
|||||||
auto item = new SpkAppItem(appId, this);
|
auto item = new SpkAppItem(appId, this);
|
||||||
auto id = mAppItemList.size();
|
auto id = mAppItemList.size();
|
||||||
|
|
||||||
|
connect(item, &SpkAppItem::clicked, this, &SpkPageAppList::ApplicationClicked);
|
||||||
item->SetTitle(name);
|
item->SetTitle(name);
|
||||||
item->SetDescription(description);
|
item->SetDescription(description);
|
||||||
item->setProperty("pkg_name", pkgName);
|
item->setProperty("pkg_name", pkgName);
|
||||||
|
|||||||
@@ -51,6 +51,18 @@ SpkUi::SpkPageUiTest::SpkPageUiTest(QWidget *parent) : QSplitter(parent)
|
|||||||
"Phasellus finibus risus id aliquam pulvinar.");
|
"Phasellus finibus risus id aliquam pulvinar.");
|
||||||
AppItem->SetIcon(QIcon::fromTheme("dialog-information").pixmap(72, 72));
|
AppItem->SetIcon(QIcon::fromTheme("dialog-information").pixmap(72, 72));
|
||||||
|
|
||||||
|
Detail1 = new SpkDetailEntry; Detail1->SetTitle("Foo"); Detail1->SetValue("1");
|
||||||
|
Detail2 = new SpkDetailEntry; Detail2->SetTitle("Foo"); Detail2->SetValue("1");
|
||||||
|
Detail3 = new SpkDetailEntry; Detail3->SetTitle("Foo"); Detail3->SetValue("1");
|
||||||
|
|
||||||
|
DetailsLay = new SpkStretchLayout;
|
||||||
|
DetailsLay->addWidget(Detail1);
|
||||||
|
DetailsLay->addWidget(Detail2);
|
||||||
|
DetailsLay->addWidget(Detail3);
|
||||||
|
|
||||||
|
DetailsWidget = new QWidget;
|
||||||
|
DetailsWidget->setLayout(DetailsLay);
|
||||||
|
|
||||||
PopupText = new QLineEdit(this);
|
PopupText = new QLineEdit(this);
|
||||||
PopupText->setObjectName("spk_pg_qsstest_poptext");
|
PopupText->setObjectName("spk_pg_qsstest_poptext");
|
||||||
PopupText->setText("Hello, world");
|
PopupText->setText("Hello, world");
|
||||||
@@ -85,6 +97,7 @@ SpkUi::SpkPageUiTest::SpkPageUiTest(QWidget *parent) : QSplitter(parent)
|
|||||||
VLayTestWidgets->addWidget(ShowPopup);
|
VLayTestWidgets->addWidget(ShowPopup);
|
||||||
VLayTestWidgets->addWidget(ShowAbout);
|
VLayTestWidgets->addWidget(ShowAbout);
|
||||||
VLayTestWidgets->addWidget(AppItem);
|
VLayTestWidgets->addWidget(AppItem);
|
||||||
|
VLayTestWidgets->addWidget(DetailsWidget);
|
||||||
|
|
||||||
Group = new QGroupBox(this);
|
Group = new QGroupBox(this);
|
||||||
Group->setObjectName("spk_pg_qsstest_groupbox");
|
Group->setObjectName("spk_pg_qsstest_groupbox");
|
||||||
|
|||||||
@@ -50,3 +50,15 @@ void SpkAppItem::paintEvent(QPaintEvent *e)
|
|||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpkAppItem::mousePressEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
mPressCond = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpkAppItem::mouseReleaseEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
if(mPressCond)
|
||||||
|
emit clicked(mAppId);
|
||||||
|
mPressCond = false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ void SpkMainWindow::PopulateAppList(QJsonObject appData, QString &&keyword)
|
|||||||
static auto err =
|
static auto err =
|
||||||
[](){
|
[](){
|
||||||
sErr("Received invalid application list data!");
|
sErr("Received invalid application list data!");
|
||||||
SpkUiMessage::SendStoreNotification(tr("An invalid response was received. Please try again!"));
|
SpkUiMessage::SendStoreNotification(tr("Received an invalid response. Please try again!"));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
int pgCurrent, pgTotal, totalApps;
|
int pgCurrent, pgTotal, totalApps;
|
||||||
@@ -178,7 +178,7 @@ void SpkMainWindow::PopulateAppList(QJsonObject appData, QString &&keyword)
|
|||||||
|
|
||||||
auto apps = appData.value("data").toArray();
|
auto apps = appData.value("data").toArray();
|
||||||
|
|
||||||
foreach(auto i, apps)
|
for(auto &&i : apps)
|
||||||
{
|
{
|
||||||
if(i.isObject())
|
if(i.isObject())
|
||||||
{
|
{
|
||||||
@@ -206,10 +206,112 @@ void SpkMainWindow::PopulateAppList(QJsonObject appData, QString &&keyword)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpkMainWindow::EnterAppDetails(int aAppId)
|
||||||
|
{
|
||||||
|
using namespace SpkUtils;
|
||||||
|
VerifySingleRequest(mAppDetailsGetReply);
|
||||||
|
QJsonObject reqData;
|
||||||
|
QJsonDocument reqDoc;
|
||||||
|
reqData.insert("application_id", QJsonValue(aAppId));
|
||||||
|
reqDoc.setObject(reqData);
|
||||||
|
mAppDetailsGetReply = STORE->SendApiRequest("application/get_application_detail", reqDoc);
|
||||||
|
DeleteReplyLater(mAppDetailsGetReply);
|
||||||
|
connect(mAppDetailsGetReply, &QNetworkReply::finished,
|
||||||
|
this, &SpkMainWindow::AppDetailsDataReceived);
|
||||||
|
setCursor(Qt::BusyCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpkMainWindow::AppDetailsDataReceived()
|
||||||
|
{
|
||||||
|
QJsonValue retval;
|
||||||
|
if(!SpkUtils::VerifyReplyJson(mAppDetailsGetReply, retval) || !retval.isObject())
|
||||||
|
{
|
||||||
|
sErrPop(tr("Failed to open app details page! Type of retval: %1.").arg(retval.type()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SwitchToPage(SpkUi::PgAppList);
|
||||||
|
PopulateAppDetails(retval.toObject());
|
||||||
|
setCursor(Qt::ArrowCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpkMainWindow::PopulateAppDetails(QJsonObject appDetails)
|
||||||
|
{
|
||||||
|
QString pkgName, author, contributor, site, iconPath, arch, version, details, shortDesc, name;
|
||||||
|
QStringList screenshots, tags;
|
||||||
|
int packageSize;
|
||||||
|
static auto err =
|
||||||
|
[](){
|
||||||
|
sErr("Received invalid application details!");
|
||||||
|
SpkUiMessage::SendStoreNotification(tr("Received an invalid response. Please try again!"));
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(appDetails.contains("package") && appDetails.value("package").isString())
|
||||||
|
pkgName = appDetails.value("package").toString();
|
||||||
|
else return err();
|
||||||
|
if(appDetails.contains("application_name_zh") && appDetails.value("application_name_zh").isString())
|
||||||
|
name = appDetails.value("application_name_zh").toString();
|
||||||
|
else name = pkgName;
|
||||||
|
if(appDetails.contains("version") && appDetails.value("version").isString())
|
||||||
|
version = appDetails.value("version").toString();
|
||||||
|
else return err();
|
||||||
|
if(appDetails.contains("icons") && appDetails.value("icons").isString())
|
||||||
|
iconPath= appDetails.value("icons").toString();
|
||||||
|
if(appDetails.contains("author") && appDetails.value("author").isString())
|
||||||
|
author = appDetails.value("author").toString();
|
||||||
|
if(appDetails.contains("contributor") && appDetails.value("contributor").isString())
|
||||||
|
contributor = appDetails.value("contributor").toString();
|
||||||
|
if(appDetails.contains("website") && appDetails.value("website").isString())
|
||||||
|
site = appDetails.value("website").toString();
|
||||||
|
if(appDetails.contains("description") && appDetails.value("description").isString())
|
||||||
|
shortDesc = appDetails.value("description").toString();
|
||||||
|
if(appDetails.contains("more") && appDetails.value("more").isString())
|
||||||
|
details = appDetails.value("more").toString();
|
||||||
|
if(appDetails.contains("arch") && appDetails.value("arch").isString())
|
||||||
|
arch = appDetails.value("arch").toString();
|
||||||
|
if(appDetails.contains("size") && appDetails.value("size").isDouble())
|
||||||
|
packageSize = appDetails.value("size").toInt();
|
||||||
|
|
||||||
|
QJsonArray imgs;
|
||||||
|
if(appDetails.contains("img_urls") && appDetails.value("img_urls").isArray())
|
||||||
|
imgs = appDetails.value("img_urls").toArray();
|
||||||
|
if(!imgs.isEmpty())
|
||||||
|
for(auto &&i : imgs)
|
||||||
|
if(i.isString()) screenshots << i.toString();
|
||||||
|
|
||||||
|
QJsonArray tags_j;
|
||||||
|
if(appDetails.contains("tags") && appDetails.value("tags").isArray())
|
||||||
|
imgs = appDetails.value("tags").toArray();
|
||||||
|
if(!tags_j.isEmpty())
|
||||||
|
for(auto &&i : tags_j)
|
||||||
|
if(i.isString()) tags << i.toString();
|
||||||
|
|
||||||
|
// Details string has a strangely appended LF. IDK but still should remove it.
|
||||||
|
shortDesc = shortDesc.trimmed();
|
||||||
|
|
||||||
|
auto w = ui->PageAppDetails;
|
||||||
|
w->mPkgName->setText(pkgName);
|
||||||
|
w->mAppTitle->setText(name);
|
||||||
|
w->mAppShortDesc->setText(shortDesc);
|
||||||
|
w->mAppDescription->setText(details);
|
||||||
|
w->mAuthor->SetValue(author);
|
||||||
|
w->mContributor->SetValue(contributor);
|
||||||
|
w->mSite->SetValue(site);
|
||||||
|
w->mArch->SetValue(arch);
|
||||||
|
w->mSize->SetValue(SpkUtils::BytesToSize(packageSize));
|
||||||
|
w->mVersion->setText(version);
|
||||||
|
SwitchToPage(SpkUi::PgAppDetails);
|
||||||
|
ui->AppDetailsItem->setHidden(false);
|
||||||
|
ui->CategoryWidget->setCurrentItem(ui->AppDetailsItem);
|
||||||
|
w->LoadAppResources(pkgName, iconPath, screenshots, tags);
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== Main Window Initialization ====================
|
// ==================== Main Window Initialization ====================
|
||||||
|
|
||||||
void SpkMainWindow::Initialize()
|
void SpkMainWindow::Initialize()
|
||||||
{
|
{
|
||||||
|
connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToPage,
|
||||||
|
this, &SpkMainWindow::SwitchToPage);
|
||||||
connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToCategory,
|
connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToCategory,
|
||||||
this, &SpkMainWindow::EnterCategoryList);
|
this, &SpkMainWindow::EnterCategoryList);
|
||||||
connect(ui->PageAppList, &SpkUi::SpkPageAppList::SwitchListPage,
|
connect(ui->PageAppList, &SpkUi::SpkPageAppList::SwitchListPage,
|
||||||
@@ -218,6 +320,8 @@ void SpkMainWindow::Initialize()
|
|||||||
this, &SpkMainWindow::SearchKeyword);
|
this, &SpkMainWindow::SearchKeyword);
|
||||||
connect(ui->SearchEdit, &QLineEdit::returnPressed,
|
connect(ui->SearchEdit, &QLineEdit::returnPressed,
|
||||||
[=](){ emit SearchKeyword(ui->SearchEdit->text(), 1); });
|
[=](){ emit SearchKeyword(ui->SearchEdit->text(), 1); });
|
||||||
|
connect(ui->PageAppList, &SpkUi::SpkPageAppList::ApplicationClicked,
|
||||||
|
this, &SpkMainWindow::EnterAppDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Main Widget Initialization ====================
|
// ==================== Main Widget Initialization ====================
|
||||||
@@ -292,11 +396,28 @@ SpkUi::SpkMainWidget::SpkMainWidget(QWidget *parent) : QFrame(parent)
|
|||||||
CategoryWidget->setColumnCount(1);
|
CategoryWidget->setColumnCount(1);
|
||||||
CategoryWidget->setHeaderHidden(true);
|
CategoryWidget->setHeaderHidden(true);
|
||||||
CategoryWidget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
|
CategoryWidget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
|
||||||
|
|
||||||
|
//============ Sidebar entries BEGIN ============
|
||||||
|
AppDetailsItem = new QTreeWidgetItem(QStringList(tr("App Details")));
|
||||||
|
AppDetailsItem->setData(0, SpkSidebarSelector::RoleItemIsCategory, false);
|
||||||
|
AppDetailsItem->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, SpkStackedPages::PgAppDetails);
|
||||||
CategoryParentItem = new QTreeWidgetItem(QStringList(tr("Categories")));
|
CategoryParentItem = new QTreeWidgetItem(QStringList(tr("Categories")));
|
||||||
CategoryParentItem->setFlags(CategoryParentItem->flags().setFlag(Qt::ItemIsSelectable, false));
|
CategoryParentItem->setFlags(CategoryParentItem->flags().setFlag(Qt::ItemIsSelectable, false));
|
||||||
CategoryParentItem->setExpanded(true);
|
#ifndef NDEBUG
|
||||||
|
UiTestItem = new QTreeWidgetItem(QStringList(tr("UI TEST")));
|
||||||
|
UiTestItem->setData(0, SpkSidebarSelector::RoleItemIsCategory, false);
|
||||||
|
UiTestItem->setData(0, SpkSidebarSelector::RoleItemCategoryPageId, SpkStackedPages::PgQssTest);
|
||||||
|
#endif
|
||||||
|
//============ Sidebar entries END ============
|
||||||
|
|
||||||
SidebarMgr->AddUnusableItem(CategoryParentItem);
|
SidebarMgr->AddUnusableItem(CategoryParentItem);
|
||||||
|
CategoryWidget->addTopLevelItem(AppDetailsItem);
|
||||||
CategoryWidget->addTopLevelItem(CategoryParentItem);
|
CategoryWidget->addTopLevelItem(CategoryParentItem);
|
||||||
|
CategoryWidget->addTopLevelItem(UiTestItem);
|
||||||
|
|
||||||
|
// Must be done after added into a view.
|
||||||
|
AppDetailsItem->setHidden(true); // Hide until we actually open up a Details page
|
||||||
|
CategoryParentItem->setExpanded(true);
|
||||||
|
|
||||||
// FIXMEIFPOSSIBLE: Fusion adds extra gradient.
|
// FIXMEIFPOSSIBLE: Fusion adds extra gradient.
|
||||||
// Details: https://forum.qt.io/topic/128190/fusion-style-kept-adding-an-extra-
|
// Details: https://forum.qt.io/topic/128190/fusion-style-kept-adding-an-extra-
|
||||||
@@ -355,7 +476,7 @@ SpkUi::SpkMainWidget::SpkMainWidget(QWidget *parent) : QFrame(parent)
|
|||||||
|
|
||||||
//============ Pages =============
|
//============ Pages =============
|
||||||
|
|
||||||
// Red-Black tree based map will be able to sort things
|
// Red-Black tree based map will be able to sort things. Just for convenience of ordering pages.
|
||||||
QMap<SpkStackedPages, QWidget*> sorter;
|
QMap<SpkStackedPages, QWidget*> sorter;
|
||||||
|
|
||||||
// Initialize pages
|
// Initialize pages
|
||||||
@@ -363,6 +484,10 @@ SpkUi::SpkMainWidget::SpkMainWidget(QWidget *parent) : QFrame(parent)
|
|||||||
PageAppList->setProperty("spk_pageid", SpkStackedPages::PgAppList);
|
PageAppList->setProperty("spk_pageid", SpkStackedPages::PgAppList);
|
||||||
sorter[PgAppList] = PageAppList;
|
sorter[PgAppList] = PageAppList;
|
||||||
|
|
||||||
|
PageAppDetails = new SpkUi::SpkPageAppDetails(this);
|
||||||
|
PageAppDetails->setProperty("spk_pageid", SpkStackedPages::PgAppDetails);
|
||||||
|
sorter[PgAppDetails] = PageAppDetails;
|
||||||
|
|
||||||
#ifndef NDEBUG // If only in debug mode should we initialize QSS test page
|
#ifndef NDEBUG // If only in debug mode should we initialize QSS test page
|
||||||
PageQssTest = new SpkUi::SpkPageUiTest(this);
|
PageQssTest = new SpkUi::SpkPageUiTest(this);
|
||||||
PageQssTest->setProperty("spk_pageid", SpkStackedPages::PgQssTest);
|
PageQssTest->setProperty("spk_pageid", SpkStackedPages::PgQssTest);
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ const std::map<SpkUi::Qss::ColorSetIndex, const char *> SpkUi::Qss::ColorSet2Tok
|
|||||||
{ TextOnSelection, "TXACC" },
|
{ TextOnSelection, "TXACC" },
|
||||||
{ TextOnGlobalBgnd, "TXGBG" },
|
{ TextOnGlobalBgnd, "TXGBG" },
|
||||||
{ TextOnControlsBgnd, "TXCBG" },
|
{ TextOnControlsBgnd, "TXCBG" },
|
||||||
{ TextLighter, "TXL" },
|
{ TextLighter, "TXL1" },
|
||||||
|
{ TextEvenLighter, "TXL2" },
|
||||||
{ TextDisabled, "TXD" },
|
{ TextDisabled, "TXD" },
|
||||||
{ GlossyEdge, "GLS" },
|
{ GlossyEdge, "GLS" },
|
||||||
{ ShadesEdge, "SHD" }
|
{ ShadesEdge, "SHD" }
|
||||||
@@ -51,6 +52,7 @@ const std::map<SpkUi::Qss::ColorSetIndex, QColor> SpkUi::Qss::DarkColorSet
|
|||||||
{ TextOnGlobalBgnd, ColorTextOnBackground(0x282828) },
|
{ TextOnGlobalBgnd, ColorTextOnBackground(0x282828) },
|
||||||
{ TextOnControlsBgnd, ColorTextOnBackground(0x282828) },
|
{ TextOnControlsBgnd, ColorTextOnBackground(0x282828) },
|
||||||
{ TextLighter, 0xd5d5d5 },
|
{ TextLighter, 0xd5d5d5 },
|
||||||
|
{ TextEvenLighter, 0x505050 },
|
||||||
{ TextDisabled, 0xbebebe },
|
{ TextDisabled, 0xbebebe },
|
||||||
{ GlossyEdge, 0x656565 },
|
{ GlossyEdge, 0x656565 },
|
||||||
{ ShadesEdge, 0x7b7b7b }
|
{ ShadesEdge, 0x7b7b7b }
|
||||||
@@ -75,6 +77,7 @@ const std::map<SpkUi::Qss::ColorSetIndex, QColor> SpkUi::Qss::LightColorSet
|
|||||||
{ TextOnGlobalBgnd, ColorTextOnBackground(0xf8f8f8) },
|
{ TextOnGlobalBgnd, ColorTextOnBackground(0xf8f8f8) },
|
||||||
{ TextOnControlsBgnd, ColorTextOnBackground(0xf8f8f8) },
|
{ TextOnControlsBgnd, ColorTextOnBackground(0xf8f8f8) },
|
||||||
{ TextLighter, 0x2a2a2a },
|
{ TextLighter, 0x2a2a2a },
|
||||||
|
{ TextEvenLighter, 0xa0a0a0 },
|
||||||
{ TextDisabled, 0x8a8a8a },
|
{ TextDisabled, 0x8a8a8a },
|
||||||
{ GlossyEdge, 0xc5c5c5 },
|
{ GlossyEdge, 0xc5c5c5 },
|
||||||
{ ShadesEdge, 0x9d9d9d }
|
{ ShadesEdge, 0x9d9d9d }
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ QSize SpkStretchLayout::sizeHint() const
|
|||||||
{
|
{
|
||||||
if(mItems.isEmpty())
|
if(mItems.isEmpty())
|
||||||
return { 300, 300 };
|
return { 300, 300 };
|
||||||
auto w = geometry().width();
|
auto w = geometry().width() - spacing();
|
||||||
auto it = mItems.first();
|
auto it = mItems.first();
|
||||||
int countPerLine = w / (it->minimumSize().width() + spacing());
|
int countPerLine = w / (it->minimumSize().width() + spacing());
|
||||||
int lines = ceil((double)mItems.size() / countPerLine);
|
int lines = ceil((double)mItems.size() / countPerLine);
|
||||||
@@ -75,14 +75,16 @@ void SpkStretchLayout::setGeometry(const QRect &rect)
|
|||||||
else // Stretch items.
|
else // Stretch items.
|
||||||
size = QSize {(w / countPerLine - spc), itm->maximumSize().height() };
|
size = QSize {(w / countPerLine - spc), itm->maximumSize().height() };
|
||||||
|
|
||||||
|
auto origin = geometry().topLeft();
|
||||||
|
|
||||||
QLayoutItem *o;
|
QLayoutItem *o;
|
||||||
for(int i = 0; i < mItems.size(); i++)
|
for(int i = 0; i < mItems.size(); i++)
|
||||||
{
|
{
|
||||||
o = mItems.at(i);
|
o = mItems.at(i);
|
||||||
QRect geo;
|
QRect geo;
|
||||||
geo.setSize(size);
|
geo.setSize(size);
|
||||||
geo.moveTo((i % countPerLine) * (size.width() + spc) + spc,
|
geo.moveTo((i % countPerLine) * (size.width() + spc) + spc + origin.x(),
|
||||||
(i / countPerLine) * (size.height() + spacing()) + spc);
|
(i / countPerLine) * (size.height() + spacing()) + spc + origin.y());
|
||||||
o->setGeometry(geo);
|
o->setGeometry(geo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
55
inc/page/spkpageappdetails.h
Normal file
55
inc/page/spkpageappdetails.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include "page/spkpagebase.h"
|
||||||
|
#include "spkstretchlayout.h"
|
||||||
|
|
||||||
|
namespace SpkUi
|
||||||
|
{
|
||||||
|
class SpkDetailEntry;
|
||||||
|
|
||||||
|
class SpkPageAppDetails : public SpkPageBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SpkPageAppDetails(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void LoadAppResources(QString pkgName, QString icon, QStringList screenshots, QStringList tags);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void ResourceAcquisitionFinished(int id, ResourceResult result);
|
||||||
|
void Activated();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr QSize IconSize { 144, 144 };
|
||||||
|
|
||||||
|
QScrollArea *mMainArea;
|
||||||
|
QWidget *mDetailWidget, *mIconTitleWidget, *mWid4MainArea;
|
||||||
|
QLabel *mAppTitle, *mAppIcon, *mAppDescription, *mAppShortDesc, *mPkgName, *mVersion;
|
||||||
|
SpkDetailEntry *mAuthor, *mContributor, *mSite, *mArch, *mSize;
|
||||||
|
SpkStretchLayout *mDetailLay;
|
||||||
|
QVBoxLayout *mMainLay, *mTitleLay, *mLay4MainArea;
|
||||||
|
QHBoxLayout *mIconTitleLay;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpkDetailEntry : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SpkDetailEntry(QWidget *parent = nullptr);
|
||||||
|
void SetTitle(const QString &s) { mTitle.setText(s); }
|
||||||
|
void SetValue(const QString &s) { mField.setText(s); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLabel mTitle, mField;
|
||||||
|
QHBoxLayout mLay;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ namespace SpkUi
|
|||||||
QString mKeyword;
|
QString mKeyword;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void ApplicationClicked(QString name, QString pkgName);
|
void ApplicationClicked(int appId);
|
||||||
void SwitchListPage(int categoryId, int page);
|
void SwitchListPage(int categoryId, int page);
|
||||||
void SwitchSearchPage(QString keyword, int page);
|
void SwitchSearchPage(QString keyword, int page);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
#include "spkappitem.h"
|
#include "spkappitem.h"
|
||||||
|
#include "spkstretchlayout.h"
|
||||||
|
#include "page/spkpageappdetails.h"
|
||||||
|
|
||||||
#include "spkloading.h"
|
#include "spkloading.h"
|
||||||
|
|
||||||
@@ -40,6 +42,9 @@ namespace SpkUi
|
|||||||
QSlider *SlideV;
|
QSlider *SlideV;
|
||||||
SpkLoading *Loading;
|
SpkLoading *Loading;
|
||||||
SpkAppItem *AppItem;
|
SpkAppItem *AppItem;
|
||||||
|
SpkStretchLayout *DetailsLay;
|
||||||
|
SpkDetailEntry *Detail1, *Detail2, *Detail3;
|
||||||
|
QWidget *DetailsWidget;
|
||||||
|
|
||||||
QLineEdit *PopupText;
|
QLineEdit *PopupText;
|
||||||
QPushButton *ShowPopup,
|
QPushButton *ShowPopup,
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class SpkAppItem : public QWidget
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e);
|
void paintEvent(QPaintEvent *e);
|
||||||
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr int IconSize = 72;
|
static constexpr int IconSize = 72;
|
||||||
@@ -29,7 +31,11 @@ class SpkAppItem : public QWidget
|
|||||||
ElidedLabel *mDescription;
|
ElidedLabel *mDescription;
|
||||||
int mAppId;
|
int mAppId;
|
||||||
|
|
||||||
|
bool mPressCond;
|
||||||
|
|
||||||
QVBoxLayout *mLayText;
|
QVBoxLayout *mLayText;
|
||||||
QHBoxLayout *mMainLay;
|
QHBoxLayout *mMainLay;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void clicked(int);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "spkfocuslineedit.h"
|
#include "spkfocuslineedit.h"
|
||||||
#include "page/spkpageuitest.h"
|
#include "page/spkpageuitest.h"
|
||||||
#include "page/spkpageapplist.h"
|
#include "page/spkpageapplist.h"
|
||||||
|
#include "page/spkpageappdetails.h"
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ namespace SpkUi
|
|||||||
{
|
{
|
||||||
PgInvalid = -1,
|
PgInvalid = -1,
|
||||||
PgAppList,
|
PgAppList,
|
||||||
|
PgAppDetails,
|
||||||
PgQssTest // Must be at last
|
PgQssTest // Must be at last
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ namespace SpkUi
|
|||||||
mLastSelectedItem = nullptr;
|
mLastSelectedItem = nullptr;
|
||||||
}
|
}
|
||||||
mLastCheckedBtn = b;
|
mLastCheckedBtn = b;
|
||||||
emit SwitchToPage(b->property("spk_pageno").toInt());
|
emit SwitchToPage(static_cast<SpkStackedPages>(b->property("spk_pageno").toInt()));
|
||||||
}
|
}
|
||||||
void TreeItemSelected(QTreeWidgetItem *item, int column)
|
void TreeItemSelected(QTreeWidgetItem *item, int column)
|
||||||
{
|
{
|
||||||
@@ -103,7 +105,8 @@ namespace SpkUi
|
|||||||
if(item->data(column, RoleItemIsCategory).toBool())
|
if(item->data(column, RoleItemIsCategory).toBool())
|
||||||
emit SwitchToCategory(item->data(column, RoleItemCategoryPageId).toInt(), 0);
|
emit SwitchToCategory(item->data(column, RoleItemCategoryPageId).toInt(), 0);
|
||||||
else
|
else
|
||||||
emit SwitchToPage(item->data(column, RoleItemCategoryPageId).toInt());
|
emit SwitchToPage(static_cast<SpkStackedPages>(
|
||||||
|
item->data(column, RoleItemCategoryPageId).toInt()));
|
||||||
}
|
}
|
||||||
void UnusableItemSelected(QTreeWidgetItem *i)
|
void UnusableItemSelected(QTreeWidgetItem *i)
|
||||||
{
|
{
|
||||||
@@ -120,7 +123,7 @@ namespace SpkUi
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SwitchToCategory(int aCategoryId, int aPage);
|
void SwitchToCategory(int aCategoryId, int aPage);
|
||||||
void SwitchToPage(int aPageId);
|
void SwitchToPage(SpkStackedPages aPageId);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SpkMainWidget : public QFrame
|
class SpkMainWidget : public QFrame
|
||||||
@@ -146,7 +149,9 @@ namespace SpkUi
|
|||||||
QMap<int, QTreeWidgetItem> *CategoryItemMap;
|
QMap<int, QTreeWidgetItem> *CategoryItemMap;
|
||||||
SpkSidebarSelector *SidebarMgr;
|
SpkSidebarSelector *SidebarMgr;
|
||||||
|
|
||||||
QTreeWidgetItem *CategoryParentItem;
|
QTreeWidgetItem *CategoryParentItem,
|
||||||
|
*AppDetailsItem,
|
||||||
|
*UiTestItem;
|
||||||
|
|
||||||
// Title bar search bar
|
// Title bar search bar
|
||||||
SpkFocusLineEdit *SearchEdit;
|
SpkFocusLineEdit *SearchEdit;
|
||||||
@@ -156,6 +161,7 @@ namespace SpkUi
|
|||||||
//Pages
|
//Pages
|
||||||
SpkPageUiTest *PageQssTest;
|
SpkPageUiTest *PageQssTest;
|
||||||
SpkPageAppList *PageAppList;
|
SpkPageAppList *PageAppList;
|
||||||
|
SpkPageAppDetails *PageAppDetails;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +181,8 @@ class SpkMainWindow : public SpkWindow
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<QNetworkReply> mCategoryGetReply,
|
QPointer<QNetworkReply> mCategoryGetReply,
|
||||||
mCategoryAppListGetReply;
|
mCategoryAppListGetReply,
|
||||||
|
mAppDetailsGetReply;
|
||||||
SpkUi::SpkStackedPages mCurrentPage = SpkUi::PgInvalid;
|
SpkUi::SpkStackedPages mCurrentPage = SpkUi::PgInvalid;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@@ -191,7 +198,11 @@ class SpkMainWindow : public SpkWindow
|
|||||||
// Search a keyword (and switch pages)
|
// Search a keyword (and switch pages)
|
||||||
void SearchKeyword(QString aKeyword, int aPage);
|
void SearchKeyword(QString aKeyword, int aPage);
|
||||||
void SearchDataReceived();
|
void SearchDataReceived();
|
||||||
|
// Enter the details page of an application (and switch pages)
|
||||||
|
void EnterAppDetails(int aAppId);
|
||||||
|
void AppDetailsDataReceived();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PopulateAppList(QJsonObject appData, QString &&keyword);
|
void PopulateAppList(QJsonObject appData, QString &&keyword);
|
||||||
|
void PopulateAppDetails(QJsonObject appDetails);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace SpkUi
|
|||||||
TextOnGlobalBgnd,
|
TextOnGlobalBgnd,
|
||||||
TextOnControlsBgnd,
|
TextOnControlsBgnd,
|
||||||
TextLighter,
|
TextLighter,
|
||||||
|
TextEvenLighter,
|
||||||
TextDisabled,
|
TextDisabled,
|
||||||
GlossyEdge,
|
GlossyEdge,
|
||||||
ShadesEdge,
|
ShadesEdge,
|
||||||
|
|||||||
@@ -26,4 +26,5 @@ namespace SpkUtils
|
|||||||
|
|
||||||
QString CutFileName(QString);
|
QString CutFileName(QString);
|
||||||
QString CutPath(QString);
|
QString CutPath(QString);
|
||||||
|
QString BytesToSize(size_t s, int prec = 2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
TXACC: Text on Selection/Activation
|
TXACC: Text on Selection/Activation
|
||||||
TXGBG: Text on Global background
|
TXGBG: Text on Global background
|
||||||
TXCBG: Text on controls background
|
TXCBG: Text on controls background
|
||||||
TXL: Text slightly lighter
|
TXL1: Text slightly lighter
|
||||||
|
TXL2: Text lighter even more
|
||||||
TXD: Text disabled
|
TXD: Text disabled
|
||||||
GLS: Glossy edge on controls
|
GLS: Glossy edge on controls
|
||||||
SHD: Shades edge on controls
|
SHD: Shades edge on controls
|
||||||
@@ -106,7 +107,7 @@ ElidedLabel
|
|||||||
|
|
||||||
#styAboutDesc
|
#styAboutDesc
|
||||||
{
|
{
|
||||||
color: TXL
|
color: TXL1
|
||||||
}
|
}
|
||||||
|
|
||||||
SpkAppItem
|
SpkAppItem
|
||||||
@@ -126,12 +127,29 @@ SpkAppItem::hover
|
|||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#styDetTitle
|
||||||
|
{
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
#styAppItmDesc
|
#styAppItmDesc
|
||||||
{
|
{
|
||||||
color: TXL;
|
color: TXL1;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#styDetDesc
|
||||||
|
{
|
||||||
|
color: TXL1;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#styDetPkg
|
||||||
|
{
|
||||||
|
color: TXL2
|
||||||
|
}
|
||||||
|
|
||||||
#styChkBtn
|
#styChkBtn
|
||||||
{
|
{
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
|
|||||||
@@ -88,3 +88,14 @@ QString SpkUtils::CutPath(QString path)
|
|||||||
{
|
{
|
||||||
return path.section('/', 1, -2, QString::SectionIncludeLeadingSep);
|
return path.section('/', 1, -2, QString::SectionIncludeLeadingSep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SpkUtils::BytesToSize(size_t s, int prec)
|
||||||
|
{
|
||||||
|
if(s > (1 << 30))
|
||||||
|
return QString::number(double (s) / (1 << 30), 'f', prec) + " GB";
|
||||||
|
if(s > (1 << 20))
|
||||||
|
return QString::number(double (s) / (1 << 20), 'f', prec) + " MB";
|
||||||
|
if(s > (1 << 10))
|
||||||
|
return QString::number(double (s) / (1 << 10), 'f', prec) + " KB";
|
||||||
|
return QString::number(s) + " B";
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user