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.
nmWTAI-Platform/Src/nmNum/nmSubWxs/nmReservoirParameterField.cpp

488 lines
14 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmReservoirParameterField.h"
#include "iParaItemCtrl.h"
#include "iParameter.h"
#include "iSysParaHelper.h"
#include "mModuleDefines.h"
#include <QComboBox>
#include <QCoreApplication>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPalette>
#include <QSizePolicy>
namespace
{
/* Qt 4.8的lupdate需要显式标记间接翻译字符串。 */
static const char* const s_pFieldTranslationMarkers[] =
{
QT_TRANSLATE_NOOP("nmReservoirParameterField", "The parameter layout is unavailable."),
QT_TRANSLATE_NOOP("nmReservoirParameterField", "Parameter definition not found: %1"),
QT_TRANSLATE_NOOP("nmReservoirParameterField", "Failed to bind the unit for parameter: %1")
};
/** @brief 返回轻量字段类使用的翻译文字。 */
QString fieldText(const char* pText)
{
Q_UNUSED(s_pFieldTranslationMarkers);
return QCoreApplication::translate(
"nmReservoirParameterField", pText);
}
/** @brief 根据有效状态生成悬浮提示文字。 */
QString validationToolTip(const QString& sText, bool bValid)
{
if (bValid)
{
return sText;
}
QString sEscaped = sText;
sEscaped.replace("&", "&amp;");
sEscaped.replace("<", "&lt;");
sEscaped.replace(">", "&gt;");
sEscaped.replace("\"", "&quot;");
sEscaped.replace("\n", "<br/>");
return "<span style=\"color:red;\">" +
sEscaped + "</span>";
}
}
nmReservoirParameterField::nmReservoirParameterField(
const nmReservoirParameterFieldInfo& oFieldInfo,
nmIReservoirParameterUnitService* pUnitService,
QObject* pParent)
: QObject(pParent),
m_oFieldInfo(oFieldInfo),
m_pUnitService(pUnitService),
m_pParameter(nullptr),
m_pLabel(nullptr),
m_pLineEdit(nullptr),
m_pValueComboBox(nullptr),
m_pUnitComboBox(nullptr),
m_pUnitLabel(nullptr),
m_clrNormalText(),
m_sExternalValidationError(),
m_bVisible(true),
m_bUpdating(false)
{
}
nmReservoirParameterField::~nmReservoirParameterField()
{
m_pUnitService = nullptr;
m_pParameter = nullptr;
m_pLabel = nullptr;
m_pLineEdit = nullptr;
m_pValueComboBox = nullptr;
m_pUnitComboBox = nullptr;
m_pUnitLabel = nullptr;
}
bool nmReservoirParameterField::initialize(QGridLayout* pLayout,
int nRow,
int nColumnOffset,
QString& sError)
{
if (pLayout == nullptr)
{
sError = fieldText("The parameter layout is unavailable.");
return false;
}
// 第一步枚举字段不依赖XML数值定义直接创建稳定code下拉框。
if (isEnum())
{
createEnumEditor(pLayout, nRow, nColumnOffset);
sError.clear();
return true;
}
// 第二步数值字段必须取得NM系列的基础参数定义。
m_pParameter = _paraHelper->getPara(
m_oFieldInfo.m_sBaseParameterId, s_Nm_Serie);
if (m_pParameter == nullptr)
{
sError = fieldText("Parameter definition not found: %1")
.arg(m_oFieldInfo.m_sBaseParameterId);
return false;
}
// 第三步:创建原型中的标签、输入框和单位列,不增加字段外框。
return createNumericEditor(pLayout, nRow, nColumnOffset, sError);
}
QString nmReservoirParameterField::parameterId() const
{
return m_oFieldInfo.m_sParameterId;
}
QString nmReservoirParameterField::baseParameterId() const
{
return m_oFieldInfo.m_sBaseParameterId;
}
bool nmReservoirParameterField::isEnum() const
{
return m_oFieldInfo.m_eEditorType == NM_RESERVOIR_EDITOR_ENUM;
}
void nmReservoirParameterField::setValueRightAligned(bool bRightAligned)
{
if (m_pLineEdit != nullptr)
{
m_pLineEdit->setAlignment(
(bRightAligned ? Qt::AlignRight : Qt::AlignLeft) |
Qt::AlignVCenter);
}
}
int nmReservoirParameterField::editorMinimumWidth()
{
return 140;
}
int nmReservoirParameterField::unitMinimumWidth()
{
return 86;
}
int nmReservoirParameterField::editorHeight()
{
return 25;
}
bool nmReservoirParameterField::createNumericEditor(
QGridLayout* pLayout,
int nRow,
int nColumnOffset,
QString& sError)
{
QWidget* pParentWidget = pLayout->parentWidget();
m_pLabel = new QLabel(m_pParameter->m_sAlias, pParentWidget);
m_pLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
m_pLabel->setWordWrap(false);
m_pLabel->setSizePolicy(QSizePolicy::Preferred,
QSizePolicy::Fixed);
m_pLineEdit = new QLineEdit(pParentWidget);
m_clrNormalText = m_pLineEdit->palette().color(QPalette::Text);
m_pLineEdit->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
m_pLineEdit->setFixedHeight(editorHeight());
m_pLineEdit->setMinimumWidth(editorMinimumWidth());
m_pLineEdit->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed);
pLayout->addWidget(m_pLabel, nRow, nColumnOffset);
pLayout->addWidget(m_pLineEdit, nRow, nColumnOffset + 1);
// 有单位参数直接注册到主对话框绑定器;字段只按控件指针读写,
// 因此多口井共用同一基础参数ID时也不会发生串值。
if (m_oFieldInfo.m_bUnitEnabled &&
!m_pParameter->m_sUnit.isEmpty())
{
m_pUnitComboBox = new QComboBox(pParentWidget);
m_pUnitComboBox->setFixedHeight(editorHeight());
m_pUnitComboBox->setMinimumWidth(unitMinimumWidth());
m_pUnitComboBox->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed);
pLayout->addWidget(m_pUnitComboBox, nRow, nColumnOffset + 2);
if (m_pUnitService == nullptr ||
!m_pUnitService->bindUnitField(
m_pLineEdit,
m_pUnitComboBox,
m_oFieldInfo.m_sBaseParameterId))
{
sError = fieldText(
"Failed to bind the unit for parameter: %1")
.arg(m_oFieldInfo.m_sBaseParameterId);
return false;
}
}
else
{
// 无单位参数保留空列用于对齐,不显示额外的单位说明文字。
m_pUnitLabel = new QLabel(pParentWidget);
m_pUnitLabel->setMinimumWidth(unitMinimumWidth());
m_pUnitLabel->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed);
pLayout->addWidget(m_pUnitLabel, nRow, nColumnOffset + 2);
}
updateValidationAppearance(true);
sError.clear();
return true;
}
void nmReservoirParameterField::createEnumEditor(QGridLayout* pLayout,
int nRow,
int nColumnOffset)
{
QWidget* pParentWidget = pLayout->parentWidget();
m_pLabel = new QLabel(m_oFieldInfo.m_sLabel, pParentWidget);
m_pLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
m_pLabel->setWordWrap(false);
m_pLabel->setSizePolicy(QSizePolicy::Preferred,
QSizePolicy::Fixed);
m_pValueComboBox = new QComboBox(pParentWidget);
m_pValueComboBox->setFixedHeight(editorHeight());
m_pValueComboBox->setMinimumWidth(editorMinimumWidth());
m_pValueComboBox->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed);
for (int nIndex = 0;
nIndex < m_oFieldInfo.m_listOptions.size();
++nIndex)
{
const nmReservoirEnumOption& oOption =
m_oFieldInfo.m_listOptions[nIndex];
m_pValueComboBox->addItem(oOption.m_sText, oOption.m_sCode);
}
// 枚举参数没有单位,空白单位列仅用于保持各行编辑器对齐。
m_pUnitLabel = new QLabel(pParentWidget);
m_pUnitLabel->setMinimumWidth(unitMinimumWidth());
m_pUnitLabel->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Fixed);
pLayout->addWidget(m_pLabel, nRow, nColumnOffset);
pLayout->addWidget(m_pValueComboBox, nRow, nColumnOffset + 1);
pLayout->addWidget(m_pUnitLabel, nRow, nColumnOffset + 2);
}
void nmReservoirParameterField::setBaseValue(const QVariant& oValue)
{
if (m_pLineEdit == nullptr || !oValue.isValid())
{
return;
}
m_bUpdating = true;
double dValue = oValue.toDouble();
if (m_pUnitComboBox != nullptr && m_pUnitService != nullptr)
{
m_pUnitService->setUnitBaseValue(m_pLineEdit, dValue);
}
else
{
m_pLineEdit->setText(formatBaseValue(dValue));
}
m_bUpdating = false;
validate();
}
QVariant nmReservoirParameterField::baseValue(bool& bValid)
{
bValid = validate();
if (!bValid || m_pLineEdit == nullptr)
{
return QVariant();
}
if (m_pUnitComboBox != nullptr && m_pUnitService != nullptr)
{
return QVariant(m_pUnitService->unitBaseValue(m_pLineEdit));
}
bool bNumberOk = false;
double dValue = m_pLineEdit->text().trimmed().toDouble(&bNumberOk);
return bNumberOk ? QVariant(dValue) : QVariant();
}
void nmReservoirParameterField::setEnumCode(const QString& sCode)
{
if (m_pValueComboBox == nullptr)
{
return;
}
int nIndex = m_pValueComboBox->findData(sCode);
m_bUpdating = true;
m_pValueComboBox->setCurrentIndex(nIndex >= 0 ? nIndex : 0);
m_bUpdating = false;
}
QString nmReservoirParameterField::enumCode() const
{
if (m_pValueComboBox == nullptr ||
m_pValueComboBox->currentIndex() < 0)
{
return QString();
}
return m_pValueComboBox->itemData(
m_pValueComboBox->currentIndex()).toString();
}
void nmReservoirParameterField::setExternalValidationError(
const QString& sError)
{
m_sExternalValidationError = sError;
validate();
}
bool nmReservoirParameterField::validate()
{
if (!m_bVisible || isEnum())
{
return true;
}
if (m_pLineEdit == nullptr || m_pParameter == nullptr)
{
return false;
}
bool bValid = false;
if (m_pUnitComboBox != nullptr && m_pUnitService != nullptr)
{
bValid = m_pUnitService->isUnitInputValid(m_pLineEdit);
}
else
{
bool bNumberOk = false;
double dValue = m_pLineEdit->text().trimmed()
.toDouble(&bNumberOk);
bValid = bNumberOk && dValue == dValue &&
dValue >= m_pParameter->m_dMin &&
dValue <= m_pParameter->m_dMax;
if (bValid &&
m_oFieldInfo.m_eEditorType == NM_RESERVOIR_EDITOR_INTEGER)
{
bValid = dValue == static_cast<int>(dValue);
}
}
bValid = bValid && m_sExternalValidationError.isEmpty();
updateValidationAppearance(bValid);
return bValid;
}
void nmReservoirParameterField::setFieldVisible(bool bVisible)
{
m_bVisible = bVisible;
if (m_pLabel != nullptr)
{
m_pLabel->setVisible(bVisible);
}
if (m_pLineEdit != nullptr)
{
m_pLineEdit->setVisible(bVisible);
}
if (m_pValueComboBox != nullptr)
{
m_pValueComboBox->setVisible(bVisible);
}
if (m_pUnitComboBox != nullptr)
{
m_pUnitComboBox->setVisible(bVisible);
}
if (m_pUnitLabel != nullptr)
{
m_pUnitLabel->setVisible(bVisible);
}
}
bool nmReservoirParameterField::isFieldVisible() const
{
return m_bVisible;
}
QLineEdit* nmReservoirParameterField::valueEditor() const
{
return m_pLineEdit;
}
QComboBox* nmReservoirParameterField::enumEditor() const
{
return m_pValueComboBox;
}
QString nmReservoirParameterField::formatBaseValue(double dValue) const
{
if (m_pParameter == nullptr)
{
return QString::number(dValue, 'g', 15);
}
if (m_oFieldInfo.m_eEditorType == NM_RESERVOIR_EDITOR_INTEGER ||
m_pParameter->m_nDigit == 0)
{
return QString::number(dValue, 'f', 0);
}
if (m_pParameter->m_bScientific)
{
return QString::number(dValue, 'e', m_pParameter->m_nDigit);
}
QString sValue = QString::number(
dValue, 'f', m_pParameter->m_nDigit);
while (sValue.contains('.') && sValue.endsWith('0'))
{
sValue.chop(1);
}
if (sValue.endsWith('.'))
{
sValue.chop(1);
}
return sValue;
}
void nmReservoirParameterField::updateValidationAppearance(bool bValid)
{
if (m_pLineEdit == nullptr || m_pParameter == nullptr)
{
return;
}
// 只修改文字色避免Qt 4.8样式表绘制覆盖原生输入框边框。
QPalette oPalette = m_pLineEdit->palette();
oPalette.setColor(QPalette::Text,
bValid ? m_clrNormalText : QColor(Qt::red));
m_pLineEdit->setPalette(oPalette);
QString sCurrentUnit;
iUnitGroup* pUnitGroup = nullptr;
if (m_pUnitComboBox != nullptr && m_pUnitService != nullptr)
{
sCurrentUnit = m_pUnitService->currentUnit(m_pLineEdit);
pUnitGroup = m_pUnitService->unitGroup(m_pLineEdit);
}
QString sRange = iParaItemCtrl::getScaleStrOf(
m_pParameter, sCurrentUnit, pUnitGroup);
// 参数别名来自当前语言XML稳定ID便于定位参数定义。
QString sHelp = m_pParameter->m_sAlias;
if (!m_pParameter->m_sName.isEmpty())
{
if (!sHelp.isEmpty())
{
sHelp += "[" + m_pParameter->m_sName + "]";
}
else
{
sHelp = m_pParameter->m_sName;
}
}
if (!sRange.isEmpty())
{
if (!sHelp.isEmpty())
{
sHelp += "\n";
}
sHelp += sRange;
}
if (!m_sExternalValidationError.isEmpty())
{
if (!sHelp.isEmpty())
{
sHelp += "\n";
}
sHelp += m_sExternalValidationError;
}
m_pLineEdit->setToolTip(validationToolTip(sHelp, bValid));
m_pLineEdit->setWhatsThis(sHelp);
if (m_pLabel != nullptr)
{
m_pLabel->setWhatsThis(sHelp);
}
}