Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport: bitcoin-core/gui#154, #176, #221, #248, #251 - qt improvements and related fixes #6111

Merged
merged 8 commits into from
Jul 23, 2024
4 changes: 4 additions & 0 deletions doc/release-notes-154.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Compatibility
==============

Dash Core change appearance when macOS "dark mode" is activated.
3 changes: 0 additions & 3 deletions share/qt/Info.plist.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@
<key>NSHighResolutionCapable</key>
<string>True</string>

<key>NSRequiresAquaSystemAppearance</key>
<string>True</string>

<key>NSHumanReadableCopyright</key>
<string>Copyright © 2009-@COPYRIGHT_YEAR@ The Bitcoin Core developers, 2014-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string>
<key>LSApplicationCategoryType</key>
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ QT_MOC_CPP = \
qt/moc_transactiondesc.cpp \
qt/moc_transactiondescdialog.cpp \
qt/moc_transactionfilterproxy.cpp \
qt/moc_transactionoverviewwidget.cpp \
qt/moc_transactiontablemodel.cpp \
qt/moc_transactionview.cpp \
qt/moc_utilitydialog.cpp \
Expand Down Expand Up @@ -164,6 +165,7 @@ BITCOIN_QT_H = \
qt/transactiondesc.h \
qt/transactiondescdialog.h \
qt/transactionfilterproxy.h \
qt/transactionoverviewwidget.h \
qt/transactionrecord.h \
qt/transactiontablemodel.h \
qt/transactionview.h \
Expand Down
62 changes: 60 additions & 2 deletions src/qt/forms/overviewpage.ui
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,23 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
<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>
Expand Down Expand Up @@ -560,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>
Expand Down Expand Up @@ -609,7 +638,7 @@
</layout>
</item>
<item>
<widget class="QListView" name="listTransactions">
<widget class="TransactionOverviewWidget" name="listTransactions">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
Expand All @@ -619,20 +648,49 @@
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</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>
</widget>
<customwidgets>
<customwidget>
<class>TransactionOverviewWidget</class>
<extends>QListView</extends>
<header>qt/transactionoverviewwidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
12 changes: 6 additions & 6 deletions src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1785,14 +1785,14 @@ QString formatNiceTimeOffset(qint64 secs)

