Skip to content

Commit 727aa52

Browse files
committed
qml: Introduce Send pages for singlesig, sigle input/output send
1 parent 59fa29a commit 727aa52

17 files changed

+836
-14
lines changed

src/Makefile.qt.include

+10
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ QT_MOC_CPP = \
4545
qml/models/moc_peerdetailsmodel.cpp \
4646
qml/models/moc_peerlistsortproxy.cpp \
4747
qml/models/moc_transaction.cpp \
48+
qml/models/moc_sendrecipient.cpp \
4849
qml/models/moc_walletlistmodel.cpp \
4950
qml/models/moc_walletqmlmodel.cpp \
51+
qml/models/moc_walletqmlmodel.cpp \
52+
qml/models/moc_walletqmlmodeltransaction.cpp \
5053
qml/moc_appmode.cpp \
5154
qml/moc_bitcoinamount.cpp \
5255
qml/moc_clipboard.cpp \
@@ -132,8 +135,10 @@ BITCOIN_QT_H = \
132135
qml/models/peerdetailsmodel.h \
133136
qml/models/peerlistsortproxy.h \
134137
qml/models/transaction.h \
138+
qml/models/sendrecipient.h \
135139
qml/models/walletlistmodel.h \
136140
qml/models/walletqmlmodel.h \
141+
qml/models/walletqmlmodeltransaction.h \
137142
qml/appmode.h \
138143
qml/clipboard.h \
139144
qml/bitcoin.h \
@@ -329,8 +334,10 @@ BITCOIN_QML_BASE_CPP = \
329334
qml/models/peerdetailsmodel.cpp \
330335
qml/models/peerlistsortproxy.cpp \
331336
qml/models/transaction.cpp \
337+
qml/models/sendrecipient.cpp \
332338
qml/models/walletlistmodel.cpp \
333339
qml/models/walletqmlmodel.cpp \
340+
qml/models/walletqmlmodeltransaction.cpp \
334341
qml/imageprovider.cpp \
335342
qml/util.cpp \
336343
qml/walletqmlcontroller.cpp
@@ -462,6 +469,9 @@ QML_RES_QML = \
462469
qml/pages/wallet/CreateWalletWizard.qml \
463470
qml/pages/wallet/DesktopWallets.qml \
464471
qml/pages/wallet/RequestPayment.qml \
472+
qml/pages/wallet/Send.qml \
473+
qml/pages/wallet/SendResult.qml \
474+
qml/pages/wallet/SendReview.qml \
465475
qml/pages/wallet/WalletBadge.qml \
466476
qml/pages/wallet/WalletSelect.qml
467477

src/qml/bitcoin.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@
2323
#include <qml/components/blockclockdial.h>
2424
#include <qml/controls/linegraph.h>
2525
#include <qml/guiconstants.h>
26+
#include <qml/imageprovider.h>
2627
#include <qml/models/activitylistmodel.h>
2728
#include <qml/models/chainmodel.h>
2829
#include <qml/models/networktraffictower.h>
2930
#include <qml/models/nodemodel.h>
3031
#include <qml/models/options_model.h>
3132
#include <qml/models/peerdetailsmodel.h>
3233
#include <qml/models/peerlistsortproxy.h>
34+
#include <qml/models/sendrecipient.h>
3335
#include <qml/models/walletlistmodel.h>
3436
#include <qml/models/walletqmlmodel.h>
35-
#include <qml/imageprovider.h>
37+
#include <qml/models/walletqmlmodeltransaction.h>
3638
#include <qml/util.h>
3739
#include <qml/walletqmlcontroller.h>
3840
#include <qt/guiutil.h>
@@ -337,10 +339,13 @@ int QmlGuiMain(int argc, char* argv[])
337339
qmlRegisterUncreatableType<PeerDetailsModel>("org.bitcoincore.qt", 1, 0, "PeerDetailsModel", "");
338340
qmlRegisterType<BitcoinAmount>("org.bitcoincore.qt", 1, 0, "BitcoinAmount");
339341
qmlRegisterUncreatableType<Transaction>("org.bitcoincore.qt", 1, 0, "Transaction", "");
342+
qmlRegisterUncreatableType<SendRecipient>("org.bitcoincore.qt", 1, 0, "SendRecipient", "");
340343

341344
#ifdef ENABLE_WALLET
342345
qmlRegisterUncreatableType<WalletQmlModel>("org.bitcoincore.qt", 1, 0, "WalletQmlModel",
343346
"WalletQmlModel cannot be instantiated from QML");
347+
qmlRegisterUncreatableType<WalletQmlModelTransaction>("org.bitcoincore.qt", 1, 0, "WalletQmlModelTransaction",
348+
"WalletQmlModelTransaction cannot be instantiated from QML");
344349
#endif
345350

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

