feat(detail): 色阶编辑器另存覆盖 + 散点模板库可用(1:1)
- IColorTemplateRepository/Api 加 updateLvlTemplate(PUT /business/lvlTemplate
{id,templateName,properties}),对照原版 updateLvlTemplate
- ColorScaleConfigDialog 另存为改自定义弹窗:名称+「覆盖原模板」复选(仅 lvlTemplateId
非空可勾)→勾选 updateLvlTemplate / 否则 saveLvlTemplate;ctor 增 lvlTemplateId(默认空)
- 散点路径接通模板库:工厂给 Scatter 视图注入 colorTplRepo,构造色阶编辑器传
colorTplRepo+projectId+data_.templateId→另存/打开/覆盖可用(原 nullptr 禁用)
- 3D 体色阶编辑器(main.cpp)及网格(GridDataChartView)用默认空 templateId,行为不变
build all 绿,336/336。
This commit is contained in:
parent
0212fb5d2e
commit
3dfe8b54f5
|
|
@ -97,14 +97,16 @@ ColorScaleConfigDialog::ColorScaleConfigDialog(const geopro::core::ColorScale& i
|
|||
double vmax, std::vector<double> samples,
|
||||
const ContourLineConfig& lineInit,
|
||||
geopro::data::IColorTemplateRepository* tplRepo,
|
||||
QString projectId, QWidget* parent)
|
||||
QString projectId, QString lvlTemplateId,
|
||||
QWidget* parent)
|
||||
: QDialog(parent),
|
||||
vmin_(vmin),
|
||||
vmax_(vmax),
|
||||
samples_(std::move(samples)),
|
||||
lineCfg_(lineInit),
|
||||
tplRepo_(tplRepo),
|
||||
projectId_(std::move(projectId)) {
|
||||
projectId_(std::move(projectId)),
|
||||
lvlTemplateId_(std::move(lvlTemplateId)) {
|
||||
setWindowTitle(QStringLiteral("色阶配置"));
|
||||
setModal(true);
|
||||
resize(560, 420);
|
||||
|
|
@ -433,11 +435,31 @@ void ColorScaleConfigDialog::loadColorBar(
|
|||
|
||||
void ColorScaleConfigDialog::onSaveOther() {
|
||||
if (tplRepo_ == nullptr || projectId_.isEmpty()) return;
|
||||
bool ok = false;
|
||||
const QString name = QInputDialog::getText(this, QStringLiteral("另存模板配置"),
|
||||
QStringLiteral("模板名称:"), QLineEdit::Normal,
|
||||
QStringLiteral("等值线配置.lvl"), &ok);
|
||||
if (!ok || name.trimmed().isEmpty()) return;
|
||||
|
||||
// 自定义另存为弹窗(复刻 handleSaveOther):名称输入 + 覆盖复选框。
|
||||
// 「覆盖」仅当有来源模板 id(lvlTemplateId_ 非空)时可勾选,对照原版 props.data.lvlTemplateId。
|
||||
QDialog askDlg(this);
|
||||
askDlg.setWindowTitle(QStringLiteral("另存模板配置"));
|
||||
askDlg.setModal(true);
|
||||
auto* askRoot = new QVBoxLayout(&askDlg);
|
||||
auto* nameRow = new QHBoxLayout();
|
||||
nameRow->addWidget(new QLabel(QStringLiteral("模板名称:"), &askDlg));
|
||||
auto* nameEdit = new QLineEdit(QStringLiteral("等值线配置.lvl"), &askDlg);
|
||||
nameRow->addWidget(nameEdit, 1);
|
||||
askRoot->addLayout(nameRow);
|
||||
auto* overwriteCheck = new QCheckBox(QStringLiteral("覆盖原模板"), &askDlg);
|
||||
overwriteCheck->setEnabled(!lvlTemplateId_.isEmpty()); // 无来源模板 → 禁用覆盖
|
||||
askRoot->addWidget(overwriteCheck);
|
||||
auto* askBtns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &askDlg);
|
||||
askBtns->button(QDialogButtonBox::Ok)->setText(QStringLiteral("应用"));
|
||||
askBtns->button(QDialogButtonBox::Cancel)->setText(QStringLiteral("取消"));
|
||||
connect(askBtns, &QDialogButtonBox::accepted, &askDlg, &QDialog::accept);
|
||||
connect(askBtns, &QDialogButtonBox::rejected, &askDlg, &QDialog::reject);
|
||||
askRoot->addWidget(askBtns);
|
||||
if (askDlg.exec() != QDialog::Accepted) return;
|
||||
const QString name = nameEdit->text().trimmed();
|
||||
if (name.isEmpty()) return;
|
||||
const bool overwrite = overwriteCheck->isChecked() && !lvlTemplateId_.isEmpty();
|
||||
|
||||
// 组装 properties(复刻 handleSaveOther)。
|
||||
QJsonArray colorBar;
|
||||
|
|
@ -457,18 +479,22 @@ void ColorScaleConfigDialog::onSaveOther() {
|
|||
{QStringLiteral("colorBar"), colorBar}};
|
||||
|
||||
// 走仓储传输;回调里用 QPointer 守卫 this(模态对话框可能已关)。
|
||||
// 勾选覆盖 → PUT 更新来源模板(updateLvlTemplate);否则 → POST 新建(saveLvlTemplate)。
|
||||
QPointer<ColorScaleConfigDialog> self(this);
|
||||
tplRepo_->saveLvlTemplate(projectId_, name.trimmed(), properties,
|
||||
[self](bool ok, QString msg) {
|
||||
auto onDone = [self, overwrite](bool ok, QString msg) {
|
||||
if (!self) return;
|
||||
if (ok)
|
||||
QMessageBox::information(self, QStringLiteral("另存"),
|
||||
QStringLiteral("另存成功。"));
|
||||
else
|
||||
QMessageBox::warning(
|
||||
QMessageBox::information(
|
||||
self, QStringLiteral("另存"),
|
||||
overwrite ? QStringLiteral("更新成功。") : QStringLiteral("另存成功。"));
|
||||
else
|
||||
QMessageBox::warning(self, QStringLiteral("另存"),
|
||||
QStringLiteral("另存失败:%1").arg(msg));
|
||||
});
|
||||
};
|
||||
if (overwrite)
|
||||
tplRepo_->updateLvlTemplate(lvlTemplateId_, name, properties, std::move(onDone));
|
||||
else
|
||||
tplRepo_->saveLvlTemplate(projectId_, name, properties, std::move(onDone));
|
||||
}
|
||||
|
||||
void ColorScaleConfigDialog::onOpen() {
|
||||
|
|
|
|||
|
|
@ -29,12 +29,15 @@ public:
|
|||
// init:当前色阶(升序断点填表);vmin/vmax:数据原始范围(层级/颜色子对话框 + 新增外推用);
|
||||
// samples:数据原始标量(等积分层 + 颜色编辑器直方图用,空则等积退化为线性);
|
||||
// lineInit:线形/标注初值(2D 传当前态,3D 用默认);
|
||||
// tplRepo/projectId:lvl 模板库仓储句柄(可空 → 另存为/打开 禁用)。
|
||||
// tplRepo/projectId:lvl 模板库仓储句柄(可空 → 另存为/打开 禁用);
|
||||
// lvlTemplateId:当前色阶来源模板 id(可空,对照原版 props.data.lvlTemplateId)。
|
||||
// 非空时「另存为」弹窗的「覆盖」复选框可勾选 → 走 PUT 更新该模板;3D/无模板场景不传即可。
|
||||
ColorScaleConfigDialog(const geopro::core::ColorScale& init, double vmin, double vmax,
|
||||
std::vector<double> samples = {},
|
||||
const ContourLineConfig& lineInit = {},
|
||||
geopro::data::IColorTemplateRepository* tplRepo = nullptr,
|
||||
QString projectId = {}, QWidget* parent = nullptr);
|
||||
QString projectId = {}, QString lvlTemplateId = {},
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
// 由表格当前断点装配的新色阶(按层级升序 addStop)。
|
||||
geopro::core::ColorScale colorScale() const;
|
||||
|
|
@ -74,6 +77,7 @@ private:
|
|||
|
||||
geopro::data::IColorTemplateRepository* tplRepo_ = nullptr; // lvl 模板库仓储(可空)
|
||||
QString projectId_;
|
||||
QString lvlTemplateId_; // 当前色阶来源模板 id(可空 → 另存为弹窗禁用「覆盖」)
|
||||
// 随子对话框更新、写入另存为 properties(复刻原版透传字段)。
|
||||
QString lvlSchemeType_ = QStringLiteral("normal");
|
||||
int logLinesCount_ = 8;
|
||||
|
|
|
|||
|
|
@ -807,10 +807,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
|||
}
|
||||
// 3D 无等值线,线形/标注配置忽略(用默认);仅取色阶应用。
|
||||
// 「另存为/打开」与「新建色阶/配色方案」走色阶模板仓储,projectId 取当前项目。
|
||||
// 3D 体无来源 lvl 模板 → lvlTemplateId 传空(覆盖复选框禁用,行为不变)。
|
||||
geopro::app::ColorScaleConfigDialog dlg(
|
||||
sceneView->currentColorScale(), sceneView->currentVmin(),
|
||||
sceneView->currentVmax(), std::move(samples), {}, &colorTplRepo,
|
||||
nav.currentProjectId(), &window);
|
||||
nav.currentProjectId(), QString(), &window);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
sceneCtrl->setVolumeColorScale(dsId, dlg.colorScale());
|
||||
});
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ std::unique_ptr<IDetailView> makeDetailView(controller::ViewKind kind, QWidget*
|
|||
auto* raw = new RawDataChartView(parent);
|
||||
// 注入反演命令仓储 + dsId/projectId 取值回调(measurement 反演运算/生成视电阻率)。
|
||||
raw->setCommandRepo(cmdRepo, dsIdGetter, projectIdGetter);
|
||||
// 注入色阶模板仓储(散点「色阶配置」编辑器另存为/打开/覆盖用;projectId 复用上面的 getter)。
|
||||
raw->setColorTemplateRepo(colorTplRepo);
|
||||
return std::unique_ptr<IDetailView>(raw);
|
||||
}
|
||||
case controller::ViewKind::FilledContour: {
|
||||
|
|
|
|||
|
|
@ -318,8 +318,9 @@ void GridDataChartView::openColorScaleEditor() {
|
|||
|
||||
// projectId 在打开时取一次(随项目切换生效);无 getter 退化为空 → 后端按钮禁用。
|
||||
const QString projectId = projectIdGetter_ ? projectIdGetter_() : QString();
|
||||
// 网格剖面载荷(ContourPayload)无 templateId 字段 → lvlTemplateId 传空(覆盖复选框禁用)。
|
||||
ColorScaleConfigDialog dlg(gridScale_, grid_.vmin, grid_.vmax, std::move(samples), lineCfg_,
|
||||
tplRepo_, projectId, this);
|
||||
tplRepo_, projectId, QString(), this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
|
||||
gridScale_ = dlg.colorScale();
|
||||
|
|
|
|||
|
|
@ -352,6 +352,10 @@ void RawDataChartView::setCommandRepo(geopro::data::IDatasetCommandRepository* r
|
|||
projectIdGetter_ = std::move(projectIdGetter);
|
||||
}
|
||||
|
||||
void RawDataChartView::setColorTemplateRepo(geopro::data::IColorTemplateRepository* repo) {
|
||||
colorTplRepo_ = repo;
|
||||
}
|
||||
|
||||
void RawDataChartView::openInversionDialog(bool apparentResistivity, QWidget* anchor) {
|
||||
// 无仓储/无 dsId 取值回调 → 退化占位(与未注入时一致)。
|
||||
const QString dsId = dsIdGetter_ ? dsIdGetter_() : QString();
|
||||
|
|
@ -388,7 +392,10 @@ void RawDataChartView::openInversionColorScale(QWidget* anchor) {
|
|||
}
|
||||
if (vMin > vMax) { vMin = 0.0; vMax = 1.0; }
|
||||
std::vector<double> samples = data_.scatter.v;
|
||||
ColorScaleConfigDialog dlg(data_.scale, vMin, vMax, std::move(samples), {}, nullptr, {}, this);
|
||||
// 接通色阶模板库:注入仓储 + 当前 projectId + 载荷 templateId(另存为/打开/覆盖 可用)。
|
||||
ColorScaleConfigDialog dlg(data_.scale, vMin, vMax, std::move(samples), {}, colorTplRepo_,
|
||||
projectIdGetter_ ? projectIdGetter_() : QString(), data_.templateId,
|
||||
this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
|
||||
// 本地重建上色重绘。
|
||||
|
|
@ -565,8 +572,10 @@ void RawDataChartView::openScatterColorScale(QWidget* anchor) {
|
|||
if (vMin > vMax) { vMin = 0.0; vMax = 1.0; }
|
||||
std::vector<double> samples = data_.scatter.v; // 直方图/等积分层用原始标量
|
||||
|
||||
// 散点无独立 lvl 模板仓储(视图只持命令仓储)→ tplRepo 传空(另存为/打开 禁用)。
|
||||
ColorScaleConfigDialog dlg(data_.scale, vMin, vMax, std::move(samples), {}, nullptr, {}, this);
|
||||
// 接通色阶模板库:注入仓储 + 当前 projectId + 载荷 templateId(另存为/打开/覆盖 可用)。
|
||||
ColorScaleConfigDialog dlg(data_.scale, vMin, vMax, std::move(samples), {}, colorTplRepo_,
|
||||
projectIdGetter_ ? projectIdGetter_() : QString(), data_.templateId,
|
||||
this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
|
||||
// 本地重建 colorSvc_ 重绘散点(M8 即时生效)。
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class QwtPlotRescaler;
|
|||
|
||||
namespace geopro::data {
|
||||
class IDatasetCommandRepository;
|
||||
class IColorTemplateRepository;
|
||||
}
|
||||
|
||||
namespace geopro::app {
|
||||
|
|
@ -47,6 +48,10 @@ public:
|
|||
std::function<QString()> dsIdGetter,
|
||||
std::function<QString()> projectIdGetter);
|
||||
|
||||
// 注入色阶模板仓储(散点「色阶配置」编辑器「另存为/打开/覆盖」用;projectId 复用
|
||||
// setCommandRepo 注入的 projectIdGetter_)。可传空 → 编辑器后端按钮禁用。
|
||||
void setColorTemplateRepo(geopro::data::IColorTemplateRepository* repo);
|
||||
|
||||
protected:
|
||||
// 信息模式(M13)下捕获画布点击:找最近散点显示属性。其余事件不消费。
|
||||
bool eventFilter(QObject* obj, QEvent* ev) override;
|
||||
|
|
@ -123,6 +128,8 @@ private:
|
|||
geopro::data::IDatasetCommandRepository* cmdRepo_ = nullptr;
|
||||
std::function<QString()> dsIdGetter_;
|
||||
std::function<QString()> projectIdGetter_;
|
||||
// 色阶模板仓储(注入;空则编辑器「另存为/打开」禁用)。
|
||||
geopro::data::IColorTemplateRepository* colorTplRepo_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace geopro::app
|
||||
|
|
|
|||
|
|
@ -35,6 +35,24 @@ void ApiColorTemplateRepository::saveLvlTemplate(const QString& projectId,
|
|||
});
|
||||
}
|
||||
|
||||
void ApiColorTemplateRepository::updateLvlTemplate(const QString& id,
|
||||
const QString& templateName,
|
||||
const QJsonObject& properties,
|
||||
std::function<void(bool, QString)> cb) {
|
||||
QJsonObject body{{QStringLiteral("id"), id},
|
||||
{QStringLiteral("templateName"), templateName},
|
||||
{QStringLiteral("properties"), properties}};
|
||||
auto* call = api_.putJsonAsync(QStringLiteral("/business/lvlTemplate"), body);
|
||||
if (call == nullptr) {
|
||||
if (cb) cb(false, QStringLiteral("请求创建失败"));
|
||||
return;
|
||||
}
|
||||
QObject::connect(call, &net::IApiCall::finished, call,
|
||||
[cb = std::move(cb)](const net::ApiResponse& resp) {
|
||||
if (cb) cb(isOk(resp), resp.msg);
|
||||
});
|
||||
}
|
||||
|
||||
void ApiColorTemplateRepository::listLvlTemplates(
|
||||
const QString& projectId, std::function<void(bool, QJsonArray, QString)> cb) {
|
||||
QJsonObject body{{QStringLiteral("projectId"), projectId},
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ public:
|
|||
void saveLvlTemplate(const QString& projectId, const QString& templateName,
|
||||
const QJsonObject& properties,
|
||||
std::function<void(bool ok, QString msg)> cb) override;
|
||||
void updateLvlTemplate(const QString& id, const QString& templateName,
|
||||
const QJsonObject& properties,
|
||||
std::function<void(bool ok, QString msg)> cb) override;
|
||||
void listLvlTemplates(const QString& projectId,
|
||||
std::function<void(bool ok, QJsonArray list, QString msg)> cb) override;
|
||||
void newClrScheme(const QString& projectId, const QJsonObject& properties,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@ public:
|
|||
const QJsonObject& properties,
|
||||
std::function<void(bool ok, QString msg)> cb) = 0;
|
||||
|
||||
// 覆盖更新 lvl 模板:PUT /business/lvlTemplate(body {id, templateName, properties})。
|
||||
// 复刻原版 updateLvlTemplate(另存为弹窗勾选「覆盖」时调用,id=当前模板 lvlTemplateId)。
|
||||
virtual void updateLvlTemplate(const QString& id, const QString& templateName,
|
||||
const QJsonObject& properties,
|
||||
std::function<void(bool ok, QString msg)> cb) = 0;
|
||||
|
||||
// 列 lvl 模板:POST /business/lvlTemplate/page(pageNo=1,pageSize=1000)。
|
||||
// 回调 list = 响应 data.list 数组(每项含 templateName/properties)。
|
||||
virtual void listLvlTemplates(const QString& projectId,
|
||||
|
|
|
|||
Loading…
Reference in New Issue