diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-10-28 11:19:24 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2015-09-11 16:02:34 +0200 |
commit | c8d3638b9ebc24e4766714da1c9f961e350799c6 (patch) | |
tree | fe9ea6420575091dda63092ea9467a4fa0306a99 /utils/regtools | |
parent | 2c832968c91cb56e4c252bd8eafb03d7d9c8aeda (diff) | |
download | rockbox-c8d3638b9ebc24e4766714da1c9f961e350799c6.tar.gz rockbox-c8d3638b9ebc24e4766714da1c9f961e350799c6.zip |
qeditor: introduce new "sexy register display"
Change-Id: Ib938b4be71d2c7623851dbc3c211f96105077d7d
Diffstat (limited to 'utils/regtools')
-rw-r--r-- | utils/regtools/qeditor/qeditor.pro | 2 | ||||
-rw-r--r-- | utils/regtools/qeditor/regdisplaypanel.cpp | 13 | ||||
-rw-r--r-- | utils/regtools/qeditor/regdisplaypanel.h | 2 | ||||
-rw-r--r-- | utils/regtools/qeditor/regedit.cpp | 54 | ||||
-rw-r--r-- | utils/regtools/qeditor/regedit.h | 6 | ||||
-rw-r--r-- | utils/regtools/qeditor/utils.cpp | 261 | ||||
-rw-r--r-- | utils/regtools/qeditor/utils.h | 82 |
7 files changed, 286 insertions, 134 deletions
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro index 39b6c76cc9..eecc0aba3f 100644 --- a/utils/regtools/qeditor/qeditor.pro +++ b/utils/regtools/qeditor/qeditor.pro | |||
@@ -12,7 +12,7 @@ libsocdesc.commands = cd ../lib && make | |||
12 | QMAKE_EXTRA_TARGETS += libsocdesc | 12 | QMAKE_EXTRA_TARGETS += libsocdesc |
13 | PRE_TARGETDEPS += libsocdesc | 13 | PRE_TARGETDEPS += libsocdesc |
14 | 14 | ||
15 | VERSION = 2.0.3 | 15 | VERSION = 2.0.4 |
16 | 16 | ||
17 | DEFINES += APP_VERSION=\\\"$$VERSION\\\" | 17 | DEFINES += APP_VERSION=\\\"$$VERSION\\\" |
18 | 18 | ||
diff --git a/utils/regtools/qeditor/regdisplaypanel.cpp b/utils/regtools/qeditor/regdisplaypanel.cpp index 3dbdb54241..167c776cce 100644 --- a/utils/regtools/qeditor/regdisplaypanel.cpp +++ b/utils/regtools/qeditor/regdisplaypanel.cpp | |||
@@ -196,7 +196,7 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S | |||
196 | raw_val_layout->addWidget(m_raw_val_edit); | 196 | raw_val_layout->addWidget(m_raw_val_edit); |
197 | raw_val_layout->addStretch(); | 197 | raw_val_layout->addStretch(); |
198 | 198 | ||
199 | m_value_table = new GrowingTableView; | 199 | m_value_table = new GrowingTableView(); |
200 | m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership | 200 | m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership |
201 | m_value_model->SetRegister(m_reg.GetReg()); | 201 | m_value_model->SetRegister(m_reg.GetReg()); |
202 | m_value_model->SetReadOnly(read_only); | 202 | m_value_model->SetReadOnly(read_only); |
@@ -208,7 +208,7 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S | |||
208 | // FIXME we cannot use setAlternatingRowColors() because we override the | 208 | // FIXME we cannot use setAlternatingRowColors() because we override the |
209 | // background color, should it be part of the model ? | 209 | // background color, should it be part of the model ? |
210 | 210 | ||
211 | SocFieldCachedItemDelegate *m_table_delegate = new SocFieldCachedItemDelegate(this); | 211 | m_table_delegate = new SocFieldCachedItemDelegate(this); |
212 | m_table_edit_factory = new QItemEditorFactory(); | 212 | m_table_edit_factory = new QItemEditorFactory(); |
213 | SocFieldCachedEditorCreator *m_table_edit_creator = new SocFieldCachedEditorCreator(); | 213 | SocFieldCachedEditorCreator *m_table_edit_creator = new SocFieldCachedEditorCreator(); |
214 | // FIXME see QTBUG-30392 | 214 | // FIXME see QTBUG-30392 |
@@ -217,8 +217,10 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S | |||
217 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); | 217 | m_table_delegate->setItemEditorFactory(m_table_edit_factory); |
218 | m_value_table->setItemDelegate(m_table_delegate); | 218 | m_value_table->setItemDelegate(m_table_delegate); |
219 | 219 | ||
220 | m_sexy_display = new RegSexyDisplay(reg_ref, this); | 220 | m_sexy_display2 = new Unscroll<RegSexyDisplay2>(this); |
221 | m_sexy_display->setFont(m_reg_font); | 221 | m_sexy_display2->setFont(m_reg_font); |
222 | m_sexy_display2->setModel(m_value_model); | ||
223 | m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
222 | 224 | ||
223 | m_desc = new QLabel(this); | 225 | m_desc = new QLabel(this); |
224 | m_desc->setTextFormat(Qt::RichText); | 226 | m_desc->setTextFormat(Qt::RichText); |
@@ -228,8 +230,9 @@ RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const S | |||
228 | right_layout->addLayout(top_layout); | 230 | right_layout->addLayout(top_layout); |
229 | if(raw_val_layout) | 231 | if(raw_val_layout) |
230 | right_layout->addLayout(raw_val_layout); | 232 | right_layout->addLayout(raw_val_layout); |
231 | right_layout->addWidget(m_sexy_display); | 233 | right_layout->addWidget(m_sexy_display2); |
232 | right_layout->addWidget(m_value_table); | 234 | right_layout->addWidget(m_value_table); |
235 | right_layout->addStretch(); | ||
233 | 236 | ||
234 | setTitle("Register Description"); | 237 | setTitle("Register Description"); |
235 | m_viewport = new QWidget; | 238 | m_viewport = new QWidget; |
diff --git a/utils/regtools/qeditor/regdisplaypanel.h b/utils/regtools/qeditor/regdisplaypanel.h index 313fc7e369..9a692778fe 100644 --- a/utils/regtools/qeditor/regdisplaypanel.h +++ b/utils/regtools/qeditor/regdisplaypanel.h | |||
@@ -105,7 +105,7 @@ protected: | |||
105 | const SocRegRef& m_reg; | 105 | const SocRegRef& m_reg; |
106 | bool m_allow_write; | 106 | bool m_allow_write; |
107 | RegLineEdit *m_raw_val_edit; | 107 | RegLineEdit *m_raw_val_edit; |
108 | RegSexyDisplay *m_sexy_display; | 108 | Unscroll< RegSexyDisplay2 > *m_sexy_display2; |
109 | GrowingTableView *m_value_table; | 109 | GrowingTableView *m_value_table; |
110 | RegFieldTableModel *m_value_model; | 110 | RegFieldTableModel *m_value_model; |
111 | QStyledItemDelegate *m_table_delegate; | 111 | QStyledItemDelegate *m_table_delegate; |
diff --git a/utils/regtools/qeditor/regedit.cpp b/utils/regtools/qeditor/regedit.cpp index 9dca6280e0..851e054eb0 100644 --- a/utils/regtools/qeditor/regedit.cpp +++ b/utils/regtools/qeditor/regedit.cpp | |||
@@ -336,47 +336,33 @@ RegEditPanel::RegEditPanel(SocRegRef ref, QWidget *parent) | |||
336 | top_layout->addLayout(name_layout); | 336 | top_layout->addLayout(name_layout); |
337 | top_layout->addWidget(m_desc_group, 1); | 337 | top_layout->addWidget(m_desc_group, 1); |
338 | 338 | ||
339 | m_sexy_display = new RegSexyDisplay(m_ref, this); | 339 | m_value_table = new QTableView(this); |
340 | m_sexy_display->setFont(m_reg_font); | 340 | m_value_model = new RegFieldTableModel(m_value_table); // view takes ownership |
341 | m_value_model->SetRegister(m_ref.GetReg()); | ||
342 | m_value_model->SetReadOnly(true); | ||
343 | m_value_table->setModel(m_value_model); | ||
344 | m_value_table->verticalHeader()->setVisible(false); | ||
345 | m_value_table->horizontalHeader()->setStretchLastSection(true); | ||
346 | m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
347 | // FIXME we cannot use setAlternatingRowColors() because we override the | ||
348 | // background color, should it be part of the model ? | ||
349 | m_table_delegate = new SocFieldCachedItemDelegate(this); | ||
350 | m_value_table->setItemDelegate(m_table_delegate); | ||
351 | m_value_table->resizeColumnsToContents(); | ||
352 | |||
353 | m_sexy_display2 = new Unscroll<RegSexyDisplay2>(this); | ||
354 | m_sexy_display2->setFont(m_reg_font); | ||
355 | m_sexy_display2->setModel(m_value_model); | ||
356 | m_sexy_display2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | ||
341 | 357 | ||
342 | m_field_table = new QTableWidget; | ||
343 | m_field_table->setRowCount(m_ref.GetReg().field.size()); | ||
344 | m_field_table->setColumnCount(4); | ||
345 | for(size_t row = 0; row < m_ref.GetReg().field.size(); row++) | ||
346 | { | ||
347 | const soc_reg_field_t& field = m_ref.GetReg().field[row]; | ||
348 | QString bits_str; | ||
349 | if(field.first_bit == field.last_bit) | ||
350 | bits_str.sprintf("%d", field.first_bit); | ||
351 | else | ||
352 | bits_str.sprintf("%d:%d", field.last_bit, field.first_bit); | ||
353 | QTableWidgetItem *item = new QTableWidgetItem(bits_str); | ||
354 | item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter); | ||
355 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
356 | m_field_table->setItem(row, 1, item); | ||
357 | item = new QTableWidgetItem(QString(field.name.c_str())); | ||
358 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
359 | m_field_table->setItem(row, 2, item); | ||
360 | item = new QTableWidgetItem(QString(field.desc.c_str())); | ||
361 | item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); | ||
362 | m_field_table->setItem(row, 3, item); | ||
363 | UpdateWarning(row); | ||
364 | } | ||
365 | m_field_table->setHorizontalHeaderItem(0, new QTableWidgetItem("")); | ||
366 | m_field_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Bits")); | ||
367 | m_field_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); | ||
368 | m_field_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Description")); | ||
369 | m_field_table->verticalHeader()->setVisible(false); | ||
370 | m_field_table->resizeColumnsToContents(); | ||
371 | m_field_table->horizontalHeader()->setStretchLastSection(true); | ||
372 | QHBoxLayout *field_layout = new QHBoxLayout; | 358 | QHBoxLayout *field_layout = new QHBoxLayout; |
373 | field_layout->addWidget(m_field_table); | 359 | field_layout->addWidget(m_value_table); |
374 | m_field_group = new QGroupBox("Flags", this); | 360 | m_field_group = new QGroupBox("Flags", this); |
375 | m_field_group->setLayout(field_layout); | 361 | m_field_group->setLayout(field_layout); |
376 | 362 | ||
377 | QVBoxLayout *layout = new QVBoxLayout; | 363 | QVBoxLayout *layout = new QVBoxLayout; |
378 | layout->addLayout(top_layout, 0); | 364 | layout->addLayout(top_layout, 0); |
379 | layout->addWidget(m_sexy_display, 0); | 365 | layout->addWidget(m_sexy_display2, 0); |
380 | layout->addWidget(m_field_group); | 366 | layout->addWidget(m_field_group); |
381 | 367 | ||
382 | UpdateFormula(); | 368 | UpdateFormula(); |
diff --git a/utils/regtools/qeditor/regedit.h b/utils/regtools/qeditor/regedit.h index 96c4875833..c56f0d9026 100644 --- a/utils/regtools/qeditor/regedit.h +++ b/utils/regtools/qeditor/regedit.h | |||
@@ -185,10 +185,12 @@ protected: | |||
185 | QComboBox *m_formula_combo; | 185 | QComboBox *m_formula_combo; |
186 | QLineEdit *m_formula_string_edit; | 186 | QLineEdit *m_formula_string_edit; |
187 | QPushButton *m_formula_string_gen; | 187 | QPushButton *m_formula_string_gen; |
188 | RegSexyDisplay *m_sexy_display; | 188 | Unscroll< RegSexyDisplay2 > *m_sexy_display2; |
189 | MyTextEditor *m_desc_edit; | 189 | MyTextEditor *m_desc_edit; |
190 | QGroupBox *m_field_group; | 190 | QGroupBox *m_field_group; |
191 | QTableWidget *m_field_table; | 191 | QTableView *m_value_table; |
192 | RegFieldTableModel *m_value_model; | ||
193 | QStyledItemDelegate *m_table_delegate; | ||
192 | }; | 194 | }; |
193 | 195 | ||
194 | class FieldEditPanel : public QWidget, public AbstractRegEditPanel | 196 | class FieldEditPanel : public QWidget, public AbstractRegEditPanel |
diff --git a/utils/regtools/qeditor/utils.cpp b/utils/regtools/qeditor/utils.cpp index 4116dbcc81..e4a872ed49 100644 --- a/utils/regtools/qeditor/utils.cpp +++ b/utils/regtools/qeditor/utils.cpp | |||
@@ -669,104 +669,178 @@ void RegFieldTableModel::RecomputeTheme() | |||
669 | } | 669 | } |
670 | 670 | ||
671 | /** | 671 | /** |
672 | * RegSexyDisplay | 672 | * RegSexyDisplay2 |
673 | */ | 673 | */ |
674 | RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent) | 674 | |
675 | :QWidget(parent), m_reg(reg) | 675 | RegSexyDisplay2::RegSexyDisplay2(QWidget *parent) |
676 | :QAbstractItemView(parent) | ||
677 | { | ||
678 | m_is_dirty = true; | ||
679 | // the frame around the register is ugly, disable it | ||
680 | setFrameShape(QFrame::NoFrame); | ||
681 | } | ||
682 | |||
683 | QModelIndex RegSexyDisplay2::indexAt(const QPoint& point) const | ||
684 | { | ||
685 | Q_UNUSED(point); | ||
686 | return QModelIndex(); | ||
687 | } | ||
688 | |||
689 | void RegSexyDisplay2::scrollTo(const QModelIndex& index, ScrollHint hint) | ||
690 | { | ||
691 | Q_UNUSED(index); | ||
692 | Q_UNUSED(hint); | ||
693 | } | ||
694 | |||
695 | QRect RegSexyDisplay2::visualRect(const QModelIndex& index) const | ||
696 | { | ||
697 | Q_UNUSED(index); | ||
698 | return QRect(); | ||
699 | } | ||
700 | |||
701 | bool RegSexyDisplay2::isIndexHidden(const QModelIndex& index) const | ||
702 | { | ||
703 | Q_UNUSED(index); | ||
704 | return false; | ||
705 | } | ||
706 | |||
707 | QModelIndex RegSexyDisplay2::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) | ||
708 | { | ||
709 | Q_UNUSED(cursorAction); | ||
710 | Q_UNUSED(modifiers); | ||
711 | return QModelIndex(); | ||
712 | } | ||
713 | |||
714 | void RegSexyDisplay2::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) | ||
715 | { | ||
716 | Q_UNUSED(rect); | ||
717 | Q_UNUSED(flags); | ||
718 | } | ||
719 | |||
720 | int RegSexyDisplay2::verticalOffset() const | ||
721 | { | ||
722 | return verticalScrollBar()->value(); | ||
723 | } | ||
724 | |||
725 | int RegSexyDisplay2::horizontalOffset() const | ||
726 | { | ||
727 | return horizontalScrollBar()->value(); | ||
728 | } | ||
729 | |||
730 | void RegSexyDisplay2::scrollContentsBy(int dx, int dy) | ||
731 | { | ||
732 | viewport()->scroll(dx, dy); | ||
733 | } | ||
734 | |||
735 | void RegSexyDisplay2::setModel(QAbstractItemModel *model) | ||
676 | { | 736 | { |
677 | m_size = QSize(); | 737 | QAbstractItemView::setModel(model); |
738 | m_is_dirty = true; | ||
678 | } | 739 | } |
679 | 740 | ||
680 | int RegSexyDisplay::separatorSize() const | 741 | void RegSexyDisplay2::dataChanged(const QModelIndex &topLeft, |
742 | const QModelIndex &bottomRight) | ||
743 | { | ||
744 | m_is_dirty = true; | ||
745 | QAbstractItemView::dataChanged(topLeft, bottomRight); | ||
746 | } | ||
747 | |||
748 | void RegSexyDisplay2::rowsInserted(const QModelIndex &parent, int start, int end) | ||
749 | { | ||
750 | m_is_dirty = true; | ||
751 | QAbstractItemView::rowsInserted(parent, start, end); | ||
752 | } | ||
753 | |||
754 | void RegSexyDisplay2::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) | ||
755 | { | ||
756 | m_is_dirty = true; | ||
757 | QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); | ||
758 | } | ||
759 | |||
760 | int RegSexyDisplay2::GetSeparatorSize() const | ||
681 | { | 761 | { |
682 | return 1; | 762 | return 1; |
683 | } | 763 | } |
684 | 764 | ||
685 | int RegSexyDisplay::marginSize() const | 765 | int RegSexyDisplay2::GetMarginSize() const |
686 | { | 766 | { |
687 | return fontMetrics().height() / 3; | 767 | return viewOptions().fontMetrics.height() / 3; |
688 | } | 768 | } |
689 | 769 | ||
690 | int RegSexyDisplay::textSep() const | 770 | int RegSexyDisplay2::GetHeaderTextSep() const |
691 | { | 771 | { |
692 | return marginSize() / 2; | 772 | return GetMarginSize() / 2; |
693 | } | 773 | } |
694 | 774 | ||
695 | int RegSexyDisplay::headerHeight() const | 775 | int RegSexyDisplay2::GetHeaderHeight() const |
696 | { | 776 | { |
697 | return 2 * marginSize() + textSep() + 2 * fontMetrics().height(); | 777 | return 2 * GetMarginSize() + GetHeaderTextSep() + 2 * viewOptions().fontMetrics.height(); |
698 | } | 778 | } |
699 | 779 | ||
700 | int RegSexyDisplay::columnWidth() const | 780 | int RegSexyDisplay2::GetColumnWidth() const |
701 | { | 781 | { |
702 | return 2 * marginSize() + fontMetrics().height(); | 782 | return 2 * GetMarginSize() + viewOptions().fontMetrics.height(); |
703 | } | 783 | } |
704 | 784 | ||
705 | int RegSexyDisplay::maxContentHeight() const | 785 | int RegSexyDisplay2::GetMaxContentHeight() const |
706 | { | 786 | { |
707 | int max = 0; | 787 | int max = 0; |
708 | QFontMetrics metrics = fontMetrics(); | 788 | QFontMetrics metrics = viewOptions().fontMetrics; |
709 | for(size_t i = 0; i < m_reg.GetReg().field.size(); i++) | 789 | if(model()) |
710 | { | 790 | { |
711 | QString s = QString::fromStdString(m_reg.GetReg().field[i].name); | 791 | for(int i = 0; i < model()->rowCount(); i++) |
712 | // add extra spaces arounds | 792 | { |
713 | s = " " + s + " "; | 793 | QModelIndex index = model()->index(i, 1, rootIndex()); |
714 | max = qMax(max, metrics.boundingRect(s).width()); | 794 | QString s = model()->data(index).toString(); |
795 | max = qMax(max, metrics.boundingRect(s).width()); | ||
796 | } | ||
715 | } | 797 | } |
716 | return 2 * marginSize() + max; | 798 | return 2 * GetMarginSize() + max; |
717 | } | ||
718 | |||
719 | int RegSexyDisplay::gapHeight() const | ||
720 | { | ||
721 | return marginSize() / 2; | ||
722 | } | 799 | } |
723 | 800 | ||
724 | QSize RegSexyDisplay::minimumSizeHint() const | 801 | int RegSexyDisplay2::GetGapHeight() const |
725 | { | 802 | { |
726 | /* cache computation because it's expensive */ | 803 | return GetMarginSize() / 2; |
727 | if(m_size.isValid()) | ||
728 | return m_size; | ||
729 | /* width: display 32 columns + 33 vertical separators */ | ||
730 | m_size.setWidth(32 * columnWidth() + 33 * separatorSize()); | ||
731 | /* height: one separator + two digits + one separator + margin + separator | ||
732 | * + names + separator */ | ||
733 | m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight()); | ||
734 | return m_size; | ||
735 | } | 804 | } |
736 | 805 | ||
737 | QSize RegSexyDisplay::sizeHint() const | 806 | QRegion RegSexyDisplay2::visualRegionForSelection(const QItemSelection& selection) const |
738 | { | 807 | { |
739 | return minimumSizeHint(); | 808 | Q_UNUSED(selection); |
809 | return QRegion(); | ||
740 | } | 810 | } |
741 | 811 | ||
742 | void RegSexyDisplay::paintEvent(QPaintEvent *event) | 812 | void RegSexyDisplay2::paintEvent(QPaintEvent *event) |
743 | { | 813 | { |
744 | // FIXME could be optimised with QStaticText | ||
745 | Q_UNUSED(event); | 814 | Q_UNUSED(event); |
746 | int txt_h = fontMetrics().height(); | 815 | int txt_h = viewOptions().fontMetrics.height(); |
747 | int sep_sz = separatorSize(); | 816 | int sep_sz = GetSeparatorSize(); |
748 | int w = width(); | 817 | int w = qMax(m_minimum_width, viewport()->width()); |
749 | int h = height() - 1; | 818 | int h = qMax(m_minimum_height, viewport()->height()); |
750 | int col_w = (w - 33 * sep_sz) / 32; | 819 | int nr_bits = 32; |
751 | int hdr_h = headerHeight(); | 820 | int col_w = (w - (nr_bits + 1) * sep_sz) / nr_bits; |
752 | int gap_h = gapHeight(); | 821 | int hdr_h = GetHeaderHeight(); |
753 | int tot_w = 33 * sep_sz + 32 * col_w; | 822 | int gap_h = GetGapHeight(); |
754 | int margin = marginSize(); | 823 | int tot_w = (nr_bits + 1) * sep_sz + nr_bits * col_w; |
755 | int txt_sep = textSep(); | 824 | int margin = GetMarginSize(); |
825 | int txt_sep = GetHeaderTextSep(); | ||
756 | int tot_hdr_sz = 2 * sep_sz + hdr_h; | 826 | int tot_hdr_sz = 2 * sep_sz + hdr_h; |
757 | // computer xshift | 827 | |
758 | int x_shift = (w - tot_w) / 2; | 828 | int x_shift = (w - tot_w) / 2; |
759 | #define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w)) | 829 | #define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w)) |
760 | 830 | ||
761 | QPainter painter(this); | 831 | QPainter painter(viewport()); |
762 | QBrush back_brush = palette().base(); | 832 | painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); |
763 | QBrush line_brush = palette().dark(); | 833 | painter.translate(-horizontalScrollBar()->value(), -verticalScrollBar()->value()); |
834 | QStyleOptionViewItem option = viewOptions(); | ||
835 | QBrush back_brush = option.palette.base(); | ||
836 | QBrush line_brush = option.palette.dark(); | ||
764 | 837 | ||
765 | // fill interesting zone with base | 838 | // fill interesting zone with base |
839 | painter.fillRect(event->rect(), option.palette.window()); | ||
766 | painter.fillRect(x_shift, 0, tot_w, h, back_brush); | 840 | painter.fillRect(x_shift, 0, tot_w, h, back_brush); |
767 | 841 | ||
768 | // draw top and bottom lines | 842 | // draw top and bottom lines |
769 | painter.setPen(QPen(palette().dark(), sep_sz)); | 843 | painter.setPen(QPen(line_brush, sep_sz)); |
770 | painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush); | 844 | painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush); |
771 | painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush); | 845 | painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush); |
772 | // draw intemediate lines | 846 | // draw intemediate lines |
@@ -776,38 +850,76 @@ void RegSexyDisplay::paintEvent(QPaintEvent *event) | |||
776 | painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush); | 850 | painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush); |
777 | painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush); | 851 | painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush); |
778 | // redraw some lines but wider | 852 | // redraw some lines but wider |
779 | for(int i = 4; i < 32; i += 4) | 853 | for(int i = 4; i < nr_bits; i += 4) |
780 | painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush); | 854 | painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush); |
781 | // draw numbers in the header | 855 | // draw numbers in the header |
782 | painter.setPen(palette().brush(QPalette::ButtonText).color()); | 856 | painter.setPen(palette().brush(QPalette::ButtonText).color()); |
783 | for(int i = 0; i < 32; i++) | 857 | for(int i = 0; i < nr_bits; i++) |
784 | { | 858 | { |
785 | QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h); | 859 | QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h); |
786 | painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10)); | 860 | painter.drawText(r, Qt::AlignCenter, QString("%1").arg((nr_bits - 1 - i) / 10)); |
787 | r.translate(0, txt_h + txt_sep); | 861 | r.translate(0, txt_h + txt_sep); |
788 | painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10)); | 862 | painter.drawText(r, Qt::AlignCenter, QString("%1").arg((nr_bits - 1 - i) % 10)); |
789 | } | 863 | } |
790 | // display content | 864 | // display content |
791 | for(size_t i = 0; i < m_reg.GetReg().field.size(); i++) | 865 | if(model()) |
792 | { | 866 | { |
793 | const soc_reg_field_t& field = m_reg.GetReg().field[i]; | 867 | for(int i = 0; i < model()->rowCount(); i++) |
794 | QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz), | 868 | { |
795 | QPoint(ith_col_x(32 - field.first_bit), h - sep_sz)); | 869 | QVariant vrange = model()->data(model()->index(i, 0, rootIndex())); |
796 | painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush); | 870 | if(!vrange.canConvert< SocFieldBitRange >()) |
797 | painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush); | 871 | continue; |
798 | r.setY(r.y() + gap_h + sep_sz); | 872 | SocFieldBitRange range = vrange.value< SocFieldBitRange >(); |
799 | // draw rotated text | 873 | QString name = model()->data(model()->index(i, 1, rootIndex())).toString(); |
800 | painter.save(); | 874 | QRect r(QPoint(ith_col_x(nr_bits - 1 - range.GetLastBit()) + sep_sz, tot_hdr_sz), |
801 | painter.translate(r.bottomLeft()); | 875 | QPoint(ith_col_x(nr_bits - range.GetFirstBit()), h - sep_sz)); |
802 | painter.rotate(-90); | 876 | painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush); |
803 | //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red)); | 877 | painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush); |
804 | QRect r2(0, 0, r.height(), r.width()); | 878 | r.setY(r.y() + gap_h + sep_sz); |
805 | painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name)); | 879 | // draw rotated text |
806 | painter.restore(); | 880 | painter.save(); |
881 | painter.translate(r.bottomLeft()); | ||
882 | painter.rotate(-90); | ||
883 | //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red)); | ||
884 | QRect r2(0, 0, r.height(), r.width()); | ||
885 | painter.drawText(r2, Qt::AlignCenter, name); | ||
886 | painter.restore(); | ||
887 | } | ||
807 | } | 888 | } |
808 | #undef ith_col_x | 889 | #undef ith_col_x |
809 | } | 890 | } |
810 | 891 | ||
892 | void RegSexyDisplay2::RecomputeGeometry() | ||
893 | { | ||
894 | if(!m_is_dirty) | ||
895 | return; | ||
896 | /* height: header + gap + sep + content + sep */ | ||
897 | m_minimum_height = 0; | ||
898 | m_minimum_height += GetHeaderHeight() + GetGapHeight(); | ||
899 | m_minimum_height += 2 * GetSeparatorSize() + GetMaxContentHeight(); | ||
900 | /* width: sep + (col + sep) * n */ | ||
901 | m_minimum_width = GetSeparatorSize() * 33 + GetColumnWidth() * 32; | ||
902 | m_is_dirty = false; | ||
903 | viewport()->update(); | ||
904 | } | ||
905 | |||
906 | void RegSexyDisplay2::resizeEvent(QResizeEvent*) | ||
907 | { | ||
908 | m_is_dirty = true; | ||
909 | RecomputeGeometry(); | ||
910 | updateGeometries(); | ||
911 | } | ||
912 | |||
913 | void RegSexyDisplay2::updateGeometries() | ||
914 | { | ||
915 | horizontalScrollBar()->setSingleStep(1); | ||
916 | horizontalScrollBar()->setPageStep(viewport()->width()); | ||
917 | horizontalScrollBar()->setRange(0, qMax(0, m_minimum_width - viewport()->width())); | ||
918 | verticalScrollBar()->setSingleStep(1); | ||
919 | verticalScrollBar()->setPageStep(viewport()->height()); | ||
920 | verticalScrollBar()->setRange(0, qMax(0, m_minimum_height - viewport()->height())); | ||
921 | } | ||
922 | |||
811 | /** | 923 | /** |
812 | * GrowingTableView | 924 | * GrowingTableView |
813 | */ | 925 | */ |
@@ -831,7 +943,6 @@ void GrowingTableView::DataChanged(const QModelIndex& tl, const QModelIndex& br) | |||
831 | { | 943 | { |
832 | Q_UNUSED(tl); | 944 | Q_UNUSED(tl); |
833 | Q_UNUSED(br); | 945 | Q_UNUSED(br); |
834 | resizeRowsToContents(); | ||
835 | resizeColumnsToContents(); | 946 | resizeColumnsToContents(); |
836 | int h = contentsMargins().top() + contentsMargins().bottom(); | 947 | int h = contentsMargins().top() + contentsMargins().bottom(); |
837 | h += horizontalHeader()->height(); | 948 | h += horizontalHeader()->height(); |
diff --git a/utils/regtools/qeditor/utils.h b/utils/regtools/qeditor/utils.h index c78b0a40e4..078f3a85d7 100644 --- a/utils/regtools/qeditor/utils.h +++ b/utils/regtools/qeditor/utils.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <QStyledItemDelegate> | 37 | #include <QStyledItemDelegate> |
38 | #include <QComboBox> | 38 | #include <QComboBox> |
39 | #include <QFileDialog> | 39 | #include <QFileDialog> |
40 | #include <QScrollBar> | ||
40 | #include "settings.h" | 41 | #include "settings.h" |
41 | #include "backend.h" | 42 | #include "backend.h" |
42 | 43 | ||
@@ -292,28 +293,77 @@ protected: | |||
292 | bool m_read_only; | 293 | bool m_read_only; |
293 | }; | 294 | }; |
294 | 295 | ||
295 | class RegSexyDisplay : public QWidget | 296 | class RegSexyDisplay2 : public QAbstractItemView |
296 | { | 297 | { |
297 | Q_OBJECT | 298 | Q_OBJECT |
298 | public: | 299 | public: |
299 | RegSexyDisplay(const SocRegRef& reg, QWidget *parent = 0); | 300 | RegSexyDisplay2(QWidget *parent = 0); |
301 | virtual QModelIndex indexAt(const QPoint& point) const; | ||
302 | virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible); | ||
303 | virtual QRect visualRect(const QModelIndex& index ) const; | ||
304 | virtual void setModel(QAbstractItemModel *model); | ||
300 | 305 | ||
301 | QSize minimumSizeHint() const; | 306 | protected slots: |
302 | QSize sizeHint() const; | 307 | virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); |
308 | virtual void rowsInserted(const QModelIndex &parent, int start, int end); | ||
309 | virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); | ||
310 | virtual void scrollContentsBy(int dx, int dy); | ||
311 | virtual void updateGeometries(); | ||
303 | 312 | ||
304 | protected: | 313 | protected: |
305 | int marginSize() const; | 314 | int GetMarginSize() const; // margin in cells |
306 | int separatorSize() const; | 315 | int GetSeparatorSize() const; // size of lines betweens cells |
307 | int columnWidth() const; | 316 | int GetColumnWidth() const; // width of a 1-bit column (excluding separators) |
308 | int headerHeight() const; | 317 | int GetHeaderHeight() const; // height of the header (excluding separators) |
309 | int gapHeight() const; | 318 | int GetGapHeight() const; // height of gap between header and fields |
310 | int maxContentHeight() const; | 319 | int GetMaxContentHeight() const; // maximum height of field columns |
311 | int textSep() const; | 320 | int GetHeaderTextSep() const; // height between digits in header |
312 | void paintEvent(QPaintEvent *event); | 321 | void RecomputeGeometry(); |
313 | 322 | ||
314 | private: | 323 | virtual bool isIndexHidden(const QModelIndex& index) const; |
315 | SocRegRef m_reg; | 324 | virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); |
316 | mutable QSize m_size; | 325 | virtual void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags); |
326 | virtual int verticalOffset() const; | ||
327 | virtual int horizontalOffset() const; | ||
328 | virtual QRegion visualRegionForSelection(const QItemSelection& selection) const; | ||
329 | virtual void paintEvent(QPaintEvent *event); | ||
330 | virtual void resizeEvent(QResizeEvent* event); | ||
331 | |||
332 | bool m_is_dirty; | ||
333 | int m_minimum_width, m_minimum_height; | ||
334 | }; | ||
335 | |||
336 | /** | ||
337 | * The Qt designers chose to make QAbstractItemView a QAbstractScrollArea, so | ||
338 | * that the table scrolls when it doesn't fit. This might be a problem when | ||
339 | * one wants to put several tables on top of another, and the whole set into a | ||
340 | * big scrollable area, because QAbstractScrollArea provides dummy values as | ||
341 | * (minimum) size hints...So the big scroll area has no way of knowing the actual | ||
342 | * size of the widget inside and it ends being a scrollable table inside another | ||
343 | * scrollable, which is just super weird. | ||
344 | * The Unscroll<T> class provides a workaround this behaviour: it expects T | ||
345 | * to derive from QAbstractScrollArea and provides correct (minimum) size hints, | ||
346 | * based on the value of the scroll bars. | ||
347 | */ | ||
348 | template<typename T> | ||
349 | class Unscroll : public T | ||
350 | { | ||
351 | public: | ||
352 | Unscroll(QWidget *parent = 0):T(parent) {} | ||
353 | virtual QSize sizeHint() const | ||
354 | { | ||
355 | QScrollBar *hsb = this->horizontalScrollBar(); | ||
356 | QScrollBar *vsb = this->verticalScrollBar(); | ||
357 | int w = hsb->maximum() - hsb->minimum() + hsb->pageStep(); | ||
358 | int h = vsb->maximum() - vsb->minimum() + vsb->pageStep(); | ||
359 | QMargins m = this->contentsMargins(); | ||
360 | return QSize(m.left() + w + m.right(), m.top() + h + m.bottom()); | ||
361 | } | ||
362 | |||
363 | virtual QSize minimumSizeHint() const | ||
364 | { | ||
365 | return sizeHint(); | ||
366 | } | ||
317 | }; | 367 | }; |
318 | 368 | ||
319 | class GrowingTableView : public QTableView | 369 | class GrowingTableView : public QTableView |