aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgubatron <gubatron@gmail.com>2014-03-21 01:45:47 -0400
committergubatron <gubatron@gmail.com>2014-03-21 01:45:47 -0400
commit8c29273ff058f90dfa16a30b3d8457b842c0954d (patch)
treed6e52183eb06a512319343373ddc4a11e56b350b
parent6539cfc583c5963fbb3138b99c1a8677970e0305 (diff)
[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);
-rw-r--r--src/qt/guiutil.cpp115
-rw-r--r--src/qt/guiutil.h40
-rw-r--r--src/qt/receivecoinsdialog.cpp41
-rw-r--r--src/qt/receivecoinsdialog.h13
-rw-r--r--src/qt/transactionview.cpp22
-rw-r--r--src/qt/transactionview.h13
6 files changed, 217 insertions, 27 deletions
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 7e1831f037..4a4fece3e1 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -379,6 +379,121 @@ bool ToolTipToRichTextFilter::eventFilter(QObject *obj, QEvent *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
boost::filesystem::path static StartupShortcutPath()
{
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 52124ff20a..26202e8d41 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -8,6 +8,8 @@
#include <QMessageBox>
#include <QObject>
#include <QString>
+#include <QTableView>
+#include <QHeaderView>
class QValidatedLineEdit;
class SendCoinsRecipient;
@@ -116,6 +118,44 @@ namespace GUIUtil
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 SetStartOnSystemStartup(bool fAutoStart);
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 2af3949ae4..f630324947 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -55,34 +55,35 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(QWidget *parent) :
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
}
+
+
void ReceiveCoinsDialog::setModel(WalletModel *model)
{
this->model = model;
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);
-
+ connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
connect(ui->recentRequestsView->selectionModel(),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
this,
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());
}
+//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)
{
if (event->key() == Qt::Key_Return)
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index bfe8b3401f..1d051d9324 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -10,7 +10,9 @@
#include <QMenu>
#include <QPoint>
#include <QVariant>
+#include <QHeaderView>
#include <QItemSelection>
+#include "guiutil.h"
namespace Ui {
class ReceiveCoinsDialog;
@@ -28,11 +30,18 @@ class ReceiveCoinsDialog : public QDialog
Q_OBJECT
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);
~ReceiveCoinsDialog();
-
void setModel(WalletModel *model);
+
public slots:
void clear();
void reject();
@@ -43,9 +52,11 @@ protected:
private:
Ui::ReceiveCoinsDialog *ui;
+ GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
WalletModel *model;
QMenu *contextMenu;
void copyColumnToClipboard(int column);
+ virtual void resizeEvent(QResizeEvent* event);
private slots:
void on_receiveButton_clicked();
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index a0c3ce62aa..d178efe8d5 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -168,6 +168,7 @@ void TransactionView::setModel(WalletModel *model)
transactionProxyModel->setSortRole(Qt::EditRole);
+ transactionView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
transactionView->setModel(transactionProxyModel);
transactionView->setAlternatingRowColors(true);
transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -176,15 +177,12 @@ void TransactionView::setModel(WalletModel *model)
transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
transactionView->verticalHeader()->hide();
- transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Status, 23);
- transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Date, 120);
- transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Type, 120);
-#if QT_VERSION < 0x050000
- transactionView->horizontalHeader()->setResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
-#else
- transactionView->horizontalHeader()->setSectionResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
-#endif
- transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Amount, 100);
+ transactionView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH);
+ transactionView->setColumnWidth(TransactionTableModel::Date, DATE_COLUMN_WIDTH);
+ transactionView->setColumnWidth(TransactionTableModel::Type, TYPE_COLUMN_WIDTH);
+ transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
+
+ columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
}
}
@@ -439,3 +437,9 @@ void TransactionView::focusTransaction(const QModelIndex &idx)
transactionView->setCurrentIndex(targetIdx);
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);
+}
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 18f2b9bfc9..fe8e205d6c 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -6,6 +6,7 @@
#define TRANSACTIONVIEW_H
#include <QWidget>
+#include "guiutil.h"
class TransactionFilterProxy;
class WalletModel;
@@ -44,6 +45,14 @@ public:
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:
WalletModel *model;
TransactionFilterProxy *transactionProxyModel;
@@ -62,6 +71,10 @@ private:
QWidget *createDateRangeWidget();
+ GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
+
+ virtual void resizeEvent(QResizeEvent* event);
+
private slots:
void contextualMenu(const QPoint &);
void dateRangeChanged();