158 lines
5.9 KiB
C++
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
|