Browse Source

[QT] Fixes feel when resizing the last column on tables (issue #2862)

Re-submitting this pull request with a single commit.

This patch introduces a GUIUtil class that is used when setting up the 2 tables we have so far on the Qt-GUI.
In the past you could only resize the last column, which has BTC amounts from the right border of the column header, something that was rather unnatural.

If a new table were ever to be added to the interface, fixing the last columns resizing behavior is rather simple. Just look at how we initialize here a TableViewLastColumnResizingFixer object when setting up the table header's behavior, and then how we override the resize event of the component (can be the table, or the dialog) and we invoke columnResizingFixer->stretchColumnWidth(columnIndex);
0.10
gubatron 11 years ago
parent
commit
8c29273ff0
  1. 115
      src/qt/guiutil.cpp
  2. 40
      src/qt/guiutil.h
  3. 41
      src/qt/receivecoinsdialog.cpp
  4. 13
      src/qt/receivecoinsdialog.h
  5. 22
      src/qt/transactionview.cpp
  6. 13
      src/qt/transactionview.h

115
src/qt/guiutil.cpp

@ -379,6 +379,121 @@ bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *evt)
return QObject::eventFilter(obj, evt); return QObject::eventFilter(obj, evt);
} }
void TableViewLastColumnResizingFixer::connectViewHeadersSignals()
{
connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int)));
connect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged()));
}
//we need to disconnect these while handling the resize events, otherwise we can enter infinite loops
void TableViewLastColumnResizingFixer::disconnectViewHeadersSignals()
{
disconnect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(on_sectionResized(int,int,int)));
disconnect(tableView->horizontalHeader(), SIGNAL(geometriesChanged()), this, SLOT(on_geometriesChanged()));
}
//setup the resize mode, handles compatibility for QT5 and below as the method signatures changed. (refactored here for readability)
void TableViewLastColumnResizingFixer::setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode)
{
#if QT_VERSION < 0x050000
tableView->horizontalHeader()->setResizeMode(logicalIndex, resizeMode);
#else
tableView->horizontalHeader()->setSectionResizeMode(logicalIndex, resizeMode);
#endif
}
void TableViewLastColumnResizingFixer::resizeColumn(int nColumnIndex, int width) {
tableView->setColumnWidth(nColumnIndex, width);
tableView->horizontalHeader()->resizeSection(nColumnIndex, width);
}
int TableViewLastColumnResizingFixer::getColumnsWidth()
{
int nColumnsWidthSum = 0;
for (int i = 0; i < columnCount; i++)
{
nColumnsWidthSum += tableView->horizontalHeader()->sectionSize(i);
}
return nColumnsWidthSum;
}
int TableViewLastColumnResizingFixer::getAvailableWidthForColumn(int column)
{
int nResult = lastColumnMinimumWidth;
int nTableWidth = tableView->horizontalHeader()->width();
if (nTableWidth > 0)
{
int nOtherColsWidth = getColumnsWidth() - tableView->horizontalHeader()->sectionSize(column);
nResult = std::max(nResult, nTableWidth - nOtherColsWidth);
}
return nResult;
}
//make sure we don't make the columns wider than the table's viewport's width.
void TableViewLastColumnResizingFixer::adjustTableColumnsWidth()
{
disconnectViewHeadersSignals();
resizeColumn(lastColumnIndex, getAvailableWidthForColumn(lastColumnIndex));
connectViewHeadersSignals();
int nTableWidth = tableView->horizontalHeader()->width();
int nColsWidth = getColumnsWidth();
if (nColsWidth > nTableWidth)
{
resizeColumn(secondToLastColumnIndex,getAvailableWidthForColumn(secondToLastColumnIndex));
}
}
//make column use all the space available, useful during window resizing.
void TableViewLastColumnResizingFixer::stretchColumnWidth(int column) {
disconnectViewHeadersSignals();
resizeColumn(column, getAvailableWidthForColumn(column));
connectViewHeadersSignals();
}
//when a section is resized this is a slot-proxy for ajustAmountColumnWidth()
void TableViewLastColumnResizingFixer::on_sectionResized(int logicalIndex, int oldSize, int newSize)
{
adjustTableColumnsWidth();
int remainingWidth = getAvailableWidthForColumn(logicalIndex);
if (newSize > remainingWidth)
{
resizeColumn(logicalIndex, remainingWidth);
}
}
//when the table's geometry is ready, we manually perform the Stretch of the "Message" column
//as the "Stretch" resize mode does not allow for interactive resizing.
void TableViewLastColumnResizingFixer::on_geometriesChanged()
{
if ((getColumnsWidth() - this->tableView->horizontalHeader()->width()) != 0)
{
disconnectViewHeadersSignals();
resizeColumn(secondToLastColumnIndex, getAvailableWidthForColumn(secondToLastColumnIndex));
connectViewHeadersSignals();
}
}
/**
* Initializes all internal variables and prepares the
* the resize modes of the last 2 columns of the table and
*/
TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth) :
tableView(table),
lastColumnMinimumWidth(lastColMinimumWidth),
allColumnsMinimumWidth(allColsMinimumWidth)
{
columnCount = tableView->horizontalHeader()->count();
lastColumnIndex = columnCount - 1;
secondToLastColumnIndex = columnCount - 2;
tableView->horizontalHeader()->setMinimumSectionSize(allColumnsMinimumWidth);
setViewHeaderResizeMode(secondToLastColumnIndex, QHeaderView::Interactive);
setViewHeaderResizeMode(lastColumnIndex, QHeaderView::Interactive);
}
#ifdef WIN32 #ifdef WIN32
boost::filesystem::path static StartupShortcutPath() boost::filesystem::path static StartupShortcutPath()
{ {

40
src/qt/guiutil.h

@ -8,6 +8,8 @@
#include <QMessageBox> #include <QMessageBox>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QTableView>
#include <QHeaderView>
class QValidatedLineEdit; class QValidatedLineEdit;
class SendCoinsRecipient; class SendCoinsRecipient;
@ -116,6 +118,44 @@ namespace GUIUtil
int size_threshold; int size_threshold;
}; };
/**
* Makes a QTableView last column feel as if it was being resized from its left border.
* Also makes sure the column widths are never larger than the table's viewport.
* In Qt, all columns are resizable from the right, but it's not intuitive resizing the last column from the right.
* Usually our second to last columns behave as if stretched, and when on strech mode, columns aren't resizable
* interactively or programatically.
*
* This helper object takes care of this issue.
*
*/
class TableViewLastColumnResizingFixer: public QObject
{
Q_OBJECT
public:
TableViewLastColumnResizingFixer(QTableView* table, int lastColMinimumWidth, int allColsMinimumWidth);
void stretchColumnWidth(int column);
private:
QTableView* tableView;
int lastColumnMinimumWidth;
int allColumnsMinimumWidth;
int lastColumnIndex;
int columnCount;
int secondToLastColumnIndex;
void adjustTableColumnsWidth();
int getAvailableWidthForColumn(int column);
int getColumnsWidth();
void connectViewHeadersSignals();
void disconnectViewHeadersSignals();
void setViewHeaderResizeMode(int logicalIndex, QHeaderView::ResizeMode resizeMode);
void resizeColumn(int nColumnIndex, int width);
private slots:
void on_sectionResized(int logicalIndex, int oldSize, int newSize);
void on_geometriesChanged();
};
bool GetStartOnSystemStartup(); bool GetStartOnSystemStartup();
bool SetStartOnSystemStartup(bool fAutoStart); bool SetStartOnSystemStartup(bool fAutoStart);