QString formatBytes(uint64_t bytes)
{
if(bytes < 1024)
if (bytes < 1'000)
return QObject::tr("%1 B").arg(bytes);
if(bytes < 1024 * 1024)
return QObject::tr("%1 KB").arg(bytes / 1024);
if(bytes < 1024 * 1024 * 1024)
return QObject::tr("%1 MB").arg(bytes / 1024 / 1024);
if (bytes < 1'000'000)
return QObject::tr("%1 kB").arg(bytes / 1'000);
if (bytes < 1'000'000'000)
return QObject::tr("%1 MB").arg(bytes / 1'000'000);

return QObject::tr("%1 GB").arg(bytes / 1024 / 1024 / 1024);
return QObject::tr("%1 GB").arg(bytes / 1'000'000'000);
}

qreal calculateIdealFontSize(int width, const QString& text, QFont font, qreal minPointSize, qreal font_size) {
Expand Down
28 changes: 24 additions & 4 deletions src/qt/overviewpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
#include <qt/transactionfilterproxy.h>
#include <qt/transactionoverviewwidget.h>
#include <qt/transactiontablemodel.h>
#include <qt/utilitydialog.h>
#include <qt/walletmodel.h>

#include <coinjoin/options.h>
#include <interfaces/coinjoin.h>

#include <algorithm>
#include <map>
#include <cmath>

#include <QAbstractItemDelegate>
Expand All @@ -42,7 +45,7 @@ class TxViewDelegate : public QAbstractItemDelegate
explicit TxViewDelegate(QObject* parent = nullptr) :
QAbstractItemDelegate(), unit(BitcoinUnits::DASH)
{

connect(this, &TxViewDelegate::width_changed, this, &TxViewDelegate::sizeHintChanged);
}

inline void paint(QPainter *painter, const QStyleOptionViewItem &option,
Expand Down Expand Up @@ -83,7 +86,8 @@ class TxViewDelegate : public QAbstractItemDelegate
qint64 nAmount = index.data(TransactionTableModel::AmountRole).toLongLong();
QString strAmount = BitcoinUnits::floorWithUnit(unit, nAmount, true, BitcoinUnits::SeparatorStyle::ALWAYS);
painter->setPen(colorForeground);
painter->drawText(rectTopHalf, Qt::AlignRight | Qt::AlignVCenter, strAmount);
QRect amount_bounding_rect;
painter->drawText(rectTopHalf, Qt::AlignRight | Qt::AlignVCenter, strAmount, &amount_bounding_rect);

// Draw second line (with the initial font)
// Content: Address/label, Optional Watchonly indicator
Expand All @@ -93,6 +97,7 @@ class TxViewDelegate : public QAbstractItemDelegate
QString address = indexAddress.data(Qt::DisplayRole).toString();
painter->setPen(colorForeground);
painter->drawText(rectBottomHalf, Qt::AlignLeft | Qt::AlignVCenter, address, &rectBounding);
int address_rect_min_width = rectBounding.width();
// Optional Watchonly indicator
if (index.data(TransactionTableModel::WatchonlyRole).toBool())
{
Expand All @@ -101,17 +106,32 @@ class TxViewDelegate : public QAbstractItemDelegate
iconWatchonly.paint(painter, rectWatchonly);
}

const int minimum_width = std::max(address_rect_min_width, amount_bounding_rect.width() /*+ date_bounding_rect.width() */);
const auto search = m_minimum_width.find(index.row());
if (search == m_minimum_width.end() || search->second != minimum_width) {
m_minimum_width[index.row()] = minimum_width;
Q_EMIT width_changed(index);
}
painter->restore();
}

inline QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
return QSize(ITEM_HEIGHT, ITEM_HEIGHT);
const auto search = m_minimum_width.find(index.row());
const int minimum_text_width = search == m_minimum_width.end() ? 0 : search->second;
return {ITEM_HEIGHT + 8 + minimum_text_width, ITEM_HEIGHT};
}

int unit;

Q_SIGNALS:
//! An intermediate signal for emitting from the `paint() const` member function.
void width_changed(const QModelIndex& index) const;

private:
mutable std::map<int, int> m_minimum_width;
};

#include <qt/overviewpage.moc>

OverviewPage::OverviewPage(QWidget* parent) :
Expand Down Expand Up @@ -151,7 +171,7 @@ OverviewPage::OverviewPage(QWidget* parent) :
// Note: minimum height of listTransactions will be set later in updateAdvancedCJUI() to reflect actual settings
ui->listTransactions->setAttribute(Qt::WA_MacShowFocusRect, false);

connect(ui->listTransactions, &QListView::clicked, this, &OverviewPage::handleTransactionClicked);
connect(ui->listTransactions, &TransactionOverviewWidget::clicked, this, &OverviewPage::handleTransactionClicked);

// init "out of sync" warning labels
ui->labelWalletStatus->setText("(" + tr("out of sync") + ")");
Expand Down
8 changes: 4 additions & 4 deletions src/qt/paymentserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (!IsValidDestination(dest)) {
if (uri.hasQueryItem("r")) { // payment request
Q_EMIT message(tr("URI handling"),
tr("Cannot process payment request as BIP70 is no longer supported.")+
tr("Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70."),
tr("Cannot process payment request as BIP70 is no longer supported.\n"
"Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70."),
CClientUIInterface::ICON_WARNING);
} else {
Q_EMIT message(tr("URI handling"), QString::fromStdString(error_msg),
Expand All @@ -262,8 +262,8 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (QFile::exists(s)) // payment request file
{
Q_EMIT message(tr("Payment request file handling"),
tr("Cannot process payment request as BIP70 is no longer supported.")+
tr("Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70."),
tr("Cannot process payment request as BIP70 is no longer supported.\n"
"Due to discontinued support, you should request the merchant to provide you with a BIP21 compatible URI or use a wallet that does continue to support BIP70."),
CClientUIInterface::ICON_WARNING);
}
}
Expand Down
1 change: 0 additions & 1 deletion src/qt/res/css/general.css
Original file line number Diff line number Diff line change
Expand Up @@ -1544,7 +1544,6 @@ QWidget .QFrame#frame_2 .QLabel#labelTransactionsStatus { /* Recent Transactions

QWidget .QFrame#frame_2 QListView { /* Transaction List */
background: #00000000;
max-width: 430px;
margin-right: 10px;
}

Expand Down
46 changes: 23 additions & 23 deletions src/qt/rpcconsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,9 @@ RPCConsole::RPCConsole(interfaces::Node& node, QWidget* parent, Qt::WindowFlags
const QString list{"<ul><li>" + Join(CONNECTION_TYPE_DOC, QString("</li><li>")) + "</li></ul>"};
ui->peerConnectionTypeLabel->setToolTip(ui->peerConnectionTypeLabel->toolTip().arg(list));
const QString hb_list{"<ul><li>\""
+ tr("To") + "\" – " + tr("we selected the peer for high bandwidth relay") + "</li><li>\""
+ tr("From") + "\" – " + tr("the peer selected us for high bandwidth relay") + "</li><li>\""
+ tr("No") + "\" – " + tr("no high bandwidth relay selected") + "</li></ul>"};
+ ts.to + "\" – " + tr("we selected the peer for high bandwidth relay") + "</li><li>\""
+ ts.from + "\" – " + tr("the peer selected us for high bandwidth relay") + "</li><li>\""
+ ts.no + "\" – " + tr("no high bandwidth relay selected") + "</li></ul>"};
ui->peerHighBandwidthLabel->setToolTip(ui->peerHighBandwidthLabel->toolTip().arg(hb_list));
ui->dataDir->setToolTip(ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(QString(nonbreaking_hyphen) + "blocksdir"));
Expand Down Expand Up @@ -707,10 +707,10 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_

// create peer table context menu actions
QAction* disconnectAction = new QAction(tr("&Disconnect"), this);
QAction* banAction1h = new QAction(tr("Ban for") + " " + tr("1 &hour"), this);
QAction* banAction24h = new QAction(tr("Ban for") + " " + tr("1 &day"), this);
QAction* banAction7d = new QAction(tr("Ban for") + " " + tr("1 &week"), this);
QAction* banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this);
QAction* banAction1h = new QAction(ts.ban_for + " " + tr("1 &hour"), this);
QAction* banAction24h = new QAction(ts.ban_for + " " + tr("1 &day"), this);
QAction* banAction7d = new QAction(ts.ban_for + " " + tr("1 &week"), this);
QAction* banAction365d = new QAction(ts.ban_for + " " + tr("1 &year"), this);

// create peer table context menu
peersTableContextMenu = new QMenu(this);
Expand Down Expand Up @@ -1301,9 +1301,9 @@ void RPCConsole::updateDetailWidget()
ui->peerLastBlock->setText(TimeDurationField(time_now, stats->nodeStats.m_last_block_time));
ui->peerLastTx->setText(TimeDurationField(time_now, stats->nodeStats.m_last_tx_time));
QString bip152_hb_settings;
if (stats->nodeStats.m_bip152_highbandwidth_to) bip152_hb_settings += "To";
if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings == "" ? "From" : "/From");
if (bip152_hb_settings == "") bip152_hb_settings = "No";
if (stats->nodeStats.m_bip152_highbandwidth_to) bip152_hb_settings = ts.to;
if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings.isEmpty() ? ts.from : QLatin1Char('/') + ts.from);
if (bip152_hb_settings.isEmpty()) bip152_hb_settings = ts.no;
ui->peerHighBandwidth->setText(bip152_hb_settings);
ui->peerLastSend->setText(TimeDurationField(time_now, stats->nodeStats.m_last_send));
ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.m_last_recv));
Expand All @@ -1317,19 +1317,19 @@ void RPCConsole::updateDetailWidget()
ui->peerConnectionType->setText(GUIUtil::ConnectionTypeToQString(stats->nodeStats.m_conn_type, /* prepend_direction */ true));
ui->peerNetwork->setText(GUIUtil::NetworkToQString(stats->nodeStats.m_network));
if (stats->nodeStats.m_permissionFlags == NetPermissionFlags::None) {
ui->peerPermissions->setText(tr("N/A"));
ui->peerPermissions->setText(ts.na);
} else {
QStringList permissions;
for (const auto& permission : NetPermissions::ToStrings(stats->nodeStats.m_permissionFlags)) {
permissions.append(QString::fromStdString(permission));
}
ui->peerPermissions->setText(permissions.join(" & "));
}
ui->peerMappedAS->setText(stats->nodeStats.m_mapped_as != 0 ? QString::number(stats->nodeStats.m_mapped_as) : tr("N/A"));
ui->peerMappedAS->setText(stats->nodeStats.m_mapped_as != 0 ? QString::number(stats->nodeStats.m_mapped_as) : ts.na);
auto dmn = clientModel->getMasternodeList().first.GetMNByService(stats->nodeStats.addr);
if (dmn == nullptr) {
ui->peerNodeType->setText(tr("Regular"));
ui->peerPoSeScore->setText(tr("N/A"));
ui->peerPoSeScore->setText(ts.na);
} else {
if (stats->nodeStats.verifiedProRegTxHash.IsNull()) {
ui->peerNodeType->setText(tr("Masternode"));
Expand All @@ -1343,23 +1343,23 @@ void RPCConsole::updateDetailWidget()
// nodeStateStats couldn't be fetched.
if (stats->fNodeStateStatsAvailable) {
// Sync height is init to -1
if (stats->nodeStateStats.nSyncHeight > -1)
if (stats->nodeStateStats.nSyncHeight > -1) {
ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
else
ui->peerSyncHeight->setText(tr("Unknown"));

} else {
ui->peerSyncHeight->setText(ts.unknown);
}
// Common height is init to -1
if (stats->nodeStateStats.nCommonHeight > -1)
if (stats->nodeStateStats.nCommonHeight > -1) {
ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));
else
ui->peerCommonHeight->setText(tr("Unknown"));

} else {
ui->peerCommonHeight->setText(ts.unknown);
}
ui->peerHeight->setText(QString::number(stats->nodeStateStats.m_starting_height));
ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStateStats.m_ping_wait));
ui->peerAddrRelayEnabled->setText(stats->nodeStateStats.m_addr_relay_enabled ? "Yes" : "No");
ui->peerAddrRelayEnabled->setText(stats->nodeStateStats.m_addr_relay_enabled ? ts.yes : ts.no);
ui->peerAddrProcessed->setText(QString::number(stats->nodeStateStats.m_addr_processed));
ui->peerAddrRateLimited->setText(QString::number(stats->nodeStateStats.m_addr_rate_limited));
ui->peerRelayTxes->setText(stats->nodeStateStats.m_relay_txs ? "Yes" : "No");
ui->peerRelayTxes->setText(stats->nodeStateStats.m_relay_txs ? ts.yes : ts.no);
}

ui->peersTabRightPanel->show();
Expand Down
5 changes: 5 additions & 0 deletions src/qt/rpcconsole.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ public Q_SLOTS:
void handleRestart(QStringList args);

private:
struct TranslatedStrings {
const QString yes{tr("Yes")}, no{tr("No")}, to{tr("To")}, from{tr("From")},
ban_for{tr("Ban for")}, na{tr("N/A")}, unknown{tr("Unknown")};
} const ts;

void startExecutor();
void setTrafficGraphRange(TrafficGraphData::GraphRange range);
/** Build parameter list for restart */
Expand Down
2 changes: 1 addition & 1 deletion src/qt/trafficgraphwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *)
float val = pow(10.0f, base);
float val2 = val;

const QString units = tr("KB/s");
const QString units = tr("kB/s");
const float yMarginText = 2.0;

// draw lines
Expand Down
Loading
Loading