Merge pull request 'Beta-8' (#369) from tobtoht/feather:filename into master

Reviewed-on: https://git.featherwallet.org/feather/feather/pulls/369
This commit is contained in:
tobtoht 2021-07-08 16:48:30 +00:00
commit c7290df5fc
216 changed files with 2671 additions and 1672 deletions

View file

@ -2,3 +2,4 @@
!contrib/Qt5.15_LinuxPatch.json !contrib/Qt5.15_LinuxPatch.json
!utils/pubkeys/* !utils/pubkeys/*
!contrib/build-deps/verify-packages.sh !contrib/build-deps/verify-packages.sh
!contrib/monero-seed.patch

View file

@ -22,7 +22,7 @@ git clone --branch master --recursive https://git.featherwallet.org/feather/feat
cd feather cd feather
``` ```
Replace `master` with the desired version tag (e.g. `beta-7`) to build the release binary. Replace `master` with the desired version tag (e.g. `beta-8`) to build the release binary.
#### 2. Base image #### 2. Base image
@ -63,7 +63,7 @@ git clone --branch master --recursive https://git.featherwallet.org/feather/feat
cd feather cd feather
``` ```
Replace `master` with the desired version tag (e.g. `beta-7`) to build the release binary. Replace `master` with the desired version tag (e.g. `beta-8`) to build the release binary.
#### 2. Base image #### 2. Base image

View file

@ -7,7 +7,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
set(VERSION_MAJOR "0") set(VERSION_MAJOR "0")
set(VERSION_MINOR "1") set(VERSION_MINOR "1")
set(VERSION_REVISION "0") set(VERSION_REVISION "0")
set(VERSION "beta-7") set(VERSION "beta-8")
option(STATIC "Link libraries statically, requires static Qt") option(STATIC "Link libraries statically, requires static Qt")
@ -17,7 +17,7 @@ option(LOCALMONERO "Include LocalMonero module" ON)
option(XMRIG "Include XMRig module" ON) option(XMRIG "Include XMRig module" ON)
option(TOR_BIN "Path to Tor binary to embed inside Feather" OFF) option(TOR_BIN "Path to Tor binary to embed inside Feather" OFF)
option(CHECK_UPDATES "Enable checking for application updates" OFF) option(CHECK_UPDATES "Enable checking for application updates" OFF)
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF) option(USE_DEVICE_TREZOR "Trezor support compilation" ON)
option(DONATE_BEG "Prompt donation window every once in a while" ON) option(DONATE_BEG "Prompt donation window every once in a while" ON)
option(WITH_SCANNER "Enable webcam QR scanner" OFF) option(WITH_SCANNER "Enable webcam QR scanner" OFF)
@ -34,7 +34,7 @@ if(DEBUG)
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
endif() endif()
set(MONERO_HEAD "36fb05da3394505f8033ceb8806b28909617696f") set(MONERO_HEAD "9c1a80a642c37f7d6ee5c14b774bbb38e6cb9c52")
set(BUILD_GUI_DEPS ON) set(BUILD_GUI_DEPS ON)
set(ARCH "x86-64") set(ARCH "x86-64")
set(BUILD_64 ON) set(BUILD_64 ON)
@ -73,6 +73,8 @@ add_subdirectory(monero)
set_property(TARGET wallet_merged PROPERTY FOLDER "monero") set_property(TARGET wallet_merged PROPERTY FOLDER "monero")
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH) get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY) get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY)
get_directory_property(DEVICE_TREZOR_READY DIRECTORY "monero" DEFINITION DEVICE_TREZOR_READY)
get_directory_property(TREZOR_DEP_LIBS DIRECTORY "monero" DEFINITION TREZOR_DEP_LIBS)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
include(VersionMonero) include(VersionMonero)

View file

@ -266,9 +266,11 @@ RUN git clone -b v4.1.1 --depth 1 https://github.com/fukuchi/libqrencode.git &&
# monero-seed: Required for Feather # monero-seed: Required for Feather
# Tevador's 14 word seed library # Tevador's 14 word seed library
ADD contrib/monero-seed.patch .
RUN git clone https://git.featherwallet.org/feather/monero-seed.git && \ RUN git clone https://git.featherwallet.org/feather/monero-seed.git && \
cd monero-seed && \ cd monero-seed && \
git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \ git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \
git apply /monero-seed.patch && \
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \ cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
make -Cbuild -j$THREADS && \ make -Cbuild -j$THREADS && \
make -Cbuild install && \ make -Cbuild install && \

View file

@ -39,7 +39,7 @@ CMAKEFLAGS = \
-DINSTALL_VENDORED_LIBUNBOUND=Off \ -DINSTALL_VENDORED_LIBUNBOUND=Off \
-DMANUAL_SUBMODULES=1 \ -DMANUAL_SUBMODULES=1 \
-DSTATIC=On \ -DSTATIC=On \
-DUSE_DEVICE_TREZOR=Off \ -DUSE_DEVICE_TREZOR=On \
$(CMAKEFLAGS_EXTRA) $(CMAKEFLAGS_EXTRA)
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64" release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"

37
contrib/monero-seed.patch Normal file
View file

@ -0,0 +1,37 @@
diff --git a/src/argon2/blake2/blake2.h b/src/argon2/blake2/blake2.h
index 9f97e1c..469e8fe 100644
--- a/src/argon2/blake2/blake2.h
+++ b/src/argon2/blake2/blake2.h
@@ -66,6 +66,14 @@ enum {
1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)
};
+#define blake2b_init moneroseed_blake2b_init
+#define blake2b_init_key moneroseed_blake2b_init_key
+#define blake2b_init_param moneroseed_blake2b_init_param
+#define blake2b_update moneroseed_blake2b_update
+#define blake2b_final moneroseed_blake2b_final
+#define blake2b moneroseed_blake2b
+#define blake2b_long moneroseed_blake2b_long
+
/* Streaming API */
ARGON2_LOCAL int blake2b_init(blake2b_state *S, size_t outlen);
ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
diff --git a/src/argon2/core.h b/src/argon2/core.h
index 78000ba..e569eb4 100644
--- a/src/argon2/core.h
+++ b/src/argon2/core.h
@@ -101,6 +101,13 @@ typedef struct Argon2_thread_data {
/*************************Argon2 core functions********************************/
+#define finalize moneroseed_finalize
+#define initialize moneroseed_initialize
+#define validate_inputs moneroseed_validate_inputs
+#define fill_first_blocks moneroseed_fill_first_blocks
+#define initial_hash moneroseed_initial_hash
+#define fill_memory_blocks moneroseed_fill_memory_blocks
+
/* Allocates memory to the given pointer, uses the appropriate allocator as
* specified in the context. Total allocated memory is num*size.
* @param context argon2_context which specifies the allocator

View file

@ -250,6 +250,10 @@ target_link_libraries(feather
${LIBZIP_LIBRARIES} ${LIBZIP_LIBRARIES}
) )
if(DEVICE_TREZOR_READY)
target_link_libraries(feather ${TREZOR_DEP_LIBS})
endif()
if (WITH_SCANNER) if (WITH_SCANNER)
target_link_libraries(feather target_link_libraries(feather
Qt5::Multimedia Qt5::Multimedia

View file

@ -1,14 +1,15 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "CalcWidget.h"
#include "ui_CalcWidget.h"
#include <QList> #include <QList>
#include "calcwidget.h"
#include "ui_calcwidget.h"
#include "utils/ColorScheme.h"
#include "utils/AppData.h"
#include "utils/config.h"
#include "dialog/CalcConfigDialog.h" #include "dialog/CalcConfigDialog.h"
#include "utils/AppData.h"
#include "utils/ColorScheme.h"
#include "utils/config.h"
CalcWidget::CalcWidget(QWidget *parent) CalcWidget::CalcWidget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
@ -144,6 +145,4 @@ void CalcWidget::setupComboBox(QComboBox *comboBox, const QStringList &crypto, c
comboBox->addItems(fiat); comboBox->addItems(fiat);
} }
CalcWidget::~CalcWidget() { CalcWidget::~CalcWidget() = default;
delete ui;
}

View file

@ -31,7 +31,7 @@ private:
void convert(bool reverse); void convert(bool reverse);
void setupComboBox(QComboBox *comboBox, const QStringList &crypto, const QStringList &fiat); void setupComboBox(QComboBox *comboBox, const QStringList &crypto, const QStringList &fiat);
Ui::CalcWidget *ui; QScopedPointer<Ui::CalcWidget> ui;
bool m_comboBoxInit = false; bool m_comboBoxInit = false;
}; };

View file

@ -1,12 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "calcwindow.h" #include "CalcWindow.h"
#include "mainwindow.h" #include "ui_CalcWindow.h"
#include "utils/Icons.h"
#include "utils/AppData.h"
#include "ui_calcwindow.h" #include "utils/AppData.h"
#include "utils/Icons.h"
CalcWindow::CalcWindow(QWidget *parent) CalcWindow::CalcWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@ -23,6 +22,4 @@ void CalcWindow::closeEvent(QCloseEvent *foo) {
emit closed(); emit closed();
} }
CalcWindow::~CalcWindow() { CalcWindow::~CalcWindow() = default;
delete ui;
}

View file

@ -1,8 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef CalcWindow_H #ifndef FEATHER_CALCWINDOW_H
#define CalcWindow_H #define FEATHER_CALCWINDOW_H
#include <QMainWindow> #include <QMainWindow>
@ -25,7 +25,7 @@ private:
void closeEvent(QCloseEvent *bar) override; void closeEvent(QCloseEvent *bar) override;
private: private:
Ui::CalcWindow *ui; QScopedPointer<Ui::CalcWindow> ui;
}; };
#endif // CalcWindow_H #endif // FEATHER_CALCWINDOW_H

View file

@ -37,7 +37,7 @@
<customwidget> <customwidget>
<class>CalcWidget</class> <class>CalcWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>calcwidget.h</header> <header>CalcWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View file

@ -1,16 +1,15 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "coinswidget.h" #include "CoinsWidget.h"
#include "ui_coinswidget.h" #include "ui_CoinsWidget.h"
#include "dialog/outputinfodialog.h"
#include "dialog/outputsweepdialog.h"
#include "mainwindow.h"
#include "utils/Icons.h"
#include <QClipboard>
#include <QMessageBox> #include <QMessageBox>
#include "dialog/OutputInfoDialog.h"
#include "dialog/OutputSweepDialog.h"
#include "utils/Icons.h"
CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent) CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::CoinsWidget) , ui(new Ui::CoinsWidget)
@ -39,6 +38,9 @@ CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
// context menu // context menu
ui->coins->setContextMenuPolicy(Qt::CustomContextMenu); ui->coins->setContextMenuPolicy(Qt::CustomContextMenu);
m_editLabelAction = new QAction("Edit Label", this);
connect(m_editLabelAction, &QAction::triggered, this, &CoinsWidget::editLabel);
m_thawOutputAction = new QAction("Thaw output", this); m_thawOutputAction = new QAction("Thaw output", this);
m_freezeOutputAction = new QAction("Freeze output", this); m_freezeOutputAction = new QAction("Freeze output", this);
@ -47,16 +49,26 @@ CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
m_viewOutputAction = new QAction(icons()->icon("info2.svg"), "Details", this); m_viewOutputAction = new QAction(icons()->icon("info2.svg"), "Details", this);
m_sweepOutputAction = new QAction("Sweep output", this); m_sweepOutputAction = new QAction("Sweep output", this);
m_sweepOutputsAction = new QAction("Sweep selected outputs", this);
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput); connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput);
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput); connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput); connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
connect(m_sweepOutputAction, &QAction::triggered, this, &CoinsWidget::onSweepOutput); connect(m_sweepOutputAction, &QAction::triggered, this, &CoinsWidget::onSweepOutputs);
connect(m_sweepOutputsAction, &QAction::triggered, this, &CoinsWidget::onSweepOutputs);
connect(m_freezeAllSelectedAction, &QAction::triggered, this, &CoinsWidget::freezeAllSelected); connect(m_freezeAllSelectedAction, &QAction::triggered, this, &CoinsWidget::freezeAllSelected);
connect(m_thawAllSelectedAction, &QAction::triggered, this, &CoinsWidget::thawAllSelected); connect(m_thawAllSelectedAction, &QAction::triggered, this, &CoinsWidget::thawAllSelected);
connect(ui->coins, &QTreeView::customContextMenuRequested, this, &CoinsWidget::showContextMenu); connect(ui->coins, &QTreeView::customContextMenuRequested, this, &CoinsWidget::showContextMenu);
connect(ui->coins, &QTreeView::doubleClicked, this, &CoinsWidget::viewOutput); connect(ui->coins, &QTreeView::doubleClicked, [this](QModelIndex index){
if (!m_model) return;
if (!(m_model->flags(index) & Qt::ItemIsEditable)) {
this->viewOutput();
}
});
connect(ui->search, &QLineEdit::textChanged, this, &CoinsWidget::setSearchFilter);
} }
void CoinsWidget::setModel(CoinsModel * model, Coins * coins) { void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
@ -76,11 +88,20 @@ void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
} }
ui->coins->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->coins->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->coins->header()->setSectionResizeMode(CoinsModel::AddressLabel, QHeaderView::Stretch); ui->coins->header()->setSectionResizeMode(CoinsModel::Label, QHeaderView::Stretch);
ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder); ui->coins->header()->setSortIndicator(CoinsModel::BlockHeight, Qt::DescendingOrder);
ui->coins->setSortingEnabled(true); ui->coins->setSortingEnabled(true);
} }
void CoinsWidget::setSearchbarVisible(bool visible) {
ui->search->setVisible(visible);
}
void CoinsWidget::focusSearchbar() {
ui->search->setFocusPolicy(Qt::StrongFocus);
ui->search->setFocus();
}
void CoinsWidget::showContextMenu(const QPoint &point) { void CoinsWidget::showContextMenu(const QPoint &point) {
QModelIndexList list = ui->coins->selectionModel()->selectedRows(); QModelIndexList list = ui->coins->selectionModel()->selectedRows();
@ -88,6 +109,7 @@ void CoinsWidget::showContextMenu(const QPoint &point) {
if (list.size() > 1) { if (list.size() > 1) {
menu->addAction(m_freezeAllSelectedAction); menu->addAction(m_freezeAllSelectedAction);
menu->addAction(m_thawAllSelectedAction); menu->addAction(m_thawAllSelectedAction);
menu->addAction(m_sweepOutputsAction);
} }
else { else {
CoinsInfo* c = this->currentEntry(); CoinsInfo* c = this->currentEntry();
@ -98,6 +120,7 @@ void CoinsWidget::showContextMenu(const QPoint &point) {
bool isUnlocked = c->unlocked(); bool isUnlocked = c->unlocked();
menu->addMenu(m_copyMenu); menu->addMenu(m_copyMenu);
menu->addAction(m_editLabelAction);
if (!isSpent) { if (!isSpent) {
isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction); isFrozen ? menu->addAction(m_thawOutputAction) : menu->addAction(m_freezeOutputAction);
@ -127,6 +150,11 @@ void CoinsWidget::setShowSpent(bool show)
m_proxyModel->setShowSpent(show); m_proxyModel->setShowSpent(show);
} }
void CoinsWidget::setSearchFilter(const QString &filter) {
if (!m_proxyModel) return;
m_proxyModel->setSearchFilter(filter);
}
void CoinsWidget::freezeOutput() { void CoinsWidget::freezeOutput() {
QModelIndex index = ui->coins->currentIndex(); QModelIndex index = ui->coins->currentIndex();
QVector<int> indexes = {m_proxyModel->mapToSource(index).row()}; QVector<int> indexes = {m_proxyModel->mapToSource(index).row()};
@ -167,23 +195,46 @@ void CoinsWidget::viewOutput() {
dialog->show(); dialog->show();
} }
void CoinsWidget::onSweepOutput() { void CoinsWidget::onSweepOutputs() {
CoinsInfo* c = this->currentEntry(); QVector<CoinsInfo*> selectedCoins = this->currentEntries();
if (!c) return; QVector<QString> keyImages;
QString keyImage = c->keyImage(); quint64 totalAmount = 0;
for (const auto coin : selectedCoins) {
if (!coin) return;
if (!c->keyImageKnown()) { QString keyImage = coin->keyImage();
QMessageBox::warning(this, "Unable to sweep output", "Unable to sweep output: key image unknown"); if (!coin->keyImageKnown()) {
QMessageBox::warning(this, "Unable to sweep outputs", "Unable to create transaction: selected output has unknown key image");
return; return;
} }
auto *dialog = new OutputSweepDialog(this, c); if (coin->spent()) {
int ret = dialog->exec(); QMessageBox::warning(this, "Unable to sweep outputs", "Unable to create transaction: selected output was already spent");
return;
}
if (coin->frozen()) {
QMessageBox::warning(this, "Unable to sweep outputs", "Unable to create transaction: selected output is frozen.\n\n"
"Thaw the selected output(s) before spending.");
return;
}
if (!coin->unlocked()) {
QMessageBox::warning(this, "Unable to sweep outputs", "Unable to create transaction: selected output is locked.\n\n"
"Wait until the output has reached the required number of confirmation before spending.");
return;
}
keyImages.push_back(keyImage);
totalAmount += coin->amount();
}
OutputSweepDialog dialog{this, totalAmount};
int ret = dialog.exec();
if (!ret) return; if (!ret) return;
m_ctx->onSweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs()); m_ctx->onSweepOutputs(keyImages, dialog.address(), dialog.churn(), dialog.outputs());
dialog->deleteLater();
} }
void CoinsWidget::copy(copyField field) { void CoinsWidget::copy(copyField field) {
@ -204,9 +255,13 @@ void CoinsWidget::copy(copyField field) {
case Address: case Address:
data = c->address(); data = c->address();
break; break;
case Label: case Label: {
if (!c->description().isEmpty())
data = c->description();
else
data = c->addressLabel(); data = c->addressLabel();
break; break;
}
case Height: case Height:
data = QString::number(c->blockHeight()); data = QString::number(c->blockHeight());
break; break;
@ -227,6 +282,15 @@ CoinsInfo* CoinsWidget::currentEntry() {
} }
} }
QVector<CoinsInfo*> CoinsWidget::currentEntries() {
QModelIndexList list = ui->coins->selectionModel()->selectedRows();
QVector<CoinsInfo*> selectedCoins;
for (const auto index : list) {
selectedCoins.push_back(m_model->entryFromIndex(m_proxyModel->mapToSource(index)));
}
return selectedCoins;
}
void CoinsWidget::freezeCoins(const QVector<int>& indexes) { void CoinsWidget::freezeCoins(const QVector<int>& indexes) {
for (int i : indexes) { for (int i : indexes) {
m_ctx->wallet->coins()->freeze(i); m_ctx->wallet->coins()->freeze(i);
@ -243,6 +307,10 @@ void CoinsWidget::thawCoins(const QVector<int> &indexes) {
m_ctx->updateBalance(); m_ctx->updateBalance();
} }
CoinsWidget::~CoinsWidget() { void CoinsWidget::editLabel() {
delete ui; QModelIndex index = ui->coins->currentIndex().siblingAtColumn(m_model->ModelColumn::Label);
ui->coins->setCurrentIndex(index);
ui->coins->edit(index);
} }
CoinsWidget::~CoinsWidget() = default;

View file

@ -4,15 +4,15 @@
#ifndef FEATHER_COINSWIDGET_H #ifndef FEATHER_COINSWIDGET_H
#define FEATHER_COINSWIDGET_H #define FEATHER_COINSWIDGET_H
#include <QMenu>
#include <QWidget>
#include <QtSvg/QSvgWidget>
#include "appcontext.h" #include "appcontext.h"
#include "model/CoinsModel.h" #include "model/CoinsModel.h"
#include "model/CoinsProxyModel.h" #include "model/CoinsProxyModel.h"
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include <QMenu>
#include <QWidget>
#include <QtSvg/QSvgWidget>
namespace Ui { namespace Ui {
class CoinsWidget; class CoinsWidget;
} }
@ -26,6 +26,10 @@ public:
void setModel(CoinsModel * model, Coins * coins); void setModel(CoinsModel * model, Coins * coins);
~CoinsWidget() override; ~CoinsWidget() override;
public slots:
void setSearchbarVisible(bool visible);
void focusSearchbar();
private slots: private slots:
void showHeaderMenu(const QPoint& position); void showHeaderMenu(const QPoint& position);
void setShowSpent(bool show); void setShowSpent(bool show);
@ -34,7 +38,9 @@ private slots:
void thawOutput(); void thawOutput();
void thawAllSelected(); void thawAllSelected();
void viewOutput(); void viewOutput();
void onSweepOutput(); void onSweepOutputs();
void setSearchFilter(const QString &filter);
void editLabel();
private: private:
void freezeCoins(const QVector<int>& indexes); void freezeCoins(const QVector<int>& indexes);
@ -50,7 +56,7 @@ private:
Amount Amount
}; };
Ui::CoinsWidget *ui; QScopedPointer<Ui::CoinsWidget> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
QMenu *m_contextMenu; QMenu *m_contextMenu;
@ -63,6 +69,8 @@ private:
QAction *m_thawAllSelectedAction; QAction *m_thawAllSelectedAction;
QAction *m_viewOutputAction; QAction *m_viewOutputAction;
QAction *m_sweepOutputAction; QAction *m_sweepOutputAction;
QAction *m_sweepOutputsAction;
QAction *m_editLabelAction;
Coins *m_coins; Coins *m_coins;
CoinsModel * m_model; CoinsModel * m_model;
CoinsProxyModel * m_proxyModel; CoinsProxyModel * m_proxyModel;
@ -70,6 +78,7 @@ private:
void showContextMenu(const QPoint & point); void showContextMenu(const QPoint & point);
void copy(copyField field); void copy(copyField field);
CoinsInfo* currentEntry(); CoinsInfo* currentEntry();
QVector<CoinsInfo*> currentEntries();
}; };

View file

@ -29,6 +29,13 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<widget class="QLineEdit" name="search">
<property name="placeholderText">
<string>Search..</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QTreeView" name="coins"> <widget class="QTreeView" name="coins">
<property name="selectionMode"> <property name="selectionMode">

View file

@ -1,16 +1,16 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "contactswidget.h" #include "ContactsWidget.h"
#include "ui_contactswidget.h" #include "ui_ContactsWidget.h"
#include "dialog/contactsdialog.h"
#include "model/ModelUtils.h"
#include "mainwindow.h"
#include "libwalletqt/AddressBook.h"
#include "utils/Icons.h"
#include <QMessageBox> #include <QMessageBox>
#include "dialog/ContactsDialog.h"
#include "libwalletqt/AddressBook.h"
#include "model/ModelUtils.h"
#include "utils/Icons.h"
ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent) ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::ContactsWidget) , ui(new Ui::ContactsWidget)
@ -150,7 +150,4 @@ void ContactsWidget::deleteContact()
m_model->deleteRow(m_proxyModel->mapToSource(index).row()); m_model->deleteRow(m_proxyModel->mapToSource(index).row());
} }
ContactsWidget::~ContactsWidget() ContactsWidget::~ContactsWidget() = default;
{
delete ui;
}

View file

@ -1,16 +1,16 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef CONTACTSWIDGET_H #ifndef FEATHER_CONTACTSWIDGET_H
#define CONTACTSWIDGET_H #define FEATHER_CONTACTSWIDGET_H
#include "model/AddressBookModel.h"
#include "model/AddressBookProxyModel.h"
#include "appcontext.h"
#include <QWidget> #include <QWidget>
#include <QMenu> #include <QMenu>
#include "appcontext.h"
#include "model/AddressBookModel.h"
#include "model/AddressBookProxyModel.h"
namespace Ui { namespace Ui {
class ContactsWidget; class ContactsWidget;
} }
@ -42,7 +42,7 @@ private slots:
void showHeaderMenu(const QPoint &position); void showHeaderMenu(const QPoint &position);
private: private:
Ui::ContactsWidget *ui; QScopedPointer<Ui::ContactsWidget> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
QAction *m_showFullAddressesAction; QAction *m_showFullAddressesAction;
@ -53,4 +53,4 @@ private:
AddressBookProxyModel * m_proxyModel; AddressBookProxyModel * m_proxyModel;
}; };
#endif // CONTACTSWIDGET_H #endif // FEATHER_CONTACTSWIDGET_H

View file

@ -1,16 +1,17 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "historywidget.h" #include "HistoryWidget.h"
#include "ui_historywidget.h" #include "ui_HistoryWidget.h"
#include "dialog/transactioninfodialog.h"
#include "dialog/TxProofDialog.h"
#include "utils/Icons.h"
#include "utils/config.h"
#include "appcontext.h"
#include <QMessageBox> #include <QMessageBox>
#include "appcontext.h"
#include "dialog/TxInfoDialog.h"
#include "dialog/TxProofDialog.h"
#include "utils/config.h"
#include "utils/Icons.h"
HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent) HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::HistoryWidget) , ui(new Ui::HistoryWidget)
@ -82,7 +83,7 @@ void HistoryWidget::showContextMenu(const QPoint &point) {
if (!tx) return; if (!tx) return;
bool unconfirmed = tx->isFailed() || tx->isPending(); bool unconfirmed = tx->isFailed() || tx->isPending();
if (m_ctx->txCache.contains(tx->hash()) && unconfirmed && tx->direction() != TransactionInfo::Direction_In) { if (unconfirmed && tx->direction() != TransactionInfo::Direction_In) {
menu.addAction(icons()->icon("info2.svg"), "Resend transaction", this, &HistoryWidget::onResendTransaction); menu.addAction(icons()->icon("info2.svg"), "Resend transaction", this, &HistoryWidget::onResendTransaction);
} }
@ -115,8 +116,8 @@ void HistoryWidget::showTxDetails() {
auto *tx = ui->history->currentEntry(); auto *tx = ui->history->currentEntry();
if (!tx) return; if (!tx) return;
auto *dialog = new TransactionInfoDialog(m_ctx, tx, this); auto *dialog = new TxInfoDialog(m_ctx, tx, this);
connect(dialog, &TransactionInfoDialog::resendTranscation, [this](const QString &txid){ connect(dialog, &TxInfoDialog::resendTranscation, [this](const QString &txid){
emit resendTransaction(txid); emit resendTransaction(txid);
}); });
dialog->show(); dialog->show();
@ -181,6 +182,4 @@ void HistoryWidget::showSyncNoticeMsg() {
"To update the history page during synchronization press Ctrl+R."); "To update the history page during synchronization press Ctrl+R.");
} }
HistoryWidget::~HistoryWidget() { HistoryWidget::~HistoryWidget() = default;
delete ui;
}

View file

@ -4,15 +4,15 @@
#ifndef FEATHER_HISTORYWIDGET_H #ifndef FEATHER_HISTORYWIDGET_H
#define FEATHER_HISTORYWIDGET_H #define FEATHER_HISTORYWIDGET_H
#include "model/TransactionHistoryModel.h"
#include "model/TransactionHistoryProxyModel.h"
#include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h"
#include "appcontext.h"
#include <QWidget> #include <QWidget>
#include <QMenu> #include <QMenu>
#include "appcontext.h"
#include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h"
#include "model/TransactionHistoryModel.h"
#include "model/TransactionHistoryProxyModel.h"
namespace Ui { namespace Ui {
class HistoryWidget; class HistoryWidget;
} }
@ -56,7 +56,7 @@ private:
void showContextMenu(const QPoint &point); void showContextMenu(const QPoint &point);
void showSyncNoticeMsg(); void showSyncNoticeMsg();
Ui::HistoryWidget *ui; QScopedPointer<Ui::HistoryWidget> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
QMenu *m_contextMenu; QMenu *m_contextMenu;
QMenu *m_copyMenu; QMenu *m_copyMenu;

View file

@ -1,38 +1,40 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include <QMessageBox> #include "MainWindow.h"
#include <QFileDialog> #include "ui_MainWindow.h"
#include "mainwindow.h" #include <QFileDialog>
#include "ui_mainwindow.h" #include <QInputDialog>
#include <QMessageBox>
#include "config-feather.h" #include "config-feather.h"
#include "dialog/txconfdialog.h" #include "constants.h"
#include "dialog/txconfadvdialog.h" #include "dialog/AccountSwitcherDialog.h"
#include "dialog/debuginfodialog.h" #include "dialog/BalanceDialog.h"
#include "dialog/walletinfodialog.h" #include "dialog/DebugInfoDialog.h"
#include "dialog/torinfodialog.h" #include "dialog/PasswordDialog.h"
#include "dialog/viewonlydialog.h" #include "dialog/TorInfoDialog.h"
#include "dialog/broadcasttxdialog.h" #include "dialog/TxBroadcastDialog.h"
#include "dialog/tximportdialog.h" #include "dialog/TxConfAdvDialog.h"
#include "dialog/passworddialog.h" #include "dialog/TxConfDialog.h"
#include "dialog/balancedialog.h" #include "dialog/TxImportDialog.h"
#include "dialog/TxInfoDialog.h"
#include "dialog/ViewOnlyDialog.h"
#include "dialog/WalletInfoDialog.h"
#include "dialog/WalletCacheDebugDialog.h" #include "dialog/WalletCacheDebugDialog.h"
#include "dialog/UpdateDialog.h" #include "dialog/UpdateDialog.h"
#include "dialog/AccountSwitcherDialog.h"
#include "constants.h"
#include "libwalletqt/AddressBook.h" #include "libwalletqt/AddressBook.h"
#include "utils/AsyncTask.h"
#include "utils/AppData.h" #include "utils/AppData.h"
#include "utils/AsyncTask.h"
#include "utils/ColorScheme.h" #include "utils/ColorScheme.h"
#include "utils/SemanticVersion.h"
#include "utils/NetworkManager.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/WebsocketNotifier.h" #include "utils/NetworkManager.h"
#include "utils/Updater.h"
#include "utils/os/tails.h" #include "utils/os/tails.h"
#include "utils/SemanticVersion.h"
#include "utils/TorManager.h" #include "utils/TorManager.h"
#include "utils/Updater.h"
#include "utils/WebsocketNotifier.h"
MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *parent) MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@ -151,7 +153,7 @@ void MainWindow::initStatusBar() {
connect(m_statusBtnTor, &StatusBarButton::clicked, this, &MainWindow::menuTorClicked); connect(m_statusBtnTor, &StatusBarButton::clicked, this, &MainWindow::menuTorClicked);
this->statusBar()->addPermanentWidget(m_statusBtnTor); this->statusBar()->addPermanentWidget(m_statusBtnTor);
m_statusBtnHwDevice = new StatusBarButton(icons()->icon("ledger.png"), "Ledger", this); m_statusBtnHwDevice = new StatusBarButton(this->hardwareDevicePairedIcon(), this->getHardwareDevice(), this);
connect(m_statusBtnHwDevice, &StatusBarButton::clicked, this, &MainWindow::menuHwDeviceClicked); connect(m_statusBtnHwDevice, &StatusBarButton::clicked, this, &MainWindow::menuHwDeviceClicked);
this->statusBar()->addPermanentWidget(m_statusBtnHwDevice); this->statusBar()->addPermanentWidget(m_statusBtnHwDevice);
m_statusBtnHwDevice->hide(); m_statusBtnHwDevice->hide();
@ -206,6 +208,10 @@ void MainWindow::initWidgets() {
#else #else
ui->tabWidget->setTabVisible(Tabs::XMRIG, false); ui->tabWidget->setTabVisible(Tabs::XMRIG, false);
#endif #endif
#if defined(Q_OS_MACOS)
ui->line->hide();
#endif
} }
void MainWindow::initMenu() { void MainWindow::initMenu() {
@ -217,6 +223,10 @@ void MainWindow::initMenu() {
connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::menuQuitClicked); // Quit application connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::menuQuitClicked); // Quit application
connect(ui->actionSettings, &QAction::triggered, this, &MainWindow::menuSettingsClicked); connect(ui->actionSettings, &QAction::triggered, this, &MainWindow::menuSettingsClicked);
// [File] -> [Recently open]
m_clearRecentlyOpenAction = new QAction("Clear history", ui->menuFile);
connect(m_clearRecentlyOpenAction, &QAction::triggered, this, &MainWindow::menuClearHistoryClicked);
// [Wallet] // [Wallet]
connect(ui->actionInformation, &QAction::triggered, this, &MainWindow::showWalletInfoDialog); connect(ui->actionInformation, &QAction::triggered, this, &MainWindow::showWalletInfoDialog);
connect(ui->actionAccount, &QAction::triggered, this, &MainWindow::showAccountSwitcherDialog); connect(ui->actionAccount, &QAction::triggered, this, &MainWindow::showAccountSwitcherDialog);
@ -304,6 +314,7 @@ void MainWindow::initMenu() {
connect(ui->actionLoadSignedTxFromText, &QAction::triggered, this, &MainWindow::loadSignedTxFromText); connect(ui->actionLoadSignedTxFromText, &QAction::triggered, this, &MainWindow::loadSignedTxFromText);
connect(ui->actionImport_transaction, &QAction::triggered, this, &MainWindow::importTransaction); connect(ui->actionImport_transaction, &QAction::triggered, this, &MainWindow::importTransaction);
connect(ui->actionPay_to_many, &QAction::triggered, this, &MainWindow::payToMany); connect(ui->actionPay_to_many, &QAction::triggered, this, &MainWindow::payToMany);
connect(ui->actionAddress_checker, &QAction::triggered, this, &MainWindow::showAddressChecker);
connect(ui->actionCalculator, &QAction::triggered, this, &MainWindow::showCalcWindow); connect(ui->actionCalculator, &QAction::triggered, this, &MainWindow::showCalcWindow);
connect(ui->actionCreateDesktopEntry, &QAction::triggered, this, &MainWindow::onCreateDesktopEntry); connect(ui->actionCreateDesktopEntry, &QAction::triggered, this, &MainWindow::onCreateDesktopEntry);
@ -356,6 +367,8 @@ void MainWindow::initWalletContext() {
connect(m_ctx.get(), &AppContext::createTransactionSuccess, this, &MainWindow::onCreateTransactionSuccess); connect(m_ctx.get(), &AppContext::createTransactionSuccess, this, &MainWindow::onCreateTransactionSuccess);
connect(m_ctx.get(), &AppContext::transactionCommitted, this, &MainWindow::onTransactionCommitted); connect(m_ctx.get(), &AppContext::transactionCommitted, this, &MainWindow::onTransactionCommitted);
connect(m_ctx.get(), &AppContext::deviceError, this, &MainWindow::onDeviceError); connect(m_ctx.get(), &AppContext::deviceError, this, &MainWindow::onDeviceError);
connect(m_ctx.get(), &AppContext::deviceButtonRequest, this, &MainWindow::onDeviceButtonRequest);
connect(m_ctx.get(), &AppContext::deviceButtonPressed, this, &MainWindow::onDeviceButtonPressed);
connect(m_ctx.get(), &AppContext::initiateTransaction, this, &MainWindow::onInitiateTransaction); connect(m_ctx.get(), &AppContext::initiateTransaction, this, &MainWindow::onInitiateTransaction);
connect(m_ctx.get(), &AppContext::endTransaction, this, &MainWindow::onEndTransaction); connect(m_ctx.get(), &AppContext::endTransaction, this, &MainWindow::onEndTransaction);
connect(m_ctx.get(), &AppContext::customRestoreHeightSet, this, &MainWindow::onCustomRestoreHeightSet); connect(m_ctx.get(), &AppContext::customRestoreHeightSet, this, &MainWindow::onCustomRestoreHeightSet);
@ -366,8 +379,9 @@ void MainWindow::initWalletContext() {
connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage); connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage);
// Wallet // Wallet
connect(m_ctx->wallet.get(), &Wallet::connectionStatusChanged, this, &MainWindow::onConnectionStatusChanged); connect(m_ctx->wallet, &Wallet::connectionStatusChanged, this, &MainWindow::onConnectionStatusChanged);
connect(m_ctx->wallet.get(), &Wallet::currentSubaddressAccountChanged, this, &MainWindow::updateTitle); connect(m_ctx->wallet, &Wallet::currentSubaddressAccountChanged, this, &MainWindow::updateTitle);
connect(m_ctx->wallet, &Wallet::walletPassphraseNeeded, this, &MainWindow::onWalletPassphraseNeeded);
} }
void MainWindow::menuToggleTabVisible(const QString &key){ void MainWindow::menuToggleTabVisible(const QString &key){
@ -379,6 +393,11 @@ void MainWindow::menuToggleTabVisible(const QString &key){
toggleTab->menuAction->setText((show ? QString("Hide ") : QString("Show ")) + toggleTab->name); toggleTab->menuAction->setText((show ? QString("Hide ") : QString("Show ")) + toggleTab->name);
} }
void MainWindow::menuClearHistoryClicked() {
config()->remove(Config::recentlyOpenedWallets);
this->updateRecentlyOpenedMenu();
}
QString MainWindow::walletName() { QString MainWindow::walletName() {
return QFileInfo(m_ctx->wallet->cachePath()).fileName(); return QFileInfo(m_ctx->wallet->cachePath()).fileName();
} }
@ -426,9 +445,7 @@ void MainWindow::onWalletOpened() {
this->bringToFront(); this->bringToFront();
this->setEnabled(true); this->setEnabled(true);
if (!torManager()->torConnected) if (!torManager()->torConnected)
this->setStatusText("Wallet opened - Starting Tor (may take a while)"); this->setStatusText("Starting Tor (may take a while)");
else
this->setStatusText("Wallet opened - Searching for node");
// receive page // receive page
m_ctx->wallet->subaddress()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_ctx->wallet->subaddress()->refresh(m_ctx->wallet->currentSubaddressAccount());
@ -445,13 +462,23 @@ void MainWindow::onWalletOpened() {
// coins page // coins page
m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
m_coinsWidget->setModel(m_ctx->wallet->coinsModel(), m_ctx->wallet->coins()); m_coinsWidget->setModel(m_ctx->wallet->coinsModel(), m_ctx->wallet->coins());
m_ctx->wallet->coinsModel()->setCurrentSubaddressAccount(m_ctx->wallet->currentSubaddressAccount());
// Coin labeling uses set_tx_note, so we need to refresh history too
connect(m_ctx->wallet->coins(), &Coins::descriptionChanged, [this] {
m_ctx->wallet->history()->refresh(m_ctx->wallet->currentSubaddressAccount());
});
// Vice versa
connect(m_ctx->wallet->history(), &TransactionHistory::txNoteChanged, [this] {
m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
});
this->updatePasswordIcon(); this->updatePasswordIcon();
this->updateTitle(); this->updateTitle();
m_ctx->nodes->connectToNode(); m_ctx->nodes->connectToNode();
m_updateBytes.start(250); m_updateBytes.start(250);
this->updateRecentlyOpened(m_ctx->wallet->cachePath()); this->addToRecentlyOpened(m_ctx->wallet->cachePath());
} }
void MainWindow::onBalanceUpdated(quint64 balance, quint64 spendable) { void MainWindow::onBalanceUpdated(quint64 balance, quint64 spendable) {
@ -619,8 +646,22 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
void MainWindow::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid) { void MainWindow::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid) {
if (status) { // success if (status) { // success
QMessageBox msgBox{this};
QPushButton *showDetailsButton = msgBox.addButton("Show details", QMessageBox::ActionRole);
msgBox.addButton(QMessageBox::Ok);
QString body = QString("Successfully sent %1 transaction(s).").arg(txid.count()); QString body = QString("Successfully sent %1 transaction(s).").arg(txid.count());
QMessageBox::information(this, "Transactions sent", body); msgBox.setText(body);
msgBox.setWindowTitle("Transaction sent");
msgBox.setIcon(QMessageBox::Icon::Information);
msgBox.exec();
if (msgBox.clickedButton() == showDetailsButton) {
this->showHistoryTab();
TransactionInfo *txInfo = m_ctx->wallet->history()->transaction(txid.first());
TxInfoDialog dialog{m_ctx, txInfo, this};
connect(&dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
dialog.exec();
}
m_sendWidget->clearFields(); m_sendWidget->clearFields();
} else { } else {
auto err = tx->errorString(); auto err = tx->errorString();
@ -704,7 +745,7 @@ void MainWindow::showConnectionStatusDialog() {
} }
void MainWindow::showPasswordDialog() { void MainWindow::showPasswordDialog() {
PasswordChangeDialog dialog{this, m_ctx->wallet.get()}; PasswordChangeDialog dialog{this, m_ctx->wallet};
dialog.exec(); dialog.exec();
this->updatePasswordIcon(); this->updatePasswordIcon();
} }
@ -780,12 +821,12 @@ void MainWindow::menuSettingsClicked() {
} }
void MainWindow::menuSignVerifyClicked() { void MainWindow::menuSignVerifyClicked() {
SignVerifyDialog dialog{m_ctx->wallet.get(), this}; SignVerifyDialog dialog{m_ctx->wallet, this};
dialog.exec(); dialog.exec();
} }
void MainWindow::menuVerifyTxProof() { void MainWindow::menuVerifyTxProof() {
VerifyProofDialog dialog{m_ctx->wallet.get(), this}; VerifyProofDialog dialog{m_ctx->wallet, this};
dialog.exec(); dialog.exec();
} }
@ -801,6 +842,26 @@ void MainWindow::updateWidgetIcons() {
m_localMoneroWidget->skinChanged(); m_localMoneroWidget->skinChanged();
#endif #endif
ui->conversionWidget->skinChanged(); ui->conversionWidget->skinChanged();
m_statusBtnHwDevice->setIcon(this->hardwareDevicePairedIcon());
}
QIcon MainWindow::hardwareDevicePairedIcon() {
QString filename;
if (m_ctx->wallet->isLedger())
filename = "ledger.png";
else if (m_ctx->wallet->isTrezor())
filename = ColorScheme::darkScheme ? "trezor_white.png" : "trezor.png";
return icons()->icon(filename);
}
QIcon MainWindow::hardwareDeviceUnpairedIcon() {
QString filename;
if (m_ctx->wallet->isLedger())
filename = "ledger_unpaired.png";
else if (m_ctx->wallet->isTrezor())
filename = ColorScheme::darkScheme ? "trezor_unpaired_white.png" : "trezor_unpaired.png";
return icons()->icon(filename);
} }
void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::closeEvent(QCloseEvent *event) {
@ -853,8 +914,8 @@ void MainWindow::payToMany() {
"A maximum of 16 addresses may be specified."); "A maximum of 16 addresses may be specified.");
} }
void MainWindow::showSendScreen(const CCSEntry &entry) { void MainWindow::showSendScreen(const CCSEntry &entry) { // TODO: rename this function
m_sendWidget->fill(entry); m_sendWidget->fill(entry.address, QString("CCS: %1").arg(entry.title));
ui->tabWidget->setCurrentIndex(Tabs::SEND); ui->tabWidget->setCurrentIndex(Tabs::SEND);
} }
@ -864,7 +925,8 @@ void MainWindow::onViewOnBlockExplorer(const QString &txid) {
} }
void MainWindow::onResendTransaction(const QString &txid) { void MainWindow::onResendTransaction(const QString &txid) {
if (!m_ctx->txCache.contains(txid)) { QString txHex = m_ctx->getCacheTransaction(txid);
if (txHex.isEmpty()) {
QMessageBox::warning(this, "Unable to resend transaction", "Transaction was not found in transaction cache. Unable to resend."); QMessageBox::warning(this, "Unable to resend transaction", "Transaction was not found in transaction cache. Unable to resend.");
return; return;
} }
@ -872,7 +934,7 @@ void MainWindow::onResendTransaction(const QString &txid) {
// Connect to a different node so chances of successful relay are higher // Connect to a different node so chances of successful relay are higher
m_ctx->nodes->autoConnect(true); m_ctx->nodes->autoConnect(true);
BroadcastTxDialog dialog{this, m_ctx, m_ctx->txCache[txid]}; TxBroadcastDialog dialog{this, m_ctx, txHex};
dialog.exec(); dialog.exec();
} }
@ -921,6 +983,27 @@ void MainWindow::showAccountSwitcherDialog() {
dialog.exec(); dialog.exec();
} }
void MainWindow::showAddressChecker() {
QString address = QInputDialog::getText(this, "Address Checker", "Address: ");
if (address.isEmpty()) {
return;
}
if (!WalletManager::addressValid(address, constants::networkType)) {
QMessageBox::warning(this, "Address Checker", "Invalid address.");
return;
}
SubaddressIndex index = m_ctx->wallet->subaddressIndex(address);
if (!index.isValid()) {
// TODO: probably mention lookahead here
QMessageBox::warning(this, "Address Checker", "This address does not belong to this wallet.");
return;
} else {
QMessageBox::information(this, "Address Checker", QString("This address belongs to Account #%1").arg(index.major));
}
}
void MainWindow::showNodeExhaustedMessage() { void MainWindow::showNodeExhaustedMessage() {
// Spawning dialogs inside a lambda can cause system freezes on linux so we have to do it this way ¯\_(ツ)_/¯ // Spawning dialogs inside a lambda can cause system freezes on linux so we have to do it this way ¯\_(ツ)_/¯
@ -1034,7 +1117,7 @@ void MainWindow::loadSignedTx() {
} }
void MainWindow::loadSignedTxFromText() { void MainWindow::loadSignedTxFromText() {
BroadcastTxDialog dialog{this, m_ctx}; TxBroadcastDialog dialog{this, m_ctx};
dialog.exec(); dialog.exec();
} }
@ -1065,7 +1148,8 @@ void MainWindow::onDeviceError(const QString &error) {
if (m_showDeviceError) { if (m_showDeviceError) {
return; return;
} }
m_statusBtnHwDevice->setIcon(icons()->icon("ledger_unpaired.png"));
m_statusBtnHwDevice->setIcon(this->hardwareDeviceUnpairedIcon());
while (true) { while (true) {
m_showDeviceError = true; m_showDeviceError = true;
auto result = QMessageBox::question(this, "Hardware device", "Lost connection to hardware device. Attempt to reconnect?"); auto result = QMessageBox::question(this, "Hardware device", "Lost connection to hardware device. Attempt to reconnect?");
@ -1080,27 +1164,70 @@ void MainWindow::onDeviceError(const QString &error) {
return; return;
} }
} }
m_statusBtnHwDevice->setIcon(icons()->icon("ledger.png")); m_statusBtnHwDevice->setIcon(this->hardwareDevicePairedIcon());
m_ctx->wallet->startRefresh(); m_ctx->wallet->startRefresh();
m_showDeviceError = false; m_showDeviceError = false;
} }
void MainWindow::onDeviceButtonRequest(quint64 code) {
if (m_ctx->wallet->isTrezor()) {
switch (code) {
case 8:
{
// Annoyingly, this code is used for a variety of actions, including:
// Confirm refresh: Do you really want to start refresh?
// Confirm export: Do you really want to export tx_key?
if (m_constructingTransaction) { // This code is also used when signing a tx, we handle this elsewhere
break;
}
m_splashDialog->setMessage("Confirm action on device to proceed");
m_splashDialog->setIcon(QPixmap(":/assets/images/confirmed.png"));
m_splashDialog->show();
m_splashDialog->setEnabled(true);
break;
}
}
}
}
void MainWindow::onDeviceButtonPressed() {
if (m_constructingTransaction) {
return;
}
m_splashDialog->hide();
}
void MainWindow::onWalletPassphraseNeeded(bool on_device) {
auto button = QMessageBox::question(nullptr, "Wallet Passphrase Needed", "Enter passphrase on hardware wallet?\n\n"
"It is recommended to enter passphrase on "
"the hardware wallet for better security.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (button == QMessageBox::Yes) {
m_ctx->wallet->onPassphraseEntered("", true, false);
return;
}
bool ok;
QString passphrase = QInputDialog::getText(nullptr, "Wallet Passphrase Needed", "Enter passphrase:", QLineEdit::EchoMode::Password, "", &ok);
if (ok) {
m_ctx->wallet->onPassphraseEntered(passphrase, false, false);
} else {
m_ctx->wallet->onPassphraseEntered(passphrase, false, true);
}
}
void MainWindow::updateNetStats() { void MainWindow::updateNetStats() {
if (m_ctx->wallet == nullptr) { if (!m_ctx->wallet || m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected
m_statusLabelNetStats->setText(""); || m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized)
return; {
} m_statusLabelNetStats->hide();
if (m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected) {
m_statusLabelNetStats->setText("");
return; return;
} }
if (m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized) { m_statusLabelNetStats->show();
m_statusLabelNetStats->setText("");
return;
}
m_statusLabelNetStats->setText(QString("(D: %1)").arg(Utils::formatBytes(m_ctx->wallet->getBytesReceived()))); m_statusLabelNetStats->setText(QString("(D: %1)").arg(Utils::formatBytes(m_ctx->wallet->getBytesReceived())));
} }
@ -1113,7 +1240,7 @@ void MainWindow::rescanSpent() {
} }
void MainWindow::showBalanceDialog() { void MainWindow::showBalanceDialog() {
BalanceDialog dialog{this, m_ctx->wallet.get()}; BalanceDialog dialog{this, m_ctx->wallet};
dialog.exec(); dialog.exec();
} }
@ -1379,7 +1506,7 @@ void MainWindow::donationNag() {
config()->set(Config::donateBeg, donationCounter); config()->set(Config::donateBeg, donationCounter);
} }
void MainWindow::updateRecentlyOpened(const QString &keysFile) { void MainWindow::addToRecentlyOpened(const QString &keysFile) {
auto recent = config()->get(Config::recentlyOpenedWallets).toList(); auto recent = config()->get(Config::recentlyOpenedWallets).toList();
if (recent.contains(keysFile)) { if (recent.contains(keysFile)) {
@ -1400,12 +1527,19 @@ void MainWindow::updateRecentlyOpened(const QString &keysFile) {
} }
config()->set(Config::recentlyOpenedWallets, recent_); config()->set(Config::recentlyOpenedWallets, recent_);
ui->menuRecently_open->clear();
for (const auto &var : recent_) { this->updateRecentlyOpenedMenu();
QString path = var.toString();
QFileInfo fileInfo{path};
ui->menuRecently_open->addAction(fileInfo.fileName(), m_windowManager, std::bind(&WindowManager::tryOpenWallet, m_windowManager, path, ""));
} }
void MainWindow::updateRecentlyOpenedMenu() {
ui->menuRecently_open->clear();
const QStringList recentWallets = config()->get(Config::recentlyOpenedWallets).toStringList();
for (const auto &walletPath : recentWallets) {
QFileInfo fileInfo{walletPath};
ui->menuRecently_open->addAction(fileInfo.fileName(), m_windowManager, std::bind(&WindowManager::tryOpenWallet, m_windowManager, walletPath, ""));
}
ui->menuRecently_open->addSeparator();
ui->menuRecently_open->addAction(m_clearRecentlyOpenAction);
} }
void MainWindow::toggleSearchbar(bool visible) { void MainWindow::toggleSearchbar(bool visible) {
@ -1414,6 +1548,7 @@ void MainWindow::toggleSearchbar(bool visible) {
m_historyWidget->setSearchbarVisible(visible); m_historyWidget->setSearchbarVisible(visible);
m_receiveWidget->setSearchbarVisible(visible); m_receiveWidget->setSearchbarVisible(visible);
m_contactsWidget->setSearchbarVisible(visible); m_contactsWidget->setSearchbarVisible(visible);
m_coinsWidget->setSearchbarVisible(visible);
int currentTab = ui->tabWidget->currentIndex(); int currentTab = ui->tabWidget->currentIndex();
if (currentTab == Tabs::HISTORY) if (currentTab == Tabs::HISTORY)
@ -1422,8 +1557,8 @@ void MainWindow::toggleSearchbar(bool visible) {
m_contactsWidget->focusSearchbar(); m_contactsWidget->focusSearchbar();
else if (currentTab == Tabs::RECEIVE) else if (currentTab == Tabs::RECEIVE)
m_receiveWidget->focusSearchbar(); m_receiveWidget->focusSearchbar();
else if (currentTab == Tabs::COINS)
m_coinsWidget->focusSearchbar();
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() = default;
delete ui;
}

View file

@ -1,28 +1,27 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef MAINWINDOW_H #ifndef FEATHER_MAINWINDOW_H
#define MAINWINDOW_H #define FEATHER_MAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QMenu> #include <QMenu>
#include <utility>
#include "appcontext.h" #include "appcontext.h"
#include "components.h" #include "components.h"
#include "calcwindow.h" #include "CalcWindow.h"
#include "settings.h" #include "SettingsDialog.h"
#include "dialog/aboutdialog.h" #include "dialog/AboutDialog.h"
#include "dialog/signverifydialog.h" #include "dialog/SignVerifyDialog.h"
#include "dialog/verifyproofdialog.h" #include "dialog/VerifyProofDialog.h"
#include "dialog/seeddialog.h" #include "dialog/SeedDialog.h"
#include "dialog/passwordchangedialog.h" #include "dialog/PasswordChangeDialog.h"
#include "dialog/keysdialog.h" #include "dialog/KeysDialog.h"
#include "dialog/aboutdialog.h" #include "dialog/AboutDialog.h"
#include "dialog/RestoreHeightDialog.h" #include "dialog/RestoreHeightDialog.h"
#include "dialog/splashdialog.h" #include "dialog/SplashDialog.h"
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
#include "model/SubaddressModel.h" #include "model/SubaddressModel.h"
#include "model/SubaddressProxyModel.h" #include "model/SubaddressProxyModel.h"
@ -31,16 +30,16 @@
#include "model/CoinsProxyModel.h" #include "model/CoinsProxyModel.h"
#include "utils/networking.h" #include "utils/networking.h"
#include "utils/config.h" #include "utils/config.h"
#include "widgets/ccswidget.h" #include "widgets/CCSWidget.h"
#include "widgets/redditwidget.h" #include "widgets/RedditWidget.h"
#include "widgets/TickerWidget.h" #include "widgets/TickerWidget.h"
#include "wizard/WalletWizard.h" #include "wizard/WalletWizard.h"
#include "contactswidget.h" #include "ContactsWidget.h"
#include "historywidget.h" #include "HistoryWidget.h"
#include "sendwidget.h" #include "SendWidget.h"
#include "receivewidget.h" #include "ReceiveWidget.h"
#include "coinswidget.h" #include "CoinsWidget.h"
#include "WindowManager.h" #include "WindowManager.h"
@ -49,7 +48,7 @@
#endif #endif
#ifdef HAS_XMRIG #ifdef HAS_XMRIG
#include "widgets/xmrigwidget.h" #include "widgets/XMRigWidget.h"
#endif #endif
namespace Ui { namespace Ui {
@ -114,6 +113,7 @@ private slots:
void menuWalletCloseClicked(); void menuWalletCloseClicked();
void menuTorClicked(); void menuTorClicked();
void menuToggleTabVisible(const QString &key); void menuToggleTabVisible(const QString &key);
void menuClearHistoryClicked();
void onExportHistoryCSV(bool checked); void onExportHistoryCSV(bool checked);
void onExportContactsCSV(bool checked); void onExportContactsCSV(bool checked);
void onCreateDesktopEntry(bool checked); void onCreateDesktopEntry(bool checked);
@ -156,6 +156,7 @@ private slots:
void showViewOnlyDialog(); void showViewOnlyDialog();
void showWalletCacheDebugDialog(); void showWalletCacheDebugDialog();
void showAccountSwitcherDialog(); void showAccountSwitcherDialog();
void showAddressChecker();
void donateButtonClicked(); void donateButtonClicked();
void showCalcWindow(); void showCalcWindow();
@ -172,12 +173,17 @@ private slots:
void showRestoreHeightDialog(); void showRestoreHeightDialog();
void importTransaction(); void importTransaction();
void onDeviceError(const QString &error); void onDeviceError(const QString &error);
void onDeviceButtonRequest(quint64 code);
void onDeviceButtonPressed();
void onWalletPassphraseNeeded(bool on_device);
void menuHwDeviceClicked(); void menuHwDeviceClicked();
void onUpdatesAvailable(const QJsonObject &updates); void onUpdatesAvailable(const QJsonObject &updates);
void toggleSearchbar(bool enabled); void toggleSearchbar(bool enabled);
void onSetStatusText(const QString &text); void onSetStatusText(const QString &text);
private: private:
friend WindowManager;
void initStatusBar(); void initStatusBar();
void initWidgets(); void initWidgets();
void initMenu(); void initMenu();
@ -203,10 +209,14 @@ private:
QString getHardwareDevice(); QString getHardwareDevice();
void updateTitle(); void updateTitle();
void donationNag(); void donationNag();
void updateRecentlyOpened(const QString &filename); void addToRecentlyOpened(const QString &filename);
void updateRecentlyOpenedMenu();
void updateWidgetIcons(); void updateWidgetIcons();
Ui::MainWindow *ui; QIcon hardwareDevicePairedIcon();
QIcon hardwareDeviceUnpairedIcon();
QScopedPointer<Ui::MainWindow> ui;
WindowManager *m_windowManager; WindowManager *m_windowManager;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
@ -229,6 +239,8 @@ private:
QList<PriceTickerWidget*> m_priceTickerWidgets; QList<PriceTickerWidget*> m_priceTickerWidgets;
BalanceTickerWidget *m_balanceTickerWidget; BalanceTickerWidget *m_balanceTickerWidget;
QPointer<QAction> m_clearRecentlyOpenAction;
// lower status bar // lower status bar
QPushButton *m_statusUpdateAvailable; QPushButton *m_statusUpdateAvailable;
ClickableLabel *m_statusLabelBalance; ClickableLabel *m_statusLabelBalance;
@ -257,4 +269,4 @@ private:
bool cleanedUp = false; bool cleanedUp = false;
}; };
#endif // MAINWINDOW_H #endif // FEATHER_MAINWINDOW_H

View file

@ -352,7 +352,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>977</width> <width>977</width>
<height>28</height> <height>27</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -455,6 +455,7 @@
<addaction name="actionImport_transaction"/> <addaction name="actionImport_transaction"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionPay_to_many"/> <addaction name="actionPay_to_many"/>
<addaction name="actionAddress_checker"/>
<addaction name="actionCalculator"/> <addaction name="actionCalculator"/>
<addaction name="actionCreateDesktopEntry"/> <addaction name="actionCreateDesktopEntry"/>
</widget> </widget>
@ -797,25 +798,30 @@
<string>Show Searchbar</string> <string>Show Searchbar</string>
</property> </property>
</action> </action>
<action name="actionAddress_checker">
<property name="text">
<string>Address checker</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
<class>CalcWidget</class> <class>CalcWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>calcwidget.h</header> <header>CalcWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>CCSWidget</class> <class>CCSWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>widgets/ccswidget.h</header> <header>widgets/CCSWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>RedditWidget</class> <class>RedditWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>widgets/redditwidget.h</header> <header>widgets/RedditWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View file

@ -1,15 +1,16 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "ui_receivewidget.h" #include "ReceiveWidget.h"
#include "receivewidget.h" #include "ui_ReceiveWidget.h"
#include "model/ModelUtils.h"
#include "dialog/qrcodedialog.h"
#include "utils/Icons.h"
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
#include "dialog/QrCodeDialog.h"
#include "model/ModelUtils.h"
#include "utils/Icons.h"
ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent) ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::ReceiveWidget) , ui(new Ui::ReceiveWidget)
@ -208,9 +209,8 @@ void ReceiveWidget::showQrCodeDialog() {
} }
QString address = index.model()->data(index.siblingAtColumn(SubaddressModel::Address), Qt::UserRole).toString(); QString address = index.model()->data(index.siblingAtColumn(SubaddressModel::Address), Qt::UserRole).toString();
QrCode qr(address, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH); QrCode qr(address, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
auto *dialog = new QrCodeDialog(this, qr, "Address"); QrCodeDialog dialog{this, &qr, "Address"};
dialog->exec(); dialog.exec();
dialog->deleteLater();
} }
QStringList ReceiveWidget::getHiddenAddresses() { QStringList ReceiveWidget::getHiddenAddresses() {
@ -243,6 +243,4 @@ Monero::SubaddressRow* ReceiveWidget::currentEntry() {
} }
} }
ReceiveWidget::~ReceiveWidget() { ReceiveWidget::~ReceiveWidget() = default;
delete ui;
}

View file

@ -4,14 +4,15 @@
#ifndef FEATHER_RECEIVEWIDGET_H #ifndef FEATHER_RECEIVEWIDGET_H
#define FEATHER_RECEIVEWIDGET_H #define FEATHER_RECEIVEWIDGET_H
#include <QMenu>
#include <QWidget>
#include <QtSvg/QSvgWidget>
#include "appcontext.h" #include "appcontext.h"
#include "qrcode/QrCode.h"
#include "libwalletqt/Subaddress.h" #include "libwalletqt/Subaddress.h"
#include "model/SubaddressProxyModel.h" #include "model/SubaddressProxyModel.h"
#include "model/SubaddressModel.h" #include "model/SubaddressModel.h"
#include "qrcode/QrCode.h"
#include <QWidget>
#include <QtSvg/QSvgWidget>
namespace Ui { namespace Ui {
class ReceiveWidget; class ReceiveWidget;
@ -50,7 +51,7 @@ private slots:
void generateSubaddress(); void generateSubaddress();
private: private:
Ui::ReceiveWidget *ui; QScopedPointer<Ui::ReceiveWidget> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
QMenu *m_headerMenu; QMenu *m_headerMenu;
QAction *m_showFullAddressesAction; QAction *m_showFullAddressesAction;

View file

@ -1,14 +1,15 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "SendWidget.h"
#include "ui_SendWidget.h"
#include <QMessageBox> #include <QMessageBox>
#include "sendwidget.h"
#include "mainwindow.h" #include "ColorScheme.h"
#include "ui_sendwidget.h"
#include "constants.h" #include "constants.h"
#include "utils/AppData.h" #include "utils/AppData.h"
#include "Icons.h" #include "Icons.h"
#include "ColorScheme.h"
#ifdef WITH_SCANNER #ifdef WITH_SCANNER
#include "qrcode_scanner/QrCodeScanDialog.h" #include "qrcode_scanner/QrCodeScanDialog.h"
@ -40,6 +41,7 @@ SendWidget::SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
connect(ui->lineAmount, &QLineEdit::textChanged, this, &SendWidget::amountEdited); connect(ui->lineAmount, &QLineEdit::textChanged, this, &SendWidget::amountEdited);
connect(ui->lineAddress, &QPlainTextEdit::textChanged, this, &SendWidget::addressEdited); connect(ui->lineAddress, &QPlainTextEdit::textChanged, this, &SendWidget::addressEdited);
connect(ui->btn_openAlias, &QPushButton::clicked, this, &SendWidget::aliasClicked); connect(ui->btn_openAlias, &QPushButton::clicked, this, &SendWidget::aliasClicked);
connect(ui->lineAddress, &PayToEdit::dataPasted, this, &SendWidget::onDataPasted);
ui->label_conversionAmount->setText(""); ui->label_conversionAmount->setText("");
ui->label_conversionAmount->hide(); ui->label_conversionAmount->hide();
ui->btn_openAlias->hide(); ui->btn_openAlias->hide();
@ -86,22 +88,20 @@ void SendWidget::amountEdited(const QString &text) {
this->updateConversionLabel(); this->updateConversionLabel();
} }
void SendWidget::fill(const CCSEntry &entry) {
this->fill(entry.address, QString("CCS: %1").arg(entry.title), 0.0);
}
void SendWidget::fill(double amount) { void SendWidget::fill(double amount) {
ui->lineAmount->setText(QString::number(amount)); ui->lineAmount->setText(QString::number(amount));
} }
void SendWidget::fill(const QString &address, const QString &description, double amount) { void SendWidget::fill(const QString &address, const QString &description, double amount) {
ui->lineDescription->setText(description);
ui->lineAddress->setText(address); ui->lineAddress->setText(address);
ui->lineAddress->moveCursor(QTextCursor::Start); ui->lineAddress->moveCursor(QTextCursor::Start);
ui->lineDescription->setText(description);
if (amount > 0) if (amount > 0)
ui->lineAmount->setText(QString::number(amount)); ui->lineAmount->setText(QString::number(amount));
ui->lineAmount->setFocus();
this->updateConversionLabel(); this->updateConversionLabel();
} }
@ -275,6 +275,25 @@ void SendWidget::onEndTransaction() {
ui->btnSend->setEnabled(true); ui->btnSend->setEnabled(true);
} }
void SendWidget::onDataPasted(const QString &data) {
if (!data.isEmpty()) {
QVariantMap uriData = m_ctx->wallet->parse_uri_to_object(data);
if (!uriData.contains("error")) {
if (uriData.contains("address"))
ui->lineAddress->setText(uriData.value("address").toString());
if (uriData.contains("amount"))
ui->lineAmount->setText(uriData.value("amount").toString());
if (uriData.contains("tx_description"))
ui->lineDescription->setText(uriData.value("tx_description").toString());
} else {
ui->lineAddress->setText(data);
}
}
else {
QMessageBox::warning(this, "Error", "No Qr Code found.");
}
}
void SendWidget::setupComboBox() { void SendWidget::setupComboBox() {
ui->comboCurrencySelection->clear(); ui->comboCurrencySelection->clear();
@ -302,6 +321,4 @@ void SendWidget::skinChanged() {
} }
} }
SendWidget::~SendWidget() { SendWidget::~SendWidget() = default;
delete ui;
}

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef SENDWIDGET_H #ifndef FEATHER_SENDWIDGET_H
#define SENDWIDGET_H #define FEATHER_SENDWIDGET_H
#include <QWidget> #include <QWidget>
#include "appcontext.h" #include "appcontext.h"
#include "widgets/ccswidget.h" #include "widgets/CCSWidget.h"
namespace Ui { namespace Ui {
class SendWidget; class SendWidget;
@ -18,7 +19,6 @@ Q_OBJECT
public: public:
explicit SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
void fill(const CCSEntry &entry);
void fill(const QString &address, const QString &description, double amount = 0); void fill(const QString &address, const QString &description, double amount = 0);
void fill(double amount); void fill(double amount);
void clearFields(); void clearFields();
@ -44,14 +44,17 @@ public slots:
void onInitiateTransaction(); void onInitiateTransaction();
void onEndTransaction(); void onEndTransaction();
private slots:
void onDataPasted(const QString &data);
private: private:
void setupComboBox(); void setupComboBox();
double amountDouble(); double amountDouble();
Ui::SendWidget *ui; QScopedPointer<Ui::SendWidget> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
quint64 amount(); quint64 amount();
double conversionAmount(); double conversionAmount();
}; };
#endif // SENDWIDGET_H #endif // FEATHER_SENDWIDGET_H

View file

@ -1,9 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "settings.h" #include "SettingsDialog.h"
#include "ui_settings.h" #include "ui_SettingsDialog.h"
#include "mainwindow.h"
#include <QFileDialog> #include <QFileDialog>
@ -194,6 +193,4 @@ void Settings::setupLocalMoneroFrontendCombobox() {
ui->combo_localMoneroFrontend->setCurrentIndex(ui->combo_localMoneroFrontend->findData(config()->get(Config::localMoneroFrontend).toString())); ui->combo_localMoneroFrontend->setCurrentIndex(ui->combo_localMoneroFrontend->findData(config()->get(Config::localMoneroFrontend).toString()));
} }
Settings::~Settings() { Settings::~Settings() = default;
delete ui;
}

View file

@ -1,15 +1,15 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef SETTINGS_H #ifndef FEATHER_SETTINGS_H
#define SETTINGS_H #define FEATHER_SETTINGS_H
#include <QAbstractButton>
#include <QDialog> #include <QDialog>
#include <QSettings> #include <QSettings>
#include <QAbstractButton>
#include "appcontext.h" #include "appcontext.h"
#include "widgets/nodewidget.h" #include "widgets/NodeWidget.h"
namespace Ui { namespace Ui {
class Settings; class Settings;
@ -50,7 +50,7 @@ private:
void setupSkinCombobox(); void setupSkinCombobox();
void setupLocalMoneroFrontendCombobox(); void setupLocalMoneroFrontendCombobox();
Ui::Settings *ui; QScopedPointer<Ui::Settings> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
QStringList m_skins{"Native", "QDarkStyle", "Breeze/Dark", "Breeze/Light"}; QStringList m_skins{"Native", "QDarkStyle", "Breeze/Dark", "Breeze/Light"};
@ -58,4 +58,4 @@ private:
QStringList m_timeFormats{"hh:mm", "hh:mm ap"}; QStringList m_timeFormats{"hh:mm", "hh:mm ap"};
}; };
#endif // SETTINGS_H #endif // FEATHER_SETTINGS_H

View file

@ -670,7 +670,7 @@
<customwidget> <customwidget>
<class>NodeWidget</class> <class>NodeWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>widgets/nodewidget.h</header> <header>widgets/NodeWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View file

@ -2,25 +2,30 @@
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "WindowManager.h" #include "WindowManager.h"
#include <QInputDialog>
#include <QMessageBox>
#include "constants.h" #include "constants.h"
#include "dialog/passworddialog.h" #include "dialog/PasswordDialog.h"
#include "dialog/splashdialog.h" #include "dialog/SplashDialog.h"
#include "utils/WebsocketNotifier.h"
#include "utils/os/tails.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/NetworkManager.h" #include "utils/NetworkManager.h"
#include "utils/os/tails.h"
#include "utils/TorManager.h" #include "utils/TorManager.h"
#include "utils/WebsocketNotifier.h"
#include <QMessageBox>
WindowManager::WindowManager() { WindowManager::WindowManager() {
m_walletManager = WalletManager::instance(); m_walletManager = WalletManager::instance();
m_splashDialog = new SplashDialog; m_splashDialog = new SplashDialog;
m_cleanupThread = new QThread();
connect(m_walletManager, &WalletManager::walletOpened, this, &WindowManager::onWalletOpened); connect(m_walletManager, &WalletManager::walletOpened, this, &WindowManager::onWalletOpened);
connect(m_walletManager, &WalletManager::walletCreated, this, &WindowManager::onWalletCreated); connect(m_walletManager, &WalletManager::walletCreated, this, &WindowManager::onWalletCreated);
connect(m_walletManager, &WalletManager::deviceButtonRequest, this, &WindowManager::onDeviceButtonRequest); connect(m_walletManager, &WalletManager::deviceButtonRequest, this, &WindowManager::onDeviceButtonRequest);
connect(m_walletManager, &WalletManager::deviceButtonPressed, this, &WindowManager::onDeviceButtonPressed);
connect(m_walletManager, &WalletManager::deviceError, this, &WindowManager::onDeviceError); connect(m_walletManager, &WalletManager::deviceError, this, &WindowManager::onDeviceError);
connect(m_walletManager, &WalletManager::walletPassphraseNeeded, this, &WindowManager::onWalletPassphraseNeeded);
connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow); connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow);
@ -67,6 +72,11 @@ void WindowManager::close() {
void WindowManager::closeWindow(MainWindow *window) { void WindowManager::closeWindow(MainWindow *window) {
m_windows.removeOne(window); m_windows.removeOne(window);
// Move Wallet to a different thread for cleanup so it doesn't block GUI thread
window->m_ctx->wallet->moveToThread(m_cleanupThread);
m_cleanupThread->start();
window->m_ctx->wallet->deleteLater();
} }
void WindowManager::restartApplication(const QString &binaryFilename) { void WindowManager::restartApplication(const QString &binaryFilename) {
@ -141,7 +151,7 @@ void WindowManager::onWalletOpened(Wallet *wallet) {
// Don't show incorrect password when we try with empty password for the first time // Don't show incorrect password when we try with empty password for the first time
bool showIncorrectPassword = m_openWalletTriedOnce; bool showIncorrectPassword = m_openWalletTriedOnce;
m_openWalletTriedOnce = true; m_openWalletTriedOnce = true;
this->onWalletOpenPasswordRequired(showIncorrectPassword, wallet->cachePath()); this->onWalletOpenPasswordRequired(showIncorrectPassword, wallet->keysPath());
} }
else if (errMsg == QString("basic_string::_M_replace_aux") || errMsg == QString("std::bad_alloc")) { else if (errMsg == QString("basic_string::_M_replace_aux") || errMsg == QString("std::bad_alloc")) {
qCritical() << errMsg; qCritical() << errMsg;
@ -227,7 +237,7 @@ void WindowManager::tryCreateWallet(FeatherSeed seed, const QString &path, const
this->onWalletOpened(wallet); this->onWalletOpened(wallet);
} }
void WindowManager::tryCreateWalletFromDevice(const QString &path, const QString &password, int restoreHeight) void WindowManager::tryCreateWalletFromDevice(const QString &path, const QString &password, const QString &deviceName, int restoreHeight)
{ {
if (Utils::fileExists(path)) { if (Utils::fileExists(path)) {
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path); auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
@ -236,7 +246,7 @@ void WindowManager::tryCreateWalletFromDevice(const QString &path, const QString
} }
m_openingWallet = true; m_openingWallet = true;
m_walletManager->createWalletFromDeviceAsync(path, password, constants::networkType, "Ledger", restoreHeight); m_walletManager->createWalletFromDeviceAsync(path, password, constants::networkType, deviceName, restoreHeight);
} }
void WindowManager::tryCreateWalletFromKeys(const QString &path, const QString &password, const QString &address, void WindowManager::tryCreateWalletFromKeys(const QString &path, const QString &password, const QString &address,
@ -293,16 +303,38 @@ void WindowManager::handleWalletError(const QString &message) {
} }
void WindowManager::displayWalletErrorMessage(const QString &message) { void WindowManager::displayWalletErrorMessage(const QString &message) {
QString errMsg = message; QString errMsg = QString("Error: %1").arg(message);
QString link;
// Ledger
if (message.contains("No device found")) { if (message.contains("No device found")) {
errMsg += "\n\nThis wallet is backed by a hardware device. Make sure the Monero app is opened on the device.\n" errMsg += "\n\nThis wallet is backed by a Ledger hardware device. Make sure the Monero app is opened on the device.\n"
"You may need to restart Feather before the device can get detected."; "You may need to restart Feather before the device can get detected.";
} }
if (message.contains("Unable to open device")) { if (message.contains("Unable to open device")) {
errMsg += "\n\nThe device might be in use by a different application."; errMsg += "\n\nThe device might be in use by a different application.";
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
errMsg += "\n\nNote: On Linux you may need to follow the instructions in the link below before the device can be opened:\n" errMsg += "\n\nNote: On Linux you may need to follow the instructions in the link below before the device can be opened:\n"
"<a>https://support.ledger.com/hc/en-us/articles/115005165269-Fix-connection-issues</a>"; "https://support.ledger.com/hc/en-us/articles/115005165269-Fix-connection-issues";
link = "https://support.ledger.com/hc/en-us/articles/115005165269-Fix-connection-issues";
#endif
}
// TREZOR
if (message.contains("Unable to claim libusb device")) {
errMsg += "\n\nThis wallet is backed by a Trezor hardware device. Feather was unable to access the device. "
"Please make sure it is not opened by another program and try again.";
}
if (message.contains("Cannot get a device address")) {
errMsg += "\n\nRestart the Trezor hardware device and try again.";
}
if (message.contains("Could not connect to the device Trezor") || message.contains("Device connect failed")) {
errMsg += "\n\nThis wallet is backed by a Trezor hardware device. Make sure the device is connected to your computer and unlocked.";
#if defined(Q_OS_LINUX)
errMsg += "\n\nNote: On Linux you may need to follow the instructions in the link below before the device can be opened:\n"
"https://wiki.trezor.io/Udev_rules";
link = "https://wiki.trezor.io/Udev_rules";
#endif #endif
} }
@ -323,23 +355,68 @@ void WindowManager::displayWalletErrorMessage(const QString &message) {
msgBox.setWindowTitle("Wallet error"); msgBox.setWindowTitle("Wallet error");
msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok);
QPushButton *openLinkButton = nullptr;
if (!link.isEmpty()) {
openLinkButton = msgBox.addButton("Open link", QMessageBox::ActionRole);
}
msgBox.exec(); msgBox.exec();
if (openLinkButton && msgBox.clickedButton() == openLinkButton) {
Utils::externalLinkWarning(nullptr, link);
}
} }
// ######################## DEVICE ######################## // ######################## DEVICE ########################
void WindowManager::onDeviceButtonRequest(quint64 code) { void WindowManager::onDeviceButtonRequest(quint64 code) {
m_splashDialog->setMessage("Action required on device: Export the view key to open the wallet."); QString message;
switch (code) {
case 1: // Trezor
message = "Action required on device: enter your PIN to continue.";
break;
case 8: // Trezor
message = "Action required on device: Export watch-only credentials to open the wallet.";
break;
case 19: // Trezor
message = "Action required on device: Enter passphrase to open the wallet.";
break;
default:
message = "Action required on device: Export the view key to open the wallet.";
}
m_splashDialog->setMessage(message);
m_splashDialog->setIcon(QPixmap(":/assets/images/key.png")); m_splashDialog->setIcon(QPixmap(":/assets/images/key.png"));
m_splashDialog->show(); m_splashDialog->show();
m_splashDialog->setEnabled(true); m_splashDialog->setEnabled(true);
} }
void WindowManager::onDeviceButtonPressed() {
m_splashDialog->hide();
}
void WindowManager::onDeviceError(const QString &errorMessage) { void WindowManager::onDeviceError(const QString &errorMessage) {
// TODO: when does this get called? // TODO: when does this get called?
qCritical() << Q_FUNC_INFO << errorMessage; qCritical() << Q_FUNC_INFO << errorMessage;
} }
void WindowManager::onWalletPassphraseNeeded(bool on_device) {
auto button = QMessageBox::question(nullptr, "Wallet Passphrase Needed", "Enter passphrase on hardware wallet?\n\n"
"It is recommended to enter passphrase on "
"the hardware wallet for better security.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (button == QMessageBox::Yes) {
m_walletManager->onPassphraseEntered("", true, false);
return;
}
bool ok;
QString passphrase = QInputDialog::getText(nullptr, "Wallet Passphrase Needed", "Enter passphrase:", QLineEdit::EchoMode::Password, "", &ok);
if (ok) {
m_walletManager->onPassphraseEntered(passphrase, false, false);
} else {
m_walletManager->onPassphraseEntered(passphrase, false, true);
}
}
// ######################## TRAY ######################## // ######################## TRAY ########################
void WindowManager::buildTrayMenu() { void WindowManager::buildTrayMenu() {

View file

@ -5,11 +5,12 @@
#define FEATHER_WINDOWMANAGER_H #define FEATHER_WINDOWMANAGER_H
#include <QObject> #include <QObject>
#include "dialog/TorInfoDialog.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
#include "MainWindow.h"
#include "wizard/WalletWizard.h" #include "wizard/WalletWizard.h"
#include "dialog/torinfodialog.h"
#include "mainwindow.h"
class MainWindow; class MainWindow;
class WindowManager : public QObject { class WindowManager : public QObject {
@ -38,11 +39,13 @@ private slots:
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path); void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
void onInitialNetworkConfigured(); void onInitialNetworkConfigured();
void onDeviceButtonRequest(quint64 code); void onDeviceButtonRequest(quint64 code);
void onDeviceButtonPressed();
void onDeviceError(const QString &errorMessage); void onDeviceError(const QString &errorMessage);
void onWalletPassphraseNeeded(bool on_device);
private: private:
void tryCreateWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset); void tryCreateWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset);
void tryCreateWalletFromDevice(const QString &path, const QString &password, int restoreHeight); void tryCreateWalletFromDevice(const QString &path, const QString &password, const QString &deviceName, int restoreHeight);
void tryCreateWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight); void tryCreateWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight);
bool autoOpenWallet(); bool autoOpenWallet();
@ -76,6 +79,8 @@ private:
bool m_openWalletTriedOnce = false; bool m_openWalletTriedOnce = false;
bool m_openingWallet = false; bool m_openingWallet = false;
bool m_initialNetworkConfigured = false; bool m_initialNetworkConfigured = false;
QThread *m_cleanupThread;
}; };

View file

@ -2,7 +2,6 @@
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include <QDir> #include <QDir>
#include <QMessageBox>
#include "appcontext.h" #include "appcontext.h"
#include "constants.h" #include "constants.h"
@ -27,21 +26,22 @@ AppContext::AppContext(Wallet *wallet)
, networkType(constants::networkType) , networkType(constants::networkType)
, m_rpc(new DaemonRpc{this, getNetworkTor(), ""}) , m_rpc(new DaemonRpc{this, getNetworkTor(), ""})
{ {
connect(this->wallet.get(), &Wallet::moneySpent, this, &AppContext::onMoneySpent); connect(this->wallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent);
connect(this->wallet.get(), &Wallet::moneyReceived, this, &AppContext::onMoneyReceived); connect(this->wallet, &Wallet::moneyReceived, this, &AppContext::onMoneyReceived);
connect(this->wallet.get(), &Wallet::unconfirmedMoneyReceived, this, &AppContext::onUnconfirmedMoneyReceived); connect(this->wallet, &Wallet::unconfirmedMoneyReceived, this, &AppContext::onUnconfirmedMoneyReceived);
connect(this->wallet.get(), &Wallet::newBlock, this, &AppContext::onWalletNewBlock); connect(this->wallet, &Wallet::newBlock, this, &AppContext::onWalletNewBlock);
connect(this->wallet.get(), &Wallet::updated, this, &AppContext::onWalletUpdate); connect(this->wallet, &Wallet::updated, this, &AppContext::onWalletUpdate);
connect(this->wallet.get(), &Wallet::refreshed, this, &AppContext::onWalletRefreshed); connect(this->wallet, &Wallet::refreshed, this, &AppContext::onWalletRefreshed);
connect(this->wallet.get(), &Wallet::transactionCommitted, this, &AppContext::onTransactionCommitted); connect(this->wallet, &Wallet::transactionCommitted, this, &AppContext::onTransactionCommitted);
connect(this->wallet.get(), &Wallet::heightRefreshed, this, &AppContext::onHeightRefreshed); connect(this->wallet, &Wallet::heightRefreshed, this, &AppContext::onHeightRefreshed);
connect(this->wallet.get(), &Wallet::transactionCreated, this, &AppContext::onTransactionCreated); connect(this->wallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
connect(this->wallet.get(), &Wallet::deviceError, this, &AppContext::onDeviceError); connect(this->wallet, &Wallet::deviceError, this, &AppContext::onDeviceError);
connect(this->wallet.get(), &Wallet::deviceButtonRequest, this, &AppContext::onDeviceButtonRequest); connect(this->wallet, &Wallet::deviceButtonRequest, this, &AppContext::onDeviceButtonRequest);
connect(this->wallet.get(), &Wallet::connectionStatusChanged, [this]{ connect(this->wallet, &Wallet::deviceButtonPressed, this, &AppContext::onDeviceButtonPressed);
connect(this->wallet, &Wallet::connectionStatusChanged, [this]{
this->nodes->autoConnect(); this->nodes->autoConnect();
}); });
connect(this->wallet.get(), &Wallet::currentSubaddressAccountChanged, [this]{ connect(this->wallet, &Wallet::currentSubaddressAccountChanged, [this]{
this->updateBalance(); this->updateBalance();
}); });
@ -110,13 +110,13 @@ void AppContext::onCreateTransactionMultiDest(const QVector<QString> &addresses,
emit initiateTransaction(); emit initiateTransaction();
} }
void AppContext::onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) { void AppContext::onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs) {
if (churn) { if (churn) {
address = this->wallet->address(0, 0); // primary address address = this->wallet->address(0, 0);
} }
qInfo() << "Creating transaction"; qInfo() << "Creating transaction";
this->wallet->createTransactionSingleAsync(keyImage, address, outputs, this->tx_priority); this->wallet->createTransactionSelectedAsync(keyImages, address, outputs, this->tx_priority);
emit initiateTransaction(); emit initiateTransaction();
} }
@ -158,6 +158,15 @@ void AppContext::onMultiBroadcast(PendingTransaction *tx) {
} }
} }
void AppContext::addCacheTransaction(const QString &txid, const QString &txHex) const {
this->wallet->setCacheAttribute(QString("tx:%1").arg(txid), txHex);
}
QString AppContext::getCacheTransaction(const QString &txid) const {
QString txHex = this->wallet->getCacheAttribute(QString("tx:%1").arg(txid));
return txHex;
}
// ################## Models ################## // ################## Models ##################
void AppContext::onPreferredFiatCurrencyChanged(const QString &symbol) { void AppContext::onPreferredFiatCurrencyChanged(const QString &symbol) {
@ -179,6 +188,10 @@ void AppContext::onDeviceButtonRequest(quint64 code) {
emit deviceButtonRequest(code); emit deviceButtonRequest(code);
} }
void AppContext::onDeviceButtonPressed() {
emit deviceButtonPressed();
}
void AppContext::onDeviceError(const QString &message) { void AppContext::onDeviceError(const QString &message) {
qCritical() << "Device error: " << message; qCritical() << "Device error: " << message;
emit deviceError(message); emit deviceError(message);
@ -257,6 +270,10 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
emit openAliasResolveError(msg); emit openAliasResolveError(msg);
} }
void AppContext::stopTimers() {
m_storeTimer.stop();
}
// ########################################## LIBWALLET QT SIGNALS #################################################### // ########################################## LIBWALLET QT SIGNALS ####################################################
void AppContext::onMoneySpent(const QString &txId, quint64 amount) { void AppContext::onMoneySpent(const QString &txId, quint64 amount) {

View file

@ -25,7 +25,7 @@ Q_OBJECT
public: public:
explicit AppContext(Wallet *wallet); explicit AppContext(Wallet *wallet);
QScopedPointer<Wallet> wallet; Wallet *wallet;
Nodes *nodes; Nodes *nodes;
bool donationSending = false; bool donationSending = false;
@ -34,7 +34,6 @@ public:
NetworkType::Type networkType; NetworkType::Type networkType;
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low; PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
QMap<QString, QString> txCache;
// libwalletqt // libwalletqt
bool refreshed = false; bool refreshed = false;
@ -46,11 +45,16 @@ public:
void storeWallet(); void storeWallet();
void stopTimers();
void addCacheTransaction(const QString &txid, const QString &txHex) const;
QString getCacheTransaction(const QString &txid) const;
public slots: public slots:
void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all); void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all);
void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description); void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address); void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs); void onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs);
void onCreateTransactionError(const QString &msg); void onCreateTransactionError(const QString &msg);
void onOpenAliasResolve(const QString &openAlias); void onOpenAliasResolve(const QString &openAlias);
void onSetRestoreHeight(quint64 height); void onSetRestoreHeight(quint64 height);
@ -58,6 +62,7 @@ public slots:
void onAmountPrecisionChanged(int precision); void onAmountPrecisionChanged(int precision);
void onMultiBroadcast(PendingTransaction *tx); void onMultiBroadcast(PendingTransaction *tx);
void onDeviceButtonRequest(quint64 code); void onDeviceButtonRequest(quint64 code);
void onDeviceButtonPressed();
void onDeviceError(const QString &message); void onDeviceError(const QString &message);
void onTorSettingsChanged(); // should not be here void onTorSettingsChanged(); // should not be here
@ -91,6 +96,7 @@ signals:
void initiateTransaction(); void initiateTransaction();
void endTransaction(); void endTransaction();
void deviceButtonRequest(quint64 code); void deviceButtonRequest(quint64 code);
void deviceButtonPressed();
void deviceError(const QString &message); void deviceError(const QString &message);
private: private:

View file

@ -107,7 +107,9 @@
<file>assets/images/tor_logo_disabled.png</file> <file>assets/images/tor_logo_disabled.png</file>
<file>assets/images/tor_logo.png</file> <file>assets/images/tor_logo.png</file>
<file>assets/images/trezor.png</file> <file>assets/images/trezor.png</file>
<file>assets/images/trezor_white.png</file>
<file>assets/images/trezor_unpaired.png</file> <file>assets/images/trezor_unpaired.png</file>
<file>assets/images/trezor_unpaired_white.png</file>
<file>assets/images/unconfirmed.png</file> <file>assets/images/unconfirmed.png</file>
<file>assets/images/unlock.png</file> <file>assets/images/unlock.png</file>
<file>assets/images/unlock.svg</file> <file>assets/images/unlock.svg</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1,7 +1,6 @@
{ {
"mainnet": { "mainnet": {
"tor": [ "tor": [
"xmrtolujkxnlinre.onion:18081",
"xmrag4hf5xlabmob.onion:18081", "xmrag4hf5xlabmob.onion:18081",
"monero26mmldsallmxok2kwamne4ve3mybvvn2yijsvss7ey63hc4yyd.onion:18081", "monero26mmldsallmxok2kwamne4ve3mybvvn2yijsvss7ey63hc4yyd.onion:18081",
"monero5sjoz5xmjn.onion:18081", "monero5sjoz5xmjn.onion:18081",
@ -24,14 +23,23 @@
"node.xmr.ru:18081", "node.xmr.ru:18081",
"selsta1.featherwallet.net:18081", "selsta1.featherwallet.net:18081",
"selsta2.featherwallet.net:18081", "selsta2.featherwallet.net:18081",
"node-1.sethsimmons.me:18089" "node-1.sethsimmons.me:18089",
"node.melo.tools:18081"
]
},
"testnet": {
"tor": [],
"clearnet": [
"testnet.melo.tools:28081"
] ]
}, },
"stagenet": { "stagenet": {
"tor": [], "tor": [
"ct36dsbe3oubpbebpxmiqz4uqk6zb6nhmkhoekileo4fts23rvuse2qd.onion:38081"
],
"clearnet": [ "clearnet": [
"run.your.own.node.xmr.pm:38089", "super.fast.node.xmr.pm:38089",
"super.fast.node.xmr.pm:38089" "stagenet.melo.tools:38081"
] ]
} }
} }

View file

@ -1,8 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef COMP_H #ifndef FEATHER_COMPONENTS_H
#define COMP_H #define FEATHER_COMPONENTS_H
#include <QPushButton> #include <QPushButton>
#include <QHBoxLayout> #include <QHBoxLayout>
@ -120,4 +120,5 @@ protected:
void mousePressEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override;
}; };
#endif
#endif //FEATHER_COMPONENTS_H

8
src/constants.cpp Normal file
View file

@ -0,0 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project.
#include "constants.h"
namespace constants {
NetworkType::Type networkType = NetworkType::Type::MAINNET;
};

View file

@ -11,8 +11,7 @@
namespace constants namespace constants
{ {
// application constants extern NetworkType::Type networkType; // TODO: not really a const
static NetworkType::Type networkType; // TODO: compiler moans, also not really a const
// coin constants // coin constants
const std::string coinName = "monero"; const std::string coinName = "monero";

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "aboutdialog.h" #include "AboutDialog.h"
#include "ui_aboutdialog.h" #include "ui_AboutDialog.h"
#include "utils/utils.h"
#include "config-feather.h" #include "config-feather.h"
#include "utils/Utils.h"
AboutDialog::AboutDialog(QWidget *parent) AboutDialog::AboutDialog(QWidget *parent)
: QDialog(parent) : QDialog(parent)
@ -38,7 +39,4 @@ AboutDialog::AboutDialog(QWidget *parent)
this->adjustSize(); this->adjustSize();
} }
AboutDialog::~AboutDialog() { AboutDialog::~AboutDialog() = default;
delete ui;
}

View file

@ -1,12 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef ABOUT_H #ifndef FEATHER_ABOUT_H
#define ABOUT_H #define FEATHER_ABOUT_H
#include <QDialog> #include <QDialog>
#include <QStringListModel> #include <QStringListModel>
#include <QAbstractButton>
namespace Ui { namespace Ui {
class AboutDialog; class AboutDialog;
@ -21,8 +20,8 @@ public:
~AboutDialog() override; ~AboutDialog() override;
private: private:
Ui::AboutDialog *ui; QScopedPointer<Ui::AboutDialog> ui;
QStringListModel *m_model; QStringListModel *m_model;
}; };
#endif // ABOUT_H #endif // FEATHER_ABOUT_H

View file

@ -4,11 +4,12 @@
#include "AccountSwitcherDialog.h" #include "AccountSwitcherDialog.h"
#include "ui_AccountSwitcherDialog.h" #include "ui_AccountSwitcherDialog.h"
#include "libwalletqt/SubaddressAccount.h"
#include "utils/Icons.h"
#include "model/ModelUtils.h"
#include <QMenu> #include <QMenu>
#include "libwalletqt/SubaddressAccount.h"
#include "model/ModelUtils.h"
#include "utils/Icons.h"
AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent) AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::AccountSwitcherDialog) , ui(new Ui::AccountSwitcherDialog)
@ -44,7 +45,7 @@ AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWi
m_ctx->wallet->subaddressAccount()->refresh(); m_ctx->wallet->subaddressAccount()->refresh();
}); });
connect(m_ctx->wallet.get(), &Wallet::currentSubaddressAccountChanged, this, &AccountSwitcherDialog::updateSelection); connect(m_ctx->wallet, &Wallet::currentSubaddressAccountChanged, this, &AccountSwitcherDialog::updateSelection);
connect(m_ctx->wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection); connect(m_ctx->wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection);
this->updateSelection(); this->updateSelection();
@ -78,7 +79,6 @@ void AccountSwitcherDialog::editLabel() {
} }
void AccountSwitcherDialog::updateSelection() { void AccountSwitcherDialog::updateSelection() {
qDebug() << "test";
QModelIndex index = m_model->index(m_ctx->wallet->currentSubaddressAccount(), 0); QModelIndex index = m_model->index(m_ctx->wallet->currentSubaddressAccount(), 0);
ui->accounts->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); ui->accounts->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
} }
@ -103,6 +103,4 @@ Monero::SubaddressAccountRow* AccountSwitcherDialog::currentEntry() {
return m_ctx->wallet->subaddressAccountModel()->entryFromIndex(index); return m_ctx->wallet->subaddressAccountModel()->entryFromIndex(index);
} }
AccountSwitcherDialog::~AccountSwitcherDialog() { AccountSwitcherDialog::~AccountSwitcherDialog() = default;
delete ui;
}

View file

@ -5,8 +5,8 @@
#define FEATHER_ACCOUNTSWITCHERDIALOG_H #define FEATHER_ACCOUNTSWITCHERDIALOG_H
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "appcontext.h"
#include "model/SubaddressAccountModel.h" #include "model/SubaddressAccountModel.h"
namespace Ui { namespace Ui {
@ -33,7 +33,7 @@ private:
Monero::SubaddressAccountRow* currentEntry(); Monero::SubaddressAccountRow* currentEntry();
Ui::AccountSwitcherDialog *ui; QScopedPointer<Ui::AccountSwitcherDialog> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
SubaddressAccountModel *m_model; SubaddressAccountModel *m_model;
SubaddressAccountProxyModel *m_proxyModel; SubaddressAccountProxyModel *m_proxyModel;

View file

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddressInfoDialog</class>
<widget class="QDialog" name="AddressInfoDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>520</width>
<height>310</height>
</rect>
</property>
<property name="windowTitle">
<string>Address</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Address:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_address">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Public view key:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_publicViewKey">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Public spend key:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_publicSpendKey">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Subaddress index:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_subaddressIndex">
<property name="minimumSize">
<size>
<width>500</width>
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AddressInfoDialog</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>AddressInfoDialog</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>

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "balancedialog.h" #include "BalanceDialog.h"
#include "ui_balancedialog.h" #include "ui_BalanceDialog.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "model/ModelUtils.h"
BalanceDialog::BalanceDialog(QWidget *parent, Wallet *wallet) BalanceDialog::BalanceDialog(QWidget *parent, Wallet *wallet)
: QDialog(parent) : QDialog(parent)
@ -16,12 +17,15 @@ BalanceDialog::BalanceDialog(QWidget *parent, Wallet *wallet)
"This will take 20 minutes on average."); "This will take 20 minutes on average.");
ui->label_unconfirmed->setText(WalletManager::displayAmount(wallet->balance() - wallet->unlockedBalance())); ui->label_unconfirmed->setText(WalletManager::displayAmount(wallet->balance() - wallet->unlockedBalance()));
ui->label_unconfirmed->setFont(ModelUtils::getMonospaceFont());
ui->label_spendable->setText(WalletManager::displayAmount(wallet->unlockedBalance())); ui->label_spendable->setText(WalletManager::displayAmount(wallet->unlockedBalance()));
ui->label_spendable->setFont(ModelUtils::getMonospaceFont());
ui->label_total->setText(WalletManager::displayAmount(wallet->balance())); ui->label_total->setText(WalletManager::displayAmount(wallet->balance()));
ui->label_total->setFont(ModelUtils::getMonospaceFont());
this->adjustSize(); this->adjustSize();
} }
BalanceDialog::~BalanceDialog() { BalanceDialog::~BalanceDialog() = default;
delete ui;
}

View file

@ -4,10 +4,10 @@
#ifndef FEATHER_BALANCEDIALOG_H #ifndef FEATHER_BALANCEDIALOG_H
#define FEATHER_BALANCEDIALOG_H #define FEATHER_BALANCEDIALOG_H
#include "libwalletqt/Wallet.h"
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class BalanceDialog; class BalanceDialog;
} }
@ -21,7 +21,7 @@ public:
~BalanceDialog() override; ~BalanceDialog() override;
private: private:
Ui::BalanceDialog *ui; QScopedPointer<Ui::BalanceDialog> ui;
}; };
#endif //FEATHER_BALANCEDIALOG_H #endif //FEATHER_BALANCEDIALOG_H

View file

View file

@ -3,6 +3,7 @@
#include "CalcConfigDialog.h" #include "CalcConfigDialog.h"
#include "ui_CalcConfigDialog.h" #include "ui_CalcConfigDialog.h"
#include "AppData.h" #include "AppData.h"
#include "utils/config.h" #include "utils/config.h"
@ -97,6 +98,4 @@ void CalcConfigDialog::fillListWidgets() {
setChecked(ui->list_fiat, checkedFiatCurrencies); setChecked(ui->list_fiat, checkedFiatCurrencies);
} }
CalcConfigDialog::~CalcConfigDialog() { CalcConfigDialog::~CalcConfigDialog() = default;
delete ui;
}

View file

@ -32,7 +32,7 @@ private:
void fillListWidgets(); void fillListWidgets();
QListWidget* getVisibleListWidget(); QListWidget* getVisibleListWidget();
Ui::CalcConfigDialog *ui; QScopedPointer<Ui::CalcConfigDialog> ui;
}; };

View file

@ -1,8 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "ui_contactsdialog.h" #include "ui_ContactsDialog.h"
#include "contactsdialog.h" #include "ContactsDialog.h"
ContactsDialog::ContactsDialog(QWidget *parent, const QString &address, const QString &name) ContactsDialog::ContactsDialog(QWidget *parent, const QString &address, const QString &name)
: QDialog(parent) : QDialog(parent)
@ -25,11 +25,6 @@ ContactsDialog::ContactsDialog(QWidget *parent, const QString &address, const QS
this->adjustSize(); this->adjustSize();
} }
ContactsDialog::~ContactsDialog()
{
delete ui;
}
QString ContactsDialog::getAddress() { QString ContactsDialog::getAddress() {
return m_address; return m_address;
} }
@ -37,3 +32,5 @@ QString ContactsDialog::getAddress() {
QString ContactsDialog::getName() { QString ContactsDialog::getName() {
return m_name; return m_name;
} }
ContactsDialog::~ContactsDialog() = default;

View file

@ -22,7 +22,7 @@ public:
QString getName(); QString getName();
private: private:
Ui::ContactsDialog *ui; QScopedPointer<Ui::ContactsDialog> ui;
QString m_address; QString m_address;
QString m_name; QString m_name;

View file

@ -1,13 +1,14 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "debuginfodialog.h" #include "DebugInfoDialog.h"
#include "ui_debuginfodialog.h" #include "ui_DebugInfoDialog.h"
#include "config-feather.h" #include "config-feather.h"
#include "utils/WebsocketClient.h"
#include "utils/TorManager.h"
#include "utils/WebsocketNotifier.h"
#include "utils/os/tails.h" #include "utils/os/tails.h"
#include "utils/TorManager.h"
#include "utils/WebsocketClient.h"
#include "utils/WebsocketNotifier.h"
DebugInfoDialog::DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent) DebugInfoDialog::DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
: QDialog(parent) : QDialog(parent)
@ -146,6 +147,4 @@ void DebugInfoDialog::copyToClipboad() {
Utils::copyToClipboard(text); Utils::copyToClipboard(text);
} }
DebugInfoDialog::~DebugInfoDialog() { DebugInfoDialog::~DebugInfoDialog() = default;
delete ui;
}

View file

@ -5,6 +5,7 @@
#define FEATHER_DEBUGINFODIALOG_H #define FEATHER_DEBUGINFODIALOG_H
#include <QDialog> #include <QDialog>
#include "appcontext.h" #include "appcontext.h"
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
@ -25,7 +26,7 @@ private:
void copyToClipboad(); void copyToClipboad();
void updateInfo(); void updateInfo();
Ui::DebugInfoDialog *ui; QScopedPointer<Ui::DebugInfoDialog> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
QTimer m_updateTimer; QTimer m_updateTimer;

View file

@ -14,6 +14,4 @@ InfoDialog::InfoDialog(QWidget *parent, const QString &title, const QString &inf
ui->info->setPlainText(infoData); ui->info->setPlainText(infoData);
} }
InfoDialog::~InfoDialog() { InfoDialog::~InfoDialog() = default;
delete ui;
}

View file

@ -19,7 +19,7 @@ public:
~InfoDialog() override; ~InfoDialog() override;
private: private:
Ui::InfoDialog *ui; QScopedPointer<Ui::InfoDialog> ui;
}; };

View file

@ -1,8 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "keysdialog.h" #include "KeysDialog.h"
#include "ui_keysdialog.h" #include "ui_KeysDialog.h"
KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent) KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
: QDialog(parent) : QDialog(parent)
@ -22,7 +22,4 @@ KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
this->adjustSize(); this->adjustSize();
} }
KeysDialog::~KeysDialog() KeysDialog::~KeysDialog() = default;
{
delete ui;
}

View file

@ -5,6 +5,7 @@
#define FEATHER_KEYSDIALOG_H #define FEATHER_KEYSDIALOG_H
#include <QDialog> #include <QDialog>
#include "appcontext.h" #include "appcontext.h"
namespace Ui { namespace Ui {
@ -20,7 +21,7 @@ public:
~KeysDialog() override; ~KeysDialog() override;
private: private:
Ui::KeysDialog *ui; QScopedPointer<Ui::KeysDialog> ui;
}; };

View file

@ -5,7 +5,7 @@
#include "ui_LocalMoneroInfoDialog.h" #include "ui_LocalMoneroInfoDialog.h"
#include "utils/config.h" #include "utils/config.h"
#include "utils/utils.h" #include "utils/Utils.h"
LocalMoneroInfoDialog::LocalMoneroInfoDialog(QWidget *parent, LocalMoneroModel *model, int row) LocalMoneroInfoDialog::LocalMoneroInfoDialog(QWidget *parent, LocalMoneroModel *model, int row)
: QDialog(parent) : QDialog(parent)
@ -46,6 +46,4 @@ void LocalMoneroInfoDialog::onGoToOffer() {
Utils::externalLinkWarning(this, offerUrl); Utils::externalLinkWarning(this, offerUrl);
} }
LocalMoneroInfoDialog::~LocalMoneroInfoDialog() { LocalMoneroInfoDialog::~LocalMoneroInfoDialog() = default;
delete ui;
}

View file

@ -6,6 +6,7 @@
#include <QDialog> #include <QDialog>
#include <QLabel> #include <QLabel>
#include "model/LocalMoneroModel.h" #include "model/LocalMoneroModel.h"
namespace Ui { namespace Ui {
@ -26,7 +27,7 @@ private slots:
private: private:
void setLabelText(QLabel *label, LocalMoneroModel::Column column); void setLabelText(QLabel *label, LocalMoneroModel::Column column);
Ui::LocalMoneroInfoDialog *ui; QScopedPointer<Ui::LocalMoneroInfoDialog> ui;
LocalMoneroModel *m_model; LocalMoneroModel *m_model;
int m_row; int m_row;
}; };

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "outputinfodialog.h" #include "OutputInfoDialog.h"
#include "ui_outputinfodialog.h" #include "ui_OutputInfoDialog.h"
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "utils/utils.h" #include "utils/Utils.h"
OutputInfoDialog::OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent) OutputInfoDialog::OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent)
: QDialog(parent) : QDialog(parent)
@ -37,6 +38,4 @@ OutputInfoDialog::OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent)
this->adjustSize(); this->adjustSize();
} }
OutputInfoDialog::~OutputInfoDialog() { OutputInfoDialog::~OutputInfoDialog() = default;
delete ui;
}

View file

@ -5,6 +5,7 @@
#define FEATHER_OUTPUTINFODIALOG_H #define FEATHER_OUTPUTINFODIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/CoinsInfo.h" #include "libwalletqt/CoinsInfo.h"
@ -21,7 +22,7 @@ public:
~OutputInfoDialog() override; ~OutputInfoDialog() override;
private: private:
Ui::OutputInfoDialog *ui; QScopedPointer<Ui::OutputInfoDialog> ui;
}; };

View file

@ -1,18 +1,18 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "ui_outputsweepdialog.h" #include "OutputSweepDialog.h"
#include "outputsweepdialog.h" #include "ui_OutputSweepDialog.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
OutputSweepDialog::OutputSweepDialog(QWidget *parent, CoinsInfo* coin) OutputSweepDialog::OutputSweepDialog(QWidget *parent, quint64 amount)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::OutputSweepDialog) , ui(new Ui::OutputSweepDialog)
, m_amount(amount)
{ {
ui->setupUi(this); ui->setupUi(this);
m_amount = coin->amount();
connect(ui->checkBox_churn, &QCheckBox::toggled, [&](bool toggled){ connect(ui->checkBox_churn, &QCheckBox::toggled, [&](bool toggled){
ui->lineEdit_address->setEnabled(!toggled); ui->lineEdit_address->setEnabled(!toggled);
ui->lineEdit_address->setText(toggled ? "Primary address" : ""); ui->lineEdit_address->setText(toggled ? "Primary address" : "");
@ -40,11 +40,6 @@ OutputSweepDialog::OutputSweepDialog(QWidget *parent, CoinsInfo* coin)
this->adjustSize(); this->adjustSize();
} }
OutputSweepDialog::~OutputSweepDialog()
{
delete ui;
}
QString OutputSweepDialog::address() { QString OutputSweepDialog::address() {
return m_address; return m_address;
} }
@ -56,3 +51,5 @@ bool OutputSweepDialog::churn() const {
int OutputSweepDialog::outputs() const { int OutputSweepDialog::outputs() const {
return m_outputs; return m_outputs;
} }
OutputSweepDialog::~OutputSweepDialog() = default;

View file

@ -5,6 +5,7 @@
#define FEATHER_OUTPUTSWEEPDIALOG_H #define FEATHER_OUTPUTSWEEPDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/CoinsInfo.h" #include "libwalletqt/CoinsInfo.h"
namespace Ui { namespace Ui {
@ -16,7 +17,7 @@ class OutputSweepDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit OutputSweepDialog(QWidget *parent, CoinsInfo* coin); explicit OutputSweepDialog(QWidget *parent, quint64 amount);
~OutputSweepDialog() override; ~OutputSweepDialog() override;
QString address(); QString address();
@ -24,7 +25,7 @@ public:
int outputs() const; int outputs() const;
private: private:
Ui::OutputSweepDialog *ui; QScopedPointer<Ui::OutputSweepDialog> ui;
uint64_t m_amount; uint64_t m_amount;

View file

@ -1,8 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "passwordchangedialog.h" #include "PasswordChangeDialog.h"
#include "ui_passwordchangedialog.h" #include "ui_PasswordChangeDialog.h"
#include <QMessageBox> #include <QMessageBox>
@ -40,11 +40,6 @@ PasswordChangeDialog::PasswordChangeDialog(QWidget *parent, Wallet *wallet)
this->adjustSize(); this->adjustSize();
} }
PasswordChangeDialog::~PasswordChangeDialog()
{
delete ui;
}
void PasswordChangeDialog::passwordsMatch() { void PasswordChangeDialog::passwordsMatch() {
bool match = ui->lineEdit_newPassword->text() == ui->lineEdit_confirmPassword->text(); bool match = ui->lineEdit_newPassword->text() == ui->lineEdit_confirmPassword->text();
ui->btn_OK->setEnabled(match); ui->btn_OK->setEnabled(match);
@ -70,3 +65,5 @@ void PasswordChangeDialog::setPassword() {
QMessageBox::warning(this, "Error", QString("Error: %1").arg(m_wallet->errorString())); QMessageBox::warning(this, "Error", QString("Error: %1").arg(m_wallet->errorString()));
} }
} }
PasswordChangeDialog::~PasswordChangeDialog() = default;

View file

@ -5,6 +5,7 @@
#define FEATHER_PASSWORDCHANGEDIALOG_H #define FEATHER_PASSWORDCHANGEDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
@ -20,11 +21,11 @@ public:
~PasswordChangeDialog() override; ~PasswordChangeDialog() override;
private: private:
Ui::PasswordChangeDialog *ui;
Wallet *m_wallet;
void passwordsMatch(); void passwordsMatch();
void setPassword(); void setPassword();
QScopedPointer<Ui::PasswordChangeDialog> ui;
Wallet *m_wallet;
}; };
#endif //FEATHER_PASSWORDCHANGEDIALOG_H #endif //FEATHER_PASSWORDCHANGEDIALOG_H

View file

@ -1,8 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "passworddialog.h" #include "PasswordDialog.h"
#include "ui_passworddialog.h" #include "ui_PasswordDialog.h"
#include "utils/Icons.h" #include "utils/Icons.h"
PasswordDialog::PasswordDialog(const QString &walletName, bool incorrectPassword, QWidget *parent) PasswordDialog::PasswordDialog(const QString &walletName, bool incorrectPassword, QWidget *parent)
@ -22,7 +23,4 @@ PasswordDialog::PasswordDialog(const QString &walletName, bool incorrectPassword
this->adjustSize(); this->adjustSize();
} }
PasswordDialog::~PasswordDialog() PasswordDialog::~PasswordDialog() = default;
{
delete ui;
}

View file

@ -21,7 +21,7 @@ public:
QString password = ""; QString password = "";
private: private:
Ui::PasswordDialog *ui; QScopedPointer<Ui::PasswordDialog> ui;
}; };
#endif //FEATHER_PASSWORDDIALOG_H #endif //FEATHER_PASSWORDDIALOG_H

View file

@ -1,22 +1,23 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "qrcodedialog.h" #include "QrCodeDialog.h"
#include "ui_qrcodedialog.h" #include "ui_QrCodeDialog.h"
#include <QClipboard> #include <QClipboard>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title) QrCodeDialog::QrCodeDialog(QWidget *parent, QrCode *qrCode, const QString &title)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::QrCodeDialog) , ui(new Ui::QrCodeDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
this->setWindowTitle(title); this->setWindowTitle(title);
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio); ui->qrWidget->setQrCode(qrCode);
ui->QrCode->setPixmap(m_pixmap);
m_pixmap = qrCode->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage); connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage);
connect(ui->btn_Save, &QPushButton::clicked, this, &QrCodeDialog::saveImage); connect(ui->btn_Save, &QPushButton::clicked, this, &QrCodeDialog::saveImage);
@ -24,17 +25,7 @@ QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString
accept(); accept();
}); });
this->adjustSize(); this->resize(500, 500);
}
QrCodeDialog::~QrCodeDialog()
{
delete ui;
}
void QrCodeDialog::setQrCode(const QrCode &qrCode) {
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
ui->QrCode->setPixmap(m_pixmap);
} }
void QrCodeDialog::copyImage() { void QrCodeDialog::copyImage() {
@ -53,3 +44,5 @@ void QrCodeDialog::saveImage() {
m_pixmap.save(&file, "PNG"); m_pixmap.save(&file, "PNG");
QMessageBox::information(this, "Information", "QR code saved to file"); QMessageBox::information(this, "Information", "QR code saved to file");
} }
QrCodeDialog::~QrCodeDialog() = default;

View file

@ -3,9 +3,11 @@
#ifndef FEATHER_QRCODEDIALOG_H #ifndef FEATHER_QRCODEDIALOG_H
#define FEATHER_QRCODEDIALOG_H #define FEATHER_QRCODEDIALOG_H
#include <QDialog> #include <QDialog>
#include "qrcode/QrCode.h" #include "qrcode/QrCode.h"
#include "widgets/QrCodeWidget.h"
namespace Ui { namespace Ui {
class QrCodeDialog; class QrCodeDialog;
@ -16,17 +18,15 @@ class QrCodeDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title = "Qr Code"); explicit QrCodeDialog(QWidget *parent, QrCode *qrCode, const QString &title = "Qr Code");
~QrCodeDialog() override; ~QrCodeDialog() override;
void setQrCode(const QrCode &qrCode);
private: private:
void copyImage(); void copyImage();
void saveImage(); void saveImage();
Ui::QrCodeDialog *ui; QScopedPointer<Ui::QrCodeDialog> ui;
QPixmap m_pixmap; QPixmap m_pixmap;
}; };
#endif //FEATHER_QRCODEDIALOG_H #endif //FEATHER_QRCODEDIALOG_H

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>522</width> <width>520</width>
<height>562</height> <height>446</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -15,22 +15,19 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QLabel" name="QrCode"> <widget class="QrCodeWidget" name="qrWidget" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>500</width> <width>150</width>
<height>500</height> <height>150</height>
</size> </size>
</property> </property>
<property name="text">
<string>QrCode</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -88,6 +85,14 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>QrCodeWidget</class>
<extends>QWidget</extends>
<header>widgets/QrCodeWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View file

@ -5,6 +5,7 @@
#define FEATHER_RESTOREHEIGHTDIALOG_H #define FEATHER_RESTOREHEIGHTDIALOG_H
#include <QDialog> #include <QDialog>
#include "widgets/RestoreHeightWidget.h" #include "widgets/RestoreHeightWidget.h"
class RestoreHeightDialog : public QDialog class RestoreHeightDialog : public QDialog

View file

@ -1,8 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "ui_seeddialog.h" #include "SeedDialog.h"
#include "seeddialog.h" #include "ui_SeedDialog.h"
#include "constants.h" #include "constants.h"
SeedDialog::SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent) SeedDialog::SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
@ -62,7 +63,4 @@ void SeedDialog::setSeed(const QString &seed) {
"</ul>").arg(words)); "</ul>").arg(words));
} }
SeedDialog::~SeedDialog() SeedDialog::~SeedDialog() = default;
{
delete ui;
}

View file

@ -5,6 +5,7 @@
#define FEATHER_SEEDDIALOG_H #define FEATHER_SEEDDIALOG_H
#include <QDialog> #include <QDialog>
#include "appcontext.h" #include "appcontext.h"
namespace Ui { namespace Ui {
@ -22,7 +23,7 @@ public:
private: private:
void setSeed(const QString &seed); void setSeed(const QString &seed);
Ui::SeedDialog *ui; QScopedPointer<Ui::SeedDialog> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
}; };

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "signverifydialog.h" #include "SignVerifyDialog.h"
#include "ui_signverifydialog.h" #include "ui_SignVerifyDialog.h"
#include "utils/utils.h"
#include <QMessageBox> #include <QMessageBox>
#include "utils/Utils.h"
SignVerifyDialog::SignVerifyDialog(Wallet *wallet, QWidget *parent) SignVerifyDialog::SignVerifyDialog(Wallet *wallet, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::SignVerifyDialog) , ui(new Ui::SignVerifyDialog)
@ -25,6 +26,12 @@ SignVerifyDialog::SignVerifyDialog(Wallet *wallet, QWidget *parent)
ui->address->setText(m_wallet->address(0, 0)); ui->address->setText(m_wallet->address(0, 0));
ui->address->setCursorPosition(0); ui->address->setCursorPosition(0);
if (m_wallet->isHwBacked()) {
// We don't have the secret spend key to sign messages
ui->btn_Sign->setEnabled(false);
ui->btn_Sign->setToolTip("Message signing is not supported on this hardware device.");
}
ui->btn_Copy->setVisible(false); ui->btn_Copy->setVisible(false);
} }
@ -52,7 +59,4 @@ void SignVerifyDialog::copyToClipboard() {
Utils::copyToClipboard(sig.join("\n")); Utils::copyToClipboard(sig.join("\n"));
} }
SignVerifyDialog::~SignVerifyDialog() SignVerifyDialog::~SignVerifyDialog() = default;
{
delete ui;
}

View file

@ -5,6 +5,7 @@
#define FEATHER_SIGNVERIFYDIALOG_H #define FEATHER_SIGNVERIFYDIALOG_H
#include <QDialog> #include <QDialog>
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
@ -19,14 +20,14 @@ public:
explicit SignVerifyDialog(Wallet *wallet, QWidget *parent = nullptr); explicit SignVerifyDialog(Wallet *wallet, QWidget *parent = nullptr);
~SignVerifyDialog() override; ~SignVerifyDialog() override;
private:
Ui::SignVerifyDialog *ui;
Wallet *m_wallet;
private slots: private slots:
void signMessage(); void signMessage();
void verifyMessage(); void verifyMessage();
void copyToClipboard(); void copyToClipboard();
private:
QScopedPointer<Ui::SignVerifyDialog> ui;
Wallet *m_wallet;
}; };

View file

@ -1,8 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "splashdialog.h" #include "SplashDialog.h"
#include "ui_splashdialog.h" #include "ui_SplashDialog.h"
#include "utils/Icons.h" #include "utils/Icons.h"
SplashDialog::SplashDialog(QWidget *parent) SplashDialog::SplashDialog(QWidget *parent)
@ -29,6 +30,4 @@ void SplashDialog::setIcon(const QPixmap &icon) {
ui->icon->setPixmap(icon.scaledToWidth(32, Qt::SmoothTransformation)); ui->icon->setPixmap(icon.scaledToWidth(32, Qt::SmoothTransformation));
} }
SplashDialog::~SplashDialog() { SplashDialog::~SplashDialog() = default;
delete ui;
}

View file

@ -22,7 +22,7 @@ public:
void setIcon(const QPixmap &icon); void setIcon(const QPixmap &icon);
private: private:
Ui::SplashDialog *ui; QScopedPointer<Ui::SplashDialog> ui;
}; };
#endif //FEATHER_SPLASHDIALOG_H #endif //FEATHER_SPLASHDIALOG_H

View file

@ -1,17 +1,19 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "torinfodialog.h" #include "TorInfoDialog.h"
#include "ui_torinfodialog.h" #include "ui_TorInfoDialog.h"
#include <QPushButton>
#include <QDesktopServices> #include <QDesktopServices>
#include <QMessageBox>
#include <QInputDialog> #include <QInputDialog>
#include <QMessageBox>
#include <QPushButton>
#include <QRegularExpressionValidator>
#include "utils/TorManager.h" #include "utils/ColorScheme.h"
#include "utils/os/tails.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/os/tails.h"
#include "utils/TorManager.h"
TorInfoDialog::TorInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent) TorInfoDialog::TorInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
: QDialog(parent) : QDialog(parent)
@ -36,6 +38,9 @@ TorInfoDialog::TorInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
initPrivacyLevel(); initPrivacyLevel();
onConnectionStatusChanged(torManager()->torConnected); onConnectionStatusChanged(torManager()->torConnected);
auto *portValidator = new QRegularExpressionValidator{QRegularExpression("[0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]")};
ui->line_port->setValidator(portValidator);
connect(torManager(), &TorManager::connectionStateChanged, this, &TorInfoDialog::onConnectionStatusChanged); connect(torManager(), &TorManager::connectionStateChanged, this, &TorInfoDialog::onConnectionStatusChanged);
connect(torManager(), &TorManager::logsUpdated, this, &TorInfoDialog::onLogsUpdated); connect(torManager(), &TorManager::logsUpdated, this, &TorInfoDialog::onLogsUpdated);
@ -139,9 +144,10 @@ void TorInfoDialog::initPrivacyLevel() {
ui->frame_notice->hide(); ui->frame_notice->hide();
} }
QPixmap iconNoTor(":/assets/images/securityLevelStandardWhite.png"); bool dark = ColorScheme::darkScheme;
QPixmap iconNoSync(":/assets/images/securityLevelSaferWhite.png"); QPixmap iconNoTor(dark ? ":/assets/images/securityLevelStandardWhite.png" : ":/assets/images/securityLevelStandard.png");
QPixmap iconAllTor(":/assets/images/securityLevelSafestWhite.png"); QPixmap iconNoSync(dark ? ":/assets/images/securityLevelSaferWhite.png" : ":/assets/images/securityLevelSafer.png");
QPixmap iconAllTor(dark ? ":/assets/images/securityLevelSafestWhite.png" : ":/assets/images/securityLevelSafest.png");
ui->icon_noTor->setPixmap(iconNoTor.scaledToHeight(16, Qt::SmoothTransformation)); ui->icon_noTor->setPixmap(iconNoTor.scaledToHeight(16, Qt::SmoothTransformation));
ui->icon_noSync->setPixmap(iconNoSync.scaledToHeight(16, Qt::SmoothTransformation)); ui->icon_noSync->setPixmap(iconNoSync.scaledToHeight(16, Qt::SmoothTransformation));
ui->icon_allTor->setPixmap(iconAllTor.scaledToHeight(16, Qt::SmoothTransformation)); ui->icon_allTor->setPixmap(iconAllTor.scaledToHeight(16, Qt::SmoothTransformation));
@ -165,6 +171,4 @@ void TorInfoDialog::onShowInitSyncConfigDialog() {
} }
} }
TorInfoDialog::~TorInfoDialog() { TorInfoDialog::~TorInfoDialog() = default;
delete ui;
}

View file

@ -5,7 +5,6 @@
#define FEATHER_TORINFODIALOG_H #define FEATHER_TORINFODIALOG_H
#include <QDialog> #include <QDialog>
#include <QAbstractButton>
#include "appcontext.h" #include "appcontext.h"
@ -38,7 +37,7 @@ private:
void initConnectionSettings(); void initConnectionSettings();
void initPrivacyLevel(); void initPrivacyLevel();
Ui::TorInfoDialog *ui; QScopedPointer<Ui::TorInfoDialog> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
}; };

View file

@ -1,15 +1,16 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#include "broadcasttxdialog.h" #include "TxBroadcastDialog.h"
#include "ui_broadcasttxdialog.h" #include "ui_TxBroadcastDialog.h"
#include "utils/NetworkManager.h"
#include <QMessageBox> #include <QMessageBox>
BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex) #include "utils/NetworkManager.h"
TxBroadcastDialog::TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::BroadcastTxDialog) , ui(new Ui::TxBroadcastDialog)
, m_ctx(std::move(ctx)) , m_ctx(std::move(ctx))
{ {
ui->setupUi(this); ui->setupUi(this);
@ -17,10 +18,10 @@ BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, QSharedPointer<AppContext>
auto node = m_ctx->nodes->connection(); auto node = m_ctx->nodes->connection();
m_rpc = new DaemonRpc(this, getNetworkTor(), node.toAddress()); m_rpc = new DaemonRpc(this, getNetworkTor(), node.toAddress());
connect(ui->btn_Broadcast, &QPushButton::clicked, this, &BroadcastTxDialog::broadcastTx); connect(ui->btn_Broadcast, &QPushButton::clicked, this, &TxBroadcastDialog::broadcastTx);
connect(ui->btn_Close, &QPushButton::clicked, this, &BroadcastTxDialog::reject); connect(ui->btn_Close, &QPushButton::clicked, this, &TxBroadcastDialog::reject);
connect(m_rpc, &DaemonRpc::ApiResponse, this, &BroadcastTxDialog::onApiResponse); connect(m_rpc, &DaemonRpc::ApiResponse, this, &TxBroadcastDialog::onApiResponse);
if (!transactionHex.isEmpty()) { if (!transactionHex.isEmpty()) {
ui->transaction->setPlainText(transactionHex); ui->transaction->setPlainText(transactionHex);
@ -29,7 +30,7 @@ BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, QSharedPointer<AppContext>
this->adjustSize(); this->adjustSize();
} }
void BroadcastTxDialog::broadcastTx() { void TxBroadcastDialog::broadcastTx() {
QString tx = ui->transaction->toPlainText(); QString tx = ui->transaction->toPlainText();
FeatherNode node = ui->radio_useCustom->isChecked() ? FeatherNode(ui->customNode->text()) : m_ctx->nodes->connection(); FeatherNode node = ui->radio_useCustom->isChecked() ? FeatherNode(ui->customNode->text()) : m_ctx->nodes->connection();
@ -44,7 +45,7 @@ void BroadcastTxDialog::broadcastTx() {
m_rpc->sendRawTransaction(tx); m_rpc->sendRawTransaction(tx);
} }
void BroadcastTxDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) { void TxBroadcastDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
if (!resp.ok) { if (!resp.ok) {
QMessageBox::warning(this, "Transaction broadcast", resp.status); QMessageBox::warning(this, "Transaction broadcast", resp.status);
return; return;
@ -56,6 +57,4 @@ void BroadcastTxDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
} }
} }
BroadcastTxDialog::~BroadcastTxDialog() { TxBroadcastDialog::~TxBroadcastDialog() = default;
delete ui;
}

View file

@ -1,35 +1,35 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project. // Copyright (c) 2020-2021, The Monero Project.
#ifndef FEATHER_BROADCASTTXDIALOG_H #ifndef FEATHER_TXBROADCASTDIALOG_H
#define FEATHER_BROADCASTTXDIALOG_H #define FEATHER_TXBROADCASTDIALOG_H
#include <QDialog> #include <QDialog>
#include "appcontext.h" #include "appcontext.h"
#include "utils/daemonrpc.h" #include "utils/daemonrpc.h"
namespace Ui { namespace Ui {
class BroadcastTxDialog; class TxBroadcastDialog;
} }
class BroadcastTxDialog : public QDialog class TxBroadcastDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BroadcastTxDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex = ""); explicit TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex = "");
~BroadcastTxDialog() override; ~TxBroadcastDialog() override;
private slots: private slots:
void broadcastTx(); void broadcastTx();
void onApiResponse(const DaemonRpc::DaemonResponse &resp); void onApiResponse(const DaemonRpc::DaemonResponse &resp);
private: private:
Ui::BroadcastTxDialog *ui; QScopedPointer<Ui::TxBroadcastDialog> ui;
QSharedPointer<AppContext> m_ctx; QSharedPointer<AppContext> m_ctx;
UtilsNetworking *m_network;
DaemonRpc *m_rpc; DaemonRpc *m_rpc;
}; };
#endif //FEATHER_BROADCASTTXDIALOG_H #endif //FEATHER_TXBROADCASTDIALOG_H

Some files were not shown because too many files have changed in this diff Show more