qt: Finetune OverviewPage (#3715)

* qt: Adjust "Recent Transactions" in Overview tab

Make sure they follow the same format as the transactions in
TransactionsView.

- Removed the transaction type representing arrows
- Apply the same coloring like like in the transaction tab for
the different transaction types (orange = internal, red = outgoing,
green = incoming)

* qt: Cleanup layout of OverviewPage in css

* qt: Add three spacer (left, middle, right) and adjust layout stretch.

This allows to have the elements on the screen aligned symetrically
around the center independent from the window size/resizing.

* qt: Inrease date/amount size for "Recent Transactions" in Overview tab

* qt: Inrease number of "Recent Transactions" displayed in Overview tab

Just to fill the empty space

* qt: Make sure PS elements show as expected and adjust number of recent transactions based on PS

* qt: Adjust transaction entry generation

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* qt: Adjust warning message box

Co-Authored-By: UdjinM6 <UdjinM6@users.noreply.github.com>

* Move tx list style to css

* Fix tx list style for the traditional theme

* Drop (no longer needed?) min height offset in SetupTransactionList

Can't reproduce the tx list scrolling issue anymore

* Avoid recreating transaction filter from scratch every time SetupTransactionList is called

We call SetupTransactionList every second now (from privateSendStatus()) and this makes GUI unresponsive for huge wallets (I have ~400k txes in my testnet wallet) because of filter recreation/sorting. There is no need to go through all setup steps really, simply updating the limit works just fine and fixes the issue.

* qt: Fix an `if` statement

* qt: Just some refactoring

* fix code style

* bail out if `filter->rowCount() == nNumItems`

* qt: Make sure number of transactions is always correct

* Drop spacer to let recent tx list occupy max height available

* TransactionFilterProxy::setLimit should emit signals to let coresponding layouts update themselves

https://doc.qt.io/qt-5/qabstractitemmodel.html#layoutAboutToBeChanged
https://doc.qt.io/qt-5/qabstractitemmodel.html#layoutChanged

Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
dustinface 2020-09-25 18:04:53 +02:00 committed by GitHub
parent e552c898b9
commit b22aa1813c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 187 additions and 127 deletions

View File

@ -25,9 +25,6 @@
<property name="visible">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">QLabel { background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop:0 #F0D0A0, stop:1 #F8D488); color:#000000; }</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
@ -40,7 +37,23 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,1,0,1">
<item>
<spacer name="horizontalSpacerLeft">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
@ -563,6 +576,19 @@
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacerCenter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
@ -613,9 +639,6 @@
</item>
<item>
<widget class="QListView" name="listTransactions">
<property name="styleSheet">
<string notr="true">QListView { background: transparent; }</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
@ -633,21 +656,24 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacerRight">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>

View File

@ -24,10 +24,10 @@
#include <QSettings>
#include <QTimer>
#define ICON_OFFSET 16
#define DECORATION_SIZE 54
#define NUM_ITEMS 5
#define NUM_ITEMS_ADV 7
#define ITEM_HEIGHT 54
#define NUM_ITEMS_DISABLED 5
#define NUM_ITEMS_ENABLED_NORMAL 7
#define NUM_ITEMS_ENABLED_ADVANCED 9
class TxViewDelegate : public QAbstractItemDelegate
{
@ -44,70 +44,65 @@ public:
{
painter->save();
QIcon icon = qvariant_cast<QIcon>(index.data(TransactionTableModel::RawDecorationRole));
QRect mainRect = option.rect;
mainRect.moveLeft(ICON_OFFSET);
QRect decorationRect(mainRect.topLeft(), QSize(DECORATION_SIZE, DECORATION_SIZE));
int xspace = DECORATION_SIZE + 8;
int ypad = 6;
int xspace = 8;
int ypad = 8;
int halfheight = (mainRect.height() - 2*ypad)/2;
QRect amountRect(mainRect.left() + xspace, mainRect.top()+ypad, mainRect.width() - xspace - ICON_OFFSET, halfheight);
QRect addressRect(mainRect.left() + xspace, mainRect.top()+ypad+halfheight, mainRect.width() - xspace, halfheight);
icon = QIcon(icon);
icon.paint(painter, decorationRect);
QRect rectTopHalf(mainRect.left() + xspace, mainRect.top() + ypad, mainRect.width() - xspace, halfheight);
QRect rectBottomHalf(mainRect.left() + xspace, mainRect.top() + ypad + halfheight + 5, mainRect.width() - xspace, halfheight);
QRect rectBounding;
QColor colorForeground;
QFont fontInitial = painter->font();
QDateTime date = index.data(TransactionTableModel::DateRole).toDateTime();
QString address = index.data(Qt::DisplayRole).toString();
qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
QVariant value = index.data(Qt::ForegroundRole);
QColor foreground = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::DEFAULT);
if(value.canConvert<QBrush>())
{
QBrush brush = qvariant_cast<QBrush>(value);
foreground = brush.color();
}
// Grab model indexes for desired data from TransactionTableModel
QModelIndex indexDate = index.sibling(index.row(), TransactionTableModel::Date);
QModelIndex indexAmount = index.sibling(index.row(), TransactionTableModel::Amount);
QModelIndex indexAddress = index.sibling(index.row(), TransactionTableModel::ToAddress);
painter->setPen(foreground);
QRect boundingRect;
painter->drawText(addressRect, Qt::AlignLeft|Qt::AlignVCenter, address, &boundingRect);
// Draw first line (with slightly bigger font than the second line will get)
// Content: Date/Time, Optional IS indicator, Amount
QFont font = fontInitial;
font.setPointSize(font.pointSize() * 1.17);
painter->setFont(font);
// Date/Time
colorForeground = qvariant_cast<QColor>(indexDate.data(Qt::ForegroundRole));
QString strDate = indexDate.data(Qt::DisplayRole).toString();
painter->setPen(colorForeground);
painter->drawText(rectTopHalf, Qt::AlignLeft | Qt::AlignVCenter, strDate, &rectBounding);
// Optional IS indicator
QIcon iconInstantSend = qvariant_cast<QIcon>(indexAddress.data(TransactionTableModel::RawDecorationRole));
QRect rectInstantSend(rectBounding.right() + 5, rectTopHalf.top(), 16, halfheight);
iconInstantSend.paint(painter, rectInstantSend);
// Amount
colorForeground = qvariant_cast<QColor>(indexAmount.data(Qt::ForegroundRole));
// Note: do NOT use Qt::DisplayRole, have format properly here
qint64 nAmount = index.data(TransactionTableModel::AmountRole).toLongLong();
QString strAmount = BitcoinUnits::floorWithUnit(unit, nAmount, true, BitcoinUnits::separatorAlways);
painter->setPen(colorForeground);
painter->drawText(rectTopHalf, Qt::AlignRight | Qt::AlignVCenter, strAmount);
// Draw second line (with the initial font)
// Content: Address/label, Optional Watchonly indicator
painter->setFont(fontInitial);
// Address/Label
colorForeground = qvariant_cast<QColor>(indexAddress.data(Qt::ForegroundRole));
QString address = indexAddress.data(Qt::DisplayRole).toString();
painter->setPen(colorForeground);
painter->drawText(rectBottomHalf, Qt::AlignLeft | Qt::AlignVCenter, address, &rectBounding);
// Optional Watchonly indicator
if (index.data(TransactionTableModel::WatchonlyRole).toBool())
{
QIcon iconWatchonly = qvariant_cast<QIcon>(index.data(TransactionTableModel::WatchonlyDecorationRole));
QRect watchonlyRect(boundingRect.right() + 5, mainRect.top()+ypad+halfheight, 16, halfheight);
iconWatchonly.paint(painter, watchonlyRect);
QRect rectWatchonly(rectBounding.right() + 5, rectBottomHalf.top(), 16, halfheight);
iconWatchonly.paint(painter, rectWatchonly);
}
if(amount < 0)
{
foreground = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::RED);
}
else if(!confirmed)
{
foreground = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::UNCONFIRMED);
}
else
{
foreground = option.palette.color(QPalette::Text);
}
painter->setPen(foreground);
QString amountText = BitcoinUnits::floorWithUnit(unit, amount, true, BitcoinUnits::separatorAlways);
if(!confirmed)
{
amountText = QString("[") + amountText + QString("]");
}
painter->drawText(amountRect, Qt::AlignRight|Qt::AlignVCenter, amountText);
painter->setPen(option.palette.color(QPalette::Text));
painter->drawText(amountRect, Qt::AlignLeft|Qt::AlignVCenter, GUIUtil::dateTimeStr(date));
painter->restore();
}
inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QSize(DECORATION_SIZE, DECORATION_SIZE);
return QSize(ITEM_HEIGHT, ITEM_HEIGHT);
}
int unit;
@ -151,7 +146,6 @@ OverviewPage::OverviewPage(QWidget* parent) :
// Recent transactions
ui->listTransactions->setItemDelegate(txdelegate);
ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
// Note: minimum height of listTransactions will be set later in updateAdvancedPSUI() to reflect actual settings
ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);
@ -163,7 +157,7 @@ OverviewPage::OverviewPage(QWidget* parent) :
ui->labelTransactionsStatus->setText("(" + tr("out of sync") + ")");
// hide PS frame (helps to preserve saved size)
// we'll setup and make it visible in updateAdvancedPSUI() later
// we'll setup and make it visible in privateSendStatus() later
ui->framePrivateSend->setVisible(false);
// start with displaying the "out of sync" warnings
@ -304,9 +298,6 @@ void OverviewPage::setWalletModel(WalletModel *model)
// explicitly update PS frame and transaction list to reflect actual settings
updateAdvancedPSUI(model->getOptionsModel()->getShowAdvancedPSUI());
// Initialize PS UI
privateSendStatus(true);
if (!CPrivateSendClientOptions::IsEnabled()) return;
connect(model->getOptionsModel(), SIGNAL(privateSendRoundsChanged()), this, SLOT(updatePrivateSendProgress()));
@ -459,16 +450,7 @@ void OverviewPage::updatePrivateSendProgress()
void OverviewPage::updateAdvancedPSUI(bool fShowAdvancedPSUI) {
this->fShowAdvancedPSUI = fShowAdvancedPSUI;
int nNumItems = (!CPrivateSendClientOptions::IsEnabled() || !fShowAdvancedPSUI) ? NUM_ITEMS : NUM_ITEMS_ADV;
SetupTransactionList(nNumItems);
if (!CPrivateSendClientOptions::IsEnabled()) return;
ui->framePrivateSend->setVisible(true);
ui->labelCompletitionText->setVisible(fShowAdvancedPSUI);
ui->privateSendProgress->setVisible(fShowAdvancedPSUI);
ui->labelSubmittedDenomText->setVisible(fShowAdvancedPSUI);
ui->labelSubmittedDenom->setVisible(fShowAdvancedPSUI);
privateSendStatus(true);
}
void OverviewPage::privateSendStatus(bool fForce)
@ -477,13 +459,43 @@ void OverviewPage::privateSendStatus(bool fForce)
if(!walletModel) return;
auto tempWidgets = {ui->labelSubmittedDenomText,
ui->labelSubmittedDenom};
bool fIsEnabled = CPrivateSendClientOptions::IsEnabled();
ui->framePrivateSend->setVisible(fIsEnabled);
if (!fIsEnabled) {
SetupTransactionList(NUM_ITEMS_DISABLED);
return;
}
// Wrap all privatesend related widgets we want to show/hide state based.
// Value of the map contains a flag if this widget belongs to the advanced
// PrivateSend UI option or not. True if it does, false if not.
std::map<QWidget*, bool> privateSendWidgets = {
{ui->labelCompletitionText, true},
{ui->privateSendProgress, true},
{ui->labelSubmittedDenomText, true},
{ui->labelSubmittedDenom, true},
{ui->labelAmountAndRoundsText, false},
{ui->labelAmountRounds, false}
};
auto setWidgetsVisible = [&](bool fVisible) {
for (const auto& it : tempWidgets) {
it->setVisible(fVisible);
static bool fInitial{true};
static bool fLastVisible{false};
static bool fLastShowAdvanced{false};
// Only update the widget's visibility if something changed since the last call of setWidgetsVisible
if (fLastShowAdvanced == fShowAdvancedPSUI && fLastVisible == fVisible) {
if (fInitial) {
fInitial = false;
} else {
return;
}
}
// Set visible if: fVisible and not advanced UI element or advanced ui element and advanced ui active
for (const auto& it : privateSendWidgets) {
it.first->setVisible(fVisible && (!it.second || it.second == fShowAdvancedPSUI));
}
fLastVisible = fVisible;
fLastShowAdvanced = fShowAdvancedPSUI;
};
static int64_t nLastDSProgressBlockTime = 0;
@ -520,7 +532,13 @@ void OverviewPage::privateSendStatus(bool fForce)
if (fShowAdvancedPSUI) strEnabled += ", " + strKeysLeftText;
ui->labelPrivateSendEnabled->setText(strEnabled);
// If mixing isn't active always show the lower number of txes because there are
// anyway the most PS widgets hidden.
SetupTransactionList(NUM_ITEMS_ENABLED_NORMAL);
return;
} else {
SetupTransactionList(fShowAdvancedPSUI ? NUM_ITEMS_ENABLED_ADVANCED : NUM_ITEMS_ENABLED_NORMAL);
}
// Warn user that wallet is running out of keys
@ -654,22 +672,28 @@ void OverviewPage::togglePrivateSend(){
}
}
void OverviewPage::SetupTransactionList(int nNumItems) {
ui->listTransactions->setMinimumHeight(nNumItems * (DECORATION_SIZE + 2));
void OverviewPage::SetupTransactionList(int nNumItems)
{
if (walletModel == nullptr || walletModel->getTransactionTableModel() == nullptr) {
return;
}
if(walletModel && walletModel->getOptionsModel()) {
// Set up transaction list
// Set up transaction list
if (filter == nullptr) {
filter.reset(new TransactionFilterProxy());
filter->setSourceModel(walletModel->getTransactionTableModel());
filter->setLimit(nNumItems);
filter->setDynamicSortFilter(true);
filter->setSortRole(Qt::EditRole);
filter->setShowInactive(false);
filter->sort(TransactionTableModel::Date, Qt::DescendingOrder);
ui->listTransactions->setModel(filter.get());
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
}
if (filter->rowCount() == nNumItems) {
return;
}
filter->setLimit(nNumItems);
}
void OverviewPage::DisablePrivateSendCompletely() {

View File

@ -33,6 +33,7 @@ in the <theme.css> file.
# Used colors in general.css for commit 44de8a93f2
#00000000
#222222
#5e8c41
#a84832
#c79304
@ -1295,6 +1296,17 @@ QDialog#OptionsDialog QLabel#overriddenByCommandLineInfoLabel {
min-width: 550px;
}
/******************************************************
OverviewPage
******************************************************/
QWidget#OverviewPage QLabel#labelAlerts {
background-color: #c79304;
color: #222222;
border-radius: 5px;
padding: 5px;
}
/******************************************************
OverviewPage Balances
******************************************************/
@ -1304,21 +1316,18 @@ QWidget .QFrame#frame { /* Wallet Balance */
}
QWidget .QFrame#frame > .QLabel {
min-width: 100px;
min-height: 25px;
min-width: 60px;
min-height: 26px;
}
QWidget .QFrame#frame .QLabel#label_5 { /* Wallet Label */
min-width: 180px;
margin-top: 0;
margin-right: 5px;
padding-right: 5px;
}
QWidget .QFrame#frame .QLabel#labelWalletStatus { /* Wallet Sync Status */
qproperty-alignment: 'AlignVCenter | AlignLeft';
color: #a84832;
margin-left: 3px;
}
QWidget .QFrame#frame .QLabel#labelSpendable { /* Spendable Header */
@ -1414,25 +1423,22 @@ OverviewPage PrivateSend
QWidget .QFrame#framePrivateSend { /* PrivateSend Widget */
background-color: #00000000;
max-width: 451px;
min-width: 451px;
max-height: 350px;
}
QWidget .QFrame#framePrivateSend > .QLabel {
min-width: 175px;
min-width: 100px;
min-height: 26px;
}
QWidget .QFrame#framePrivateSend .QLabel#labelPrivateSendHeader { /* PrivateSend Header */
qproperty-alignment: 'AlignVCenter | AlignLeft';
margin-right: 10px;
margin-right: 5px;
}
QWidget .QFrame#framePrivateSend .QLabel#labelPrivateSendSyncStatus { /* PrivateSend Sync Status */
qproperty-alignment: 'AlignVCenter | AlignLeft';
color: #a84832;
margin-left: 2px;
padding-right: 5px;
}
QWidget .QFrame#framePrivateSend .QLabel#labelPrivateSendEnabledText { /* PrivateSend Enabled Status Label */
@ -1510,35 +1516,23 @@ OverviewPage RecentTransactions
******************************************************/
QWidget .QFrame#frame_2 { /* Transactions Widget */
min-width: 510px;
margin-right: 20px;
margin-left: 0;
margin-top: 0;
min-width: 430;
}
QWidget .QFrame#frame_2 .QLabel#label_4 { /* Recent Transactions Label */
min-width: 180px;
margin-left: 18px;
margin-top: 0;
margin-right: 5px;
padding-right: 5px;
margin-right: 0px;
min-height: 30px;
}
QWidget .QFrame#frame_2 .QLabel#labelTransactionsStatus { /* Recent Transactions Sync Status */
qproperty-alignment: 'AlignBottom | AlignRight';
qproperty-alignment: 'AlignVCenter | AlignLeft';
color: #a84832;
min-width: 93px;
margin-top: 0;
margin-left: 16px;
margin-right: 5px;
min-height: 16px;
}
QWidget .QFrame#frame_2 QListView { /* Transaction List */
max-width: 369px;
margin-top: 12px;
margin-left: 0px; /* CSS Voodoo - set to -66px to hide default transaction icons */
background: #00000000;
max-width: 430px;
margin-right: 10px;
}
/******************************************************

View File

@ -20,6 +20,7 @@ Loaded in GUIUtil::loadStyleSheet() in guitil.cpp.
# Used colors in traditional.css for commit 44de8a93f2
#00000000
#222222
#333
#fff
#008de4
@ -226,12 +227,25 @@ QDialog#OptionsDialog QLabel#overriddenByCommandLineInfoLabel {
OverviewPage
******************************************************/
QWidget#OverviewPage QLabel#labelAlerts {
background-color: #c79304;
color: #222222;
border-radius: 5px;
padding: 5px;
}
QWidget .QFrame#frame .QLabel#labelWalletStatus, /* Wallet Sync Status */
QWidget .QFrame#framePrivateSend .QLabel#labelPrivateSendSyncStatus, /* PrivateSend Sync Status */
QWidget .QFrame#frame_2 .QLabel#labelTransactionsStatus { /* Recent Transactions Sync Status */
color: #a84832;
}
QWidget .QFrame#frame_2 QListView { /* Transaction List */
background: #00000000;
min-width: 430px;
margin-right: 10px;
}
/******************************************************
SendCoinsDialog
******************************************************/

View File

@ -98,7 +98,9 @@ void TransactionFilterProxy::setWatchOnlyFilter(WatchOnlyFilter filter)
void TransactionFilterProxy::setLimit(int limit)
{
Q_EMIT layoutAboutToBeChanged();
this->limitRows = limit;
Q_EMIT layoutChanged();
}
void TransactionFilterProxy::setShowInactive(bool _showInactive)