diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm
index c0659bfb..75bee651 100644
Binary files a/Bin/Config/Lang/cn/nmNum_cn.qm and b/Bin/Config/Lang/cn/nmNum_cn.qm differ
diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts
index c445156b..513cea33 100644
--- a/Bin/Config/Lang/cn/nmNum_cn.ts
+++ b/Bin/Config/Lang/cn/nmNum_cn.ts
@@ -2870,11 +2870,12 @@ Reason: %1
Below min低于最小值
Above max高于最大值
Color map色带
+ Color mapping颜色映射
+ Out-of-range colors越界值颜色
Minimum最小值
Maximum最大值
- Unit单位
- Dimensionless无量纲
Minimum and maximum must be finite numbers.最小值和最大值必须是有限数。
+ Unable to convert the range to the selected unit.无法将范围换算为所选单位。
Minimum must be less than maximum.最小值必须小于最大值。
Unable to read the committed color settings.无法读取已提交的颜色设置。
diff --git a/Bin/Res/Icon/NmRestorePropertyRange.png b/Bin/Res/Icon/NmRestorePropertyRange.png
new file mode 100644
index 00000000..9d1e81e6
Binary files /dev/null and b/Bin/Res/Icon/NmRestorePropertyRange.png differ
diff --git a/Include/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.h b/Include/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.h
index 02e1ed83..4bd9922b 100644
--- a/Include/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.h
+++ b/Include/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.h
@@ -14,6 +14,7 @@ class QLabel;
class QLineEdit;
class QPushButton;
class QToolButton;
+class iUnitGroup;
class nmPebiResultSceneController;
/**
@@ -54,6 +55,10 @@ private slots:
void onRestorePropertyRangeClicked();
/** @brief 用户编辑任一上下限后显式进入手工范围模式。 */
void onManualRangeEdited(const QString& sText);
+ /** @brief 色带改变后刷新未启用越界颜色的端点预览。 */
+ void onColorMapChanged(int nIndex);
+ /** @brief 切换输入单位并保持两个输入值表示的物理量不变。 */
+ void onDisplayUnitChanged(int nIndex);
/** @brief 根据复选框同步低于范围颜色按钮状态。 */
void onBelowRangeToggled(bool bChecked);
/** @brief 根据复选框同步高于范围颜色按钮状态。 */
@@ -72,8 +77,10 @@ private:
void createUi();
/** @brief 从 Scene 读取初值并记录不可变的预期身份。 */
bool initializeFromScene();
- /** @brief 将设置和值域写入控件,不触发手工范围编辑状态。 */
- void populateEditor(const nmPebiResultDisplaySettings& oSettings,
+ /** @brief 从属性目录和全局单位表初始化当前对话框的单位选择。 */
+ void initializeUnitEditor();
+ /** @brief 换算成功后将设置和值域写入控件,不触发手工编辑状态。 */
+ bool populateEditor(const nmPebiResultDisplaySettings& oSettings,
const double dVisibleRange[2]);
/** @brief 解析编辑值并构造待提交纯值设置。 */
bool collectEditedSettings(
@@ -85,6 +92,18 @@ private:
QString formatValue(double dValue) const;
/** @brief 使用 C locale 严格解析有限 double。 */
bool parseFiniteValue(const QString& sText, double& dValue) const;
+ /** @brief 使用全局单位表换算单个有限值。 */
+ bool convertUnitValue(double dSourceValue,
+ const QString& sSourceUnit,
+ const QString& sDestinationUnit,
+ double& dDestinationValue) const;
+ /** @brief 将基础单位范围换算到当前对话框显示单位。 */
+ bool convertBaseRangeToDisplay(const double dBaseRange[2],
+ double dDisplayRange[2]) const;
+ /** @brief 根据当前单位刷新两个范围输入框的提示文字。 */
+ void refreshRangeToolTips();
+ /** @brief 根据色带、范围模式和启用状态刷新两个颜色按钮。 */
+ void refreshRangeColorButtons();
/** @brief 更新颜色按钮色块。 */
void updateColorButton(QPushButton* pButton,
const QColor& oColor);
@@ -95,16 +114,21 @@ private:
quint64 m_nExpectedBindingRevision; ///< 打开时捕获的 Scene 成功绑定序号。
QString m_sExpectedSnapshotId; ///< 打开时捕获的快照稳定 ID。
QString m_sExpectedPropertyId; ///< 打开时捕获的属性稳定 ID。
- QString m_sDisplayUnit; ///< 当前属性默认显示单位,仅用于标签。
+ QString m_sBaseUnit; ///< Catalog 中的数据层基础单位。
+ QString m_sDisplayUnit; ///< 当前对话框实例选择的输入显示单位。
+ iUnitGroup* m_pUnitGroup; ///< 全局单位框架拥有,未找到时为空。
double m_dPropertyRange[2]; ///< 快照完整业务范围,回退按钮使用。
nmPebiResultDisplaySettings m_oBaselineSettings; ///< 最近成功 Apply 的基线。
+ QColor m_oEditedBelowRangeColor; ///< 尚未提交的低于范围颜色。
+ QColor m_oEditedAboveRangeColor; ///< 尚未提交的高于范围颜色。
bool m_bManualRangeEdited; ///< 仅用户编辑或已有手工范围时为 true。
+ bool m_bRangeValuesEditedByUser; ///< 本次基线后用户是否亲自编辑过数值。
bool m_bInitialized; ///< Scene 初值是否完整读取成功。
QComboBox* m_pColorMapCombo; ///< 带渐变预览和稳定 ID 的色带框。
QLineEdit* m_pMinimumEdit; ///< 支持科学计数法的最小值文字框。
QLineEdit* m_pMaximumEdit; ///< 支持科学计数法的最大值文字框。
- QLabel* m_pUnitLabel; ///< 当前属性默认显示单位;无量纲时显示“无量纲”。
+ QComboBox* m_pUnitCombo; ///< 两个范围输入框共用的临时显示单位。
QToolButton* m_pRestoreRangeButton; ///< 恢复完整业务范围按钮。
QCheckBox* m_pLogarithmicCheck; ///< Log10 映射开关。
QLabel* m_pLogReasonLabel; ///< Log 不可用时的明确原因。
diff --git a/Src/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.cpp b/Src/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.cpp
index c23bf501..920dabcd 100644
--- a/Src/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.cpp
+++ b/Src/nmNum/nmSubWxs/nmWxPebiResultColorScaleSettingsDlg.cpp
@@ -1,6 +1,8 @@
#include "nmWxPebiResultColorScaleSettingsDlg.h"
-#include "nmPebiResultPropertyDisplayText.h"
+#include "iUnitGroup.h"
+#include "iUnitHelper.h"
+#include "nmPebiResultPropertyCatalog.h"
#include "nmPebiResultSceneController.h"
#include "nmVTKColorMapCatalog.h"
@@ -9,14 +11,17 @@
#include
#include
#include
-#include
+#include
+#include
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -80,12 +85,14 @@ nmWxPebiResultColorScaleSettingsDlg(
: QDialog(pParent),
m_pSceneController(pSceneController),
m_nExpectedBindingRevision(0),
+ m_pUnitGroup(nullptr),
m_bManualRangeEdited(false),
+ m_bRangeValuesEditedByUser(false),
m_bInitialized(false),
m_pColorMapCombo(nullptr),
m_pMinimumEdit(nullptr),
m_pMaximumEdit(nullptr),
- m_pUnitLabel(nullptr),
+ m_pUnitCombo(nullptr),
m_pRestoreRangeButton(nullptr),
m_pLogarithmicCheck(nullptr),
m_pLogReasonLabel(nullptr),
@@ -104,7 +111,7 @@ nmWxPebiResultColorScaleSettingsDlg(
m_bInitialized = initializeFromScene();
m_pApplyButton->setEnabled(m_bInitialized);
m_pOkButton->setEnabled(m_bInitialized);
- if(!m_bInitialized) {
+ if(!m_bInitialized && m_pErrorLabel->text().isEmpty()) {
setErrorText(tr("The result color settings are unavailable."));
}
}
@@ -128,10 +135,17 @@ void nmWxPebiResultColorScaleSettingsDlg::onOkClicked()
void nmWxPebiResultColorScaleSettingsDlg::onRestorePropertyRangeClicked()
{
+ double dDisplayRange[2] = { 0.0, 0.0 };
+ if(!convertBaseRangeToDisplay(m_dPropertyRange, dDisplayRange)) {
+ setErrorText(tr("Unable to convert the range to the selected unit."));
+ return;
+ }
m_bManualRangeEdited = false;
- m_pMinimumEdit->setText(formatValue(m_dPropertyRange[0]));
- m_pMaximumEdit->setText(formatValue(m_dPropertyRange[1]));
+ m_bRangeValuesEditedByUser = false;
+ m_pMinimumEdit->setText(formatValue(dDisplayRange[0]));
+ m_pMaximumEdit->setText(formatValue(dDisplayRange[1]));
refreshLogAvailability();
+ refreshRangeColorButtons();
setErrorText(QString());
}
@@ -140,50 +154,114 @@ void nmWxPebiResultColorScaleSettingsDlg::onManualRangeEdited(
{
Q_UNUSED(sText);
m_bManualRangeEdited = true;
+ m_bRangeValuesEditedByUser = true;
refreshLogAvailability();
+ refreshRangeColorButtons();
+}
+
+void nmWxPebiResultColorScaleSettingsDlg::onColorMapChanged(int nIndex)
+{
+ Q_UNUSED(nIndex);
+ refreshRangeColorButtons();
+}
+
+void nmWxPebiResultColorScaleSettingsDlg::onDisplayUnitChanged(int nIndex)
+{
+ if(nIndex < 0) {
+ return;
+ }
+ const QString sNewUnit = m_pUnitCombo->itemText(nIndex);
+ if(sNewUnit == m_sDisplayUnit) {
+ return;
+ }
+
+ double dOldDisplayRange[2] = { 0.0, 0.0 };
+ double dBaseRange[2] = { 0.0, 0.0 };
+ double dNewDisplayRange[2] = { 0.0, 0.0 };
+ QString sError;
+ if(!parseFiniteValue(m_pMinimumEdit->text(), dOldDisplayRange[0]) ||
+ !parseFiniteValue(m_pMaximumEdit->text(), dOldDisplayRange[1])) {
+ sError = tr("Minimum and maximum must be finite numbers.");
+ } else if(!convertUnitValue(
+ dOldDisplayRange[0], m_sDisplayUnit,
+ m_sBaseUnit, dBaseRange[0]) ||
+ !convertUnitValue(
+ dOldDisplayRange[1], m_sDisplayUnit,
+ m_sBaseUnit, dBaseRange[1]) ||
+ !convertUnitValue(
+ dBaseRange[0], m_sBaseUnit,
+ sNewUnit, dNewDisplayRange[0]) ||
+ !convertUnitValue(
+ dBaseRange[1], m_sBaseUnit,
+ sNewUnit, dNewDisplayRange[1])) {
+ sError = tr("Unable to convert the range to the selected unit.");
+ }
+
+ if(!sError.isEmpty()) {
+ const bool bSignalsBlocked = m_pUnitCombo->blockSignals(true);
+ m_pUnitCombo->setCurrentIndex(
+ m_pUnitCombo->findText(m_sDisplayUnit));
+ m_pUnitCombo->blockSignals(bSignalsBlocked);
+ setErrorText(sError);
+ return;
+ }
+
+ m_sDisplayUnit = sNewUnit;
+ m_pMinimumEdit->setText(formatValue(dNewDisplayRange[0]));
+ m_pMaximumEdit->setText(formatValue(dNewDisplayRange[1]));
+ refreshRangeToolTips();
+ refreshLogAvailability();
+ setErrorText(QString());
}
void nmWxPebiResultColorScaleSettingsDlg::onBelowRangeToggled(bool bChecked)
{
- m_pBelowColorButton->setEnabled(bChecked);
+ Q_UNUSED(bChecked);
+ refreshRangeColorButtons();
}
void nmWxPebiResultColorScaleSettingsDlg::onAboveRangeToggled(bool bChecked)
{
- m_pAboveColorButton->setEnabled(bChecked);
+ Q_UNUSED(bChecked);
+ refreshRangeColorButtons();
}
void nmWxPebiResultColorScaleSettingsDlg::onChooseBelowRangeColor()
{
QColor oColor = QColorDialog::getColor(
- m_oBaselineSettings.m_oBelowRangeColor, this,
+ m_oEditedBelowRangeColor, this,
tr("Below minimum color"));
if(oColor.isValid()) {
oColor.setAlpha(255);
- m_oBaselineSettings.m_oBelowRangeColor = oColor;
- updateColorButton(m_pBelowColorButton, oColor);
+ m_oEditedBelowRangeColor = oColor;
+ refreshRangeColorButtons();
}
}
void nmWxPebiResultColorScaleSettingsDlg::onChooseAboveRangeColor()
{
QColor oColor = QColorDialog::getColor(
- m_oBaselineSettings.m_oAboveRangeColor, this,
+ m_oEditedAboveRangeColor, this,
tr("Above maximum color"));
if(oColor.isValid()) {
oColor.setAlpha(255);
- m_oBaselineSettings.m_oAboveRangeColor = oColor;
- updateColorButton(m_pAboveColorButton, oColor);
+ m_oEditedAboveRangeColor = oColor;
+ refreshRangeColorButtons();
}
}
void nmWxPebiResultColorScaleSettingsDlg::refreshLogAvailability()
{
- double dMinimum = 0.0;
+ double dDisplayMinimum = 0.0;
+ double dBaseMinimum = 0.0;
const bool bMinimumValid =
- parseFiniteValue(m_pMinimumEdit->text(), dMinimum);
+ parseFiniteValue(m_pMinimumEdit->text(), dDisplayMinimum);
+ const bool bMinimumConverted = bMinimumValid &&
+ convertUnitValue(dDisplayMinimum, m_sDisplayUnit,
+ m_sBaseUnit, dBaseMinimum);
const bool bPropertyPositive = m_dPropertyRange[0] > 0.0;
- const bool bDisplayPositive = bMinimumValid && dMinimum > 0.0;
+ const bool bDisplayPositive =
+ bMinimumConverted && dBaseMinimum > 0.0;
const bool bAvailable = bPropertyPositive && bDisplayPositive;
if(!bAvailable && m_pLogarithmicCheck->isChecked()) {
// 禁用前先清除不可提交的 Log 状态,避免用户被锁在失败循环中。
@@ -193,25 +271,27 @@ void nmWxPebiResultColorScaleSettingsDlg::refreshLogAvailability()
m_pLogarithmicCheck->blockSignals(bSignalsBlocked);
}
m_pLogarithmicCheck->setEnabled(bAvailable);
+ QString sReason;
if(!bPropertyPositive) {
- m_pLogReasonLabel->setText(
- tr("Logarithmic scale requires a positive property range."));
+ sReason = tr(
+ "Logarithmic scale requires a positive property range.");
} else if(!bDisplayPositive) {
- m_pLogReasonLabel->setText(
- tr("Logarithmic scale requires a positive minimum."));
- } else {
- m_pLogReasonLabel->clear();
+ sReason = tr(
+ "Logarithmic scale requires a positive minimum.");
}
+ m_pLogReasonLabel->setText(sReason);
+ m_pLogReasonLabel->setVisible(!sReason.isEmpty());
}
void nmWxPebiResultColorScaleSettingsDlg::createUi()
{
setWindowTitle(tr("Color settings for current property"));
setModal(true);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_pColorMapCombo = new QComboBox(this);
m_pColorMapCombo->setIconSize(QSize(128, 16));
- m_pColorMapCombo->setMinimumWidth(260);
+ m_pColorMapCombo->setMinimumWidth(280);
const QStringList listColorMapIds =
nmVTKColorMapCatalog::getColorMapIds();
for(int nIndex = 0; nIndex < listColorMapIds.size(); ++nIndex) {
@@ -224,61 +304,92 @@ void nmWxPebiResultColorScaleSettingsDlg::createUi()
m_pMinimumEdit = new QLineEdit(this);
m_pMaximumEdit = new QLineEdit(this);
- m_pUnitLabel = new QLabel(this);
+ m_pMinimumEdit->setMinimumWidth(220);
+ m_pMinimumEdit->setMaximumWidth(250);
+ m_pMaximumEdit->setMinimumWidth(220);
+ m_pMaximumEdit->setMaximumWidth(250);
+ m_pUnitCombo = new QComboBox(this);
+ m_pUnitCombo->setMinimumWidth(80);
+ m_pUnitCombo->setMaximumWidth(140);
+ m_pUnitCombo->hide();
m_pMinimumEdit->setAlignment(Qt::AlignRight);
m_pMaximumEdit->setAlignment(Qt::AlignRight);
m_pRestoreRangeButton = new QToolButton(this);
m_pRestoreRangeButton->setAutoRaise(true);
- m_pRestoreRangeButton->setFixedSize(24, 24);
- m_pRestoreRangeButton->setIconSize(QSize(16, 16));
+ m_pRestoreRangeButton->setFixedSize(36, 36);
+ m_pRestoreRangeButton->setIconSize(QSize(32, 32));
m_pRestoreRangeButton->setIcon(QIcon(resultColorIconPath(
- QString::fromLatin1("Undo.png"))));
+ QString::fromLatin1("NmRestorePropertyRange.png"))));
m_pRestoreRangeButton->setToolTip(tr("Restore property range"));
- QHBoxLayout* pMinimumLayout = new QHBoxLayout();
- pMinimumLayout->setContentsMargins(0, 0, 0, 0);
- pMinimumLayout->addWidget(m_pMinimumEdit, 1);
- pMinimumLayout->addWidget(m_pRestoreRangeButton);
- QWidget* pMinimumWidget = new QWidget(this);
- pMinimumWidget->setLayout(pMinimumLayout);
-
m_pLogarithmicCheck = new QCheckBox(tr("Logarithmic scale"), this);
m_pLogReasonLabel = new QLabel(this);
m_pLogReasonLabel->setWordWrap(true);
m_pLogReasonLabel->setStyleSheet(
QString::fromLatin1("color: #666666;"));
+ m_pLogReasonLabel->hide();
m_pBelowRangeCheck = new QCheckBox(tr("Below min"), this);
m_pBelowColorButton = new QPushButton(this);
m_pBelowColorButton->setFixedSize(44, 22);
- QHBoxLayout* pBelowLayout = new QHBoxLayout();
- pBelowLayout->setContentsMargins(0, 0, 0, 0);
- pBelowLayout->addWidget(m_pBelowRangeCheck);
- pBelowLayout->addWidget(m_pBelowColorButton);
- pBelowLayout->addStretch();
- QWidget* pBelowWidget = new QWidget(this);
- pBelowWidget->setLayout(pBelowLayout);
+ m_pBelowColorButton->setEnabled(false);
+ m_pBelowColorButton->setToolTip(tr("Below minimum color"));
m_pAboveRangeCheck = new QCheckBox(tr("Above max"), this);
m_pAboveColorButton = new QPushButton(this);
m_pAboveColorButton->setFixedSize(44, 22);
- QHBoxLayout* pAboveLayout = new QHBoxLayout();
- pAboveLayout->setContentsMargins(0, 0, 0, 0);
- pAboveLayout->addWidget(m_pAboveRangeCheck);
- pAboveLayout->addWidget(m_pAboveColorButton);
- pAboveLayout->addStretch();
- QWidget* pAboveWidget = new QWidget(this);
- pAboveWidget->setLayout(pAboveLayout);
-
- QFormLayout* pFormLayout = new QFormLayout();
- pFormLayout->addRow(tr("Color map"), m_pColorMapCombo);
- pFormLayout->addRow(tr("Minimum"), pMinimumWidget);
- pFormLayout->addRow(tr("Maximum"), m_pMaximumEdit);
- pFormLayout->addRow(tr("Unit"), m_pUnitLabel);
- pFormLayout->addRow(QString(), m_pLogarithmicCheck);
- pFormLayout->addRow(QString(), m_pLogReasonLabel);
- pFormLayout->addRow(QString(), pBelowWidget);
- pFormLayout->addRow(QString(), pAboveWidget);
+ m_pAboveColorButton->setEnabled(false);
+ m_pAboveColorButton->setToolTip(tr("Above maximum color"));
+
+ QGroupBox* pMappingGroup = new QGroupBox(tr("Color mapping"), this);
+ QGridLayout* pMappingLayout = new QGridLayout(pMappingGroup);
+ pMappingLayout->setContentsMargins(10, 16, 10, 10);
+ pMappingLayout->setHorizontalSpacing(8);
+ pMappingLayout->setVerticalSpacing(6);
+ QLabel* pColorMapLabel = new QLabel(tr("Color map"), pMappingGroup);
+ QLabel* pMinimumLabel = new QLabel(tr("Minimum"), pMappingGroup);
+ QLabel* pMaximumLabel = new QLabel(tr("Maximum"), pMappingGroup);
+ pColorMapLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+ pMinimumLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+ pMaximumLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+ const int nFieldLabelWidth = qMax(
+ pColorMapLabel->sizeHint().width(),
+ qMax(pMinimumLabel->sizeHint().width(),
+ pMaximumLabel->sizeHint().width()));
+ pMappingLayout->setColumnMinimumWidth(0, nFieldLabelWidth);
+ pMappingLayout->setColumnMinimumWidth(1, 220);
+ pMappingLayout->addWidget(pColorMapLabel, 0, 0);
+ pMappingLayout->addWidget(m_pColorMapCombo, 0, 1, 1, 4);
+ pMappingLayout->addWidget(pMinimumLabel, 1, 0);
+ pMappingLayout->addWidget(m_pMinimumEdit, 1, 1);
+ pMappingLayout->addWidget(m_pUnitCombo, 1, 2, 2, 1,
+ Qt::AlignVCenter);
+ pMappingLayout->addWidget(m_pRestoreRangeButton, 1, 4, 2, 1,
+ Qt::AlignCenter);
+ pMappingLayout->addWidget(pMaximumLabel, 2, 0);
+ pMappingLayout->addWidget(m_pMaximumEdit, 2, 1);
+ pMappingLayout->addWidget(m_pLogarithmicCheck, 3, 1, 1, 4);
+ pMappingLayout->addWidget(m_pLogReasonLabel, 4, 1, 1, 4);
+ pMappingLayout->setColumnStretch(0, 0);
+ pMappingLayout->setColumnStretch(1, 0);
+ pMappingLayout->setColumnStretch(2, 0);
+ pMappingLayout->setColumnStretch(3, 1);
+ pMappingLayout->setColumnStretch(4, 0);
+
+ QGroupBox* pRangeColorGroup = new QGroupBox(
+ tr("Out-of-range colors"), this);
+ QGridLayout* pRangeColorLayout = new QGridLayout(pRangeColorGroup);
+ pRangeColorLayout->setContentsMargins(10, 16, 10, 10);
+ pRangeColorLayout->setHorizontalSpacing(12);
+ pRangeColorLayout->setVerticalSpacing(6);
+ pRangeColorLayout->addWidget(m_pBelowRangeCheck, 0, 1);
+ pRangeColorLayout->addWidget(m_pBelowColorButton, 0, 2, Qt::AlignLeft);
+ pRangeColorLayout->addWidget(m_pAboveRangeCheck, 1, 1);
+ pRangeColorLayout->addWidget(m_pAboveColorButton, 1, 2, Qt::AlignLeft);
+ pRangeColorLayout->setColumnStretch(0, 1);
+ pRangeColorLayout->setColumnStretch(1, 0);
+ pRangeColorLayout->setColumnStretch(2, 0);
+ pRangeColorLayout->setColumnStretch(3, 1);
m_pErrorLabel = new QLabel(this);
m_pErrorLabel->setWordWrap(true);
@@ -291,18 +402,41 @@ void nmWxPebiResultColorScaleSettingsDlg::createUi()
Qt::Horizontal, this);
m_pApplyButton = pButtonBox->button(QDialogButtonBox::Apply);
m_pOkButton = pButtonBox->button(QDialogButtonBox::Ok);
+ QPushButton* pCancelButton =
+ pButtonBox->button(QDialogButtonBox::Cancel);
+ const QSize oFooterIconSize(16, 16);
+ m_pOkButton->setIcon(QIcon(resultColorIconPath(
+ QString::fromLatin1("OK.png"))));
+ pCancelButton->setIcon(QIcon(resultColorIconPath(
+ QString::fromLatin1("Cancel.png"))));
+ m_pOkButton->setMinimumWidth(72);
+ pCancelButton->setMinimumWidth(72);
+ m_pApplyButton->setMinimumWidth(72);
+ m_pOkButton->setIconSize(oFooterIconSize);
+ pCancelButton->setIconSize(oFooterIconSize);
+ if(pButtonBox->layout() != nullptr) {
+ pButtonBox->layout()->setSpacing(6);
+ }
connect(m_pApplyButton, SIGNAL(clicked()),
this, SLOT(onApplyClicked()));
connect(m_pOkButton, SIGNAL(clicked()),
this, SLOT(onOkClicked()));
- connect(pButtonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
- this, SLOT(reject()));
+ connect(pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
QVBoxLayout* pMainLayout = new QVBoxLayout(this);
- pMainLayout->addLayout(pFormLayout);
- pMainLayout->addWidget(m_pErrorLabel);
- pMainLayout->addWidget(pButtonBox);
- setMinimumWidth(420);
+ pMainLayout->setContentsMargins(12, 10, 12, 0);
+ pMainLayout->setSpacing(8);
+ pMainLayout->addWidget(pMappingGroup);
+ pMainLayout->addWidget(pRangeColorGroup);
+ QHBoxLayout* pFooterLayout = new QHBoxLayout();
+ pFooterLayout->setContentsMargins(4, 2, 4, 5);
+ pFooterLayout->setSpacing(8);
+ m_pErrorLabel->setSizePolicy(
+ QSizePolicy::Expanding, QSizePolicy::Preferred);
+ pFooterLayout->addWidget(m_pErrorLabel, 1);
+ pFooterLayout->addWidget(pButtonBox);
+ pMainLayout->addLayout(pFooterLayout);
+ setMinimumWidth(470);
connect(m_pRestoreRangeButton, SIGNAL(clicked()),
this, SLOT(onRestorePropertyRangeClicked()));
@@ -310,6 +444,10 @@ void nmWxPebiResultColorScaleSettingsDlg::createUi()
this, SLOT(onManualRangeEdited(QString)));
connect(m_pMaximumEdit, SIGNAL(textEdited(QString)),
this, SLOT(onManualRangeEdited(QString)));
+ connect(m_pColorMapCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onColorMapChanged(int)));
+ connect(m_pUnitCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(onDisplayUnitChanged(int)));
connect(m_pBelowRangeCheck, SIGNAL(toggled(bool)),
this, SLOT(onBelowRangeToggled(bool)));
connect(m_pAboveRangeCheck, SIGNAL(toggled(bool)),
@@ -329,48 +467,102 @@ bool nmWxPebiResultColorScaleSettingsDlg::initializeFromScene()
m_pSceneController->getSnapshotBindingRevision();
m_sExpectedSnapshotId = m_pSceneController->getCurrentSnapshotId();
m_sExpectedPropertyId = m_pSceneController->getCurrentPropertyId();
- m_sDisplayUnit = nmPebiResultPropertyDisplayText::getDefaultDisplayUnit(
- m_sExpectedPropertyId);
- m_pUnitLabel->setText(m_sDisplayUnit.isEmpty()
- ? tr("Dimensionless") : m_sDisplayUnit);
+ nmPebiResultPropertyDescriptor oDescriptor;
double dVisibleRange[2] = { 0.0, 0.0 };
if(m_nExpectedBindingRevision == 0 ||
m_sExpectedSnapshotId.isEmpty() || m_sExpectedPropertyId.isEmpty() ||
+ !nmPebiResultPropertyCatalog::findDescriptor(
+ m_sExpectedPropertyId, oDescriptor) ||
!m_pSceneController->getCurrentPropertyRange(m_dPropertyRange) ||
!m_pSceneController->getCurrentDisplayRange(dVisibleRange) ||
!m_pSceneController->getCurrentDisplaySettings(
m_oBaselineSettings)) {
return false;
}
- populateEditor(m_oBaselineSettings, dVisibleRange);
- return true;
+ m_sBaseUnit = oDescriptor.m_sBaseUnit;
+ m_sDisplayUnit = oDescriptor.m_sDefaultDisplayUnit.isEmpty()
+ ? m_sBaseUnit : oDescriptor.m_sDefaultDisplayUnit;
+ initializeUnitEditor();
+ return populateEditor(m_oBaselineSettings, dVisibleRange);
}
-void nmWxPebiResultColorScaleSettingsDlg::populateEditor(
+void nmWxPebiResultColorScaleSettingsDlg::initializeUnitEditor()
+{
+ const bool bSignalsBlocked = m_pUnitCombo->blockSignals(true);
+ m_pUnitCombo->clear();
+ m_pUnitGroup = nullptr;
+ if(m_sBaseUnit.isEmpty()) {
+ m_sDisplayUnit.clear();
+ m_pUnitCombo->setEnabled(false);
+ m_pUnitCombo->hide();
+ m_pUnitCombo->blockSignals(bSignalsBlocked);
+ return;
+ }
+
+ m_pUnitGroup = iUnitHelper::getUnitGroupByUnit(m_sBaseUnit);
+ QStringList listUnits;
+ if(m_pUnitGroup != nullptr &&
+ m_pUnitGroup->indexOf(m_sBaseUnit) >= 0) {
+ listUnits = m_pUnitGroup->getAllUnitNames();
+ }
+ const bool bHasUnitGroup = !listUnits.isEmpty() &&
+ listUnits.contains(m_sBaseUnit);
+ if(!bHasUnitGroup) {
+ m_pUnitGroup = nullptr;
+ listUnits.clear();
+ listUnits.append(m_sBaseUnit);
+ m_sDisplayUnit = m_sBaseUnit;
+ } else if(!listUnits.contains(m_sDisplayUnit)) {
+ m_sDisplayUnit = m_sBaseUnit;
+ }
+
+ m_pUnitCombo->addItems(listUnits);
+ m_pUnitCombo->setCurrentIndex(
+ m_pUnitCombo->findText(m_sDisplayUnit));
+ m_pUnitCombo->setEnabled(bHasUnitGroup);
+ m_pUnitCombo->show();
+ m_pUnitCombo->blockSignals(bSignalsBlocked);
+}
+
+bool nmWxPebiResultColorScaleSettingsDlg::populateEditor(
const nmPebiResultDisplaySettings& oSettings,
const double dVisibleRange[2])
{
+ double dDisplayRange[2] = { 0.0, 0.0 };
+ if(!convertBaseRangeToDisplay(dVisibleRange, dDisplayRange)) {
+ setErrorText(tr("Unable to convert the range to the selected unit."));
+ return false;
+ }
+
+ m_oEditedBelowRangeColor = oSettings.m_oBelowRangeColor;
+ m_oEditedAboveRangeColor = oSettings.m_oAboveRangeColor;
+ m_oEditedBelowRangeColor.setAlpha(255);
+ m_oEditedAboveRangeColor.setAlpha(255);
+ m_bManualRangeEdited = oSettings.m_bHasManualRange;
+
+ const bool bColorMapSignalsBlocked =
+ m_pColorMapCombo->blockSignals(true);
+ const bool bBelowSignalsBlocked =
+ m_pBelowRangeCheck->blockSignals(true);
+ const bool bAboveSignalsBlocked =
+ m_pAboveRangeCheck->blockSignals(true);
const int nColorIndex = m_pColorMapCombo->findData(
oSettings.m_sColorMapId);
m_pColorMapCombo->setCurrentIndex(nColorIndex);
- m_pMinimumEdit->setText(formatValue(dVisibleRange[0]));
- m_pMaximumEdit->setText(formatValue(dVisibleRange[1]));
- m_bManualRangeEdited = oSettings.m_bHasManualRange;
+ m_pMinimumEdit->setText(formatValue(dDisplayRange[0]));
+ m_pMaximumEdit->setText(formatValue(dDisplayRange[1]));
m_pLogarithmicCheck->setChecked(
oSettings.m_eScaleMode == NM_PebiColorScale_Logarithmic);
m_pBelowRangeCheck->setChecked(oSettings.m_bUseBelowRangeColor);
m_pAboveRangeCheck->setChecked(oSettings.m_bUseAboveRangeColor);
- updateColorButton(m_pBelowColorButton, oSettings.m_oBelowRangeColor);
- updateColorButton(m_pAboveColorButton, oSettings.m_oAboveRangeColor);
- onBelowRangeToggled(oSettings.m_bUseBelowRangeColor);
- onAboveRangeToggled(oSettings.m_bUseAboveRangeColor);
+ m_pColorMapCombo->blockSignals(bColorMapSignalsBlocked);
+ m_pBelowRangeCheck->blockSignals(bBelowSignalsBlocked);
+ m_pAboveRangeCheck->blockSignals(bAboveSignalsBlocked);
+ m_bRangeValuesEditedByUser = false;
+ refreshRangeColorButtons();
refreshLogAvailability();
-
- const QString sUnitSuffix = m_sDisplayUnit.isEmpty()
- ? QString() : QString::fromLatin1(" (") +
- m_sDisplayUnit + QString::fromLatin1(")");
- m_pMinimumEdit->setToolTip(tr("Minimum") + sUnitSuffix);
- m_pMaximumEdit->setToolTip(tr("Maximum") + sUnitSuffix);
+ refreshRangeToolTips();
+ return true;
}
bool nmWxPebiResultColorScaleSettingsDlg::collectEditedSettings(
@@ -378,24 +570,40 @@ bool nmWxPebiResultColorScaleSettingsDlg::collectEditedSettings(
QString& sError) const
{
sError.clear();
- double dMinimum = 0.0;
- double dMaximum = 0.0;
- if(!parseFiniteValue(m_pMinimumEdit->text(), dMinimum) ||
- !parseFiniteValue(m_pMaximumEdit->text(), dMaximum)) {
+ double dDisplayMinimum = 0.0;
+ double dDisplayMaximum = 0.0;
+ if(!parseFiniteValue(m_pMinimumEdit->text(), dDisplayMinimum) ||
+ !parseFiniteValue(m_pMaximumEdit->text(), dDisplayMaximum)) {
sError = tr("Minimum and maximum must be finite numbers.");
return false;
}
// 提交值与界面最多 12 位有效数字保持一致,重复 Apply 不产生隐藏精度差异。
- double dCanonicalMinimum = 0.0;
- double dCanonicalMaximum = 0.0;
- if(!parseFiniteValue(formatValue(dMinimum), dCanonicalMinimum) ||
- !parseFiniteValue(formatValue(dMaximum), dCanonicalMaximum)) {
+ if(!parseFiniteValue(
+ formatValue(dDisplayMinimum), dDisplayMinimum) ||
+ !parseFiniteValue(
+ formatValue(dDisplayMaximum), dDisplayMaximum)) {
sError = tr("Minimum and maximum must be finite numbers.");
return false;
}
- dMinimum = dCanonicalMinimum;
- dMaximum = dCanonicalMaximum;
- if(m_bManualRangeEdited && dMinimum >= dMaximum) {
+
+ double dBaseMinimum = 0.0;
+ double dBaseMaximum = 0.0;
+ const bool bReuseBaselineRange = m_bManualRangeEdited &&
+ !m_bRangeValuesEditedByUser &&
+ m_oBaselineSettings.m_bHasManualRange;
+ if(bReuseBaselineRange) {
+ dBaseMinimum = m_oBaselineSettings.m_dManualMinimum;
+ dBaseMaximum = m_oBaselineSettings.m_dManualMaximum;
+ } else if(!convertUnitValue(
+ dDisplayMinimum, m_sDisplayUnit,
+ m_sBaseUnit, dBaseMinimum) ||
+ !convertUnitValue(
+ dDisplayMaximum, m_sDisplayUnit,
+ m_sBaseUnit, dBaseMaximum)) {
+ sError = tr("Unable to convert the range to the selected unit.");
+ return false;
+ }
+ if(m_bManualRangeEdited && dBaseMinimum >= dBaseMaximum) {
sError = tr("Minimum must be less than maximum.");
return false;
}
@@ -407,10 +615,14 @@ bool nmWxPebiResultColorScaleSettingsDlg::collectEditedSettings(
oSettings.m_eScaleMode = m_pLogarithmicCheck->isChecked()
? NM_PebiColorScale_Logarithmic : NM_PebiColorScale_Linear;
oSettings.m_bHasManualRange = m_bManualRangeEdited;
- oSettings.m_dManualMinimum = m_bManualRangeEdited ? dMinimum : 0.0;
- oSettings.m_dManualMaximum = m_bManualRangeEdited ? dMaximum : 0.0;
+ oSettings.m_dManualMinimum =
+ m_bManualRangeEdited ? dBaseMinimum : 0.0;
+ oSettings.m_dManualMaximum =
+ m_bManualRangeEdited ? dBaseMaximum : 0.0;
oSettings.m_bUseBelowRangeColor = m_pBelowRangeCheck->isChecked();
oSettings.m_bUseAboveRangeColor = m_pAboveRangeCheck->isChecked();
+ oSettings.m_oBelowRangeColor = m_oEditedBelowRangeColor;
+ oSettings.m_oAboveRangeColor = m_oEditedAboveRangeColor;
oSettings.m_oBelowRangeColor.setAlpha(255);
oSettings.m_oAboveRangeColor.setAlpha(255);
return true;
@@ -444,7 +656,11 @@ bool nmWxPebiResultColorScaleSettingsDlg::applyEditor()
}
m_oBaselineSettings = oCommittedSettings;
- populateEditor(oCommittedSettings, dVisibleRange);
+ if(!populateEditor(oCommittedSettings, dVisibleRange)) {
+ sError = tr("Unable to convert the range to the selected unit.");
+ emit operationFailed(sError);
+ return false;
+ }
setErrorText(QString());
emit displaySettingsApplied();
return true;
@@ -469,6 +685,98 @@ bool nmWxPebiResultColorScaleSettingsDlg::parseFiniteValue(
return true;
}
+bool nmWxPebiResultColorScaleSettingsDlg::convertUnitValue(
+ double dSourceValue,
+ const QString& sSourceUnit,
+ const QString& sDestinationUnit,
+ double& dDestinationValue) const
+{
+ if(!isFiniteEditorValue(dSourceValue)) {
+ return false;
+ }
+ if(sSourceUnit == sDestinationUnit) {
+ dDestinationValue = dSourceValue;
+ return true;
+ }
+ if(sSourceUnit.isEmpty() || sDestinationUnit.isEmpty() ||
+ m_pUnitGroup == nullptr ||
+ m_pUnitGroup->indexOf(sSourceUnit) < 0 ||
+ m_pUnitGroup->indexOf(sDestinationUnit) < 0) {
+ return false;
+ }
+
+ int nDigit = 12;
+ double dCandidate = 0.0;
+ if(!m_pUnitGroup->convert(
+ sSourceUnit, dSourceValue,
+ sDestinationUnit, dCandidate, nDigit) ||
+ !isFiniteEditorValue(dCandidate)) {
+ return false;
+ }
+ dDestinationValue = dCandidate;
+ return true;
+}
+
+bool nmWxPebiResultColorScaleSettingsDlg::convertBaseRangeToDisplay(
+ const double dBaseRange[2],
+ double dDisplayRange[2]) const
+{
+ double dMinimum = 0.0;
+ double dMaximum = 0.0;
+ if(!convertUnitValue(
+ dBaseRange[0], m_sBaseUnit,
+ m_sDisplayUnit, dMinimum) ||
+ !convertUnitValue(
+ dBaseRange[1], m_sBaseUnit,
+ m_sDisplayUnit, dMaximum)) {
+ return false;
+ }
+ dDisplayRange[0] = dMinimum;
+ dDisplayRange[1] = dMaximum;
+ return true;
+}
+
+void nmWxPebiResultColorScaleSettingsDlg::refreshRangeToolTips()
+{
+ const QString sUnitSuffix = m_sDisplayUnit.isEmpty()
+ ? QString() : QString::fromLatin1(" (") +
+ m_sDisplayUnit + QString::fromLatin1(")");
+ m_pMinimumEdit->setToolTip(tr("Minimum") + sUnitSuffix);
+ m_pMaximumEdit->setToolTip(tr("Maximum") + sUnitSuffix);
+}
+
+void nmWxPebiResultColorScaleSettingsDlg::refreshRangeColorButtons()
+{
+ const QString sColorMapId = m_pColorMapCombo->itemData(
+ m_pColorMapCombo->currentIndex()).toString();
+ QColor oMinimumColor;
+ QColor oMaximumColor;
+ const bool bHasMinimumColor = nmVTKColorMapCatalog::getColor(
+ sColorMapId, 0.0, oMinimumColor);
+ const bool bAutomaticConstant = !m_bManualRangeEdited &&
+ m_dPropertyRange[0] == m_dPropertyRange[1];
+ const bool bHasMaximumColor = bAutomaticConstant
+ ? bHasMinimumColor
+ : nmVTKColorMapCatalog::getColor(
+ sColorMapId, 1.0, oMaximumColor);
+ if(bAutomaticConstant && bHasMinimumColor) {
+ oMaximumColor = oMinimumColor;
+ }
+
+ const bool bUseBelowColor = m_pBelowRangeCheck->isChecked();
+ const bool bUseAboveColor = m_pAboveRangeCheck->isChecked();
+ m_pBelowColorButton->setEnabled(bUseBelowColor);
+ m_pAboveColorButton->setEnabled(bUseAboveColor);
+ updateColorButton(
+ m_pBelowColorButton,
+ !bUseBelowColor && bHasMinimumColor
+ ? oMinimumColor : m_oEditedBelowRangeColor);
+ updateColorButton(
+ m_pAboveColorButton,
+ !bUseAboveColor && bHasMaximumColor
+ ? oMaximumColor : m_oEditedAboveRangeColor);
+}
+
void nmWxPebiResultColorScaleSettingsDlg::updateColorButton(
QPushButton* pButton,
const QColor& oColor)
@@ -477,7 +785,10 @@ void nmWxPebiResultColorScaleSettingsDlg::updateColorButton(
return;
}
pButton->setStyleSheet(QString::fromLatin1(
- "QPushButton { background-color: rgb(%1,%2,%3); border: 1px solid #666; }")
+ "QPushButton { background-color: rgb(%1,%2,%3); "
+ "border: 1px solid #666; } "
+ "QPushButton:disabled { background-color: rgb(%1,%2,%3); "
+ "border: 1px solid #888; }")
.arg(oColor.red()).arg(oColor.green()).arg(oColor.blue()));
}