From 20a381e4ba81777b2ad2d9cc988b990ca2ed0f55 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Mon, 11 Feb 2019 13:23:40 +0100 Subject: QTableView based memory view is working. Signed-off-by: Pavel Pisa --- qtmips_gui/hexlineedit.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++ qtmips_gui/hexlineedit.h | 68 +++++++++++++++++++++++++++++ qtmips_gui/memorydock.cpp | 18 ++++---- qtmips_gui/memorydock.h | 2 + qtmips_gui/memorymodel.cpp | 33 +++++++++++--- qtmips_gui/memorymodel.h | 2 +- qtmips_gui/memorytableview.cpp | 56 ++++++++++++++++++------ qtmips_gui/memorytableview.h | 10 +++-- qtmips_gui/qtmips_gui.pro | 6 ++- 9 files changed, 258 insertions(+), 35 deletions(-) create mode 100644 qtmips_gui/hexlineedit.cpp create mode 100644 qtmips_gui/hexlineedit.h diff --git a/qtmips_gui/hexlineedit.cpp b/qtmips_gui/hexlineedit.cpp new file mode 100644 index 0000000..c138591 --- /dev/null +++ b/qtmips_gui/hexlineedit.cpp @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci + * Copyright (c) 2019 Pavel Pisa + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#include "hexlineedit.h" + +HexLineEdit::HexLineEdit(QWidget *parent, int digits, int base, QString prefix): + Super(parent) { + this->base = base; + this->digits = digits; + this->prefix = prefix; + last_set = 0; + QChar dmask; + QString t = ""; + QString mask = ""; + + for (int i = 0; i 1) + t.fill(dmask, digits - 1); + + mask += t; + + setInputMask(mask); + + connect(this, SIGNAL(editingFinished()), this, SLOT(on_edit_finished())); + + set_value(0); +} + +void HexLineEdit::set_value(std::int32_t value) { + QString s, t = ""; + last_set = value; + s = QString::number(value, base); + if (s.count() < digits) + t.fill('0', digits - s.count()); + setText(prefix + t +s); + +} + +void HexLineEdit::on_edit_finished() { + bool ok; + std::uint32_t val; + val = text().toLong(&ok, 16); + if (!ok) { + set_value(last_set); + return; + } + last_set = val; + emit value_edit_finished(val); +} diff --git a/qtmips_gui/hexlineedit.h b/qtmips_gui/hexlineedit.h new file mode 100644 index 0000000..6b16edc --- /dev/null +++ b/qtmips_gui/hexlineedit.h @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0+ +/******************************************************************************* + * QtMips - MIPS 32-bit Architecture Subset Simulator + * + * Implemented to support following courses: + * + * B35APO - Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b35apo + * + * B4M35PAP - Advanced Computer Architectures + * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start + * + * Copyright (c) 2017-2019 Karel Koci + * Copyright (c) 2019 Pavel Pisa + * + * Faculty of Electrical Engineering (http://www.fel.cvut.cz) + * Czech Technical University (http://www.cvut.cz/) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#ifndef HEXLINEEDIT_H +#define HEXLINEEDIT_H + +#include +#include + +class HexLineEdit : public QLineEdit +{ + Q_OBJECT + + using Super = QLineEdit; + +public: + HexLineEdit(QWidget *parent = nullptr, int digits = 8, int base = 0, + QString prefix = "0x"); + +public slots: + void set_value(std::int32_t value); + +signals: + void value_edit_finished(std::int32_t value); + +private slots: + void on_edit_finished(); + +private: + int base; + int digits; + QString prefix; + std::uint32_t last_set; +}; + +#endif // HEXLINEEDIT_H diff --git a/qtmips_gui/memorydock.cpp b/qtmips_gui/memorydock.cpp index 97226af..dfeb9c8 100644 --- a/qtmips_gui/memorydock.cpp +++ b/qtmips_gui/memorydock.cpp @@ -38,15 +38,15 @@ #include #include #include -#include #include #include "memorydock.h" #include "memorymodel.h" #include "memorytableview.h" +#include "hexlineedit.h" -MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : QDockWidget(parent) { +MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : Super(parent) { setObjectName("Memory"); setWindowTitle("Memory"); @@ -58,16 +58,14 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : QDockWidget(paren cell_size->addItem("Word", MemoryModel::CELLSIZE_WORD); cell_size->setCurrentIndex(MemoryModel::CELLSIZE_WORD); - QTableView *memory_content = new MemoryTableView(0); + QTableView *memory_content = new MemoryTableView(0, settings); // memory_content->setSizePolicy(); MemoryModel *memory_model = new MemoryModel(0); memory_content->setModel(memory_model); memory_content->verticalHeader()->hide(); //memory_content->setHorizontalHeader(memory_model->); - QLineEdit *go_edit = new QLineEdit(); - go_edit->setText("0x00000000"); - go_edit->setInputMask("\\0\\xHhhhhhhh"); + QLineEdit *go_edit = new HexLineEdit(0, 8, 16, "0x"); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(cell_size); @@ -82,10 +80,10 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : QDockWidget(paren connect(this, &MemoryDock::machine_setup, memory_model, &MemoryModel::setup); connect(cell_size, SIGNAL(currentIndexChanged(int)), memory_content, SLOT(set_cell_size(int))); - connect(go_edit, SIGNAL(textEdited(QString)), - memory_content, SLOT(go_to_edit_text(QString))); - connect(memory_content, SIGNAL(set_go_edit_text(QString)), - go_edit, SLOT(setText(QString))); + connect(go_edit, SIGNAL(value_edit_finished(std::int32_t)), + memory_content, SLOT(go_to_address(std::int32_t))); + connect(memory_content, SIGNAL(address_changed(std::int32_t)), + go_edit, SLOT(set_value(std::int32_t))); } void MemoryDock::setup(machine::QtMipsMachine *machine) { diff --git a/qtmips_gui/memorydock.h b/qtmips_gui/memorydock.h index 81797a7..5dd366f 100644 --- a/qtmips_gui/memorydock.h +++ b/qtmips_gui/memorydock.h @@ -44,6 +44,8 @@ class MemoryDock : public QDockWidget { Q_OBJECT + using Super = QDockWidget; + public: MemoryDock(QWidget *parent, QSettings *settings); diff --git a/qtmips_gui/memorymodel.cpp b/qtmips_gui/memorymodel.cpp index 69a412d..09157bf 100644 --- a/qtmips_gui/memorymodel.cpp +++ b/qtmips_gui/memorymodel.cpp @@ -33,10 +33,12 @@ * ******************************************************************************/ +#include + #include "memorymodel.h" MemoryModel::MemoryModel(QObject *parent) - :QAbstractTableModel(parent), data_font("Monospace") { + : Super(parent), data_font("Monospace") { cell_size = CELLSIZE_WORD; cells_per_row = 1; index0_offset = 0; @@ -48,7 +50,7 @@ MemoryModel::MemoryModel(QObject *parent) int MemoryModel::rowCount(const QModelIndex & /*parent*/) const { // std::uint64_t rows = (0x2000 + cells_per_row - 1) / cells_per_row; - return 2000; + return 750; } int MemoryModel::columnCount(const QModelIndex & /*parent*/) const { @@ -64,7 +66,7 @@ QVariant MemoryModel::headerData(int section, Qt::Orientation orientation, int r } else { std::uint32_t addr = (section - 1) * cellSizeBytes(); - QString ret = "+0x" + QString::number(addr, 16); + QString ret = "+" + QString::number(addr, 10); return ret; } } @@ -106,8 +108,8 @@ QVariant MemoryModel::data(const QModelIndex &index, int role) const { t = QString::number(data, 16); s.fill('0', cellSizeBytes() * 2 - t.count()); - t = s + t; - + t = s + t.toUpper(); +#if 0 machine::LocationStatus loc_stat = machine::LOCSTAT_NONE; if (machine->cache_data() != nullptr) { loc_stat = machine->cache_data()->location_status(address); @@ -116,8 +118,28 @@ QVariant MemoryModel::data(const QModelIndex &index, int role) const { else if (loc_stat & machine::LOCSTAT_CACHED) t += " C"; } +#endif return t; } + if (role == Qt::BackgroundRole) { + std::uint32_t address; + if (!get_row_address(address, index.row()) || + machine == nullptr || index.column() == 0) + return QVariant(); + address += cellSizeBytes() * (index.column() - 1); + if (machine->cache_data() != nullptr) { + machine::LocationStatus loc_stat; + loc_stat = machine->cache_data()->location_status(address); + if (loc_stat & machine::LOCSTAT_DIRTY) { + QBrush bgd(Qt::yellow); + return bgd; + } else if (loc_stat & machine::LOCSTAT_CACHED) { + QBrush bgd(Qt::lightGray); + return bgd; + } + } + return QVariant(); + } if (role==Qt::FontRole) return data_font; return QVariant(); @@ -127,6 +149,7 @@ void MemoryModel::setup(machine::QtMipsMachine *machine) { this->machine = machine; if (machine != nullptr) connect(machine, SIGNAL(post_tick()), this, SLOT(check_for_updates())); + emit update_all(); } void MemoryModel::setCellsPerRow(unsigned int cells) { diff --git a/qtmips_gui/memorymodel.h b/qtmips_gui/memorymodel.h index b06eff8..f093dbb 100644 --- a/qtmips_gui/memorymodel.h +++ b/qtmips_gui/memorymodel.h @@ -70,7 +70,7 @@ public: return &data_font; } - inline const std::uint32_t getIndex0Offset() const { + inline std::uint32_t getIndex0Offset() const { return index0_offset; } diff --git a/qtmips_gui/memorytableview.cpp b/qtmips_gui/memorytableview.cpp index 09accb0..9b5d0ba 100644 --- a/qtmips_gui/memorytableview.cpp +++ b/qtmips_gui/memorytableview.cpp @@ -39,9 +39,15 @@ #include "memorytableview.h" #include "memorymodel.h" -MemoryTableView::MemoryTableView(QWidget *parent) : Super(parent) { +MemoryTableView::MemoryTableView(QWidget *parent, QSettings *settings) : Super(parent) { connect(verticalScrollBar() , SIGNAL(valueChanged(int)), this, SLOT(adjust_scroll_pos())); + this->settings = settings; + initial_address = settings->value("DataViewAddr0", 0).toULongLong(); +} + +void MemoryTableView::addr0_save_change(std::uint32_t val) { + settings->setValue("DataViewAddr0", val); } void MemoryTableView::adjustColumnCount() { @@ -55,7 +61,10 @@ void MemoryTableView::adjustColumnCount() { QString t = ""; t.fill(QChar('0'), m->cellSizeBytes() * 2); - int width1 = fm.width(t + " C"); + /* t + = " C"; */ + int width1 = fm.width(t) + 1; + if (width1 < fm.width("+99")) + width1 = fm.width("+99"); horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed); horizontalHeader()->resizeSection(1, width1); @@ -76,6 +85,10 @@ void MemoryTableView::adjustColumnCount() { horizontalHeader()->setSectionResizeMode(i, QHeaderView::Fixed); horizontalHeader()->resizeSection(i, width1); } + if (initial_address != 0) { + go_to_address(initial_address); + initial_address = 0; + } } } @@ -101,11 +114,14 @@ void MemoryTableView:: adjust_scroll_pos() { MemoryModel *m = dynamic_cast(model()); if (m == nullptr) return; + + QModelIndex prev_index = currentIndex(); std::uint32_t row_bytes = m->cellSizeBytes() * m->cellsPerRow(); std::uint32_t index0_offset = m->getIndex0Offset(); do { int row = rowAt(0); + int prev_row = row; if (row < m->rowCount() / 8) { if ((row == 0) && (index0_offset < row_bytes) && (index0_offset != 0)) { m->adjustRowAndOffset(row, 0, 0); @@ -121,33 +137,45 @@ void MemoryTableView:: adjust_scroll_pos() { } else { break; } - scrollTo(m->index(row, 0), - QAbstractItemView::PositionAtTop); - emit m->update_all(); + scrollTo(m->index(row, 0), QAbstractItemView::PositionAtTop); + setCurrentIndex(m->index(prev_index.row() + row - prev_row, + prev_index.column())); + emit m->update_all(); } while(0); m->get_row_address(address, rowAt(0)); - QString s, t; - s = QString::number(address, 16).toUpper(); - t.fill('0', 8 - s.count()); - emit set_go_edit_text("0x" + t + s); + addr0_save_change(address); + emit address_changed(address); } void MemoryTableView::resizeEvent(QResizeEvent *event) { + MemoryModel *m = dynamic_cast(model()); + std::uint32_t address; + bool keep_row0 = false; + + if (m != nullptr) { + if (initial_address == 0) { + keep_row0 = m->get_row_address(address, rowAt(0)); + } else { + address = initial_address; + } + } Super::resizeEvent(event); adjustColumnCount(); + if (keep_row0) { + initial_address = 0; + go_to_address(address); + } } -void MemoryTableView::go_to_edit_text(QString text) { +void MemoryTableView:: go_to_address(std::int32_t address) { MemoryModel *m = dynamic_cast(model()); int row; if (m == nullptr) return; - bool convertOK = true; - std::int32_t address = text.toULong(&convertOK, 0); - if (!convertOK) - return; m->adjustRowAndOffset(row, m->rowCount() / 2, address); scrollTo(m->index(row, 0), QAbstractItemView::PositionAtTop); + setCurrentIndex(m->index(row, 1)); + addr0_save_change(address); emit m->update_all(); } diff --git a/qtmips_gui/memorytableview.h b/qtmips_gui/memorytableview.h index ba00539..9ade84f 100644 --- a/qtmips_gui/memorytableview.h +++ b/qtmips_gui/memorytableview.h @@ -37,6 +37,7 @@ #define MEMORYTABLEVIEW_H #include +#include #include #include @@ -47,19 +48,22 @@ class MemoryTableView : public QTableView using Super = QTableView; public: - MemoryTableView(QWidget *parent); + MemoryTableView(QWidget *parent, QSettings *settings); void resizeEvent(QResizeEvent *event) override; signals: - void set_go_edit_text(QString text); + void address_changed(std::int32_t address); public slots: void set_cell_size(int index); - void go_to_edit_text(QString text); + void go_to_address(std::int32_t address); private slots: void adjust_scroll_pos(); private: + void addr0_save_change(std::uint32_t val); void adjustColumnCount(); + QSettings *settings; + std::uint32_t initial_address; }; #endif // MEMORYTABLEVIEW_H diff --git a/qtmips_gui/qtmips_gui.pro b/qtmips_gui/qtmips_gui.pro index 39d3cc6..05aa784 100644 --- a/qtmips_gui/qtmips_gui.pro +++ b/qtmips_gui/qtmips_gui.pro @@ -48,7 +48,8 @@ SOURCES += \ graphicsview.cpp \ coreview/value.cpp \ memorymodel.cpp \ - memorytableview.cpp + memorytableview.cpp \ + hexlineedit.cpp HEADERS += \ mainwindow.h \ @@ -77,7 +78,8 @@ HEADERS += \ graphicsview.h \ coreview/value.h \ memorymodel.h \ - memorytableview.h + memorytableview.h \ + hexlineedit.h FORMS += \ NewDialog.ui \ -- cgit v1.2.3