新增截图预览

This commit is contained in:
RigoLigoRLC 2022-03-13 20:27:03 +08:00
parent 904cc3cb1c
commit 8d40a0598e
9 changed files with 321 additions and 49 deletions

@ -79,6 +79,7 @@ set(SOURCE_FILES
inc/spkstretchlayout.h gui/spkstretchlayout.cpp
inc/spkfocuslineedit.h
inc/spknotifydot.h gui/spknotifydot.cpp
inc/spkimgviewer.h gui/spkimgviewer.cpp
inc/page/spkpagebase.h gui/page/spkpagebase.cpp
inc/page/spkpagehome.h gui/page/spkpagehome.cpp

@ -23,31 +23,59 @@ namespace SpkUi
Qt::SmoothTransformation));
else
{
mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(IconSize));
mAppIcon->setPixmap(mBrokenImg);
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppIcon, 0);
}
}
// Load screenshots
// Load screenshots. Screenshots have id starting with 1.
if(aScreenshots.isEmpty())
return;
else
{
auto count = aScreenshots.size();
mImgViewer->SetImageTotal(count);
if(count > mScreenshotPreviews.size())
{
auto from = mScreenshotPreviews.size(), to = count - mScreenshotPreviews.size();
for(int i = 0; i <= to; i++)
{
auto wid = new SpkClickLabel;
wid->setProperty("shotId", from + i + 1);
wid->setFixedHeight(200);
wid->setCursor(Qt::PointingHandCursor);
connect(wid, &SpkClickLabel::Pressed, this, &SpkPageAppDetails::ImageClicked);
mScreenshotPreviews.append(wid);
mScreenshotLay->addWidget(wid);
}
}
}
int shotId = 0;
for(auto &i : aScreenshots)
{
shotId++;
res = RES->RequestResource(shotId, aPkgName, SpkResource::ResourceType::AppScreenshot, aIcon,
res = RES->RequestResource(shotId, aPkgName, SpkResource::ResourceType::AppScreenshot, i,
shotId);
auto preview = mScreenshotPreviews[shotId - 1];
preview->setVisible(true);
if(res.status == SpkResource::ResourceStatus::Ready)
{
if(pic.loadFromData(res.data))
;// TODO
else
{
// TODO
// mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppScreenshot, 0);
}
{
mAppImages[shotId] = pic;
mImgViewer->SetPixmap(shotId, &mAppImages[shotId]);
preview->setPixmap(pic.scaledToHeight(200, Qt::SmoothTransformation));
}
else
{
mAppImages[shotId] = mBrokenImg;
RES->PurgeCachedResource(aPkgName, SpkResource::ResourceType::AppScreenshot, 0);
}
}
else
{
preview->setPixmap(mIconLoading);
}
}
@ -64,7 +92,9 @@ namespace SpkUi
mPkgPath = url;
}
SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent)
SpkPageAppDetails::SpkPageAppDetails(QWidget *parent) : SpkPageBase(parent),
mBrokenImg(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_)),
mIconLoading(QIcon(":/icons/loading-icon.svg").pixmap(SpkAppItem::IconSize_))
{
mMainArea = new QScrollArea;
mMainArea->setWidgetResizable(true);
@ -148,6 +178,18 @@ namespace SpkUi
mDetailsLay->addLayout(mDetailLay);
mDetailsLay->addWidget(mAppDescription);
// mMainLay->addStretch();
mScreenshotLay = new QHBoxLayout;
mScreenshotArea = new QScrollArea;
mWid4ShotArea = new QWidget;
mWid4ShotArea->setLayout(mScreenshotLay);
mScreenshotArea->setWidget(mWid4ShotArea);
mScreenshotArea->setWidgetResizable(true);
mScreenshotArea->setFixedHeight(230);
mScreenshotArea->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
mDetailsLay->addWidget(mScreenshotArea);
mWid4MainArea = new QWidget;
mWid4MainArea->setLayout(mDetailsLay);
@ -182,43 +224,80 @@ namespace SpkUi
mBottomBarLay->addWidget(mBtnRequestUpdate);
mBottomBarLay->addWidget(mBtnReport);
mImgViewer = new SpkImgViewer;
mImgViewer->setVisible(false);
connect(mBtnDownload, &QPushButton::clicked,
[=](){ emit RequestDownload(mAppTitle->text(), mPkgName->text(),
"/store/reading/youdao-dict/youdao-dict_6.0.0-0~ubuntu_amd64.deb");
});
});
}
SpkPageAppDetails::~SpkPageAppDetails()
{
delete mImgViewer;
}
void SpkPageAppDetails::ResourceAcquisitionFinished(int id, ResourceResult result)
{
QPixmap icon;
QPixmap img;
// qDebug() << "PageAppDetails: Resource" << id << "acquired";
if(!id)
{
// id == 0, icon
if(result.status == SpkResource::ResourceStatus::Ready)
{
if(icon.loadFromData(result.data))
mAppIcon->setPixmap(icon.scaled(SpkAppItem::IconSize_,
if(img.loadFromData(result.data))
mAppIcon->setPixmap(img.scaled(SpkAppItem::IconSize_,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
else
mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
mAppIcon->setPixmap(mBrokenImg);
}
else if(result.status == SpkResource::ResourceStatus::Failed)
{
mAppIcon->setPixmap(QIcon(":/icons/broken-icon.svg").pixmap(SpkAppItem::IconSize_));
mAppIcon->setPixmap(mBrokenImg);
RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
}
}
else
{
// TODO: screenshots
auto preview = mScreenshotPreviews[id - 1];
preview->setVisible(true);
if(result.status == SpkResource::ResourceStatus::Ready)
{
if(img.loadFromData(result.data))
{
mAppImages[id] = img;
mImgViewer->SetPixmap(id, &mAppImages[id]);
mScreenshotPreviews[id - 1]->setPixmap(img.scaledToHeight(200, Qt::SmoothTransformation));
}
else
{
mImgViewer->SetPixmap(id, &mBrokenImg);
mScreenshotPreviews[id - 1]->setPixmap(mBrokenImg);
}
}
else if(result.status == SpkResource::ResourceStatus::Failed)
{
mImgViewer->SetPixmap(id, &mBrokenImg);
mScreenshotPreviews[id - 1]->setPixmap(mBrokenImg);
RES->PurgeCachedResource(mPkgName->text(), SpkResource::ResourceType::AppIcon, 0);
}
}
}
void SpkPageAppDetails::Activated()
{
RES->Acquire(this, false);
for(auto &i : mScreenshotPreviews)
i->setVisible(false);
mImgViewer->Clear();
}
void SpkPageAppDetails::ImageClicked()
{
mImgViewer->ShowWithImage(sender()->property("shotId").toInt());
}
SpkDetailEntry::SpkDetailEntry(QWidget *parent) : QWidget(parent)

120
gui/spkimgviewer.cpp Normal file

@ -0,0 +1,120 @@
#include "spktitlebar.h"
#include "spkimgviewer.h"
#include "spkui_general.h"
#include <QDebug>
#include <QFocusEvent>
#include <QGuiApplication>
#include <QScreen>
SpkImgViewer::SpkImgViewer(QWidget *parent) :
SpkWindow(parent),
mIconLoading(QIcon(":/icons/loading-icon.svg").pixmap({ 72, 72 }))
{
mImgIndict = new QLabel;
mImgIndict->setText("%1/%2");
mBtnPrev = new QPushButton;
mBtnPrev->setText("<");
mBtnNext = new QPushButton;
mBtnNext->setText(">");
auto titleBar = GetTitleBar();
titleBar->SetUseIcon(false);
titleBar->SetTitle(tr("Image Preview"));
titleBar->SetOperationButton(SpkTitleBar::OperationButton::Close);
auto lay = titleBar->GetUserSpace();
lay->setAlignment(Qt::AlignVCenter);
lay->addStretch();
lay->addWidget(mBtnPrev);
lay->addWidget(mImgIndict);
lay->addWidget(mBtnNext);
lay->addStretch();
mImgArea = new QScrollArea;
mImgArea->setWidgetResizable(true);
mImgArea->setContentsMargins(10, 10, 10, 10);
mImgShow = new ImgView;
mImgArea->setWidget(mImgShow);
auto w = new QWidget;
auto l = new QHBoxLayout;
l->setContentsMargins(10, 10, 10, 10);
l->addWidget(mImgArea);
w->setLayout(l);
SetCentralWidget(w);
connect(mBtnPrev, &QPushButton::clicked,
[&](){ if(mCurrentImg > 0) { SwitchToImage(--mCurrentImg); } });
connect(mBtnNext, &QPushButton::clicked,
[&](){ if(mCurrentImg < mTotalImg) { SwitchToImage(++mCurrentImg); } });
}
void SpkImgViewer::ShowWithImage(int idx)
{
SwitchToImage(idx);
show();
}
void SpkImgViewer::Clear()
{
mImgMap.clear();
mImgShow->SetPixmap(nullptr);
mCurrentImg = 1;
}
void SpkImgViewer::SetPixmap(int idx, QPixmap *img)
{
mImgMap[idx] = img;
if(mCurrentImg == idx)
{
mImgShow->SetPixmap(img);
}
ResizeToFitImageSize(img->size());
}
void SpkImgViewer::SwitchToImage(int idx)
{
auto img = mImgMap.value(idx, nullptr);
mCurrentImg = idx;
mImgShow->SetPixmap(img ? img : &mIconLoading);
if(img)
ResizeToFitImageSize(img->size());
if(idx == 1)
{
mBtnPrev->setEnabled(false);
mBtnNext->setEnabled(true);
}
else if(idx == mTotalImg)
{
mBtnPrev->setEnabled(true);
mBtnNext->setEnabled(false);
}
else
{
mBtnPrev->setEnabled(true);
mBtnNext->setEnabled(true);
}
mImgIndict->setText(QString("%1/%2").arg(mCurrentImg).arg(mTotalImg));
}
bool SpkImgViewer::event(QEvent *e)
{
if(e->type() == QEvent::WindowDeactivate)
close();
return SpkWindow::event(e);
}
void SpkImgViewer::ResizeToFitImageSize(QSize s)
{
auto targetSize = s;
targetSize.rheight() += SpkTitleBar::Height;
targetSize = s.grownBy(QMargins(10, 10, 10, 10));
targetSize = targetSize.boundedTo(SpkUi::PrimaryScreenSize * 0.8);
resize(targetSize);
targetSize /= 2;
auto targetPos = SpkUi::PrimaryScreenSize / 2 - targetSize;
move(targetPos.width(), targetPos.height());
}

@ -9,8 +9,7 @@ SpkTitleBar::SpkTitleBar(QWidget *parent) : QFrame(parent)
{
mLinkedWindow = nullptr;
setMinimumHeight(48);
setMaximumHeight(48);
setFixedHeight(Height);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
mIcon = new QLabel(this);

@ -8,16 +8,27 @@
#include <QFormLayout>
#include "page/spkpagebase.h"
#include "spkstretchlayout.h"
#include "spkimgviewer.h"
namespace SpkUi
{
class SpkDetailEntry;
class SpkClickLabel : public QLabel
{
Q_OBJECT
protected:
virtual void mousePressEvent(QMouseEvent *e) override { emit Pressed(); }
signals:
void Pressed();
};
class SpkPageAppDetails : public SpkPageBase
{
Q_OBJECT
public:
SpkPageAppDetails(QWidget *parent = nullptr);
~SpkPageAppDetails();
void LoadAppResources(QString pkgName, QString icon, QStringList screenshots, QStringList tags);
void SetWebsiteLink(QString url);
@ -25,6 +36,7 @@ namespace SpkUi
private:
QString mPkgPath;
QPixmap mBrokenImg, mIconLoading;
public slots:
void ResourceAcquisitionFinished(int id, ResourceResult result);
@ -34,14 +46,18 @@ namespace SpkUi
static constexpr QSize IconSize { 144, 144 };
// Main Area
QScrollArea *mMainArea;
QWidget *mDetailWidget, *mIconTitleWidget, *mWid4MainArea;
QScrollArea *mMainArea, *mScreenshotArea;
QWidget *mDetailWidget, *mIconTitleWidget, *mWid4MainArea, *mWid4ShotArea;
QLabel *mAppTitle, *mAppIcon, *mAppDescription, *mAppShortDesc, *mPkgName, *mVersion,
*mWebsite;
SpkDetailEntry *mAuthor, *mContributor, *mSite, *mArch, *mSize;
SpkStretchLayout *mDetailLay;
QVBoxLayout *mDetailsLay, *mTitleLay, *mMainLay;
QHBoxLayout *mIconTitleLay;
QHBoxLayout *mIconTitleLay, *mScreenshotLay;
QList<SpkClickLabel*> mScreenshotPreviews;
QMap<int, QPixmap> mAppImages;
SpkImgViewer *mImgViewer;
// Bottom bar
QWidget *mBottomBar;
@ -50,6 +66,9 @@ namespace SpkUi
signals:
void RequestDownload(QString name, QString pkgName, QString path);
private slots:
void ImageClicked();
};
class SpkDetailEntry : public QWidget

61
inc/spkimgviewer.h Normal file

@ -0,0 +1,61 @@
#pragma once
#include <QPainter>
#include <QScrollArea>
#include "spkwindow.h"
class ImgView : public QWidget
{
Q_OBJECT
public:
ImgView(QWidget *parent = nullptr) : QWidget(parent) { mPixmap = nullptr; }
void SetPixmap(QPixmap *p) { mPixmap = p; if(p) setFixedSize(p->size()); update(); }
protected:
void paintEvent(QPaintEvent *e)
{
QPainter p(this);
if(mPixmap)
p.drawPixmap(0, 0, *mPixmap);
p.end();
e->accept();
}
private:
QPixmap *mPixmap;
};
class SpkImgViewer : public SpkWindow
{
Q_OBJECT
public:
SpkImgViewer(QWidget *parent = nullptr);
void ShowWithImage(int idx);
void SetImageTotal(int a) { mTotalImg = a; }
public slots:
void Clear();
void SetPixmap(int idx, QPixmap *img);
private slots:
void SwitchToImage(int idx);
protected:
bool event(QEvent*) override;
private:
void ResizeToFitImageSize(QSize);
private:
QPushButton *mBtnPrev, *mBtnNext;
QScrollArea *mImgArea;
QLabel *mImgIndict;
QMap<int, QPixmap*> mImgMap;
int mCurrentImg, mTotalImg;
QPixmap mIconLoading;
ImgView *mImgShow;
};

@ -43,6 +43,7 @@ class SpkTitleBar : public QFrame
public:
SpkTitleBar(QWidget *parent = nullptr);
~SpkTitleBar();
static constexpr int Height = 48;
using OperationButton = SpkTitleBarDefaultButton::OperationButton;
void SetOperationButton(OperationButton);

@ -403,6 +403,14 @@ Right now we are not just a Chinese group. We are discovering our way into more
<translation></translation>
</message>
</context>
<context>
<name>SpkImgViewer</name>
<message>
<location filename="../gui/spkimgviewer.cpp" line="23"/>
<source>Image Preview</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SpkMainWindow</name>
<message>
@ -666,47 +674,47 @@ to use terminal for program output.</source>
<context>
<name>SpkUi::SpkPageAppDetails</name>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="59"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="87"/>
<source>Website link</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="124"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="154"/>
<source>Author</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="126"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="156"/>
<source>Contributor</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="130"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="160"/>
<source>Architecture</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="132"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="162"/>
<source>Size</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="164"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="206"/>
<source>Download</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="170"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="212"/>
<source>Uninstall</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="173"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="215"/>
<source>Request Update</source>
<translation></translation>
</message>
<message>
<location filename="../gui/page/spkpageappdetails.cpp" line="176"/>
<location filename="../gui/page/spkpageappdetails.cpp" line="218"/>
<source>Report</source>
<translation></translation>
</message>

@ -6,7 +6,7 @@
#include "spkstore.h"
#include "spkdownload.h"
#include "spkmsgbox.h"
#include "spkimgviewer.h"
int main(int argc, char *argv[])
@ -30,21 +30,5 @@ int main(int argc, char *argv[])
SpkStore store(false, LogPath);
// SpkDownloadMgr dl;
// dl.SetNewServers({
// "https://d1.store.deepinos.org.cn/",
// "https://d2.store.deepinos.org.cn/",
// "https://d3.store.deepinos.org.cn/",
// "https://d4.store.deepinos.org.cn/",
// "https://d5.store.deepinos.org.cn/"
// });
// dl.SetDestinationFolder("/tmp/");
// dl.StartNewDownload("store/office/cn.com.10jqka/cn.com.10jqka_1.6.1.2_amd64.deb", 0);
// QObject::connect(&dl, &SpkDownloadMgr::DownloadStopped,
// [&](SpkDownloadMgr::TaskResult, int)
// {
// SpkMsgBox::StaticExec("Finished", "");
// });
return QApplication::exec();
}