Skip to content

Commit 9a863b0

Browse files
committed
qml: Introduce Send pages for singlesig, sigle input/output send
1 parent 765f608 commit 9a863b0

20 files changed

+1077
-5
lines changed

src/Makefile.qt.include

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ QT_MOC_CPP = \
4343
qml/models/moc_options_model.cpp \
4444
qml/models/moc_peerdetailsmodel.cpp \
4545
qml/models/moc_peerlistsortproxy.cpp \
46+
qml/models/moc_sendrecipient.cpp \
4647
qml/models/moc_walletlistmodel.cpp \
4748
qml/models/moc_walletqmlmodel.cpp \
49+
qml/models/moc_walletqmlmodel.cpp \
50+
qml/models/moc_walletqmlmodeltransaction.cpp \
4851
qml/moc_appmode.cpp \
52+
qml/moc_bitcoinamount.cpp \
4953
qml/moc_walletqmlcontroller.cpp \
5054
qt/moc_addressbookpage.cpp \
5155
qt/moc_addresstablemodel.cpp \
@@ -126,10 +130,13 @@ BITCOIN_QT_H = \
126130
qml/models/options_model.h \
127131
qml/models/peerdetailsmodel.h \
128132
qml/models/peerlistsortproxy.h \
133+
qml/models/sendrecipient.h \
129134
qml/models/walletlistmodel.h \
130135
qml/models/walletqmlmodel.h \
136+
qml/models/walletqmlmodeltransaction.h \
131137
qml/appmode.h \
132138
qml/bitcoin.h \
139+
qml/bitcoinamount.h \
133140
qml/guiconstants.h \
134141
qml/imageprovider.h \
135142
qml/util.h \
@@ -310,6 +317,7 @@ BITCOIN_QT_WALLET_CPP = \
310317

311318
BITCOIN_QML_BASE_CPP = \
312319
qml/bitcoin.cpp \
320+
qml/bitcoinamount.cpp \
313321
qml/components/blockclockdial.cpp \
314322
qml/controls/linegraph.cpp \
315323
qml/models/chainmodel.cpp \
@@ -318,8 +326,10 @@ BITCOIN_QML_BASE_CPP = \
318326
qml/models/options_model.cpp \
319327
qml/models/peerdetailsmodel.cpp \
320328
qml/models/peerlistsortproxy.cpp \
329+
qml/models/sendrecipient.cpp \
321330
qml/models/walletlistmodel.cpp \
322331
qml/models/walletqmlmodel.cpp \
332+
qml/models/walletqmlmodeltransaction.cpp \
323333
qml/imageprovider.cpp \
324334
qml/util.cpp \
325335
qml/walletqmlcontroller.cpp
@@ -343,6 +353,7 @@ QML_RES_ICONS = \
343353
qml/res/icons/cross.png \
344354
qml/res/icons/error.png \
345355
qml/res/icons/export.png \
356+
qml/res/icons/flip-vertical.png \
346357
qml/res/icons/gear.png \
347358
qml/res/icons/gear-outline.png \
348359
qml/res/icons/hidden.png \
@@ -371,9 +382,9 @@ QML_RES_QML = \
371382
qml/components/ConnectionSettings.qml \
372383
qml/components/DeveloperOptions.qml \
373384
qml/components/ExternalPopup.qml \
374-
qml/components/PeersIndicator.qml \
375385
qml/components/NetworkTrafficGraph.qml \
376386
qml/components/NetworkIndicator.qml \
387+
qml/components/PeersIndicator.qml \
377388
qml/components/ProxySettings.qml \
378389
qml/components/Separator.qml \
379390
qml/components/StorageLocations.qml \
@@ -394,13 +405,14 @@ QML_RES_QML = \
394405
qml/controls/IPAddressValueInput.qml \
395406
qml/controls/KeyValueRow.qml \
396407
qml/controls/NavButton.qml \
397-
qml/controls/PageIndicator.qml \
408+
qml/controls/LabeledTextInput.qml \
398409
qml/controls/NavigationBar.qml \
399410
qml/controls/NavigationBar2.qml \
400411
qml/controls/NavigationTab.qml \
401412
qml/controls/OptionButton.qml \
402413
qml/controls/OptionSwitch.qml \
403414
qml/controls/OutlineButton.qml \
415+
qml/controls/PageIndicator.qml \
404416
qml/controls/PageStack.qml \
405417
qml/controls/ProgressIndicator.qml \
406418
qml/controls/qmldir \
@@ -440,6 +452,9 @@ QML_RES_QML = \
440452
qml/pages/wallet/CreatePassword.qml \
441453
qml/pages/wallet/CreateWalletWizard.qml \
442454
qml/pages/wallet/DesktopWallets.qml \
455+
qml/pages/wallet/Send.qml \
456+
qml/pages/wallet/SendResult.qml \
457+
qml/pages/wallet/SendReview.qml \
443458
qml/pages/wallet/WalletBadge.qml \
444459
qml/pages/wallet/WalletSelect.qml
445460

