You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
9.0 KiB
C++
206 lines
9.0 KiB
C++
#include "nmWxMeasuringScaleDlg.h"
|
|
|
|
#include "iUnitWxBinder.h"
|
|
#include "ZxBaseUtil.h"
|
|
|
|
#include <QComboBox>
|
|
#include <QDialogButtonBox>
|
|
#include <QFontMetrics>
|
|
#include <QGridLayout>
|
|
#include <QGroupBox>
|
|
#include <QHBoxLayout>
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QPushButton>
|
|
#include <QVBoxLayout>
|
|
#include <qnumeric.h>
|
|
|
|
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<QComboBox*>("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();
|
|
}
|