geopro/src/app/SettingsDialog.cpp

158 lines
5.9 KiB
C++

#include "SettingsDialog.hpp"
#include <QComboBox>
#include <QCoreApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QListWidget>
#include <QProcess>
#include <QPushButton>
#include <QStackedWidget>
#include <QTextBrowser>
#include <QVBoxLayout>
#include <QWidget>
#include "Theme.hpp"
namespace geopro::app {
namespace {
// 「标签 + 控件」一行(标签定宽左对齐,控件右随)。
QWidget* makeRow(const QString& label, QWidget* control) {
auto* row = new QWidget();
auto* lay = new QHBoxLayout(row);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(12);
auto* lbl = new QLabel(label, row);
lbl->setMinimumWidth(96);
lay->addWidget(lbl);
lay->addWidget(control, 1);
return row;
}
// 区段标题。
QLabel* sectionTitle(const QString& text, QWidget* parent) {
auto* t = new QLabel(text, parent);
t->setStyleSheet(QStringLiteral("font-size:%1px; font-weight:600;")
.arg(geopro::app::scaledPx(geopro::app::type::kHeading)));
return t;
}
QWidget* buildAppearancePage() {
auto* page = new QWidget();
auto* v = new QVBoxLayout(page);
v->setContentsMargins(24, 20, 24, 20);
v->setSpacing(16);
v->addWidget(sectionTitle(QStringLiteral("外观"), page));
// 主题:跟随系统 / 浅色 / 深色(热切)。
auto* themeCombo = new QComboBox(page);
themeCombo->addItem(QStringLiteral("跟随系统"), QStringLiteral("system"));
themeCombo->addItem(QStringLiteral("浅色"), QStringLiteral("light"));
themeCombo->addItem(QStringLiteral("深色"), QStringLiteral("dark"));
const QString curTheme = geopro::app::themeModePreference();
themeCombo->setCurrentIndex(themeCombo->findData(curTheme) >= 0 ? themeCombo->findData(curTheme) : 0);
QObject::connect(themeCombo, &QComboBox::activated, page, [themeCombo](int) {
geopro::app::setThemeModePreference(themeCombo->currentData().toString());
});
v->addWidget(makeRow(QStringLiteral("主题"), themeCombo));
// 界面字号:小/标准/大/特大(重启生效)。
auto* fontCombo = new QComboBox(page);
fontCombo->addItem(QStringLiteral(""), 90);
fontCombo->addItem(QStringLiteral("标准"), 100);
fontCombo->addItem(QStringLiteral(""), 115);
fontCombo->addItem(QStringLiteral("特大"), 130);
const int curScale = geopro::app::fontScalePreference();
fontCombo->setCurrentIndex(fontCombo->findData(curScale) >= 0 ? fontCombo->findData(curScale) : 1);
v->addWidget(makeRow(QStringLiteral("界面字号"), fontCombo));
// 字号改动:持久化 + 提示重启(提供立即重启)。
auto* restartRow = new QWidget(page);
auto* rlay = new QHBoxLayout(restartRow);
rlay->setContentsMargins(96 + 12, 0, 0, 0); // 与控件列对齐
rlay->setSpacing(10);
auto* hint = new QLabel(QStringLiteral("界面字号将在重启后生效"), restartRow);
geopro::app::applyTokenizedStyleSheet(
hint, QStringLiteral("color:{{text/secondary}}; font-size:%1px;")
.arg(geopro::app::scaledPx(geopro::app::type::kCaption)));
auto* restartBtn = new QPushButton(QStringLiteral("立即重启"), restartRow);
rlay->addWidget(hint);
rlay->addWidget(restartBtn);
rlay->addStretch();
restartRow->setVisible(false);
v->addWidget(restartRow);
QObject::connect(fontCombo, &QComboBox::activated, page, [fontCombo, restartRow](int) {
geopro::app::setFontScalePreference(fontCombo->currentData().toInt());
restartRow->setVisible(true);
});
QObject::connect(restartBtn, &QPushButton::clicked, restartBtn, [] {
QProcess::startDetached(QCoreApplication::applicationFilePath(),
QCoreApplication::arguments().mid(1));
qApp->quit();
});
v->addStretch();
return page;
}
QWidget* buildAboutPage() {
auto* page = new QWidget();
auto* v = new QVBoxLayout(page);
v->setContentsMargins(24, 20, 24, 20);
v->setSpacing(12);
v->addWidget(sectionTitle(QStringLiteral("关于"), page));
auto* ver = new QLabel(QStringLiteral("Geopro 3.0 — 项目分析视图 (M1)"), page);
ver->setStyleSheet(QStringLiteral("font-size:%1px; font-weight:600;")
.arg(geopro::app::scaledPx(geopro::app::type::kTitle)));
v->addWidget(ver);
auto* license = new QTextBrowser(page);
license->setOpenExternalLinks(true);
license->setHtml(QStringLiteral(
"<b>第三方组件与许可证</b>"
"<table cellpadding='3' style='margin-top:6px'>"
"<tr><td>Qt 6</td><td>GUI 框架</td><td>LGPL-3.0</td></tr>"
"<tr><td>VTK 9</td><td>二维/三维渲染</td><td>BSD-3-Clause</td></tr>"
"<tr><td>Qt-Advanced-Docking-System</td><td>停靠布局</td><td>LGPL-2.1</td></tr>"
"<tr><td>QtKeychain</td><td>凭证安全存取</td><td>BSD-3-Clause</td></tr>"
"</table>"
"<p style='margin-top:8px'>完整声明见随附 <i>NOTICE.md</i>。</p>"));
v->addWidget(license, 1);
return page;
}
} // namespace
SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent) {
setWindowTitle(QStringLiteral("设置"));
resize(720, 480);
auto* root = new QHBoxLayout(this);
root->setContentsMargins(0, 0, 0, 0);
root->setSpacing(0);
// 左:分类列表。
auto* sidebar = new QListWidget(this);
sidebar->setObjectName(QStringLiteral("settingsSidebar"));
sidebar->setFixedWidth(150);
sidebar->addItem(QStringLiteral("外观"));
sidebar->addItem(QStringLiteral("关于"));
root->addWidget(sidebar);
// 右:分页。
auto* stack = new QStackedWidget(this);
stack->addWidget(buildAppearancePage());
stack->addWidget(buildAboutPage());
root->addWidget(stack, 1);
QObject::connect(sidebar, &QListWidget::currentRowChanged, stack,
&QStackedWidget::setCurrentIndex);
sidebar->setCurrentRow(0);
}
} // namespace geopro::app