Skip to content

Commit

Permalink
Implement proportional column resizing for SideStakeTableView
Browse files Browse the repository at this point in the history
This is based on the same approach used for the AddressBook.
  • Loading branch information
jamescowens committed Oct 14, 2023
1 parent 65f1d88 commit 93f0167
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 11 deletions.
132 changes: 125 additions & 7 deletions src/qt/optionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "miner.h"
#include "sidestaketablemodel.h"
#include "editsidestakedialog.h"
#include "logging.h"

#include <QSortFilterProxyModel>
#include <QDir>
Expand All @@ -26,6 +27,8 @@ OptionsDialog::OptionsDialog(QWidget* parent)
, fRestartWarningDisplayed_Proxy(false)
, fRestartWarningDisplayed_Lang(false)
, fProxyIpValid(true)
, m_init_column_sizes_set(false)
, m_resize_columns_in_progress(false)
{
ui->setupUi(this);

Expand Down Expand Up @@ -159,11 +162,25 @@ void OptionsDialog::setModel(OptionsModel *model)
ui->sidestakingTableView->setColumnWidth(SideStakeTableModel::Allocation, GRC::ScalePx(this, ALLOCATION_COLUMN_WIDTH));
ui->sidestakingTableView->setColumnWidth(SideStakeTableModel::Description, GRC::ScalePx(this, DESCRIPTION_COLUMN_WIDTH));
ui->sidestakingTableView->setColumnWidth(SideStakeTableModel::Status, GRC::ScalePx(this, STATUS_COLUMN_WIDTH));
ui->sidestakingTableView->horizontalHeader()->setStretchLastSection(true);
ui->sidestakingTableView->setShowGrid(true);

// Set table column sizes vector for sidestake table proportional resize algorithm.
m_table_column_sizes = {GRC::ScalePx(this, ADDRESS_COLUMN_WIDTH),
GRC::ScalePx(this, ALLOCATION_COLUMN_WIDTH),
GRC::ScalePx(this, DESCRIPTION_COLUMN_WIDTH),
GRC::ScalePx(this, STATUS_COLUMN_WIDTH)};

ui->sidestakingTableView->sortByColumn(0, Qt::AscendingOrder);

// Insures initial size of sidestake table and (header) columns are correct as of the context directly
// after tab selection.
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &OptionsDialog::tabWidgetSelectionChanged);

// Insures that header width remains constant and columns are resized correctly when a column delimiter is
// dragged to resize one column.
connect(ui->sidestakingTableView->horizontalHeader(), &QHeaderView::sectionResized,
this, &OptionsDialog::sidestakeTableSectionResized);

connect(ui->enableSideStaking, &QCheckBox::toggled, this, &OptionsDialog::hideSideStakeEdit);
connect(ui->enableSideStaking, &QCheckBox::toggled, this, &OptionsDialog::refreshSideStakeTableModel);

Expand Down Expand Up @@ -543,13 +560,8 @@ bool OptionsDialog::eventFilter(QObject *object, QEvent *event)
}

