168 lines
5.0 KiB
C++
168 lines
5.0 KiB
C++
#include "LauncherHomeWidget.h"
|
|
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QPixmap>
|
|
#include <QImage>
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QFont>
|
|
#include <QColor>
|
|
|
|
namespace {
|
|
|
|
QPixmap prepareLauncherIcon(const QString& iconPath, int size, int radius)
|
|
{
|
|
QPixmap src(iconPath);
|
|
if (src.isNull())
|
|
return QPixmap();
|
|
|
|
QImage img = src.scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)
|
|
.toImage()
|
|
.convertToFormat(QImage::Format_ARGB32);
|
|
|
|
for (int y = 0; y < img.height(); ++y) {
|
|
QRgb* line = reinterpret_cast<QRgb*>(img.scanLine(y));
|
|
for (int x = 0; x < img.width(); ++x) {
|
|
if (qRed(line[x]) > 235 && qGreen(line[x]) > 235 && qBlue(line[x]) > 235)
|
|
line[x] = qRgba(0, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
QPixmap out(size, size);
|
|
out.fill(Qt::transparent);
|
|
QPainter p(&out);
|
|
p.setRenderHint(QPainter::Antialiasing, true);
|
|
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
|
QPainterPath clip;
|
|
clip.addRoundedRect(QRectF(0.5, 0.5, size - 1.0, size - 1.0), radius, radius);
|
|
p.setClipPath(clip);
|
|
p.drawImage(0, 0, img);
|
|
return out;
|
|
}
|
|
|
|
QPushButton* makeAppCard(const QString& title,
|
|
const QString& subtitle,
|
|
const QString& iconPath,
|
|
QWidget* parent)
|
|
{
|
|
auto* card = new QPushButton(parent);
|
|
card->setCursor(Qt::PointingHandCursor);
|
|
card->setFlat(true);
|
|
card->setMinimumSize(240, 320);
|
|
card->setMaximumWidth(300);
|
|
card->setAttribute(Qt::WA_StyledBackground, true);
|
|
card->setStyleSheet(
|
|
QStringLiteral(
|
|
"QPushButton {"
|
|
" background-color: #f7f8fa;"
|
|
" border: 1px solid #d0d5de;"
|
|
" border-radius: 16px;"
|
|
" text-align: center;"
|
|
" padding: 20px 18px;"
|
|
"}"
|
|
"QPushButton:hover {"
|
|
" background-color: #eef2f7;"
|
|
" border: 1px solid #aeb6c4;"
|
|
"}"
|
|
"QPushButton:pressed {"
|
|
" background-color: #e4e9f0;"
|
|
"}"));
|
|
|
|
auto* lay = new QVBoxLayout(card);
|
|
lay->setSpacing(14);
|
|
lay->setContentsMargins(22, 26, 22, 26);
|
|
|
|
auto* icon = new QLabel(card);
|
|
icon->setAlignment(Qt::AlignCenter);
|
|
icon->setFixedSize(148, 148);
|
|
icon->setStyleSheet(QStringLiteral("background: transparent; border: none;"));
|
|
const QPixmap pm = prepareLauncherIcon(iconPath, 148, 28);
|
|
if (!pm.isNull())
|
|
icon->setPixmap(pm);
|
|
icon->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
lay->addWidget(icon, 0, Qt::AlignHCenter);
|
|
|
|
auto* t = new QLabel(title, card);
|
|
t->setAlignment(Qt::AlignCenter);
|
|
QFont tf = t->font();
|
|
tf.setPointSize(15);
|
|
tf.setBold(true);
|
|
t->setFont(tf);
|
|
t->setStyleSheet(QStringLiteral("color:#2a3140; background:transparent; border:none;"));
|
|
t->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
lay->addWidget(t);
|
|
|
|
auto* s = new QLabel(subtitle, card);
|
|
s->setAlignment(Qt::AlignCenter);
|
|
s->setWordWrap(true);
|
|
s->setStyleSheet(QStringLiteral("color:#6a7385; background:transparent; border:none; font-size:12px;"));
|
|
s->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
lay->addWidget(s);
|
|
lay->addStretch(1);
|
|
return card;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
LauncherHomeWidget::LauncherHomeWidget(QWidget* parent)
|
|
: QWidget(parent)
|
|
{
|
|
setAttribute(Qt::WA_StyledBackground, true);
|
|
setStyleSheet(QStringLiteral(
|
|
"LauncherHomeWidget {"
|
|
" background: #f0f2f5;"
|
|
"}"));
|
|
|
|
auto* root = new QVBoxLayout(this);
|
|
root->setContentsMargins(48, 40, 48, 48);
|
|
root->setSpacing(28);
|
|
|
|
auto* brand = new QLabel(tr("Dose Comparison & Analysis Tools"), this);
|
|
QFont bf = brand->font();
|
|
bf.setPointSize(22);
|
|
bf.setBold(false);
|
|
brand->setFont(bf);
|
|
brand->setStyleSheet(QStringLiteral("color:#333945; background:transparent;"));
|
|
brand->setAlignment(Qt::AlignCenter);
|
|
root->addWidget(brand);
|
|
|
|
auto* hint = new QLabel(tr("选择一个应用开始"), this);
|
|
hint->setAlignment(Qt::AlignCenter);
|
|
hint->setStyleSheet(QStringLiteral("color:#7a8496; font-size:14px; background:transparent;"));
|
|
root->addWidget(hint);
|
|
|
|
auto* row = new QHBoxLayout();
|
|
row->setSpacing(36);
|
|
row->addStretch(1);
|
|
|
|
auto* profileCard = makeAppCard(
|
|
tr("Profile Comparison"),
|
|
tr("剂量三切面叠加与交线 Profile 对比"),
|
|
QStringLiteral(":/app-profile.png"),
|
|
this);
|
|
connect(profileCard, &QPushButton::clicked, this, &LauncherHomeWidget::openProfileRequested);
|
|
row->addWidget(profileCard);
|
|
|
|
auto* dvhCard = makeAppCard(
|
|
tr("DVH Comparison"),
|
|
tr("多剂量计划与结构勾画的 DVH 对比"),
|
|
QStringLiteral(":/app-dvh.png"),
|
|
this);
|
|
connect(dvhCard, &QPushButton::clicked, this, &LauncherHomeWidget::openDvhRequested);
|
|
row->addWidget(dvhCard);
|
|
|
|
auto* gammaCard = makeAppCard(
|
|
tr("Gamma Analysis"),
|
|
tr("Background / Front 三维 Gamma 通过率与 Gamma Map"),
|
|
QStringLiteral(":/app-gamma.png"),
|
|
this);
|
|
connect(gammaCard, &QPushButton::clicked, this, &LauncherHomeWidget::openGammaRequested);
|
|
row->addWidget(gammaCard);
|
|
|
|
row->addStretch(1);
|
|
root->addLayout(row, 1);
|
|
}
|