|
|
|
|
|
#include "nmParameterField.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "iParaItemCtrl.h"
|
|
|
|
|
|
#include "iParameter.h"
|
|
|
|
|
|
#include "iSysParaHelper.h"
|
|
|
|
|
|
#include "iUnitHelper.h"
|
|
|
|
|
|
#include "mModuleDefines.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QComboBox>
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
|
#include <QGridLayout>
|
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
|
#include <QPalette>
|
|
|
|
|
|
#include <QSizePolicy>
|
|
|
|
|
|
#include <QStringList>
|
|
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/* Qt 4.8的lupdate需要显式标记间接翻译字符串。 */
|
|
|
|
|
|
static const char* const s_pFieldTranslationMarkers[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmParameterField", "The parameter layout is unavailable."),
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmParameterField", "Parameter definition not found: %1"),
|
|
|
|
|
|
QT_TRANSLATE_NOOP("nmParameterField", "Failed to bind the unit for parameter: %1")
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
QString fieldText(const char* pText)
|
|
|
|
|
|
{
|
|
|
|
|
|
Q_UNUSED(s_pFieldTranslationMarkers);
|
|
|
|
|
|
return QCoreApplication::translate("nmParameterField", pText);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString validationToolTip(const QString& sText, bool bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
return sText;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 无效提示使用富文本着色,业务文本必须先转义以免被当作HTML解析。
|
|
|
|
|
|
QString sEscaped = sText;
|
|
|
|
|
|
sEscaped.replace("&", "&");
|
|
|
|
|
|
sEscaped.replace("<", "<");
|
|
|
|
|
|
sEscaped.replace(">", ">");
|
|
|
|
|
|
sEscaped.replace("\"", """);
|
|
|
|
|
|
sEscaped.replace("\n", "<br/>");
|
|
|
|
|
|
return "<span style=\"color:red;\">" + sEscaped + "</span>";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QChar superscriptDigit(QChar ch)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (ch.unicode())
|
|
|
|
|
|
{
|
|
|
|
|
|
case '0': return QChar(0x2070);
|
|
|
|
|
|
case '1': return QChar(0x00B9);
|
|
|
|
|
|
case '2': return QChar(0x00B2);
|
|
|
|
|
|
case '3': return QChar(0x00B3);
|
|
|
|
|
|
case '4': return QChar(0x2074);
|
|
|
|
|
|
case '5': return QChar(0x2075);
|
|
|
|
|
|
case '6': return QChar(0x2076);
|
|
|
|
|
|
case '7': return QChar(0x2077);
|
|
|
|
|
|
case '8': return QChar(0x2078);
|
|
|
|
|
|
case '9': return QChar(0x2079);
|
|
|
|
|
|
default: return QChar();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QChar plainDigitFromSuperscript(QChar ch)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (ch.unicode())
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0x2070: return QLatin1Char('0');
|
|
|
|
|
|
case 0x00B9: return QLatin1Char('1');
|
|
|
|
|
|
case 0x00B2: return QLatin1Char('2');
|
|
|
|
|
|
case 0x00B3: return QLatin1Char('3');
|
|
|
|
|
|
case 0x2074: return QLatin1Char('4');
|
|
|
|
|
|
case 0x2075: return QLatin1Char('5');
|
|
|
|
|
|
case 0x2076: return QLatin1Char('6');
|
|
|
|
|
|
case 0x2077: return QLatin1Char('7');
|
|
|
|
|
|
case 0x2078: return QLatin1Char('8');
|
|
|
|
|
|
case 0x2079: return QLatin1Char('9');
|
|
|
|
|
|
default: return QChar();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString toSuperscriptUnit(const QString& sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
QString sResult;
|
|
|
|
|
|
sResult.reserve(sUnit.size());
|
|
|
|
|
|
for (int nIndex = 0; nIndex < sUnit.size(); ++nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (sUnit[nIndex] == QLatin1Char('^') &&
|
|
|
|
|
|
nIndex + 1 < sUnit.size())
|
|
|
|
|
|
{
|
|
|
|
|
|
QString sDigits;
|
|
|
|
|
|
int nDigitIndex = nIndex + 1;
|
|
|
|
|
|
while (nDigitIndex < sUnit.size())
|
|
|
|
|
|
{
|
|
|
|
|
|
QChar chSuperscript = superscriptDigit(sUnit[nDigitIndex]);
|
|
|
|
|
|
if (chSuperscript.isNull())
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sDigits.append(chSuperscript);
|
|
|
|
|
|
++nDigitIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!sDigits.isEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
sResult.append(sDigits);
|
|
|
|
|
|
nIndex = nDigitIndex - 1;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sResult.append(sUnit[nIndex]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return sResult;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString fromSuperscriptUnit(const QString& sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
QString sResult;
|
|
|
|
|
|
sResult.reserve(sUnit.size() * 2);
|
|
|
|
|
|
bool bInSuperscriptDigits = false;
|
|
|
|
|
|
for (int nIndex = 0; nIndex < sUnit.size(); ++nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
QChar chDigit = plainDigitFromSuperscript(sUnit[nIndex]);
|
|
|
|
|
|
if (!chDigit.isNull())
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!bInSuperscriptDigits)
|
|
|
|
|
|
{
|
|
|
|
|
|
sResult.append(QLatin1Char('^'));
|
|
|
|
|
|
bInSuperscriptDigits = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
sResult.append(chDigit);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bInSuperscriptDigits = false;
|
|
|
|
|
|
sResult.append(sUnit[nIndex]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return sResult;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void appendUnique(QStringList& listUnits, const QString& sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!sUnit.isEmpty() && !listUnits.contains(sUnit))
|
|
|
|
|
|
{
|
|
|
|
|
|
listUnits << sUnit;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void appendUnitSpellingVariants(QStringList& listUnits,
|
|
|
|
|
|
const QString& sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
QString sVariant = toSuperscriptUnit(sUnit);
|
|
|
|
|
|
appendUnique(listUnits, sVariant);
|
|
|
|
|
|
|
|
|
|
|
|
sVariant = fromSuperscriptUnit(sUnit);
|
|
|
|
|
|
appendUnique(listUnits, sVariant);
|
|
|
|
|
|
|
|
|
|
|
|
sVariant = sUnit;
|
|
|
|
|
|
sVariant.replace(QLatin1String("."), QString(QChar(0x00B7)));
|
|
|
|
|
|
appendUnique(listUnits, sVariant);
|
|
|
|
|
|
|
|
|
|
|
|
sVariant = sUnit;
|
|
|
|
|
|
sVariant.replace(QString(QChar(0x00B7)), QLatin1String("."));
|
|
|
|
|
|
appendUnique(listUnits, sVariant);
|
|
|
|
|
|
|
|
|
|
|
|
sVariant = sUnit;
|
|
|
|
|
|
sVariant.replace(QLatin1String("/D"), QLatin1String("/d"));
|
|
|
|
|
|
appendUnique(listUnits, sVariant);
|
|
|
|
|
|
|
|
|
|
|
|
sVariant = sUnit;
|
|
|
|
|
|
sVariant.replace(QLatin1String("/d"), QLatin1String("/D"));
|
|
|
|
|
|
appendUnique(listUnits, sVariant);
|
|
|
|
|
|
|
|
|
|
|
|
if (sUnit == QLatin1String("Darcy"))
|
|
|
|
|
|
{
|
|
|
|
|
|
appendUnique(listUnits, QLatin1String("D"));
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (sUnit == QLatin1String("D"))
|
|
|
|
|
|
{
|
|
|
|
|
|
appendUnique(listUnits, QLatin1String("Darcy"));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QStringList unitSpellingCandidates(const QString& sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
QStringList listUnits;
|
|
|
|
|
|
appendUnique(listUnits, sUnit);
|
|
|
|
|
|
for (int nIndex = 0; nIndex < listUnits.size(); ++nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
appendUnitSpellingVariants(listUnits, listUnits[nIndex]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return listUnits;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString resolveAvailableUnitSpelling(const QString& sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
QStringList listUnits = unitSpellingCandidates(sUnit);
|
|
|
|
|
|
for (int nIndex = 0; nIndex < listUnits.size(); ++nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (iUnitHelper::getUnitGroupByUnit(listUnits[nIndex]) != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return listUnits[nIndex];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return sUnit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void resolveParameterUnitSpelling(iParameter* pParameter)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pParameter == nullptr || pParameter->m_sUnit.isEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 参数XML和单位XML可能使用不同排版写法,绑定前切到当前单位表可识别的单位名。
|
|
|
|
|
|
QString sResolvedUnit = resolveAvailableUnitSpelling(pParameter->m_sUnit);
|
|
|
|
|
|
if (sResolvedUnit != pParameter->m_sUnit)
|
|
|
|
|
|
{
|
|
|
|
|
|
pParameter->m_sUnit = sResolvedUnit;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmParameterFieldInfo::nmParameterFieldInfo()
|
|
|
|
|
|
: m_eEditorType(NM_PARAMETER_EDITOR_NUMBER),
|
|
|
|
|
|
m_bUnitEnabled(true)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmParameterField::nmParameterField(
|
|
|
|
|
|
const nmParameterFieldInfo& oFieldInfo,
|
|
|
|
|
|
nmIParameterUnitService* 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)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmParameterField::~nmParameterField()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pUnitService = nullptr;
|
|
|
|
|
|
m_pParameter = nullptr;
|
|
|
|
|
|
m_pLabel = nullptr;
|
|
|
|
|
|
m_pLineEdit = nullptr;
|
|
|
|
|
|
m_pValueComboBox = nullptr;
|
|
|
|
|
|
m_pUnitComboBox = nullptr;
|
|
|
|
|
|
m_pUnitLabel = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmParameterField::initialize(QGridLayout* pLayout,
|
|
|
|
|
|
int nRow,
|
|
|
|
|
|
int nColumnOffset,
|
|
|
|
|
|
QString& sError)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pLayout == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
sError = fieldText("The parameter layout is unavailable.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:文本和枚举字段不依赖XML数值定义。
|
|
|
|
|
|
if (isText())
|
|
|
|
|
|
{
|
|
|
|
|
|
createTextEditor(pLayout, nRow, nColumnOffset);
|
|
|
|
|
|
sError.clear();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
resolveParameterUnitSpelling(m_pParameter);
|
|
|
|
|
|
|
|
|
|
|
|
// 第三步:创建标签、输入框和单位列。
|
|
|
|
|
|
return createNumericEditor(pLayout, nRow, nColumnOffset, sError);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString nmParameterField::parameterId() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_oFieldInfo.m_sParameterId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString nmParameterField::baseParameterId() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_oFieldInfo.m_sBaseParameterId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmParameterField::isEnum() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_oFieldInfo.m_eEditorType == NM_PARAMETER_EDITOR_ENUM;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmParameterField::isText() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_oFieldInfo.m_eEditorType == NM_PARAMETER_EDITOR_TEXT;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmParameterField::setValueRightAligned(bool bRightAligned)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pLineEdit != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pLineEdit->setAlignment(
|
|
|
|
|
|
(bRightAligned ? Qt::AlignRight : Qt::AlignLeft) |
|
|
|
|
|
|
Qt::AlignVCenter);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int nmParameterField::editorMinimumWidth()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 140;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int nmParameterField::unitMinimumWidth()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 86;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int nmParameterField::editorHeight()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 25;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmParameterField::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);
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:有单位字段交给窗口服务绑定;无单位字段保留占位列。
|
|
|
|
|
|
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 nmParameterField::createTextEditor(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_pLineEdit = new QLineEdit(pParentWidget);
|
|
|
|
|
|
m_clrNormalText = m_pLineEdit->palette().color(QPalette::Text);
|
|
|
|
|
|
m_pLineEdit->setFixedHeight(editorHeight());
|
|
|
|
|
|
m_pLineEdit->setMinimumWidth(editorMinimumWidth());
|
|
|
|
|
|
m_pLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
|
|
|
|
|
|
|
|
|
|
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_pLineEdit, nRow, nColumnOffset + 1);
|
|
|
|
|
|
pLayout->addWidget(m_pUnitLabel, nRow, nColumnOffset + 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmParameterField::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_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 nmParameterEnumOption& 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 nmParameterField::setBaseValue(const QVariant& oValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pLineEdit == nullptr || !oValue.isValid())
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 程序回填仍走控件标准写值接口,由所属页面的刷新标记屏蔽业务提交。
|
|
|
|
|
|
if (isText())
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pLineEdit->setText(oValue.toString());
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_pUnitComboBox != nullptr && m_pUnitService != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pUnitService->setUnitBaseValue(
|
|
|
|
|
|
m_pLineEdit, oValue.toDouble());
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pLineEdit->setText(formatBaseValue(oValue.toDouble()));
|
|
|
|
|
|
}
|
|
|
|
|
|
validate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVariant nmParameterField::baseValue(bool& bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
bValid = validate();
|
|
|
|
|
|
if (!bValid || m_pLineEdit == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return QVariant();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 单位字段始终向业务层返回基准单位值,界面显示单位不进入数据模型。
|
|
|
|
|
|
if (isText())
|
|
|
|
|
|
{
|
|
|
|
|
|
return QVariant(m_pLineEdit->text().trimmed());
|
|
|
|
|
|
}
|
|
|
|
|
|
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 nmParameterField::setEnumCode(const QString& sCode)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pValueComboBox == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
int nIndex = m_pValueComboBox->findData(sCode);
|
|
|
|
|
|
m_pValueComboBox->setCurrentIndex(nIndex >= 0 ? nIndex : 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString nmParameterField::enumCode() const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pValueComboBox == nullptr ||
|
|
|
|
|
|
m_pValueComboBox->currentIndex() < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return QString();
|
|
|
|
|
|
}
|
|
|
|
|
|
return m_pValueComboBox->itemData(
|
|
|
|
|
|
m_pValueComboBox->currentIndex()).toString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmParameterField::setExternalValidationError(const QString& sError)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_sExternalValidationError = sError;
|
|
|
|
|
|
validate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmParameterField::validate()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_bVisible || isEnum())
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_pLineEdit == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:按编辑器类型执行本地格式、范围和整数约束校验。
|
|
|
|
|
|
bool bValid = false;
|
|
|
|
|
|
if (isText())
|
|
|
|
|
|
{
|
|
|
|
|
|
bValid = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_pParameter == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
bValid = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else 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_PARAMETER_EDITOR_INTEGER)
|
|
|
|
|
|
{
|
|
|
|
|
|
bValid = dValue == static_cast<int>(dValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 第二步:叠加面板提供的跨字段业务规则,例如射孔区间关系。
|
|
|
|
|
|
bValid = bValid && m_sExternalValidationError.isEmpty();
|
|
|
|
|
|
updateValidationAppearance(bValid);
|
|
|
|
|
|
return bValid;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmParameterField::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 nmParameterField::isFieldVisible() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_bVisible;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QLineEdit* nmParameterField::valueEditor() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pLineEdit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QComboBox* nmParameterField::enumEditor() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pValueComboBox;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString nmParameterField::formatBaseValue(double dValue) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pParameter == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return QString::number(dValue, 'g', 15);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_oFieldInfo.m_eEditorType == NM_PARAMETER_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 nmParameterField::updateValidationAppearance(bool bValid)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pLineEdit == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第一步:只调整文字颜色,不覆盖应用主题提供的输入框背景和边框。
|
|
|
|
|
|
QPalette oPalette = m_pLineEdit->palette();
|
|
|
|
|
|
oPalette.setColor(QPalette::Text,
|
|
|
|
|
|
bValid ? m_clrNormalText : QColor(Qt::red));
|
|
|
|
|
|
m_pLineEdit->setPalette(oPalette);
|
|
|
|
|
|
|
|
|
|
|
|
// 第二步:组合参数名称、当前单位范围和跨字段错误作为统一帮助信息。
|
|
|
|
|
|
QString sHelp = m_oFieldInfo.m_sLabel;
|
|
|
|
|
|
if (m_pParameter != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|