#include "nmWxMeasuringScaleDlg.h" #include "iUnitWxBinder.h" #include "ZxBaseUtil.h" #include #include #include #include #include #include #include #include #include #include #include namespace { // 与储层参数常规字段一致;初始尺寸计算和实际布局使用同一比例。 const int s_nValueStretch = 8; const int s_nUnitStretch = 5; } nmWxMeasuringScaleDlg::nmWxMeasuringScaleDlg( QPointF startPoint, QPointF endPoint, double* pLength) : m_startPoint(startPoint), m_endPoint(endPoint), m_pLength(pLength), m_pLengthEdit(nullptr), m_bUnitBound(false) { // 坐标仅用于展示;数据由所属绘图窗口在标定成功后统一保存。 m_sStartPoint = QString("(%1, %2)").arg(m_startPoint.x()).arg(m_startPoint.y()); m_sEndPoint = QString("(%1, %2)").arg(m_endPoint.x()).arg(m_endPoint.y()); initUI(); setWindowTitle(tr("MeasuringScale setting")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // 按字体、主题及坐标内容选择初始大小,由 Qt 结合屏幕尺寸限制初始展开范围。 // 不固定窗口大小,长坐标仍可通过拉宽窗口或在只读框内移动光标查看。 adjustSize(); } QSize nmWxMeasuringScaleDlg::sizeHint() const { QSize preferredSize = iDlgBase::sizeHint(); const QComboBox* pLengthUnit = findChild("scaleLengthUnit"); if (m_pLengthEdit == nullptr || pLengthUnit == nullptr || !preferredSize.isValid()) { return preferredSize; } // 三个输入框共用一列;在布局推荐宽度上,为较长的坐标文本补足空间。 // 最小推荐宽度包含主题边框和内边距,扣除其字符宽度后可估算文本之外的留白。 const QFontMetrics metrics = m_pLengthEdit->fontMetrics(); const int nTextPadding = qMax(0, m_pLengthEdit->minimumSizeHint().width() - metrics.maxWidth()) + metrics.width(QLatin1String("00")); const int nCoordinateWidth = qMax(metrics.width(m_sStartPoint), metrics.width(m_sEndPoint)) + nTextPadding; // 输入列变宽时单位列也会按 8:5 伸展,初始推荐宽度需同时预留两列的空间。 const int nEditorHintWidth = m_pLengthEdit->sizeHint().width(); const int nUnitHintWidth = pLengthUnit->sizeHint().width(); const int nTotalStretch = s_nValueStretch + s_nUnitStretch; const int nWidthForCoordinates = (qMax(nCoordinateWidth, nEditorHintWidth) * nTotalStretch + s_nValueStretch - 1) / s_nValueStretch; const int nWidthForUnits = (nUnitHintWidth * nTotalStretch + s_nUnitStretch - 1) / s_nUnitStretch; preferredSize.rwidth() += qMax(0, qMax(nWidthForCoordinates, nWidthForUnits) - nEditorHintWidth - nUnitHintWidth); return preferredSize; } void nmWxMeasuringScaleDlg::initUI() { // 沿用编辑井、储层参数对话框的外边距,底部留白由按钮区统一负责。 QVBoxLayout* pMainLayout = new QVBoxLayout(this); pMainLayout->setContentsMargins(12, 10, 12, 0); pMainLayout->setSpacing(10); QGroupBox* pGroup = new QGroupBox(tr("Scale parameters"), this); // 与测量工具一致:分组只横向伸展,纵向使用字体和主题计算的内容高度。 pGroup->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); QGridLayout* pGrid = new QGridLayout(pGroup); pGrid->setContentsMargins(8, 15, 8, 10); pGrid->setHorizontalSpacing(6); pGrid->setVerticalSpacing(6); // 标签由文字决定宽度;输入框与单位下拉框沿用储层参数的 8:5 横向伸展比例。 pGrid->setColumnStretch(0, 0); pGrid->setColumnStretch(1, s_nValueStretch); pGrid->setColumnStretch(2, s_nUnitStretch); // 三行共用相同尺寸的输入框,标签不带冒号;坐标行保留空单位列以保证对齐。 const QStringList listLabels = QStringList() << tr("Start coordinates") << tr("End coordinates") << tr("Actual length"); QLineEdit* pEditors[3]; for (int nRow = 0; nRow < 3; ++nRow) { QLabel* pLabel = new QLabel(listLabels[nRow], pGroup); pLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); pLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); pGrid->addWidget(pLabel, nRow, 0); pEditors[nRow] = new QLineEdit(pGroup); pEditors[nRow]->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); // 输入列随窗口加宽;纵向 Fixed 采用主题推荐高度,不固定像素值。 pEditors[nRow]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); pGrid->addWidget(pEditors[nRow], nRow, 1); } // 坐标使用只读输入框,允许选中和复制;实际长度是唯一可编辑的数值。 pEditors[0]->setObjectName("scaleStartPoint"); pEditors[0]->setText(m_sStartPoint); pEditors[0]->setReadOnly(true); pEditors[1]->setObjectName("scaleEndPoint"); pEditors[1]->setText(m_sEndPoint); pEditors[1]->setReadOnly(true); m_pLengthEdit = pEditors[2]; m_pLengthEdit->setObjectName("scaleLength"); QComboBox* pLengthUnit = new QComboBox(pGroup); pLengthUnit->setObjectName("scaleLengthUnit"); // 随完整单位列表和字体计算宽度,窗口缩小时仍保留单位文字及下拉箭头。 pLengthUnit->setSizeAdjustPolicy(QComboBox::AdjustToContents); pLengthUnit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); pGrid->addWidget(pLengthUnit, 2, 2); // 以米作为单位组识别入口;参数标识为空时,框架按下拉框已有单位查找单位组。 // 完整单位列表、显示精度及切换换算均交给框架,不再使用旧控件的手写单位列表。 // 比例尺仅要求长度为有限正数,不借用井长参数,避免引入井参数专有的范围限制。 pLengthUnit->addItem("m"); m_bUnitBound = bindUnitPairWxs(m_pLengthEdit, pLengthUnit, QString(), false); m_bUnitBound = m_bUnitBound && m_pUnitBinder != nullptr; if (m_bUnitBound) { // 输入为米制基准值,显示文本由绑定器生成,不能把基准值直接当作显示单位值。 m_pUnitBinder->setBaseValue(m_pLengthEdit, m_pLength ? *m_pLength : 0.0); } m_pLengthEdit->setEnabled(m_bUnitBound); pLengthUnit->setEnabled(m_bUnitBound); pMainLayout->addWidget(pGroup); // 纵向余量由分组与底部按钮之间的布局空间吸收,不拉长输入框或行间距。 pMainLayout->addStretch(1); // 使用标准按钮框和框架图标,与其他已统一的参数对话框保持相同的底部布局。 QWidget* pFooter = new QWidget(this); pFooter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QHBoxLayout* pFooterLayout = new QHBoxLayout(pFooter); pFooterLayout->setContentsMargins(4, 5, 4, 5); pFooterLayout->setSpacing(8); pFooterLayout->addStretch(); QDialogButtonBox* pButtons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, pFooter); QPushButton* pOk = pButtons->button(QDialogButtonBox::Ok); pOk->setText(tr("OK")); pOk->setIcon(zxLoadIcon("OK")); pOk->setDefault(true); QPushButton* pCancel = pButtons->button(QDialogButtonBox::Cancel); pCancel->setText(tr("Cancel")); pCancel->setIcon(zxLoadIcon("Cancel")); pFooterLayout->addWidget(pButtons); pMainLayout->addWidget(pFooter); connect(pButtons, SIGNAL(accepted()), this, SLOT(accept())); connect(pButtons, SIGNAL(rejected()), this, SLOT(reject())); if (!m_bUnitBound) { // 单位服务不可用时保留取消入口,并明确提示原因,禁止按错误单位提交。 QLabel* pError = new QLabel(tr("Length units are unavailable."), this); pError->setWordWrap(true); pMainLayout->insertWidget(1, pError); pOk->setEnabled(false); } // 打开后可直接输入实际长度,替换调用方传入的初始值。 m_pLengthEdit->setFocus(); m_pLengthEdit->selectAll(); } void nmWxMeasuringScaleDlg::accept() { // 仅确认时向调用方返回米制长度;对话框不直接修改分析数据或坐标轴。 if (!m_bUnitBound || m_pLength == nullptr) { return; } // 校验当前输入并取得米制基准值,避免直接读取显示文本后将英尺等单位误当作米。 // 绘图区使用长度计算缩放比例,因此还需拒绝零值、负值及非有限数值。 double dLength = 0.0; if (!m_pUnitBinder->isInputOK(m_pLengthEdit, true, &dLength) || !qIsFinite(dLength) || dLength <= 0.0) { // 无效长度不提交,也不增加校验提示;保留输入焦点,便于用户直接修改。 m_pLengthEdit->setFocus(); m_pLengthEdit->selectAll(); return; } // 调用方还需检查缩放结果,成功后才能一起提交轴范围和比例尺数据。 *m_pLength = dLength; iDlgBase::accept(); }