refactor/pure-qt-ui #3
|
|
@ -25,7 +25,8 @@ add_executable(geopro_desktop WIN32
|
||||||
panels/DatasetListPanel.cpp
|
panels/DatasetListPanel.cpp
|
||||||
panels/ObjectTreePanel.cpp
|
panels/ObjectTreePanel.cpp
|
||||||
CentralScene.cpp
|
CentralScene.cpp
|
||||||
ProjectListDialog.cpp)
|
ProjectListDialog.cpp
|
||||||
|
SettingsDialog.cpp)
|
||||||
|
|
||||||
target_include_directories(geopro_desktop PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(geopro_desktop PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
# QtKeychain 经 FetchContent 接入,头文件不随 target 传播,显式加源/构建目录(含生成的 export 头)。
|
# QtKeychain 经 FetchContent 接入,头文件不随 target 传播,显式加源/构建目录(含生成的 export 头)。
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,12 @@ QString headerQss()
|
||||||
"QToolButton#tabBtn:hover { color:#1F2A3D; }"
|
"QToolButton#tabBtn:hover { color:#1F2A3D; }"
|
||||||
"QToolButton#tabBtn:checked { color:#2D6CB5; font-weight:%3;"
|
"QToolButton#tabBtn:checked { color:#2D6CB5; font-weight:%3;"
|
||||||
" border-bottom:2px solid #2D6CB5; }")
|
" border-bottom:2px solid #2D6CB5; }")
|
||||||
.arg(type::kTitle)
|
.arg(scaledPx(type::kTitle))
|
||||||
.arg(type::kCaption)
|
.arg(scaledPx(type::kCaption))
|
||||||
.arg(type::kWeightSemibold)
|
.arg(type::kWeightSemibold)
|
||||||
.arg(QString::fromUtf8(semantic::kWarningFill))
|
.arg(QString::fromUtf8(semantic::kWarningFill))
|
||||||
.arg(QString::fromUtf8(semantic::kWarning))
|
.arg(QString::fromUtf8(semantic::kWarning))
|
||||||
.arg(type::kBody);
|
.arg(scaledPx(type::kBody));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数量徽标(默认隐藏,调用方 setText+setVisible 显示)。
|
// 数量徽标(默认隐藏,调用方 setText+setVisible 显示)。
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
#include "SettingsDialog.hpp"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QTextBrowser>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <ElaComboBox.h>
|
||||||
|
#include <ElaPushButton.h>
|
||||||
|
#include <ElaText.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 区段标题。
|
||||||
|
ElaText* sectionTitle(const QString& text, QWidget* parent) {
|
||||||
|
auto* t = new ElaText(text, parent);
|
||||||
|
t->setTextPixelSize(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 ElaComboBox(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 ElaComboBox(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 ElaText(QStringLiteral("界面字号将在重启后生效"), restartRow);
|
||||||
|
hint->setTextPixelSize(geopro::app::scaledPx(geopro::app::type::kCaption));
|
||||||
|
auto* restartBtn = new ElaPushButton(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 ElaText(QStringLiteral("Geopro 3.0 — 项目分析视图 (M1)"), page);
|
||||||
|
ver->setTextPixelSize(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>ElaWidgetTools</td><td>Fluent 控件</td><td>MIT</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
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace geopro::app {
|
||||||
|
|
||||||
|
// 设置对话框(左分类 + 右内容页,参考常见客户端布局):
|
||||||
|
// 外观 —— 主题(跟随系统/浅色/深色,热切) + 界面字号(小/标准/大/特大,重启生效)
|
||||||
|
// 关于 —— 版本号 + 第三方组件与许可证
|
||||||
|
class SettingsDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SettingsDialog(QWidget* parent = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace geopro::app
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
|
#include <QSettings>
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
@ -473,6 +474,60 @@ void applyBrandAccent()
|
||||||
eTheme->setThemeColor(ElaThemeType::Dark, ElaThemeType::BasicSelectedHoverAlpha, QColor(0x3C, 0x5D, 0x87));
|
eTheme->setThemeColor(ElaThemeType::Dark, ElaThemeType::BasicSelectedHoverAlpha, QColor(0x3C, 0x5D, 0x87));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── 设置:主题 / 字号 偏好 ──────────────────────────────────────────────
|
||||||
|
namespace {
|
||||||
|
constexpr int kBaseFontPx = 13; // 基准字号(与 eApp 默认一致)
|
||||||
|
int g_fontScale = 100; // 当前字号缩放百分比
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
QString themeModePreference()
|
||||||
|
{
|
||||||
|
return QSettings().value(QStringLiteral("ui/themeMode"), QStringLiteral("system")).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyPersistedThemeMode()
|
||||||
|
{
|
||||||
|
const QString m = themeModePreference();
|
||||||
|
if (m == QStringLiteral("light")) {
|
||||||
|
eTheme->setIsFollowSystemTheme(false);
|
||||||
|
eTheme->setThemeMode(ElaThemeType::Light);
|
||||||
|
} else if (m == QStringLiteral("dark")) {
|
||||||
|
eTheme->setIsFollowSystemTheme(false);
|
||||||
|
eTheme->setThemeMode(ElaThemeType::Dark);
|
||||||
|
} else { // system:跟随系统明暗
|
||||||
|
eTheme->setIsFollowSystemTheme(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setThemeModePreference(const QString& mode)
|
||||||
|
{
|
||||||
|
QSettings().setValue(QStringLiteral("ui/themeMode"), mode);
|
||||||
|
applyPersistedThemeMode(); // 主题可热切,立即应用
|
||||||
|
}
|
||||||
|
|
||||||
|
int fontScalePreference()
|
||||||
|
{
|
||||||
|
return QSettings().value(QStringLiteral("ui/fontScale"), 100).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFontScalePreference(int percent)
|
||||||
|
{
|
||||||
|
QSettings().setValue(QStringLiteral("ui/fontScale"), percent); // 重启后生效
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyPersistedFontScale()
|
||||||
|
{
|
||||||
|
g_fontScale = fontScalePreference();
|
||||||
|
QFont f = qApp->font();
|
||||||
|
f.setPixelSize(kBaseFontPx * g_fontScale / 100);
|
||||||
|
qApp->setFont(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int scaledPx(int basePx)
|
||||||
|
{
|
||||||
|
return basePx * g_fontScale / 100;
|
||||||
|
}
|
||||||
|
|
||||||
bool isDarkTheme()
|
bool isDarkTheme()
|
||||||
{
|
{
|
||||||
return eTheme->getThemeMode() == ElaThemeType::Dark;
|
return eTheme->getThemeMode() == ElaThemeType::Dark;
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,19 @@ void applyTheme(QApplication& app);
|
||||||
// (选中/激活/标题栏强调) 与本项目 QSS 共用同一套蓝,消除"多种蓝打架"。在 eApp->init() 后调一次。
|
// (选中/激活/标题栏强调) 与本项目 QSS 共用同一套蓝,消除"多种蓝打架"。在 eApp->init() 后调一次。
|
||||||
void applyBrandAccent();
|
void applyBrandAccent();
|
||||||
|
|
||||||
|
// ── 设置:主题 / 界面字号 偏好(QSettings 持久化)────────────────────────
|
||||||
|
// 启动时(eApp->init + applyBrandAccent 之后、弹登录窗之前)各调一次,使登录页与主页统一。
|
||||||
|
void applyPersistedThemeMode(); // 应用持久化主题:跟随系统 / 浅色 / 深色 → ElaTheme
|
||||||
|
void applyPersistedFontScale(); // 应用持久化字号:设 qApp 基准字体 + 记录缩放(供 scaledPx)
|
||||||
|
|
||||||
|
QString themeModePreference(); // "system" | "light" | "dark"(默认 system)
|
||||||
|
void setThemeModePreference(const QString& mode); // 持久化 + 立即应用(主题可热切)
|
||||||
|
|
||||||
|
int fontScalePreference(); // 缩放百分比 90/100/115/130(默认 100)
|
||||||
|
void setFontScalePreference(int percent); // 仅持久化(字号改动重启后生效)
|
||||||
|
|
||||||
|
int scaledPx(int basePx); // basePx × 当前字号% / 100(内联 QSS 字号用,使自定义 chrome 也随字号缩放)
|
||||||
|
|
||||||
// 当前 ElaTheme 是否暗色(供内联样式判断)。
|
// 当前 ElaTheme 是否暗色(供内联样式判断)。
|
||||||
bool isDarkTheme();
|
bool isDarkTheme();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "TopBar.hpp"
|
#include "TopBar.hpp"
|
||||||
|
|
||||||
|
#include <QAbstractButton>
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
|
|
@ -145,12 +146,12 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) {
|
||||||
" font-size:%1px; }"
|
" font-size:%1px; }"
|
||||||
"#userName { color:#1F2A3D; font-size:%3px; font-weight:%4; }"
|
"#userName { color:#1F2A3D; font-size:%3px; font-weight:%4; }"
|
||||||
"#userRole { color:#8A93A3; font-size:%5px; }")
|
"#userRole { color:#8A93A3; font-size:%5px; }")
|
||||||
.arg(type::kBody)
|
.arg(scaledPx(type::kBody))
|
||||||
.arg(type::kWeightBold)
|
.arg(type::kWeightBold)
|
||||||
.arg(type::kLabel)
|
.arg(scaledPx(type::kLabel))
|
||||||
.arg(type::kWeightSemibold)
|
.arg(type::kWeightSemibold)
|
||||||
.arg(type::kCaption)
|
.arg(scaledPx(type::kCaption))
|
||||||
.arg(type::kTitle));
|
.arg(scaledPx(type::kTitle)));
|
||||||
|
|
||||||
auto* lay = new QHBoxLayout(this);
|
auto* lay = new QHBoxLayout(this);
|
||||||
lay->setContentsMargins(14, 0, 14, 0);
|
lay->setContentsMargins(14, 0, 14, 0);
|
||||||
|
|
@ -188,7 +189,10 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) {
|
||||||
|
|
||||||
lay->addWidget(makeIconButton(this, ElaIconType::CircleQuestion, QStringLiteral("帮助")));
|
lay->addWidget(makeIconButton(this, ElaIconType::CircleQuestion, QStringLiteral("帮助")));
|
||||||
lay->addWidget(makeIconButton(this, ElaIconType::Bell, QStringLiteral("通知")));
|
lay->addWidget(makeIconButton(this, ElaIconType::Bell, QStringLiteral("通知")));
|
||||||
lay->addWidget(makeIconButton(this, ElaIconType::Gear, QStringLiteral("设置")));
|
auto* gearBtn = makeIconButton(this, ElaIconType::Gear, QStringLiteral("设置"));
|
||||||
|
if (auto* gb = qobject_cast<QAbstractButton*>(gearBtn))
|
||||||
|
QObject::connect(gb, &QAbstractButton::clicked, this, [this] { emit settingsRequested(); });
|
||||||
|
lay->addWidget(gearBtn);
|
||||||
lay->addSpacing(10);
|
lay->addSpacing(10);
|
||||||
lay->addWidget(makeDivider(this));
|
lay->addWidget(makeDivider(this));
|
||||||
lay->addSpacing(12);
|
lay->addSpacing(12);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ signals:
|
||||||
void projectSwitchRequested(const QString& projectId);
|
void projectSwitchRequested(const QString& projectId);
|
||||||
void allProjectsRequested(); // 点击"全部项目…"
|
void allProjectsRequested(); // 点击"全部项目…"
|
||||||
void logoutRequested(); // 头像菜单「退出登录」
|
void logoutRequested(); // 头像菜单「退出登录」
|
||||||
|
void settingsRequested(); // 点击齿轮图标 → 打开设置
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QToolButton* wsBtn_ = nullptr;
|
QToolButton* wsBtn_ = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -104,10 +104,10 @@ LoginWindow::LoginWindow(geopro::net::AuthService& auth, QWidget* parent)
|
||||||
"#fieldLabel { color: #5A6B85; font-size: %4px; font-weight: %5; }"
|
"#fieldLabel { color: #5A6B85; font-size: %4px; font-weight: %5; }"
|
||||||
// 输入框已 Ela 化(ElaLineEdit 自绘 Fluent + 自动明暗),不再写 QLineEdit QSS。
|
// 输入框已 Ela 化(ElaLineEdit 自绘 Fluent + 自动明暗),不再写 QLineEdit QSS。
|
||||||
"#captchaImg { border: 1px solid #C7D2E0; border-radius: 8px; background: #EEF2FB; }")
|
"#captchaImg { border: 1px solid #C7D2E0; border-radius: 8px; background: #EEF2FB; }")
|
||||||
.arg(type::kDisplay)
|
.arg(scaledPx(type::kDisplay))
|
||||||
.arg(type::kWeightBold)
|
.arg(type::kWeightBold)
|
||||||
.arg(type::kCaption)
|
.arg(scaledPx(type::kCaption))
|
||||||
.arg(type::kCaption)
|
.arg(scaledPx(type::kCaption))
|
||||||
.arg(type::kWeightSemibold));
|
.arg(type::kWeightSemibold));
|
||||||
|
|
||||||
auto* root = new QVBoxLayout(this);
|
auto* root = new QVBoxLayout(this);
|
||||||
|
|
@ -198,7 +198,7 @@ LoginWindow::LoginWindow(geopro::net::AuthService& auth, QWidget* parent)
|
||||||
// 错误提示:固定占位高度,避免出现时整体布局跳动。
|
// 错误提示:固定占位高度,避免出现时整体布局跳动。
|
||||||
errorLabel_ = new QLabel(body);
|
errorLabel_ = new QLabel(body);
|
||||||
geopro::app::applyThemedStyleSheet(
|
geopro::app::applyThemedStyleSheet(
|
||||||
errorLabel_, QStringLiteral("color: #C0392B; font-size: %1px;").arg(type::kCaption));
|
errorLabel_, QStringLiteral("color: #C0392B; font-size: %1px;").arg(scaledPx(type::kCaption)));
|
||||||
errorLabel_->setWordWrap(true);
|
errorLabel_->setWordWrap(true);
|
||||||
errorLabel_->setMinimumHeight(18);
|
errorLabel_->setMinimumHeight(18);
|
||||||
form->addWidget(errorLabel_);
|
form->addWidget(errorLabel_);
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@
|
||||||
#include "Glyphs.hpp"
|
#include "Glyphs.hpp"
|
||||||
#include "PanelHeader.hpp"
|
#include "PanelHeader.hpp"
|
||||||
#include "Theme.hpp"
|
#include "Theme.hpp"
|
||||||
|
#include "SettingsDialog.hpp"
|
||||||
#include "TopBar.hpp"
|
#include "TopBar.hpp"
|
||||||
#include "CentralScene.hpp"
|
#include "CentralScene.hpp"
|
||||||
#include "ProjectListDialog.hpp"
|
#include "ProjectListDialog.hpp"
|
||||||
|
|
@ -335,7 +336,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
"QToolButton:hover{ background:#EEF3FB; }"
|
"QToolButton:hover{ background:#EEF3FB; }"
|
||||||
"QToolButton:checked{ color:#2D6CB5; font-weight:%2;"
|
"QToolButton:checked{ color:#2D6CB5; font-weight:%2;"
|
||||||
" border-bottom:2px solid #2D6CB5; }")
|
" border-bottom:2px solid #2D6CB5; }")
|
||||||
.arg(geopro::app::type::kBody)
|
.arg(geopro::app::scaledPx(geopro::app::type::kBody))
|
||||||
.arg(geopro::app::type::kWeightSemibold);
|
.arg(geopro::app::type::kWeightSemibold);
|
||||||
|
|
||||||
// 工具条:「二维地图/三维视图」两个互斥可勾选按钮。默认二维地图。
|
// 工具条:「二维地图/三维视图」两个互斥可勾选按钮。默认二维地图。
|
||||||
|
|
@ -380,7 +381,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
layerTitle, QStringLiteral("font-weight:%1;color:#2D6CB5;border:none;background:transparent;"
|
layerTitle, QStringLiteral("font-weight:%1;color:#2D6CB5;border:none;background:transparent;"
|
||||||
"padding-bottom:3px;font-size:%2px;")
|
"padding-bottom:3px;font-size:%2px;")
|
||||||
.arg(geopro::app::type::kWeightSemibold)
|
.arg(geopro::app::type::kWeightSemibold)
|
||||||
.arg(geopro::app::type::kTitle));
|
.arg(geopro::app::scaledPx(geopro::app::type::kTitle)));
|
||||||
auto* chkCurtain = new ElaCheckBox(QStringLiteral("帘面(断面墙)"));
|
auto* chkCurtain = new ElaCheckBox(QStringLiteral("帘面(断面墙)"));
|
||||||
chkCurtain->setChecked(true);
|
chkCurtain->setChecked(true);
|
||||||
auto* chkVoxel = new ElaCheckBox(QStringLiteral("体素(dd_voxel)"));
|
auto* chkVoxel = new ElaCheckBox(QStringLiteral("体素(dd_voxel)"));
|
||||||
|
|
@ -431,7 +432,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
esTitle->setAlignment(Qt::AlignCenter);
|
esTitle->setAlignment(Qt::AlignCenter);
|
||||||
geopro::app::applyThemedStyleSheet(
|
geopro::app::applyThemedStyleSheet(
|
||||||
esTitle, QStringLiteral("color:#5A6B85; font-size:%1px; font-weight:%2;")
|
esTitle, QStringLiteral("color:#5A6B85; font-size:%1px; font-weight:%2;")
|
||||||
.arg(geopro::app::type::kHeading)
|
.arg(geopro::app::scaledPx(geopro::app::type::kHeading))
|
||||||
.arg(geopro::app::type::kWeightSemibold));
|
.arg(geopro::app::type::kWeightSemibold));
|
||||||
|
|
||||||
auto* esHint = new QLabel(QStringLiteral("单击左侧采集批次,查看反演剖面与异常点\n"
|
auto* esHint = new QLabel(QStringLiteral("单击左侧采集批次,查看反演剖面与异常点\n"
|
||||||
|
|
@ -439,7 +440,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
emptyState);
|
emptyState);
|
||||||
esHint->setAlignment(Qt::AlignCenter);
|
esHint->setAlignment(Qt::AlignCenter);
|
||||||
geopro::app::applyThemedStyleSheet(
|
geopro::app::applyThemedStyleSheet(
|
||||||
esHint, QStringLiteral("color:#8A93A3; font-size:%1px;").arg(geopro::app::type::kBody));
|
esHint,
|
||||||
|
QStringLiteral("color:#8A93A3; font-size:%1px;").arg(geopro::app::scaledPx(geopro::app::type::kBody)));
|
||||||
|
|
||||||
esLay->addWidget(esIcon);
|
esLay->addWidget(esIcon);
|
||||||
esLay->addWidget(esTitle);
|
esLay->addWidget(esTitle);
|
||||||
|
|
@ -930,6 +932,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
QCoreApplication::arguments().mid(1));
|
QCoreApplication::arguments().mid(1));
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
});
|
});
|
||||||
|
// 设置:点齿轮 → 打开设置对话框(外观/关于)。
|
||||||
|
QObject::connect(topBar, &geopro::app::TopBar::settingsRequested, &window, [&window]() {
|
||||||
|
geopro::app::SettingsDialog dlg(&window);
|
||||||
|
dlg.exec();
|
||||||
|
});
|
||||||
QObject::connect(topBar, &geopro::app::TopBar::allProjectsRequested, &window,
|
QObject::connect(topBar, &geopro::app::TopBar::allProjectsRequested, &window,
|
||||||
[&projectRepo, &nav, topBar, &window]() {
|
[&projectRepo, &nav, topBar, &window]() {
|
||||||
auto* dlg = new geopro::app::ProjectListDialog(projectRepo, &window);
|
auto* dlg = new geopro::app::ProjectListDialog(projectRepo, &window);
|
||||||
|
|
@ -1060,9 +1067,11 @@ int main(int argc, char* argv[])
|
||||||
// 两种壳都需要它(登录发生在选壳之前)。Ela 控件跟随 ElaTheme;标准控件仍由下面 QSS 接管。
|
// 两种壳都需要它(登录发生在选壳之前)。Ela 控件跟随 ElaTheme;标准控件仍由下面 QSS 接管。
|
||||||
eApp->init();
|
eApp->init();
|
||||||
geopro::app::applyBrandAccent(); // 统一品牌强调色(Ela Primary),全 UI 选中/激活一套蓝
|
geopro::app::applyBrandAccent(); // 统一品牌强调色(Ela Primary),全 UI 选中/激活一套蓝
|
||||||
|
geopro::app::applyPersistedThemeMode(); // 应用持久化主题(跟随系统/浅/深)——登录页与主页统一
|
||||||
|
geopro::app::applyPersistedFontScale(); // 应用持久化字号缩放(登录页也随之缩放)
|
||||||
|
|
||||||
// 专业主题(Fusion + 调色板 + 全局样式表):标准控件外观,登录窗与工作台共用。
|
// 专业主题(Fusion + 调色板 + 全局样式表):标准控件外观,登录窗与工作台共用。
|
||||||
// 跟随 ElaTheme 初始模式(可能随系统为暗),使登录窗与标准控件明暗一致(review M2)。
|
// 跟随最终 ElaTheme 模式(持久化偏好已生效),使登录窗与标准控件明暗一致。
|
||||||
geopro::app::applyThemeMode(app, eTheme->getThemeMode() == ElaThemeType::Dark);
|
geopro::app::applyThemeMode(app, eTheme->getThemeMode() == ElaThemeType::Dark);
|
||||||
|
|
||||||
// PROJ 数据(proj.db)定位:体素配准的 CrsTransform 需要。优先已设环境变量;
|
// PROJ 数据(proj.db)定位:体素配准的 CrsTransform 需要。优先已设环境变量;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue