feat(ui): 全局下拉空态优化 EmptyAwareComboBox(占位+暂无数据,对齐Arco)

下拉无数据时原为空白框+空弹窗,不优雅。新增统一空态感知下拉对齐原版 Arco ASelect:
- EmptyAwareComboBox(QComboBox 子类):showPopup 无真实项时临时插禁用灰色「暂无数据」
  条(关闭即移除,不污染取值),仍可点开;占位经 setPlaceholderText(currentIndex=-1)显示
- FormKit 加 comboBox(placeholder) 统一入口
- 全局替换全部 37 处 new QComboBox:7 处数据驱动给占位(白化文件/异常类型/反演模型/
  导入类型脚本/导出模板),30 处仅换类保留自动选首项语义(逐处判断,不破坏取值)

build all 绿,341/341。
This commit is contained in:
gaozheng 2026-06-23 17:35:54 +08:00
parent f51706b4b3
commit 7d0e72dec2
31 changed files with 213 additions and 45 deletions

View File

@ -1,6 +1,8 @@
#include "AnomalySaveDialog.hpp" #include "AnomalySaveDialog.hpp"
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFormLayout> #include <QFormLayout>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
@ -39,7 +41,7 @@ AnomalySaveDialog::AnomalySaveDialog(const QString& screenshotPath, int shotW, i
formkit::capField(name_); formkit::capField(name_);
form->addRow(formkit::editLabel(QStringLiteral("名称")), name_); form->addRow(formkit::editLabel(QStringLiteral("名称")), name_);
type_ = new QComboBox(); type_ = new EmptyAwareComboBox();
for (const auto& t : kMockTypes) for (const auto& t : kMockTypes)
type_->addItem(QString::fromUtf8(t.label), QString::fromUtf8(t.id)); type_->addItem(QString::fromUtf8(t.label), QString::fromUtf8(t.id));
formkit::capField(type_); formkit::capField(type_);

View File

@ -22,6 +22,7 @@ add_executable(geopro_desktop WIN32
main.cpp main.cpp
Theme.cpp Theme.cpp
FormKit.cpp FormKit.cpp
EmptyAwareComboBox.cpp
TopBar.cpp TopBar.cpp
ToastOverlay.cpp ToastOverlay.cpp
Glyphs.cpp Glyphs.cpp

View File

@ -5,6 +5,8 @@
#include <QColorDialog> #include <QColorDialog>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QFile> #include <QFile>
@ -105,7 +107,7 @@ ColorGradientDialog::ColorGradientDialog(const std::vector<Stop>& init, double m
int rowIdx = 0; int rowIdx = 0;
// 配色方案(下拉带预览色条)。 // 配色方案(下拉带预览色条)。
schemeCombo_ = new QComboBox(this); schemeCombo_ = new EmptyAwareComboBox(this);
schemeCombo_->setIconSize(QSize(100, 16)); schemeCombo_->setIconSize(QSize(100, 16));
{ {
auto* cell = new QHBoxLayout(); auto* cell = new QHBoxLayout();
@ -118,7 +120,7 @@ ColorGradientDialog::ColorGradientDialog(const std::vector<Stop>& init, double m
{ {
auto* cell = new QHBoxLayout(); auto* cell = new QHBoxLayout();
cell->addWidget(formkit::editLabel(QStringLiteral("分布方式:"))); cell->addWidget(formkit::editLabel(QStringLiteral("分布方式:")));
auto* distCombo = new QComboBox(this); auto* distCombo = new EmptyAwareComboBox(this);
distCombo->addItem(QStringLiteral("线性"), QStringLiteral("linear")); distCombo->addItem(QStringLiteral("线性"), QStringLiteral("linear"));
distCombo->addItem(QStringLiteral("对数"), QStringLiteral("log")); distCombo->addItem(QStringLiteral("对数"), QStringLiteral("log"));
distCombo->setCurrentIndex(0); distCombo->setCurrentIndex(0);

View File

@ -3,6 +3,8 @@
#include <cmath> #include <cmath>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QDoubleValidator> #include <QDoubleValidator>
#include <QFormLayout> #include <QFormLayout>
@ -38,7 +40,7 @@ ContourLevelDialog::ContourLevelDialog(const ContourLevelParams& init, double or
new QLabel(QStringLiteral("%1 ~ %2").arg(originMin_).arg(originMax_))); new QLabel(QStringLiteral("%1 ~ %2").arg(originMin_).arg(originMax_)));
// 分层方式。 // 分层方式。
methodCombo_ = new QComboBox(this); methodCombo_ = new EmptyAwareComboBox(this);
methodCombo_->addItem(QStringLiteral("一般的"), 0); methodCombo_->addItem(QStringLiteral("一般的"), 0);
methodCombo_->addItem(QStringLiteral("对数"), 1); methodCombo_->addItem(QStringLiteral("对数"), 1);
methodCombo_->addItem(QStringLiteral("等积"), 2); methodCombo_->addItem(QStringLiteral("等积"), 2);

View File

@ -4,6 +4,8 @@
#include <QColor> #include <QColor>
#include <QColorDialog> #include <QColorDialog>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QFormLayout> #include <QFormLayout>
#include <QPushButton> #include <QPushButton>
@ -34,7 +36,7 @@ ContourLineDialog::ContourLineDialog(const ContourLineConfig& init, QWidget* par
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
// 复刻 contourLine.vue选项顺序「虚线」在前、「实线」在后。 // 复刻 contourLine.vue选项顺序「虚线」在前、「实线」在后。
lineTypeCombo_ = new QComboBox(this); lineTypeCombo_ = new EmptyAwareComboBox(this);
lineTypeCombo_->addItem(QStringLiteral("- - - - - - - - -"), true); // dashed lineTypeCombo_->addItem(QStringLiteral("- - - - - - - - -"), true); // dashed
lineTypeCombo_->addItem(QStringLiteral("——————"), false); // solid lineTypeCombo_->addItem(QStringLiteral("——————"), false); // solid
lineTypeCombo_->setCurrentIndex(cfg_.dashed ? 0 : 1); lineTypeCombo_->setCurrentIndex(cfg_.dashed ? 0 : 1);

View File

@ -0,0 +1,65 @@
#include "EmptyAwareComboBox.hpp"
#include <QColor>
#include <QStandardItem>
#include <QStandardItemModel>
#include "Theme.hpp"
namespace geopro::app {
namespace {
// 临时「暂无数据」项用 UserRole 打标,便于 realItemCount/hidePopup 精准识别与移除。
constexpr int kEmptyHintRole = Qt::UserRole + 9001;
const char* kEmptyHintText = "暂无数据";
} // namespace
EmptyAwareComboBox::EmptyAwareComboBox(QWidget* parent) : QComboBox(parent) {
// 不在此强设 currentIndex。占位语义由 setPlaceholderText 的「添加项前调用」时机决定:
// - 经 formkit::comboBox(placeholder,...) 建的(占位在添加项前设好)→ 即便后续异步加入
// 数据项Qt 仍维持 currentIndex=-1 显示占位不自动选首项Arco ASelect 占位语义)。
// - 不带占位直接 new 的静态下拉 → addItem 首项后 Qt 自动选中索引 0保持既有默认选中行为
}
int EmptyAwareComboBox::realItemCount() const {
int n = 0;
for (int i = 0; i < count(); ++i) {
// 排除临时「暂无数据」占位项。
if (itemData(i, kEmptyHintRole).toBool()) continue;
// 排除不可选项(禁用 / NoItemFlags它们不构成「真实可选数据」。
if (!(itemData(i, Qt::UserRole - 1).value<Qt::ItemFlags>() & Qt::ItemIsSelectable))
continue;
++n;
}
return n;
}
void EmptyAwareComboBox::showPopup() {
// 无真实可选项时,临时插入一条灰色禁用「暂无数据」,让弹窗不再空白(同 Arco
if (realItemCount() == 0 && !emptyHintInserted_) {
addItem(QString::fromUtf8(kEmptyHintText));
const int idx = count() - 1;
setItemData(idx, true, kEmptyHintRole); // 打标,关闭时按标移除
setItemData(idx, Qt::AlignCenter, Qt::TextAlignmentRole);
// 灰色禁用观感:取项目 token 色text/disabled与 Arco 空态一致。
setItemData(idx, tokenColor("text/disabled"), Qt::ForegroundRole);
if (auto* m = qobject_cast<QStandardItemModel*>(model())) {
if (auto* it = m->item(idx)) it->setFlags(Qt::NoItemFlags); // 不可选/不可聚焦
}
emptyHintInserted_ = true;
}
QComboBox::showPopup();
}
void EmptyAwareComboBox::hidePopup() {
QComboBox::hidePopup();
// 移除临时「暂无数据」项,恢复纯净数据(取值/计数不受污染)。临时项是禁用不可选的,
// 用户无法选中它,故移除后 currentIndex 自然维持原值(占位组合仍为 -1无需强设
if (emptyHintInserted_) {
for (int i = count() - 1; i >= 0; --i)
if (itemData(i, kEmptyHintRole).toBool()) removeItem(i);
emptyHintInserted_ = false;
}
}
} // namespace geopro::app

View File

@ -0,0 +1,34 @@
#pragma once
// EmptyAwareComboBox —— 空态感知下拉框(对齐原版 web Arco ASelect 观感)。
//
// 历史问题:数据驱动的下拉(白化文件、异常类型、反演模型……)异步加载,加载前/无数据时:
// 1) 裸 QComboBox 会自动选中首项或留空,无「请选择 X」灰色占位提示
// 2) 弹窗里一片空白,用户不知是「加载中」还是「真的没有」。
// Arco ASelect 的标准行为是:未选时显示灰色占位文案,无数据时弹窗显示一条灰色「暂无数据」。
// 本类把这两点收敛到唯一实现,全局通过 formkit::comboBox(...) 建下拉即自动获得一致观感。
#include <QComboBox>
namespace geopro::app {
// QComboBox 子类未选→占位文案Qt6 自带 placeholderTextcurrentIndex=-1 时显示);
// 无真实可选项→点开弹窗时临时插入一条禁用的灰色「暂无数据」,弹窗关闭后移除(不污染数据/取值)。
class EmptyAwareComboBox : public QComboBox {
Q_OBJECT
public:
explicit EmptyAwareComboBox(QWidget* parent = nullptr);
// 点开弹窗:若无真实可选项(排除占位/禁用项),临时插入一条禁用「暂无数据」再弹出。
void showPopup() override;
// 关闭弹窗:移除临时「暂无数据」项,保证数据/取值不被污染。
void hidePopup() override;
private:
// 统计「真实可选条目数」排除占位项与不可选NoItemFlags/禁用)项。
int realItemCount() const;
bool emptyHintInserted_ = false; // 当前是否插入了临时「暂无数据」项
};
} // namespace geopro::app

View File

@ -35,7 +35,8 @@ ExportDatasetDialog::ExportDatasetDialog(geopro::data::IAsyncProjectRepository&
auto* cardLay = formkit::cardBody(card); auto* cardLay = formkit::cardBody(card);
auto* fl = formkit::makeEditForm(); auto* fl = formkit::makeEditForm();
templateCombo_ = new QComboBox(this); // 空态感知下拉:数据驱动(异步 loadTemplates未选显占位、无数据弹「暂无数据」。
templateCombo_ = formkit::comboBox(QStringLiteral("请选择导出模板"), this);
formkit::capField(templateCombo_); formkit::capField(templateCombo_);
fl->addRow(formkit::editLabel(QStringLiteral("导出模板")), templateCombo_); fl->addRow(formkit::editLabel(QStringLiteral("导出模板")), templateCombo_);
cardLay->addLayout(fl); cardLay->addLayout(fl);

View File

@ -11,11 +11,20 @@
#include <utility> #include <utility>
#include "EmptyAwareComboBox.hpp"
#include "Theme.hpp" #include "Theme.hpp"
#include "panels/KeyValueView.hpp" #include "panels/KeyValueView.hpp"
namespace geopro::app::formkit { namespace geopro::app::formkit {
QComboBox* comboBox(const QString& placeholder, QWidget* parent) {
auto* cb = new EmptyAwareComboBox(parent);
// 有占位文案:设占位 + 维持 currentIndex=-1构造已置 -1未选时显灰字占位。
// 无占位文案留空addItem 后自动选首项(保持静态下拉的既有默认选中行为)。
if (!placeholder.isEmpty()) cb->setPlaceholderText(placeholder);
return cb;
}
DetailForm& DetailForm::group(const QString& name) { DetailForm& DetailForm::group(const QString& name) {
geopro::data::DynamicFormGroup g; geopro::data::DynamicFormGroup g;
g.name = name.toStdString(); g.name = name.toStdString();

View File

@ -15,6 +15,7 @@
#include "repo/RepoTypes.hpp" #include "repo/RepoTypes.hpp"
class QBoxLayout; class QBoxLayout;
class QComboBox;
class QDialog; class QDialog;
class QDialogButtonBox; class QDialogButtonBox;
class QFormLayout; class QFormLayout;
@ -23,6 +24,12 @@ class QWidget;
namespace geopro::app::formkit { namespace geopro::app::formkit {
// ── 下拉框:全局建下拉的标准入口(返回空态感知下拉 EmptyAwareComboBox──────────────
// placeholder 非空时设占位文案 + currentIndex=-1未选显灰字占位对齐 Arco ASelect
// placeholder 为空时保持 QComboBox 默认行为addItem 后自动选首项),不强加占位。
// 无真实可选项时点开弹窗会显示一条灰色「暂无数据」(实现于 EmptyAwareComboBox
QComboBox* comboBox(const QString& placeholder = QString(), QWidget* parent = nullptr);
// ── 只读详情:唯一键值模型构建器 ───────────────────────────────────────────── // ── 只读详情:唯一键值模型构建器 ─────────────────────────────────────────────
// 链式 group()/row() 产出 data::DynamicForm喂给唯一的 §6.4 渲染器 DynamicFormView。 // 链式 group()/row() 产出 data::DynamicForm喂给唯一的 §6.4 渲染器 DynamicFormView。
// 三维体/切片/异常等「数据详情」对话框共用,杜绝裸 QFormLayout 漂移。 // 三维体/切片/异常等「数据详情」对话框共用,杜绝裸 QFormLayout 漂移。

View File

@ -53,10 +53,11 @@ ImportDatasetDialog::ImportDatasetDialog(geopro::data::IAsyncProjectRepository&
auto* fl = formkit::makeEditForm(); auto* fl = formkit::makeEditForm();
typeCombo_ = new QComboBox(card); // 空态感知下拉:数据类型/导入脚本均数据驱动(异步加载),未选显占位、无数据弹「暂无数据」。
typeCombo_ = formkit::comboBox(QStringLiteral("请选择数据类型"), card);
formkit::capField(typeCombo_); formkit::capField(typeCombo_);
fl->addRow(formkit::editLabel(QStringLiteral("数据类型")), typeCombo_); fl->addRow(formkit::editLabel(QStringLiteral("数据类型")), typeCombo_);
scriptCombo_ = new QComboBox(card); scriptCombo_ = formkit::comboBox(QStringLiteral("请选择导入脚本"), card);
formkit::capField(scriptCombo_); formkit::capField(scriptCombo_);
fl->addRow(formkit::editLabel(QStringLiteral("导入脚本")), scriptCombo_); fl->addRow(formkit::editLabel(QStringLiteral("导入脚本")), scriptCombo_);

View File

@ -3,6 +3,8 @@
#include <utility> #include <utility>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QJsonDocument> #include <QJsonDocument>
@ -140,7 +142,7 @@ void ObjectFormDialog::buildTopFields() {
// 新建 GS/TM类型下拉数据源 gsList / tmList选择后重载动态表单 // 新建 GS/TM类型下拉数据源 gsList / tmList选择后重载动态表单
const QString label = const QString label =
confType_ == kConfTm ? QStringLiteral("方法类型") : QStringLiteral("对象类型"); confType_ == kConfTm ? QStringLiteral("方法类型") : QStringLiteral("对象类型");
typeCombo_ = new QComboBox(topBox_); typeCombo_ = new EmptyAwareComboBox(topBox_);
addRow(label, typeCombo_); addRow(label, typeCombo_);
QObject::connect(typeCombo_, qOverload<int>(&QComboBox::currentIndexChanged), this, QObject::connect(typeCombo_, qOverload<int>(&QComboBox::currentIndexChanged), this,
[this](int) { [this](int) {

View File

@ -3,6 +3,8 @@
#include <QAbstractItemView> #include <QAbstractItemView>
#include <QColor> #include <QColor>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFont> #include <QFont>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
@ -54,7 +56,7 @@ ProjectListDialog::ProjectListDialog(data::IAsyncProjectRepository& repo, QWidge
filter->addWidget(nameEdit_); filter->addWidget(nameEdit_);
filter->addSpacing(8); filter->addSpacing(8);
filter->addWidget(new QLabel(QStringLiteral("项目类型"), this)); filter->addWidget(new QLabel(QStringLiteral("项目类型"), this));
typeCombo_ = new QComboBox(this); typeCombo_ = new EmptyAwareComboBox(this);
typeCombo_->setFixedWidth(160); typeCombo_->setFixedWidth(160);
filter->addWidget(typeCombo_); filter->addWidget(typeCombo_);
filter->addSpacing(8); filter->addSpacing(8);

View File

@ -1,6 +1,8 @@
#include "SettingsDialog.hpp" #include "SettingsDialog.hpp"
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QCoreApplication> #include <QCoreApplication>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
@ -63,7 +65,7 @@ QWidget* buildAppearancePage() {
geopro::app::formkit::addSection(v, QStringLiteral("外观"), page, false); geopro::app::formkit::addSection(v, QStringLiteral("外观"), page, false);
// 主题:跟随系统 / 浅色 / 深色(热切)。 // 主题:跟随系统 / 浅色 / 深色(热切)。
auto* themeCombo = new QComboBox(page); auto* themeCombo = new EmptyAwareComboBox(page);
themeCombo->addItem(QStringLiteral("跟随系统"), QStringLiteral("system")); themeCombo->addItem(QStringLiteral("跟随系统"), QStringLiteral("system"));
themeCombo->addItem(QStringLiteral("浅色"), QStringLiteral("light")); themeCombo->addItem(QStringLiteral("浅色"), QStringLiteral("light"));
themeCombo->addItem(QStringLiteral("深色"), QStringLiteral("dark")); themeCombo->addItem(QStringLiteral("深色"), QStringLiteral("dark"));
@ -76,7 +78,7 @@ QWidget* buildAppearancePage() {
QStringLiteral("跟随系统 / 浅色 / 深色,切换即时生效"))); QStringLiteral("跟随系统 / 浅色 / 深色,切换即时生效")));
// 界面字号:小/标准/大/特大(重启生效)。 // 界面字号:小/标准/大/特大(重启生效)。
auto* fontCombo = new QComboBox(page); auto* fontCombo = new EmptyAwareComboBox(page);
fontCombo->addItem(QStringLiteral(""), 90); fontCombo->addItem(QStringLiteral(""), 90);
fontCombo->addItem(QStringLiteral("标准"), 100); fontCombo->addItem(QStringLiteral("标准"), 100);
fontCombo->addItem(QStringLiteral(""), 115); fontCombo->addItem(QStringLiteral(""), 115);

View File

@ -1,6 +1,8 @@
#include "VolumeParamsDialog.hpp" #include "VolumeParamsDialog.hpp"
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QFormLayout> #include <QFormLayout>
@ -43,7 +45,7 @@ VolumeParamsDialog::VolumeParamsDialog(int sourceCount, QWidget* parent) : QDial
formkit::capField(name_); formkit::capField(name_);
form->addRow(formkit::editLabel(QStringLiteral("名称")), name_); form->addRow(formkit::editLabel(QStringLiteral("名称")), name_);
model_ = new QComboBox(); model_ = new EmptyAwareComboBox();
model_->addItem(QStringLiteral("反距离加权 (IDW)"), model_->addItem(QStringLiteral("反距离加权 (IDW)"),
static_cast<int>(geopro::data::VolumeBuildParams::Model::Idw)); static_cast<int>(geopro::data::VolumeBuildParams::Model::Idw));
model_->addItem(QStringLiteral("克里金 (Kriging)"), model_->addItem(QStringLiteral("克里金 (Kriging)"),

View File

@ -2,6 +2,8 @@
#include <QColorDialog> #include <QColorDialog>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QPushButton> #include <QPushButton>
#include <QTextCharFormat> #include <QTextCharFormat>
@ -117,7 +119,7 @@ void DescriptionPanel::buildToolbar(QToolBar* tb) {
addAlignBtn(QStringLiteral(""), Qt::AlignJustify); addAlignBtn(QStringLiteral(""), Qt::AlignJustify);
// 标题下拉(正文 / H1~H4——块级作用于当前段。 // 标题下拉(正文 / H1~H4——块级作用于当前段。
auto* headerBox = new QComboBox(tb); auto* headerBox = new EmptyAwareComboBox(tb);
headerBox->addItem(QStringLiteral("正文"), 0); headerBox->addItem(QStringLiteral("正文"), 0);
for (int h = 1; h <= 4; ++h) headerBox->addItem(QStringLiteral("标题%1").arg(h), h); for (int h = 1; h <= 4; ++h) headerBox->addItem(QStringLiteral("标题%1").arg(h), h);
tb->addWidget(headerBox); tb->addWidget(headerBox);
@ -131,7 +133,7 @@ void DescriptionPanel::buildToolbar(QToolBar* tb) {
}); });
// 字号下拉px // 字号下拉px
auto* sizeBox = new QComboBox(tb); auto* sizeBox = new EmptyAwareComboBox(tb);
for (int px : kFontSizesPx) sizeBox->addItem(QStringLiteral("%1px").arg(px), px); for (int px : kFontSizesPx) sizeBox->addItem(QStringLiteral("%1px").arg(px), px);
sizeBox->setCurrentIndex(2); // 默认 16px与原版一致 sizeBox->setCurrentIndex(2); // 默认 16px与原版一致
tb->addWidget(sizeBox); tb->addWidget(sizeBox);
@ -143,7 +145,7 @@ void DescriptionPanel::buildToolbar(QToolBar* tb) {
}); });
// 字体族下拉(对照原版 ql-font // 字体族下拉(对照原版 ql-font
auto* fontBox = new QComboBox(tb); auto* fontBox = new EmptyAwareComboBox(tb);
for (const auto& fo : kFontFamilies) for (const auto& fo : kFontFamilies)
fontBox->addItem(QString::fromUtf8(fo.label), QString::fromUtf8(fo.family)); fontBox->addItem(QString::fromUtf8(fo.label), QString::fromUtf8(fo.family));
tb->addWidget(fontBox); tb->addWidget(fontBox);

View File

@ -2,6 +2,8 @@
#include <QCheckBox> #include <QCheckBox>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDate> #include <QDate>
#include <QDateEdit> #include <QDateEdit>
#include <QDateTime> #include <QDateTime>
@ -101,7 +103,7 @@ QWidget* buildWidget(const data::EditField& f) {
if (ro) le->setEnabled(false); if (ro) le->setEnabled(false);
return le; return le;
} }
auto* cb = new QComboBox(); auto* cb = new EmptyAwareComboBox();
flattenOptions(f.options, cb); flattenOptions(f.options, cb);
const int idx = cb->findData(val); const int idx = cb->findData(val);
if (idx >= 0) cb->setCurrentIndex(idx); if (idx >= 0) cb->setCurrentIndex(idx);

View File

@ -299,7 +299,8 @@ void AutoAnnotationDialog::addRule() {
rc.minPoints->setValue(kDefaultMinPoints); rc.minPoints->setValue(kDefaultMinPoints);
form->addRow(formkit::editLabel(QStringLiteral("最小点数")), rc.minPoints); form->addRow(formkit::editLabel(QStringLiteral("最小点数")), rc.minPoints);
rc.type = new QComboBox(rc.body); // 空态感知下拉异常类型异步加载loadExceptionTypes未选显占位、无数据弹「暂无数据」。
rc.type = formkit::comboBox(QStringLiteral("请选择异常类型"), rc.body);
for (const QJsonValue& ov : exceptionTypeOptions_) { for (const QJsonValue& ov : exceptionTypeOptions_) {
const QJsonObject o = ov.toObject(); const QJsonObject o = ov.toObject();
rc.type->addItem(o.value(QStringLiteral("name")).toString(), rc.type->addItem(o.value(QStringLiteral("name")).toString(),

View File

@ -1,6 +1,8 @@
#include "panels/chart/ExceptionDetailDialog.hpp" #include "panels/chart/ExceptionDetailDialog.hpp"
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFile> #include <QFile>
#include <QFileDialog> #include <QFileDialog>
#include <QFormLayout> #include <QFormLayout>
@ -134,7 +136,7 @@ QWidget* ExceptionDetailDialog::buildCoordTab() {
// 坐标系切换 + 顶点数 + 导出(对照原版坐标信息 tab // 坐标系切换 + 顶点数 + 导出(对照原版坐标信息 tab
auto* topRow = new QHBoxLayout(); auto* topRow = new QHBoxLayout();
topRow->addWidget(new QLabel(QStringLiteral("坐标系:"), tab)); topRow->addWidget(new QLabel(QStringLiteral("坐标系:"), tab));
coordSysCombo_ = new QComboBox(tab); coordSysCombo_ = new EmptyAwareComboBox(tab);
coordSysCombo_->addItem(QStringLiteral("图形坐标"), QStringLiteral("jb")); coordSysCombo_->addItem(QStringLiteral("图形坐标"), QStringLiteral("jb"));
// 条件显示(对照原版 drawerExceptionInfolatLon.length===0 → 仅图形坐标;否则三项)。 // 条件显示(对照原版 drawerExceptionInfolatLon.length===0 → 仅图形坐标;否则三项)。
// 纯展示响应坐标,不做客户端换算;响应未携带经纬度时退化为仅图形坐标,与原版一致。 // 纯展示响应坐标,不做客户端换算;响应未携带经纬度时退化为仅图形坐标,与原版一致。

View File

@ -3,6 +3,8 @@
#include <utility> #include <utility>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
@ -49,7 +51,7 @@ ExceptionDialog::ExceptionDialog(geopro::data::IDatasetCommandRepository* repo,
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
// 标注类型remarkSourceType "1".."4",与原版 annotationType 一致)。 // 标注类型remarkSourceType "1".."4",与原版 annotationType 一致)。
markTypeCombo_ = new QComboBox(this); markTypeCombo_ = new EmptyAwareComboBox(this);
markTypeCombo_->addItem(QStringLiteral(""), QStringLiteral("1")); markTypeCombo_->addItem(QStringLiteral(""), QStringLiteral("1"));
markTypeCombo_->addItem(QStringLiteral("线"), QStringLiteral("2")); markTypeCombo_->addItem(QStringLiteral("线"), QStringLiteral("2"));
markTypeCombo_->addItem(QStringLiteral(""), QStringLiteral("3")); markTypeCombo_->addItem(QStringLiteral(""), QStringLiteral("3"));
@ -58,7 +60,8 @@ ExceptionDialog::ExceptionDialog(geopro::data::IDatasetCommandRepository* repo,
form->addRow(formkit::editLabel(QStringLiteral("标注类型")), markTypeCombo_); form->addRow(formkit::editLabel(QStringLiteral("标注类型")), markTypeCombo_);
// 异常类型行:下拉 + 「新增异常类型」按钮(对照原版 exceptionDialog 同行布局)。 // 异常类型行:下拉 + 「新增异常类型」按钮(对照原版 exceptionDialog 同行布局)。
exceptionTypeCombo_ = new QComboBox(this); // 空态感知下拉异常类型异步加载loadExceptionTypes未选显占位、无数据弹「暂无数据」。
exceptionTypeCombo_ = formkit::comboBox(QStringLiteral("请选择异常类型"), this);
formkit::capField(exceptionTypeCombo_); formkit::capField(exceptionTypeCombo_);
addTypeBtn_ = new QPushButton(QStringLiteral("新增异常类型"), this); addTypeBtn_ = new QPushButton(QStringLiteral("新增异常类型"), this);
auto* typeRow = new QWidget(this); auto* typeRow = new QWidget(this);

View File

@ -2,6 +2,8 @@
#include <QColorDialog> #include <QColorDialog>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
@ -29,7 +31,7 @@ ExceptionTextDialog::ExceptionTextDialog(QWidget* parent)
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
// 字体(对照原版 1宋体/2微软雅黑/3黑体/4楷体值为字符串 int // 字体(对照原版 1宋体/2微软雅黑/3黑体/4楷体值为字符串 int
fontCombo_ = new QComboBox(this); fontCombo_ = new EmptyAwareComboBox(this);
fontCombo_->addItem(QStringLiteral("宋体"), QStringLiteral("1")); fontCombo_->addItem(QStringLiteral("宋体"), QStringLiteral("1"));
fontCombo_->addItem(QStringLiteral("微软雅黑"), QStringLiteral("2")); fontCombo_->addItem(QStringLiteral("微软雅黑"), QStringLiteral("2"));
fontCombo_->addItem(QStringLiteral("黑体"), QStringLiteral("3")); fontCombo_->addItem(QStringLiteral("黑体"), QStringLiteral("3"));

View File

@ -5,6 +5,8 @@
#include <QButtonGroup> #include <QButtonGroup>
#include <QColorDialog> #include <QColorDialog>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QFormLayout> #include <QFormLayout>
#include <QGroupBox> #include <QGroupBox>
@ -170,7 +172,7 @@ void ExceptionTypeDialog::pickColor(QPushButton* swatch, QColor& target) {
QGroupBox* ExceptionTypeDialog::buildPointLegend() { QGroupBox* ExceptionTypeDialog::buildPointLegend() {
auto* box = new QGroupBox(QStringLiteral(""), this); auto* box = new QGroupBox(QStringLiteral(""), this);
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
pointShape_ = new QComboBox(box); pointShape_ = new EmptyAwareComboBox(box);
fillCombo(pointShape_, kPointShapes, QStringLiteral("circle")); fillCombo(pointShape_, kPointShapes, QStringLiteral("circle"));
form->addRow(formkit::editLabel(QStringLiteral("形状:")), pointShape_); form->addRow(formkit::editLabel(QStringLiteral("形状:")), pointShape_);
pointSize_ = new QSpinBox(box); pointSize_ = new QSpinBox(box);
@ -188,7 +190,7 @@ QGroupBox* ExceptionTypeDialog::buildPointLegend() {
QGroupBox* ExceptionTypeDialog::buildPolylineLegend() { QGroupBox* ExceptionTypeDialog::buildPolylineLegend() {
auto* box = new QGroupBox(QStringLiteral("多段线"), this); auto* box = new QGroupBox(QStringLiteral("多段线"), this);
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
polylineShape_ = new QComboBox(box); polylineShape_ = new EmptyAwareComboBox(box);
fillCombo(polylineShape_, kLineShapes, QStringLiteral("solid")); fillCombo(polylineShape_, kLineShapes, QStringLiteral("solid"));
form->addRow(formkit::editLabel(QStringLiteral("线形:")), polylineShape_); form->addRow(formkit::editLabel(QStringLiteral("线形:")), polylineShape_);
polylineWidth_ = new QSpinBox(box); polylineWidth_ = new QSpinBox(box);
@ -206,7 +208,7 @@ QGroupBox* ExceptionTypeDialog::buildPolylineLegend() {
QGroupBox* ExceptionTypeDialog::buildPolygonLegend() { QGroupBox* ExceptionTypeDialog::buildPolygonLegend() {
auto* box = new QGroupBox(QStringLiteral("多边形"), this); auto* box = new QGroupBox(QStringLiteral("多边形"), this);
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
polygonFill_ = new QComboBox(box); polygonFill_ = new EmptyAwareComboBox(box);
fillCombo(polygonFill_, kSurfaceFills, QString()); // 默认 '' = 颜色填充 fillCombo(polygonFill_, kSurfaceFills, QString()); // 默认 '' = 颜色填充
form->addRow(formkit::editLabel(QStringLiteral("填充图例:")), polygonFill_); form->addRow(formkit::editLabel(QStringLiteral("填充图例:")), polygonFill_);
polygonFillColorBtn_ = makeColorSwatch(polygonFillColor_); polygonFillColorBtn_ = makeColorSwatch(polygonFillColor_);
@ -220,7 +222,7 @@ QGroupBox* ExceptionTypeDialog::buildPolygonLegend() {
QGroupBox* ExceptionTypeDialog::buildTextLegend() { QGroupBox* ExceptionTypeDialog::buildTextLegend() {
auto* box = new QGroupBox(QStringLiteral("文字"), this); auto* box = new QGroupBox(QStringLiteral("文字"), this);
auto* form = formkit::makeEditForm(); auto* form = formkit::makeEditForm();
textFont_ = new QComboBox(box); textFont_ = new EmptyAwareComboBox(box);
fillCombo(textFont_, kTextFonts, QStringLiteral("1")); // 默认 1=宋体 fillCombo(textFont_, kTextFonts, QStringLiteral("1")); // 默认 1=宋体
form->addRow(formkit::editLabel(QStringLiteral("字体:")), textFont_); form->addRow(formkit::editLabel(QStringLiteral("字体:")), textFont_);
textSize_ = new QSpinBox(box); textSize_ = new QSpinBox(box);

View File

@ -3,6 +3,8 @@
#include <utility> #include <utility>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QFrame> #include <QFrame>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
@ -159,14 +161,14 @@ void FilterDialog::buildRight(QHBoxLayout* body) {
// 滤波设置分组。 // 滤波设置分组。
addSpecTitle(rightLay, QStringLiteral("滤波设置"), card); addSpecTitle(rightLay, QStringLiteral("滤波设置"), card);
dataEdge_ = new QComboBox(card); dataEdge_ = new EmptyAwareComboBox(card);
dataEdge_->addItem(QStringLiteral("设置为无效点"), QStringLiteral("whitening")); dataEdge_->addItem(QStringLiteral("设置为无效点"), QStringLiteral("whitening"));
dataEdge_->addItem(QStringLiteral("忽略"), QStringLiteral("skip")); dataEdge_->addItem(QStringLiteral("忽略"), QStringLiteral("skip"));
dataEdge_->addItem(QStringLiteral("复制边缘点"), QStringLiteral("edgePoint")); dataEdge_->addItem(QStringLiteral("复制边缘点"), QStringLiteral("edgePoint"));
dataEdge_->addItem(QStringLiteral("填充"), QStringLiteral("filling")); dataEdge_->addItem(QStringLiteral("填充"), QStringLiteral("filling"));
dataEdgeValue_ = new QLineEdit(card); dataEdgeValue_ = new QLineEdit(card);
dataEdgeValue_->setEnabled(false); dataEdgeValue_->setEnabled(false);
noDataPoints_ = new QComboBox(card); noDataPoints_ = new EmptyAwareComboBox(card);
noDataPoints_->addItem(QStringLiteral("扩展"), QStringLiteral("expansion")); noDataPoints_->addItem(QStringLiteral("扩展"), QStringLiteral("expansion"));
noDataPoints_->addItem(QStringLiteral("保留"), QStringLiteral("retain")); noDataPoints_->addItem(QStringLiteral("保留"), QStringLiteral("retain"));
noDataPoints_->addItem(QStringLiteral("忽略"), QStringLiteral("skip")); // 原版 skip → 忽略 noDataPoints_->addItem(QStringLiteral("忽略"), QStringLiteral("skip")); // 原版 skip → 忽略

View File

@ -4,6 +4,8 @@
#include <utility> #include <utility>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QFrame> #include <QFrame>
#include <QGridLayout> #include <QGridLayout>
@ -158,7 +160,7 @@ void GridWizardDialog::buildStep2() {
// 分组 2数据值设置数据值max/min + 恢复默认值 + 数据值保存为)。 // 分组 2数据值设置数据值max/min + 恢复默认值 + 数据值保存为)。
addSectionTitle(p2Lay, QStringLiteral("数据值设置"), page2); addSectionTitle(p2Lay, QStringLiteral("数据值设置"), page2);
saveFormat_ = new QComboBox(page2); saveFormat_ = new EmptyAwareComboBox(page2);
saveFormat_->addItem(QStringLiteral("线性"), QStringLiteral("linear")); saveFormat_->addItem(QStringLiteral("线性"), QStringLiteral("linear"));
saveFormat_->addItem(QStringLiteral("对数"), QStringLiteral("log")); saveFormat_->addItem(QStringLiteral("对数"), QStringLiteral("log"));
saveFormat_->setFixedWidth(120); saveFormat_->setFixedWidth(120);

View File

@ -39,7 +39,10 @@ InversionFormDialog::InversionFormDialog(Mode mode, geopro::data::IDatasetComman
// 模型选择行label + 下拉)。生成视电阻率下拉禁用(复刻原版 disabled // 模型选择行label + 下拉)。生成视电阻率下拉禁用(复刻原版 disabled
auto* modelLay = new QVBoxLayout(); auto* modelLay = new QVBoxLayout();
modelLay->addWidget(formkit::editLabel(QStringLiteral("反演模型"), this)); modelLay->addWidget(formkit::editLabel(QStringLiteral("反演模型"), this));
modelCombo_ = new QComboBox(this); // 空态感知下拉反演模型异步加载listInversionScripts。反演运算模式占位「请选择反演模型」
// (替代旧的空首项 allow-clear hack未选显占位、无脚本弹「暂无数据」生成视电阻率模式
// 禁用并由 loadScripts 显式选中,占位不影响其默认选中。
modelCombo_ = formkit::comboBox(QStringLiteral("请选择反演模型"), this);
if (mode_ == Mode::ApparentResistivity) modelCombo_->setEnabled(false); if (mode_ == Mode::ApparentResistivity) modelCombo_->setEnabled(false);
modelLay->addWidget(modelCombo_); modelLay->addWidget(modelCombo_);
root->addLayout(modelLay); root->addLayout(modelLay);
@ -81,8 +84,7 @@ void InversionFormDialog::loadScripts() {
if (!ok) return; if (!ok) return;
QSignalBlocker block(self->modelCombo_); // 填充期不触发 onModelChanged QSignalBlocker block(self->modelCombo_); // 填充期不触发 onModelChanged
self->modelCombo_->clear(); self->modelCombo_->clear();
// 反演运算:首项为空(对应原版 allow-clear无默认选中 // 反演运算:不再插空首项——占位文案 + currentIndex=-1 即「无默认选中」(对应原版 allow-clear
if (mode == Mode::Inversion) self->modelCombo_->addItem(QString(), QString());
int defaultIdx = -1; int defaultIdx = -1;
for (const QJsonValue& v : list) { for (const QJsonValue& v : list) {
const QJsonObject o = v.toObject(); const QJsonObject o = v.toObject();

View File

@ -17,6 +17,8 @@
#include <QByteArray> #include <QByteArray>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QCursor> #include <QCursor>
#include <QEvent> #include <QEvent>
#include <QFileDialog> #include <QFileDialog>
@ -78,7 +80,7 @@ RawDataChartView::RawDataChartView(QWidget* parent) : QWidget(parent) {
auto* lblCurrentChart = new QLabel(QStringLiteral("当前图形:"), toolbar); auto* lblCurrentChart = new QLabel(QStringLiteral("当前图形:"), toolbar);
chartTypeCombo_ = new QComboBox(toolbar); chartTypeCombo_ = new EmptyAwareComboBox(toolbar);
chartTypeCombo_->addItem(QStringLiteral("散点图")); chartTypeCombo_->addItem(QStringLiteral("散点图"));
auto* btnSaveAs = new QToolButton(toolbar); auto* btnSaveAs = new QToolButton(toolbar);
@ -822,16 +824,16 @@ void RawDataChartView::buildMeasurementToolbar(const geopro::core::ScatterToolba
// x / y 下拉本地换列重绘v 下拉:重新请求散点+色阶M6值类型下拉本地变换M7 // x / y 下拉本地换列重绘v 下拉:重新请求散点+色阶M6值类型下拉本地变换M7
// 各下拉固定宽度对照原版 datasetTool.vueX=120/Y=160/V=160/值类型=120 // 各下拉固定宽度对照原版 datasetTool.vueX=120/Y=160/V=160/值类型=120
xCombo_ = new QComboBox(toolbar); xCombo_ = new EmptyAwareComboBox(toolbar);
xCombo_->setFixedWidth(kComboW_X); xCombo_->setFixedWidth(kComboW_X);
fillCombo(xCombo_, conf.x, conf.defaultX, QString()); fillCombo(xCombo_, conf.x, conf.defaultX, QString());
yCombo_ = new QComboBox(toolbar); yCombo_ = new EmptyAwareComboBox(toolbar);
yCombo_->setFixedWidth(kComboW_Y); yCombo_->setFixedWidth(kComboW_Y);
fillCombo(yCombo_, conf.y, conf.defaultY, QString()); fillCombo(yCombo_, conf.y, conf.defaultY, QString());
vCombo_ = new QComboBox(toolbar); vCombo_ = new EmptyAwareComboBox(toolbar);
vCombo_->setFixedWidth(kComboW_V); vCombo_->setFixedWidth(kComboW_V);
fillCombo(vCombo_, conf.v, conf.defaultV, QString()); fillCombo(vCombo_, conf.v, conf.defaultV, QString());
valueTypeCombo_ = new QComboBox(toolbar); valueTypeCombo_ = new EmptyAwareComboBox(toolbar);
valueTypeCombo_->setFixedWidth(kComboW_ValueType); valueTypeCombo_->setFixedWidth(kComboW_ValueType);
// 值类型固定三项(原版 linearity/inverse/logarithm本地变换无后端。 // 值类型固定三项(原版 linearity/inverse/logarithm本地变换无后端。
valueTypeCombo_->addItem(QStringLiteral("线性"), QStringLiteral("linearity")); valueTypeCombo_->addItem(QStringLiteral("线性"), QStringLiteral("linearity"));

View File

@ -3,6 +3,8 @@
#include <algorithm> #include <algorithm>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QIntValidator> #include <QIntValidator>
#include <QLabel> #include <QLabel>
@ -90,7 +92,7 @@ TablePager::TablePager(QWidget* parent) : QWidget(parent) {
lay->addWidget(new QLabel(QStringLiteral(""), this)); lay->addWidget(new QLabel(QStringLiteral(""), this));
sizeCombo_ = new QComboBox(this); sizeCombo_ = new EmptyAwareComboBox(this);
for (int s : kPageSizes) for (int s : kPageSizes)
sizeCombo_->addItem(QStringLiteral("%1条/页").arg(s), s); sizeCombo_->addItem(QStringLiteral("%1条/页").arg(s), s);
connect(sizeCombo_, &QComboBox::activated, this, [this](int i) { connect(sizeCombo_, &QComboBox::activated, this, [this](int i) {

View File

@ -4,6 +4,8 @@
#include <QButtonGroup> #include <QButtonGroup>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
@ -14,6 +16,7 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "FormKit.hpp" // formkit::comboBox空态感知下拉
#include "Theme.hpp" #include "Theme.hpp"
#include "panels/chart/InversionProcessOps.hpp" // buildWhitenBody #include "panels/chart/InversionProcessOps.hpp" // buildWhitenBody
#include "repo/IDatasetCommandRepository.hpp" #include "repo/IDatasetCommandRepository.hpp"
@ -61,7 +64,7 @@ WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo,
root->setSpacing(geopro::app::space::kMd); root->setSpacing(geopro::app::space::kMd);
// 白化方式下拉(原版 3 项,数值对照 whiteningMethod 1/2/3 // 白化方式下拉(原版 3 项,数值对照 whiteningMethod 1/2/3
methodCombo_ = new QComboBox(this); methodCombo_ = new EmptyAwareComboBox(this);
methodCombo_->addItem(QStringLiteral("数据边界自动白化"), 1); methodCombo_->addItem(QStringLiteral("数据边界自动白化"), 1);
methodCombo_->addItem(QStringLiteral("白化文件"), 2); methodCombo_->addItem(QStringLiteral("白化文件"), 2);
methodCombo_->addItem(QStringLiteral("模型白化"), 3); methodCombo_->addItem(QStringLiteral("模型白化"), 3);
@ -96,7 +99,8 @@ WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo,
auto* page2 = new QWidget(this); auto* page2 = new QWidget(this);
auto* p2 = new QVBoxLayout(page2); auto* p2 = new QVBoxLayout(page2);
p2->setContentsMargins(0, 0, 0, 0); p2->setContentsMargins(0, 0, 0, 0);
fileCombo_ = new QComboBox(page2); // 空态感知下拉白化文件异步加载listWhitenedData未选显占位、无文件弹「暂无数据」。
fileCombo_ = formkit::comboBox(QStringLiteral("请选择白化文件"), page2);
p2->addLayout(optionRow(QStringLiteral("选择白化文件"), fileCombo_, page2)); p2->addLayout(optionRow(QStringLiteral("选择白化文件"), fileCombo_, page2));
stack_->addWidget(page2); stack_->addWidget(page2);

View File

@ -1,6 +1,8 @@
#include "panels/columns/Column2DDataset.hpp" #include "panels/columns/Column2DDataset.hpp"
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
@ -23,7 +25,7 @@ Column2DDataset::Column2DDataset(QWidget* parent) : QWidget(parent) {
// 地图 // 地图
{ {
auto* form = new QFormLayout(); auto* form = new QFormLayout();
auto* basemap = new QComboBox(); auto* basemap = new EmptyAwareComboBox();
basemap->addItem(QStringLiteral("天地图")); basemap->addItem(QStringLiteral("天地图"));
basemap->addItem(QStringLiteral("Google Map")); basemap->addItem(QStringLiteral("Google Map"));
basemap->addItem(QStringLiteral("隐藏")); basemap->addItem(QStringLiteral("隐藏"));
@ -38,7 +40,7 @@ Column2DDataset::Column2DDataset(QWidget* parent) : QWidget(parent) {
// 2D视图 // 2D视图
{ {
auto* form = new QFormLayout(); auto* form = new QFormLayout();
auto* view2d = new QComboBox(); auto* view2d = new EmptyAwareComboBox();
view2d->addItem(QStringLiteral("关闭")); view2d->addItem(QStringLiteral("关闭"));
view2d->addItem(QStringLiteral("Z=0")); view2d->addItem(QStringLiteral("Z=0"));
view2d->addItem(QStringLiteral("顶部")); view2d->addItem(QStringLiteral("顶部"));

View File

@ -1,6 +1,8 @@
#include "panels/columns/Column3DAnalysis.hpp" #include "panels/columns/Column3DAnalysis.hpp"
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QGroupBox> #include <QGroupBox>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
@ -76,7 +78,7 @@ Column3DAnalysis::Column3DAnalysis(QWidget* parent) : QWidget(parent) {
{ {
auto* fr = new QHBoxLayout(); auto* fr = new QHBoxLayout();
fr->addWidget(new QLabel(QStringLiteral("显示"))); fr->addWidget(new QLabel(QStringLiteral("显示")));
anomalyFilter_ = new QComboBox(); anomalyFilter_ = new EmptyAwareComboBox();
anomalyFilter_->addItem(QStringLiteral("全部显示")); // 0 anomalyFilter_->addItem(QStringLiteral("全部显示")); // 0
anomalyFilter_->addItem(QStringLiteral("随GS")); // 1 anomalyFilter_->addItem(QStringLiteral("随GS")); // 1
anomalyFilter_->addItem(QStringLiteral("随数据集")); // 2 anomalyFilter_->addItem(QStringLiteral("随数据集")); // 2

View File

@ -5,6 +5,8 @@
#include <QAbstractItemView> #include <QAbstractItemView>
#include <QAction> #include <QAction>
#include <QComboBox> #include <QComboBox>
#include "EmptyAwareComboBox.hpp"
#include <QDebug> #include <QDebug>
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
@ -36,7 +38,7 @@ Column3DDataset::Column3DDataset(QWidget* parent) : QWidget(parent) {
// 坐标轴设置 // 坐标轴设置
{ {
auto* form = new QFormLayout(); auto* form = new QFormLayout();
auto* mode = new QComboBox(); auto* mode = new EmptyAwareComboBox();
mode->addItem(QStringLiteral("标准"), static_cast<int>(AxesMode::Standard)); mode->addItem(QStringLiteral("标准"), static_cast<int>(AxesMode::Standard));
mode->addItem(QStringLiteral("三维立体"), static_cast<int>(AxesMode::Stereo)); mode->addItem(QStringLiteral("三维立体"), static_cast<int>(AxesMode::Stereo));
mode->addItem(QStringLiteral("不显示"), static_cast<int>(AxesMode::None)); mode->addItem(QStringLiteral("不显示"), static_cast<int>(AxesMode::None));
@ -44,7 +46,7 @@ Column3DDataset::Column3DDataset(QWidget* parent) : QWidget(parent) {
[this, mode](int) { emit axesModeChanged(static_cast<AxesMode>(mode->currentData().toInt())); }); [this, mode](int) { emit axesModeChanged(static_cast<AxesMode>(mode->currentData().toInt())); });
auto* oPoint = new QPushButton(QStringLiteral("设置…")); auto* oPoint = new QPushButton(QStringLiteral("设置…"));
connect(oPoint, &QPushButton::clicked, this, &Column3DDataset::oPointClicked); connect(oPoint, &QPushButton::clicked, this, &Column3DDataset::oPointClicked);
auto* unit = new QComboBox(); auto* unit = new EmptyAwareComboBox();
unit->addItem(QStringLiteral("无刻度"), static_cast<int>(AxesUnit::None)); unit->addItem(QStringLiteral("无刻度"), static_cast<int>(AxesUnit::None));
unit->addItem(QStringLiteral(""), static_cast<int>(AxesUnit::Meter)); unit->addItem(QStringLiteral(""), static_cast<int>(AxesUnit::Meter));
unit->addItem(QStringLiteral("英尺"), static_cast<int>(AxesUnit::Feet)); unit->addItem(QStringLiteral("英尺"), static_cast<int>(AxesUnit::Feet));