// This is required to provide immediate feedback on invalid allocation entries on in place editing.
if (object == ui->sidestakingTableView)
{
if (object == ui->sidestakingTableView) {
if (model->getSideStakeTableModel()->getEditStatus() == SideStakeTableModel::INVALID_ALLOCATION) {
LogPrint(BCLog::LogFlags::VERBOSE, "INFO %s: event type = %i",
__func__,
(int) event->type());

emit sidestakeAllocationInvalid();
}
}
Expand Down Expand Up @@ -593,3 +605,109 @@ void OptionsDialog::updateSideStakeTableView()
{
ui->sidestakingTableView->update();
}

void OptionsDialog::resizeSideStakeTableColumns(const bool& neighbor_pair_adjust, const int& index,
const int& old_size, const int& new_size)
{
// This prevents unwanted recursion to here from addressBookSectionResized.
m_resize_columns_in_progress = true;

if (!model) {
m_resize_columns_in_progress = false;

return;
}

if (!m_init_column_sizes_set) {
for (int i = 0; i < (int) m_table_column_sizes.size(); ++i) {
ui->sidestakingTableView->horizontalHeader()->resizeSection(i, m_table_column_sizes[i]);


LogPrint(BCLog::LogFlags::VERBOSE, "INFO: %s: section size = %i",
__func__,
ui->sidestakingTableView->horizontalHeader()->sectionSize(i));
}

LogPrint(BCLog::LogFlags::VERBOSE, "INFO: %s: header width = %i",
__func__,
ui->sidestakingTableView->horizontalHeader()->width()
);

m_init_column_sizes_set = true;
m_resize_columns_in_progress = false;

return;
}

if (neighbor_pair_adjust) {
if (index != SideStakeTableModel::all_ColumnIndex.size() - 1) {
int new_neighbor_section_size = ui->sidestakingTableView->horizontalHeader()->sectionSize(index + 1)
+ old_size - new_size;

ui->sidestakingTableView->horizontalHeader()->resizeSection(
index + 1, new_neighbor_section_size);

// This detects and deals with the case where the resize of a column tries to force the neighbor
// to a size below its minimum, in which case we have to reverse out the attempt.
if (ui->sidestakingTableView->horizontalHeader()->sectionSize(index + 1)
!= new_neighbor_section_size) {
ui->sidestakingTableView->horizontalHeader()->resizeSection(
index,
ui->sidestakingTableView->horizontalHeader()->sectionSize(index)
+ new_neighbor_section_size
- ui->sidestakingTableView->horizontalHeader()->sectionSize(index + 1));
}
} else {
// Do not allow the last column to be resized because there is no adjoining neighbor to the right
// and we are maintaining the total width fixed to the size of the containing frame.
ui->sidestakingTableView->horizontalHeader()->resizeSection(index, old_size);
}

m_resize_columns_in_progress = false;

return;
}

// This is the proportional resize case when the window is resized.
const int width = ui->sidestakingTableView->horizontalHeader()->width() - 5;

int orig_header_width = 0;

for (const auto& iter : SideStakeTableModel::all_ColumnIndex) {
orig_header_width += ui->sidestakingTableView->horizontalHeader()->sectionSize(iter);
}

if (!width || !orig_header_width) return;

for (const auto& iter : SideStakeTableModel::all_ColumnIndex) {
int section_size = ui->sidestakingTableView->horizontalHeader()->sectionSize(iter);

ui->sidestakingTableView->horizontalHeader()->resizeSection(
iter, section_size * width / orig_header_width);
}

m_resize_columns_in_progress = false;
}

void OptionsDialog::resizeEvent(QResizeEvent *event)
{
resizeSideStakeTableColumns();

QWidget::resizeEvent(event);
}

void OptionsDialog::sidestakeTableSectionResized(int index, int old_size, int new_size)
{
// Avoid implicit recursion between resizeTableColumns and addressBookSectionResized
if (m_resize_columns_in_progress) return;

resizeSideStakeTableColumns(true, index, old_size, new_size);
}

void OptionsDialog::tabWidgetSelectionChanged(int index)
{
// Index = 2 is the sidestaking tab for the current tab order.
if (index == 2) {
resizeSideStakeTableColumns();
}
}
22 changes: 18 additions & 4 deletions src/qt/optionsdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ class OptionsDialog : public QDialog
void setModel(OptionsModel *model);
void setMapper();

public slots:
void resizeSideStakeTableColumns(const bool& neighbor_pair_adjust = false, const int& index = 0,
const int& old_size = 0, const int& new_size = 0);

protected:
bool eventFilter(QObject *object, QEvent *event);
bool eventFilter(QObject *object, QEvent *event) override;
void resizeEvent(QResizeEvent *event) override;

private slots:
/* enable only apply button */
Expand Down Expand Up @@ -59,6 +64,8 @@ private slots:

void refreshSideStakeTableModel();

void tabWidgetSelectionChanged(int index);

signals:
void proxyIpValid(QValidatedLineEdit *object, bool fValid);
void stakingEfficiencyValid(QValidatedLineEdit *object, bool fValid);
Expand All @@ -75,18 +82,25 @@ private slots:
bool fStakingEfficiencyValid;
bool fMinStakeSplitValueValid;

std::vector<int> m_table_column_sizes;
bool m_init_column_sizes_set;
bool m_resize_columns_in_progress;

enum SideStakeTableColumnWidths
{
ADDRESS_COLUMN_WIDTH = 200,
ALLOCATION_COLUMN_WIDTH = 80,
ALLOCATION_COLUMN_WIDTH = 50,
DESCRIPTION_COLUMN_WIDTH = 130,
BANSUBNET_COLUMN_WIDTH = 150,
STATUS_COLUMN_WIDTH = 150
STATUS_COLUMN_WIDTH = 50
};

private slots:
void sidestakeSelectionChanged();
void updateSideStakeTableView();

/** Resize address book table columns based on incoming signal */
void sidestakeTableSectionResized(int index, int old_size, int new_size);

};

#endif // BITCOIN_QT_OPTIONSDIALOG_H
5 changes: 5 additions & 0 deletions src/qt/sidestaketablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class SideStakeTableModel : public QAbstractTableModel
Status
};

static constexpr std::initializer_list<ColumnIndex> all_ColumnIndex = {Address,
Allocation,
Description,
Status};

/** Return status of edit/insert operation */
enum EditStatus {
OK, /**< Everything ok */
Expand Down

0 comments on commit 93f0167

Please sign in to comment.