src/qml/bitcoin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <node/interface_ui.h>
1616
#include <noui.h>
1717
#include <qml/appmode.h>
18+
#include <qml/bitcoinamount.h>
1819
#ifdef __ANDROID__
1920
#include <qml/androidnotifier.h>
2021
#endif
@@ -27,8 +28,10 @@
2728
#include <qml/models/options_model.h>
2829
#include <qml/models/peerdetailsmodel.h>
2930
#include <qml/models/peerlistsortproxy.h>
31+
#include <qml/models/sendrecipient.h>
3032
#include <qml/models/walletlistmodel.h>
3133
#include <qml/models/walletqmlmodel.h>
34+
#include <qml/models/walletqmlmodeltransaction.h>
3235
#include <qml/imageprovider.h>
3336
#include <qml/util.h>
3437
#include <qml/walletqmlcontroller.h>
@@ -330,10 +333,14 @@ int QmlGuiMain(int argc, char* argv[])
330333
qmlRegisterType<BlockClockDial>("org.bitcoincore.qt", 1, 0, "BlockClockDial");
331334
qmlRegisterType<LineGraph>("org.bitcoincore.qt", 1, 0, "LineGraph");
332335
qmlRegisterUncreatableType<PeerDetailsModel>("org.bitcoincore.qt", 1, 0, "PeerDetailsModel", "");
336+
qmlRegisterType<BitcoinAmount>("org.bitcoincore.qt", 1, 0, "BitcoinAmount");
337+
qmlRegisterUncreatableType<SendRecipient>("org.bitcoincore.qt", 1, 0, "SendRecipient", "");
333338

334339
#ifdef ENABLE_WALLET
335340
qmlRegisterUncreatableType<WalletQmlModel>("org.bitcoincore.qt", 1, 0, "WalletQmlModel",
336341
"WalletQmlModel cannot be instantiated from QML");
342+
qmlRegisterUncreatableType<WalletQmlModelTransaction>("org.bitcoincore.qt", 1, 0, "WalletQmlModelTransaction",
343+
"WalletQmlModelTransaction cannot be instantiated from QML");
337344
#endif
338345

339346
engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml")));

src/qml/bitcoin_qml.qrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<file>controls/ContinueButton.qml</file>
2424
<file>controls/CoreText.qml</file>
2525
<file>controls/CoreTextField.qml</file>
26+
<file>controls/LabeledTextInput.qml</file>
2627
<file>controls/ExternalLink.qml</file>
2728
<file>controls/FocusBorder.qml</file>
2829
<file>controls/Header.qml</file>
@@ -77,6 +78,9 @@
7778
<file>pages/wallet/CreatePassword.qml</file>
7879
<file>pages/wallet/CreateWalletWizard.qml</file>
7980
<file>pages/wallet/DesktopWallets.qml</file>
81+
<file>pages/wallet/Send.qml</file>
82+
<file>pages/wallet/SendResult.qml</file>
83+
<file>pages/wallet/SendReview.qml</file>
8084
<file>pages/wallet/WalletBadge.qml</file>
8185
<file>pages/wallet/WalletSelect.qml</file>
8286
</qresource>
@@ -96,6 +100,7 @@
96100
<file alias="cross">res/icons/cross.png</file>
97101
<file alias="error">res/icons/error.png</file>
98102
<file alias="export">res/icons/export.png</file>
103+
<file alias="flip-vertical">res/icons/flip-vertical.png</file>
99104
<file alias="gear">res/icons/gear.png</file>
100105
<file alias="gear-outline">res/icons/gear-outline.png</file>
101106
<file alias="hidden">res/icons/hidden.png</file>

