From a5eec7c91c4bbf3d0478afdc36af8ad2d804172d Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Mon, 6 Jun 2022 11:19:49 -0500 Subject: [PATCH] Finished Array Visualizer having a X, Y, XX, YY, or XY arrays. --- src/SeerArrayVisualizerWidget.cpp | 277 +++++++++++++++++++++++------- src/SeerArrayVisualizerWidget.h | 8 +- src/SeerArrayVisualizerWidget.ui | 14 +- src/SeerArrayWidget.cpp | 18 ++ src/SeerArrayWidget.h | 6 + 5 files changed, 255 insertions(+), 68 deletions(-) diff --git a/src/SeerArrayVisualizerWidget.cpp b/src/SeerArrayVisualizerWidget.cpp index 98bf27b..f3022c8 100644 --- a/src/SeerArrayVisualizerWidget.cpp +++ b/src/SeerArrayVisualizerWidget.cpp @@ -24,7 +24,8 @@ SeerArrayVisualizerWidget::SeerArrayVisualizerWidget (QWidget* parent) : QWidget _bVariableId = Seer::createID(); // Create two id's for queries. _bMemoryId = Seer::createID(); - _series = 0; + _aSeries = 0; + _bSeries = 0; // Set up UI. setupUi(this); @@ -76,6 +77,8 @@ SeerArrayVisualizerWidget::SeerArrayVisualizerWidget (QWidget* parent) : QWidget QObject::connect(bVariableNameLineEdit, &QLineEdit::returnPressed, this, &SeerArrayVisualizerWidget::handlebVariableNameLineEdit); QObject::connect(aArrayDisplayFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerArrayVisualizerWidget::handleaArrayDisplayFormatComboBox); QObject::connect(bArrayDisplayFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerArrayVisualizerWidget::handlebArrayDisplayFormatComboBox); + QObject::connect(aAxisComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerArrayVisualizerWidget::handleaAxisComboBox); + QObject::connect(bAxisComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerArrayVisualizerWidget::handlebAxisComboBox); QObject::connect(arrayTableWidget, &SeerArrayWidget::dataChanged, this, &SeerArrayVisualizerWidget::handleDataChanged); QObject::connect(splitter, &QSplitter::splitterMoved, this, &SeerArrayVisualizerWidget::handleSplitterMoved); @@ -541,81 +544,127 @@ void SeerArrayVisualizerWidget::handlebArrayDisplayFormatComboBox (int index) { } } +void SeerArrayVisualizerWidget::handleaAxisComboBox (int index) { + + arrayTableWidget->setAAxis(aAxisComboBox->itemText(index)); + + handleDataChanged(); +} + +void SeerArrayVisualizerWidget::handlebAxisComboBox (int index) { + + arrayTableWidget->setBAxis(bAxisComboBox->itemText(index)); + + handleDataChanged(); +} + void SeerArrayVisualizerWidget::handleDataChanged () { - if (_series) { - arrayChartView->chart()->removeSeries(_series); + // Delete old series. + if (_aSeries) { + arrayChartView->chart()->removeSeries(_aSeries); arrayChartView->chart()->update(); - delete _series; - _series = 0; + delete _aSeries; + _aSeries = 0; } - if (scatterRadioButton->isChecked()) { - - QScatterSeries* scatter = new QScatterSeries; - scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle); - scatter->setMarkerSize(7); - _series = scatter; - - }else if (lineRadioButton->isChecked()) { - - QLineSeries* line = new QLineSeries; - _series = line; - - }else if (splineRadioButton->isChecked()) { - - QSplineSeries* line = new QSplineSeries; - _series = line; + if (_bSeries) { + arrayChartView->chart()->removeSeries(_bSeries); + arrayChartView->chart()->update(); + delete _bSeries; + _bSeries = 0; } - if (_series == 0) { - return; - } - - _series->setPointsVisible(false); - _series->setPointLabelsVisible(false); - _series->setPointLabelsClipping(true); - - + // If only the first array is defined, create a series for it. + // Handle the X and Y axis. if (arrayTableWidget->aSize() > 0 && arrayTableWidget->bSize() == 0) { - const QVector& values = arrayTableWidget->aArrayValues(); - - for (int i = 0; i < values.size(); ++i) { - _series->append(i, values[i]); - } - - _series->setName(QString("%1:%2:%3").arg(arrayTableWidget->aLabel()).arg(arrayTableWidget->aAddressOffset()).arg(arrayTableWidget->aAddressStride())); + createASeries(); + // If only the second array is defined, create a series for it. + // Handle the X and Y axis. }else if (arrayTableWidget->aSize() == 0 && arrayTableWidget->bSize() > 0) { - const QVector& values = arrayTableWidget->bArrayValues(); - - for (int i = 0; i < values.size(); ++i) { - _series->append(i, values[i]); - } - - _series->setName(QString("%1:%2:%3").arg(arrayTableWidget->bLabel()).arg(arrayTableWidget->bAddressOffset()).arg(arrayTableWidget->bAddressStride())); + createBSeries(); } else if (arrayTableWidget->aSize() > 0 && arrayTableWidget->bSize() > 0) { - const QVector& xvalues = arrayTableWidget->aArrayValues(); - const QVector& yvalues = arrayTableWidget->bArrayValues(); + // If the axis is the same for the two arrays, plot them as + // two unique series. + if (arrayTableWidget->aAxis() == arrayTableWidget->bAxis()) { - for (int i = 0; i < std::min(xvalues.size(),yvalues.size()); ++i) { - _series->append(xvalues[i], yvalues[i]); + createASeries(); + createBSeries(); + + // Otherwise, we have an X and Y axis. + // Plot one series using the two arrays as an X and as a Y. + }else{ + + if (scatterRadioButton->isChecked()) { + + QScatterSeries* scatter = new QScatterSeries; + scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle); + scatter->setMarkerSize(7); + _aSeries = scatter; + + }else if (lineRadioButton->isChecked()) { + + QLineSeries* line = new QLineSeries; + _aSeries = line; + + }else if (splineRadioButton->isChecked()) { + + QSplineSeries* line = new QSplineSeries; + _aSeries = line; + + }else{ + qWarning() << "Invalid line type."; + return; + } + + _aSeries->setPointsVisible(false); + _aSeries->setPointLabelsVisible(false); + _aSeries->setPointLabelsClipping(true); + + const QVector& xvalues = arrayTableWidget->aArrayValues(); + const QVector& yvalues = arrayTableWidget->bArrayValues(); + + if (arrayTableWidget->aAxis() == "Y" && arrayTableWidget->bAxis() == "X") { + + for (int i = 0; i < std::min(xvalues.size(),yvalues.size()); ++i) { + _aSeries->append(xvalues[i], yvalues[i]); + } + + }else if (arrayTableWidget->aAxis() == "X" && arrayTableWidget->bAxis() == "Y") { + + for (int i = 0; i < std::min(xvalues.size(),yvalues.size()); ++i) { + _aSeries->append(yvalues[i], xvalues[i]); + } + + }else{ + qWarning() << "Invalid axis type of '" << arrayTableWidget->aAxis() << "'. Not 'X' or 'Y'."; + } + + _aSeries->setName(aVariableName() + "/" + bVariableName()); + _aSeries->setName(QString("%1:%2:%3 | %4:%5:%6") + .arg(arrayTableWidget->aLabel()).arg(arrayTableWidget->aAddressOffset()).arg(arrayTableWidget->aAddressStride()) + .arg(arrayTableWidget->bLabel()).arg(arrayTableWidget->bAddressOffset()).arg(arrayTableWidget->bAddressStride())); } - - _series->setName(aVariableName() + "/" + bVariableName()); - _series->setName(QString("%1:%2:%3 | %4:%5:%6") - .arg(arrayTableWidget->aLabel()).arg(arrayTableWidget->aAddressOffset()).arg(arrayTableWidget->aAddressStride()) - .arg(arrayTableWidget->bLabel()).arg(arrayTableWidget->bAddressOffset()).arg(arrayTableWidget->bAddressStride())); } - QObject::connect(_series, &QLineSeries::hovered, this, &SeerArrayVisualizerWidget::handleSeriesHovered); + if (_aSeries) { + QObject::connect(_aSeries, &QLineSeries::hovered, this, &SeerArrayVisualizerWidget::handleSeriesHovered); - arrayChartView->chart()->addSeries(_series); - arrayChartView->chart()->createDefaultAxes(); + arrayChartView->chart()->addSeries(_aSeries); + arrayChartView->chart()->createDefaultAxes(); + } + + if (_bSeries) { + QObject::connect(_bSeries, &QLineSeries::hovered, this, &SeerArrayVisualizerWidget::handleSeriesHovered); + + arrayChartView->chart()->addSeries(_bSeries); + arrayChartView->chart()->createDefaultAxes(); + } // Zoom out slightly to allow for text label at edges. arrayChartView->chart()->zoomReset(); @@ -686,16 +735,26 @@ void SeerArrayVisualizerWidget::handleTitleLineEdit () { void SeerArrayVisualizerWidget::handlePointsCheckBox () { - if (_series) { - _series->setPointsVisible(pointsCheckBox->isChecked()); + if (_aSeries) { + _aSeries->setPointsVisible(pointsCheckBox->isChecked()); + arrayChartView->chart()->update(); + } + + if (_bSeries) { + _bSeries->setPointsVisible(pointsCheckBox->isChecked()); arrayChartView->chart()->update(); } } void SeerArrayVisualizerWidget::handleLabelsCheckBox () { - if (_series) { - _series->setPointLabelsVisible(labelsCheckBox->isChecked()); + if (_aSeries) { + _aSeries->setPointLabelsVisible(labelsCheckBox->isChecked()); + arrayChartView->chart()->update(); + } + + if (_bSeries) { + _bSeries->setPointLabelsVisible(labelsCheckBox->isChecked()); arrayChartView->chart()->update(); } } @@ -705,3 +764,101 @@ void SeerArrayVisualizerWidget::handleLineTypeButtonGroup () { handleDataChanged(); } +void SeerArrayVisualizerWidget::createASeries() { + + if (scatterRadioButton->isChecked()) { + + QScatterSeries* scatter = new QScatterSeries; + scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle); + scatter->setMarkerSize(7); + _aSeries = scatter; + + }else if (lineRadioButton->isChecked()) { + + QLineSeries* line = new QLineSeries; + _aSeries = line; + + }else if (splineRadioButton->isChecked()) { + + QSplineSeries* line = new QSplineSeries; + _aSeries = line; + + }else{ + qWarning() << "Invalid line type."; + return; + } + + _aSeries->setPointsVisible(false); + _aSeries->setPointLabelsVisible(false); + _aSeries->setPointLabelsClipping(true); + + const QVector& values = arrayTableWidget->aArrayValues(); + + if (arrayTableWidget->aAxis() == "Y") { + + for (int i = 0; i < values.size(); ++i) { + _aSeries->append(i, values[i]); + } + + }else if (arrayTableWidget->aAxis() == "X") { + + for (int i = 0; i < values.size(); ++i) { + _aSeries->append(values[i], i); + } + + }else{ + qWarning() << "Invalid axis type of '" << arrayTableWidget->aAxis() << "'. Not 'X' or 'Y'."; + } + + _aSeries->setName(QString("%1:%2:%3").arg(arrayTableWidget->aLabel()).arg(arrayTableWidget->aAddressOffset()).arg(arrayTableWidget->aAddressStride())); +} + +void SeerArrayVisualizerWidget::createBSeries() { + + if (scatterRadioButton->isChecked()) { + + QScatterSeries* scatter = new QScatterSeries; + scatter->setMarkerShape(QScatterSeries::MarkerShapeRectangle); + scatter->setMarkerSize(7); + _bSeries = scatter; + + }else if (lineRadioButton->isChecked()) { + + QLineSeries* line = new QLineSeries; + _bSeries = line; + + }else if (splineRadioButton->isChecked()) { + + QSplineSeries* line = new QSplineSeries; + _bSeries = line; + + }else{ + qWarning() << "Invalid line type."; + return; + } + + _bSeries->setPointsVisible(false); + _bSeries->setPointLabelsVisible(false); + _bSeries->setPointLabelsClipping(true); + + const QVector& values = arrayTableWidget->bArrayValues(); + + if (arrayTableWidget->bAxis() == "Y") { + + for (int i = 0; i < values.size(); ++i) { + _bSeries->append(i, values[i]); + } + + }else if (arrayTableWidget->bAxis() == "X") { + + for (int i = 0; i < values.size(); ++i) { + _bSeries->append(values[i], i); + } + + }else{ + qWarning() << "Invalid axis type of '" << arrayTableWidget->bAxis() << "'. Not 'X' or 'Y'."; + } + + _bSeries->setName(QString("%1:%2:%3").arg(arrayTableWidget->bLabel()).arg(arrayTableWidget->bAddressOffset()).arg(arrayTableWidget->bAddressStride())); +} + diff --git a/src/SeerArrayVisualizerWidget.h b/src/SeerArrayVisualizerWidget.h index 470224b..6aedad2 100644 --- a/src/SeerArrayVisualizerWidget.h +++ b/src/SeerArrayVisualizerWidget.h @@ -36,6 +36,8 @@ class SeerArrayVisualizerWidget : public QWidget, protected Ui::SeerArrayVisuali void handlebVariableNameLineEdit (); void handleaArrayDisplayFormatComboBox (int index); void handlebArrayDisplayFormatComboBox (int index); + void handleaAxisComboBox (int index); + void handlebAxisComboBox (int index); void handleDataChanged (); void handleSplitterMoved (int pos, int index); void handleSeriesHovered (const QPointF& point, bool state); @@ -50,7 +52,11 @@ class SeerArrayVisualizerWidget : public QWidget, protected Ui::SeerArrayVisuali void resizeEvent (QResizeEvent* event); private: - QXYSeries* _series; + void createASeries (); + void createBSeries (); + + QXYSeries* _aSeries; + QXYSeries* _bSeries; int _aVariableId; int _bVariableId; int _aMemoryId; diff --git a/src/SeerArrayVisualizerWidget.ui b/src/SeerArrayVisualizerWidget.ui index d4bbbb7..0d0651c 100644 --- a/src/SeerArrayVisualizerWidget.ui +++ b/src/SeerArrayVisualizerWidget.ui @@ -25,7 +25,7 @@ - array stride + Array stride true @@ -88,7 +88,7 @@ - array stride + Array stride true @@ -150,7 +150,7 @@ - array offset + Array offset true @@ -229,7 +229,7 @@ true - variable address + Variable address false @@ -248,7 +248,7 @@ - array offset + Array offset true @@ -264,7 +264,7 @@ true - variable address + Variable address false @@ -304,7 +304,7 @@ Variable axis type. - X + Y diff --git a/src/SeerArrayWidget.cpp b/src/SeerArrayWidget.cpp index e30b957..c16b53e 100644 --- a/src/SeerArrayWidget.cpp +++ b/src/SeerArrayWidget.cpp @@ -18,11 +18,13 @@ SeerArrayWidget::SeerArrayWidget(QWidget* parent) : QTableWidget(parent) { horizontalHeader()->setDefaultAlignment(Qt::AlignRight); _aData = 0; + _aAxis = "Y"; _aArrayMode = SeerArrayWidget::UnknownArrayMode; _aAddressOffset = 0; _aAddressStride = 1; _bData = 0; + _bAxis = "X"; _bArrayMode = SeerArrayWidget::UnknownArrayMode; _bAddressOffset = 0; _bAddressStride = 1; @@ -49,6 +51,14 @@ int SeerArrayWidget::elementsPerLine () const { return 1; } +const QString& SeerArrayWidget::aAxis () const { + return _aAxis; +} + +void SeerArrayWidget::setAAxis (const QString& axis) { + _aAxis = axis; +} + const QString& SeerArrayWidget::aLabel () const { return _aLabel; } @@ -156,6 +166,14 @@ const QVector& SeerArrayWidget::aArrayValues () const { return _aArrayValues; } +const QString& SeerArrayWidget::bAxis () const { + return _bAxis; +} + +void SeerArrayWidget::setBAxis (const QString& axis) { + _bAxis = axis; +} + const QString& SeerArrayWidget::bLabel () const { return _bLabel; } diff --git a/src/SeerArrayWidget.h b/src/SeerArrayWidget.h index 70a1a42..1eabc89 100644 --- a/src/SeerArrayWidget.h +++ b/src/SeerArrayWidget.h @@ -42,6 +42,8 @@ class SeerArrayWidget: public QTableWidget { int elementsPerLine () const; + const QString& aAxis () const; + void setAAxis (const QString& axis); const QString& aLabel () const; void setAAddressOffset (unsigned long offset); unsigned long aAddressOffset () const; @@ -55,6 +57,8 @@ class SeerArrayWidget: public QTableWidget { QString aArrayModeString () const; const QVector& aArrayValues () const; + const QString& bAxis () const; + void setBAxis (const QString& axis); const QString& bLabel () const; void setBAddressOffset (unsigned long offset); unsigned long bAddressOffset () const; @@ -81,6 +85,7 @@ class SeerArrayWidget: public QTableWidget { private: void create (); + QString _aAxis; QString _aLabel; int _aColumnId; DataStorage* _aData; @@ -89,6 +94,7 @@ class SeerArrayWidget: public QTableWidget { SeerArrayWidget::ArrayMode _aArrayMode; QVector _aArrayValues; + QString _bAxis; QString _bLabel; int _bColumnId; DataStorage* _bData;