forked from len0rd/rockbox
qeditor: introduce new "sexy register display"
Change-Id: Ib938b4be71d2c7623851dbc3c211f96105077d7d
This commit is contained in:
parent
2c832968c9
commit
c8d3638b9e
7 changed files with 285 additions and 133 deletions
|
@ -12,7 +12,7 @@ libsocdesc.commands = cd ../lib && make
|
||||||
QMAKE_EXTRA_TARGETS += libsocdesc
|
QMAKE_EXTRA_TARGETS += libsocdesc
|
||||||
PRE_TARGETDEPS += libsocdesc
|
PRE_TARGETDEPS += libsocdesc
|
||||||
|
|
||||||
VERSION = 2.0.3
|
VERSION = 2.0.4
|
||||||
|
|
||||||
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S
|
||||||
raw_val_layout->addWidget(m_raw_val_edit);
|
raw_val_layout->addWidget(m_raw_val_edit);
|
||||||
raw_val_layout->addStretch();
|
raw_val_layout->addStretch();
|
||||||
|
|
||||||
m_value_table = new GrowingTableView;
|
m_value_table = new GrowingTableView();
|
||||||
m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership
|
m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership
|
||||||
m_value_model->SetRegister(m_reg.GetReg());
|
m_value_model->SetRegister(m_reg.GetReg());
|
||||||
m_value_model->SetReadOnly(read_only);
|
m_value_model->SetReadOnly(read_only);
|
||||||
|
@ -208,7 +208,7 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S
|
||||||
// FIXME we cannot use setAlternatingRowColors() because we override the
|
// FIXME we cannot use setAlternatingRowColors() because we override the
|
||||||
// background color, should it be part of the model ?
|
// background color, should it be part of the model ?
|
||||||
|
|
||||||
SocFieldCachedItemDelegate *m_table_delegate = new SocFieldCachedItemDelegate(this);
|
m_table_delegate = new SocFieldCachedItemDelegate(this);
|
||||||
m_table_edit_factory = new QItemEditorFactory();
|
m_table_edit_factory = new QItemEditorFactory();
|
||||||
SocFieldCachedEditorCreator *m_table_edit_creator = new SocFieldCachedEditorCreator();
|
SocFieldCachedEditorCreator *m_table_edit_creator = new SocFieldCachedEditorCreator();
|
||||||
// FIXME see QTBUG-30392
|
// FIXME see QTBUG-30392
|
||||||
|
@ -217,8 +217,10 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S
|
||||||
m_table_delegate->setItemEditorFactory(m_table_edit_factory);
|
m_table_delegate->setItemEditorFactory(m_table_edit_factory);
|
||||||
m_value_table->setItemDelegate(m_table_delegate);
|
m_value_table->setItemDelegate(m_table_delegate);
|
||||||
|
|
||||||
m_sexy_display = new RegSexyDisplay(reg_ref, this);
|
m_sexy_display2 = new Unscroll<RegSexyDisplay2>(this);
|
||||||
m_sexy_display->setFont(m_reg_font);
|
m_sexy_display2->setFont(m_reg_font);
|
||||||
|
m_sexy_display2->setModel(m_value_model);
|
||||||
|
m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
|
||||||
m_desc = new QLabel(this);
|
m_desc = new QLabel(this);
|
||||||
m_desc->setTextFormat(Qt::RichText);
|
m_desc->setTextFormat(Qt::RichText);
|
||||||
|
@ -228,8 +230,9 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S
|
||||||
right_layout->addLayout(top_layout);
|
right_layout->addLayout(top_layout);
|
||||||
if(raw_val_layout)
|
if(raw_val_layout)
|
||||||
right_layout->addLayout(raw_val_layout);
|
right_layout->addLayout(raw_val_layout);
|
||||||
right_layout->addWidget(m_sexy_display);
|
right_layout->addWidget(m_sexy_display2);
|
||||||
right_layout->addWidget(m_value_table);
|
right_layout->addWidget(m_value_table);
|
||||||
|
right_layout->addStretch();
|
||||||
|
|
||||||
setTitle("Register Description");
|
setTitle("Register Description");
|
||||||
m_viewport = new QWidget;
|
m_viewport = new QWidget;
|
||||||
|
|
|
@ -105,7 +105,7 @@ protected:
|
||||||
const SocRegRef& m_reg;
|
const SocRegRef& m_reg;
|
||||||
bool m_allow_write;
|
bool m_allow_write;
|
||||||
RegLineEdit *m_raw_val_edit;
|
RegLineEdit *m_raw_val_edit;
|
||||||
RegSexyDisplay *m_sexy_display;
|
Unscroll< RegSexyDisplay2 > *m_sexy_display2;
|
||||||
GrowingTableView *m_value_table;
|
GrowingTableView *m_value_table;
|
||||||
RegFieldTableModel *m_value_model;
|
RegFieldTableModel *m_value_model;
|
||||||
QStyledItemDelegate *m_table_delegate;
|
QStyledItemDelegate *m_table_delegate;
|
||||||
|
|
|
@ -336,47 +336,33 @@ RegEditPanel::RegEditPanel(SocRegRef ref, QWidget *parent)
|
||||||
top_layout->addLayout(name_layout);
|
top_layout->addLayout(name_layout);
|
||||||
top_layout->addWidget(m_desc_group, 1);
|
top_layout->addWidget(m_desc_group, 1);
|
||||||
|
|
||||||
m_sexy_display = new RegSexyDisplay(m_ref, this);
|
m_value_table = new QTableView(this);
|
||||||
m_sexy_display->setFont(m_reg_font);
|
m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership
|
||||||
|
m_value_model->SetRegister(m_ref.GetReg());
|
||||||
|
m_value_model->SetReadOnly(true);
|
||||||
|
m_value_table->setModel(m_value_model);
|
||||||
|
m_value_table->verticalHeader()->setVisible(false);
|
||||||
|
m_value_table->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
// FIXME we cannot use setAlternatingRowColors() because we override the
|
||||||
|
// background color, should it be part of the model ?
|
||||||
|
m_table_delegate = new SocFieldCachedItemDelegate(this);
|
||||||
|
m_value_table->setItemDelegate(m_table_delegate);
|
||||||
|
m_value_table->resizeColumnsToContents();
|
||||||
|
|
||||||
|
m_sexy_display2 = new Unscroll<RegSexyDisplay2>(this);
|
||||||
|
m_sexy_display2->setFont(m_reg_font);
|
||||||
|
m_sexy_display2->setModel(m_value_model);
|
||||||
|
m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
|
||||||
m_field_table = new QTableWidget;
|
|
||||||
m_field_table->setRowCount(m_ref.GetReg().field.size());
|
|
||||||
m_field_table->setColumnCount(4);
|
|
||||||
for(size_t row = 0; row < m_ref.GetReg().field.size(); row++)
|
|
||||||
{
|
|
||||||
const soc_reg_field_t& field = m_ref.GetReg().field[row];
|
|
||||||
QString bits_str;
|
|
||||||
if(field.first_bit == field.last_bit)
|
|
||||||
bits_str.sprintf("%d", field.first_bit);
|
|
||||||
else
|
|
||||||
bits_str.sprintf("%d:%d", field.last_bit, field.first_bit);
|
|
||||||
QTableWidgetItem *item = new QTableWidgetItem(bits_str);
|
|
||||||
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
|
|
||||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
||||||
m_field_table->setItem(row, 1, item);
|
|
||||||
item = new QTableWidgetItem(QString(field.name.c_str()));
|
|
||||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
||||||
m_field_table->setItem(row, 2, item);
|
|
||||||
item = new QTableWidgetItem(QString(field.desc.c_str()));
|
|
||||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
||||||
m_field_table->setItem(row, 3, item);
|
|
||||||
UpdateWarning(row);
|
|
||||||
}
|
|
||||||
m_field_table->setHorizontalHeaderItem(0, new QTableWidgetItem(""));
|
|
||||||
m_field_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Bits"));
|
|
||||||
m_field_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Name"));
|
|
||||||
m_field_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Description"));
|
|
||||||
m_field_table->verticalHeader()->setVisible(false);
|
|
||||||
m_field_table->resizeColumnsToContents();
|
|
||||||
m_field_table->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
QHBoxLayout *field_layout = new QHBoxLayout;
|
QHBoxLayout *field_layout = new QHBoxLayout;
|
||||||
field_layout->addWidget(m_field_table);
|
field_layout->addWidget(m_value_table);
|
||||||
m_field_group = new QGroupBox("Flags", this);
|
m_field_group = new QGroupBox("Flags", this);
|
||||||
m_field_group->setLayout(field_layout);
|
m_field_group->setLayout(field_layout);
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
layout->addLayout(top_layout, 0);
|
layout->addLayout(top_layout, 0);
|
||||||
layout->addWidget(m_sexy_display, 0);
|
layout->addWidget(m_sexy_display2, 0);
|
||||||
layout->addWidget(m_field_group);
|
layout->addWidget(m_field_group);
|
||||||
|
|
||||||
UpdateFormula();
|
UpdateFormula();
|
||||||
|
|
|
@ -185,10 +185,12 @@ protected:
|
||||||
QComboBox *m_formula_combo;
|
QComboBox *m_formula_combo;
|
||||||
QLineEdit *m_formula_string_edit;
|
QLineEdit *m_formula_string_edit;
|
||||||
QPushButton *m_formula_string_gen;
|
QPushButton *m_formula_string_gen;
|
||||||
RegSexyDisplay *m_sexy_display;
|
Unscroll< RegSexyDisplay2 > *m_sexy_display2;
|
||||||
MyTextEditor *m_desc_edit;
|
MyTextEditor *m_desc_edit;
|
||||||
QGroupBox *m_field_group;
|
QGroupBox *m_field_group;
|
||||||
QTableWidget *m_field_table;
|
QTableView *m_value_table;
|
||||||
|
RegFieldTableModel *m_value_model;
|
||||||
|
QStyledItemDelegate *m_table_delegate;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FieldEditPanel : public QWidget, public AbstractRegEditPanel
|
class FieldEditPanel : public QWidget, public AbstractRegEditPanel
|
||||||
|
|
|
@ -669,104 +669,178 @@ void RegFieldTableModel::RecomputeTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RegSexyDisplay
|
* RegSexyDisplay2
|
||||||
*/
|
*/
|
||||||
RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent)
|
|
||||||
:QWidget(parent), m_reg(reg)
|
RegSexyDisplay2::RegSexyDisplay2(QWidget *parent)
|
||||||
|
:QAbstractItemView(parent)
|
||||||
{
|
{
|
||||||
m_size = QSize();
|
m_is_dirty = true;
|
||||||
|
// the frame around the register is ugly, disable it
|
||||||
|
setFrameShape(QFrame::NoFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::separatorSize() const
|
QModelIndex RegSexyDisplay2::indexAt(const QPoint& point) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(point);
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::scrollTo(const QModelIndex& index, ScrollHint hint)
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
Q_UNUSED(hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect RegSexyDisplay2::visualRect(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
return QRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegSexyDisplay2::isIndexHidden(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex RegSexyDisplay2::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
|
||||||
|
{
|
||||||
|
Q_UNUSED(cursorAction);
|
||||||
|
Q_UNUSED(modifiers);
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags)
|
||||||
|
{
|
||||||
|
Q_UNUSED(rect);
|
||||||
|
Q_UNUSED(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegSexyDisplay2::verticalOffset() const
|
||||||
|
{
|
||||||
|
return verticalScrollBar()->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegSexyDisplay2::horizontalOffset() const
|
||||||
|
{
|
||||||
|
return horizontalScrollBar()->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::scrollContentsBy(int dx, int dy)
|
||||||
|
{
|
||||||
|
viewport()->scroll(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::setModel(QAbstractItemModel *model)
|
||||||
|
{
|
||||||
|
QAbstractItemView::setModel(model);
|
||||||
|
m_is_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::dataChanged(const QModelIndex &topLeft,
|
||||||
|
const QModelIndex &bottomRight)
|
||||||
|
{
|
||||||
|
m_is_dirty = true;
|
||||||
|
QAbstractItemView::dataChanged(topLeft, bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||||
|
{
|
||||||
|
m_is_dirty = true;
|
||||||
|
QAbstractItemView::rowsInserted(parent, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
|
||||||
|
{
|
||||||
|
m_is_dirty = true;
|
||||||
|
QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegSexyDisplay2::GetSeparatorSize() const
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::marginSize() const
|
int RegSexyDisplay2::GetMarginSize() const
|
||||||
{
|
{
|
||||||
return fontMetrics().height() / 3;
|
return viewOptions().fontMetrics.height() / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::textSep() const
|
int RegSexyDisplay2::GetHeaderTextSep() const
|
||||||
{
|
{
|
||||||
return marginSize() / 2;
|
return GetMarginSize() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::headerHeight() const
|
int RegSexyDisplay2::GetHeaderHeight() const
|
||||||
{
|
{
|
||||||
return 2 * marginSize() + textSep() + 2 * fontMetrics().height();
|
return 2 * GetMarginSize() + GetHeaderTextSep() + 2 * viewOptions().fontMetrics.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::columnWidth() const
|
int RegSexyDisplay2::GetColumnWidth() const
|
||||||
{
|
{
|
||||||
return 2 * marginSize() + fontMetrics().height();
|
return 2 * GetMarginSize() + viewOptions().fontMetrics.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::maxContentHeight() const
|
int RegSexyDisplay2::GetMaxContentHeight() const
|
||||||
{
|
{
|
||||||
int max = 0;
|
int max = 0;
|
||||||
QFontMetrics metrics = fontMetrics();
|
QFontMetrics metrics = viewOptions().fontMetrics;
|
||||||
for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
|
if(model())
|
||||||
{
|
{
|
||||||
QString s = QString::fromStdString(m_reg.GetReg().field[i].name);
|
for(int i = 0; i < model()->rowCount(); i++)
|
||||||
// add extra spaces arounds
|
{
|
||||||
s = " " + s + " ";
|
QModelIndex index = model()->index(i, 1, rootIndex());
|
||||||
|
QString s = model()->data(index).toString();
|
||||||
max = qMax(max, metrics.boundingRect(s).width());
|
max = qMax(max, metrics.boundingRect(s).width());
|
||||||
}
|
}
|
||||||
return 2 * marginSize() + max;
|
}
|
||||||
|
return 2 * GetMarginSize() + max;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegSexyDisplay::gapHeight() const
|
int RegSexyDisplay2::GetGapHeight() const
|
||||||
{
|
{
|
||||||
return marginSize() / 2;
|
return GetMarginSize() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize RegSexyDisplay::minimumSizeHint() const
|
QRegion RegSexyDisplay2::visualRegionForSelection(const QItemSelection& selection) const
|
||||||
{
|
{
|
||||||
/* cache computation because it's expensive */
|
Q_UNUSED(selection);
|
||||||
if(m_size.isValid())
|
return QRegion();
|
||||||
return m_size;
|
|
||||||
/* width: display 32 columns + 33 vertical separators */
|
|
||||||
m_size.setWidth(32 * columnWidth() + 33 * separatorSize());
|
|
||||||
/* height: one separator + two digits + one separator + margin + separator
|
|
||||||
* + names + separator */
|
|
||||||
m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight());
|
|
||||||
return m_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize RegSexyDisplay::sizeHint() const
|
void RegSexyDisplay2::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
return minimumSizeHint();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegSexyDisplay::paintEvent(QPaintEvent *event)
|
|
||||||
{
|
|
||||||
// FIXME could be optimised with QStaticText
|
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
int txt_h = fontMetrics().height();
|
int txt_h = viewOptions().fontMetrics.height();
|
||||||
int sep_sz = separatorSize();
|
int sep_sz = GetSeparatorSize();
|
||||||
int w = width();
|
int w = qMax(m_minimum_width, viewport()->width());
|
||||||
int h = height() - 1;
|
int h = qMax(m_minimum_height, viewport()->height());
|
||||||
int col_w = (w - 33 * sep_sz) / 32;
|
int nr_bits = 32;
|
||||||
int hdr_h = headerHeight();
|
int col_w = (w - (nr_bits + 1) * sep_sz) / nr_bits;
|
||||||
int gap_h = gapHeight();
|
int hdr_h = GetHeaderHeight();
|
||||||
int tot_w = 33 * sep_sz + 32 * col_w;
|
int gap_h = GetGapHeight();
|
||||||
int margin = marginSize();
|
int tot_w = (nr_bits + 1) * sep_sz + nr_bits * col_w;
|
||||||
int txt_sep = textSep();
|
int margin = GetMarginSize();
|
||||||
|
int txt_sep = GetHeaderTextSep();
|
||||||
int tot_hdr_sz = 2 * sep_sz + hdr_h;
|
int tot_hdr_sz = 2 * sep_sz + hdr_h;
|
||||||
// computer xshift
|
|
||||||
int x_shift = (w - tot_w) / 2;
|
int x_shift = (w - tot_w) / 2;
|
||||||
#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w))
|
#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w))
|
||||||
|
|
||||||
QPainter painter(this);
|
QPainter painter(viewport());
|
||||||
QBrush back_brush = palette().base();
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
||||||
QBrush line_brush = palette().dark();
|
painter.translate(-horizontalScrollBar()->value(), -verticalScrollBar()->value());
|
||||||
|
QStyleOptionViewItem option = viewOptions();
|
||||||
|
QBrush back_brush = option.palette.base();
|
||||||
|
QBrush line_brush = option.palette.dark();
|
||||||
|
|
||||||
// fill interesting zone with base
|
// fill interesting zone with base
|
||||||
|
painter.fillRect(event->rect(), option.palette.window());
|
||||||
painter.fillRect(x_shift, 0, tot_w, h, back_brush);
|
painter.fillRect(x_shift, 0, tot_w, h, back_brush);
|
||||||
|
|
||||||
// draw top and bottom lines
|
// draw top and bottom lines
|
||||||
painter.setPen(QPen(palette().dark(), sep_sz));
|
painter.setPen(QPen(line_brush, sep_sz));
|
||||||
painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush);
|
painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush);
|
||||||
painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush);
|
painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush);
|
||||||
// draw intemediate lines
|
// draw intemediate lines
|
||||||
|
@ -776,23 +850,29 @@ void RegSexyDisplay::paintEvent(QPaintEvent *event)
|
||||||
painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush);
|
painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush);
|
||||||
painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush);
|
painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush);
|
||||||
// redraw some lines but wider
|
// redraw some lines but wider
|
||||||
for(int i = 4; i < 32; i += 4)
|
for(int i = 4; i < nr_bits; i += 4)
|
||||||
painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush);
|
painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush);
|
||||||
// draw numbers in the header
|
// draw numbers in the header
|
||||||
painter.setPen(palette().brush(QPalette::ButtonText).color());
|
painter.setPen(palette().brush(QPalette::ButtonText).color());
|
||||||
for(int i = 0; i < 32; i++)
|
for(int i = 0; i < nr_bits; i++)
|
||||||
{
|
{
|
||||||
QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h);
|
QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h);
|
||||||
painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10));
|
painter.drawText(r, Qt::AlignCenter, QString("%1").arg((nr_bits - 1 - i) / 10));
|
||||||
r.translate(0, txt_h + txt_sep);
|
r.translate(0, txt_h + txt_sep);
|
||||||
painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10));
|
painter.drawText(r, Qt::AlignCenter, QString("%1").arg((nr_bits - 1 - i) % 10));
|
||||||
}
|
}
|
||||||
// display content
|
// display content
|
||||||
for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
|
if(model())
|
||||||
{
|
{
|
||||||
const soc_reg_field_t& field = m_reg.GetReg().field[i];
|
for(int i = 0; i < model()->rowCount(); i++)
|
||||||
QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz),
|
{
|
||||||
QPoint(ith_col_x(32 - field.first_bit), h - sep_sz));
|
QVariant vrange = model()->data(model()->index(i, 0, rootIndex()));
|
||||||
|
if(!vrange.canConvert< SocFieldBitRange >())
|
||||||
|
continue;
|
||||||
|
SocFieldBitRange range = vrange.value< SocFieldBitRange >();
|
||||||
|
QString name = model()->data(model()->index(i, 1, rootIndex())).toString();
|
||||||
|
QRect r(QPoint(ith_col_x(nr_bits - 1 - range.GetLastBit()) + sep_sz, tot_hdr_sz),
|
||||||
|
QPoint(ith_col_x(nr_bits - range.GetFirstBit()), h - sep_sz));
|
||||||
painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush);
|
painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush);
|
||||||
painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush);
|
painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush);
|
||||||
r.setY(r.y() + gap_h + sep_sz);
|
r.setY(r.y() + gap_h + sep_sz);
|
||||||
|
@ -802,12 +882,44 @@ void RegSexyDisplay::paintEvent(QPaintEvent *event)
|
||||||
painter.rotate(-90);
|
painter.rotate(-90);
|
||||||
//painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red));
|
//painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red));
|
||||||
QRect r2(0, 0, r.height(), r.width());
|
QRect r2(0, 0, r.height(), r.width());
|
||||||
painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name));
|
painter.drawText(r2, Qt::AlignCenter, name);
|
||||||
painter.restore();
|
painter.restore();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#undef ith_col_x
|
#undef ith_col_x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::RecomputeGeometry()
|
||||||
|
{
|
||||||
|
if(!m_is_dirty)
|
||||||
|
return;
|
||||||
|
/* height: header + gap + sep + content + sep */
|
||||||
|
m_minimum_height = 0;
|
||||||
|
m_minimum_height += GetHeaderHeight() + GetGapHeight();
|
||||||
|
m_minimum_height += 2 * GetSeparatorSize() + GetMaxContentHeight();
|
||||||
|
/* width: sep + (col + sep) * n */
|
||||||
|
m_minimum_width = GetSeparatorSize() * 33 + GetColumnWidth() * 32;
|
||||||
|
m_is_dirty = false;
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::resizeEvent(QResizeEvent*)
|
||||||
|
{
|
||||||
|
m_is_dirty = true;
|
||||||
|
RecomputeGeometry();
|
||||||
|
updateGeometries();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegSexyDisplay2::updateGeometries()
|
||||||
|
{
|
||||||
|
horizontalScrollBar()->setSingleStep(1);
|
||||||
|
horizontalScrollBar()->setPageStep(viewport()->width());
|
||||||
|
horizontalScrollBar()->setRange(0, qMax(0, m_minimum_width - viewport()->width()));
|
||||||
|
verticalScrollBar()->setSingleStep(1);
|
||||||
|
verticalScrollBar()->setPageStep(viewport()->height());
|
||||||
|
verticalScrollBar()->setRange(0, qMax(0, m_minimum_height - viewport()->height()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GrowingTableView
|
* GrowingTableView
|
||||||
*/
|
*/
|
||||||
|
@ -831,7 +943,6 @@ void GrowingTableView::DataChanged(const QModelIndex& tl, const QModelIndex& br)
|
||||||
{
|
{
|
||||||
Q_UNUSED(tl);
|
Q_UNUSED(tl);
|
||||||
Q_UNUSED(br);
|
Q_UNUSED(br);
|
||||||
resizeRowsToContents();
|
|
||||||
resizeColumnsToContents();
|
resizeColumnsToContents();
|
||||||
int h = contentsMargins().top() + contentsMargins().bottom();
|
int h = contentsMargins().top() + contentsMargins().bottom();
|
||||||
h += horizontalHeader()->height();
|
h += horizontalHeader()->height();
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QScrollBar>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
|
|
||||||
|
@ -292,28 +293,77 @@ protected:
|
||||||
bool m_read_only;
|
bool m_read_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegSexyDisplay : public QWidget
|
class RegSexyDisplay2 : public QAbstractItemView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
RegSexyDisplay(const SocRegRef& reg, QWidget *parent = 0);
|
RegSexyDisplay2(QWidget *parent = 0);
|
||||||
|
virtual QModelIndex indexAt(const QPoint& point) const;
|
||||||
|
virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible);
|
||||||
|
virtual QRect visualRect(const QModelIndex& index ) const;
|
||||||
|
virtual void setModel(QAbstractItemModel *model);
|
||||||
|
|
||||||
QSize minimumSizeHint() const;
|
protected slots:
|
||||||
QSize sizeHint() const;
|
virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
virtual void rowsInserted(const QModelIndex &parent, int start, int end);
|
||||||
|
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
|
||||||
|
virtual void scrollContentsBy(int dx, int dy);
|
||||||
|
virtual void updateGeometries();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int marginSize() const;
|
int GetMarginSize() const; // margin in cells
|
||||||
int separatorSize() const;
|
int GetSeparatorSize() const; // size of lines betweens cells
|
||||||
int columnWidth() const;
|
int GetColumnWidth() const; // width of a 1-bit column (excluding separators)
|
||||||
int headerHeight() const;
|
int GetHeaderHeight() const; // height of the header (excluding separators)
|
||||||
int gapHeight() const;
|
int GetGapHeight() const; // height of gap between header and fields
|
||||||
int maxContentHeight() const;
|
int GetMaxContentHeight() const; // maximum height of field columns
|
||||||
int textSep() const;
|
int GetHeaderTextSep() const; // height between digits in header
|
||||||
void paintEvent(QPaintEvent *event);
|
void RecomputeGeometry();
|
||||||
|
|
||||||
private:
|
virtual bool isIndexHidden(const QModelIndex& index) const;
|
||||||
SocRegRef m_reg;
|
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
|
||||||
mutable QSize m_size;
|
virtual void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags);
|
||||||
|
virtual int verticalOffset() const;
|
||||||
|
virtual int horizontalOffset() const;
|
||||||
|
virtual QRegion visualRegionForSelection(const QItemSelection& selection) const;
|
||||||
|
virtual void paintEvent(QPaintEvent *event);
|
||||||
|
virtual void resizeEvent(QResizeEvent* event);
|
||||||
|
|
||||||
|
bool m_is_dirty;
|
||||||
|
int m_minimum_width, m_minimum_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Qt designers chose to make QAbstractItemView a QAbstractScrollArea, so
|
||||||
|
* that the table scrolls when it doesn't fit. This might be a problem when
|
||||||
|
* one wants to put several tables on top of another, and the whole set into a
|
||||||
|
* big scrollable area, because QAbstractScrollArea provides dummy values as
|
||||||
|
* (minimum) size hints...So the big scroll area has no way of knowing the actual
|
||||||
|
* size of the widget inside and it ends being a scrollable table inside another
|
||||||
|
* scrollable, which is just super weird.
|
||||||
|
* The Unscroll<T> class provides a workaround this behaviour: it expects T
|
||||||
|
* to derive from QAbstractScrollArea and provides correct (minimum) size hints,
|
||||||
|
* based on the value of the scroll bars.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class Unscroll : public T
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Unscroll(QWidget *parent = 0):T(parent) {}
|
||||||
|
virtual QSize sizeHint() const
|
||||||
|
{
|
||||||
|
QScrollBar *hsb = this->horizontalScrollBar();
|
||||||
|
QScrollBar *vsb = this->verticalScrollBar();
|
||||||
|
int w = hsb->maximum() - hsb->minimum() + hsb->pageStep();
|
||||||
|
int h = vsb->maximum() - vsb->minimum() + vsb->pageStep();
|
||||||
|
QMargins m = this->contentsMargins();
|
||||||
|
return QSize(m.left() + w + m.right(), m.top() + h + m.bottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QSize minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return sizeHint();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GrowingTableView : public QTableView
|
class GrowingTableView : public QTableView
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue