mirror of
https://github.com/feather-wallet/feather.git
synced 2024-12-23 03:59:29 +00:00
PaymentRequestDialog
This commit is contained in:
parent
3767e736c2
commit
e512e539b6
11 changed files with 368 additions and 1 deletions
|
@ -7,6 +7,7 @@
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "dialog/PaymentRequestDialog.h"
|
||||||
#include "dialog/QrCodeDialog.h"
|
#include "dialog/QrCodeDialog.h"
|
||||||
#include "model/ModelUtils.h"
|
#include "model/ModelUtils.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
|
@ -60,6 +61,8 @@ ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||||
|
|
||||||
connect(ui->check_showUsed, &QCheckBox::clicked, this, &ReceiveWidget::setShowUsedAddresses);
|
connect(ui->check_showUsed, &QCheckBox::clicked, this, &ReceiveWidget::setShowUsedAddresses);
|
||||||
connect(ui->check_showHidden, &QCheckBox::clicked, this, &ReceiveWidget::setShowHiddenAddresses);
|
connect(ui->check_showHidden, &QCheckBox::clicked, this, &ReceiveWidget::setShowHiddenAddresses);
|
||||||
|
|
||||||
|
connect(ui->btn_createPaymentRequest, &QPushButton::clicked, this, &ReceiveWidget::createPaymentRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReceiveWidget::setSearchbarVisible(bool visible) {
|
void ReceiveWidget::setSearchbarVisible(bool visible) {
|
||||||
|
@ -118,6 +121,18 @@ void ReceiveWidget::showContextMenu(const QPoint &point) {
|
||||||
menu->popup(ui->addresses->viewport()->mapToGlobal(point));
|
menu->popup(ui->addresses->viewport()->mapToGlobal(point));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReceiveWidget::createPaymentRequest() {
|
||||||
|
QModelIndex index = ui->addresses->currentIndex();
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString address = index.model()->data(index.siblingAtColumn(SubaddressModel::Address), Qt::UserRole).toString();
|
||||||
|
|
||||||
|
PaymentRequestDialog dialog{this, m_ctx, address};
|
||||||
|
dialog.exec();
|
||||||
|
}
|
||||||
|
|
||||||
void ReceiveWidget::onShowTransactions() {
|
void ReceiveWidget::onShowTransactions() {
|
||||||
QModelIndex index = ui->addresses->currentIndex();
|
QModelIndex index = ui->addresses->currentIndex();
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
|
@ -190,6 +205,7 @@ void ReceiveWidget::updateQrCode(){
|
||||||
QModelIndex index = ui->addresses->currentIndex();
|
QModelIndex index = ui->addresses->currentIndex();
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
ui->qrCode->clear();
|
ui->qrCode->clear();
|
||||||
|
ui->btn_createPaymentRequest->hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +215,7 @@ void ReceiveWidget::updateQrCode(){
|
||||||
int width = ui->qrCode->width() - 4;
|
int width = ui->qrCode->width() - 4;
|
||||||
if (qrc.isValid()) {
|
if (qrc.isValid()) {
|
||||||
ui->qrCode->setPixmap(qrc.toPixmap(1).scaled(width, width, Qt::KeepAspectRatio));
|
ui->qrCode->setPixmap(qrc.toPixmap(1).scaled(width, width, Qt::KeepAspectRatio));
|
||||||
|
ui->btn_createPaymentRequest->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ public slots:
|
||||||
void setShowHiddenAddresses(bool show);
|
void setShowHiddenAddresses(bool show);
|
||||||
void setSearchFilter(const QString &filter);
|
void setSearchFilter(const QString &filter);
|
||||||
void onShowTransactions();
|
void onShowTransactions();
|
||||||
|
void createPaymentRequest();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void showTransactions(const QString& address);
|
void showTransactions(const QString& address);
|
||||||
|
|
|
@ -69,6 +69,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_createPaymentRequest">
|
||||||
|
<property name="text">
|
||||||
|
<string>Payment Request</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_4">
|
<spacer name="verticalSpacer_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
82
src/dialog/PaymentRequestDialog.cpp
Normal file
82
src/dialog/PaymentRequestDialog.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020-2021, The Monero Project.
|
||||||
|
|
||||||
|
#include "PaymentRequestDialog.h"
|
||||||
|
#include "ui_PaymentRequestDialog.h"
|
||||||
|
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QRegExpValidator>
|
||||||
|
|
||||||
|
#include "WalletManager.h"
|
||||||
|
|
||||||
|
PaymentRequestDialog::PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::PaymentRequestDialog)
|
||||||
|
, m_ctx(std::move(ctx))
|
||||||
|
, m_address(std::move(address))
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
QString amount_rx = R"(^\d{0,8}[\.]\d{0,12}|(all)$)";
|
||||||
|
QRegExp rx;
|
||||||
|
rx.setPattern(amount_rx);
|
||||||
|
QValidator *validator = new QRegExpValidator(rx, this);
|
||||||
|
ui->line_amountXMR->setValidator(validator);
|
||||||
|
|
||||||
|
connect(ui->line_amountXMR, &QLineEdit::textChanged, this, &PaymentRequestDialog::updatePaymentRequest);
|
||||||
|
connect(ui->line_description, &QLineEdit::textChanged, this, &PaymentRequestDialog::updatePaymentRequest);
|
||||||
|
connect(ui->line_recipient, &QLineEdit::textChanged, this, &PaymentRequestDialog::updatePaymentRequest);
|
||||||
|
|
||||||
|
connect(ui->btn_copyLink, &QPushButton::clicked, this, &PaymentRequestDialog::copyLink);
|
||||||
|
connect(ui->btn_copyImage, &QPushButton::clicked, this, &PaymentRequestDialog::copyImage);
|
||||||
|
connect(ui->btn_saveImage, &QPushButton::clicked, this, &PaymentRequestDialog::saveImage);
|
||||||
|
|
||||||
|
this->updatePaymentRequest();
|
||||||
|
|
||||||
|
ui->line_amountXMR->setFocus();
|
||||||
|
|
||||||
|
this->adjustSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaymentRequestDialog::updatePaymentRequest() {
|
||||||
|
QString description = ui->line_description->text();
|
||||||
|
QString recipient = ui->line_recipient->text();
|
||||||
|
quint64 amount = WalletManager::amountFromString(ui->line_amountXMR->text());
|
||||||
|
|
||||||
|
QString uri = m_ctx->wallet->make_uri(m_address, amount, description, recipient);
|
||||||
|
|
||||||
|
ui->line_paymentRequestUri->setText(uri);
|
||||||
|
ui->line_paymentRequestUri->setCursorPosition(0);
|
||||||
|
|
||||||
|
// TODO: memory leak, cba to refactor now
|
||||||
|
m_qrCode = new QrCode(uri, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::MEDIUM);
|
||||||
|
if (m_qrCode->isValid()) {
|
||||||
|
ui->qrWidget->setQrCode(m_qrCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaymentRequestDialog::copyLink() {
|
||||||
|
Utils::copyToClipboard(ui->line_paymentRequestUri->text());
|
||||||
|
QMessageBox::information(this, "Information", "Payment request link copied to clipboard.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaymentRequestDialog::copyImage() {
|
||||||
|
QApplication::clipboard()->setPixmap(m_qrCode->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio));
|
||||||
|
QMessageBox::information(this, "Information", "QR code copied to clipboard.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaymentRequestDialog::saveImage() {
|
||||||
|
QString filename = QFileDialog::getSaveFileName(this, "Select where to save file", QDir::current().filePath("qrcode.png"));
|
||||||
|
if (filename.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(filename);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
m_qrCode->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio).save(&file, "PNG");
|
||||||
|
QMessageBox::information(this, "Information", "QR code saved to file");
|
||||||
|
}
|
||||||
|
|
||||||
|
PaymentRequestDialog::~PaymentRequestDialog() = default;
|
37
src/dialog/PaymentRequestDialog.h
Normal file
37
src/dialog/PaymentRequestDialog.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020-2021, The Monero Project.
|
||||||
|
|
||||||
|
#ifndef FEATHER_PAYMENTREQUESTDIALOG_H
|
||||||
|
#define FEATHER_PAYMENTREQUESTDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
#include "appcontext.h"
|
||||||
|
#include "qrcode/QrCode.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class PaymentRequestDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaymentRequestDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address);
|
||||||
|
~PaymentRequestDialog() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updatePaymentRequest();
|
||||||
|
void copyLink();
|
||||||
|
void copyImage();
|
||||||
|
void saveImage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QScopedPointer<Ui::PaymentRequestDialog> ui;
|
||||||
|
QSharedPointer<AppContext> m_ctx;
|
||||||
|
QString m_address;
|
||||||
|
QrCode *m_qrCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FEATHER_PAYMENTREQUESTDIALOG_H
|
203
src/dialog/PaymentRequestDialog.ui
Normal file
203
src/dialog/PaymentRequestDialog.ui
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>PaymentRequestDialog</class>
|
||||||
|
<widget class="QDialog" name="PaymentRequestDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>658</width>
|
||||||
|
<height>761</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Create Payment Request</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QrCodeWidget" name="qrWidget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="line_paymentRequestUri">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Amount:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="line_amountXMR">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>XMR</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Description:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="line_description"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Your name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="line_recipient"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_copyLink">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy Link</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_copyImage">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy Image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_saveImage">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save Image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>QrCodeWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets/QrCodeWidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>PaymentRequestDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>PaymentRequestDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -1150,6 +1150,14 @@ QVariantMap Wallet::parse_uri_to_object(const QString &uri) const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Wallet::make_uri(const QString &address, quint64 &amount, const QString &description,
|
||||||
|
const QString &recipient) const
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
std::string uri = m_walletImpl->make_uri(address.toStdString(), "", amount, description.toStdString(), recipient.toStdString(), error);
|
||||||
|
return QString::fromStdString(uri);
|
||||||
|
}
|
||||||
|
|
||||||
bool Wallet::rescanSpent()
|
bool Wallet::rescanSpent()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_asyncMutex);
|
QMutexLocker locker(&m_asyncMutex);
|
||||||
|
|
|
@ -390,6 +390,8 @@ public:
|
||||||
bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) const;
|
bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error) const;
|
||||||
QVariantMap parse_uri_to_object(const QString &uri) const;
|
QVariantMap parse_uri_to_object(const QString &uri) const;
|
||||||
|
|
||||||
|
QString make_uri(const QString &address, quint64 &amount, const QString &description, const QString &recipient) const;
|
||||||
|
|
||||||
//! Namespace your cacheAttribute keys to avoid collisions
|
//! Namespace your cacheAttribute keys to avoid collisions
|
||||||
bool setCacheAttribute(const QString &key, const QString &val);
|
bool setCacheAttribute(const QString &key, const QString &val);
|
||||||
QString getCacheAttribute(const QString &key) const;
|
QString getCacheAttribute(const QString &key) const;
|
||||||
|
|
|
@ -58,3 +58,11 @@ void QrCodeWidget::paintEvent(QPaintEvent *event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QrCodeWidget::hasHeightForWidth() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QrCodeWidget::heightForWidth(int w) const {
|
||||||
|
return w;
|
||||||
|
}
|
|
@ -18,6 +18,8 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
int heightForWidth(int w) const override;
|
||||||
|
bool hasHeightForWidth() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QrCode *m_qrcode = nullptr;
|
QrCode *m_qrcode = nullptr;
|
||||||
|
|
Loading…
Reference in a new issue