From a6078686901984388b1804e9852d56fd9c260a80 Mon Sep 17 00:00:00 2001 From: Borgbyte Date: Tue, 3 Mar 2020 19:12:24 +0000 Subject: [PATCH] Improve receive view and copy uri to clipboard --- src/ReceiveView.qml | 67 ++++++++++++++++++++++------------- src/account.cpp | 53 +++++++++++++++++++++++---- src/account.h | 19 +++++++--- src/dialogs/ReceiveDialog.qml | 1 - 4 files changed, 105 insertions(+), 35 deletions(-) diff --git a/src/ReceiveView.qml b/src/ReceiveView.qml index 270334f6f..8a9c57980 100644 --- a/src/ReceiveView.qml +++ b/src/ReceiveView.qml @@ -4,49 +4,60 @@ import QtQuick.Controls 2.5 import QtQuick.Layouts 1.12 ColumnLayout { - property alias address: receive_address.address - property var amount: parseAmount(amount_field.text) - - function url(address, amount) { - var parts = [] - if (amount && amount > 0) parts.push('amount=' + amount) - if (parts.length === 0) return address - return 'bitcoin:' + address + '?' + parts.join('&') - } - - function copyAddress() { - if (receive_address.generating) return - receive_address.copyToClipboard() - address_field.ToolTip.show(qsTr('id_address_copied_to_clipboard'), 1000) - } - spacing: 16 ReceiveAddress { id: receive_address + amount: amount_field.text Binding on account { value: account } } + Action { + id: refresh_action + icon.source: 'assets/svg/refresh.svg' + icon.width: 16 + icon.height: 16 + onTriggered: receive_address.generate() + } + + Action { + id: copy_address_action + text: qsTrId('id_copy_address') + onTriggered: { + if (receive_address.generating) return; + receive_address.copyToClipboard(); + qrcode.ToolTip.show(qsTr('id_address_copied_to_clipboard'), 1000); + } + } + + Action { + id: copy_uri_action + enabled: !wallet.network.liquid + text: qsTrId('id_copy_uri') + onTriggered: { + if (receive_address.generating) return; + receive_address.copyUriToClipboard(); + qrcode.ToolTip.show(qsTr('id_copied_to_clipboard'), 1000); + } + } + RowLayout { SectionLabel { text: qsTrId('id_scan_to_send_here') Layout.fillWidth: true } ToolButton { - icon.source: 'assets/svg/refresh.svg' - icon.width: 16 - icon.height: 16 - onClicked: receive_address.generate() + action: refresh_action } } QRCode { id: qrcode opacity: receive_address.generating ? 0 : 1.0 - text: url(address, parseAmount(amount_field.text) / 100000000) + text: receive_address.uri Layout.alignment: Qt.AlignHCenter Behavior on opacity { OpacityAnimator { duration: 200 } @@ -68,7 +79,6 @@ ColumnLayout { RowLayout { Label { - id: address_field text: receive_address.address horizontalAlignment: Label.AlignHCenter verticalAlignment: Label.AlignVCenter @@ -76,13 +86,22 @@ ColumnLayout { Layout.minimumWidth: 400 } ToolButton { + enabled: !receive_address.generating icon.source: 'assets/svg/copy_to_clipboard.svg' icon.width: 16 icon.height: 16 - onClicked: copyAddress() + onClicked: copy_menu.open() + Menu { + id: copy_menu + MenuItem { + action: copy_address_action + } + MenuItem { + action: copy_uri_action + } + } } } - SectionLabel { text: qsTrId('id_add_amount_optional') } diff --git a/src/account.cpp b/src/account.cpp index 95eb39278..d3d7d40a2 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -169,30 +169,67 @@ void ReceiveAddress::setAccount(Account *account) generate(); } +QString ReceiveAddress::amount() const +{ + return m_amount; +} + +void ReceiveAddress::setAmount(const QString& amount) +{ + if (m_amount == amount) return; + m_amount = amount; + emit changed(); +} + QString ReceiveAddress::address() const { return m_address; } +QString ReceiveAddress::uri() const +{ + if (!m_account || m_generating) return {}; + const auto wallet = m_account->wallet(); + auto unit = wallet->settings().value("unit").toString(); + unit = unit == "\u00B5BTC" ? "ubtc" : unit.toLower(); + auto amount = m_amount; + amount.replace(',', '.'); + amount = wallet->convert({{ unit, amount }}).value("btc").toString(); + if (amount.toDouble() > 0) { + return QString("%1:%2?amount=%3") + .arg(wallet->network()->data().value("bip21_prefix").toString()) + .arg(m_address) + .arg(amount); + } else { + return m_address; + } +} + bool ReceiveAddress::generating() const { return m_generating; } +void ReceiveAddress::setGenerating(bool generating) +{ + if (m_generating == generating) return; + m_generating = generating; + emit generatingChanged(m_generating); +} + void ReceiveAddress::generate() { if (m_account->m_wallet->isLocked()) return; if (!m_account && !m_address.isEmpty()) { m_address.clear(); - emit addressChanged(m_address); + emit changed(); return; } if (m_generating) return; - m_generating = true; - emit generatingChanged(true); + setGenerating(true); QMetaObject::invokeMethod(m_account->m_wallet->m_context, [this] { auto result = GA::process_auth([&] (GA_auth_handler** call) { @@ -208,9 +245,8 @@ void ReceiveAddress::generate() }); Q_ASSERT(result.value("status").toString() == "done"); m_address = result.value("result").toObject().value("address").toString(); - m_generating = false; - emit generatingChanged(true); - emit addressChanged(m_address); + setGenerating(false); + emit changed(); }); } @@ -218,3 +254,8 @@ void ReceiveAddress::copyToClipboard() { QGuiApplication::clipboard()->setText(m_address); } + +void ReceiveAddress::copyUriToClipboard() const +{ + QGuiApplication::clipboard()->setText(uri()); +} diff --git a/src/account.h b/src/account.h index 6b0edec4b..e51041e1d 100644 --- a/src/account.h +++ b/src/account.h @@ -69,29 +69,40 @@ class ReceiveAddress : public QObject { Q_OBJECT Q_PROPERTY(Account* account READ account WRITE setAccount NOTIFY accountChanged) - Q_PROPERTY(QString address READ address NOTIFY addressChanged) + Q_PROPERTY(QString amount READ amount WRITE setAmount NOTIFY changed) + Q_PROPERTY(QString address READ address NOTIFY changed) + Q_PROPERTY(QString uri READ uri NOTIFY changed) Q_PROPERTY(bool generating READ generating NOTIFY generatingChanged) public: explicit ReceiveAddress(QObject* parent = nullptr); Account* account() const; + void setAccount(Account* account); + + QString amount() const; + void setAmount(const QString& amount); + QString address() const; - bool generating() const; - void setAccount(Account* account); + QString uri() const; + + bool generating() const; + void setGenerating(bool generating); public slots: void generate(); void copyToClipboard(); + void copyUriToClipboard() const; signals: void accountChanged(Account* account); - void addressChanged(QString address); + void changed(); void generatingChanged(bool generating); public: Account* m_account{nullptr}; + QString m_amount; QString m_address; bool m_generating{false}; }; diff --git a/src/dialogs/ReceiveDialog.qml b/src/dialogs/ReceiveDialog.qml index 024ce8bff..4840bb581 100644 --- a/src/dialogs/ReceiveDialog.qml +++ b/src/dialogs/ReceiveDialog.qml @@ -42,6 +42,5 @@ Dialog { onClicked: reject() } } - ReceiveView { } }