加入应用列表的翻页功能

This commit is contained in:
RigoLigoRLC
2021-09-06 20:19:52 +08:00
parent 4ede620e71
commit f5649a121f
7 changed files with 148 additions and 28 deletions

View File

@@ -1,14 +1,50 @@
#include <page/spkpageapplist.h> #include "page/spkpageapplist.h"
#include "inc/page/spkpageapplist.h"
#include "spkutils.h" #include "spkutils.h"
#include "spkuimsg.h"
namespace SpkUi namespace SpkUi
{ {
SpkPageAppList::SpkPageAppList(QWidget *parent) : SpkPageBase(parent) SpkPageAppList::SpkPageAppList(QWidget *parent) : SpkPageBase(parent)
{ {
mItemLay = new SpkStretchLayout(this); mAppsWidget = new QWidget;
mItemLay->setContentsMargins(6, 6, 6, 6); mAppsArea = new QScrollArea(this);
mMainLay = new QVBoxLayout(this);
mItemLay = new SpkStretchLayout(mAppsWidget);
mPageSwitchWidget = new QWidget;
mPageSwitchLay = new QHBoxLayout(mPageSwitchWidget);
mBtnPgUp = new QPushButton;
mBtnPgDown = new QPushButton;
mBtnGotoPage = new QPushButton;
mPageInput = new QLineEdit;
mPageValidator = new QIntValidator(mPageInput);
mPageIndicator = new QLabel;
mPageValidator->setRange(1, 99);
mPageInput->setFixedWidth(50);
mPageInput->setValidator(mPageValidator);
mBtnGotoPage->setText(tr("Goto"));
mBtnPgUp->setText(tr("Previous"));
mBtnPgDown->setText(tr("Next"));
mPageSwitchLay->addWidget(mPageIndicator);
mPageSwitchLay->addStretch();
mPageSwitchLay->addWidget(mPageInput);
mPageSwitchLay->addWidget(mBtnGotoPage);
mPageSwitchLay->addWidget(mBtnPgUp);
mPageSwitchLay->addWidget(mBtnPgDown);
mAppsArea->setWidget(mAppsWidget);
mAppsArea->setWidgetResizable(true);
mMainLay->addWidget(mAppsArea);
mMainLay->addWidget(mPageSwitchWidget);
setLayout(mMainLay);
connect(mBtnPgUp, &QPushButton::clicked, this, &SpkPageAppList::PageUp);
connect(mBtnPgDown, &QPushButton::clicked, this, &SpkPageAppList::PageDown);
connect(mBtnGotoPage, &QPushButton::clicked, this, &SpkPageAppList::GotoPage);
} }
void SpkPageAppList::AddApplicationEntry(QString name, QString pkgName, QString description, void SpkPageAppList::AddApplicationEntry(QString name, QString pkgName, QString description,
@@ -78,6 +114,48 @@ namespace SpkUi
} }
} }
void SpkPageAppList::SetPageStatus(int total, int current, int itemCount)
{
mCurrentPage = current;
mPageIndicator->setText(tr("Page %1 / %2, %3 apps in total")
.arg(current).arg(total).arg(itemCount));
mBtnPgUp->setDisabled(current == 1);
mBtnPgDown->setDisabled(total == current || total == 1);
mBtnGotoPage->setDisabled(total == 1);
mPageValidator->setTop(total);
}
void SpkPageAppList::DisablePageSwitchers()
{
mBtnPgDown->setDisabled(true);
mBtnPgUp->setDisabled(true);
mBtnGotoPage->setDisabled(true);
}
void SpkPageAppList::PageUp()
{
DisablePageSwitchers();
emit SwitchListPage(mCategoryId, mCurrentPage - 1);
}
void SpkPageAppList::PageDown()
{
DisablePageSwitchers();
emit SwitchListPage(mCategoryId, mCurrentPage + 1);
}
void SpkPageAppList::GotoPage()
{
if(mPageInput->text().isEmpty())
return SpkUiMessage::SendStoreNotification(tr("Please enter page number to go to!"));
int page = mPageInput->text().toInt();
if(page > mPageValidator->top())
return SpkUiMessage::SendStoreNotification(tr("Page %1 is not a valid page number!")
.arg(page));
DisablePageSwitchers();
emit SwitchListPage(mCategoryId, page);
}
void SpkPageAppList::Activated() void SpkPageAppList::Activated()
{ {
RES->Acquire(this, false); RES->Acquire(this, false);

View File

@@ -1,7 +1,7 @@
#include "page/spkpagebase.h" #include "page/spkpagebase.h"
SpkPageBase::SpkPageBase(QWidget *parent) : QScrollArea(parent) SpkPageBase::SpkPageBase(QWidget *parent) : QWidget(parent)
{ {
} }

View File

@@ -89,7 +89,7 @@ void SpkMainWindow::CategoryDataReceived()
PopulateCategories(retval.toArray()); PopulateCategories(retval.toArray());
} }
void SpkMainWindow::EnterCategoryList(int aCategoryId) void SpkMainWindow::EnterCategoryList(int aCategoryId, int aPage)
{ {
// Asynchronously call category API // Asynchronously call category API
using namespace SpkUtils; using namespace SpkUtils;
@@ -97,12 +97,14 @@ void SpkMainWindow::EnterCategoryList(int aCategoryId)
QJsonObject reqData; QJsonObject reqData;
QJsonDocument reqDoc; QJsonDocument reqDoc;
reqData.insert("type_id", QJsonValue(aCategoryId)); reqData.insert("type_id", QJsonValue(aCategoryId));
reqData.insert("page", QJsonValue(aPage));
reqDoc.setObject(reqData); reqDoc.setObject(reqData);
mCategoryAppListGetReply = STORE->SendApiRequest("application/get_application_list", reqDoc); mCategoryAppListGetReply = STORE->SendApiRequest("application/get_application_list", reqDoc);
DeleteReplyLater(mCategoryAppListGetReply); DeleteReplyLater(mCategoryAppListGetReply);
connect(mCategoryAppListGetReply, &QNetworkReply::finished, connect(mCategoryAppListGetReply, &QNetworkReply::finished,
this, &SpkMainWindow::CategoryListDataReceived); this, &SpkMainWindow::CategoryListDataReceived);
setCursor(Qt::BusyCursor); setCursor(Qt::BusyCursor);
ui->PageAppList->SetCurrentCategory(aCategoryId); // AppList needs to remember current category
} }
void SpkMainWindow::CategoryListDataReceived() void SpkMainWindow::CategoryListDataReceived()
@@ -122,12 +124,27 @@ void SpkMainWindow::PopulateAppList(QJsonObject appData)
{ {
auto w = ui->PageAppList; auto w = ui->PageAppList;
w->ClearAll(); w->ClearAll();
static auto err =
[](){
sErr("Received invalid application list data!");
SpkUiMessage::SendStoreNotification(tr("An invalid response was received. Please try again!"));
return;
};
int pgCurrent, pgTotal, totalApps;
if(appData.contains("currentPage") && appData.value("currentPage").isDouble())
pgCurrent = appData.value("currentPage").toInt();
else return err();
if(appData.contains("totalPages") && appData.value("totalPages").isDouble())
pgTotal = appData.value("totalPages").toInt();
else return err();
if(appData.contains("count") && appData.value("count").isDouble())
totalApps = appData.value("count").toInt();
else return err();
w->SetPageStatus(pgTotal, pgCurrent, totalApps);
if(!appData.contains("data") || !appData.value("data").isArray()) if(!appData.contains("data") || !appData.value("data").isArray())
{ return err();
sErrPop(tr("Received invalid application list data!"));
return;
}
auto apps = appData.value("data").toArray(); auto apps = appData.value("data").toArray();
@@ -165,6 +182,8 @@ void SpkMainWindow::Initialize()
{ {
connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToCategory, connect(ui->SidebarMgr, &SpkUi::SpkSidebarSelector::SwitchToCategory,
this, &SpkMainWindow::EnterCategoryList); this, &SpkMainWindow::EnterCategoryList);
connect(ui->PageAppList, &SpkUi::SpkPageAppList::SwitchListPage,
this, &SpkMainWindow::EnterCategoryList);
} }
// ==================== Main Widget Initialization ==================== // ==================== Main Widget Initialization ====================

View File

@@ -19,21 +19,22 @@ void SpkStretchLayout::addItem(QLayoutItem *item)
QSize SpkStretchLayout::sizeHint() const QSize SpkStretchLayout::sizeHint() const
{ {
int n = mItems.count(); if(mItems.isEmpty())
auto minSize = mItems.isEmpty() ? QSize { 0, 0 } : mItems.first()->minimumSize(); return { 300, 300 };
QSize s { 200, 50 }; // s: Hint auto w = geometry().width();
if(n) auto it = mItems.first();
s = s.expandedTo(QSize { minSize.width(), minSize.height() * n }); int countPerLine = w / (it->minimumSize().width() + spacing());
return s + n * QSize(spacing(), spacing()); int lines = ceil((double)mItems.size() / countPerLine);
auto h = static_cast<int>(it->minimumSize().height() * lines + spacing() * lines);
return { w, h };
} }
QSize SpkStretchLayout::minimumSize() const QSize SpkStretchLayout::minimumSize() const
{ {
int n = mItems.count(); // It works this way, but I honestly have no idea WHY IT WORKS
auto minSize = mItems.isEmpty() ? QSize { 0, 0 } : mItems.first()->minimumSize(); auto r = sizeHint();
QSize s(minSize.width(), minSize.height() * n); r.setWidth(300);
return s + n * QSize(spacing(), spacing()); return r;
} }
int SpkStretchLayout::count() const int SpkStretchLayout::count() const
@@ -65,6 +66,9 @@ void SpkStretchLayout::setGeometry(const QRect &rect)
// Figure out how many at most can we squeeze into one line // Figure out how many at most can we squeeze into one line
int countPerLine = w / (itm->minimumSize().width() + spacing()); int countPerLine = w / (itm->minimumSize().width() + spacing());
if(countPerLine < 1)
countPerLine = 1;
if(countPerLine >= mItems.size()) // All items fit in one line if(countPerLine >= mItems.size()) // All items fit in one line
size = itm->minimumSize(); size = itm->minimumSize();
// Won't fit in one line. // Won't fit in one line.

View File

@@ -1,8 +1,7 @@
#pragma once #pragma once
#include <QScrollArea> #include <QtWidgets>
#include <QList>
#include "spkresource.h" #include "spkresource.h"
#include "spkappitem.h" #include "spkappitem.h"
#include "page/spkpagebase.h" #include "page/spkpagebase.h"
@@ -19,20 +18,40 @@ namespace SpkUi
void AddApplicationEntry(QString name, QString pkgName, QString description, QString iconUrl, void AddApplicationEntry(QString name, QString pkgName, QString description, QString iconUrl,
int appId); int appId);
void ClearAll(); void ClearAll();
void SetPageStatus(int total, int current, int itemCount);
void SetCurrentCategory(int categoryId) { mCategoryId = categoryId; }
private: private:
void DisablePageSwitchers();
public: public:
private: private:
QVBoxLayout *mMainLay;
QHBoxLayout *mPageSwitchLay;
QPushButton *mBtnPgUp, *mBtnPgDown, *mBtnGotoPage;
QLineEdit *mPageInput;
QScrollArea *mAppsArea;
QLabel *mPageIndicator;
QWidget *mAppsWidget, *mPageSwitchWidget;
SpkStretchLayout *mItemLay; SpkStretchLayout *mItemLay;
QList<SpkAppItem *> mAppItemList; QList<SpkAppItem *> mAppItemList;
QIntValidator *mPageValidator;
int mCategoryId, mCurrentPage;
signals: signals:
void ApplicationClicked(QString name, QString pkgName); void ApplicationClicked(QString name, QString pkgName);
void SwitchListPage(int categoryId, int page);
public slots: public slots:
void ResourceAcquisitionFinished(int id, ResourceResult result); void ResourceAcquisitionFinished(int id, ResourceResult result);
void Activated(); void Activated();
private slots:
void PageUp();
void PageDown();
void GotoPage();
}; };
} }

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <QScrollArea> #include <QtWidgets>
#include <spkresource.h> #include <spkresource.h>
class SpkPageBase : public QScrollArea class SpkPageBase : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -99,7 +99,7 @@ namespace SpkUi
} }
mLastSelectedItem = item; mLastSelectedItem = item;
if(item->data(column, RoleItemIsCategory).toBool()) if(item->data(column, RoleItemIsCategory).toBool())
emit SwitchToCategory(item->data(column, RoleItemCategoryPageId).toInt()); emit SwitchToCategory(item->data(column, RoleItemCategoryPageId).toInt(), 0);
else else
emit SwitchToPage(item->data(column, RoleItemCategoryPageId).toInt()); emit SwitchToPage(item->data(column, RoleItemCategoryPageId).toInt());
} }
@@ -117,7 +117,7 @@ namespace SpkUi
} }
signals: signals:
void SwitchToCategory(int aCategoryId); void SwitchToCategory(int aCategoryId, int aPage);
void SwitchToPage(int aPageId); void SwitchToPage(int aPageId);
}; };
@@ -179,7 +179,7 @@ class SpkMainWindow : public SpkWindow
void CategoryDataReceived(); void CategoryDataReceived();
void EnterCategoryList(int id); void EnterCategoryList(int aCategoryId, int aPage);
void CategoryListDataReceived(); void CategoryListDataReceived();
private: private: