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/nmWxPropertyInterpolationDl...

920 lines
31 KiB
C++

#include "nmWxPropertyInterpolationDlg.h"
#include <QAbstractItemView>
#include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QCoreApplication>
#include <QDoubleSpinBox>
#include <QEvent>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include <QMouseEvent>
#include <QPainter>
#include <QPushButton>
#include <QSize>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QTransform>
#include <QVBoxLayout>
#include "nmGuiPlot.h"
#include "nmObjPoint.h"
#include "tCurvePlotView.h"
#include "ZxObjText.h"
#include "ZxPlot.h"
namespace
{
// 使用独立翻译上下文,便于统一维护对话框文本.
QString interpolationText(const char* sourceText)
{
return QCoreApplication::translate("nmWxPropertyInterpolationDlg", sourceText);
}
// 创建统一格式的非负数值输入框.
QDoubleSpinBox* createNumberSpinBox(QWidget* parent, double value)
{
QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent);
spinBox->setRange(0.0, 1.0e12);
spinBox->setDecimals(6);
spinBox->setValue(value);
spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
return spinBox;
}
// 插值测点使用独立的小方块标记,避免与井图元混淆.
class PropertyInterpolationMarker : public nmObjPoint
{
public:
PropertyInterpolationMarker(const QString& name,
ZxSubAxisX* axisX,
ZxSubAxisY* axisY)
: nmObjPoint(name, axisX, axisY)
{
setDotRadius(1.0);
}
virtual bool drawWellPos(QPainter* painter, QPointF point) override
{
if(painter == NULL) {
return false;
}
const QTransform transform = painter->combinedTransform();
qreal scaleX = qAbs(transform.m11());
qreal scaleY = qAbs(transform.m22());
if(scaleX < 0.0001) {
scaleX = 1.0;
}
if(scaleY < 0.0001) {
scaleY = 1.0;
}
const qreal halfPixelSize = 3.0;
QRectF markerRect(point.x() - halfPixelSize / scaleX,
point.y() - halfPixelSize / scaleY,
halfPixelSize * 2.0 / scaleX,
halfPixelSize * 2.0 / scaleY);
painter->save();
QPen pen(QColor(0, 25, 100));
pen.setWidthF(1.0);
pen.setCosmetic(true);
painter->setPen(pen);
painter->setBrush(QColor(0, 70, 200));
painter->drawRect(markerRect);
painter->restore();
return true;
}
};
void setMarkerLabel(nmObjPoint* marker, const QString& text)
{
if(marker == NULL || marker->getChildren().isEmpty()) {
return;
}
ZxObjText* label = dynamic_cast<ZxObjText*>(marker->at(0));
if(label != NULL) {
label->setText(text);
label->setTextColor(QColor(30, 30, 30));
}
}
}
nmWxPropertyInterpolationDlg::nmWxPropertyInterpolationDlg(
nmGuiPlot* plot,
nmDataAnalyzeManager* dataManager,
QWidget* parent)
: iDlgBase(parent),
m_pPlot(plot),
m_pDataManager(dataManager),
m_pDataSetCombo(NULL),
m_pAddDataSetButton(NULL),
m_pDeleteDataSetButton(NULL),
m_nCurrentDataSetIndex(-1),
m_nNextPointId(0),
m_bUpdatingUi(true),
m_pPropertyCombo(NULL),
m_pNameEdit(NULL),
m_pNewValueSpin(NULL),
m_pMapPickButton(NULL),
m_pPointTable(NULL),
m_pDeletePointButton(NULL),
m_pClearPointsButton(NULL),
m_pShowPointsCheck(NULL),
m_pShowLabelsCheck(NULL),
m_pNuggetSpin(NULL),
m_pSillSpin(NULL),
m_pRangeSpin(NULL),
m_pModelCombo(NULL),
m_pPreviewButton(NULL),
m_pApplyButton(NULL)
{
setWindowTitle(interpolationText("Property Interpolation"));
setWindowModality(Qt::NonModal);
setModal(false);
setMinimumSize(520, 620);
resize(560, 680);
initInterpolationUI();
initializeDataSets();
if(qApp != NULL) {
qApp->installEventFilter(this);
}
}
nmWxPropertyInterpolationDlg::~nmWxPropertyInterpolationDlg()
{
if(qApp != NULL) {
qApp->removeEventFilter(this);
}
onMapPickToggled(false);
saveCurrentDataSet();
syncDataSetsToManager(false);
removeAllMarkers();
}
void nmWxPropertyInterpolationDlg::initInterpolationUI()
{
QVBoxLayout* mainLayout = new QVBoxLayout(this);
// 数据组创建、切换及删除.
QHBoxLayout* dataSetSelectLayout = new QHBoxLayout;
dataSetSelectLayout->addWidget(new QLabel(interpolationText("Dataset:"), this));
m_pDataSetCombo = new QComboBox(this);
dataSetSelectLayout->addWidget(m_pDataSetCombo, 1);
QString iconDir = QCoreApplication::applicationDirPath();
iconDir = iconDir.section('/', 0, -2) + "/Res/Icon/";
m_pAddDataSetButton = new QPushButton(this);
m_pAddDataSetButton->setIcon(QIcon(iconDir + "Add.png"));
m_pAddDataSetButton->setIconSize(QSize(18, 18));
m_pAddDataSetButton->setFixedSize(28, 28);
m_pAddDataSetButton->setToolTip(interpolationText("Add dataset"));
dataSetSelectLayout->addWidget(m_pAddDataSetButton);
m_pDeleteDataSetButton = new QPushButton(this);
m_pDeleteDataSetButton->setIcon(QIcon(iconDir + "NmDelete.png"));
m_pDeleteDataSetButton->setIconSize(QSize(18, 18));
m_pDeleteDataSetButton->setFixedSize(28, 28);
m_pDeleteDataSetButton->setToolTip(interpolationText("Delete dataset"));
dataSetSelectLayout->addWidget(m_pDeleteDataSetButton);
mainLayout->addLayout(dataSetSelectLayout);
// 当前数据组的名称和属性.
QFormLayout* dataSetLayout = new QFormLayout;
m_pNameEdit = new QLineEdit(this);
dataSetLayout->addRow(interpolationText("Name:"), m_pNameEdit);
m_pPropertyCombo = new QComboBox(this);
m_pPropertyCombo->addItem(interpolationText("Permeability k"), QString("k"));
m_pPropertyCombo->addItem(interpolationText("Porosity phi"), QString("phi"));
m_pPropertyCombo->addItem(interpolationText("Reservoir thickness h"), QString("h"));
dataSetLayout->addRow(interpolationText("Property:"), m_pPropertyCombo);
mainLayout->addLayout(dataSetLayout);
// 测点数据录入区域.
QGroupBox* pointGroup = new QGroupBox(interpolationText("Measurement Points"), this);
QVBoxLayout* pointLayout = new QVBoxLayout(pointGroup);
QHBoxLayout* newPointLayout = new QHBoxLayout;
newPointLayout->addWidget(new QLabel(interpolationText("New value:"), pointGroup));
m_pNewValueSpin = createNumberSpinBox(pointGroup, 0.0);
newPointLayout->addWidget(m_pNewValueSpin, 1);
m_pMapPickButton = new QPushButton(interpolationText("Select on Map"), pointGroup);
m_pMapPickButton->setCheckable(true);
m_pMapPickButton->setEnabled(!m_pPlot.isNull() &&
m_pPlot->m_pPlotView != NULL &&
m_pPlot->m_pPlot != NULL);
newPointLayout->addWidget(m_pMapPickButton);
pointLayout->addLayout(newPointLayout);
m_pPointTable = new QTableWidget(0, 3, pointGroup);
QStringList headers;
headers << interpolationText("X") << interpolationText("Y") << interpolationText("Value");
m_pPointTable->setHorizontalHeaderLabels(headers);
m_pPointTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
m_pPointTable->setSelectionBehavior(QAbstractItemView::SelectRows);
m_pPointTable->setSelectionMode(QAbstractItemView::SingleSelection);
m_pPointTable->setAlternatingRowColors(true);
pointLayout->addWidget(m_pPointTable, 1);
QHBoxLayout* pointButtonLayout = new QHBoxLayout;
pointButtonLayout->addStretch();
m_pDeletePointButton = new QPushButton(interpolationText("Delete Selected"), pointGroup);
m_pDeletePointButton->setEnabled(false);
pointButtonLayout->addWidget(m_pDeletePointButton);
m_pClearPointsButton = new QPushButton(interpolationText("Clear"), pointGroup);
m_pClearPointsButton->setEnabled(false);
pointButtonLayout->addWidget(m_pClearPointsButton);
pointLayout->addLayout(pointButtonLayout);
QHBoxLayout* displayLayout = new QHBoxLayout;
m_pShowPointsCheck = new QCheckBox(interpolationText("Show measurement points"), pointGroup);
m_pShowPointsCheck->setChecked(true);
displayLayout->addWidget(m_pShowPointsCheck);
m_pShowLabelsCheck = new QCheckBox(interpolationText("Show labels"), pointGroup);
m_pShowLabelsCheck->setChecked(true);
displayLayout->addWidget(m_pShowLabelsCheck);
displayLayout->addStretch();
pointLayout->addLayout(displayLayout);
mainLayout->addWidget(pointGroup, 1);
// Kriging插值参数设置.
QGroupBox* parameterGroup = new QGroupBox(interpolationText("Kriging Parameters"), this);
QFormLayout* parameterLayout = new QFormLayout(parameterGroup);
m_pNuggetSpin = createNumberSpinBox(parameterGroup, 0.01);
parameterLayout->addRow(interpolationText("Nugget:"), m_pNuggetSpin);
m_pSillSpin = createNumberSpinBox(parameterGroup, 100.0);
parameterLayout->addRow(interpolationText("Sill:"), m_pSillSpin);
m_pRangeSpin = createNumberSpinBox(parameterGroup, 1000.0);
parameterLayout->addRow(interpolationText("Range:"), m_pRangeSpin);
m_pModelCombo = new QComboBox(parameterGroup);
m_pModelCombo->addItem(interpolationText("Spherical (0)"), 0);
m_pModelCombo->addItem(interpolationText("Exponential (1)"), 1);
m_pModelCombo->addItem(interpolationText("Gaussian (2)"), 2);
parameterLayout->addRow(interpolationText("Model:"), m_pModelCombo);
mainLayout->addWidget(parameterGroup);
// 底部操作按钮.
QHBoxLayout* buttonLayout = new QHBoxLayout;
m_pPreviewButton = new QPushButton(interpolationText("Preview"), this);
m_pPreviewButton->setEnabled(false);
buttonLayout->addWidget(m_pPreviewButton);
buttonLayout->addStretch();
m_pApplyButton = new QPushButton(interpolationText("Apply"), this);
m_pApplyButton->setEnabled(false);
buttonLayout->addWidget(m_pApplyButton);
QPushButton* closeButton = new QPushButton(interpolationText("Close"), this);
buttonLayout->addWidget(closeButton);
mainLayout->addLayout(buttonLayout);
connect(m_pDataSetCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(onDataSetChanged(int)));
connect(m_pAddDataSetButton, SIGNAL(clicked()), this, SLOT(onAddDataSet()));
connect(m_pDeleteDataSetButton, SIGNAL(clicked()), this, SLOT(onDeleteDataSet()));
connect(m_pNameEdit, SIGNAL(textChanged(QString)),
this, SLOT(onDataSetNameChanged(QString)));
connect(m_pPropertyCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(onCurrentDataSetEdited()));
connect(m_pNuggetSpin, SIGNAL(valueChanged(double)),
this, SLOT(onCurrentDataSetEdited()));
connect(m_pSillSpin, SIGNAL(valueChanged(double)),
this, SLOT(onCurrentDataSetEdited()));
connect(m_pRangeSpin, SIGNAL(valueChanged(double)),
this, SLOT(onCurrentDataSetEdited()));
connect(m_pModelCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(onCurrentDataSetEdited()));
connect(m_pMapPickButton, SIGNAL(toggled(bool)), this, SLOT(onMapPickToggled(bool)));
connect(m_pPointTable, SIGNAL(itemSelectionChanged()),
this, SLOT(onPointSelectionChanged()));
connect(m_pPointTable, SIGNAL(itemChanged(QTableWidgetItem*)),
this, SLOT(onPointItemChanged(QTableWidgetItem*)));
connect(m_pDeletePointButton, SIGNAL(clicked()), this, SLOT(onDeleteSelectedPoint()));
connect(m_pClearPointsButton, SIGNAL(clicked()), this, SLOT(onClearPoints()));
connect(m_pShowPointsCheck, SIGNAL(toggled(bool)), this, SLOT(onShowPointsToggled(bool)));
connect(m_pShowLabelsCheck, SIGNAL(toggled(bool)), this, SLOT(onShowLabelsToggled(bool)));
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
}
void nmWxPropertyInterpolationDlg::initializeDataSets()
{
m_bUpdatingUi = true;
if(!m_pDataManager.isNull()) {
m_vecDataSets = m_pDataManager->getPropertyInterpolationDataSets();
}
bool dataChanged = false;
for(int i = 0; i < m_vecDataSets.size(); ++i) {
if(m_vecDataSets[i].name.isEmpty()) {
m_vecDataSets[i].name = nextDataSetName();
dataChanged = true;
}
}
m_vecMarkerNames.resize(m_vecDataSets.size());
createMarkersForAllDataSets();
bool oldBlock = m_pDataSetCombo->blockSignals(true);
m_pDataSetCombo->clear();
for(int i = 0; i < m_vecDataSets.size(); ++i) {
m_pDataSetCombo->addItem(m_vecDataSets[i].name);
}
const int initialIndex = m_vecDataSets.isEmpty() ? -1 : 0;
m_pDataSetCombo->setCurrentIndex(initialIndex);
m_pDataSetCombo->blockSignals(oldBlock);
m_nCurrentDataSetIndex = initialIndex;
loadDataSet(initialIndex);
m_bUpdatingUi = false;
updateDataSetButtons();
if(dataChanged) {
syncDataSetsToManager(false);
}
}
nmPropertyInterpolationDataSet nmWxPropertyInterpolationDlg::createDefaultDataSet()
{
nmPropertyInterpolationDataSet dataSet;
dataSet.name = nextDataSetName();
dataSet.property = "k";
dataSet.showPoints = true;
dataSet.showLabels = true;
dataSet.nugget = 0.01;
dataSet.sill = 100.0;
dataSet.range = 1000.0;
dataSet.model = 0;
return dataSet;
}
QString nmWxPropertyInterpolationDlg::nextDataSetName()
{
for(int number = 1; ; ++number) {
const QString name = interpolationText("Dataset #%1").arg(number);
bool exists = false;
for(int i = 0; i < m_vecDataSets.size(); ++i) {
if(m_vecDataSets[i].name == name) {
exists = true;
break;
}
}
if(!exists) {
return name;
}
}
}
void nmWxPropertyInterpolationDlg::loadDataSet(int index)
{
if(index < 0 || index >= m_vecDataSets.size()) {
clearCurrentDataSet();
return;
}
bool wasUpdating = m_bUpdatingUi;
m_bUpdatingUi = true;
const nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[index];
m_pNameEdit->setText(dataSet.name);
int propertyIndex = m_pPropertyCombo->findData(dataSet.property);
m_pPropertyCombo->setCurrentIndex(propertyIndex < 0 ? 0 : propertyIndex);
m_pNuggetSpin->setValue(dataSet.nugget);
m_pSillSpin->setValue(dataSet.sill);
m_pRangeSpin->setValue(dataSet.range);
int modelIndex = m_pModelCombo->findData(dataSet.model);
m_pModelCombo->setCurrentIndex(modelIndex < 0 ? 0 : modelIndex);
m_pShowPointsCheck->setChecked(dataSet.showPoints);
m_pShowLabelsCheck->setChecked(dataSet.showLabels);
bool oldTableBlock = m_pPointTable->blockSignals(true);
m_pPointTable->setRowCount(0);
const QStringList markerNames = m_vecMarkerNames.value(index);
for(int i = 0; i < dataSet.points.size(); ++i) {
appendPointRow(dataSet.points[i], markerNames.value(i));
}
m_pPointTable->blockSignals(oldTableBlock);
clearTableSelection();
updatePointButtons();
updateCurrentMarkerVisibility();
m_bUpdatingUi = wasUpdating;
updateDataSetButtons();
}
void nmWxPropertyInterpolationDlg::clearCurrentDataSet()
{
bool wasUpdating = m_bUpdatingUi;
m_bUpdatingUi = true;
if(m_pMapPickButton->isChecked()) {
m_pMapPickButton->setChecked(false);
}
m_pNameEdit->clear();
m_pPropertyCombo->setCurrentIndex(-1);
m_pNewValueSpin->setValue(0.0);
m_pPointTable->setRowCount(0);
m_pShowPointsCheck->setChecked(false);
m_pShowLabelsCheck->setChecked(false);
m_pNuggetSpin->setValue(0.01);
m_pSillSpin->setValue(100.0);
m_pRangeSpin->setValue(1000.0);
m_pModelCombo->setCurrentIndex(-1);
clearTableSelection();
m_bUpdatingUi = wasUpdating;
updateDataSetButtons();
}
void nmWxPropertyInterpolationDlg::saveCurrentDataSet()
{
if(m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[m_nCurrentDataSetIndex];
dataSet.name = m_pNameEdit->text();
dataSet.property = m_pPropertyCombo->itemData(m_pPropertyCombo->currentIndex()).toString();
dataSet.nugget = m_pNuggetSpin->value();
dataSet.sill = m_pSillSpin->value();
dataSet.range = m_pRangeSpin->value();
dataSet.model = m_pModelCombo->itemData(m_pModelCombo->currentIndex()).toInt();
dataSet.showPoints = m_pShowPointsCheck->isChecked();
dataSet.showLabels = m_pShowLabelsCheck->isChecked();
}
void nmWxPropertyInterpolationDlg::syncDataSetsToManager(bool markModified)
{
if(!m_pDataManager.isNull()) {
m_pDataManager->setPropertyInterpolationDataSets(m_vecDataSets);
}
if(markModified && !m_pPlot.isNull()) {
m_pPlot->setModified(true);
}
}
void nmWxPropertyInterpolationDlg::updateDataSetButtons()
{
const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
m_nCurrentDataSetIndex < m_vecDataSets.size();
const bool canPickOnMap = hasCurrent && !m_pPlot.isNull() &&
m_pPlot->m_pPlotView != NULL && m_pPlot->m_pPlot != NULL;
m_pDataSetCombo->setEnabled(hasCurrent);
m_pDeleteDataSetButton->setEnabled(hasCurrent);
m_pNameEdit->setEnabled(hasCurrent);
m_pPropertyCombo->setEnabled(hasCurrent);
m_pNewValueSpin->setEnabled(hasCurrent);
m_pMapPickButton->setEnabled(canPickOnMap);
m_pPointTable->setEnabled(hasCurrent);
m_pShowPointsCheck->setEnabled(hasCurrent);
m_pShowLabelsCheck->setEnabled(hasCurrent);
m_pNuggetSpin->setEnabled(hasCurrent);
m_pSillSpin->setEnabled(hasCurrent);
m_pRangeSpin->setEnabled(hasCurrent);
m_pModelCombo->setEnabled(hasCurrent);
updatePointButtons();
}
void nmWxPropertyInterpolationDlg::onDataSetChanged(int index)
{
if(m_bUpdatingUi || index < 0 || index >= m_vecDataSets.size() ||
index == m_nCurrentDataSetIndex) {
return;
}
saveCurrentDataSet();
syncDataSetsToManager(false);
m_nCurrentDataSetIndex = index;
loadDataSet(index);
}
void nmWxPropertyInterpolationDlg::onAddDataSet()
{
saveCurrentDataSet();
m_vecDataSets.append(createDefaultDataSet());
m_vecMarkerNames.append(QStringList());
int newIndex = m_vecDataSets.size() - 1;
bool oldBlock = m_pDataSetCombo->blockSignals(true);
m_pDataSetCombo->addItem(m_vecDataSets[newIndex].name);
m_pDataSetCombo->setCurrentIndex(newIndex);
m_pDataSetCombo->blockSignals(oldBlock);
m_nCurrentDataSetIndex = newIndex;
loadDataSet(newIndex);
updateDataSetButtons();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onDeleteDataSet()
{
if(m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
int removedIndex = m_nCurrentDataSetIndex;
removeDataSetMarkers(removedIndex);
m_vecDataSets.remove(removedIndex);
m_vecMarkerNames.remove(removedIndex);
const int newIndex = m_vecDataSets.isEmpty() ? -1 :
qMin(removedIndex, m_vecDataSets.size() - 1);
bool oldBlock = m_pDataSetCombo->blockSignals(true);
m_pDataSetCombo->removeItem(removedIndex);
m_pDataSetCombo->setCurrentIndex(newIndex);
m_pDataSetCombo->blockSignals(oldBlock);
m_nCurrentDataSetIndex = newIndex;
loadDataSet(newIndex);
updateDataSetButtons();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onDataSetNameChanged(const QString& name)
{
if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
m_vecDataSets[m_nCurrentDataSetIndex].name = name;
m_pDataSetCombo->setItemText(m_nCurrentDataSetIndex, name);
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onCurrentDataSetEdited()
{
if(m_bUpdatingUi) {
return;
}
saveCurrentDataSet();
syncDataSetsToManager(true);
}
bool nmWxPropertyInterpolationDlg::eventFilter(QObject* watched, QEvent* event)
{
if(event != NULL && event->type() == QEvent::MouseButtonPress && m_pPointTable != NULL) {
QWidget* clickedWidget = qobject_cast<QWidget*>(watched);
if(clickedWidget != NULL) {
bool isTableViewport = clickedWidget == m_pPointTable->viewport() ||
m_pPointTable->viewport()->isAncestorOf(clickedWidget);
if(clickedWidget == m_pPointTable->viewport()) {
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if(m_pPointTable->itemAt(mouseEvent->pos()) == NULL) {
clearTableSelection();
}
} else if(!isTableViewport && clickedWidget != m_pDeletePointButton) {
clearTableSelection();
}
}
}
return iDlgBase::eventFilter(watched, event);
}
void nmWxPropertyInterpolationDlg::onMapPickToggled(bool checked)
{
if(m_pPlot.isNull() || m_pPlot->m_pPlotView == NULL) {
return;
}
disconnect(m_pPlot->m_pPlotView, SIGNAL(sigLeftClick(QPointF)),
this, SLOT(onMapClicked(QPointF)));
if(checked) {
m_pPlot->cancelActiveTools();
connect(m_pPlot->m_pPlotView, SIGNAL(sigLeftClick(QPointF)),
this, SLOT(onMapClicked(QPointF)));
m_pPlot->m_pPlotView->setCursor(Qt::CrossCursor);
} else {
m_pPlot->m_pPlotView->restoreCursor();
}
}
void nmWxPropertyInterpolationDlg::onMapClicked(const QPointF& position)
{
if(!m_pMapPickButton->isChecked() || m_pPlot.isNull() ||
m_pPlot->m_pPlot == NULL || m_nCurrentDataSetIndex < 0) {
return;
}
if(!m_pPlot->m_pPlot->getInnerRectF().contains(position)) {
return;
}
QPointF plotPosition = position;
QPointF valuePoint = m_pPlot->m_pPlot->getValueForPos(plotPosition);
appendPoint(valuePoint);
}
void nmWxPropertyInterpolationDlg::appendPoint(const QPointF& valuePoint)
{
if(m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[m_nCurrentDataSetIndex];
double pointValue = m_pNewValueSpin->value();
nmPropertyInterpolationPointData point(valuePoint.x(), valuePoint.y(), pointValue);
QString markerName = createMarker(valuePoint, pointValue,
dataSet.showPoints, dataSet.showLabels);
dataSet.points.append(point);
m_vecMarkerNames[m_nCurrentDataSetIndex].append(markerName);
bool oldBlock = m_pPointTable->blockSignals(true);
appendPointRow(point, markerName);
m_pPointTable->blockSignals(oldBlock);
m_pPointTable->scrollToBottom();
updatePointButtons();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::appendPointRow(
const nmPropertyInterpolationPointData& point,
const QString& markerName)
{
int row = m_pPointTable->rowCount();
m_pPointTable->insertRow(row);
QTableWidgetItem* xItem = new QTableWidgetItem(QString::number(point.x, 'g', 15));
xItem->setFlags(xItem->flags() & ~Qt::ItemIsEditable);
xItem->setData(Qt::UserRole, markerName);
m_pPointTable->setItem(row, 0, xItem);
QTableWidgetItem* yItem = new QTableWidgetItem(QString::number(point.y, 'g', 15));
yItem->setFlags(yItem->flags() & ~Qt::ItemIsEditable);
m_pPointTable->setItem(row, 1, yItem);
m_pPointTable->setItem(row, 2,
new QTableWidgetItem(QString::number(point.value, 'f', 6)));
}
QString nmWxPropertyInterpolationDlg::createMarker(const QPointF& valuePosition,
double value,
bool showPoints,
bool showLabels)
{
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL) {
return QString();
}
QString markerName;
do {
markerName = QString("__PropertyInterpolationPoint_%1").arg(++m_nNextPointId);
} while(m_pPlot->m_pPlot->getObjByName(markerName) != NULL);
bool wasModified = m_pPlot->isModified();
PropertyInterpolationMarker* marker = new PropertyInterpolationMarker(
markerName,
m_pPlot->m_pPlot->getMainAxisX(),
m_pPlot->m_pPlot->getMainAxisY());
m_pPlot->bindObjSignals(marker);
if(!m_pPlot->m_pPlot->addOneObj(marker)) {
delete marker;
m_pPlot->setModified(wasModified);
return QString();
}
QVector<QPointF> values;
values.append(valuePosition);
marker->setAllValues(values);
m_pPlot->slotObjCompleted(marker);
setMarkerLabel(marker, QString::number(value, 'g', 10));
marker->setReadOnly(true);
marker->setLockPos(true);
marker->showSubObjs(showPoints && showLabels);
marker->setVisible(showPoints);
marker->deselect(true);
marker->update();
m_pPlot->setModified(wasModified);
return markerName;
}
void nmWxPropertyInterpolationDlg::createMarkersForAllDataSets()
{
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL) {
return;
}
for(int dataSetIndex = 0; dataSetIndex < m_vecDataSets.size(); ++dataSetIndex) {
const nmPropertyInterpolationDataSet& dataSet = m_vecDataSets[dataSetIndex];
QStringList markerNames;
for(int pointIndex = 0; pointIndex < dataSet.points.size(); ++pointIndex) {
const nmPropertyInterpolationPointData& point = dataSet.points[pointIndex];
QPointF valuePosition(point.x, point.y);
markerNames.append(createMarker(valuePosition, point.value,
dataSet.showPoints, dataSet.showLabels));
}
m_vecMarkerNames[dataSetIndex] = markerNames;
}
}
void nmWxPropertyInterpolationDlg::removeDataSetMarkers(int dataSetIndex)
{
if(dataSetIndex < 0 || dataSetIndex >= m_vecMarkerNames.size()) {
return;
}
const QStringList markerNames = m_vecMarkerNames[dataSetIndex];
for(int i = 0; i < markerNames.size(); ++i) {
removeMarkerByName(markerNames[i]);
}
m_vecMarkerNames[dataSetIndex].clear();
}
void nmWxPropertyInterpolationDlg::removeAllMarkers()
{
for(int i = 0; i < m_vecMarkerNames.size(); ++i) {
removeDataSetMarkers(i);
}
m_vecMarkerNames.clear();
}
QString nmWxPropertyInterpolationDlg::markerNameAt(int row) const
{
if(m_pPointTable == NULL || row < 0 || row >= m_pPointTable->rowCount()) {
return QString();
}
QTableWidgetItem* item = m_pPointTable->item(row, 0);
return item == NULL ? QString() : item->data(Qt::UserRole).toString();
}
nmObjPoint* nmWxPropertyInterpolationDlg::markerByName(const QString& markerName) const
{
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL || markerName.isEmpty()) {
return NULL;
}
return dynamic_cast<nmObjPoint*>(m_pPlot->m_pPlot->getObjByName(markerName));
}
nmObjPoint* nmWxPropertyInterpolationDlg::markerAt(int row) const
{
return markerByName(markerNameAt(row));
}
void nmWxPropertyInterpolationDlg::removeMarkerByName(const QString& markerName)
{
if(m_pPlot.isNull() || m_pPlot->m_pPlot == NULL || markerName.isEmpty() ||
m_pPlot->m_pPlot->getObjByName(markerName) == NULL) {
return;
}
bool wasModified = m_pPlot->isModified();
m_pPlot->m_pPlot->removeObjByName(markerName);
m_pPlot->setModified(wasModified);
}
void nmWxPropertyInterpolationDlg::onPointSelectionChanged()
{
updatePointButtons();
}
void nmWxPropertyInterpolationDlg::onPointItemChanged(QTableWidgetItem* item)
{
if(m_bUpdatingUi || item == NULL || item->column() != 2 ||
m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size() ||
item->row() >= m_vecDataSets[m_nCurrentDataSetIndex].points.size()) {
return;
}
m_vecDataSets[m_nCurrentDataSetIndex].points[item->row()].value = item->text().toDouble();
nmObjPoint* marker = markerAt(item->row());
if(marker != NULL) {
setMarkerLabel(marker, item->text());
marker->update();
}
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onDeleteSelectedPoint()
{
int row = m_pPointTable->currentRow();
if(row < 0 || m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
removeMarkerByName(markerNameAt(row));
if(row < m_vecDataSets[m_nCurrentDataSetIndex].points.size()) {
m_vecDataSets[m_nCurrentDataSetIndex].points.remove(row);
}
if(row < m_vecMarkerNames[m_nCurrentDataSetIndex].size()) {
m_vecMarkerNames[m_nCurrentDataSetIndex].removeAt(row);
}
m_pPointTable->removeRow(row);
clearTableSelection();
updatePointButtons();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onClearPoints()
{
if(m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
removeDataSetMarkers(m_nCurrentDataSetIndex);
m_vecDataSets[m_nCurrentDataSetIndex].points.clear();
m_pPointTable->setRowCount(0);
clearTableSelection();
updatePointButtons();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onShowPointsToggled(bool checked)
{
if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
m_vecDataSets[m_nCurrentDataSetIndex].showPoints = checked;
updateCurrentMarkerVisibility();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::onShowLabelsToggled(bool checked)
{
if(m_bUpdatingUi || m_nCurrentDataSetIndex < 0 ||
m_nCurrentDataSetIndex >= m_vecDataSets.size()) {
return;
}
m_vecDataSets[m_nCurrentDataSetIndex].showLabels = checked;
updateCurrentMarkerVisibility();
syncDataSetsToManager(true);
}
void nmWxPropertyInterpolationDlg::clearTableSelection()
{
m_pPointTable->clearSelection();
m_pPointTable->setCurrentCell(-1, -1);
}
void nmWxPropertyInterpolationDlg::updatePointButtons()
{
const bool hasCurrent = m_nCurrentDataSetIndex >= 0 &&
m_nCurrentDataSetIndex < m_vecDataSets.size();
m_pDeletePointButton->setEnabled(hasCurrent && m_pPointTable->currentRow() >= 0);
m_pClearPointsButton->setEnabled(hasCurrent && m_pPointTable->rowCount() > 0);
}
void nmWxPropertyInterpolationDlg::updateCurrentMarkerVisibility()
{
// 地图上只显示当前数据组的测点,其他数据组统一隐藏.
for(int dataSetIndex = 0;
dataSetIndex < m_vecMarkerNames.size(); ++dataSetIndex) {
const bool isCurrentDataSet = dataSetIndex == m_nCurrentDataSetIndex &&
dataSetIndex < m_vecDataSets.size();
const bool showPoints = isCurrentDataSet &&
m_vecDataSets[dataSetIndex].showPoints;
const bool showLabels = showPoints &&
m_vecDataSets[dataSetIndex].showLabels;
const QStringList markerNames = m_vecMarkerNames[dataSetIndex];
for(int markerIndex = 0; markerIndex < markerNames.size(); ++markerIndex) {
nmObjPoint* marker = markerByName(markerNames[markerIndex]);
if(marker != NULL) {
marker->setVisible(showPoints);
marker->showSubObjs(showLabels);
marker->update();
}
}
}
if(!m_pPlot.isNull() && m_pPlot->m_pPlotView != NULL) {
m_pPlot->m_pPlotView->updateViewport();
}
}