src/qml/bitcoin_qml.qrc

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
<file>controls/ContinueButton.qml</file>
2525
<file>controls/CoreText.qml</file>
2626
<file>controls/CoreTextField.qml</file>
27-
<file>controls/LabeledTextInput.qml</file>
2827
<file>controls/ExternalLink.qml</file>
2928
<file>controls/FocusBorder.qml</file>
3029
<file>controls/Header.qml</file>
@@ -83,6 +82,9 @@
8382
<file>pages/wallet/CreateWalletWizard.qml</file>
8483
<file>pages/wallet/DesktopWallets.qml</file>
8584
<file>pages/wallet/RequestPayment.qml</file>
85+
<file>pages/wallet/Send.qml</file>
86+
<file>pages/wallet/SendResult.qml</file>
87+
<file>pages/wallet/SendReview.qml</file>
8688
<file>pages/wallet/WalletBadge.qml</file>
8789
<file>pages/wallet/WalletSelect.qml</file>
8890
</qresource>

src/qml/bitcoinamount.cpp

+29-2
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,28 @@ QString BitcoinAmount::amount() const
6868
return m_amount;
6969
}
7070

71+
QString BitcoinAmount::satoshiAmount() const
72+
{
73+
return toSatoshis(m_amount);
74+
}
75+
7176
void BitcoinAmount::setAmount(const QString& new_amount)
7277
{
7378
m_amount = sanitize(new_amount);
7479
Q_EMIT amountChanged();
7580
}
7681

77-
long long BitcoinAmount::toSatoshis(QString& amount, const Unit unit)
82+
QString BitcoinAmount::toSatoshis(const QString& text) const
7883
{
84+
if (m_unit == Unit::SAT) {
85+
return text;
86+
} else {
87+
return convert(text, m_unit);
88+
}
89+
}
7990

91+
long long BitcoinAmount::toSatoshis(QString& amount, const Unit unit)
92+
{
8093
int num_decimals = decimals(unit);
8194

8295
QStringList parts = amount.remove(' ').split(".");
@@ -93,7 +106,7 @@ long long BitcoinAmount::toSatoshis(QString& amount, const Unit unit)
93106
return str.toLongLong();
94107
}
95108

96-
QString BitcoinAmount::convert(const QString &amount, Unit unit)
109+
QString BitcoinAmount::convert(const QString& amount, Unit unit) const
97110
{
98111
if (amount == "") {
99112
return amount;
@@ -113,6 +126,10 @@ QString BitcoinAmount::convert(const QString &amount, Unit unit)
113126
result.append(QString(8 - numDigitsAfterDecimal, '0'));
114127
}
115128
result.remove(decimalPosition, 1);
129+
130+
while (result.startsWith('0') && result.length() > 1) {
131+
result.remove(0, 1);
132+
}
116133
} else if (unit == Unit::SAT) {
117134
result.remove(decimalPosition, 1);
118135
int newDecimalPosition = decimalPosition - 8;
@@ -121,6 +138,16 @@ QString BitcoinAmount::convert(const QString &amount, Unit unit)
121138
newDecimalPosition = 0;
122139
}
123140
result.insert(newDecimalPosition, ".");
141+
142+
while (result.endsWith('0') && result.contains('.')) {
143+
result.chop(1);
144+
}
145+
if (result.endsWith('.')) {
146+
result.chop(1);
147+
}
148+
if (result.startsWith('.')) {
149+
result.insert(0, "0");
150+
}
124151
}
125152

126153
return result;

src/qml/bitcoinamount.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
#ifndef BITCOIN_QML_BITCOINAMOUNT_H
66
#define BITCOIN_QML_BITCOINAMOUNT_H
77

8+
#include <consensus/amount.h>
9+
810
#include <QObject>
911
#include <QString>
10-
#include <qobjectdefs.h>
1112

