Merge pull request #3920

8c29273 [QT] Fixes feel when resizing the last column on tables (issue #2862) (gubatron)
This commit is contained in:
Wladimir J. van der Laan 2014-03-21 08:00:57 +01:00
commit 733a799218
No known key found for this signature in database
GPG key ID: 74810B012346C9A6
6 changed files with 217 additions and 27 deletions

View file

@ -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()
{ {

View file

@ -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);

View file

@ -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)

View file

@ -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();

View file

@ -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);
}

View file

@ -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();