src/qml/bitcoinamount.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright (c) 2024 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <qml/bitcoinamount.h>
6+
7+
#include <QRegExp>
8+
#include <QStringList>
9+
10+
11+
BitcoinAmount::BitcoinAmount(QObject *parent) : QObject(parent)
12+
{
13+
m_unit = Unit::BTC;
14+
}
15+
16+
int BitcoinAmount::decimals(Unit unit)
17+
{
18+
switch (unit) {
19+
case Unit::BTC: return 8;
20+
case Unit::SAT: return 0;
21+
} // no default case, so the compiler can warn about missing cases
22+
assert(false);
23+
}
24+
25+
QString BitcoinAmount::sanitize(const QString &text)
26+
{
27+
QString result = text;
28+
29+
// Remove any invalid characters
30+
result.remove(QRegExp("[^0-9.]"));
31+
32+
// Ensure only one decimal point
33+
QStringList parts = result.split('.');
34+
if (parts.size() > 2) {
35+
result = parts[0] + "." + parts[1];
36+
}
37+
38+
// Limit decimal places to 8
39+
if (parts.size() == 2 && parts[1].length() > 8) {
40+
result = parts[0] + "." + parts[1].left(8);
41+
}
42+
43+
return result;
44+
}
45+
46+
BitcoinAmount::Unit BitcoinAmount::unit() const
47+
{
48+
return m_unit;
49+
}
50+
51+
void BitcoinAmount::setUnit(const Unit unit)
52+
{
53+
m_unit = unit;
54+
Q_EMIT unitChanged();
55+
}
56+
57+
QString BitcoinAmount::unitLabel() const
58+
{
59+
switch (m_unit) {
60+
case Unit::BTC: return "";
61+
case Unit::SAT: return "Sat";
62+
}
63+
assert(false);
64+
}
65+
66+
QString BitcoinAmount::amount() const
67+
{
68+
return m_amount;
69+
}
70+
71+
void BitcoinAmount::setAmount(const QString& new_amount)
72+
{
73+
m_amount = sanitize(new_amount);
74+
Q_EMIT amountChanged();
75+
}
76+
77+
long long BitcoinAmount::toSatoshis(QString& amount, const Unit unit)
78+
{
79+
80+
int num_decimals = decimals(unit);
81+
82+
QStringList parts = amount.remove(' ').split(".");
83+
84+
QString whole = parts[0];
85+
QString decimals;
86+
87+
if(parts.size() > 1)
88+
{
89+
decimals = parts[1];
90+
}
91+
QString str = whole + decimals.leftJustified(num_decimals, '0', true);
92+
93+
return str.toLongLong();
94+
}
95+
96+
QString BitcoinAmount::convert(const QString &amount, Unit unit)
97+
{
98+
if (amount == "") {
99+
return amount;
100+
}
101+
102+
QString result = amount;
103+
int decimalPosition = result.indexOf(".");
104+
105+
if (decimalPosition == -1) {
106+
decimalPosition = result.length();
107+
result.append(".");
108+
}
109+
110+
if (unit == Unit::BTC) {
111+
int numDigitsAfterDecimal = result.length() - decimalPosition - 1;
112+
if (numDigitsAfterDecimal < 8) {
113+
result.append(QString(8 - numDigitsAfterDecimal, '0'));
114+
}
115+
result.remove(decimalPosition, 1);
116+
117+
while (result.startsWith('0') && result.length() > 1) {
118+
result.remove(0, 1);
119+
}
120+
} else if (unit == Unit::SAT) {
121+
result.remove(decimalPosition, 1);
122+
int newDecimalPosition = decimalPosition - 8;
123+
if (newDecimalPosition < 1) {
124+
result = QString("0").repeated(-newDecimalPosition) + result;
125+
newDecimalPosition = 0;
126+
}
127+
result.insert(newDecimalPosition, ".");
128+
129+
while (result.endsWith('0') && result.contains('.')) {
130+
result.chop(1);
131+
}
132+
if (result.endsWith('.')) {
133+
result.chop(1);
134+
}
135+
if (result.startsWith('.')) {
136+
result.insert(0, "0");
137+
}
138+
}
139+
140+
return result;
141+
}

src/qml/bitcoinamount.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2024 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_QML_BITCOINAMOUNT_H
6+
#define BITCOIN_QML_BITCOINAMOUNT_H
7+
8+
#include <consensus/amount.h>
9+
10+
#include <QObject>
11+
#include <QString>
12+
#include <qobjectdefs.h>
13+
14+
class BitcoinAmount : public QObject
15+
{
16+
Q_OBJECT
17+
Q_PROPERTY(Unit unit READ unit WRITE setUnit NOTIFY unitChanged)
18+
Q_PROPERTY(QString unitLabel READ unitLabel NOTIFY unitChanged)
19+
Q_PROPERTY(QString amount READ amount WRITE setAmount NOTIFY amountChanged)
20+
21+
public:
22+
enum class Unit {
23+
BTC,
24+
SAT
25+
};
26+
Q_ENUM(Unit)
27+
28+
explicit BitcoinAmount(QObject *parent = nullptr);
29+
30+
Unit unit() const;
31+
void setUnit(Unit unit);
32+
QString unitLabel() const;
33+
QString amount() const;
34+
void setAmount(const QString& new_amount);
35+
36+
public Q_SLOTS:
37+
QString sanitize(const QString &text);
38+
QString convert(const QString &text, Unit unit);
39+
40+
Q_SIGNALS:
41+
void unitChanged();
42+
void unitLabelChanged();
43+
void amountChanged();
44+
45+
private:
46+
long long toSatoshis(QString &amount, const Unit unit);
47+
int decimals(Unit unit);
48+
49+
Unit m_unit;
50+
QString m_unitLabel;
51+
QString m_amount;
52+
};
53+
54+
#endif // BITCOIN_QML_BITCOINAMOUNT_H

0 commit comments

Comments
 (0)