chore(ela): ElaWidgetTools 评估 spike + 全面迁移计划 + 构建 TEMP 兜底
- spike/ela: 隔离 demo 验证 ElaWindow + ADS 内嵌 + QVTK + 明暗切换(Qt6.11.1/MSVC 构建通过) - CMakeLists: FetchContent 引入 ElaWidgetTools(fork,SOURCE_SUBDIR 仅编库) + 挂 spike - build.bat: TEMP/TMP 重定向到 D: 构建目录,规避 C: 盘满导致的 LNK1108 - docs: 全面 Ela 化迁移计划(P0-P4 + 控件映射表 + 风险登记)
This commit is contained in:
parent
1a9fb72cf0
commit
6df2c4832c
|
|
@ -63,7 +63,21 @@ FetchContent_Declare(qtkeychain
|
|||
GIT_TAG v0.14.0)
|
||||
FetchContent_MakeAvailable(qtkeychain)
|
||||
|
||||
# 【ElaWidgetTools 评估 spike — 仅 feat/elawidgettools 分支】Fluent UI for QWidget。
|
||||
# 用 RainbowCandyX fork(支持 Qt6.10+,对 6.11 有条件修补)。SOURCE_SUBDIR 仅编库子目录,
|
||||
# 跳过其示例/PySide bindings。静态链接(MIT 许可,static 合规且省 DLL)。库子目录自带
|
||||
# find_package(Qt6 Widgets/WidgetsPrivate) 与自身 .qrc(靠全局 AUTORCC)。仅隔离评估,不影响产品。
|
||||
set(ELAWIDGETTOOLS_BUILD_STATIC_LIB ON CACHE BOOL "" FORCE)
|
||||
FetchContent_Declare(elawidgettools
|
||||
GIT_REPOSITORY https://github.com/RainbowCandyX/ElaWidgetTools.git
|
||||
GIT_TAG main
|
||||
SOURCE_SUBDIR ElaWidgetTools)
|
||||
FetchContent_MakeAvailable(elawidgettools)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
# ElaWidgetTools 评估 spike(隔离 demo,不属于产品 geopro_desktop;评估完删分支即弃)。
|
||||
add_subdirectory(spike/ela)
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ set "ROOT=%~dp0"
|
|||
set "BUILDDIR=%ROOT%build\release"
|
||||
set "PRESET=msvc-release"
|
||||
|
||||
REM 把临时目录指向 D: 的构建目录,规避 C: 盘满导致链接器写 %TEMP% 失败(LNK1108)。
|
||||
REM 仅作用于本次构建(setlocal 作用域),不污染用户 shell。注意:仍建议尽快清理 C: 盘。
|
||||
set "TEMP=%BUILDDIR%\tmp"
|
||||
set "TMP=%BUILDDIR%\tmp"
|
||||
if not exist "%TEMP%" mkdir "%TEMP%"
|
||||
|
||||
REM --- locate Visual Studio (vswhere lives at a fixed path) ---
|
||||
set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
if not exist "%VSWHERE%" (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
# geopro_desktop → ElaWidgetTools (Fluent) 迁移计划
|
||||
|
||||
**分支**:`feat/elawidgettools` **日期**:2026-06-09 **决策**:全面 Ela 化(最彻底),支持明/暗主题。
|
||||
**前置评估已完成**:spike(`spike/ela/`) 证明 ElaWidgetTools(RainbowCandyX fork) 可用官方 Qt 6.11.1 + MSVC 经 FetchContent 构建,ElaWindow + ADS 内嵌 + QVTK 渲染均可行;ElaTheme 明暗切换可用,但**只自动覆盖 Ela\* 控件与 ElaWindow 外壳**,标准 QWidget/ADS/VTK 需手工主题联动。
|
||||
|
||||
---
|
||||
|
||||
## 0. 硬前提(动手前必须满足)
|
||||
|
||||
- **P0-a 清理 C: 盘**:当前 C: 0 GB 可用,链接器写 `%TEMP%` 失败(`LNK1108`)。迁移需大量构建验证。需用户清理 C:;我同时把 `TEMP/TMP→D:` 兜底固化进 `build.bat`,避免反复手动重定向。
|
||||
- **P0-b 验证靠用户**:每阶段我构建通过后,用户运行 + 截图,我据反馈迭代(登录门槛 + GUI,我无法目视)。
|
||||
- **P0-c 回退保障**:全程保留 `GEOPRO_UI_SHELL=classic|ela` 环境变量开关,可在「现 QMainWindow 壳」与「ElaWindow 壳」间切换,便于 A/B 与回退;迁移稳定后再移除。
|
||||
|
||||
## 1. 依赖固化(P0 工程)
|
||||
|
||||
- ElaWidgetTools 从 spike 提升为**正式依赖**:`FetchContent` 的 `GIT_TAG` 由 `main` **钉到具体 commit**(可复现)。
|
||||
- **静/动态**:先静态(MIT,省 DLL);若遇静态资源(字体/SVG 图标 .qrc)被剥离导致图标缺失,改动态(`ELAWIDGETTOOLS_BUILD_STATIC_LIB OFF` + DLL 随 `TARGET_RUNTIME_DLLS` 拷贝)。
|
||||
- **插件部署**:把 `platforms / styles / imageformats / iconengines`(含 SVG 图标用的 `qsvg`/`qsvgicon`)部署接进 `geopro_desktop` 的 post-build(今天 spike 是手动拷的,要正式化;windeployqt 会被 ADS 的 DLL 依赖卡住,改为显式 copy Qt plugins)。
|
||||
|
||||
## 2. P1 — 换壳(带开关)
|
||||
|
||||
- 新建 `ElaShellWindow`(继承 `ElaWindow`)或在 `main()` 分支构造。把现有 `buildWorkbench()` 产出的中心内容(ADS `CDockManager` + 工具条)作为 ElaWindow 的一个 page/central content 挂入(`addPageNode` / `setCentralCustomWidget`)。
|
||||
- `eApp->init()` 在 `QApplication` 后调用;保留高 DPI 与 QVTK surface format 设置顺序。
|
||||
- **dock 持久化注意**:ElaWindow 接管后,`restoreState` 后重隐藏 ADS 标题栏的时序修复(已在主分支)需在新壳下复核。
|
||||
- **验收**:`GEOPRO_UI_SHELL=ela` 启动 → 登录 → 工作台;ADS 停靠可拖动;中央/详情 VTK 正常;导航/标题栏 Fluent 外观。截图确认。
|
||||
|
||||
## 3. P2 — 主题桥(明/暗覆盖所有非 Ela 面)
|
||||
|
||||
- 新建 `ThemeBridge`:监听 `ElaTheme::themeModeChanged`,把明/暗同步到:
|
||||
1. **全局 QSS**:把 `Theme.cpp` 的 `kStyleSheet` 拆成「明」与「暗」两版(用已有 `type/space/radius/semantic` 令牌派生暗色盘),按主题切换。
|
||||
2. **ADS 停靠区**:`CDockManager::setStyleSheet` 明/暗两套。
|
||||
3. **VTK 背景**:中央 + 详情 renderer 背景随主题切深/浅底并 `Render()`。
|
||||
4. **内联样式面板**:PanelHeader / TopBar / LoginWindow / main 浮层 的内联 QSS 改为「跟随主题」(去硬编码色,引用桥提供的明/暗令牌)。
|
||||
- **暗色盘设计**:在 `Theme.hpp` 增加暗色语义(surface/ink/border/accent 的暗版),保持品牌蓝在暗底的可读性与对比度(≥4.5:1)。
|
||||
- **验收**:明/暗一键切换,全界面(外壳+停靠+面板+VTK)协调一致、无残留亮/暗块;对比度达标。截图明、暗各一。
|
||||
|
||||
## 4. P3 — 全面控件 Ela 化(工作量主体)
|
||||
|
||||
逐面替换标准控件为 `Ela*` 等价物,"白嫖"明暗与 Fluent 观感。映射(精确 Ela 类名在实施时按头文件确认):
|
||||
|
||||
| 现状 | → Ela 等价 | 所在 |
|
||||
|---|---|---|
|
||||
| QPushButton | ElaPushButton | LoginWindow / 各处 |
|
||||
| QLineEdit | ElaLineEdit | LoginWindow / ProjectListDialog 过滤 |
|
||||
| QCheckBox | ElaCheckBox | LoginWindow / 图层浮层 / 异常列表 |
|
||||
| QComboBox | ElaComboBox | ProjectListDialog / 全局 |
|
||||
| QLabel(文本) | ElaText | 各处文本/标题 |
|
||||
| QToolButton(Tab/操作) | ElaToolButton / ElaIconButton | PanelHeader / TopBar |
|
||||
| QMenuBar / QMenu | ElaMenuBar / ElaMenu | TopBar |
|
||||
| QTreeWidget | ElaTreeView(+model) 或保留+主题联动 | ObjectTreePanel |
|
||||
| QListWidget | ElaListView(+model) 或保留+联动 | Dataset/Anomaly 面板 |
|
||||
| QTableWidget | ElaTableView 或保留+联动 | ProjectListDialog |
|
||||
| QProgressBar | ElaProgressBar | 全局 |
|
||||
| QStatusBar | ElaStatusBar 或保留+联动 | main |
|
||||
| QTabWidget/分段 | ElaTabWidget / ElaToggleSwitch | PanelHeader 数据/文件 |
|
||||
| QDialog(登录) | ElaWidget/ElaWindow 风格弹窗 | LoginWindow |
|
||||
| **保留(无替代)** | QVTKOpenGLStereoWidget、ADS CDockManager | 中央/详情/停靠 |
|
||||
|
||||
- 树/列表/表若用 Ela 的 View 需改 model(成本高),可分两步:先保留 widget 版做主题联动,后续再评估换 View。
|
||||
- 登录窗重做为 Fluent 风格(沿用现有令牌与文案)。
|
||||
|
||||
## 5. P4 — 收尾
|
||||
|
||||
- 插件部署正式化、ElaWidgetTools 版本锁定、静态资源核验。
|
||||
- 去掉 `GEOPRO_UI_SHELL` 过渡开关(确认稳定后)。
|
||||
- 开源声明:ElaWidgetTools(MIT)、ADS(LGPLv2.1)、Qt(LGPL) NOTICE 归集。
|
||||
- 回归:登录、项目切换、对象树、数据集/文件分页、异常、VTK 各视图、dock 持久化。
|
||||
|
||||
## 风险登记
|
||||
|
||||
| 风险 | 缓解 |
|
||||
|---|---|
|
||||
| Qt 6.11 Windows Popup 渲染(作者红旗) | spike 已初验;P1 重点复核菜单/下拉/提示;必要时打 fork 的条件补丁 |
|
||||
| ADS 在 ElaWindow 内主题/交互异常 | spike 已验内嵌;P2 专门做 ADS 明暗 QSS |
|
||||
| Ela View 需 model 重写(树/列表/表) | 分步:先 widget 版主题联动,再评估换 View |
|
||||
| 静态库资源剥离(图标/字体缺失) | 改动态库 |
|
||||
| 我无法目视 | 每阶段用户运行+截图验收 |
|
||||
| C: 满导致构建反复失败 | 清理 C: + TEMP→D: 固化进 build.bat |
|
||||
| 大重构回归 | 全程 env 开关可回退;主分支零影响 |
|
||||
|
||||
## 执行顺序
|
||||
|
||||
P0 → P1(验收)→ P2(验收)→ P3(按面板分批,每批验收)→ P4。每步构建通过后由用户运行+截图确认再进下一步。
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# ElaWidgetTools 评估 spike(隔离 demo,独立 exe)。仅 feat/elawidgettools 分支评估用,
|
||||
# 与产品 geopro_desktop 完全解耦:链 ElaWidgetTools(Fluent 库) + ADS + VTK,验证可行性与观感。
|
||||
add_executable(geopro_ela_spike WIN32 main.cpp)
|
||||
|
||||
target_link_libraries(geopro_ela_spike PRIVATE
|
||||
Qt6::Core Qt6::Gui Qt6::Widgets
|
||||
ElaWidgetTools
|
||||
ads::qt6advanceddocking
|
||||
${VTK_LIBRARIES})
|
||||
|
||||
vtk_module_autoinit(TARGETS geopro_ela_spike MODULES ${VTK_LIBRARIES})
|
||||
|
||||
if(WIN32)
|
||||
add_custom_command(TARGET geopro_ela_spike POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_RUNTIME_DLLS:geopro_ela_spike> $<TARGET_FILE_DIR:geopro_ela_spike>
|
||||
COMMAND_EXPAND_LISTS)
|
||||
endif()
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// ElaWidgetTools 评估 spike(隔离 demo,不属于产品 app,仅 feat/elawidgettools 分支评估用)。
|
||||
// 一锤定音验证四件事:
|
||||
// ① 用你们官方 Qt 6.11.1 + MSVC 经 FetchContent 能否构建 ElaWidgetTools(RainbowCandyX fork);
|
||||
// ② ElaWindow 的 Fluent 观感在你们机器上渲染是否正常(重点看 Qt6.11 的 Popup/弹窗);
|
||||
// ③ Qt Advanced Docking System(ADS) 能否内嵌进 ElaWindow;
|
||||
// ④ QVTKOpenGLStereoWidget 视口在 ElaWindow + ADS 内能否正常渲染。
|
||||
// 结论决定是否值得对真实 app 做外壳重构。
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "ElaApplication.h"
|
||||
#include "ElaDef.h"
|
||||
#include "ElaPushButton.h"
|
||||
#include "ElaText.h"
|
||||
#include "ElaTheme.h"
|
||||
#include "ElaWindow.h"
|
||||
|
||||
#include <DockManager.h>
|
||||
#include <DockWidget.h>
|
||||
|
||||
#include <QVTKOpenGLStereoWidget.h>
|
||||
#include <vtkActor.h>
|
||||
#include <vtkConeSource.h>
|
||||
#include <vtkGenericOpenGLRenderWindow.h>
|
||||
#include <vtkNew.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkProperty.h>
|
||||
#include <vtkRenderer.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication::setHighDpiScaleFactorRoundingPolicy(
|
||||
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
QSurfaceFormat::setDefaultFormat(QVTKOpenGLStereoWidget::defaultFormat());
|
||||
|
||||
QApplication app(argc, argv);
|
||||
eApp->init(); // ElaApplication 初始化(Fluent 主题/字体/动画基建)
|
||||
|
||||
ElaWindow window;
|
||||
window.setWindowTitle(QStringLiteral("ElaWidgetTools Spike — Fluent + ADS + VTK"));
|
||||
window.resize(1200, 760);
|
||||
|
||||
// 「工作台」页内嵌 ADS 停靠管理器:验证 ADS 能否在 ElaWindow 内正常工作。
|
||||
auto* dockHost = new QWidget;
|
||||
auto* hostLay = new QVBoxLayout(dockHost);
|
||||
hostLay->setContentsMargins(0, 0, 0, 0);
|
||||
auto* dockManager = new ads::CDockManager(dockHost);
|
||||
hostLay->addWidget(dockManager);
|
||||
|
||||
// dock1:Fluent 控件样例(看观感:ElaText / ElaPushButton 与标准控件对照)。
|
||||
auto* sample = new QWidget;
|
||||
sample->setObjectName(QStringLiteral("sampleHost"));
|
||||
auto* sLay = new QVBoxLayout(sample);
|
||||
sLay->setContentsMargins(16, 16, 16, 16);
|
||||
sLay->setSpacing(12);
|
||||
sLay->addWidget(new ElaText(QStringLiteral("ElaText —— Fluent 文本"), sample));
|
||||
sLay->addWidget(new ElaPushButton(QStringLiteral("ElaPushButton 主操作"), sample));
|
||||
sLay->addWidget(new QLabel(QStringLiteral("(对照)标准 QLabel"), sample));
|
||||
|
||||
// 浅/深主题切换:ElaWidgetTools 内置 ElaTheme,运行期一键切换整套 Fluent 主题。
|
||||
auto* themeBtn = new ElaPushButton(QStringLiteral("切换 浅色 / 深色"), sample);
|
||||
QObject::connect(themeBtn, &QPushButton::clicked, themeBtn, [] {
|
||||
eTheme->setThemeMode(eTheme->getThemeMode() == ElaThemeType::Light ? ElaThemeType::Dark
|
||||
: ElaThemeType::Light);
|
||||
});
|
||||
sLay->addWidget(themeBtn);
|
||||
sLay->addStretch();
|
||||
auto* d1 = new ads::CDockWidget(QStringLiteral("Fluent 控件"));
|
||||
d1->setWidget(sample);
|
||||
dockManager->addDockWidget(ads::LeftDockWidgetArea, d1);
|
||||
|
||||
// dock2:QVTK 视口(蓝色锥体),验证 VTK 在 ElaWindow + ADS 内渲染。
|
||||
auto* vtkWidget = new QVTKOpenGLStereoWidget;
|
||||
vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
|
||||
vtkNew<vtkRenderer> renderer;
|
||||
renderer->SetBackground(1.0, 1.0, 1.0);
|
||||
vtkWidget->setRenderWindow(renderWindow);
|
||||
renderWindow->AddRenderer(renderer);
|
||||
vtkNew<vtkConeSource> cone;
|
||||
cone->SetResolution(48);
|
||||
vtkNew<vtkPolyDataMapper> mapper;
|
||||
mapper->SetInputConnection(cone->GetOutputPort());
|
||||
vtkNew<vtkActor> actor;
|
||||
actor->SetMapper(mapper);
|
||||
actor->GetProperty()->SetColor(0.18, 0.42, 0.71); // 品牌蓝 #2D6CB5 近似
|
||||
renderer->AddActor(actor);
|
||||
renderer->ResetCamera();
|
||||
auto* d2 = new ads::CDockWidget(QStringLiteral("VTK 视口(锥体)"));
|
||||
d2->setWidget(vtkWidget);
|
||||
dockManager->addDockWidget(ads::RightDockWidgetArea, d2);
|
||||
|
||||
// 关键发现演示:ADS 停靠区与普通 QWidget 不会自动跟随 ElaTheme(只有 Ela* 控件与
|
||||
// ElaWindow 外壳跟随)。这里手动把「停靠区背景 + 普通容器 + VTK 背景」同步到当前主题,
|
||||
// 并监听 ElaTheme::themeModeChanged。这段「同步」正是真集成时要为每个非 Ela 面板付出的成本。
|
||||
auto* rendererPtr = renderer.Get();
|
||||
auto* rwPtr = renderWindow.Get();
|
||||
auto applyContentTheme = [dockManager, sample, rendererPtr, rwPtr](ElaThemeType::ThemeMode mode) {
|
||||
const bool dark = (mode == ElaThemeType::Dark);
|
||||
const QString bg = dark ? QStringLiteral("#1E1F22") : QStringLiteral("#FFFFFF");
|
||||
const QString fg = dark ? QStringLiteral("#E3E3E3") : QStringLiteral("#1F2A3D");
|
||||
dockManager->setStyleSheet(
|
||||
QStringLiteral("ads--CDockAreaWidget, ads--CDockContainerWidget { background:%1; }")
|
||||
.arg(bg));
|
||||
sample->setStyleSheet(
|
||||
QStringLiteral("#sampleHost { background:%1; } #sampleHost QLabel { color:%2; }")
|
||||
.arg(bg, fg));
|
||||
rendererPtr->SetBackground(dark ? 0.11 : 1.0, dark ? 0.12 : 1.0, dark ? 0.14 : 1.0);
|
||||
rwPtr->Render();
|
||||
};
|
||||
QObject::connect(eTheme, &ElaTheme::themeModeChanged, dockManager,
|
||||
[applyContentTheme](ElaThemeType::ThemeMode m) { applyContentTheme(m); });
|
||||
applyContentTheme(eTheme->getThemeMode()); // 初始同步当前主题
|
||||
|
||||
window.addPageNode(QStringLiteral("工作台"), dockHost);
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
||||
Loading…
Reference in New Issue