1213
class BitcoinAmount : public QObject
1314
{
1415
Q_OBJECT
1516
Q_PROPERTY(Unit unit READ unit WRITE setUnit NOTIFY unitChanged)
1617
Q_PROPERTY(QString unitLabel READ unitLabel NOTIFY unitChanged)
1718
Q_PROPERTY(QString amount READ amount WRITE setAmount NOTIFY amountChanged)
19+
Q_PROPERTY(QString satoshiAmount READ satoshiAmount NOTIFY amountChanged)
1820

1921
public:
2022
enum class Unit {
@@ -30,10 +32,12 @@ class BitcoinAmount : public QObject
3032
QString unitLabel() const;
3133
QString amount() const;
3234
void setAmount(const QString& new_amount);
35+
QString satoshiAmount() const;
3336

3437
public Q_SLOTS:
35-
QString sanitize(const QString &text);
36-
QString convert(const QString &text, Unit unit);
38+
QString sanitize(const QString& text);
39+
QString convert(const QString& text, Unit unit) const;
40+
QString toSatoshis(const QString& text) const;
3741

3842
Q_SIGNALS:
3943
void unitChanged();

src/qml/imageprovider.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -206,5 +206,10 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
206206
*size = requested_size;
207207
return QIcon(":/icons/plus").pixmap(requested_size);
208208
}
209+
210+
if (id == "flip-vertical") {
211+
*size = requested_size;
212+
return QIcon(":/icons/flip-vertical").pixmap(requested_size);
213+
}
209214
return {};
210215
}

src/qml/models/sendrecipient.cpp

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (c) 2025 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/models/sendrecipient.h>
6+
#include <qobjectdefs.h>
7+
8+
SendRecipient::SendRecipient(QObject* parent)
9+
: QObject(parent), m_address(""), m_label(""), m_amount(""), m_message("")
10+
{
11+
}
12+
13+
QString SendRecipient::address() const
14+
{
15+
return m_address;
16+
}
17+
18+
void SendRecipient::setAddress(const QString& address)
19+
{
20+
if (m_address != address) {
21+
m_address = address;
22+
Q_EMIT addressChanged();
23+
}
24+
}
25+
26+
QString SendRecipient::label() const
27+
{
28+
return m_label;
29+
}
30+
31+
void SendRecipient::setLabel(const QString& label)
32+
{
33+
if (m_label != label) {
34+
m_label = label;
35+
Q_EMIT labelChanged();
36+
}
37+
}
38+
39+
QString SendRecipient::amount() const
40+
{
41+
return m_amount;
42+
}
43+
44+
void SendRecipient::setAmount(const QString& amount)
45+
{
46+
if (m_amount != amount) {
47+
m_amount = amount;
48+
Q_EMIT amountChanged();
49+
}
50+
}
51+
52+
QString SendRecipient::message() const
53+
{
54+
return m_message;
55+
}
56+
57+
void SendRecipient::setMessage(const QString& message)
58+
{
59+
if (m_message != message) {
60+
m_message = message;
61+
Q_EMIT messageChanged();
62+
}
63+
}
64+
65+
bool SendRecipient::subtractFeeFromAmount() const
66+
{
67+
return m_subtractFeeFromAmount;
68+
}
69+
70+
CAmount SendRecipient::cAmount() const
71+
{
72+
// TODO: Figure out who owns the parsing of SendRecipient::amount to CAmount
73+
return m_amount.toLongLong();
74+
}
75+
76+
void SendRecipient::clear()
77+
{
78+
m_address = "";
79+
m_label = "";
80+
m_amount = "";
81+
m_message = "";
82+
m_subtractFeeFromAmount = false;
83+
Q_EMIT addressChanged();
84+
Q_EMIT labelChanged();
85+
Q_EMIT amountChanged();
86+
Q_EMIT messageChanged();
87+
}

src/qml/models/sendrecipient.h

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) 2025 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_MODELS_SENDRECIPIENT_H
6+
#define BITCOIN_QML_MODELS_SENDRECIPIENT_H
7+
8+
#include <QObject>
9+
#include <QString>
10+
#include <qml/bitcoinamount.h>
11+
12+
class SendRecipient : public QObject
13+
{
14+
Q_OBJECT
15+
Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged)
16+
Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
17+
Q_PROPERTY(QString amount READ amount WRITE setAmount NOTIFY amountChanged)
18+
Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
19+
20+
public:
21+
explicit SendRecipient(QObject* parent = nullptr);
22+
23+
QString address() const;
24+
void setAddress(const QString& address);
25+
26+
QString label() const;
27+
void setLabel(const QString& label);
28+
29+
QString amount() const;
30+
void setAmount(const QString& amount);
31+
32+
QString message() const;
33+
void setMessage(const QString& message);
34+
35+
CAmount cAmount() const;
36+
37+
bool subtractFeeFromAmount() const;
38+
39+
Q_INVOKABLE void clear();
40+
41+
Q_SIGNALS:
42+
void addressChanged();
43+
void labelChanged();
44+
void amountChanged();
45+
void messageChanged();
46+
47+
private:
48+
QString m_address;
49+
QString m_label;
50+
QString m_amount;
51+
QString m_message;
52+
bool m_subtractFeeFromAmount{false};
53+
};
54+
55+
#endif // BITCOIN_QML_MODELS_SENDRECIPIENT_H

0 commit comments

Comments
 (0)