diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 252b639..dd2d110 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -405,6 +405,9 @@ void MainWindow::initOffline() {
connect(ui->btn_help, &QPushButton::clicked, [this] {
windowManager()->showDocs(this, "offline_tx_signing");
});
+ connect(ui->btn_viewOnlyDetails, &QPushButton::clicked, [this] {
+ this->showViewOnlyDialog();
+ });
connect(ui->btn_checkAddress, &QPushButton::clicked, [this]{
AddressCheckerIndexDialog dialog{m_wallet, this};
dialog.exec();
diff --git a/src/MainWindow.ui b/src/MainWindow.ui
index 477e9f2..e9b390e 100644
--- a/src/MainWindow.ui
+++ b/src/MainWindow.ui
@@ -403,6 +403,13 @@
+ -
+
+
+ View-only details
+
+
+
-
diff --git a/src/dialog/URDialog.cpp b/src/dialog/URDialog.cpp
index 37444c6..370f968 100644
--- a/src/dialog/URDialog.cpp
+++ b/src/dialog/URDialog.cpp
@@ -8,12 +8,29 @@
#include "utils/Utils.h"
-URDialog::URDialog(QWidget *parent)
+URDialog::URDialog(QWidget *parent, const QString &data, bool scanOnly)
: WindowModalDialog(parent)
, ui(new Ui::URDialog)
{
ui->setupUi(this);
+ if (!data.isEmpty()) {
+ ui->btn_loadFile->setVisible(false);
+ ui->btn_loadClipboard->setVisible(false);
+ ui->tabWidget->setTabVisible(1, false);
+
+ QScreen *currentScreen = QApplication::screenAt(this->geometry().center());
+ if (!currentScreen) {
+ currentScreen = QApplication::primaryScreen();
+ }
+ int availableHeight = currentScreen->availableGeometry().height() - 200;
+ this->resize(availableHeight, availableHeight);
+
+ std::string d = data.toStdString();
+ ui->widgetUR->setData("xmr-viewonly", d);
+ return;
+ }
+
connect(ui->btn_loadFile, &QPushButton::clicked, [this]{
QString fn = QFileDialog::getOpenFileName(this, "Load file", QDir::homePath(), "All Files (*)");
if (fn.isEmpty()) {
@@ -41,7 +58,7 @@ URDialog::URDialog(QWidget *parent)
std::string data = qdata.toStdString();
- ui->widgetUR->setData("ana", data);
+ ui->widgetUR->setData("any", data);
});
connect(ui->tabWidget, &QTabWidget::currentChanged, [this](int index){
@@ -51,44 +68,76 @@ URDialog::URDialog(QWidget *parent)
});
connect(ui->widgetScanner, &QrCodeScanWidget::finished, [this](bool success){
- if (!success) {
+ if (!success) {
Utils::showError(this, "Unable to scan UR");
ui->widgetScanner->reset();
return;
- }
+ }
- if (ui->radio_clipboard->isChecked()) {
- Utils::copyToClipboard(QString::fromStdString(ui->widgetScanner->getURData()));
- Utils::showInfo(this, "Data copied to clipboard");
- }
- else if (ui->radio_file->isChecked()) {
- QString fn = QFileDialog::getSaveFileName(this, "Save to file", QDir::homePath(), "ur_data");
- if (fn.isEmpty()) {
- ui->widgetScanner->reset();
- return;
- }
+ if (ui->widgetScanner->getURType() == "xmr-viewonly") {
+ QRegularExpression viewOnlyDetails(
+ "Secret view key: (?[0-9a-f]{64})\nAddress: (?\\w+)\nRestore height: (?\\d+)\nWallet name: (?\\w+)\n",
+ QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+ QString data = QString::fromStdString(ui->widgetScanner->getURData());
+ QRegularExpressionMatch match = viewOnlyDetails.match(data);
- QFile file{fn};
- if (!file.open(QIODevice::WriteOnly)) {
- Utils::showError(this, "Failed to save file", QString("Could not open file %1 for writing").arg(fn));
- ui->widgetScanner->reset();
- return;
- }
+ if (!match.hasMatch()) {
+ Utils::showError(this, "Unable to load view-only details", "Unexpected data");
+ return;
+ }
- std::string data = ui->widgetScanner->getURData();
- file.write(data.data(), data.size());
- file.close();
-
- Utils::showInfo(this, "Successfully saved data to file");
- }
-
- ui->widgetScanner->reset();
+ m_viewOnlyDetails.address = match.captured("address");
+ m_viewOnlyDetails.key = match.captured("key").toLower();
+ m_viewOnlyDetails.restoreHeight = match.captured("restoreheight").toInt();
+ m_viewOnlyDetails.walletName = QString("%1_view_only").arg(match.captured("walletname"));
+
+ this->accept();
+ }
+
+ if (ui->radio_clipboard->isChecked()) {
+ Utils::copyToClipboard(QString::fromStdString(ui->widgetScanner->getURData()));
+ Utils::showInfo(this, "Data copied to clipboard");
+ }
+ else if (ui->radio_file->isChecked()) {
+ QString fn = QFileDialog::getSaveFileName(this, "Save to file", QDir::homePath(), "ur_data");
+ if (fn.isEmpty()) {
+ ui->widgetScanner->reset();
+ return;
+ }
+
+ QFile file{fn};
+ if (!file.open(QIODevice::WriteOnly)) {
+ Utils::showError(this, "Failed to save file", QString("Could not open file %1 for writing").arg(fn));
+ ui->widgetScanner->reset();
+ return;
+ }
+
+ std::string data = ui->widgetScanner->getURData();
+ file.write(data.data(), data.size());
+ file.close();
+
+ Utils::showInfo(this, "Successfully saved data to file");
+ }
+
+ ui->widgetScanner->reset();
});
+ if (scanOnly) {
+ ui->tabWidget->setCurrentIndex(1);
+ ui->tabWidget->setTabVisible(0, false);
+ ui->radio_clipboard->setVisible(false);
+ ui->radio_file->setVisible(false);
+ return;
+ }
+
ui->radio_file->setChecked(true);
ui->tabWidget->setCurrentIndex(0);
this->resize(600, 700);
}
+ViewOnlyDetails URDialog::getViewOnlyDetails() {
+ return m_viewOnlyDetails;
+}
+
URDialog::~URDialog() = default;
\ No newline at end of file
diff --git a/src/dialog/URDialog.h b/src/dialog/URDialog.h
index d7d871b..85aa965 100644
--- a/src/dialog/URDialog.h
+++ b/src/dialog/URDialog.h
@@ -12,16 +12,26 @@ namespace Ui {
class URDialog;
}
+struct ViewOnlyDetails {
+ QString address;
+ QString key;
+ int restoreHeight = 0;
+ QString walletName;
+};
+
class URDialog : public WindowModalDialog
{
Q_OBJECT
public:
- explicit URDialog(QWidget *parent = nullptr);
+ explicit URDialog(QWidget *parent, const QString &data = "", bool scanOnly = false);
~URDialog() override;
+ ViewOnlyDetails getViewOnlyDetails();
+
private:
QScopedPointer ui;
+ ViewOnlyDetails m_viewOnlyDetails;
};
diff --git a/src/dialog/ViewOnlyDialog.cpp b/src/dialog/ViewOnlyDialog.cpp
index 1ea4549..364f6c4 100644
--- a/src/dialog/ViewOnlyDialog.cpp
+++ b/src/dialog/ViewOnlyDialog.cpp
@@ -8,6 +8,7 @@
#include
#include
+#include "URDialog.h"
#include "utils/Utils.h"
ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent)
@@ -23,6 +24,10 @@ ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent)
connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboard);
connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet);
+ connect(ui->btn_transmitOverUR, &QPushButton::clicked, [this] {
+ URDialog dialog{this, this->toString()};
+ dialog.exec();
+ });
if (m_wallet->viewOnly()) {
ui->btn_Save->setEnabled(false);
@@ -52,12 +57,17 @@ void ViewOnlyDialog::onWriteViewOnlyWallet(){
QMessageBox::information(this, "Information", "View-only wallet successfully written to disk.");
}
-void ViewOnlyDialog::copyToClipboard() {
- QString text = "";
- text += QString("Address: %1\n").arg(ui->label_primaryAddress->text());
+QString ViewOnlyDialog::toString() {
+ QString text;
text += QString("Secret view key: %1\n").arg(ui->label_secretViewKey->text());
+ text += QString("Address: %1\n").arg(ui->label_primaryAddress->text());
text += QString("Restore height: %1\n").arg(ui->label_restoreHeight->text());
- Utils::copyToClipboard(text);
+ text += QString("Wallet name: %1\n").arg(m_wallet->walletName());
+ return text;
+}
+
+void ViewOnlyDialog::copyToClipboard() {
+ Utils::copyToClipboard(this->toString());
}
ViewOnlyDialog::~ViewOnlyDialog() = default;
diff --git a/src/dialog/ViewOnlyDialog.h b/src/dialog/ViewOnlyDialog.h
index 08de238..1ba44db 100644
--- a/src/dialog/ViewOnlyDialog.h
+++ b/src/dialog/ViewOnlyDialog.h
@@ -25,6 +25,7 @@ private slots:
void onWriteViewOnlyWallet();
private:
+ QString toString();
void copyToClipboard();
QScopedPointer ui;
diff --git a/src/dialog/ViewOnlyDialog.ui b/src/dialog/ViewOnlyDialog.ui
index 2cdcdb8..a09d9da 100644
--- a/src/dialog/ViewOnlyDialog.ui
+++ b/src/dialog/ViewOnlyDialog.ui
@@ -7,7 +7,7 @@
0
0
659
- 254
+ 260
@@ -15,13 +15,13 @@
-
-
+
- Restore height
+ Secret view key
-
+
-
-
+
TextLabel
@@ -53,13 +53,13 @@
-
-
+
- Secret view key
+ Restore height
-
+
-
-
+
TextLabel
@@ -87,6 +87,13 @@
+ -
+
+
+ Transmit over UR
+
+
+
-
diff --git a/src/qrcode/scanner/QrCodeScanWidget.cpp b/src/qrcode/scanner/QrCodeScanWidget.cpp
index 0c9b6e2..39edf2d 100644
--- a/src/qrcode/scanner/QrCodeScanWidget.cpp
+++ b/src/qrcode/scanner/QrCodeScanWidget.cpp
@@ -233,6 +233,14 @@ std::string QrCodeScanWidget::getURData() {
return data;
}
+std::string QrCodeScanWidget::getURType() {
+ if (!m_decoder.is_success()) {
+ return "";
+ }
+
+ return m_decoder.expected_type().value_or("");
+}
+
QString QrCodeScanWidget::getURError() {
if (!m_decoder.is_failure()) {
return {};
diff --git a/src/qrcode/scanner/QrCodeScanWidget.h b/src/qrcode/scanner/QrCodeScanWidget.h
index 8c8b86f..a239ba4 100644
--- a/src/qrcode/scanner/QrCodeScanWidget.h
+++ b/src/qrcode/scanner/QrCodeScanWidget.h
@@ -29,6 +29,7 @@ public:
QString decodedString = "";
std::string getURData();
+ std::string getURType();
QString getURError();
void startCapture(bool scan_ur = false);
diff --git a/src/wizard/PageSetRestoreHeight.cpp b/src/wizard/PageSetRestoreHeight.cpp
index 55d02ac..22eafba 100644
--- a/src/wizard/PageSetRestoreHeight.cpp
+++ b/src/wizard/PageSetRestoreHeight.cpp
@@ -50,6 +50,12 @@ void PageSetRestoreHeight::initializePage() {
ui->line_creationDate->setText(creationDate.toString("yyyy-MM-dd"));
this->onCreationDateEdited();
}
+
+ if (m_fields->restoreHeight > 0) {
+ ui->line_restoreHeight->setText(QString::number(m_fields->restoreHeight));
+ this->onRestoreHeightEdited();
+ this->completeChanged();
+ }
}
void PageSetRestoreHeight::onCreationDateEdited() {
diff --git a/src/wizard/PageWalletFile.cpp b/src/wizard/PageWalletFile.cpp
index 6acc60c..83a70c4 100644
--- a/src/wizard/PageWalletFile.cpp
+++ b/src/wizard/PageWalletFile.cpp
@@ -42,6 +42,10 @@ void PageWalletFile::initializePage() {
ui->line_walletName->setText(this->defaultWalletName());
ui->check_defaultWalletDirectory->setVisible(false);
ui->check_defaultWalletDirectory->setChecked(false);
+
+ if (!m_fields->walletName.isEmpty()) {
+ ui->line_walletName->setText(m_fields->walletName);
+ }
}
bool PageWalletFile::validateWidgets(){
diff --git a/src/wizard/PageWalletRestoreKeys.cpp b/src/wizard/PageWalletRestoreKeys.cpp
index 4ae5739..ba69415 100644
--- a/src/wizard/PageWalletRestoreKeys.cpp
+++ b/src/wizard/PageWalletRestoreKeys.cpp
@@ -11,6 +11,7 @@
#include "WalletWizard.h"
#include "constants.h"
+#include "dialog/URDialog.h"
#include "libwalletqt/WalletManager.h"
PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *parent)
@@ -41,6 +42,17 @@ PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *pare
connect(ui->btnOptions, &QPushButton::clicked, this, &PageWalletRestoreKeys::onOptionsClicked);
connect(ui->combo_walletType, &QComboBox::currentTextChanged, this, &PageWalletRestoreKeys::showInputLines);
+ connect(ui->btn_scanUR, &QPushButton::clicked, [this] {
+ URDialog dialog{this, "", true};
+ dialog.exec();
+ ViewOnlyDetails details = dialog.getViewOnlyDetails();
+ ui->line_address->setText(details.address);
+ ui->line_address->setCursorPosition(0);
+ ui->line_viewkey->setText(details.key);
+ ui->line_viewkey->setCursorPosition(0);
+ m_fields->restoreHeight = details.restoreHeight;
+ m_fields->walletName = details.walletName;
+ });
}
void PageWalletRestoreKeys::initializePage() {
diff --git a/src/wizard/PageWalletRestoreKeys.ui b/src/wizard/PageWalletRestoreKeys.ui
index 21b9f05..716c06f 100644
--- a/src/wizard/PageWalletRestoreKeys.ui
+++ b/src/wizard/PageWalletRestoreKeys.ui
@@ -215,6 +215,13 @@
+ -
+
+
+ Scan UR
+
+
+
-