aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Kočí <cynerd@email.cz>2018-01-25 15:40:50 +0100
committerKarel Kočí <cynerd@email.cz>2018-01-25 15:40:50 +0100
commit92c7fd220506df5f7997d27dbbcdb513e66932a7 (patch)
tree387da2cffe29d48cb6894070c8dcdd9900bce2a9
parenteb75bba956fb13e156a89406f5928a55e7b66fc4 (diff)
downloadqtmips-92c7fd220506df5f7997d27dbbcdb513e66932a7.tar.gz
qtmips-92c7fd220506df5f7997d27dbbcdb513e66932a7.tar.bz2
qtmips-92c7fd220506df5f7997d27dbbcdb513e66932a7.zip
Implement memoryview
-rw-r--r--qtmips_gui/mainwindow.cpp1
-rw-r--r--qtmips_gui/memorydock.cpp37
-rw-r--r--qtmips_gui/memorydock.h17
-rw-r--r--qtmips_gui/memoryview.cpp162
-rw-r--r--qtmips_gui/memoryview.h51
-rw-r--r--qtmips_gui/programdock.cpp106
-rw-r--r--qtmips_gui/programdock.h31
-rw-r--r--qtmips_gui/statictable.cpp125
-rw-r--r--qtmips_gui/statictable.h27
9 files changed, 432 insertions, 125 deletions
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp
index c064509..0f5d11a 100644
--- a/qtmips_gui/mainwindow.cpp
+++ b/qtmips_gui/mainwindow.cpp
@@ -104,6 +104,7 @@ void MainWindow::create_core(const machine::MachineConfig &config) {
// Setup docks
registers->setup(machine);
program->setup(machine);
+ memory->setup(machine);
// Set status to ready
machine_status(machine::QtMipsMachine::ST_READY);
}
diff --git a/qtmips_gui/memorydock.cpp b/qtmips_gui/memorydock.cpp
index 8998b32..d0bad9c 100644
--- a/qtmips_gui/memorydock.cpp
+++ b/qtmips_gui/memorydock.cpp
@@ -1,22 +1,35 @@
#include "memorydock.h"
+DataView::DataView(QWidget *parent) : MemoryView(parent) { }
+
+QList<QWidget*> DataView::row_widget(std::uint32_t address, QWidget *parent) {
+ QList<QWidget*> widgs;
+ QLabel *l;
+
+ l = new QLabel(QString("0x%1").arg(address, 8, 16, QChar('0')), parent);
+ l->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ widgs.append(l);
+
+ l = new QLabel(parent);
+ l->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ if (memory != nullptr) {
+ l->setText(QString("0x%1").arg(memory->read_word(address), 8, 16, QChar('0')));
+ }
+ else
+ l->setText(" "); // Just fill it in with some plain text so we don't have just addresses there
+ widgs.append(l);
+
+ return widgs;
+}
+
MemoryDock::MemoryDock(QWidget *parent) : QDockWidget(parent) {
- memory_view = new MemoryView(this);
- setWidget(memory_view);
+ view = new DataView(this);
+ setWidget(view);
setObjectName("Memory");
setWindowTitle("Memory");
}
-MemoryDock::~MemoryDock() {
- delete memory_view;
-}
-
void MemoryDock::setup(machine::QtMipsMachine *machine) {
- if (machine == nullptr)
- // TODO reset memory view
- return;
-
- // TODO setup memory view
-
+ view->setup(machine);
}
diff --git a/qtmips_gui/memorydock.h b/qtmips_gui/memorydock.h
index 533451e..612f986 100644
--- a/qtmips_gui/memorydock.h
+++ b/qtmips_gui/memorydock.h
@@ -2,19 +2,32 @@
#define MEMORYDOCK_H
#include <QDockWidget>
+#include <QLabel>
+#include <QComboBox>
#include "qtmipsmachine.h"
#include "memoryview.h"
+class DataView : public MemoryView {
+ Q_OBJECT
+public:
+ DataView(QWidget *parent);
+
+protected:
+ QList<QWidget*> row_widget(std::uint32_t address, QWidget *parent);
+
+private:
+ QComboBox *cb_size;
+};
+
class MemoryDock : public QDockWidget {
Q_OBJECT
public:
MemoryDock(QWidget *parent);
- ~MemoryDock();
void setup(machine::QtMipsMachine *machine);
private:
- MemoryView *memory_view;
+ DataView *view;
};
#endif // MEMORYDOCK_H
diff --git a/qtmips_gui/memoryview.cpp b/qtmips_gui/memoryview.cpp
index bd5d6d8..c391169 100644
--- a/qtmips_gui/memoryview.cpp
+++ b/qtmips_gui/memoryview.cpp
@@ -1,47 +1,167 @@
#include "memoryview.h"
+///////////////////////////
+// Minimal reserved range in pixels of scroll area (otherwise 10% of height are used)
+#define MIN_OFF 10
+///////////////////////////
+
+#include <iostream>
+using namespace std;
+
MemoryView::MemoryView(QWidget *parent) : QWidget(parent) {
+ memory = nullptr;
+ addr_0 = 0;
+
layout = new QVBoxLayout(this);
- frame = new QFrame(this);
- frame->setFrameShadow(QFrame::Sunken);
- frame->setFrameShape(QFrame::StyledPanel);
- frame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- // TODO
- layout->addWidget(frame);
+ memf= new Frame(this);
+ layout->addWidget(memf);
- go_edit = new QLineEdit(this);
+
+ ctl_widg = new QWidget(this);
+ layout->addWidget(ctl_widg);
+
+ ctl_layout = new QHBoxLayout(ctl_widg);
+ go_edit = new QLineEdit(ctl_widg);
go_edit->setText("0x00000000");
go_edit->setInputMask("\\0\\xHHHHHHHH");
- layout->addWidget(go_edit);
+ ctl_layout->addWidget(go_edit);
connect(go_edit, SIGNAL(editingFinished()), this, SLOT(go_edit_finish()));
-
+ up = new QToolButton(ctl_widg);
+ up->setArrowType(Qt::UpArrow);
+ ctl_layout->addWidget(up);
+ down = new QToolButton(ctl_widg);
+ down->setArrowType(Qt::DownArrow);
+ ctl_layout->addWidget(down);
}
-MemoryView::~MemoryView() {
- delete go_edit;
- delete frame;
- delete layout;
+void MemoryView::setup(machine::QtMipsMachine *machine) {
+ memory = (machine == nullptr) ? nullptr : machine->memory();
+ reload_content();
}
-void MemoryView::set_center(std::uint32_t address) {
- center_addr = address;
+void MemoryView::set_focus(std::uint32_t address) {
+ // TODO center
// TODO update view
}
-std::uint32_t MemoryView::center() {
- return center_addr;
+std::uint32_t MemoryView::focus() {
+ // TODO
+ return 0;
+}
+
+void MemoryView::reload_content() {
+ int count = memf->widg->count();
+ memf->widg->clearRows();
+ update_content(count, 0);
+}
+
+void MemoryView::update_content(int count, int shift) {
+ if (abs(shift) >= memf->widg->count()) {
+ // This shifts more than we have so just reload whole content
+ memf->widg->clearRows();
+ addr_0 += 4*shift;
+ for (int i = 0; i <= count; i++)
+ memf->widg->addRow(row_widget(addr_0 + 4*i, memf->widg));
+ return;
+ }
+
+ int diff = count - memf->widg->count();
+ int d_b = shift;
+ int d_e = diff - shift;
+ cout << "count:" << memf->widg->count() << " tocount:" << count << " d_b:" << d_b << " d_e:" << d_e << endl;
+
+ if (d_b > 0)
+ for (int i = 0; i < d_b; i++) {
+ addr_0 -= 4;
+ memf->widg->insertRow(row_widget(addr_0, memf->widg), 0);
+ }
+ else
+ for (int i = 0; i > d_b; i--) {
+ addr_0 += 4;
+ memf->widg->removeRow(0);
+ }
+ if (d_e > 0)
+ for (int i = 0; i < d_e; i++)
+ memf->widg->addRow(row_widget(addr_0 + 4*memf->widg->count(), memf->widg));
+ else
+ for (int i = 0; i > d_e; i--)
+ memf->widg->removeRow(memf->widg->count() - 1);
}
-void MemoryView::resizeEvent(QResizeEvent *event) {
- QWidget::resizeEvent(event);
+void MemoryView::go_edit_finish() {
// TODO
}
-void MemoryView::wheelEvent(QWheelEvent *event) {
+MemoryView::Frame::Frame(MemoryView *parent) : QAbstractScrollArea(parent) {
+ mv = parent;
+ content_y = -3*MIN_OFF/2; // When this is initialized the width is 0 so this uses just min to inialize it
+
+ widg = new StaticTable(this);
+ setViewport(widg);
+
+ setFrameShadow(QFrame::Sunken);
+ setFrameShape(QFrame::StyledPanel);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ setContentsMargins(0, 0, 0, 0);
+}
+
+void MemoryView::Frame::focus(unsigned i) {
// TODO
}
-void MemoryView::go_edit_finish() {
+unsigned MemoryView::Frame::focussed() {
// TODO
+ return 0;
+}
+
+// This verifies that we are not scrolled too far away down or up and that we have enought height
+// We make 10% of height as buffer zone with fixed minimum in pixels
+void MemoryView::Frame::check_update() {
+ int hpart = qMax(height()/10, MIN_OFF);
+ int req_height = height() + 2*hpart;
+
+ while (!((content_y <= -hpart) && (content_y >= -2*hpart)) || (widg->height() < req_height)) {
+ cout << "widg.h:" << widg->height() << " req_h:" << req_height << endl;
+ cout << "content_y:" << content_y << " hpart:" << hpart << endl;
+ int row_h = widg->row_size();
+ cout << "row_h:" << row_h << " columns:" << widg->columns() << endl;
+ // Calculate how many we need and how much we need to move and update content accordingly
+ int count = (req_height / row_h) + 1;
+ int shift = (content_y + hpart + hpart/2)/row_h;
+ mv->update_content(count * widg->columns(), shift * widg->columns());
+ cout << "count:" << count << endl;
+ // Move and resize widget
+ content_y -= shift * row_h;
+ widg->setGeometry(0, content_y, width(), widg->heightForWidth(width()));
+ }
+}
+
+void MemoryView::Frame::resizeEvent(QResizeEvent *e) {
+ QAbstractScrollArea::resizeEvent(e);
+ widg->setGeometry(0, content_y, e->size().width(), widg->heightForWidth(e->size().width()));
+ check_update();
+}
+
+void MemoryView::Frame::wheelEvent(QWheelEvent *e) {
+ QPoint pix = e->pixelDelta();
+ QPoint ang = e->angleDelta();
+
+ if (!pix.isNull())
+ content_y += e->pixelDelta().ry();
+ // TODO angle scroll
+
+ // TODO smooth scroll
+ viewport()->move(0, content_y);
+ viewport()->repaint(0, content_y, width(), height());
+
+ check_update();
+}
+
+bool MemoryView::Frame::viewportEvent(QEvent *e) {
+ bool p = QAbstractScrollArea::viewportEvent(e);
+ // Pass paint event to viewport widget
+ if (e->type() == QEvent::Paint)
+ p = false;
+ return p;
}
diff --git a/qtmips_gui/memoryview.h b/qtmips_gui/memoryview.h
index e1049e8..be2c8a2 100644
--- a/qtmips_gui/memoryview.h
+++ b/qtmips_gui/memoryview.h
@@ -2,35 +2,68 @@
#define MEMORYVIEW_H
#include <QWidget>
-#include <QFrame>
+#include <QAbstractScrollArea>
#include <QBoxLayout>
+#include <QGridLayout>
#include <QLineEdit>
+#include <QToolButton>
+#include <QList>
+#include <QVector>
#include <cstdint>
+#include <QResizeEvent>
+#include "qtmipsmachine.h"
+#include "statictable.h"
class MemoryView : public QWidget {
+ Q_OBJECT
public:
MemoryView(QWidget *parent = nullptr);
- ~MemoryView();
- void set_center(std::uint32_t address);
- std::uint32_t center();
+ virtual void setup(machine::QtMipsMachine*);
+
+ void set_focus(std::uint32_t address);
+ std::uint32_t focus();
protected:
- //virtual QWidget *row_widget(std::uint32_t address) = 0;
+ const machine::Memory *memory;
- void resizeEvent(QResizeEvent *event);
- void wheelEvent(QWheelEvent *event);
+ virtual QList<QWidget*> row_widget(std::uint32_t address, QWidget *parent) = 0;
QVBoxLayout *layout;
+ void reload_content(); // reload displayed data
+ void update_content(int count, int shift); // update content to match given count and shift
+
private slots:
void go_edit_finish();
private:
- std::uint32_t center_addr;
+ unsigned count;
+ std::uint32_t addr_0; // First address in view
+
+ class Frame : public QAbstractScrollArea {
+ public:
+ Frame(MemoryView *parent);
+
+ StaticTable *widg;
+ void focus(unsigned i); // Focus on given item in widget
+ unsigned focussed(); // What item is in focus
+ void check_update(); // Update widget size and content if needed
+
+ protected:
+ MemoryView *mv;
+ int content_y;
+
+ bool viewportEvent(QEvent*);
+ void resizeEvent(QResizeEvent*);
+ void wheelEvent(QWheelEvent *event);
+ };
+ Frame *memf;
- QFrame *frame;
+ QWidget *ctl_widg;
+ QHBoxLayout *ctl_layout;
QLineEdit *go_edit;
+ QToolButton *up, *down;
};
#endif // MEMORYVIEW_H
diff --git a/qtmips_gui/programdock.cpp b/qtmips_gui/programdock.cpp
index c885083..9178dce 100644
--- a/qtmips_gui/programdock.cpp
+++ b/qtmips_gui/programdock.cpp
@@ -1,26 +1,21 @@
#include "programdock.h"
#include "qtmipsexception.h"
-ProgramDock::ProgramDock(QWidget *parent) : QDockWidget(parent) {
- widg = new QWidget(this);
- widg_layout = new QBoxLayout(QBoxLayout::TopToBottom, widg);
- widg_layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
-
- memory_view = new MemoryView(widg);
- widg_layout->addWidget(memory_view);
+ProgramView::ProgramView(QWidget *parent) : MemoryView(parent) {
+ set_center(0x80020000); // Initialize center address to program start
- ctlbox_single = new QComboBox(widg);
- ctlbox_single->addItems({
+ cb_single = new QComboBox(this);
+ cb_single->addItems({
"Don't follow",
"Follow executing instruction"
});
- ctlbox_single->setCurrentIndex(1);
- ctlbox_single->hide();
- widg_layout->addWidget(ctlbox_single);
- connect(ctlbox_single, SIGNAL(currentIndexChanged(int)), this, SLOT(ctlbox_single_changed(int)));
+ cb_single->setCurrentIndex(1);
+ cb_single->hide();
+ layout->addWidget(cb_single);
+ connect(cb_single, SIGNAL(currentIndexChanged(int)), this, SLOT(cb_single_changed(int)));
- ctlbox_pipelined = new QComboBox(widg);
- ctlbox_pipelined->addItems({
+ cb_pipelined = new QComboBox(this);
+ cb_pipelined->addItems({
"Don't follow",
"Follow Instruction fetch stage",
"Follow Instruction decode stage",
@@ -28,51 +23,68 @@ ProgramDock::ProgramDock(QWidget *parent) : QDockWidget(parent) {
"Follow Memory access stage",
"Follow Registers write back stage",
});
- ctlbox_pipelined->hide();
- ctlbox_pipelined->setCurrentIndex(1);
- widg_layout->addWidget(ctlbox_pipelined);
- connect(ctlbox_pipelined, SIGNAL(currentIndexChanged(int)), this, SLOT(ctlbox_pipelined_changed(int)));
-
- setWidget(widg);
- setObjectName("Program");
- setWindowTitle("Program");
-}
-
-ProgramDock::~ProgramDock() {
- delete memory_view;
- delete ctlbox_single;
- delete ctlbox_pipelined;
- delete widg_layout;
- delete widg;
+ cb_pipelined->hide();
+ cb_pipelined->setCurrentIndex(1);
+ layout->addWidget(cb_pipelined);
+ connect(cb_pipelined, SIGNAL(currentIndexChanged(int)), this, SLOT(cb_pipelined_changed(int)));
}
-void ProgramDock::setup(machine::QtMipsMachine *machine) {
- if (machine == nullptr) {
- // TODO zero memory viewer
+void ProgramView::setup(machine::QtMipsMachine *machine) {
+ MemoryView::setup(machine);
+ if (machine == nullptr)
return;
- }
-
- // TODO pass to viewer
bool pipelined = machine->config().pipelined();
- ctlbox_single->setVisible(!pipelined);
- ctlbox_pipelined->setVisible(pipelined);
+ cb_single->setVisible(!pipelined);
+ cb_pipelined->setVisible(pipelined);
// Sync selection somewhat
if (pipelined) {
- if (ctlbox_single->currentIndex() == 0)
- ctlbox_pipelined->setCurrentIndex(0);
- else if (ctlbox_pipelined->currentIndex() == 0)
- ctlbox_pipelined->setCurrentIndex(1);
+ if (cb_single->currentIndex() == 0)
+ cb_pipelined->setCurrentIndex(0);
+ else if (cb_pipelined->currentIndex() == 0)
+ cb_pipelined->setCurrentIndex(1);
} else
- ctlbox_single->setCurrentIndex(ctlbox_pipelined->currentIndex() == 0 ? 0 : 1);
+ cb_single->setCurrentIndex(cb_pipelined->currentIndex() == 0 ? 0 : 1);
+}
+
+QList<QWidget*> ProgramView::row_widget(std::uint32_t address, QWidget *parent) {
+ QList<QWidget*> widgs;
+ QLabel *l;
+
+ l = new QLabel(" ", parent);
+ widgs.append(l);
- // TODO also update current setting of memory viewer
+ l = new QLabel(QString("0x%1").arg(address, 8, 16, QChar('0')), parent);
+ l->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ widgs.append(l);
+
+ l = new QLabel(parent);
+ l->setTextInteractionFlags(Qt::TextSelectableByMouse);
+ if (memory != nullptr)
+ l->setText(machine::Instruction(memory->read_word(address)).to_str());
+ else
+ l->setText(" "); // Just fill it in with some plain text so we don't have just addresses there
+ widgs.append(l);
+
+ return widgs;
}
-void ProgramDock::ctlbox_single_changed(int index) {
+void ProgramView::cb_single_changed(int index) {
// TODO set memory view
}
-void ProgramDock::ctlbox_pipelined_changed(int index) {
+void ProgramView::cb_pipelined_changed(int index) {
// TODO set memory view
}
+
+ProgramDock::ProgramDock(QWidget *parent) : QDockWidget(parent) {
+ view = new ProgramView(this);
+ setWidget(view);
+
+ setObjectName("Program");
+ setWindowTitle("Program");
+}
+
+void ProgramDock::setup(machine::QtMipsMachine *machine) {
+ view->setup(machine);
+}
diff --git a/qtmips_gui/programdock.h b/qtmips_gui/programdock.h
index 4605a7b..9ed0896 100644
--- a/qtmips_gui/programdock.h
+++ b/qtmips_gui/programdock.h
@@ -9,25 +9,34 @@
#include "qtmipsmachine.h"
#include "memoryview.h"
-class ProgramDock : public QDockWidget {
+class ProgramView : public MemoryView {
Q_OBJECT
public:
- ProgramDock(QWidget *parent);
- ~ProgramDock();
+ ProgramView(QWidget *parent);
- void setup(machine::QtMipsMachine *machine);
+ void setup(machine::QtMipsMachine*);
+
+protected:
+ QList<QWidget*> row_widget(std::uint32_t address, QWidget *parent);
private slots:
- void ctlbox_single_changed(int index);
- void ctlbox_pipelined_changed(int index);
+ void cb_single_changed(int index);
+ void cb_pipelined_changed(int index);
private:
- QWidget *widg;
- QBoxLayout *widg_layout;
+ QComboBox *cb_single;
+ QComboBox *cb_pipelined;
+};
- MemoryView *memory_view;
- QComboBox *ctlbox_single;
- QComboBox *ctlbox_pipelined;
+class ProgramDock : public QDockWidget {
+ Q_OBJECT
+public:
+ ProgramDock(QWidget *parent);
+
+ void setup(machine::QtMipsMachine *machine);
+
+private:
+ ProgramView *view;
};
#endif // PROGRAMDOCK_H
diff --git a/qtmips_gui/statictable.cpp b/qtmips_gui/statictable.cpp
index 8686847..fe8a820 100644
--- a/qtmips_gui/statictable.cpp
+++ b/qtmips_gui/statictable.cpp
@@ -3,6 +3,7 @@
#include <qtmipsexception.h>
#include <iostream>
+#include <QLabel>
using namespace std;
StaticTableLayout::StaticTableLayout(QWidget *parent, int margin, int horizontal_big_spacing, int horizontal_small_spacing, int vertical_spacing) : QLayout(parent) {
@@ -29,21 +30,28 @@ bool StaticTableLayout::hasHeightForWidth() const {
}
int StaticTableLayout::heightForWidth(int w) const {
- // TODO cache value
- return layout_height(w);
+ if (cch_heightForWidth.w != w || cch_heightForWidth.count != items.count())
+ cch_heightForWidth.width = layout_height(w);
+ cch_heightForWidth.w = w;
+ cch_heightForWidth.count = items.count();
+ return cch_heightForWidth.width;
}
QSize StaticTableLayout::minimumSize() const {
- QSize s;
+ if (cch_minSize.count == items.size())
+ return cch_minSize.size;
+ cch_minSize.count = items.size();
+
+ cch_minSize.size = QSize();
for (int i = 0; i < items.size(); i++) {
QSize ss;
for (int y = 0; y < items[i].size(); y++) {
- ss = s.expandedTo(items[i][y]->minimumSize() + QSize(shspace, 0));
+ ss = cch_minSize.size.expandedTo(items[i][y]->minimumSize() + QSize(shspace, 0));
}
- s = s.expandedTo(ss - QSize(shspace, 0));
+ cch_minSize.size = cch_minSize.size.expandedTo(ss - QSize(shspace, 0));
}
- s += QSize(2*margin(), 2*margin());
- return s;
+ cch_minSize.size += QSize(2*margin(), 2*margin());
+ return cch_minSize.size;
}
void StaticTableLayout::setGeometry(const QRect &rect) {
@@ -72,13 +80,28 @@ int StaticTableLayout::count() const {
}
void StaticTableLayout::addRow(QList<QWidget*> w) {
- QVector<QLayoutItem*> v;
- for (int i = 0; i < w.size(); i++) {
- addChildWidget(w[i]);
- v.append(new QWidgetItem(w[i]));
+ items.append(list2vec(w));
+}
+
+void StaticTableLayout::insertRow(QList<QWidget*> w, int i) {
+ items.insert(i, list2vec(w));
+}
+
+void StaticTableLayout::removeRow(int i) {
+ for (int y = 0; y < items[i].size(); y++) {
+ delete items[i][y]->widget();
+ delete items[i][y];
}
+ items.remove(i);
+}
- items.append(v);
+void StaticTableLayout::clearRows() {
+ for (int i = 0; i < items.size(); i++)
+ for (int y = 0; y < items[i].size(); y++) {
+ delete items[i][y]->widget();
+ delete items[i][y];
+ }
+ items.clear();
}
void StaticTableLayout::itemRect(QRect &rect, QVector<int> &separators, int i) {
@@ -100,7 +123,6 @@ void StaticTableLayout::itemRect(QRect &rect, QVector<int> &separators, int i) {
x -= bhspace/2;
int y = top + (row * (row_height + vspace));
-
int width = 0;
for (int t = 0; t < row_widths[col].size(); t++) {
width += row_widths[col][t] + shspace;
@@ -117,14 +139,32 @@ int StaticTableLayout::columns() {
return row_widths.size();
}
+int StaticTableLayout::real_row_height() {
+ return row_height + vspace;
+}
+
int StaticTableLayout::layout_count_approx(const QRect &rect) const {
if (items.size() <= 0)
return 1;
+ // Note: for some reason (probably optimalisation) when qlabel is not visible it reports 0 size. So we have to found at least one that is visible
+ int vis = 0;
+ while (items[vis].size() <= 0 || !items[vis][0]->widget()->isVisible()) {
+ vis++;
+ if (vis >= items.size())
+ return 1; // If non is visible then just say that it has to be single column
+ }
+
int w = 0;
- for (int i = 0; i < items[0].size(); i++)
- w += items[0][i]->sizeHint().width() + shspace;
+ for (int i = 0; i < items[vis].size(); i++)
+ w += items[vis][i]->sizeHint().width() + shspace;
w -= shspace; // subtract lastest spacing
int width = rect.right() / w; // Note: this always rounds down so this always founds maximal possible count
+
+ cout << "ST: widht:" << rect.right() << " row_w" << w << " so count:" << width << " we have:" << items.count() << " In 0:" << items[vis].count() << " contains:";
+ for (int i = 0; i < items[0].size(); i++)
+ cout << ((QLabel*)items[0][i]->widget())->text().toStdString() << " ";
+ cout << endl;
+
return width <= 0 ? 1 : width; // We have to fit at least one column
}
@@ -164,22 +204,24 @@ void StaticTableLayout::layout_parms(QRect &rect, int &row_h, QList<QList<int>>
// Firt let's do orientation count only on first line
count = layout_count_approx(rect);
- if (layout_size(row_h, row_w, count) > rect.right()) {
+ while (layout_size(row_h, row_w, count) > rect.right() && count > 1) {
// Not using orientation count go down if we can't fit (if we can then just be happy with what we have)
- do {
- if (count <= 1)
- // TODO meaby warning?
- break; // We can't fit it but ignore that.
- count--;
- } while (layout_size(row_h, row_w, count) <= rect.width());
+ count--;
}
}
void StaticTableLayout::do_layout(const QRect &rect) {
+ if (cch_do_layout.size == rect.size() && cch_do_layout.count == items.size())
+ // No effective change so don't do layout
+ return;
+ cch_do_layout.size = rect.size();
+ cch_do_layout.count = items.size();
+
int row_h;
QList<QList<int>> row_w;
int count;
+ cout << "Doing layout" << endl;
QRect reff(rect);
layout_parms(reff, row_h, row_w, count);
@@ -202,6 +244,7 @@ void StaticTableLayout::do_layout(const QRect &rect) {
}
int StaticTableLayout::layout_height(int width) const {
+ cout << "Quering height" << endl;
QRect reff(0, 0, width, 0);
int row_h;
QList<QList<int>> row_w;
@@ -211,15 +254,51 @@ int StaticTableLayout::layout_height(int width) const {
return (row_h + vspace) * (items.size() / count);
}
+QVector<QLayoutItem*> StaticTableLayout::list2vec(QList<QWidget*> w) {
+ QVector<QLayoutItem*> v;
+ for (int i = 0; i < w.size(); i++) {
+ addChildWidget(w[i]);
+ v.append(new QWidgetItem(w[i]));
+ }
+ return v;
+}
+
StaticTable::StaticTable(QWidget *parent) : QWidget(parent), layout(this) {
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
}
+int StaticTable::count() {
+ return layout.count();
+}
+
void StaticTable::addRow(QList<QWidget*> w) {
layout.addRow(w);
}
+void StaticTable::insertRow(QList<QWidget*> w, int i) {
+ layout.insertRow(w, i);
+}
+
+void StaticTable::removeRow(int i) {
+ layout.removeRow(i);
+}
+
+void StaticTable::clearRows() {
+ layout.clearRows();
+}
+
+int StaticTable::columns() {
+ return qMax(layout.columns(), 1);
+}
+
+int StaticTable::row_size() {
+ return layout.real_row_height();
+}
+
void StaticTable::paintEvent(QPaintEvent*) {
+ if (layout.columns() <= 0) // Don't paint unless we have at least one column
+ return;
+
QPainter p(this);
p.setPen(QPen(QColor(200, 200, 200)));
@@ -232,7 +311,7 @@ void StaticTable::paintEvent(QPaintEvent*) {
if ((col % 2) == (row % 2))
p.setBrush(QBrush(QColor(255, 255, 255)));
else
- p.setBrush(QBrush(QColor(230, 230, 230)));
+ p.setBrush(QBrush(QColor(235, 235, 235)));
layout.itemRect(rect, separators, i);
diff --git a/qtmips_gui/statictable.h b/qtmips_gui/statictable.h
index 8248aa3..9249430 100644
--- a/qtmips_gui/statictable.h
+++ b/qtmips_gui/statictable.h
@@ -31,9 +31,13 @@ public:
int count() const override; // This returns number of item blocks
void addRow(QList<QWidget*>); // This adds row of widgets
+ void insertRow(QList<QWidget*>, int i); // Insert row to given position while shifting all other up
+ void removeRow(int i); // Remove row
+ void clearRows(); // Clear all rows from table
void itemRect(QRect &rect, QVector<int> &separators, int i); // This returns single item rectable (if expad_margin and it's on edge also count in margin)
int columns();
+ int real_row_height();
protected:
int shspace, bhspace, vspace;
@@ -47,13 +51,36 @@ protected:
void layout_parms(QRect &rect, int &row_h, QList<QList<int>> &row_w, int &count) const;
void do_layout(const QRect &rect);
int layout_height(int width) const;
+
+ QVector<QLayoutItem*> list2vec(QList<QWidget*>);
+
+ struct {
+ QSize size;
+ int count;
+ } cch_do_layout;
+ mutable struct {
+ int w, count;
+ int width;
+ } cch_heightForWidth;
+ mutable struct {
+ int count;
+ QSize size;
+ } cch_minSize;
+
};
class StaticTable : public QWidget {
public:
StaticTable(QWidget *parent = nullptr);
+ int count();
void addRow(QList<QWidget*>);
+ void insertRow(QList<QWidget*>, int i);
+ void removeRow(int i);
+ void clearRows();
+
+ int columns();
+ int row_size(); // return real row size (height) including spacing
protected:
void paintEvent(QPaintEvent*);