checkpoint. ArrayVisializer.

This commit is contained in:
Ernie Pasveer
2022-03-14 18:28:46 -05:00
parent 699ee6262f
commit 8fad055370
9 changed files with 403 additions and 126 deletions
+2
View File
@@ -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
+41 -80
View File
@@ -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<int>::of(&QComboBox::currentIndexChanged), this, &SeerArrayVisualizerWidget::handleArrayDisplayFormatComboBox);
QObject::connect(columnCountSpinBox, QOverload<int>::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() {
-2
View File
@@ -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 ();
+23 -44
View File
@@ -14,6 +14,9 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="SeerArrayWidget" name="arrayTableWidget"/>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
@@ -45,7 +48,7 @@
<item>
<widget class="QLineEdit" name="arrayLengthLineEdit">
<property name="toolTip">
<string>Number of bytes to display.</string>
<string>Number of elements to display.</string>
</property>
<property name="inputMask">
<string/>
@@ -78,6 +81,21 @@
<string>int64</string>
</property>
</item>
<item>
<property name="text">
<string>unt16</string>
</property>
</item>
<item>
<property name="text">
<string>uin32</string>
</property>
</item>
<item>
<property name="text">
<string>uin64</string>
</property>
</item>
<item>
<property name="text">
<string>float32</string>
@@ -103,34 +121,6 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="printToolButton">
<property name="toolTip">
<string>Print the display.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/seer/resources/RelaxLightIcons/document-print.svg</normaloff>:/seer/resources/HighContrast/document-print.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="saveToolButton">
<property name="toolTip">
<string>Save the display to a file.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/seer/resources/RelaxLightIcons/document-save-as.svg</normaloff>:/seer/resources/HighContrast/document-save-as.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshToolButton">
<property name="toolTip">
@@ -141,30 +131,19 @@
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/seer/resources/RelaxLightIcons/view-refresh.svg</normaloff>:/seer/resources/HighContrast/view-refresh.svg</iconset>
<normaloff>:/seer/resources/RelaxLightIcons/view-refresh.svg</normaloff>:/seer/resources/RelaxLightIcons/view-refresh.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="SeerHexWidget" name="memoryHexEditor" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>100</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SeerHexWidget</class>
<extends>QWidget</extends>
<header location="global">SeerHexWidget.h</header>
<container>1</container>
<class>SeerArrayWidget</class>
<extends>QTableWidget</extends>
<header location="global">SeerArrayWidget.h</header>
</customwidget>
</customwidgets>
<resources>
+241
View File
@@ -0,0 +1,241 @@
#include "SeerArrayWidget.h"
#include "SeerUtl.h"
#include <QtWidgets/QHeaderView>
#include <QtCore/QDebug>
#include <stdexcept>
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<short*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::UInt16ArrayMode) {
unsigned short v = *reinterpret_cast<unsigned short*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::Int32ArrayMode) {
int v = *reinterpret_cast<int*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::UInt32ArrayMode) {
unsigned int v = *reinterpret_cast<unsigned int*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::Int64ArrayMode) {
long v = *reinterpret_cast<long*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::UInt64ArrayMode) {
unsigned long v = *reinterpret_cast<unsigned long*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::Float32ArrayMode) {
float v = *reinterpret_cast<float*>(element.data());
item->setText(QString::number(v));
}else if (arrayMode() == SeerArrayWidget::Float64ArrayMode) {
double v = *reinterpret_cast<double*>(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();
}
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include <QtWidgets/QTableWidget>
#include <QtCore/QByteArray>
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;
};
+21
View File
@@ -1,4 +1,5 @@
#include "SeerUtl.h"
#include <QtCore/QDebug>
#include <mutex>
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;
}
}
}
+2
View File
@@ -16,5 +16,7 @@ namespace Seer {
unsigned char ebcdicToAscii (unsigned char byte);
unsigned char ucharToAscii (unsigned char byte);
int typeBytes (const QString& type);
};
+7
View File
@@ -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;
}