Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ BITCOIN_QT_H = \
qml/bitcoinamount.h \
qml/guiconstants.h \
qml/imageprovider.h \
qml/qrimageprovider.h \
qml/util.h \
qml/walletqmlcontroller.h \
qt/addressbookpage.h \
Expand Down Expand Up @@ -342,6 +343,7 @@ BITCOIN_QML_BASE_CPP = \
qml/models/walletqmlmodel.cpp \
qml/models/walletqmlmodeltransaction.cpp \
qml/imageprovider.cpp \
qml/qrimageprovider.cpp \
qml/util.cpp \
qml/walletqmlcontroller.cpp

Expand Down Expand Up @@ -436,6 +438,7 @@ QML_RES_QML = \
qml/controls/OptionButton.qml \
qml/controls/OptionSwitch.qml \
qml/controls/OutlineButton.qml \
qml/controls/QRImage.qml \
qml/controls/PageIndicator.qml \
qml/controls/PageStack.qml \
qml/controls/ProgressIndicator.qml \
Expand Down
2 changes: 2 additions & 0 deletions src/qml/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <qml/models/walletlistmodel.h>
#include <qml/models/walletqmlmodel.h>
#include <qml/models/walletqmlmodeltransaction.h>
#include <qml/qrimageprovider.h>
#include <qml/util.h>
#include <qml/walletqmlcontroller.h>
#include <qt/guiutil.h>
Expand Down Expand Up @@ -313,6 +314,7 @@ int QmlGuiMain(int argc, char* argv[])
QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate(Params().GetChainType())};
assert(!network_style.isNull());
engine.addImageProvider(QStringLiteral("images"), new ImageProvider{network_style.data()});
engine.addImageProvider(QStringLiteral("qr"), new QRImageProvider);

engine.rootContext()->setContextProperty("networkTrafficTower", &network_traffic_tower);
engine.rootContext()->setContextProperty("nodeModel", &node_model);
Expand Down
1 change: 1 addition & 0 deletions src/qml/bitcoin_qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<file>controls/PageIndicator.qml</file>
<file>controls/PageStack.qml</file>
<file>controls/ProgressIndicator.qml</file>
<file>controls/QRImage.qml</file>
<file>controls/qmldir</file>
<file>controls/SendOptionsPopup.qml</file>
<file>controls/Setting.qml</file>
Expand Down
17 changes: 17 additions & 0 deletions src/qml/controls/QRImage.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2025 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

import QtQuick 2.15

Image {
id: root

property string code: ""
property color backgroundColor: Qt.black
property color foregroundColor: Qt.white

fillMode: Image.PreserveAspectFit
smooth: false
source: `image://qr/${encodeURIComponent(root.code)}?&fg=${encodeURIComponent(root.foregroundColor)}&bg=${encodeURIComponent(root.backgroundColor)}`
}
20 changes: 14 additions & 6 deletions src/qml/pages/wallet/RequestPayment.qml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ Page {
clearRequest.visible = true
title.text = qsTr("Payment request #" + requestCounter)
address.text = "bc1q f5xe y2tf 89k9 zy6k gnru wszy 5fsa truy 9te1 bu"
qrImage.code = "bc1qf5xey2tf89k9zy6kgnruwszy5fsatruy9te1bu"
continueButton.text = qsTr("Copy payment request")
}
}
Expand All @@ -220,19 +221,26 @@ Page {
clearRequest.visible = false
title.text = qsTr("Request a payment")
address.text = ""
qrImage.code = ""
continueButton.text = qsTr("Create bitcoin address")
}
}
}

Rectangle {
id: qrPlaceholder
Pane {
Layout.alignment: Qt.AlignTop
Layout.minimumWidth: 150
Layout.maximumWidth: 150
color: Theme.color.neutral2
width: 150
height: 150
Layout.minimumHeight: 150
padding: 0
background: Rectangle {
color: Theme.color.neutral2
visible: qrImage.code === ""
}
contentItem: QRImage {
id: qrImage
backgroundColor: "transparent"
foregroundColor: Theme.color.neutral9
}
}
}
}
Expand Down
56 changes: 56 additions & 0 deletions src/qml/qrimageprovider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2025 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qml/qrimageprovider.h>

#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h> /* for USE_QRCODE */
#endif

#ifdef USE_QRCODE
#include <qrencode.h>
#endif

#include <QImage>
#include <QQuickImageProvider>
#include <QSize>
#include <QString>
#include <QUrl>
#include <QUrlQuery>

QRImageProvider::QRImageProvider()
: QQuickImageProvider{QQuickImageProvider::Image}
{
}

QImage QRImageProvider::requestImage(const QString& id, QSize* size, const QSize& requested_size)
{
#ifdef USE_QRCODE
const QUrl url{"image:///" + id};
const QUrlQuery query{url};
const QString data{url.path().mid(1)};
const QColor fg{query.queryItemValue("fg")};
const QColor bg{query.queryItemValue("bg")};

QRcode* code = QRcode_encodeString(data.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);

if (code) {
QImage image{code->width, code->width, QImage::Format_ARGB32};
unsigned char* p = code->data;
for (int y = 0; y < code->width; ++y) {
for (int x = 0; x < code->width; ++x) {
image.setPixelColor(x, y, (*p & 1) ? fg : bg);
++p;
}
}
*size = QSize(code->width, code->width);
QRcode_free(code);
return image;
}
#endif // USE_QRCODE
QImage pixel{1, 1, QImage::Format_ARGB32};
pixel.setPixelColor(0, 0, QColorConstants::Transparent);
*size = QSize(1, 1);
return pixel;
}
24 changes: 24 additions & 0 deletions src/qml/qrimageprovider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2025 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_QML_QRIMAGEPROVIDER_H
#define BITCOIN_QML_QRIMAGEPROVIDER_H

#include <QQuickImageProvider>

QT_BEGIN_NAMESPACE
class QImage;
class QSize;
class QString;
QT_END_NAMESPACE

class QRImageProvider : public QQuickImageProvider
{
public:
explicit QRImageProvider();

QImage requestImage(const QString& id, QSize* size, const QSize& requested_size) override;
};

#endif // BITCOIN_QML_QRIMAGEPROVIDER_H
Loading