From 1c608f4cd1c5a1102442679b9d6608a254cc7420 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 10 Feb 2019 23:55:53 +0100 Subject: Implemented workaround QTableView limits workaround which mostly works. Signed-off-by: Pavel Pisa --- qtmips_gui/memorydock.cpp | 10 +++--- qtmips_gui/memorymodel.cpp | 32 ++++++++++++++++-- qtmips_gui/memorymodel.h | 18 ++++++++++ qtmips_gui/memorytableview.cpp | 74 +++++++++++++++++++++++++++++++++++++++--- qtmips_gui/memorytableview.h | 9 +++-- 5 files changed, 129 insertions(+), 14 deletions(-) diff --git a/qtmips_gui/memorydock.cpp b/qtmips_gui/memorydock.cpp index 856dfa2..97226af 100644 --- a/qtmips_gui/memorydock.cpp +++ b/qtmips_gui/memorydock.cpp @@ -80,10 +80,12 @@ MemoryDock::MemoryDock(QWidget *parent, QSettings *settings) : QDockWidget(paren setWidget(content); connect(this, &MemoryDock::machine_setup, memory_model, &MemoryModel::setup); - connect(cell_size, QOverload::of(&QComboBox::currentIndexChanged), - memory_model, &MemoryModel::set_cell_size); - connect(memory_model, SIGNAL(cell_size_changed()), - memory_content, SLOT(adap_to_cell_size())); + 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))); } void MemoryDock::setup(machine::QtMipsMachine *machine) { diff --git a/qtmips_gui/memorymodel.cpp b/qtmips_gui/memorymodel.cpp index 13ae1c7..69a412d 100644 --- a/qtmips_gui/memorymodel.cpp +++ b/qtmips_gui/memorymodel.cpp @@ -47,8 +47,8 @@ MemoryModel::MemoryModel(QObject *parent) } int MemoryModel::rowCount(const QModelIndex & /*parent*/) const { - std::uint64_t rows = (0x2000 + cells_per_row - 1) / cells_per_row; - return rows; + // std::uint64_t rows = (0x2000 + cells_per_row - 1) / cells_per_row; + return 2000; } int MemoryModel::columnCount(const QModelIndex & /*parent*/) const { @@ -143,6 +143,10 @@ void MemoryModel::set_cell_size(int index) { emit cell_size_changed(); } +void MemoryModel::update_all() { + emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); +} + void MemoryModel::check_for_updates() { bool need_update = false; if (machine == nullptr) @@ -158,5 +162,27 @@ void MemoryModel::check_for_updates() { } if (!need_update) return; - emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); + update_all(); +} + +bool MemoryModel::adjustRowAndOffset(int &row, int optimal_row, std::uint32_t address) { + if (optimal_row < rowCount() / 8) + optimal_row = rowCount() / 8; + if (optimal_row >= rowCount() - rowCount() / 8) + optimal_row = rowCount() - rowCount() / 8; + row = rowCount() / 2; + address -= address % cellSizeBytes(); + std::uint32_t row_bytes = cells_per_row * cellSizeBytes(); + std::uint32_t diff = row * row_bytes; + if (diff > address) { + row = address / row_bytes; + if (row == 0) { + index0_offset = 0; + } else { + index0_offset = address - row * row_bytes; + } + } else { + index0_offset = address - diff; + } + return get_row_for_address(row, address); } diff --git a/qtmips_gui/memorymodel.h b/qtmips_gui/memorymodel.h index e85d476..b06eff8 100644 --- a/qtmips_gui/memorymodel.h +++ b/qtmips_gui/memorymodel.h @@ -57,6 +57,8 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool adjustRowAndOffset(int &row, int optimal_row, std::uint32_t address); + void update_all(); void setCellsPerRow(unsigned int cells); @@ -68,6 +70,10 @@ public: return &data_font; } + inline const std::uint32_t getIndex0Offset() const { + return index0_offset; + } + inline unsigned int cellSizeBytes() const { switch (cell_size) { case CELLSIZE_BYTE: @@ -83,6 +89,18 @@ public: address = index0_offset + (row * cells_per_row * cellSizeBytes()); return address >= index0_offset; } + inline bool get_row_for_address(int &row, std::uint32_t address) const { + if (address < index0_offset) { + row = -1; + return false; + } + row = (address - index0_offset) / (cells_per_row * cellSizeBytes()); + if ((address - index0_offset > 0x80000000) || row > rowCount()) { + row = rowCount(); + return false; + } + return true; + } public slots: void setup(machine::QtMipsMachine *machine); diff --git a/qtmips_gui/memorytableview.cpp b/qtmips_gui/memorytableview.cpp index 9b5cddf..09accb0 100644 --- a/qtmips_gui/memorytableview.cpp +++ b/qtmips_gui/memorytableview.cpp @@ -35,11 +35,13 @@ #include #include +#include #include "memorytableview.h" #include "memorymodel.h" MemoryTableView::MemoryTableView(QWidget *parent) : Super(parent) { - + connect(verticalScrollBar() , SIGNAL(valueChanged(int)), + this, SLOT(adjust_scroll_pos())); } void MemoryTableView::adjustColumnCount() { @@ -58,7 +60,7 @@ void MemoryTableView::adjustColumnCount() { horizontalHeader()->resizeSection(1, width1); int w = verticalHeader()->width() + 8; - int cells; + unsigned int cells; width0 = columnWidth(0); width1 = columnWidth(1); w = width() - w - width0; @@ -70,18 +72,82 @@ void MemoryTableView::adjustColumnCount() { if (cells != m->cellsPerRow()) { m->setCellsPerRow(cells); } - for (int i = 1; i < m->cellsPerRow() + 1; i++) { + for (unsigned int i = 1; i < m->cellsPerRow() + 1; i++) { horizontalHeader()->setSectionResizeMode(i, QHeaderView::Fixed); horizontalHeader()->resizeSection(i, width1); } } } -void MemoryTableView::adap_to_cell_size() { +void MemoryTableView::set_cell_size(int index) { + std::uint32_t address; + int row; + bool keep_row0 = false; + MemoryModel *m = dynamic_cast(model()); + if (m != nullptr) { + keep_row0 = m->get_row_address(address, rowAt(0)); + m->set_cell_size(index); + } adjustColumnCount(); + if (keep_row0) { + m->adjustRowAndOffset(row, m->rowCount() / 2, address); + scrollTo(m->index(row, 0), + QAbstractItemView::PositionAtTop); + } +} + +void MemoryTableView:: adjust_scroll_pos() { + std::uint32_t address; + MemoryModel *m = dynamic_cast(model()); + if (m == nullptr) + return; + std::uint32_t row_bytes = m->cellSizeBytes() * m->cellsPerRow(); + std::uint32_t index0_offset = m->getIndex0Offset(); + + do { + int row = rowAt(0); + if (row < m->rowCount() / 8) { + if ((row == 0) && (index0_offset < row_bytes) && (index0_offset != 0)) { + m->adjustRowAndOffset(row, 0, 0); + } else if (index0_offset > row_bytes) { + m->get_row_address(address, row); + m->adjustRowAndOffset(row, m->rowCount() / 7, address); + } else { + break; + } + } else if (row > m->rowCount() - m->rowCount() / 8) { + m->get_row_address(address, row); + m->adjustRowAndOffset(row, m->rowCount() - m->rowCount() / 7, address); + } else { + break; + } + scrollTo(m->index(row, 0), + QAbstractItemView::PositionAtTop); + 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); } void MemoryTableView::resizeEvent(QResizeEvent *event) { Super::resizeEvent(event); adjustColumnCount(); } + +void MemoryTableView::go_to_edit_text(QString text) { + 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); + emit m->update_all(); +} diff --git a/qtmips_gui/memorytableview.h b/qtmips_gui/memorytableview.h index 73b1ea9..ba00539 100644 --- a/qtmips_gui/memorytableview.h +++ b/qtmips_gui/memorytableview.h @@ -50,10 +50,13 @@ public: MemoryTableView(QWidget *parent); void resizeEvent(QResizeEvent *event) override; - +signals: + void set_go_edit_text(QString text); public slots: - void adap_to_cell_size(); - + void set_cell_size(int index); + void go_to_edit_text(QString text); +private slots: + void adjust_scroll_pos(); private: void adjustColumnCount(); -- cgit v1.2.3