diff options
Diffstat (limited to 'src/qt')
37 files changed, 377 insertions, 176 deletions
diff --git a/src/qt/Makefile b/src/qt/Makefile index b9dcf0c599..3bd6199059 100644 --- a/src/qt/Makefile +++ b/src/qt/Makefile @@ -7,3 +7,5 @@ check: FORCE $(MAKE) -C .. test_bitcoin_qt_check bitcoin-qt bitcoin-qt.exe: FORCE $(MAKE) -C .. bitcoin_qt +apk: FORCE + $(MAKE) -C .. bitcoin_qt_apk diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index ab6168a541..9927e925ac 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -295,7 +295,7 @@ void AddressBookPage::on_exportButton_clicked() // CSV is currently the only supported format QString filename = GUIUtil::getSaveFileName(this, tr("Export Address List"), QString(), - tr("Comma separated file (*.csv)"), nullptr); + tr("Comma separated file", "Name of CSV file format") + QLatin1String(" (*.csv)"), nullptr); if (filename.isNull()) return; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index bb444f22b3..ee2462ed74 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -198,42 +198,38 @@ QVariant AddressTableModel::data(const QModelIndex &index, int role) const AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer()); - if(role == Qt::DisplayRole || role == Qt::EditRole) - { - switch(index.column()) - { + const auto column = static_cast<ColumnIndex>(index.column()); + if (role == Qt::DisplayRole || role == Qt::EditRole) { + switch (column) { case Label: - if(rec->label.isEmpty() && role == Qt::DisplayRole) - { + if (rec->label.isEmpty() && role == Qt::DisplayRole) { return tr("(no label)"); - } - else - { + } else { return rec->label; } case Address: return rec->address; - } - } - else if (role == Qt::FontRole) - { - QFont font; - if(index.column() == Address) - { - font = GUIUtil::fixedPitchFont(); - } - return font; - } - else if (role == TypeRole) - { + } // no default case, so the compiler can warn about missing cases + assert(false); + } else if (role == Qt::FontRole) { + switch (column) { + case Label: + return QFont(); + case Address: + return GUIUtil::fixedPitchFont(); + } // no default case, so the compiler can warn about missing cases + assert(false); + } else if (role == TypeRole) { switch(rec->type) { case AddressTableEntry::Sending: return Send; case AddressTableEntry::Receiving: return Receive; - default: break; - } + case AddressTableEntry::Hidden: + return {}; + } // no default case, so the compiler can warn about missing cases + assert(false); } return QVariant(); } diff --git a/src/qt/android/AndroidManifest.xml b/src/qt/android/AndroidManifest.xml new file mode 100644 index 0000000000..abb88fe89d --- /dev/null +++ b/src/qt/android/AndroidManifest.xml @@ -0,0 +1,38 @@ +<?xml version='1.0' encoding='utf-8'?> +<manifest package="org.bitcoincore.qt" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> + <uses-sdk android:targetSdkVersion="24"/> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + + <uses-feature android:glEsVersion="0x00020000" android:required="true" /> + + <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> + + <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Bitcoin Core"> + <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" + android:name="org.bitcoincore.qt.BitcoinQtActivity" + android:label="Bitcoin Core" + android:icon="@drawable/bitcoin" + android:screenOrientation="unspecified" + android:launchMode="singleTop"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + + <meta-data android:name="android.app.arguments" android:value="-testnet"/> + <meta-data android:name="android.app.lib_name" android:value="bitcoin-qt"/> + <meta-data android:name="android.app.repository" android:value="default"/> + <meta-data android:name="android.app.bundle_local_qt_libs" android:value="1"/> + <meta-data android:name="android.app.use_local_qt_libs" android:value="1"/> + <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/> + <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> + <meta-data android:name="android.app.background_running" android:value="true"/> + <meta-data android:name="android.app.auto_screen_scale_factor" android:value="true"/> + <meta-data android:name="android.app.extract_android_style" android:value="default"/> + </activity> + + </application> +</manifest> diff --git a/src/qt/android/build.gradle b/src/qt/android/build.gradle new file mode 100644 index 0000000000..4c36e79db8 --- /dev/null +++ b/src/qt/android/build.gradle @@ -0,0 +1,52 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.1.0' + } +} + +repositories { + google() + jcenter() +} + +apply plugin: 'com.android.application' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} + +android { + compileSdkVersion androidCompileSdkVersion.toInteger() + + buildToolsVersion androidBuildToolsVersion + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] + aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] + res.srcDirs = [qt5AndroidDir + '/res', 'res'] + resources.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['libs'] + } + } + + lintOptions { + abortOnError false + } + + dexOptions { + javaMaxHeapSize '4g' + } + + defaultConfig { + minSdkVersion 24 + } +} diff --git a/src/qt/android/gradle.properties b/src/qt/android/gradle.properties new file mode 100644 index 0000000000..838870f62d --- /dev/null +++ b/src/qt/android/gradle.properties @@ -0,0 +1,4 @@ +androidBuildToolsVersion=28.0.3 +androidCompileSdkVersion=28 +qt5AndroidDir=new File(".").absolutePath +org.gradle.jvmargs=-Xmx4608M diff --git a/src/qt/android/res/drawable-hdpi/bitcoin.png b/src/qt/android/res/drawable-hdpi/bitcoin.png Binary files differnew file mode 100644 index 0000000000..31a556a35f --- /dev/null +++ b/src/qt/android/res/drawable-hdpi/bitcoin.png diff --git a/src/qt/android/res/drawable-ldpi/bitcoin.png b/src/qt/android/res/drawable-ldpi/bitcoin.png Binary files differnew file mode 100644 index 0000000000..76d80d4196 --- /dev/null +++ b/src/qt/android/res/drawable-ldpi/bitcoin.png diff --git a/src/qt/android/res/drawable-mdpi/bitcoin.png b/src/qt/android/res/drawable-mdpi/bitcoin.png Binary files differnew file mode 100644 index 0000000000..c2aeab851a --- /dev/null +++ b/src/qt/android/res/drawable-mdpi/bitcoin.png diff --git a/src/qt/android/res/drawable-xhdpi/bitcoin.png b/src/qt/android/res/drawable-xhdpi/bitcoin.png Binary files differnew file mode 100644 index 0000000000..2bd5e3defc --- /dev/null +++ b/src/qt/android/res/drawable-xhdpi/bitcoin.png diff --git a/src/qt/android/res/drawable-xxhdpi/bitcoin.png b/src/qt/android/res/drawable-xxhdpi/bitcoin.png Binary files differnew file mode 100644 index 0000000000..d236cf2132 --- /dev/null +++ b/src/qt/android/res/drawable-xxhdpi/bitcoin.png diff --git a/src/qt/android/res/drawable-xxxhdpi/bitcoin.png b/src/qt/android/res/drawable-xxxhdpi/bitcoin.png Binary files differnew file mode 100644 index 0000000000..bb1dbc3554 --- /dev/null +++ b/src/qt/android/res/drawable-xxxhdpi/bitcoin.png diff --git a/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java b/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java new file mode 100644 index 0000000000..cf3b4f6668 --- /dev/null +++ b/src/qt/android/src/org/bitcoincore/qt/BitcoinQtActivity.java @@ -0,0 +1,29 @@ +package org.bitcoincore.qt; + +import android.os.Bundle; +import android.system.ErrnoException; +import android.system.Os; + +import org.qtproject.qt5.android.bindings.QtActivity; + +import java.io.File; + +public class BitcoinQtActivity extends QtActivity +{ + @Override + public void onCreate(Bundle savedInstanceState) + { + final File bitcoinDir = new File(getFilesDir().getAbsolutePath() + "/.bitcoin"); + if (!bitcoinDir.exists()) { + bitcoinDir.mkdir(); + } + + try { + Os.setenv("QT_QPA_PLATFORM", "android", true); + } catch (ErrnoException e) { + e.printStackTrace(); + } + + super.onCreate(savedInstanceState); + } +} diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index a01a7bc386..6cb4a4c546 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -23,15 +23,13 @@ bool BannedNodeLessThan::operator()(const CCombinedBan& left, const CCombinedBan if (order == Qt::DescendingOrder) std::swap(pLeft, pRight); - switch(column) - { + switch (static_cast<BanTableModel::ColumnIndex>(column)) { case BanTableModel::Address: return pLeft->subnet.ToString().compare(pRight->subnet.ToString()) < 0; case BanTableModel::Bantime: return pLeft->banEntry.nBanUntil < pRight->banEntry.nBanUntil; - } - - return false; + } // no default case, so the compiler can warn about missing cases + assert(false); } // private implementation @@ -119,16 +117,17 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const CCombinedBan *rec = static_cast<CCombinedBan*>(index.internalPointer()); + const auto column = static_cast<ColumnIndex>(index.column()); if (role == Qt::DisplayRole) { - switch(index.column()) - { + switch (column) { case Address: return QString::fromStdString(rec->subnet.ToString()); case Bantime: QDateTime date = QDateTime::fromMSecsSinceEpoch(0); date = date.addSecs(rec->banEntry.nBanUntil); return QLocale::system().toString(date, QLocale::LongFormat); - } + } // no default case, so the compiler can warn about missing cases + assert(false); } return QVariant(); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index bad74fcbcc..fc6d0febc2 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -52,7 +52,6 @@ #include <QThread> #include <QTimer> #include <QTranslator> -#include <QtGlobal> #if defined(QT_STATICPLUGIN) #include <QtPlugin> @@ -62,6 +61,7 @@ Q_IMPORT_PLUGIN(QXcbIntegrationPlugin); Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); #elif defined(QT_QPA_PLATFORM_COCOA) Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); +Q_IMPORT_PLUGIN(QMacStylePlugin); #endif #endif @@ -464,15 +464,12 @@ int GuiMain(int argc, char* argv[]) // Generate high-dpi pixmaps QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); -#if QT_VERSION >= 0x050600 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); -#endif -#if (QT_VERSION <= QT_VERSION_CHECK(5, 9, 8)) && defined(Q_OS_MACOS) - const auto os_name = QSysInfo::prettyProductName(); - if (os_name.startsWith("macOS 11") || os_name.startsWith("macOS 10.16")) { - QApplication::setStyle("fusion"); - } +#if defined(QT_QPA_PLATFORM_ANDROID) + QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); + QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + QApplication::setAttribute(Qt::AA_DontUseNativeDialogs); #endif BitcoinApplication app; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 56813b2d19..b244bc94f2 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -71,14 +71,14 @@ ClientModel::~ClientModel() int ClientModel::getNumConnections(unsigned int flags) const { - CConnman::NumConnections connections = CConnman::CONNECTIONS_NONE; + ConnectionDirection connections = ConnectionDirection::None; if(flags == CONNECTIONS_IN) - connections = CConnman::CONNECTIONS_IN; + connections = ConnectionDirection::In; else if (flags == CONNECTIONS_OUT) - connections = CConnman::CONNECTIONS_OUT; + connections = ConnectionDirection::Out; else if (flags == CONNECTIONS_ALL) - connections = CConnman::CONNECTIONS_ALL; + connections = ConnectionDirection::Both; return m_node.getNodeCount(connections); } diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp index 1467801522..113bd30a0c 100644 --- a/src/qt/createwalletdialog.cpp +++ b/src/qt/createwalletdialog.cpp @@ -53,6 +53,12 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) : } }); + connect(ui->blank_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) { + if (!checked) { + ui->disable_privkeys_checkbox->setChecked(false); + } + }); + #ifndef USE_SQLITE ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)")); ui->descriptor_checkbox->setEnabled(false); diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 9e828ce0a6..e45cafe48a 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -1079,7 +1079,7 @@ <item row="1" column="0"> <widget class="QLabel" name="peerConnectionTypeLabel"> <property name="toolTip"> - <string>The direction and type of peer connection: %1</string> + <string>The direction and type of peer connection: %1</string> </property> <property name="text"> <string>Direction/Type</string> @@ -1342,13 +1342,65 @@ </widget> </item> <item row="12" column="0"> + <widget class="QLabel" name="peerLastBlockLabel"> + <property name="toolTip"> + <string>Elapsed time since a novel block passing initial validity checks was received from this peer.</string> + </property> + <property name="text"> + <string>Last Block</string> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QLabel" name="peerLastBlock"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="13" column="0"> + <widget class="QLabel" name="peerLastTxLabel"> + <property name="toolTip"> + <string>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</string> + </property> + <property name="text"> + <string>Last Tx</string> + </property> + </widget> + </item> + <item row="13" column="1"> + <widget class="QLabel" name="peerLastTx"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="14" column="0"> <widget class="QLabel" name="label_15"> <property name="text"> <string>Last Send</string> </property> </widget> </item> - <item row="12" column="1"> + <item row="14" column="1"> <widget class="QLabel" name="peerLastSend"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1364,14 +1416,14 @@ </property> </widget> </item> - <item row="13" column="0"> + <item row="15" column="0"> <widget class="QLabel" name="label_19"> <property name="text"> <string>Last Receive</string> </property> </widget> </item> - <item row="13" column="1"> + <item row="15" column="1"> <widget class="QLabel" name="peerLastRecv"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1387,14 +1439,14 @@ </property> </widget> </item> - <item row="14" column="0"> + <item row="16" column="0"> <widget class="QLabel" name="label_18"> <property name="text"> <string>Sent</string> </property> </widget> </item> - <item row="14" column="1"> + <item row="16" column="1"> <widget class="QLabel" name="peerBytesSent"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1410,14 +1462,14 @@ </property> </widget> </item> - <item row="15" column="0"> + <item row="17" column="0"> <widget class="QLabel" name="label_20"> <property name="text"> <string>Received</string> </property> </widget> </item> - <item row="15" column="1"> + <item row="17" column="1"> <widget class="QLabel" name="peerBytesRecv"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1433,14 +1485,14 @@ </property> </widget> </item> - <item row="16" column="0"> + <item row="18" column="0"> <widget class="QLabel" name="label_26"> <property name="text"> <string>Ping Time</string> </property> </widget> </item> - <item row="16" column="1"> + <item row="18" column="1"> <widget class="QLabel" name="peerPingTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1456,7 +1508,7 @@ </property> </widget> </item> - <item row="17" column="0"> + <item row="19" column="0"> <widget class="QLabel" name="peerPingWaitLabel"> <property name="toolTip"> <string>The duration of a currently outstanding ping.</string> @@ -1466,7 +1518,7 @@ </property> </widget> </item> - <item row="17" column="1"> + <item row="19" column="1"> <widget class="QLabel" name="peerPingWait"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1482,14 +1534,14 @@ </property> </widget> </item> - <item row="18" column="0"> + <item row="20" column="0"> <widget class="QLabel" name="peerMinPingLabel"> <property name="text"> <string>Min Ping</string> </property> </widget> </item> - <item row="18" column="1"> + <item row="20" column="1"> <widget class="QLabel" name="peerMinPing"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1505,14 +1557,14 @@ </property> </widget> </item> - <item row="19" column="0"> + <item row="21" column="0"> <widget class="QLabel" name="label_timeoffset"> <property name="text"> <string>Time Offset</string> </property> </widget> </item> - <item row="19" column="1"> + <item row="21" column="1"> <widget class="QLabel" name="timeoffset"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1528,7 +1580,7 @@ </property> </widget> </item> - <item row="20" column="0"> + <item row="22" column="0"> <widget class="QLabel" name="peerMappedASLabel"> <property name="toolTip"> <string>The mapped Autonomous System used for diversifying peer selection.</string> @@ -1538,7 +1590,7 @@ </property> </widget> </item> - <item row="20" column="1"> + <item row="22" column="1"> <widget class="QLabel" name="peerMappedAS"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -1554,7 +1606,7 @@ </property> </widget> </item> - <item row="21" column="0"> + <item row="23" column="0"> <spacer name="verticalSpacer_3"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index b82143e1ba..f85de0811a 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -68,7 +68,7 @@ </property> <property name="maximumSize"> <size> - <width>30</width> + <width>45</width> <height>16777215</height> </size> </property> @@ -89,9 +89,6 @@ <height>24</height> </size> </property> - <property name="flat"> - <bool>true</bool> - </property> </widget> </item> <item> @@ -406,7 +403,7 @@ </property> <property name="maximumSize"> <size> - <width>30</width> + <width>45</width> <height>16777215</height> </size> </property> @@ -427,9 +424,6 @@ <height>24</height> </size> </property> - <property name="flat"> - <bool>true</bool> - </property> </widget> </item> <item> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c70bd9f418..b4afdbcc22 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -59,6 +59,8 @@ #include <QUrlQuery> #include <QtGlobal> +#include <chrono> + #if defined(Q_OS_MAC) #include <QProcess> @@ -681,13 +683,13 @@ QString formatDurationStr(int secs) int seconds = secs % 60; if (days) - strList.append(QString(QObject::tr("%1 d")).arg(days)); + strList.append(QObject::tr("%1 d").arg(days)); if (hours) - strList.append(QString(QObject::tr("%1 h")).arg(hours)); + strList.append(QObject::tr("%1 h").arg(hours)); if (mins) - strList.append(QString(QObject::tr("%1 m")).arg(mins)); + strList.append(QObject::tr("%1 m").arg(mins)); if (seconds || (!days && !hours && !mins)) - strList.append(QString(QObject::tr("%1 s")).arg(seconds)); + strList.append(QObject::tr("%1 s").arg(seconds)); return strList.join(" "); } @@ -706,14 +708,16 @@ QString formatServicesStr(quint64 mask) return QObject::tr("None"); } -QString formatPingTime(int64_t ping_usec) +QString formatPingTime(std::chrono::microseconds ping_time) { - return (ping_usec == std::numeric_limits<int64_t>::max() || ping_usec == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(ping_usec / 1000), 10)); + return (ping_time == std::chrono::microseconds::max() || ping_time == 0us) ? + QObject::tr("N/A") : + QObject::tr("%1 ms").arg(QString::number((int)(count_microseconds(ping_time) / 1000), 10)); } QString formatTimeOffset(int64_t nTimeOffset) { - return QString(QObject::tr("%1 s")).arg(QString::number((int)nTimeOffset, 10)); + return QObject::tr("%1 s").arg(QString::number((int)nTimeOffset, 10)); } QString formatNiceTimeOffset(qint64 secs) @@ -755,14 +759,14 @@ QString formatNiceTimeOffset(qint64 secs) QString formatBytes(uint64_t bytes) { - if(bytes < 1024) - return QString(QObject::tr("%1 B")).arg(bytes); - if(bytes < 1024 * 1024) - return QString(QObject::tr("%1 KB")).arg(bytes / 1024); - if(bytes < 1024 * 1024 * 1024) - return QString(QObject::tr("%1 MB")).arg(bytes / 1024 / 1024); + if (bytes < 1'000) + return QObject::tr("%1 B").arg(bytes); + 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 QString(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) { diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 7984aa1141..6395ec6abd 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -20,6 +20,8 @@ #include <QString> #include <QTableView> +#include <chrono> + class QValidatedLineEdit; class SendCoinsRecipient; @@ -202,8 +204,8 @@ namespace GUIUtil /** Format CNodeStats.nServices bitmask into a user-readable string */ QString formatServicesStr(quint64 mask); - /** Format a CNodeStats.m_ping_usec into a user-readable string or display N/A, if 0 */ - QString formatPingTime(int64_t ping_usec); + /** Format a CNodeStats.m_last_ping_time into a user-readable string or display N/A, if 0 */ + QString formatPingTime(std::chrono::microseconds ping_time); /** Format a CNodeCombinedStats.nTimeOffset into a user-readable string */ QString formatTimeOffset(int64_t nTimeOffset); diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 1cc96035c6..ba35ff3b67 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -67,7 +67,7 @@ private Q_SLOTS: void updateDefaultProxyNets(); Q_SIGNALS: - void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort); + void proxyIpChecks(QValidatedLineEdit *pUiProxyIp, uint16_t nProxyPort); private: Ui::OptionsDialog *ui; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 96f6202874..58f6c14e7a 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -235,9 +235,9 @@ void PaymentServer::handleURIOrFile(const QString& s) if (!IsValidDestinationString(recipient.address.toStdString())) { if (uri.hasQueryItem("r")) { // payment request Q_EMIT message(tr("URI handling"), - tr("Cannot process payment request because BIP70 is not supported.")+ - tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+ - tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."), + tr("Cannot process payment request because BIP70 is not supported.\n" + "Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n" + "If you are receiving this error you should request the merchant provide a BIP21 compatible URI."), CClientUIInterface::ICON_WARNING); } Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address), @@ -258,9 +258,9 @@ 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 because BIP70 is not supported.")+ - tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+ - tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."), + tr("Cannot process payment request because BIP70 is not supported.\n" + "Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n" + "If you are receiving this error you should request the merchant provide a BIP21 compatible URI."), CClientUIInterface::ICON_WARNING); } } diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 5f518a67cd..3459bf4cf8 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -23,8 +23,7 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine if (order == Qt::DescendingOrder) std::swap(pLeft, pRight); - switch(column) - { + switch (static_cast<PeerTableModel::ColumnIndex>(column)) { case PeerTableModel::NetNodeId: return pLeft->nodeid < pRight->nodeid; case PeerTableModel::Address: @@ -34,16 +33,15 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine case PeerTableModel::Network: return pLeft->m_network < pRight->m_network; case PeerTableModel::Ping: - return pLeft->m_min_ping_usec < pRight->m_min_ping_usec; + return pLeft->m_min_ping_time < pRight->m_min_ping_time; case PeerTableModel::Sent: return pLeft->nSendBytes < pRight->nSendBytes; case PeerTableModel::Received: return pLeft->nRecvBytes < pRight->nRecvBytes; case PeerTableModel::Subversion: return pLeft->cleanSubVer.compare(pRight->cleanSubVer) < 0; - } - - return false; + } // no default case, so the compiler can warn about missing cases + assert(false); } // private implementation @@ -157,9 +155,9 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const CNodeCombinedStats *rec = static_cast<CNodeCombinedStats*>(index.internalPointer()); + const auto column = static_cast<ColumnIndex>(index.column()); if (role == Qt::DisplayRole) { - switch(index.column()) - { + switch (column) { case NetNodeId: return (qint64)rec->nodeStats.nodeid; case Address: @@ -170,26 +168,31 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const case Network: return GUIUtil::NetworkToQString(rec->nodeStats.m_network); case Ping: - return GUIUtil::formatPingTime(rec->nodeStats.m_min_ping_usec); + return GUIUtil::formatPingTime(rec->nodeStats.m_min_ping_time); case Sent: return GUIUtil::formatBytes(rec->nodeStats.nSendBytes); case Received: return GUIUtil::formatBytes(rec->nodeStats.nRecvBytes); case Subversion: return QString::fromStdString(rec->nodeStats.cleanSubVer); - } + } // no default case, so the compiler can warn about missing cases + assert(false); } else if (role == Qt::TextAlignmentRole) { - switch (index.column()) { - case ConnectionType: - case Network: - return QVariant(Qt::AlignCenter); - case Ping: - case Sent: - case Received: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - return QVariant(); - } + switch (column) { + case NetNodeId: + case Address: + return {}; + case ConnectionType: + case Network: + return QVariant(Qt::AlignCenter); + case Ping: + case Sent: + case Received: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case Subversion: + return {}; + } // no default case, so the compiler can warn about missing cases + assert(false); } else if (role == StatsRole) { switch (index.column()) { case NetNodeId: return QVariant::fromValue(rec); diff --git a/src/qt/psbtoperationsdialog.cpp b/src/qt/psbtoperationsdialog.cpp index 55ab6046cf..17746b395b 100644 --- a/src/qt/psbtoperationsdialog.cpp +++ b/src/qt/psbtoperationsdialog.cpp @@ -141,11 +141,11 @@ void PSBTOperationsDialog::saveTransaction() { filename_suggestion.append(".psbt"); QString filename = GUIUtil::getSaveFileName(this, tr("Save Transaction Data"), filename_suggestion, - tr("Partially Signed Transaction (Binary) (*.psbt)"), &selected_filter); + tr("Partially Signed Transaction (Binary)", "Name of binary PSBT file format") + QLatin1String(" (*.psbt)"), &selected_filter); if (filename.isEmpty()) { return; } - std::ofstream out(filename.toLocal8Bit().data()); + std::ofstream out(filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary); out << ssTx.str(); out.close(); showStatus(tr("PSBT saved to disk."), StatusLevel::INFO); diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp index 490826cbbb..a71c8831e9 100644 --- a/src/qt/qrimagewidget.cpp +++ b/src/qt/qrimagewidget.cpp @@ -120,7 +120,9 @@ void QRImageWidget::saveImage() { if (!GUIUtil::HasPixmap(this)) return; - QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr); + QString fn = GUIUtil::getSaveFileName( + this, tr("Save QR Code"), QString(), + tr("PNG Image", "Name of PNG file format") + QLatin1String(" (*.png)"), nullptr); if (!fn.isEmpty()) { exportImage().save(fn); diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 0da12c84fd..61cb89d75a 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -81,7 +81,6 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWid tableView->horizontalHeader()->setMinimumSectionSize(MINIMUM_COLUMN_WIDTH); tableView->horizontalHeader()->setStretchLastSection(true); } - tableView->horizontalHeader()->setSortIndicator(RecentRequestsTableModel::Date, Qt::DescendingOrder); } void ReceiveCoinsDialog::setModel(WalletModel *_model) @@ -96,6 +95,8 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) QTableView* tableView = ui->recentRequestsView; tableView->setModel(_model->getRecentRequestsTableModel()); + tableView->sortByColumn(RecentRequestsTableModel::Date, Qt::DescendingOrder); + connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ReceiveCoinsDialog::recentRequestsView_selectionChanged); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4a4b557acc..34d055e5a5 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -474,9 +474,9 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty 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")); @@ -608,7 +608,6 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ // set up peer table ui->peerWidget->setModel(model->getPeerTableModel()); ui->peerWidget->verticalHeader()->hide(); - ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu); @@ -619,10 +618,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); @@ -651,7 +650,6 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_ // set up ban table ui->banlistWidget->setModel(model->getBanTableModel()); ui->banlistWidget->verticalHeader()->hide(); - ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection); ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); @@ -1114,26 +1112,29 @@ void RPCConsole::updateDetailWidget() peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal)); ui->peerHeading->setText(peerAddrDetails); ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices)); - ui->peerRelayTxes->setText(stats->nodeStats.fRelayTxes ? "Yes" : "No"); + ui->peerRelayTxes->setText(stats->nodeStats.fRelayTxes ? ts.yes : ts.no); 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(stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastSend) : tr("never")); - ui->peerLastRecv->setText(stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastRecv) : tr("never")); + const int64_t time_now{GetSystemTimeInSeconds()}; + ui->peerConnTime->setText(GUIUtil::formatDurationStr(time_now - stats->nodeStats.nTimeConnected)); + ui->peerLastBlock->setText(TimeDurationField(time_now, stats->nodeStats.nLastBlockTime)); + ui->peerLastTx->setText(TimeDurationField(time_now, stats->nodeStats.nLastTXTime)); + ui->peerLastSend->setText(TimeDurationField(time_now, stats->nodeStats.nLastSend)); + ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.nLastRecv)); ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes)); ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes)); - ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nTimeConnected)); - ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_ping_usec)); - ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_usec)); + ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_last_ping_time)); + ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_time)); ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset)); ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion)); ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer)); 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 == PF_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)) { @@ -1141,25 +1142,25 @@ void RPCConsole::updateDetailWidget() } 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); // This check fails for example if the lock was busy and // 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_usec)); + ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStateStats.m_ping_wait)); } ui->peersTabRightPanel->show(); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 5f308dc36d..b9806e40c9 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -136,6 +136,11 @@ Q_SIGNALS: void cmdRequest(const QString &command, const WalletModel* wallet_model); 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(int mins); @@ -168,6 +173,11 @@ private: /** Update UI with latest network info from model. */ void updateNetworkState(); + /** Helper for the output of a time duration field. Inputs are UNIX epoch times. */ + QString TimeDurationField(uint64_t time_now, uint64_t time_at_event) const { + return time_at_event ? GUIUtil::formatDurationStr(time_now - time_at_event) : tr("Never"); + } + private Q_SLOTS: void updateAlerts(const QString& warnings); }; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 611f3584c3..95e1ce2210 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -266,7 +266,7 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa } // prepare transaction for getting txFee earlier - m_current_transaction = MakeUnique<WalletModelTransaction>(recipients); + m_current_transaction = std::make_unique<WalletModelTransaction>(recipients); WalletModel::SendCoinsReturn prepareStatus; updateCoinControlState(*m_coin_control); @@ -430,11 +430,11 @@ void SendCoinsDialog::on_sendButton_clicked() fileNameSuggestion.append(".psbt"); QString filename = GUIUtil::getSaveFileName(this, tr("Save Transaction Data"), fileNameSuggestion, - tr("Partially Signed Transaction (Binary) (*.psbt)"), &selectedFilter); + tr("Partially Signed Transaction (Binary)", "Name of binary PSBT file format") + QLatin1String(" (*.psbt)"), &selectedFilter); if (filename.isEmpty()) { return; } - std::ofstream out(filename.toLocal8Bit().data()); + std::ofstream out(filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary); out << ssTx.str(); out.close(); Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION); diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 35fcb2b0ca..a026069232 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -112,7 +112,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node) ClientModel clientModel(node, &optionsModel); AddWallet(wallet); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); - RemoveWallet(wallet, nullopt); + RemoveWallet(wallet, std::nullopt); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); editAddressDialog.setModel(walletModel.getAddressTableModel()); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 9ef5fe8fc7..a1baf6a402 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -54,6 +54,13 @@ int main(int argc, char* argv[]) NodeContext node_context; std::unique_ptr<interfaces::Node> node = interfaces::MakeNode(&node_context); + gArgs.ForceSetArg("-listen", "0"); + gArgs.ForceSetArg("-listenonion", "0"); + gArgs.ForceSetArg("-discover", "0"); + gArgs.ForceSetArg("-dnsseed", "0"); + gArgs.ForceSetArg("-fixedseeds", "0"); + gArgs.ForceSetArg("-upnp", "0"); + gArgs.ForceSetArg("-natpmp", "0"); bool fInvalid = false; diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index d6d2d0e3df..1107c44dc9 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -167,7 +167,7 @@ void TestGUI(interfaces::Node& node) ClientModel clientModel(node, &optionsModel); AddWallet(wallet); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); - RemoveWallet(wallet, nullopt); + RemoveWallet(wallet, std::nullopt); sendCoinsDialog.setModel(&walletModel); transactionView.setModel(&walletModel); diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index dabdf9d887..7e12410c80 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -79,7 +79,7 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *) int base = floor(log10(fMax)); float val = pow(10.0f, base); - const QString units = tr("KB/s"); + const QString units = tr("kB/s"); const float yMarginText = 2.0; // draw lines @@ -128,10 +128,10 @@ void TrafficGraphWidget::updateRates() quint64 bytesIn = clientModel->node().getTotalBytesRecv(), bytesOut = clientModel->node().getTotalBytesSent(); - float inRate = (bytesIn - nLastBytesIn) / 1024.0f * 1000 / timer->interval(); - float outRate = (bytesOut - nLastBytesOut) / 1024.0f * 1000 / timer->interval(); - vSamplesIn.push_front(inRate); - vSamplesOut.push_front(outRate); + float in_rate_kilobytes_per_sec = static_cast<float>(bytesIn - nLastBytesIn) / timer->interval(); + float out_rate_kilobytes_per_sec = static_cast<float>(bytesOut - nLastBytesOut) / timer->interval(); + vSamplesIn.push_front(in_rate_kilobytes_per_sec); + vSamplesOut.push_front(out_rate_kilobytes_per_sec); nLastBytesIn = bytesIn; nLastBytesOut = bytesOut; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index e6d483364c..a7556eed04 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -526,27 +526,30 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const return QVariant(); TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer()); - switch(role) - { + const auto column = static_cast<ColumnIndex>(index.column()); + switch (role) { case RawDecorationRole: - switch(index.column()) - { + switch (column) { case Status: return txStatusDecoration(rec); case Watchonly: return txWatchonlyDecoration(rec); + case Date: return {}; + case Type: return {}; case ToAddress: return txAddressDecoration(rec); - } - break; + case Amount: return {}; + } // no default case, so the compiler can warn about missing cases + assert(false); case Qt::DecorationRole: { QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole)); return platformStyle->TextColorIcon(icon); } case Qt::DisplayRole: - switch(index.column()) - { + switch (column) { + case Status: return {}; + case Watchonly: return {}; case Date: return formatTxDate(rec); case Type: @@ -555,12 +558,11 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const return formatTxToAddress(rec, false); case Amount: return formatTxAmount(rec, true, BitcoinUnits::SeparatorStyle::ALWAYS); - } - break; + } // no default case, so the compiler can warn about missing cases + assert(false); case Qt::EditRole: // Edit role is used for sorting, so return the unformatted values - switch(index.column()) - { + switch (column) { case Status: return QString::fromStdString(rec->status.sortKey); case Date: @@ -573,8 +575,8 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const return formatTxToAddress(rec, true); case Amount: return qint64(rec->credit + rec->debit); - } - break; + } // no default case, so the compiler can warn about missing cases + assert(false); case Qt::ToolTipRole: return formatTooltip(rec); case Qt::TextAlignmentRole: diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index e1ec7b6ed0..42e08c6af7 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -160,7 +160,6 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa transactionView->horizontalHeader()->setMinimumSectionSize(MINIMUM_COLUMN_WIDTH); transactionView->horizontalHeader()->setStretchLastSection(true); } - transactionView->horizontalHeader()->setSortIndicator(TransactionTableModel::Date, Qt::DescendingOrder); // Actions abandonAction = new QAction(tr("Abandon transaction"), this); @@ -236,6 +235,7 @@ void TransactionView::setModel(WalletModel *_model) transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); transactionProxyModel->setSortRole(Qt::EditRole); transactionView->setModel(transactionProxyModel); + transactionView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder); if (_model->getOptionsModel()) { @@ -357,7 +357,7 @@ void TransactionView::exportClicked() // CSV is currently the only supported format QString filename = GUIUtil::getSaveFileName(this, tr("Export Transaction History"), QString(), - tr("Comma separated file (*.csv)"), nullptr); + tr("Comma separated file", "Name of CSV file format") + QLatin1String(" (*.csv)"), nullptr); if (filename.isNull()) return; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index b1e6b43e60..8612893683 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -273,7 +273,7 @@ void WalletView::backupWallet() { QString filename = GUIUtil::getSaveFileName(this, tr("Backup Wallet"), QString(), - tr("Wallet Data (*.dat)"), nullptr); + tr("Wallet Data", "Name of wallet data file format") + QLatin1String(" (*.dat)"), nullptr); if (filename.isEmpty()) return; |