From 8fad05537034ff7aa2d9291aa6c37dd13222c9a8 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Mon, 14 Mar 2022 18:28:46 -0500 Subject: [PATCH] checkpoint. ArrayVisializer. --- src/CMakeLists.txt | 2 + src/SeerArrayVisualizerWidget.cpp | 121 +++++---------- src/SeerArrayVisualizerWidget.h | 2 - src/SeerArrayVisualizerWidget.ui | 67 +++------ src/SeerArrayWidget.cpp | 241 ++++++++++++++++++++++++++++++ src/SeerArrayWidget.h | 66 ++++++++ src/SeerUtl.cpp | 21 +++ src/SeerUtl.h | 2 + tests/helloarray/helloarray.cpp | 7 + 9 files changed, 403 insertions(+), 126 deletions(-) create mode 100644 src/SeerArrayWidget.cpp create mode 100644 src/SeerArrayWidget.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de56c0c..bd50390 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,6 +45,7 @@ set(HEADER_FILES SeerExecutableFilterProxyModel.h SeerGdbWidget.h SeerHexWidget.h + SeerArrayWidget.h SeerLogWidget.h SeerMainWindow.h SeerArrayVisualizerWidget.h @@ -110,6 +111,7 @@ set(SOURCE_FILES SeerEditorWidgetSourceArea.cpp SeerGdbWidget.cpp SeerHexWidget.cpp + SeerArrayWidget.cpp SeerLogWidget.cpp SeerMainWindow.cpp SeerArrayVisualizerWidget.cpp diff --git a/src/SeerArrayVisualizerWidget.cpp b/src/SeerArrayVisualizerWidget.cpp index 7dd873b..5594df3 100644 --- a/src/SeerArrayVisualizerWidget.cpp +++ b/src/SeerArrayVisualizerWidget.cpp @@ -24,9 +24,10 @@ SeerArrayVisualizerWidget::SeerArrayVisualizerWidget (QWidget* parent) : QWidget setWindowTitle("Seer Array Visualizer"); arrayLengthLineEdit->setValidator(new QIntValidator(1, 9999999, this)); - columnCountSpinBox->setValue(memoryHexEditor->bytesPerLine()); + columnCountSpinBox->setValue(arrayTableWidget->elementsPerLine()); arrayDisplayFormatComboBox->setCurrentIndex(0); + handleArrayDisplayFormatComboBox(0); // Connect things. QObject::connect(refreshToolButton, &QToolButton::clicked, this, &SeerArrayVisualizerWidget::handleRefreshButton); @@ -34,8 +35,6 @@ SeerArrayVisualizerWidget::SeerArrayVisualizerWidget (QWidget* parent) : QWidget QObject::connect(variableNameLineEdit, &QLineEdit::returnPressed, this, &SeerArrayVisualizerWidget::handleVariableNameLineEdit); QObject::connect(arrayDisplayFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerArrayVisualizerWidget::handleArrayDisplayFormatComboBox); QObject::connect(columnCountSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &SeerArrayVisualizerWidget::handleColumnCountSpinBox); - QObject::connect(printToolButton, &QToolButton::clicked, this, &SeerArrayVisualizerWidget::handlePrintButton); - QObject::connect(saveToolButton, &QToolButton::clicked, this, &SeerArrayVisualizerWidget::handleSaveButton); // Restore window settings. readSettings(); @@ -58,7 +57,7 @@ void SeerArrayVisualizerWidget::setVariableName (const QString& name) { // Clear old contents. QByteArray array; - memoryHexEditor->setData(new SeerHexWidget::DataStorageArray(array)); + arrayTableWidget->setData(new SeerArrayWidget::DataStorageArray(array)); // Send signal to get variable address. emit evaluateVariableExpression(_variableId, variableNameLineEdit->text()); @@ -91,7 +90,7 @@ void SeerArrayVisualizerWidget::setVariableAddress (const QString& address) { //qDebug() << address << offset << ok; - memoryHexEditor->setAddressOffset(offset); + arrayTableWidget->setAddressOffset(offset); } QString SeerArrayVisualizerWidget::variableAddress () const { @@ -125,7 +124,7 @@ void SeerArrayVisualizerWidget::handleText (const QString& text) { if (id_text.toInt() == _memoryId) { - //qDebug() << text; + qDebug() << text; QString memory_text = Seer::parseFirst(text, "memory=", '[', ']', false); @@ -149,7 +148,7 @@ void SeerArrayVisualizerWidget::handleText (const QString& text) { } // Give the byte array to the hex widget. - memoryHexEditor->setData(new SeerHexWidget::DataStorageArray(array)); + arrayTableWidget->setData(new SeerArrayWidget::DataStorageArray(array)); break; // Take just the first range for now. } @@ -195,7 +194,11 @@ void SeerArrayVisualizerWidget::handleRefreshButton () { return; } - emit evaluateMemoryExpression(_memoryId, variableAddressLineEdit->text(), arrayLengthLineEdit->text().toInt()); + int bytes = arrayLengthLineEdit->text().toInt() * Seer::typeBytes(arrayDisplayFormatComboBox->currentText()); + + qDebug() << _memoryId << variableAddressLineEdit->text() << arrayLengthLineEdit->text() << arrayDisplayFormatComboBox->currentText() << bytes; + + emit evaluateMemoryExpression(_memoryId, variableAddressLineEdit->text(), bytes); } void SeerArrayVisualizerWidget::handleVariableNameLineEdit () { @@ -205,82 +208,40 @@ void SeerArrayVisualizerWidget::handleVariableNameLineEdit () { void SeerArrayVisualizerWidget::handleArrayDisplayFormatComboBox (int index) { - memoryHexEditor->setMemoryMode(SeerHexWidget::HexMemoryMode); + qDebug() << index; + + if (index == 0) { + arrayTableWidget->setArrayMode(SeerArrayWidget::Int16ArrayMode); + + }else if (index == 1) { + arrayTableWidget->setArrayMode(SeerArrayWidget::Int32ArrayMode); + + }else if (index == 2) { + arrayTableWidget->setArrayMode(SeerArrayWidget::Int64ArrayMode); + + }else if (index == 3) { + arrayTableWidget->setArrayMode(SeerArrayWidget::UInt16ArrayMode); + + }else if (index == 4) { + arrayTableWidget->setArrayMode(SeerArrayWidget::UInt32ArrayMode); + + }else if (index == 5) { + arrayTableWidget->setArrayMode(SeerArrayWidget::UInt64ArrayMode); + + }else if (index == 6) { + arrayTableWidget->setArrayMode(SeerArrayWidget::Float32ArrayMode); + + }else if (index == 7) { + arrayTableWidget->setArrayMode(SeerArrayWidget::Float64ArrayMode); + + }else{ + // Do nothing. + } } void SeerArrayVisualizerWidget::handleColumnCountSpinBox (int value) { - memoryHexEditor->setBytesPerLine(value); -} - -void SeerArrayVisualizerWidget::handlePrintButton () { - - QPrinter printer; - - QPrintDialog* dlg = new QPrintDialog(&printer, this); - - if (dlg->exec() != QDialog::Accepted) { - return; - } - - - // Make a copy so we can temporarily add a header. - QTextDocument* clone = memoryHexEditor->document()->clone(this); - - QTextCursor cursor(clone); - QTextCharFormat format = cursor.charFormat(); - format.setBackground(QBrush(Qt::transparent)); - - cursor.insertText("\n", format); - cursor.insertText("name=" + variableName() + " address=" + variableAddress() + " bytesPerLine=" + QString::number(memoryHexEditor->bytesPerLine()) + " bytes=" + QString::number(memoryHexEditor->size()) + " memory=" + memoryHexEditor->memoryModeString() + " char=" + memoryHexEditor->charModeString() + "\n", format); - cursor.insertText("\n", format); - - clone->print(&printer); - - delete clone; -} - -void SeerArrayVisualizerWidget::handleSaveButton () { - - QFileDialog dialog(this, "Seer visualizer file", "", "Logs (*.log);;Text files (*.txt);;All files (*.*)"); - dialog.setAcceptMode(QFileDialog::AcceptSave); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setDefaultSuffix("log"); - dialog.selectFile("array.log"); - - if (dialog.exec() != QDialog::Accepted) { - return; - } - - QStringList files = dialog.selectedFiles(); - - if (files.size() == 0) { - return; - } - - if (files.size() > 1) { - QMessageBox::critical(this, tr("Error"), tr("Select only 1 file.")); - return; - } - - QFile file(files[0]); - - if (file.open(QIODevice::ReadWrite)) { - QTextStream stream(&file); - - stream << "\n"; - stream << "name=" << variableName() << " address=" << variableAddress() << " bytesPerLine=" << memoryHexEditor->bytesPerLine() << " bytes=" << memoryHexEditor->size() << " memory=" << memoryHexEditor->memoryModeString() << " char=" << memoryHexEditor->charModeString() << "\n"; - stream << "\n"; - stream << memoryHexEditor->toPlainText(); - stream << "\n"; - - file.flush(); - file.close(); - - }else{ - QMessageBox::critical(this, tr("Error"), tr("Cannot save display to file.")); - return; - } + arrayTableWidget->setElementsPerLine(value); } void SeerArrayVisualizerWidget::writeSettings() { diff --git a/src/SeerArrayVisualizerWidget.h b/src/SeerArrayVisualizerWidget.h index f5362de..5513be3 100644 --- a/src/SeerArrayVisualizerWidget.h +++ b/src/SeerArrayVisualizerWidget.h @@ -28,8 +28,6 @@ class SeerArrayVisualizerWidget : public QWidget, protected Ui::SeerArrayVisuali void handleVariableNameLineEdit (); void handleArrayDisplayFormatComboBox (int index); void handleColumnCountSpinBox (int value); - void handlePrintButton (); - void handleSaveButton (); protected: void writeSettings (); diff --git a/src/SeerArrayVisualizerWidget.ui b/src/SeerArrayVisualizerWidget.ui index d215ff2..8bec6be 100644 --- a/src/SeerArrayVisualizerWidget.ui +++ b/src/SeerArrayVisualizerWidget.ui @@ -14,6 +14,9 @@ Form + + + @@ -45,7 +48,7 @@ - Number of bytes to display. + Number of elements to display. @@ -78,6 +81,21 @@ int64 + + + unt16 + + + + + uin32 + + + + + uin64 + + float32 @@ -103,34 +121,6 @@ - - - - Print the display. - - - ... - - - - :/seer/resources/RelaxLightIcons/document-print.svg:/seer/resources/HighContrast/document-print.svg - - - - - - - Save the display to a file. - - - ... - - - - :/seer/resources/RelaxLightIcons/document-save-as.svg:/seer/resources/HighContrast/document-save-as.svg - - - @@ -141,30 +131,19 @@ - :/seer/resources/RelaxLightIcons/view-refresh.svg:/seer/resources/HighContrast/view-refresh.svg + :/seer/resources/RelaxLightIcons/view-refresh.svg:/seer/resources/RelaxLightIcons/view-refresh.svg - - - - - 0 - 100 - - - - - SeerHexWidget - QWidget -
SeerHexWidget.h
- 1 + SeerArrayWidget + QTableWidget +
SeerArrayWidget.h
diff --git a/src/SeerArrayWidget.cpp b/src/SeerArrayWidget.cpp new file mode 100644 index 0000000..bb19a1c --- /dev/null +++ b/src/SeerArrayWidget.cpp @@ -0,0 +1,241 @@ +#include "SeerArrayWidget.h" +#include "SeerUtl.h" +#include +#include +#include + +SeerArrayWidget::SeerArrayWidget(QWidget* parent) : QTableWidget(parent), _pdata(NULL) { + + QFont font; + font.setFamily("monospace [Consolas]"); + font.setFixedPitch(true); + font.setStyleHint(QFont::TypeWriter); + + setFont(font); + setFocusPolicy(Qt::StrongFocus); + setEditTriggers(QAbstractItemView::NoEditTriggers); + horizontalHeader()->setDefaultAlignment(Qt::AlignRight); + + _arrayMode = SeerArrayWidget::UnknownArrayMode; + _addressOffset = 0; + + setElementsPerLine(1); + +} + +SeerArrayWidget::~SeerArrayWidget() { + + if (_pdata) { + delete _pdata; + } +} + +void SeerArrayWidget::setElementsPerLine (int count) { + + _elementsPerLine = count; + + // Repaint the widget. + create(); +} + +int SeerArrayWidget::elementsPerLine () const { + return _elementsPerLine; +} + +void SeerArrayWidget::setAddressOffset (unsigned long offset) { + + _addressOffset = offset; + + // Repaint the widget. + create(); +} + +unsigned long SeerArrayWidget::addressOffset () const { + return _addressOffset; +} + +unsigned long SeerArrayWidget::size () const { + + if (_pdata) { + return _pdata->size(); + } + + return 0; +} + +unsigned long SeerArrayWidget::elementSize () const { + + if (arrayMode() == SeerArrayWidget::Int16ArrayMode) { + return 2; + }else if (arrayMode() == SeerArrayWidget::UInt16ArrayMode) { + return 2; + }else if (arrayMode() == SeerArrayWidget::Int32ArrayMode) { + return 4; + }else if (arrayMode() == SeerArrayWidget::UInt32ArrayMode) { + return 4; + }else if (arrayMode() == SeerArrayWidget::Int64ArrayMode) { + return 8; + }else if (arrayMode() == SeerArrayWidget::UInt64ArrayMode) { + return 8; + }else if (arrayMode() == SeerArrayWidget::Float32ArrayMode) { + return 4; + }else if (arrayMode() == SeerArrayWidget::Float64ArrayMode) { + return 8; + } + + return 0; +} + + +void SeerArrayWidget::setArrayMode (SeerArrayWidget::ArrayMode arrayMode) { + + _arrayMode = arrayMode; + + // This repaints the widget with the new array mode + setElementsPerLine(elementsPerLine()); +} + +SeerArrayWidget::ArrayMode SeerArrayWidget::arrayMode () const { + return _arrayMode; +} + +QString SeerArrayWidget::arrayModeString () const { + + if (arrayMode() == SeerArrayWidget::Int16ArrayMode) { + return "int6"; + }else if (arrayMode() == SeerArrayWidget::UInt16ArrayMode) { + return "uint16"; + }else if (arrayMode() == SeerArrayWidget::Int32ArrayMode) { + return "int32"; + }else if (arrayMode() == SeerArrayWidget::UInt32ArrayMode) { + return "uint32"; + }else if (arrayMode() == SeerArrayWidget::Int64ArrayMode) { + return "int64"; + }else if (arrayMode() == SeerArrayWidget::UInt64ArrayMode) { + return "uint64"; + }else if (arrayMode() == SeerArrayWidget::Float32ArrayMode) { + return "float32"; + }else if (arrayMode() == SeerArrayWidget::Float64ArrayMode) { + return "float64"; + } + + return "???"; +} + +void SeerArrayWidget::setData(SeerArrayWidget::DataStorage* pData) { + + if (_pdata) { + delete _pdata; + } + + _pdata = pData; + + // Repaint the widget. + create(); +} + +void SeerArrayWidget::create () { + + // Clear the table. We're going to recreate it. + clear(); + setRowCount(0); + setColumnCount(elementsPerLine()); + + // If there's no data, do nothing. + if (!_pdata) { + return; + } + + if (elementSize() < 1) { + return; + } + + int row = 0; + int col = 0; + + for (int i=0; i<_pdata->size(); i+=elementSize()) { + + // Add new row if we need to. + if (row == rowCount()) { + insertRow(rowCount()); + } + + QTableWidgetItem* item = new QTableWidgetItem; + item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter); + + QByteArray element = _pdata->getData(i, elementSize()); + + QByteArray hex = element.toHex(); + + if (arrayMode() == SeerArrayWidget::Int16ArrayMode) { + + short v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::UInt16ArrayMode) { + + unsigned short v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::Int32ArrayMode) { + + int v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::UInt32ArrayMode) { + + unsigned int v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::Int64ArrayMode) { + + long v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::UInt64ArrayMode) { + + unsigned long v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::Float32ArrayMode) { + + float v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + + }else if (arrayMode() == SeerArrayWidget::Float64ArrayMode) { + + double v = *reinterpret_cast(element.data()); + + item->setText(QString::number(v)); + } + + setItem(row, col, item); + + col++; + + if (col >= elementsPerLine()) { + col = 0; + row++; + } + } +} + +SeerArrayWidget::DataStorageArray::DataStorageArray(const QByteArray& arr) { + _data = arr; +} + +QByteArray SeerArrayWidget::DataStorageArray::getData(int position, int length) { + return _data.mid(position, length); +} + +int SeerArrayWidget::DataStorageArray::size() { + return _data.count(); +} + diff --git a/src/SeerArrayWidget.h b/src/SeerArrayWidget.h new file mode 100644 index 0000000..8347837 --- /dev/null +++ b/src/SeerArrayWidget.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include + +class SeerArrayWidget: public QTableWidget { + + public: + class DataStorage { + public: + virtual ~DataStorage() {}; + virtual QByteArray getData(int position, int length) = 0; + virtual int size() = 0; + }; + + class DataStorageArray: public DataStorage { + public: + DataStorageArray(const QByteArray& arr); + virtual QByteArray getData(int position, int length); + virtual int size(); + private: + QByteArray _data; + }; + + enum ArrayMode { + UnknownArrayMode = 0, + Int16ArrayMode = 1, + UInt16ArrayMode = 2, + Int32ArrayMode = 3, + UInt32ArrayMode = 4, + Int64ArrayMode = 5, + UInt64ArrayMode = 6, + Float32ArrayMode = 7, + Float64ArrayMode = 8 + }; + + SeerArrayWidget(QWidget* parent = 0); + ~SeerArrayWidget(); + + void setElementsPerLine (int count); + int elementsPerLine () const; + void setAddressOffset (unsigned long offset); + unsigned long addressOffset () const; + unsigned long size () const; + unsigned long elementSize () const; + + void setArrayMode (SeerArrayWidget::ArrayMode arrayMode); + SeerArrayWidget::ArrayMode arrayMode () const; + QString arrayModeString () const; + + public slots: + void setData (DataStorage* pData); + + protected: + + private: + void create (); + + DataStorage* _pdata; + + int _elementsPerLine; + unsigned long _addressOffset; + + SeerArrayWidget::ArrayMode _arrayMode; +}; + diff --git a/src/SeerUtl.cpp b/src/SeerUtl.cpp index ed21c2a..5c1146e 100644 --- a/src/SeerUtl.cpp +++ b/src/SeerUtl.cpp @@ -1,4 +1,5 @@ #include "SeerUtl.h" +#include #include namespace Seer { @@ -240,5 +241,25 @@ namespace Seer { return ucharToAsciiTable[byte]; } + + int typeBytes (const QString& type) { + + if (type == "int8" || type == "uint8") { + return 1; + }else if (type == "int16" || type == "uint16") { + return 2; + }else if (type == "int32" || type == "uint32") { + return 4; + }else if (type == "int64" || type == "uint64") { + return 8; + }else if (type == "float32") { + return 4; + }else if (type == "float64") { + return 8; + }else{ + qWarning() << "Bad data type:" << type; + return 0; + } + } } diff --git a/src/SeerUtl.h b/src/SeerUtl.h index 45f71e3..a299715 100644 --- a/src/SeerUtl.h +++ b/src/SeerUtl.h @@ -16,5 +16,7 @@ namespace Seer { unsigned char ebcdicToAscii (unsigned char byte); unsigned char ucharToAscii (unsigned char byte); + + int typeBytes (const QString& type); }; diff --git a/tests/helloarray/helloarray.cpp b/tests/helloarray/helloarray.cpp index 0d396f7..47e12b2 100644 --- a/tests/helloarray/helloarray.cpp +++ b/tests/helloarray/helloarray.cpp @@ -16,10 +16,17 @@ int main (void) { int_array[i] = i; } + float* float_array = (float*)malloc(256); + + for (int i=0; i<64; i++) { + float_array[i] = (float)i * 1.13; + } + printf("Hello array!\n"); free(array); free(int_array); + free(float_array); return 0; }