41
src/qt/receivecoinsdialog.cpp

@ -55,34 +55,35 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(QWidget *parent) :
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear())); connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
} }
void ReceiveCoinsDialog::setModel(WalletModel *model) void ReceiveCoinsDialog::setModel(WalletModel *model)
{ {
this->model = model; this->model = model;
if(model && model->getOptionsModel()) if(model && model->getOptionsModel())
{ {
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
updateDisplayUnit();
ui->recentRequestsView->setModel(model->getRecentRequestsTableModel());
ui->recentRequestsView->setAlternatingRowColors(true);
ui->recentRequestsView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->recentRequestsView->setSelectionMode(QAbstractItemView::ContiguousSelection);
ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Date, 130);
ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Label, 120);
#if QT_VERSION < 0x050000
ui->recentRequestsView->horizontalHeader()->setResizeMode(RecentRequestsTableModel::Message, QHeaderView::Stretch);
#else
ui->recentRequestsView->horizontalHeader()->setSectionResizeMode(RecentRequestsTableModel::Message, QHeaderView::Stretch);
#endif
ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Amount, 100);
model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder); model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
connect(ui->recentRequestsView->selectionModel(), connect(ui->recentRequestsView->selectionModel(),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
this, this,
SLOT(on_recentRequestsView_selectionChanged(QItemSelection, QItemSelection))); SLOT(on_recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
updateDisplayUnit();
QTableView* tableView = ui->recentRequestsView;
tableView->verticalHeader()->hide();
tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
tableView->setModel(model->getRecentRequestsTableModel());
tableView->setAlternatingRowColors(true);
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);
//(last 2 columns are set when the table geometry is ready) by the columnResizingFixer.
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, AMOUNT_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH);
} }
} }
@ -200,6 +201,12 @@ void ReceiveCoinsDialog::on_removeRequestButton_clicked()
model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent()); model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
} }
//We override the virtual resizeEvent of the QWidget to adjust tablet's column sizes as the table's width is proportional to the dialog's.
void ReceiveCoinsDialog::resizeEvent(QResizeEvent* event) {
QWidget::resizeEvent(event);
columnResizingFixer->stretchColumnWidth(RecentRequestsTableModel::Message);
}
void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event) void ReceiveCoinsDialog::keyPressEvent(QKeyEvent *event)
{ {
if (event->key() == Qt::Key_Return) if (event->key() == Qt::Key_Return)

13
src/qt/receivecoinsdialog.h

@ -10,7 +10,9 @@
#include <QMenu> #include <QMenu>
#include <QPoint> #include <QPoint>
#include <QVariant> #include <QVariant>
#include <QHeaderView>
#include <QItemSelection> #include <QItemSelection>
#include "guiutil.h"
namespace Ui { namespace Ui {
class ReceiveCoinsDialog; class ReceiveCoinsDialog;
@ -28,11 +30,18 @@ class ReceiveCoinsDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
enum ColumnWidths {
DATE_COLUMN_WIDTH = 130,
LABEL_COLUMN_WIDTH = 120,
AMOUNT_MINIMUM_COLUMN_WIDTH = 160,
MINIMUM_COLUMN_WIDTH = 130
};
explicit ReceiveCoinsDialog(QWidget *parent = 0); explicit ReceiveCoinsDialog(QWidget *parent = 0);
~ReceiveCoinsDialog(); ~ReceiveCoinsDialog();
void setModel(WalletModel *model); void setModel(WalletModel *model);
public slots: public slots:
void clear(); void clear();
void reject(); void reject();
@ -43,9 +52,11 @@ protected:
private: private:
Ui::ReceiveCoinsDialog *ui; Ui::ReceiveCoinsDialog *ui;
GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
WalletModel *model; WalletModel *model;
QMenu *contextMenu; QMenu *contextMenu;
void copyColumnToClipboard(int column); void copyColumnToClipboard(int column);
virtual void resizeEvent(QResizeEvent* event);
private slots: private slots:
void on_receiveButton_clicked(); void on_receiveButton_clicked();

22
src/qt/transactionview.cpp

@ -168,6 +168,7 @@ void TransactionView::setModel(WalletModel *model)
transactionProxyModel->setSortRole(Qt::EditRole); transactionProxyModel->setSortRole(Qt::EditRole);
transactionView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
transactionView->setModel(transactionProxyModel); transactionView->setModel(transactionProxyModel);
transactionView->setAlternatingRowColors(true); transactionView->setAlternatingRowColors(true);
transactionView->setSelectionBehavior(QAbstractItemView::SelectRows); transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
@ -176,15 +177,12 @@ void TransactionView::setModel(WalletModel *model)
transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder); transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
transactionView->verticalHeader()->hide(); transactionView->verticalHeader()->hide();
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Status, 23); transactionView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH);
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Date, 120); transactionView->setColumnWidth(TransactionTableModel::Date, DATE_COLUMN_WIDTH);
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Type, 120); transactionView->setColumnWidth(TransactionTableModel::Type, TYPE_COLUMN_WIDTH);
#if QT_VERSION < 0x050000 transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
transactionView->horizontalHeader()->setResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
#else columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
transactionView->horizontalHeader()->setSectionResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
#endif
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Amount, 100);
} }
} }
@ -439,3 +437,9 @@ void TransactionView::focusTransaction(const QModelIndex &idx)
transactionView->setCurrentIndex(targetIdx); transactionView->setCurrentIndex(targetIdx);
transactionView->setFocus(); transactionView->setFocus();
} }
//We override the virtual resizeEvent of the QWidget to adjust tablet's column sizes as the table's width is proportional to the dialog's.
void TransactionView::resizeEvent(QResizeEvent* event) {
QWidget::resizeEvent(event);
columnResizingFixer->stretchColumnWidth(TransactionTableModel::ToAddress);
}

13
src/qt/transactionview.h

@ -6,6 +6,7 @@
#define TRANSACTIONVIEW_H #define TRANSACTIONVIEW_H
#include <QWidget> #include <QWidget>
#include "guiutil.h"
class TransactionFilterProxy; class TransactionFilterProxy;
class WalletModel; class WalletModel;
@ -44,6 +45,14 @@ public:
Range Range
}; };
enum ColumnWidths {
STATUS_COLUMN_WIDTH = 23,
DATE_COLUMN_WIDTH = 120,
TYPE_COLUMN_WIDTH = 120,
AMOUNT_MINIMUM_COLUMN_WIDTH = 120,
MINIMUM_COLUMN_WIDTH = 23
};
private: private:
WalletModel *model; WalletModel *model;
TransactionFilterProxy *transactionProxyModel; TransactionFilterProxy *transactionProxyModel;
@ -62,6 +71,10 @@ private:
QWidget *createDateRangeWidget(); QWidget *createDateRangeWidget();
GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
virtual void resizeEvent(QResizeEvent* event);
private slots: private slots:
void contextualMenu(const QPoint &); void contextualMenu(const QPoint &);
void dateRangeChanged(); void dateRangeChanged();

Loading…
Cancel
Save