fix(detail): inversion 处理类对话框视觉返工对齐原版(白化/网格化/滤波/另存)
之前用客户端 FormKit 外壳导致与原版 web modal 系统性不一致,以原版为准返工: - 白化:550px、第2项"白化文件"、边界扩展改文本框、确认/取消顺序、标签右对齐 - 网格化:步1 500/步2 800px、网格参数/数据值设置双分组栅格、"数据值保存为"、 补恢复默认值按钮 + 间距↔点数双向联动 + 分项校验 - 滤波:900px 左树右设置双卡片、"忽略"、矩阵行列表头 + 奇偶校验 - 另存为(Inversion):标题"另存为新的网格数据"、400px、默认名"网格数据1"、确认/取消 - 工具条:异常标注/自动标注/另存为、原数据另存为 右对齐 API 端点/请求体字段未动(已 1:1)。build all + test 324/324 绿。
This commit is contained in:
parent
cc3c5bf755
commit
4a1fecb149
|
|
@ -3,7 +3,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QFormLayout>
|
#include <QFrame>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
|
@ -20,16 +20,17 @@
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "FormKit.hpp"
|
#include "Theme.hpp"
|
||||||
#include "panels/chart/InversionProcessOps.hpp" // buildFilterApplyBody / buildNewFilterBody
|
#include "panels/chart/InversionProcessOps.hpp" // buildFilterApplyBody / buildNewFilterBody
|
||||||
#include "repo/IDatasetCommandRepository.hpp"
|
#include "repo/IDatasetCommandRepository.hpp"
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr double kFillRange = 1e9;
|
constexpr int kDialogW = 900; // 原版弹窗宽 900px
|
||||||
constexpr int kMatrixMin = 1, kMatrixMax = 21; // 矩阵行列范围(对照原版 1~21)
|
constexpr int kMatrixMin = 1, kMatrixMax = 21; // 矩阵行列范围(对照原版 1~21)
|
||||||
constexpr int kDefaultDim = 3;
|
constexpr int kDefaultDim = 3;
|
||||||
|
constexpr int kSettingLabelW = 80; // 原版 .setting-label width:80px
|
||||||
const char kDefaultCustomKey[] = "default-custom-filter"; // 默认自定义滤波器(不可删)
|
const char kDefaultCustomKey[] = "default-custom-filter"; // 默认自定义滤波器(不可删)
|
||||||
const char kCustomGroupName[] = "自定义滤波器";
|
const char kCustomGroupName[] = "自定义滤波器";
|
||||||
|
|
||||||
|
|
@ -40,86 +41,58 @@ double cellValue(const QTableWidgetItem* it) {
|
||||||
const double v = it->text().toDouble(&ok);
|
const double v = it->text().toDouble(&ok);
|
||||||
return ok ? v : 0.0;
|
return ok ? v : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 原版分组小标题(14px 半粗 + 标题下 1px divider)。
|
||||||
|
void addSpecTitle(QVBoxLayout* into, const QString& title, QWidget* parent) {
|
||||||
|
auto* lbl = new QLabel(title, parent);
|
||||||
|
auto f = lbl->font();
|
||||||
|
f.setBold(true);
|
||||||
|
lbl->setFont(f);
|
||||||
|
into->addWidget(lbl);
|
||||||
|
auto* line = new QFrame(parent);
|
||||||
|
line->setFrameShape(QFrame::HLine);
|
||||||
|
line->setFrameShadow(QFrame::Plain);
|
||||||
|
into->addWidget(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原版带边框卡片(1px 边框 + 圆角 + 内距)。
|
||||||
|
QFrame* cardFrame(QWidget* parent) {
|
||||||
|
auto* card = new QFrame(parent);
|
||||||
|
card->setFrameShape(QFrame::StyledPanel);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FilterDialog::FilterDialog(geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
FilterDialog::FilterDialog(geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
||||||
QString projectId, QWidget* parent)
|
QString projectId, QWidget* parent)
|
||||||
: QDialog(parent), repo_(repo), dsId_(std::move(dsId)), projectId_(std::move(projectId)) {
|
: QDialog(parent), repo_(repo), dsId_(std::move(dsId)), projectId_(std::move(projectId)) {
|
||||||
setWindowTitle(QStringLiteral("滤波处理"));
|
setWindowTitle(QStringLiteral("滤波设置")); // 原版 filterSetting
|
||||||
setModal(true);
|
setModal(true);
|
||||||
resize(820, 520);
|
setFixedWidth(kDialogW);
|
||||||
|
|
||||||
auto* root = formkit::dialogRoot(this);
|
auto* root = new QVBoxLayout(this);
|
||||||
|
root->setContentsMargins(geopro::app::space::kLg, geopro::app::space::kLg,
|
||||||
|
geopro::app::space::kLg, geopro::app::space::kLg);
|
||||||
|
root->setSpacing(geopro::app::space::kMd);
|
||||||
auto* body = new QHBoxLayout();
|
auto* body = new QHBoxLayout();
|
||||||
|
body->setSpacing(geopro::app::space::kLg);
|
||||||
root->addLayout(body, 1);
|
root->addLayout(body, 1);
|
||||||
|
|
||||||
// ── 左:滤波器树 + 增删按钮 ─────────────────────────────────────────
|
buildLeft(body);
|
||||||
auto* leftLay = new QVBoxLayout();
|
buildRight(body);
|
||||||
tree_ = new QTreeWidget(this);
|
|
||||||
tree_->setHeaderHidden(true);
|
|
||||||
leftLay->addWidget(tree_, 1);
|
|
||||||
auto* treeBtnLay = new QHBoxLayout();
|
|
||||||
auto* addBtn = new QPushButton(QStringLiteral("另存为"), this);
|
|
||||||
auto* delBtn = new QPushButton(QStringLiteral("删除"), this);
|
|
||||||
treeBtnLay->addWidget(addBtn);
|
|
||||||
treeBtnLay->addWidget(delBtn);
|
|
||||||
leftLay->addLayout(treeBtnLay);
|
|
||||||
body->addLayout(leftLay, 1);
|
|
||||||
|
|
||||||
// ── 右:配置面板 ────────────────────────────────────────────────────
|
// 底部按钮(原版三按钮各 ~30%:保存设置(主,左)/确认(主,中)/取消(右))。
|
||||||
auto* rightLay = new QVBoxLayout();
|
|
||||||
auto* form = formkit::makeEditForm();
|
|
||||||
dataEdge_ = new QComboBox(this);
|
|
||||||
dataEdge_->addItem(QStringLiteral("设为无效点"), QStringLiteral("whitening"));
|
|
||||||
dataEdge_->addItem(QStringLiteral("忽略"), QStringLiteral("skip"));
|
|
||||||
dataEdge_->addItem(QStringLiteral("复制边缘点"), QStringLiteral("edgePoint"));
|
|
||||||
dataEdge_->addItem(QStringLiteral("填充"), QStringLiteral("filling"));
|
|
||||||
dataEdgeValue_ = new QLineEdit(this);
|
|
||||||
dataEdgeValue_->setEnabled(false);
|
|
||||||
noDataPoints_ = new QComboBox(this);
|
|
||||||
noDataPoints_->addItem(QStringLiteral("扩展"), QStringLiteral("expansion"));
|
|
||||||
noDataPoints_->addItem(QStringLiteral("保留"), QStringLiteral("retain"));
|
|
||||||
noDataPoints_->addItem(QStringLiteral("跳过"), QStringLiteral("skip"));
|
|
||||||
noDataPoints_->addItem(QStringLiteral("填充"), QStringLiteral("filling"));
|
|
||||||
noDataPoints_->setCurrentIndex(3); // 默认填充(对照原版)
|
|
||||||
noDataValue_ = new QLineEdit(this);
|
|
||||||
filterTimes_ = new QSpinBox(this);
|
|
||||||
filterTimes_->setRange(1, 10);
|
|
||||||
rows_ = new QSpinBox(this);
|
|
||||||
rows_->setRange(kMatrixMin, kMatrixMax);
|
|
||||||
rows_->setValue(kDefaultDim);
|
|
||||||
cols_ = new QSpinBox(this);
|
|
||||||
cols_->setRange(kMatrixMin, kMatrixMax);
|
|
||||||
cols_->setValue(kDefaultDim);
|
|
||||||
formkit::capField(dataEdge_);
|
|
||||||
formkit::capField(dataEdgeValue_);
|
|
||||||
formkit::capField(noDataPoints_);
|
|
||||||
formkit::capField(noDataValue_);
|
|
||||||
formkit::capField(filterTimes_);
|
|
||||||
formkit::capField(rows_);
|
|
||||||
formkit::capField(cols_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("数据边缘:")), dataEdge_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("数据边缘值:")), dataEdgeValue_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("无数据点:")), noDataPoints_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("无数据点值:")), noDataValue_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("滤波次数:")), filterTimes_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("行:")), rows_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("列:")), cols_);
|
|
||||||
rightLay->addLayout(form);
|
|
||||||
matrix_ = new QTableWidget(kDefaultDim, kDefaultDim, this);
|
|
||||||
matrix_->horizontalHeader()->setVisible(false);
|
|
||||||
matrix_->verticalHeader()->setVisible(false);
|
|
||||||
rightLay->addWidget(matrix_, 1);
|
|
||||||
body->addLayout(rightLay, 2);
|
|
||||||
|
|
||||||
// 底部按钮。
|
|
||||||
auto* btnLay = new QHBoxLayout();
|
auto* btnLay = new QHBoxLayout();
|
||||||
btnLay->addStretch();
|
btnLay->setSpacing(geopro::app::space::kMd);
|
||||||
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
auto* saveSettingBtn = new QPushButton(QStringLiteral("保存设置"), this);
|
||||||
okBtn_ = new QPushButton(QStringLiteral("应用"), this);
|
okBtn_ = new QPushButton(QStringLiteral("确认"), this);
|
||||||
okBtn_->setDefault(true);
|
okBtn_->setDefault(true);
|
||||||
btnLay->addWidget(cancelBtn);
|
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
||||||
btnLay->addWidget(okBtn_);
|
btnLay->addWidget(saveSettingBtn, 30);
|
||||||
|
btnLay->addStretch(2);
|
||||||
|
btnLay->addWidget(okBtn_, 30);
|
||||||
|
btnLay->addStretch(2);
|
||||||
|
btnLay->addWidget(cancelBtn, 30);
|
||||||
root->addLayout(btnLay);
|
root->addLayout(btnLay);
|
||||||
|
|
||||||
resizeMatrix(); // 默认 3x3 中心 1
|
resizeMatrix(); // 默认 3x3 中心 1
|
||||||
|
|
@ -127,14 +100,16 @@ FilterDialog::FilterDialog(geopro::data::IDatasetCommandRepository* repo, QStrin
|
||||||
|
|
||||||
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
||||||
connect(okBtn_, &QPushButton::clicked, this, &FilterDialog::onConfirm);
|
connect(okBtn_, &QPushButton::clicked, this, &FilterDialog::onConfirm);
|
||||||
connect(addBtn, &QPushButton::clicked, this, &FilterDialog::saveCustomFilter);
|
connect(saveSettingBtn, &QPushButton::clicked, this, &FilterDialog::saveCustomFilter);
|
||||||
connect(delBtn, &QPushButton::clicked, this, &FilterDialog::deleteSelectedFilter);
|
|
||||||
connect(tree_, &QTreeWidget::itemSelectionChanged, this,
|
connect(tree_, &QTreeWidget::itemSelectionChanged, this,
|
||||||
&FilterDialog::onTreeSelectionChanged);
|
&FilterDialog::onTreeSelectionChanged);
|
||||||
|
// 行/列:仅奇数允许,偶数弹警告并回退旧值(对照原版 watch rows/cols)。
|
||||||
|
prevRows_ = kDefaultDim;
|
||||||
|
prevCols_ = kDefaultDim;
|
||||||
connect(rows_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
connect(rows_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||||
[this](int) { resizeMatrix(); });
|
[this](int v) { onDimChanged(rows_, v, prevRows_, QStringLiteral("行")); });
|
||||||
connect(cols_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
connect(cols_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||||
[this](int) { resizeMatrix(); });
|
[this](int v) { onDimChanged(cols_, v, prevCols_, QStringLiteral("列")); });
|
||||||
// 数据边缘/无数据点:仅「填充」启用对应值输入框(对照原版 v-if=filling)。
|
// 数据边缘/无数据点:仅「填充」启用对应值输入框(对照原版 v-if=filling)。
|
||||||
connect(dataEdge_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int) {
|
connect(dataEdge_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int) {
|
||||||
dataEdgeValue_->setEnabled(dataEdge_->currentData().toString() ==
|
dataEdgeValue_->setEnabled(dataEdge_->currentData().toString() ==
|
||||||
|
|
@ -149,6 +124,125 @@ FilterDialog::FilterDialog(geopro::data::IDatasetCommandRepository* repo, QStrin
|
||||||
loadFilters();
|
loadFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FilterDialog::buildLeft(QHBoxLayout* body) {
|
||||||
|
auto* card = cardFrame(this);
|
||||||
|
card->setMinimumWidth(270); // 原版左卡片 min-width:270px
|
||||||
|
auto* leftLay = new QVBoxLayout(card);
|
||||||
|
leftLay->setContentsMargins(geopro::app::space::kLg, geopro::app::space::kLg,
|
||||||
|
geopro::app::space::kLg, geopro::app::space::kLg);
|
||||||
|
auto* title = new QLabel(QStringLiteral("滤波方式:"), card); // 原版 filterType:
|
||||||
|
auto tf = title->font();
|
||||||
|
tf.setBold(true);
|
||||||
|
title->setFont(tf);
|
||||||
|
leftLay->addWidget(title);
|
||||||
|
tree_ = new QTreeWidget(card);
|
||||||
|
tree_->setHeaderHidden(true);
|
||||||
|
leftLay->addWidget(tree_, 1);
|
||||||
|
auto* treeBtnLay = new QHBoxLayout();
|
||||||
|
auto* addBtn = new QPushButton(QStringLiteral("另存为"), card);
|
||||||
|
auto* delBtn = new QPushButton(QStringLiteral("删除"), card);
|
||||||
|
treeBtnLay->addWidget(addBtn);
|
||||||
|
treeBtnLay->addWidget(delBtn);
|
||||||
|
leftLay->addLayout(treeBtnLay);
|
||||||
|
body->addWidget(card, 3); // 左 ~30%
|
||||||
|
|
||||||
|
connect(addBtn, &QPushButton::clicked, this, &FilterDialog::saveCustomFilter);
|
||||||
|
connect(delBtn, &QPushButton::clicked, this, &FilterDialog::deleteSelectedFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterDialog::buildRight(QHBoxLayout* body) {
|
||||||
|
auto* card = cardFrame(this);
|
||||||
|
auto* rightLay = new QVBoxLayout(card);
|
||||||
|
rightLay->setContentsMargins(geopro::app::space::kLg, geopro::app::space::kLg,
|
||||||
|
geopro::app::space::kLg, geopro::app::space::kLg);
|
||||||
|
rightLay->setSpacing(geopro::app::space::kMd);
|
||||||
|
|
||||||
|
// 滤波设置分组。
|
||||||
|
addSpecTitle(rightLay, QStringLiteral("滤波设置"), card);
|
||||||
|
dataEdge_ = new QComboBox(card);
|
||||||
|
dataEdge_->addItem(QStringLiteral("设置为无效点"), QStringLiteral("whitening"));
|
||||||
|
dataEdge_->addItem(QStringLiteral("忽略"), QStringLiteral("skip"));
|
||||||
|
dataEdge_->addItem(QStringLiteral("复制边缘点"), QStringLiteral("edgePoint"));
|
||||||
|
dataEdge_->addItem(QStringLiteral("填充"), QStringLiteral("filling"));
|
||||||
|
dataEdgeValue_ = new QLineEdit(card);
|
||||||
|
dataEdgeValue_->setEnabled(false);
|
||||||
|
noDataPoints_ = new QComboBox(card);
|
||||||
|
noDataPoints_->addItem(QStringLiteral("扩展"), QStringLiteral("expansion"));
|
||||||
|
noDataPoints_->addItem(QStringLiteral("保留"), QStringLiteral("retain"));
|
||||||
|
noDataPoints_->addItem(QStringLiteral("忽略"), QStringLiteral("skip")); // 原版 skip → 忽略
|
||||||
|
noDataPoints_->addItem(QStringLiteral("填充"), QStringLiteral("filling"));
|
||||||
|
noDataPoints_->setCurrentIndex(3); // 默认填充(对照原版)
|
||||||
|
noDataValue_ = new QLineEdit(card);
|
||||||
|
filterTimes_ = new QSpinBox(card);
|
||||||
|
filterTimes_->setRange(1, 10);
|
||||||
|
|
||||||
|
rightLay->addLayout(settingRow(QStringLiteral("数据边缘:"), dataEdge_,
|
||||||
|
QStringLiteral("值:"), dataEdgeValue_, card));
|
||||||
|
rightLay->addLayout(settingRow(QStringLiteral("无数据点:"), noDataPoints_,
|
||||||
|
QStringLiteral("值:"), noDataValue_, card));
|
||||||
|
rightLay->addLayout(settingRow(QStringLiteral("滤波次数:"), filterTimes_,
|
||||||
|
QString(), nullptr, card));
|
||||||
|
|
||||||
|
// 滤波器规格分组。
|
||||||
|
addSpecTitle(rightLay, QStringLiteral("滤波器规格"), card);
|
||||||
|
rows_ = new QSpinBox(card);
|
||||||
|
rows_->setRange(kMatrixMin, kMatrixMax);
|
||||||
|
rows_->setValue(kDefaultDim);
|
||||||
|
cols_ = new QSpinBox(card);
|
||||||
|
cols_->setRange(kMatrixMin, kMatrixMax);
|
||||||
|
cols_->setValue(kDefaultDim);
|
||||||
|
auto* specsRow = new QHBoxLayout();
|
||||||
|
auto* rowLbl = new QLabel(QStringLiteral("行:"), card);
|
||||||
|
rowLbl->setMinimumWidth(30);
|
||||||
|
specsRow->addWidget(rowLbl);
|
||||||
|
specsRow->addWidget(rows_);
|
||||||
|
specsRow->addSpacing(geopro::app::space::kLg);
|
||||||
|
auto* colLbl = new QLabel(QStringLiteral("列:"), card);
|
||||||
|
colLbl->setMinimumWidth(30);
|
||||||
|
specsRow->addWidget(colLbl);
|
||||||
|
specsRow->addWidget(cols_);
|
||||||
|
specsRow->addStretch();
|
||||||
|
rightLay->addLayout(specsRow);
|
||||||
|
|
||||||
|
matrix_ = new QTableWidget(kDefaultDim, kDefaultDim, card);
|
||||||
|
matrix_->horizontalHeader()->setVisible(true); // 原版矩阵带行列号表头
|
||||||
|
matrix_->verticalHeader()->setVisible(true);
|
||||||
|
rightLay->addWidget(matrix_, 1);
|
||||||
|
body->addWidget(card, 6); // 右 ~60%
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原版 .setting-row:label(80px) + 主控件(30%) [+ 右侧 label「值:」+ 值框(30%)]。
|
||||||
|
QHBoxLayout* FilterDialog::settingRow(const QString& label, QWidget* main, const QString& valLabel,
|
||||||
|
QWidget* valField, QWidget* parent) {
|
||||||
|
auto* row = new QHBoxLayout();
|
||||||
|
row->setSpacing(geopro::app::space::kMd);
|
||||||
|
auto* lbl = new QLabel(label, parent);
|
||||||
|
lbl->setMinimumWidth(kSettingLabelW);
|
||||||
|
row->addWidget(lbl);
|
||||||
|
row->addWidget(main, 3);
|
||||||
|
if (valField) {
|
||||||
|
row->addSpacing(geopro::app::space::kLg);
|
||||||
|
row->addWidget(new QLabel(valLabel, parent));
|
||||||
|
row->addWidget(valField, 3);
|
||||||
|
} else {
|
||||||
|
row->addStretch(4);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FilterDialog::onDimChanged(QSpinBox* box, int newVal, int& prev, const QString& which) {
|
||||||
|
if (newVal % 2 == 0) { // 偶数 → 警告并回退(对照原版 watch 回退旧值)
|
||||||
|
QMessageBox::warning(
|
||||||
|
this, windowTitle(),
|
||||||
|
QStringLiteral("滤波矩阵%1数必须为奇数,以确保有唯一的中心点").arg(which));
|
||||||
|
QSignalBlocker b(box);
|
||||||
|
box->setValue(prev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = newVal;
|
||||||
|
resizeMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
void FilterDialog::loadFilters() {
|
void FilterDialog::loadFilters() {
|
||||||
if (!repo_) return;
|
if (!repo_) return;
|
||||||
QPointer<FilterDialog> self(this);
|
QPointer<FilterDialog> self(this);
|
||||||
|
|
@ -226,6 +320,12 @@ void FilterDialog::resizeMatrix() {
|
||||||
std::vector<std::vector<double>> old = readMatrix();
|
std::vector<std::vector<double>> old = readMatrix();
|
||||||
matrix_->setRowCount(r);
|
matrix_->setRowCount(r);
|
||||||
matrix_->setColumnCount(c);
|
matrix_->setColumnCount(c);
|
||||||
|
// 行列号表头(1..n)。
|
||||||
|
QStringList hh, vh;
|
||||||
|
for (int j = 0; j < c; ++j) hh << QString::number(j + 1);
|
||||||
|
for (int i = 0; i < r; ++i) vh << QString::number(i + 1);
|
||||||
|
matrix_->setHorizontalHeaderLabels(hh);
|
||||||
|
matrix_->setVerticalHeaderLabels(vh);
|
||||||
for (int i = 0; i < r; ++i)
|
for (int i = 0; i < r; ++i)
|
||||||
for (int j = 0; j < c; ++j) {
|
for (int j = 0; j < c; ++j) {
|
||||||
auto* it = matrix_->item(i, j);
|
auto* it = matrix_->item(i, j);
|
||||||
|
|
@ -272,8 +372,8 @@ void FilterDialog::saveCustomFilter() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
const QString name = QInputDialog::getText(this, QStringLiteral("另存为新自定义滤波器"),
|
const QString name = QInputDialog::getText(this, QStringLiteral("保存为新的自定义滤波器"),
|
||||||
QStringLiteral("名称:"), QLineEdit::Normal,
|
QStringLiteral("请输入滤波器名称"), QLineEdit::Normal,
|
||||||
QStringLiteral("自定义滤波器1"), &ok);
|
QStringLiteral("自定义滤波器1"), &ok);
|
||||||
if (!ok || name.trimmed().isEmpty()) return;
|
if (!ok || name.trimmed().isEmpty()) return;
|
||||||
QPointer<FilterDialog> self(this);
|
QPointer<FilterDialog> self(this);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ class QTreeWidget;
|
||||||
class QTreeWidgetItem;
|
class QTreeWidgetItem;
|
||||||
class QTableWidget;
|
class QTableWidget;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
|
class QHBoxLayout;
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
namespace geopro::data {
|
namespace geopro::data {
|
||||||
class IDatasetCommandRepository;
|
class IDatasetCommandRepository;
|
||||||
|
|
@ -31,6 +33,11 @@ public:
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void buildLeft(QHBoxLayout* body); // 左:滤波方式树卡片
|
||||||
|
void buildRight(QHBoxLayout* body); // 右:滤波设置 + 滤波器规格卡片
|
||||||
|
QHBoxLayout* settingRow(const QString& label, QWidget* main, const QString& valLabel,
|
||||||
|
QWidget* valField, QWidget* parent); // 原版 .setting-row
|
||||||
|
void onDimChanged(QSpinBox* box, int newVal, int& prev, const QString& which); // 奇偶校验
|
||||||
void loadFilters(); // 拉滤波器树
|
void loadFilters(); // 拉滤波器树
|
||||||
void buildTree(); // 由 flatItems_ 建树
|
void buildTree(); // 由 flatItems_ 建树
|
||||||
void onTreeSelectionChanged(); // 选中叶节点 → 右侧回填
|
void onTreeSelectionChanged(); // 选中叶节点 → 右侧回填
|
||||||
|
|
@ -56,6 +63,8 @@ private:
|
||||||
QSpinBox* filterTimes_ = nullptr;
|
QSpinBox* filterTimes_ = nullptr;
|
||||||
QSpinBox* rows_ = nullptr;
|
QSpinBox* rows_ = nullptr;
|
||||||
QSpinBox* cols_ = nullptr;
|
QSpinBox* cols_ = nullptr;
|
||||||
|
int prevRows_ = 3; // 奇偶校验回退用(上一合法行数)
|
||||||
|
int prevCols_ = 3; // 上一合法列数
|
||||||
QTableWidget* matrix_ = nullptr;
|
QTableWidget* matrix_ = nullptr;
|
||||||
|
|
||||||
QPushButton* okBtn_ = nullptr;
|
QPushButton* okBtn_ = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,11 @@ GridDataChartView::GridDataChartView(QWidget* parent) : QWidget(parent) {
|
||||||
tbLay->addWidget(lblSimplify);
|
tbLay->addWidget(lblSimplify);
|
||||||
tbLay->addWidget(simplifySlider_);
|
tbLay->addWidget(simplifySlider_);
|
||||||
tbLay->addWidget(simplifyValueLabel_);
|
tbLay->addWidget(simplifyValueLabel_);
|
||||||
|
// 原版 .right-buttons margin-left:auto:异常标注/自动标注/另存为 右对齐。
|
||||||
|
tbLay->addStretch();
|
||||||
tbLay->addWidget(btnAnomalyLabel);
|
tbLay->addWidget(btnAnomalyLabel);
|
||||||
tbLay->addWidget(btnAutoLabel);
|
tbLay->addWidget(btnAutoLabel);
|
||||||
tbLay->addWidget(btnSaveAs);
|
tbLay->addWidget(btnSaveAs);
|
||||||
tbLay->addStretch();
|
|
||||||
|
|
||||||
lay->addWidget(toolbar);
|
lay->addWidget(toolbar);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
#include "panels/chart/GridWizardDialog.hpp"
|
#include "panels/chart/GridWizardDialog.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
#include <QFormLayout>
|
#include <QFrame>
|
||||||
|
#include <QGridLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
|
|
@ -15,7 +17,7 @@
|
||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "FormKit.hpp"
|
#include "Theme.hpp"
|
||||||
#include "panels/chart/InversionProcessOps.hpp" // buildGridToBody
|
#include "panels/chart/InversionProcessOps.hpp" // buildGridToBody
|
||||||
#include "repo/IDatasetCommandRepository.hpp"
|
#include "repo/IDatasetCommandRepository.hpp"
|
||||||
|
|
||||||
|
|
@ -25,86 +27,75 @@ namespace {
|
||||||
constexpr double kCoordRange = 1e9; // 坐标范围(足够宽)
|
constexpr double kCoordRange = 1e9; // 坐标范围(足够宽)
|
||||||
constexpr int kSizeMin = 1, kSizeMax = 300; // 点数范围(对照原版 1~300)
|
constexpr int kSizeMin = 1, kSizeMax = 300; // 点数范围(对照原版 1~300)
|
||||||
constexpr int kDefaultXSize = 100; // 默认点数(原版 xPoints 默认 100)
|
constexpr int kDefaultXSize = 100; // 默认点数(原版 xPoints 默认 100)
|
||||||
|
constexpr int kStep1W = 500, kStep2W = 800; // 原版步骤 1/2 弹窗宽
|
||||||
|
constexpr int kParamLabelW = 60; // 原版 .param-group label min-width:60px
|
||||||
|
constexpr int kParamFieldW = 100; // 原版输入框宽 100px
|
||||||
|
|
||||||
// 配一个坐标 spinbox(6 位小数,宽范围)。
|
// 配一个坐标 spinbox(6 位小数,宽范围)。
|
||||||
QDoubleSpinBox* makeCoordSpin(QWidget* parent) {
|
QDoubleSpinBox* makeCoordSpin(QWidget* parent) {
|
||||||
auto* sp = new QDoubleSpinBox(parent);
|
auto* sp = new QDoubleSpinBox(parent);
|
||||||
sp->setRange(-kCoordRange, kCoordRange);
|
sp->setRange(-kCoordRange, kCoordRange);
|
||||||
sp->setDecimals(6);
|
sp->setDecimals(6);
|
||||||
|
sp->setFixedWidth(kParamFieldW);
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分组卡片标题(原版 .section-title:14px 半粗 + 标题下 1px divider)。
|
||||||
|
void addSectionTitle(QVBoxLayout* into, const QString& title, QWidget* parent) {
|
||||||
|
auto* lbl = new QLabel(title, parent);
|
||||||
|
auto f = lbl->font();
|
||||||
|
f.setBold(true);
|
||||||
|
lbl->setFont(f);
|
||||||
|
into->addWidget(lbl);
|
||||||
|
auto* line = new QFrame(parent);
|
||||||
|
line->setFrameShape(QFrame::HLine);
|
||||||
|
line->setFrameShadow(QFrame::Plain);
|
||||||
|
into->addWidget(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原版 .param-group:定宽右标签 + 紧随输入框,多个并排成一行栅格。
|
||||||
|
void addParamCell(QGridLayout* grid, int row, int col, const QString& label, QWidget* field,
|
||||||
|
QWidget* parent) {
|
||||||
|
auto* cell = new QHBoxLayout();
|
||||||
|
cell->setSpacing(geopro::app::space::kSm);
|
||||||
|
auto* lbl = new QLabel(label, parent);
|
||||||
|
lbl->setMinimumWidth(kParamLabelW);
|
||||||
|
lbl->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
cell->addWidget(lbl);
|
||||||
|
cell->addWidget(field);
|
||||||
|
grid->addLayout(cell, row, col);
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
GridWizardDialog::GridWizardDialog(geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
GridWizardDialog::GridWizardDialog(geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: QDialog(parent), repo_(repo), dsId_(std::move(dsId)) {
|
: QDialog(parent), repo_(repo), dsId_(std::move(dsId)) {
|
||||||
setWindowTitle(QStringLiteral("网格化"));
|
setWindowTitle(QStringLiteral("网格配置")); // 原版 gridSetting
|
||||||
setModal(true);
|
setModal(true);
|
||||||
resize(560, 420);
|
setFixedWidth(kStep1W);
|
||||||
|
|
||||||
auto* root = formkit::dialogRoot(this);
|
auto* root = new QVBoxLayout(this);
|
||||||
|
root->setContentsMargins(geopro::app::space::kLg, geopro::app::space::kLg,
|
||||||
|
geopro::app::space::kLg, geopro::app::space::kLg);
|
||||||
|
root->setSpacing(geopro::app::space::kMd);
|
||||||
stack_ = new QStackedWidget(this);
|
stack_ = new QStackedWidget(this);
|
||||||
root->addWidget(stack_, 1);
|
root->addWidget(stack_, 1);
|
||||||
|
|
||||||
// ── 步骤 1:算法选择(单选列表)──────────────────────────────────────
|
buildStep1();
|
||||||
auto* page1 = new QWidget(this);
|
buildStep2();
|
||||||
auto* p1Lay = new QVBoxLayout(page1);
|
|
||||||
p1Lay->addWidget(new QLabel(QStringLiteral("请选择网格方法:"), page1));
|
|
||||||
algoList_ = new QListWidget(page1);
|
|
||||||
p1Lay->addWidget(algoList_, 1);
|
|
||||||
stack_->addWidget(page1);
|
|
||||||
|
|
||||||
// ── 步骤 2:网格参数 + 数据值设置 ────────────────────────────────────
|
// ── 底部按钮(上一步 / 确认(主) / 取消,原版步骤 2 三按钮)────────────
|
||||||
auto* page2 = new QWidget(this);
|
|
||||||
auto* p2Lay = new QVBoxLayout(page2);
|
|
||||||
xMin_ = makeCoordSpin(page2); xMax_ = makeCoordSpin(page2);
|
|
||||||
yMin_ = makeCoordSpin(page2); yMax_ = makeCoordSpin(page2);
|
|
||||||
vMin_ = makeCoordSpin(page2); vMax_ = makeCoordSpin(page2);
|
|
||||||
xSize_ = new QSpinBox(page2); xSize_->setRange(kSizeMin, kSizeMax); xSize_->setValue(kDefaultXSize);
|
|
||||||
ySize_ = new QSpinBox(page2); ySize_->setRange(kSizeMin, kSizeMax); ySize_->setValue(kDefaultXSize);
|
|
||||||
xSpacing_ = makeCoordSpin(page2); xSpacing_->setRange(0.0, kCoordRange);
|
|
||||||
ySpacing_ = makeCoordSpin(page2); ySpacing_->setRange(0.0, kCoordRange);
|
|
||||||
saveFormat_ = new QComboBox(page2);
|
|
||||||
saveFormat_->addItem(QStringLiteral("线性"), QStringLiteral("linear"));
|
|
||||||
saveFormat_->addItem(QStringLiteral("对数"), QStringLiteral("log"));
|
|
||||||
|
|
||||||
formkit::capField(xMin_);
|
|
||||||
formkit::capField(xMax_);
|
|
||||||
formkit::capField(xSpacing_);
|
|
||||||
formkit::capField(yMin_);
|
|
||||||
formkit::capField(yMax_);
|
|
||||||
formkit::capField(ySpacing_);
|
|
||||||
formkit::capField(vMin_);
|
|
||||||
formkit::capField(vMax_);
|
|
||||||
formkit::capField(xSize_);
|
|
||||||
formkit::capField(ySize_);
|
|
||||||
formkit::capField(saveFormat_);
|
|
||||||
|
|
||||||
auto* form = formkit::makeEditForm();
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("Xmin:")), xMin_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("Xmax:")), xMax_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("X点数:")), xSize_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("X间距:")), xSpacing_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("Ymin:")), yMin_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("Ymax:")), yMax_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("Y点数:")), ySize_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("Y间距:")), ySpacing_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("数据值min:")), vMin_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("数据值max:")), vMax_);
|
|
||||||
form->addRow(formkit::editLabel(QStringLiteral("保存格式:")), saveFormat_);
|
|
||||||
p2Lay->addLayout(form);
|
|
||||||
stack_->addWidget(page2);
|
|
||||||
|
|
||||||
// ── 底部按钮(上一步 / 下一步 / 确认 / 取消)────────────────────────
|
|
||||||
auto* btnLay = new QHBoxLayout();
|
auto* btnLay = new QHBoxLayout();
|
||||||
|
btnLay->setSpacing(geopro::app::space::kMd);
|
||||||
btnLay->addStretch();
|
btnLay->addStretch();
|
||||||
prevBtn_ = new QPushButton(QStringLiteral("上一步"), this);
|
prevBtn_ = new QPushButton(QStringLiteral("上一步"), this);
|
||||||
nextBtn_ = new QPushButton(QStringLiteral("下一步"), this);
|
|
||||||
okBtn_ = new QPushButton(QStringLiteral("确认"), this);
|
okBtn_ = new QPushButton(QStringLiteral("确认"), this);
|
||||||
|
okBtn_->setDefault(true);
|
||||||
|
nextBtn_ = new QPushButton(QStringLiteral("下一步"), this);
|
||||||
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
||||||
btnLay->addWidget(prevBtn_);
|
btnLay->addWidget(prevBtn_);
|
||||||
btnLay->addWidget(nextBtn_);
|
|
||||||
btnLay->addWidget(okBtn_);
|
btnLay->addWidget(okBtn_);
|
||||||
|
btnLay->addWidget(nextBtn_);
|
||||||
btnLay->addWidget(cancelBtn);
|
btnLay->addWidget(cancelBtn);
|
||||||
root->addLayout(btnLay);
|
root->addLayout(btnLay);
|
||||||
prevBtn_->setVisible(false);
|
prevBtn_->setVisible(false);
|
||||||
|
|
@ -114,18 +105,108 @@ GridWizardDialog::GridWizardDialog(geopro::data::IDatasetCommandRepository* repo
|
||||||
connect(nextBtn_, &QPushButton::clicked, this, &GridWizardDialog::goToStep2);
|
connect(nextBtn_, &QPushButton::clicked, this, &GridWizardDialog::goToStep2);
|
||||||
connect(prevBtn_, &QPushButton::clicked, this, [this]() {
|
connect(prevBtn_, &QPushButton::clicked, this, [this]() {
|
||||||
stack_->setCurrentIndex(0);
|
stack_->setCurrentIndex(0);
|
||||||
|
setFixedWidth(kStep1W);
|
||||||
prevBtn_->setVisible(false); okBtn_->setVisible(false); nextBtn_->setVisible(true);
|
prevBtn_->setVisible(false); okBtn_->setVisible(false); nextBtn_->setVisible(true);
|
||||||
});
|
});
|
||||||
connect(okBtn_, &QPushButton::clicked, this, &GridWizardDialog::onConfirm);
|
connect(okBtn_, &QPushButton::clicked, this, &GridWizardDialog::onConfirm);
|
||||||
// 点数变化 → 重算间距(原版 calculateXInterval/calculateYInterval)。
|
|
||||||
connect(xSize_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
|
||||||
[this](int) { recalcXSpacing(); });
|
|
||||||
connect(ySize_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
|
||||||
[this](int) { recalcYSpacing(); });
|
|
||||||
|
|
||||||
loadAlgorithms();
|
loadAlgorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GridWizardDialog::buildStep1() {
|
||||||
|
auto* page1 = new QWidget(this);
|
||||||
|
auto* p1Lay = new QVBoxLayout(page1);
|
||||||
|
p1Lay->setContentsMargins(0, 0, 0, 0);
|
||||||
|
p1Lay->setSpacing(geopro::app::space::kMd);
|
||||||
|
p1Lay->addWidget(new QLabel(QStringLiteral("请选择网格方法:"), page1));
|
||||||
|
algoList_ = new QListWidget(page1);
|
||||||
|
p1Lay->addWidget(algoList_, 1);
|
||||||
|
stack_->addWidget(page1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridWizardDialog::buildStep2() {
|
||||||
|
auto* page2 = new QWidget(this);
|
||||||
|
auto* p2Lay = new QVBoxLayout(page2);
|
||||||
|
p2Lay->setContentsMargins(0, 0, 0, 0);
|
||||||
|
p2Lay->setSpacing(geopro::app::space::kLg);
|
||||||
|
|
||||||
|
xMin_ = makeCoordSpin(page2); xMax_ = makeCoordSpin(page2);
|
||||||
|
yMin_ = makeCoordSpin(page2); yMax_ = makeCoordSpin(page2);
|
||||||
|
vMin_ = makeCoordSpin(page2); vMax_ = makeCoordSpin(page2);
|
||||||
|
xSize_ = new QSpinBox(page2); xSize_->setRange(kSizeMin, kSizeMax);
|
||||||
|
xSize_->setValue(kDefaultXSize); xSize_->setFixedWidth(100);
|
||||||
|
ySize_ = new QSpinBox(page2); ySize_->setRange(kSizeMin, kSizeMax);
|
||||||
|
ySize_->setValue(kDefaultXSize); ySize_->setFixedWidth(100);
|
||||||
|
xSpacing_ = makeCoordSpin(page2); xSpacing_->setRange(0.0, kCoordRange);
|
||||||
|
ySpacing_ = makeCoordSpin(page2); ySpacing_->setRange(0.0, kCoordRange);
|
||||||
|
|
||||||
|
// 分组 1:网格参数(栅格:Xmax→Xmin→X间距→X点数 同行;Y 同理)。
|
||||||
|
addSectionTitle(p2Lay, QStringLiteral("网格参数"), page2);
|
||||||
|
auto* grid = new QGridLayout();
|
||||||
|
grid->setHorizontalSpacing(geopro::app::space::kMd);
|
||||||
|
grid->setVerticalSpacing(geopro::app::space::kMd);
|
||||||
|
addParamCell(grid, 0, 0, QStringLiteral("Xmax"), xMax_, page2);
|
||||||
|
addParamCell(grid, 0, 1, QStringLiteral("Xmin"), xMin_, page2);
|
||||||
|
addParamCell(grid, 0, 2, QStringLiteral("X间距"), xSpacing_, page2);
|
||||||
|
addParamCell(grid, 0, 3, QStringLiteral("X点数"), xSize_, page2);
|
||||||
|
addParamCell(grid, 1, 0, QStringLiteral("Ymax"), yMax_, page2);
|
||||||
|
addParamCell(grid, 1, 1, QStringLiteral("Ymin"), yMin_, page2);
|
||||||
|
addParamCell(grid, 1, 2, QStringLiteral("Y间距"), ySpacing_, page2);
|
||||||
|
addParamCell(grid, 1, 3, QStringLiteral("Y点数"), ySize_, page2);
|
||||||
|
grid->setColumnStretch(4, 1);
|
||||||
|
p2Lay->addLayout(grid);
|
||||||
|
|
||||||
|
// 分组 2:数据值设置(数据值max/min + 恢复默认值 + 数据值保存为)。
|
||||||
|
addSectionTitle(p2Lay, QStringLiteral("数据值设置"), page2);
|
||||||
|
saveFormat_ = new QComboBox(page2);
|
||||||
|
saveFormat_->addItem(QStringLiteral("线性"), QStringLiteral("linear"));
|
||||||
|
saveFormat_->addItem(QStringLiteral("对数"), QStringLiteral("log"));
|
||||||
|
saveFormat_->setFixedWidth(120);
|
||||||
|
auto* restoreBtn = new QPushButton(QStringLiteral("恢复默认值"), page2);
|
||||||
|
|
||||||
|
auto* dv = new QGridLayout();
|
||||||
|
dv->setHorizontalSpacing(geopro::app::space::kLg);
|
||||||
|
dv->setVerticalSpacing(geopro::app::space::kMd);
|
||||||
|
auto* vmaxLbl = new QLabel(QStringLiteral("数据值max"), page2);
|
||||||
|
vmaxLbl->setMinimumWidth(kParamLabelW + 20);
|
||||||
|
vmaxLbl->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
dv->addWidget(vmaxLbl, 0, 0);
|
||||||
|
dv->addWidget(vMax_, 0, 1);
|
||||||
|
dv->addWidget(restoreBtn, 0, 3);
|
||||||
|
auto* vminLbl = new QLabel(QStringLiteral("数据值min"), page2);
|
||||||
|
vminLbl->setMinimumWidth(kParamLabelW + 20);
|
||||||
|
vminLbl->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
dv->addWidget(vminLbl, 1, 0);
|
||||||
|
dv->addWidget(vMin_, 1, 1);
|
||||||
|
auto* fmtLbl = new QLabel(QStringLiteral("数据值保存为"), page2); // 原版 saveFormat
|
||||||
|
fmtLbl->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
dv->addWidget(fmtLbl, 1, 2);
|
||||||
|
dv->addWidget(saveFormat_, 1, 3);
|
||||||
|
dv->setColumnStretch(4, 1);
|
||||||
|
p2Lay->addLayout(dv);
|
||||||
|
p2Lay->addStretch();
|
||||||
|
stack_->addWidget(page2);
|
||||||
|
|
||||||
|
// 联动:Xmax/Xmin/X点数变 → 反算 X间距(round);X间距变 → 反算 X点数(round)。
|
||||||
|
connect(xMax_, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
||||||
|
[this](double) { calcXInterval(); });
|
||||||
|
connect(xMin_, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
||||||
|
[this](double) { calcXInterval(); });
|
||||||
|
connect(xSize_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||||
|
[this](int) { calcXInterval(); });
|
||||||
|
connect(xSpacing_, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
||||||
|
[this](double) { calcXPoints(); });
|
||||||
|
connect(yMax_, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
||||||
|
[this](double) { calcYInterval(); });
|
||||||
|
connect(yMin_, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
||||||
|
[this](double) { calcYInterval(); });
|
||||||
|
connect(ySize_, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||||
|
[this](int) { calcYInterval(); });
|
||||||
|
connect(ySpacing_, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
|
||||||
|
[this](double) { calcYPoints(); });
|
||||||
|
connect(restoreBtn, &QPushButton::clicked, this, &GridWizardDialog::loadParams);
|
||||||
|
}
|
||||||
|
|
||||||
void GridWizardDialog::loadAlgorithms() {
|
void GridWizardDialog::loadAlgorithms() {
|
||||||
if (!repo_) return;
|
if (!repo_) return;
|
||||||
QPointer<GridWizardDialog> self(this);
|
QPointer<GridWizardDialog> self(this);
|
||||||
|
|
@ -149,6 +230,7 @@ void GridWizardDialog::goToStep2() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stack_->setCurrentIndex(1);
|
stack_->setCurrentIndex(1);
|
||||||
|
setFixedWidth(kStep2W);
|
||||||
nextBtn_->setVisible(false);
|
nextBtn_->setVisible(false);
|
||||||
prevBtn_->setVisible(true);
|
prevBtn_->setVisible(true);
|
||||||
okBtn_->setVisible(true);
|
okBtn_->setVisible(true);
|
||||||
|
|
@ -166,28 +248,63 @@ void GridWizardDialog::loadParams() {
|
||||||
self->yMax_->setValue(d.value(QStringLiteral("ymax")).toDouble());
|
self->yMax_->setValue(d.value(QStringLiteral("ymax")).toDouble());
|
||||||
self->vMin_->setValue(d.value(QStringLiteral("vmin")).toDouble());
|
self->vMin_->setValue(d.value(QStringLiteral("vmin")).toDouble());
|
||||||
self->vMax_->setValue(d.value(QStringLiteral("vmax")).toDouble());
|
self->vMax_->setValue(d.value(QStringLiteral("vmax")).toDouble());
|
||||||
// 初始间距 = (xmax-xmin)/xSize,y 间距同 x(原版 onMounted 逻辑)。
|
// 原版 onMounted:X点数固定 100 → 算 X间距 → Y间距=X间距 → Y点数=ceil。
|
||||||
self->recalcXSpacing();
|
self->xSize_->setValue(kDefaultXSize);
|
||||||
|
self->calcXInterval();
|
||||||
const double dx = self->xSpacing_->value();
|
const double dx = self->xSpacing_->value();
|
||||||
if (dx > 0) self->ySpacing_->setValue(dx);
|
if (dx > 0) self->ySpacing_->setValue(dx); // 触发 calcYPoints
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridWizardDialog::recalcXSpacing() {
|
void GridWizardDialog::calcXInterval() {
|
||||||
const int n = xSize_->value();
|
const int n = xSize_->value();
|
||||||
if (n > 0) xSpacing_->setValue((xMax_->value() - xMin_->value()) / n);
|
const double range = xMax_->value() - xMin_->value();
|
||||||
|
if (n > 0 && range > 0) {
|
||||||
|
QSignalBlocker b(xSpacing_); // 防与 calcXPoints 互触发
|
||||||
|
xSpacing_->setValue(range / n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridWizardDialog::recalcYSpacing() {
|
void GridWizardDialog::calcXPoints() {
|
||||||
|
const double iv = xSpacing_->value();
|
||||||
|
const double range = xMax_->value() - xMin_->value();
|
||||||
|
if (iv > 0 && range > 0) {
|
||||||
|
QSignalBlocker b(xSize_);
|
||||||
|
xSize_->setValue(static_cast<int>(std::lround(range / iv))); // 原版 round
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridWizardDialog::calcYInterval() {
|
||||||
const int n = ySize_->value();
|
const int n = ySize_->value();
|
||||||
if (n > 0) ySpacing_->setValue((yMax_->value() - yMin_->value()) / n);
|
const double range = yMax_->value() - yMin_->value();
|
||||||
|
if (n > 0 && range > 0) {
|
||||||
|
QSignalBlocker b(ySpacing_);
|
||||||
|
ySpacing_->setValue(range / n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridWizardDialog::calcYPoints() {
|
||||||
|
const double iv = ySpacing_->value();
|
||||||
|
const double range = yMax_->value() - yMin_->value();
|
||||||
|
if (iv > 0 && range > 0) {
|
||||||
|
QSignalBlocker b(ySize_);
|
||||||
|
ySize_->setValue(static_cast<int>(std::ceil(range / iv))); // 原版 ceil(与 X 的 round 不同)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridWizardDialog::onConfirm() {
|
void GridWizardDialog::onConfirm() {
|
||||||
if (!repo_ || !algoList_->currentItem()) { reject(); return; }
|
if (!repo_ || !algoList_->currentItem()) { reject(); return; }
|
||||||
if (xMax_->value() < xMin_->value() || yMax_->value() < yMin_->value() ||
|
// 原版按 Xmax/Ymax/数据值分别提示。
|
||||||
vMax_->value() < vMin_->value()) {
|
if (xMax_->value() < xMin_->value()) {
|
||||||
QMessageBox::warning(this, windowTitle(), QStringLiteral("最大值不能小于最小值"));
|
QMessageBox::warning(this, windowTitle(), QStringLiteral("Xmax不能小于Xmin"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (yMax_->value() < yMin_->value()) {
|
||||||
|
QMessageBox::warning(this, windowTitle(), QStringLiteral("Ymax不能小于Ymin"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (vMax_->value() < vMin_->value()) {
|
||||||
|
QMessageBox::warning(this, windowTitle(), QStringLiteral("数据值max不能小于数据值min"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GridToParams p;
|
GridToParams p;
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,15 @@ public:
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void buildStep1(); // 步骤 1:算法选择列表
|
||||||
|
void buildStep2(); // 步骤 2:网格参数 + 数据值设置(两分组卡片)
|
||||||
void loadAlgorithms(); // 步骤 1:拉算法列表
|
void loadAlgorithms(); // 步骤 1:拉算法列表
|
||||||
void loadParams(); // 步骤 2:拉 x/y/v 默认参数
|
void loadParams(); // 步骤 2:拉 x/y/v 默认参数(兼「恢复默认值」)
|
||||||
void goToStep2(); // 下一步(校验算法已选)
|
void goToStep2(); // 下一步(校验算法已选)
|
||||||
void recalcXSpacing(); // (xMax-xMin)/xSize → xSpacing(间距已有值时)
|
void calcXInterval(); // Xmax/Xmin/X点数变 → X间距=(xMax-xMin)/xSize
|
||||||
void recalcYSpacing(); // (yMax-yMin)/ySize → ySpacing
|
void calcXPoints(); // X间距变 → X点数=round((xMax-xMin)/xSpacing)
|
||||||
|
void calcYInterval(); // Ymax/Ymin/Y点数变 → Y间距=(yMax-yMin)/ySize
|
||||||
|
void calcYPoints(); // Y间距变 → Y点数=ceil((yMax-yMin)/ySpacing)
|
||||||
void onConfirm(); // 确认 → toGrid
|
void onConfirm(); // 确认 → toGrid
|
||||||
|
|
||||||
geopro::data::IDatasetCommandRepository* repo_ = nullptr;
|
geopro::data::IDatasetCommandRepository* repo_ = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,9 @@ RawDataChartView::RawDataChartView(QWidget* parent) : QWidget(parent) {
|
||||||
tbLay->addWidget(btnColorScale);
|
tbLay->addWidget(btnColorScale);
|
||||||
tbLay->addWidget(lblCurrentChart);
|
tbLay->addWidget(lblCurrentChart);
|
||||||
tbLay->addWidget(chartTypeCombo_);
|
tbLay->addWidget(chartTypeCombo_);
|
||||||
tbLay->addWidget(btnSaveAs);
|
// 原版 .right-buttons margin-left:auto:另存为 右对齐。
|
||||||
tbLay->addStretch();
|
tbLay->addStretch();
|
||||||
|
tbLay->addWidget(btnSaveAs);
|
||||||
|
|
||||||
// 反演原数据默认工具条交互(O1 网格 / O2 色阶配置 / O3 另存为)。
|
// 反演原数据默认工具条交互(O1 网格 / O2 色阶配置 / O3 另存为)。
|
||||||
connect(btnGrid, &QToolButton::clicked, this, [this, btnGrid]() { openGridWizard(btnGrid); });
|
connect(btnGrid, &QToolButton::clicked, this, [this, btnGrid]() { openGridWizard(btnGrid); });
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <QButtonGroup>
|
#include <QButtonGroup>
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
|
@ -13,49 +12,68 @@
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "FormKit.hpp"
|
#include "Theme.hpp"
|
||||||
#include "panels/chart/ScatterDataOps.hpp" // buildSaveRawDataBody(纯组装,便于单测)
|
#include "panels/chart/ScatterDataOps.hpp" // buildSaveRawDataBody(纯组装,便于单测)
|
||||||
#include "repo/IDatasetCommandRepository.hpp"
|
#include "repo/IDatasetCommandRepository.hpp"
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr int kInversionW = 400; // 原版 inversion 另存为弹窗宽 400px
|
||||||
|
constexpr int kLabelW = 60; // 原版 .label width:60px
|
||||||
|
} // namespace
|
||||||
|
|
||||||
SaveAsDialog::SaveAsDialog(Mode mode, geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
SaveAsDialog::SaveAsDialog(Mode mode, geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: QDialog(parent), mode_(mode), repo_(repo), dsId_(std::move(dsId)) {
|
: QDialog(parent), mode_(mode), repo_(repo), dsId_(std::move(dsId)) {
|
||||||
setWindowTitle(QStringLiteral("数据另存为"));
|
|
||||||
setModal(true);
|
setModal(true);
|
||||||
|
|
||||||
auto* root = formkit::dialogRoot(this);
|
auto* root = new QVBoxLayout(this);
|
||||||
|
root->setContentsMargins(geopro::app::space::kLg, geopro::app::space::kLg,
|
||||||
|
geopro::app::space::kLg, geopro::app::space::kLg);
|
||||||
|
root->setSpacing(geopro::app::space::kMd);
|
||||||
|
|
||||||
auto* card = formkit::formCard(this);
|
if (mode_ == Mode::Inversion) {
|
||||||
auto* cardLay = formkit::cardBody(card);
|
// ── inversion:原版「另存为新的网格数据」400px,仅名称行 ──
|
||||||
|
setWindowTitle(QStringLiteral("另存为新的网格数据"));
|
||||||
|
setFixedWidth(kInversionW);
|
||||||
|
|
||||||
|
auto* nameRow = new QHBoxLayout();
|
||||||
|
nameRow->setSpacing(geopro::app::space::kMd);
|
||||||
|
nameLabel_ = new QLabel(QStringLiteral("名称:"), this); // 原版 label「名称:」
|
||||||
|
nameLabel_->setMinimumWidth(kLabelW);
|
||||||
|
nameEdit_ = new QLineEdit(this);
|
||||||
|
nameEdit_->setPlaceholderText(QStringLiteral("请输入名称"));
|
||||||
|
nameEdit_->setText(QStringLiteral("网格数据1")); // 原版默认值
|
||||||
|
nameRow->addWidget(nameLabel_);
|
||||||
|
nameRow->addWidget(nameEdit_, 1);
|
||||||
|
root->addLayout(nameRow);
|
||||||
|
} else {
|
||||||
|
// ── RawData(measurement):新增/覆盖 + 名称(保持既有逻辑,不在本批返工范围)──
|
||||||
|
setWindowTitle(QStringLiteral("数据另存为"));
|
||||||
|
|
||||||
if (mode_ == Mode::RawData) {
|
|
||||||
// 新增/覆盖单选(复刻原版 a-radio-group:1=新增 0=覆盖)。
|
|
||||||
auto* opLay = new QHBoxLayout();
|
auto* opLay = new QHBoxLayout();
|
||||||
auto* rbNew = new QRadioButton(QStringLiteral("新增"), this);
|
auto* rbNew = new QRadioButton(QStringLiteral("新增"), this);
|
||||||
auto* rbOverwrite = new QRadioButton(QStringLiteral("覆盖"), this);
|
auto* rbOverwrite = new QRadioButton(QStringLiteral("覆盖"), this);
|
||||||
opGroup_ = new QButtonGroup(this);
|
opGroup_ = new QButtonGroup(this);
|
||||||
opGroup_->addButton(rbNew, 1);
|
opGroup_->addButton(rbNew, 1);
|
||||||
opGroup_->addButton(rbOverwrite, 0);
|
opGroup_->addButton(rbOverwrite, 0);
|
||||||
rbNew->setChecked(true); // 默认新增(与原版 dataStored 初值一致)
|
rbNew->setChecked(true); // 默认新增
|
||||||
opLay->addWidget(rbNew);
|
opLay->addWidget(rbNew);
|
||||||
opLay->addWidget(rbOverwrite);
|
opLay->addWidget(rbOverwrite);
|
||||||
opLay->addStretch();
|
opLay->addStretch();
|
||||||
cardLay->addLayout(opLay);
|
root->addLayout(opLay);
|
||||||
}
|
|
||||||
|
|
||||||
// 名称行:RawData 仅新增可见;Inversion 始终可见。
|
auto* nameRow = new QHBoxLayout();
|
||||||
auto* nameForm = formkit::makeEditForm();
|
nameRow->setSpacing(geopro::app::space::kMd);
|
||||||
nameLabel_ = formkit::editLabel(QStringLiteral("数据名称"), this);
|
nameLabel_ = new QLabel(QStringLiteral("数据名称"), this);
|
||||||
|
nameLabel_->setMinimumWidth(kLabelW);
|
||||||
nameEdit_ = new QLineEdit(this);
|
nameEdit_ = new QLineEdit(this);
|
||||||
formkit::capField(nameEdit_);
|
nameRow->addWidget(nameLabel_);
|
||||||
nameForm->addRow(nameLabel_, nameEdit_);
|
nameRow->addWidget(nameEdit_, 1);
|
||||||
cardLay->addLayout(nameForm);
|
root->addLayout(nameRow);
|
||||||
root->addWidget(card);
|
|
||||||
|
|
||||||
if (mode_ == Mode::RawData && opGroup_) {
|
// 切到覆盖隐藏名称框,切回新增显示。
|
||||||
// 切到覆盖隐藏名称框,切回新增显示(复刻原版 v-show=dataStored===1)。
|
|
||||||
connect(opGroup_, QOverload<int>::of(&QButtonGroup::idClicked), this, [this](int id) {
|
connect(opGroup_, QOverload<int>::of(&QButtonGroup::idClicked), this, [this](int id) {
|
||||||
const bool isNew = (id == 1);
|
const bool isNew = (id == 1);
|
||||||
nameLabel_->setVisible(isNew);
|
nameLabel_->setVisible(isNew);
|
||||||
|
|
@ -63,13 +81,15 @@ SaveAsDialog::SaveAsDialog(Mode mode, geopro::data::IDatasetCommandRepository* r
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 底部按钮:原版右对齐,确认(主,左)/取消(右)。
|
||||||
auto* btnLay = new QHBoxLayout();
|
auto* btnLay = new QHBoxLayout();
|
||||||
|
btnLay->setSpacing(geopro::app::space::kMd);
|
||||||
btnLay->addStretch();
|
btnLay->addStretch();
|
||||||
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
okBtn_ = new QPushButton(QStringLiteral("确认"), this);
|
||||||
okBtn_ = new QPushButton(QStringLiteral("确定"), this);
|
|
||||||
okBtn_->setDefault(true);
|
okBtn_->setDefault(true);
|
||||||
btnLay->addWidget(cancelBtn);
|
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
||||||
btnLay->addWidget(okBtn_);
|
btnLay->addWidget(okBtn_);
|
||||||
|
btnLay->addWidget(cancelBtn);
|
||||||
root->addLayout(btnLay);
|
root->addLayout(btnLay);
|
||||||
|
|
||||||
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
||||||
|
|
@ -84,7 +104,7 @@ void SaveAsDialog::onConfirm() {
|
||||||
const bool needName = (mode_ == Mode::Inversion) || (operationType == 1);
|
const bool needName = (mode_ == Mode::Inversion) || (operationType == 1);
|
||||||
const QString name = nameEdit_->text().trimmed();
|
const QString name = nameEdit_->text().trimmed();
|
||||||
if (needName && name.isEmpty()) {
|
if (needName && name.isEmpty()) {
|
||||||
QMessageBox::warning(this, windowTitle(), QStringLiteral("请输入数据名称"));
|
QMessageBox::warning(this, windowTitle(), QStringLiteral("请输入名称"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,9 @@
|
||||||
|
|
||||||
#include <QButtonGroup>
|
#include <QButtonGroup>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include <QFormLayout>
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
@ -15,14 +14,34 @@
|
||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "FormKit.hpp"
|
#include "Theme.hpp"
|
||||||
#include "panels/chart/InversionProcessOps.hpp" // buildWhitenBody
|
#include "panels/chart/InversionProcessOps.hpp" // buildWhitenBody
|
||||||
#include "repo/IDatasetCommandRepository.hpp"
|
#include "repo/IDatasetCommandRepository.hpp"
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr double kExtRange = 1e6; // 边界扩展范围
|
constexpr int kDialogW = 550; // 原版弹窗宽 550px
|
||||||
|
constexpr int kLabelMinW = 120; // 原版 .field-label min-width:120px 右对齐
|
||||||
|
constexpr double kCtrlRatio = 0.6; // 原版控件宽 60%
|
||||||
|
|
||||||
|
// 原版 .field-label:定宽右对齐标签。
|
||||||
|
QLabel* fieldLabel(const QString& text, QWidget* parent) {
|
||||||
|
auto* lbl = new QLabel(text, parent);
|
||||||
|
lbl->setMinimumWidth(kLabelMinW);
|
||||||
|
lbl->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
return lbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原版 .option-item:flex 行(标签右对齐 + 控件占 60%)。控件外裹一层以 60/40 拉伸。
|
||||||
|
QHBoxLayout* optionRow(const QString& label, QWidget* ctrl, QWidget* parent) {
|
||||||
|
auto* row = new QHBoxLayout();
|
||||||
|
row->setSpacing(geopro::app::space::kLg);
|
||||||
|
row->addWidget(fieldLabel(label, parent));
|
||||||
|
row->addWidget(ctrl, 6); // 控件 60%
|
||||||
|
row->addStretch(4); // 余 40% 留白
|
||||||
|
return row;
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo, QString dsId,
|
||||||
|
|
@ -32,37 +51,37 @@ WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo,
|
||||||
dsId_(std::move(dsId)),
|
dsId_(std::move(dsId)),
|
||||||
projectId_(std::move(projectId)),
|
projectId_(std::move(projectId)),
|
||||||
tmObjectId_(std::move(tmObjectId)) {
|
tmObjectId_(std::move(tmObjectId)) {
|
||||||
setWindowTitle(QStringLiteral("白化"));
|
setWindowTitle(QStringLiteral("白化配置")); // 原版 whiteningSetting
|
||||||
setModal(true);
|
setModal(true);
|
||||||
resize(460, 280);
|
setFixedWidth(kDialogW);
|
||||||
|
|
||||||
auto* root = formkit::dialogRoot(this);
|
auto* root = new QVBoxLayout(this);
|
||||||
|
root->setContentsMargins(geopro::app::space::kLg, geopro::app::space::kLg,
|
||||||
|
geopro::app::space::kLg, geopro::app::space::kLg);
|
||||||
|
root->setSpacing(geopro::app::space::kMd);
|
||||||
|
|
||||||
// 白化方式下拉(数值对照原版 whiteningMethod 1/2/3)。
|
// 白化方式下拉(原版 3 项,数值对照 whiteningMethod 1/2/3)。
|
||||||
auto* methodLay = formkit::makeEditForm();
|
|
||||||
methodCombo_ = new QComboBox(this);
|
methodCombo_ = new QComboBox(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);
|
||||||
formkit::capField(methodCombo_);
|
root->addLayout(optionRow(QStringLiteral("白化方式"), methodCombo_, this));
|
||||||
methodLay->addRow(formkit::editLabel(QStringLiteral("白化方式")), methodCombo_);
|
|
||||||
root->addLayout(methodLay);
|
|
||||||
|
|
||||||
stack_ = new QStackedWidget(this);
|
stack_ = new QStackedWidget(this);
|
||||||
root->addWidget(stack_, 1);
|
root->addWidget(stack_);
|
||||||
|
|
||||||
// ── 方式 1:数据边界自动白化 ────────────────────────────────────────
|
// ── 方式 1:数据边界自动白化(边界扩展文本框 + 内/外白化单选)────────────
|
||||||
auto* page1 = new QWidget(this);
|
auto* page1 = new QWidget(this);
|
||||||
auto* p1 = formkit::makeEditForm();
|
auto* p1 = new QVBoxLayout(page1);
|
||||||
page1->setLayout(p1);
|
p1->setContentsMargins(0, 0, 0, 0);
|
||||||
extension_ = new QDoubleSpinBox(page1);
|
p1->setSpacing(geopro::app::space::kMd);
|
||||||
extension_->setRange(-kExtRange, kExtRange);
|
extension_ = new QLineEdit(QStringLiteral("0"), page1); // 原版 AInput,默认 "0"
|
||||||
extension_->setDecimals(3);
|
p1->addLayout(optionRow(QStringLiteral("白化边界扩展"), extension_, page1));
|
||||||
formkit::capField(extension_);
|
auto* typeWrap = new QWidget(page1);
|
||||||
p1->addRow(formkit::editLabel(QStringLiteral("白化边界扩展")), extension_);
|
auto* typeRow = new QHBoxLayout(typeWrap);
|
||||||
auto* typeRow = new QHBoxLayout();
|
typeRow->setContentsMargins(0, 0, 0, 0);
|
||||||
auto* rbOuter = new QRadioButton(QStringLiteral("外部白化"), page1);
|
auto* rbOuter = new QRadioButton(QStringLiteral("外部白化"), typeWrap);
|
||||||
auto* rbInner = new QRadioButton(QStringLiteral("内部白化"), page1);
|
auto* rbInner = new QRadioButton(QStringLiteral("内部白化"), typeWrap);
|
||||||
rbOuter->setChecked(true);
|
rbOuter->setChecked(true);
|
||||||
whiteningType_ = new QButtonGroup(this);
|
whiteningType_ = new QButtonGroup(this);
|
||||||
whiteningType_->addButton(rbOuter, 0);
|
whiteningType_->addButton(rbOuter, 0);
|
||||||
|
|
@ -70,25 +89,26 @@ WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo,
|
||||||
typeRow->addWidget(rbOuter);
|
typeRow->addWidget(rbOuter);
|
||||||
typeRow->addWidget(rbInner);
|
typeRow->addWidget(rbInner);
|
||||||
typeRow->addStretch();
|
typeRow->addStretch();
|
||||||
p1->addRow(formkit::editLabel(QStringLiteral("白化")), typeRow);
|
p1->addLayout(optionRow(QStringLiteral("白化"), typeWrap, page1));
|
||||||
stack_->addWidget(page1);
|
stack_->addWidget(page1);
|
||||||
|
|
||||||
// ── 方式 2:白化模板(选文件)──────────────────────────────────────
|
// ── 方式 2:白化文件(选文件)──────────────────────────────────────
|
||||||
auto* page2 = new QWidget(this);
|
auto* page2 = new QWidget(this);
|
||||||
auto* p2 = formkit::makeEditForm();
|
auto* p2 = new QVBoxLayout(page2);
|
||||||
page2->setLayout(p2);
|
p2->setContentsMargins(0, 0, 0, 0);
|
||||||
fileCombo_ = new QComboBox(page2);
|
fileCombo_ = new QComboBox(page2);
|
||||||
formkit::capField(fileCombo_);
|
p2->addLayout(optionRow(QStringLiteral("选择白化文件"), fileCombo_, page2));
|
||||||
p2->addRow(formkit::editLabel(QStringLiteral("选择白化文件")), fileCombo_);
|
|
||||||
stack_->addWidget(page2);
|
stack_->addWidget(page2);
|
||||||
|
|
||||||
// ── 方式 3:模型白化(梯形/矩形)───────────────────────────────────
|
// ── 方式 3:模型白化(梯形/矩形)───────────────────────────────────
|
||||||
auto* page3 = new QWidget(this);
|
auto* page3 = new QWidget(this);
|
||||||
auto* p3 = formkit::makeEditForm();
|
auto* p3 = new QVBoxLayout(page3);
|
||||||
page3->setLayout(p3);
|
p3->setContentsMargins(0, 0, 0, 0);
|
||||||
auto* subRow = new QHBoxLayout();
|
auto* subWrap = new QWidget(page3);
|
||||||
auto* rbTrap = new QRadioButton(QStringLiteral("梯形白化"), page3);
|
auto* subRow = new QHBoxLayout(subWrap);
|
||||||
auto* rbRect = new QRadioButton(QStringLiteral("矩形白化"), page3);
|
subRow->setContentsMargins(0, 0, 0, 0);
|
||||||
|
auto* rbTrap = new QRadioButton(QStringLiteral("梯形白化"), subWrap);
|
||||||
|
auto* rbRect = new QRadioButton(QStringLiteral("矩形白化"), subWrap);
|
||||||
rbTrap->setChecked(true);
|
rbTrap->setChecked(true);
|
||||||
modelSubType_ = new QButtonGroup(this);
|
modelSubType_ = new QButtonGroup(this);
|
||||||
modelSubType_->addButton(rbTrap, 2); // 2 梯形
|
modelSubType_->addButton(rbTrap, 2); // 2 梯形
|
||||||
|
|
@ -96,17 +116,20 @@ WhiteningDialog::WhiteningDialog(geopro::data::IDatasetCommandRepository* repo,
|
||||||
subRow->addWidget(rbTrap);
|
subRow->addWidget(rbTrap);
|
||||||
subRow->addWidget(rbRect);
|
subRow->addWidget(rbRect);
|
||||||
subRow->addStretch();
|
subRow->addStretch();
|
||||||
p3->addRow(formkit::editLabel(QStringLiteral("白化")), subRow);
|
p3->addLayout(optionRow(QStringLiteral("白化"), subWrap, page3));
|
||||||
stack_->addWidget(page3);
|
stack_->addWidget(page3);
|
||||||
|
|
||||||
// 底部按钮。
|
Q_UNUSED(kCtrlRatio);
|
||||||
|
|
||||||
|
// 底部按钮:原版 justify-content:space-between,确认(主,左)/取消(右) 各 45%。
|
||||||
auto* btnLay = new QHBoxLayout();
|
auto* btnLay = new QHBoxLayout();
|
||||||
btnLay->addStretch();
|
btnLay->setSpacing(geopro::app::space::kMd);
|
||||||
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
okBtn_ = new QPushButton(QStringLiteral("确认"), this);
|
||||||
okBtn_ = new QPushButton(QStringLiteral("确定"), this);
|
|
||||||
okBtn_->setDefault(true);
|
okBtn_->setDefault(true);
|
||||||
btnLay->addWidget(cancelBtn);
|
auto* cancelBtn = new QPushButton(QStringLiteral("取消"), this);
|
||||||
btnLay->addWidget(okBtn_);
|
btnLay->addWidget(okBtn_, 45);
|
||||||
|
btnLay->addStretch(10);
|
||||||
|
btnLay->addWidget(cancelBtn, 45);
|
||||||
root->addLayout(btnLay);
|
root->addLayout(btnLay);
|
||||||
|
|
||||||
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
|
||||||
|
|
@ -144,11 +167,11 @@ void WhiteningDialog::onConfirm() {
|
||||||
p.dsObjectId = dsId_;
|
p.dsObjectId = dsId_;
|
||||||
p.whiteningMethod = methodCombo_->currentData().toInt();
|
p.whiteningMethod = methodCombo_->currentData().toInt();
|
||||||
if (p.whiteningMethod == 1) {
|
if (p.whiteningMethod == 1) {
|
||||||
p.boundaryExtension = extension_->value();
|
p.boundaryExtension = extension_->text().toDouble(); // 原版 Number(extension)||0
|
||||||
p.whiteningType = whiteningType_->checkedId();
|
p.whiteningType = whiteningType_->checkedId();
|
||||||
} else if (p.whiteningMethod == 2) {
|
} else if (p.whiteningMethod == 2) {
|
||||||
if (fileCombo_->currentIndex() < 0) {
|
if (fileCombo_->currentIndex() < 0) {
|
||||||
QMessageBox::warning(this, windowTitle(), QStringLiteral("请选择白化文件"));
|
QMessageBox::warning(this, windowTitle(), QStringLiteral("请选择一个白化文件"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p.whitenedDataId = fileCombo_->currentData().toString();
|
p.whitenedDataId = fileCombo_->currentData().toString();
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QDoubleSpinBox;
|
class QLineEdit;
|
||||||
class QButtonGroup;
|
class QButtonGroup;
|
||||||
class QStackedWidget;
|
class QStackedWidget;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
|
@ -38,7 +38,7 @@ private:
|
||||||
QComboBox* methodCombo_ = nullptr;
|
QComboBox* methodCombo_ = nullptr;
|
||||||
QStackedWidget* stack_ = nullptr;
|
QStackedWidget* stack_ = nullptr;
|
||||||
// 方式 1:
|
// 方式 1:
|
||||||
QDoubleSpinBox* extension_ = nullptr;
|
QLineEdit* extension_ = nullptr; // 原版 AInput 文本框(默认 "0")
|
||||||
QButtonGroup* whiteningType_ = nullptr; // 0 外部 / 1 内部
|
QButtonGroup* whiteningType_ = nullptr; // 0 外部 / 1 内部
|
||||||
// 方式 2:
|
// 方式 2:
|
||||||
QComboBox* fileCombo_ = nullptr;
|
QComboBox* fileCombo_ = nullptr;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue