vdi-cloud/terminal/kiosk-shell/src/desktop_list_page.cpp

197 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "desktop_list_page.h"
#include <QFont>
#include <QFrame>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QVBoxLayout>
namespace vdi {
namespace {
// 在信息行里加一个拉伸占位(独立函数避免在类外重复声明)
void addStretchToRow(QHBoxLayout* row) {
row->addStretch(1);
}
} // namespace
DesktopListPage::DesktopListPage(QWidget* parent) : QWidget(parent) {
auto* root = new QVBoxLayout(this);
root->setContentsMargins(80, 50, 80, 40);
root->setSpacing(16);
// ---- 标题区 ----
auto* title = new QLabel(QStringLiteral("选择云桌面"), this);
QFont titleFont = title->font();
titleFont.setPointSize(26);
titleFont.setBold(true);
title->setFont(titleFont);
title->setAlignment(Qt::AlignCenter);
root->addWidget(title);
auto* infoRow = new QHBoxLayout();
labelUser_ = new QLabel(this);
labelUser_->setStyleSheet(QStringLiteral("color: #8a94a6;"));
// 无登录页演示模式下不设"退出登录"(用户身份由设备/平台承担,
// 正式认证接入后由 DesktopService 驱动恢复登录流程)
infoRow->addWidget(labelUser_);
addStretchToRow(infoRow);
root->addLayout(infoRow);
// ---- 卡片区 ----
auto* scroll = new QScrollArea(this);
scroll->setWidgetResizable(true);
scroll->setFrameShape(QFrame::NoFrame);
scroll->setStyleSheet(QStringLiteral(
"QScrollArea { background: transparent; }"
"QWidget { background: transparent; }"));
auto* cardsHost = new QWidget(scroll);
cardsLayout_ = new QVBoxLayout(cardsHost);
cardsLayout_->setSpacing(14);
cardsLayout_->addStretch(1);
scroll->setWidget(cardsHost);
root->addWidget(scroll, 1);
// ---- 状态条 ----
labelStatus_ = new QLabel(this);
labelStatus_->setAlignment(Qt::AlignCenter);
labelStatus_->setStyleSheet(QStringLiteral("color: #8a94a6;"));
root->addWidget(labelStatus_);
}
void DesktopListPage::setDesktops(const std::vector<DesktopInfo>& desktops) {
desktops_ = desktops;
rebuildCards();
}
void DesktopListPage::rebuildCards() {
actionButtons_.clear();
// 清空旧卡片(最后一项是 stretch)
while (cardsLayout_->count() > 1) {
QLayoutItem* item = cardsLayout_->takeAt(0);
if (item->widget()) {
item->widget()->deleteLater();
}
delete item;
}
for (const DesktopInfo& d : desktops_) {
auto* card = new QFrame(this);
card->setMinimumHeight(96);
card->setStyleSheet(QStringLiteral(
"QFrame { background: #1a2233; border: 1px solid #2b3654; border-radius: 10px; }"
"QFrame:hover { border: 1px solid #2f6feb; }"
"QLabel { border: none; background: transparent; }"));
auto* row = new QHBoxLayout(card);
row->setContentsMargins(24, 16, 24, 16);
row->setSpacing(18);
auto* textCol = new QVBoxLayout();
textCol->setSpacing(4);
auto* name = new QLabel(d.name, card);
QFont nameFont = name->font();
nameFont.setPointSize(15);
nameFont.setBold(true);
name->setFont(nameFont);
auto* osLine = new QLabel(d.os, card);
osLine->setStyleSheet(QStringLiteral("color: #8a94a6;"));
textCol->addWidget(name);
textCol->addWidget(osLine);
row->addLayout(textCol, 1);
// 状态标签(会话通道统一 Moonlight,无需按桌面标注协议)
QString stateText;
QString stateColor;
switch (d.state) {
case DesktopState::kAvailable:
stateText = QStringLiteral("可连接");
stateColor = QStringLiteral("#3fb950");
break;
case DesktopState::kPending:
stateText = QStringLiteral("任务进行中");
stateColor = QStringLiteral("#d29922");
break;
case DesktopState::kUnassigned:
stateText = QStringLiteral("待分配");
stateColor = QStringLiteral("#8a94a6");
break;
}
auto* state = new QLabel(stateText, card);
state->setStyleSheet(QStringLiteral("color: %1; font-weight: bold;").arg(stateColor));
row->addWidget(state);
// “设置”:每张卡都可编辑连接参数(协议/地址/应用名/分辨率/帧率)
auto* editBtn = new QPushButton(QStringLiteral("设置"), card);
editBtn->setMinimumSize(88, 42);
editBtn->setEnabled(!busy_);
actionButtons_.push_back(editBtn);
connect(editBtn, &QPushButton::clicked, this, [this, id = d.id]() {
if (!busy_) {
emit editRequested(id);
}
});
row->addWidget(editBtn);
if (d.state == DesktopState::kAvailable) {
auto* connectBtn = new QPushButton(QStringLiteral("连接"), card);
connectBtn->setMinimumSize(110, 42);
connectBtn->setStyleSheet(QStringLiteral(
"QPushButton { background: #2f6feb; color: white; border: none; "
"border-radius: 6px; font-weight: bold; }"
"QPushButton:disabled { background: #3a4a63; }"));
connectBtn->setEnabled(!busy_);
actionButtons_.push_back(connectBtn);
connect(connectBtn, &QPushButton::clicked, this, [this, id = d.id]() {
if (!busy_) {
setBusy(true);
setStatus(QStringLiteral("正在连接,请稍候…"));
emit desktopSelected(id);
}
});
row->addWidget(connectBtn);
} else {
auto* btn = new QPushButton(QStringLiteral("连接"), card);
btn->setMinimumSize(110, 42);
btn->setEnabled(false);
row->addWidget(btn);
}
cardsLayout_->insertWidget(cardsLayout_->count() - 1, card);
}
}
void DesktopListPage::setStatus(const QString& text, bool error) {
labelStatus_->setText(text);
labelStatus_->setStyleSheet(
QStringLiteral("color: %1;").arg(error ? QStringLiteral("#e05561")
: QStringLiteral("#8a94a6")));
}
void DesktopListPage::setBusy(bool busy) {
busy_ = busy;
for (QPushButton* button : actionButtons_) {
if (button) {
button->setEnabled(!busy_);
}
}
}
QString DesktopListPage::currentUser() const {
return currentUser_;
}
void DesktopListPage::setCurrentUser(const QString& user) {
currentUser_ = user;
labelUser_->setText(user.isEmpty()
? QStringLiteral("当前用户:未登录")
: QStringLiteral("当前用户:%1").arg(user));
}
} // namespace vdi