mirror of
https://github.com/feather-wallet/feather.git
synced 2024-11-17 17:57:39 +00:00
Merge pull request '1.0.0' (#394) from tobtoht/feather:1.0.0 into master
Reviewed-on: https://git.featherwallet.org/feather/feather/pulls/394
This commit is contained in:
commit
465a10b983
135 changed files with 2014 additions and 1195 deletions
|
@ -3,10 +3,10 @@ project(feather)
|
|||
|
||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||
|
||||
set(VERSION_MAJOR "0")
|
||||
set(VERSION_MINOR "1")
|
||||
set(VERSION_MAJOR "1")
|
||||
set(VERSION_MINOR "0")
|
||||
set(VERSION_REVISION "0")
|
||||
set(VERSION "beta-9")
|
||||
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
|
||||
|
||||
option(STATIC "Link libraries statically, requires static Qt")
|
||||
|
||||
|
@ -32,7 +32,7 @@ if(DEBUG)
|
|||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
endif()
|
||||
|
||||
set(MONERO_HEAD "d4257af2e7503fc6dc09fc704606230d353a0a02")
|
||||
set(MONERO_HEAD "bdd284b35d2e2c9c6ac733b4bc5ce8bd3b1162dd")
|
||||
set(BUILD_GUI_DEPS ON)
|
||||
option(ARCH "Target architecture" "x86-64")
|
||||
set(BUILD_64 ON)
|
||||
|
|
7
Makefile
7
Makefile
|
@ -11,7 +11,12 @@ CMAKEFLAGS = \
|
|||
release:
|
||||
mkdir -p build/release && \
|
||||
cd build/release && \
|
||||
cmake -D CMAKE_BUILD_TYPE=Release $(CMAKEFLAGS) ../.. && \
|
||||
cmake \
|
||||
-DARCH=x86-64 \
|
||||
-D BUILD_TAG="linux-x64" \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
$(CMAKEFLAGS) \
|
||||
../.. && \
|
||||
$(MAKE)
|
||||
|
||||
release-static:
|
||||
|
|
2
PKGBUILD
2
PKGBUILD
|
@ -2,7 +2,7 @@
|
|||
# Contributor: wowario <wowario[at]protonmail[dot]com>
|
||||
|
||||
pkgname='monero-feather-git'
|
||||
pkgver=0.8.0.d3791cbd26
|
||||
pkgver=1.0.0
|
||||
pkgrel=1
|
||||
pkgdesc='A free Monero desktop wallet'
|
||||
license=('BSD')
|
||||
|
|
28
contrib/installers/windows/LICENSE.txt
Normal file
28
contrib/installers/windows/LICENSE.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2020-2021, The Monero Project
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
BIN
contrib/installers/windows/appicon.ico
Normal file
BIN
contrib/installers/windows/appicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
67
contrib/installers/windows/feather.iss
Normal file
67
contrib/installers/windows/feather.iss
Normal file
|
@ -0,0 +1,67 @@
|
|||
; Feather Wallet Installer for Windows
|
||||
; Copyright (c) 2021-2021, The Monero Project
|
||||
|
||||
#define AppName "Feather Wallet"
|
||||
#define AppVersion "1.0.2"
|
||||
#define AppPublisher "Feather Wallet"
|
||||
#define AppURL "https://featherwallet.org"
|
||||
#define AppExeName "feather.exe"
|
||||
|
||||
[Setup]
|
||||
AppId={{E3C599C7-4DF1-49F2-9C35-918A288677A4}
|
||||
AppName={#AppName}
|
||||
AppVersion={#AppVersion}
|
||||
;AppVerName={#AppName} {#AppVersion}
|
||||
AppPublisher={#AppPublisher}
|
||||
AppPublisherURL={#AppURL}
|
||||
AppSupportURL={#AppURL}
|
||||
AppUpdatesURL={#AppURL}
|
||||
DefaultDirName={autopf}\{#AppName}
|
||||
DisableDirPage=yes
|
||||
DisableProgramGroupPage=yes
|
||||
; Uncomment the following line to run in non administrative install mode (install for current user only.)
|
||||
;PrivilegesRequired=lowest
|
||||
OutputBaseFilename=FeatherWalletSetup
|
||||
SetupIconFile=appicon.ico
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
|
||||
ArchitecturesInstallIn64BitMode=x64
|
||||
ArchitecturesAllowed=x64
|
||||
DisableReadyPage=yes
|
||||
|
||||
WizardSmallImageFile=compiler:WizClassicSmallImage.bmp
|
||||
WizardImageFile=compiler:WizClassicImage.bmp
|
||||
|
||||
UninstallDisplayIcon={app}\{#AppExeName}
|
||||
|
||||
[Messages]
|
||||
SetupWindowTitle=Setup - Feather Wallet {#AppVersion}
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
|
||||
|
||||
[Files]
|
||||
Source: "bin\{#AppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
;Source: "C:\Users\dev\Desktop\feather setup\finishbanner.bmp"; Flags: dontcopy
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Code]
|
||||
procedure CurPageChanged(CurPageID: Integer);
|
||||
begin
|
||||
if CurPageID = wpSelectTasks then
|
||||
WizardForm.NextButton.Caption := SetupMessage(msgButtonInstall)
|
||||
end;
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#AppName}"; Filename: "{app}\{#AppExeName}"
|
||||
Name: "{autodesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\{#AppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
2
monero
2
monero
|
@ -1 +1 @@
|
|||
Subproject commit d4257af2e7503fc6dc09fc704606230d353a0a02
|
||||
Subproject commit bdd284b35d2e2c9c6ac733b4bc5ce8bd3b1162dd
|
|
@ -23,13 +23,12 @@ CalcWidget::CalcWidget(QWidget *parent)
|
|||
ui->imageExchange->setFixedSize(26, 26);
|
||||
|
||||
// validator/locale for input
|
||||
QLocale lo(QLocale::C);
|
||||
lo.setNumberOptions(QLocale::RejectGroupSeparator);
|
||||
auto dv = new QDoubleValidator(0.0, 2147483647, 10, this); // [0, 32bit max], 10 decimals of precision
|
||||
dv->setNotation(QDoubleValidator::StandardNotation);
|
||||
dv->setLocale(lo);
|
||||
ui->lineFrom->setValidator(dv);
|
||||
ui->lineTo->setValidator(dv);
|
||||
QString amount_rx = R"(^\d{0,8}[\.]\d{0,12}$)";
|
||||
QRegExp rx;
|
||||
rx.setPattern(amount_rx);
|
||||
QValidator *validator = new QRegExpValidator(rx, this);
|
||||
ui->lineFrom->setValidator(validator);
|
||||
ui->lineTo->setValidator(validator);
|
||||
|
||||
connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &CalcWidget::onPricesReceived);
|
||||
connect(&appData()->prices, &Prices::cryptoPricesUpdated, this, &CalcWidget::onPricesReceived);
|
||||
|
|
|
@ -26,8 +26,7 @@ CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
connect(ui->coins->header(), &QHeaderView::customContextMenuRequested, this, &CoinsWidget::showHeaderMenu);
|
||||
|
||||
// copy menu
|
||||
m_copyMenu->setIcon(icons()->icon("copy.png"));
|
||||
m_copyMenu->addAction("Public key", this, [this]{copy(copyField::PubKey);});
|
||||
m_copyMenu->addAction("Public Key", this, [this]{copy(copyField::PubKey);});
|
||||
m_copyMenu->addAction("Key Image", this, [this]{copy(copyField::KeyImage);});
|
||||
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
|
||||
m_copyMenu->addAction("Address", this, [this]{copy(copyField::Address);});
|
||||
|
@ -47,12 +46,12 @@ CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
m_freezeAllSelectedAction = new QAction("Freeze selected", this);
|
||||
m_thawAllSelectedAction = new QAction("Thaw selected", this);
|
||||
|
||||
m_viewOutputAction = new QAction(icons()->icon("info2.svg"), "Details", this);
|
||||
m_viewOutputAction = new QAction("Details", 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_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
|
||||
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeAllSelected);
|
||||
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawAllSelected);
|
||||
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
|
||||
connect(m_sweepOutputAction, &QAction::triggered, this, &CoinsWidget::onSweepOutputs);
|
||||
connect(m_sweepOutputsAction, &QAction::triggered, this, &CoinsWidget::onSweepOutputs);
|
||||
|
@ -155,36 +154,24 @@ void CoinsWidget::setSearchFilter(const QString &filter) {
|
|||
m_proxyModel->setSearchFilter(filter);
|
||||
}
|
||||
|
||||
void CoinsWidget::freezeOutput() {
|
||||
QModelIndex index = ui->coins->currentIndex();
|
||||
QVector<int> indexes = {m_proxyModel->mapToSource(index).row()};
|
||||
this->freezeCoins(indexes);
|
||||
QStringList CoinsWidget::selectedPubkeys() {
|
||||
QModelIndexList list = ui->coins->selectionModel()->selectedRows();
|
||||
|
||||
QStringList pubkeys;
|
||||
for (QModelIndex index: list) {
|
||||
pubkeys << m_model->entryFromIndex(m_proxyModel->mapToSource(index))->pubKey();
|
||||
}
|
||||
return pubkeys;
|
||||
}
|
||||
|
||||
void CoinsWidget::freezeAllSelected() {
|
||||
QModelIndexList list = ui->coins->selectionModel()->selectedRows();
|
||||
|
||||
QVector<int> indexes;
|
||||
for (QModelIndex index: list) {
|
||||
indexes.push_back(m_proxyModel->mapToSource(index).row()); // todo: will segfault if index get invalidated
|
||||
}
|
||||
this->freezeCoins(indexes);
|
||||
}
|
||||
|
||||
void CoinsWidget::thawOutput() {
|
||||
QModelIndex index = ui->coins->currentIndex();
|
||||
QVector<int> indexes = {m_proxyModel->mapToSource(index).row()};
|
||||
this->thawCoins(indexes);
|
||||
QStringList pubkeys = this->selectedPubkeys();
|
||||
this->freezeCoins(pubkeys);
|
||||
}
|
||||
|
||||
void CoinsWidget::thawAllSelected() {
|
||||
QModelIndexList list = ui->coins->selectionModel()->selectedRows();
|
||||
|
||||
QVector<int> indexes;
|
||||
for (QModelIndex index: list) {
|
||||
indexes.push_back(m_proxyModel->mapToSource(index).row());
|
||||
}
|
||||
this->thawCoins(indexes);
|
||||
QStringList pubkeys = this->selectedPubkeys();
|
||||
this->thawCoins(pubkeys);
|
||||
}
|
||||
|
||||
void CoinsWidget::viewOutput() {
|
||||
|
@ -291,17 +278,17 @@ QVector<CoinsInfo*> CoinsWidget::currentEntries() {
|
|||
return selectedCoins;
|
||||
}
|
||||
|
||||
void CoinsWidget::freezeCoins(const QVector<int>& indexes) {
|
||||
for (int i : indexes) {
|
||||
m_ctx->wallet->coins()->freeze(i);
|
||||
void CoinsWidget::freezeCoins(QStringList &pubkeys) {
|
||||
for (auto &pubkey : pubkeys) {
|
||||
m_ctx->wallet->coins()->freeze(pubkey);
|
||||
}
|
||||
m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
|
||||
m_ctx->updateBalance();
|
||||
}
|
||||
|
||||
void CoinsWidget::thawCoins(const QVector<int> &indexes) {
|
||||
for (int i : indexes) {
|
||||
m_ctx->wallet->coins()->thaw(i);
|
||||
void CoinsWidget::thawCoins(QStringList &pubkeys) {
|
||||
for (auto &pubkey : pubkeys) {
|
||||
m_ctx->wallet->coins()->thaw(pubkey);
|
||||
}
|
||||
m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
|
||||
m_ctx->updateBalance();
|
||||
|
|
|
@ -33,9 +33,7 @@ public slots:
|
|||
private slots:
|
||||
void showHeaderMenu(const QPoint& position);
|
||||
void setShowSpent(bool show);
|
||||
void freezeOutput();
|
||||
void freezeAllSelected();
|
||||
void thawOutput();
|
||||
void thawAllSelected();
|
||||
void viewOutput();
|
||||
void onSweepOutputs();
|
||||
|
@ -43,8 +41,8 @@ private slots:
|
|||
void editLabel();
|
||||
|
||||
private:
|
||||
void freezeCoins(const QVector<int>& indexes);
|
||||
void thawCoins(const QVector<int>& indexes);
|
||||
void freezeCoins(QStringList &pubkeys);
|
||||
void thawCoins(QStringList &pubkeys);
|
||||
|
||||
enum copyField {
|
||||
PubKey = 0,
|
||||
|
@ -79,6 +77,7 @@ private:
|
|||
void copy(copyField field);
|
||||
CoinsInfo* currentEntry();
|
||||
QVector<CoinsInfo*> currentEntries();
|
||||
QStringList selectedPubkeys();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@ ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_btn_addContact = new QPushButton(this);
|
||||
m_btn_addContact->setIcon(icons()->icon("localMonero_register.svg"));
|
||||
ui->searchLayout->addWidget(m_btn_addContact, 0, Qt::AlignRight);
|
||||
connect(m_btn_addContact, &QPushButton::clicked, [this]{this->newContact();});
|
||||
|
||||
m_model = m_ctx->wallet->addressBookModel();
|
||||
m_proxyModel = new AddressBookProxyModel;
|
||||
m_proxyModel->setSourceModel(m_model);
|
||||
|
@ -45,7 +50,7 @@ ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
// context menu
|
||||
ui->contacts->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_contextMenu = new QMenu(ui->contacts);
|
||||
m_contextMenu->addAction(icons()->icon("person.svg"), "New contact", [this]{
|
||||
m_contextMenu->addAction("New contact", [this]{
|
||||
this->newContact();
|
||||
});
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#ifndef FEATHER_CONTACTSWIDGET_H
|
||||
#define FEATHER_CONTACTSWIDGET_H
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
#include <QMenu>
|
||||
|
||||
|
@ -51,6 +52,7 @@ private:
|
|||
QMenu *m_headerMenu;
|
||||
AddressBookModel * m_model;
|
||||
AddressBookProxyModel * m_proxyModel;
|
||||
QPushButton *m_btn_addContact;
|
||||
};
|
||||
|
||||
#endif // FEATHER_CONTACTSWIDGET_H
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>589</width>
|
||||
<height>416</height>
|
||||
<width>914</width>
|
||||
<height>763</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -29,6 +29,8 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="searchLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search">
|
||||
<property name="placeholderText">
|
||||
|
@ -36,8 +38,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="contacts">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "dialog/TxProofDialog.h"
|
||||
#include "utils/config.h"
|
||||
#include "utils/Icons.h"
|
||||
#include "WebsocketNotifier.h"
|
||||
|
||||
HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
|
@ -26,10 +27,9 @@ HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
m_contextMenu->addAction("View on block explorer", this, &HistoryWidget::onViewOnBlockExplorer);
|
||||
|
||||
// copy menu
|
||||
m_copyMenu->setIcon(icons()->icon("copy.png"));
|
||||
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
|
||||
m_copyMenu->addAction("Description", this, [this]{copy(copyField::Description);});
|
||||
m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);});
|
||||
m_copyMenu->addAction("Description", this, [this]{copy(copyField::Description);});
|
||||
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
|
||||
|
||||
ui->history->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
@ -53,7 +53,10 @@ HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
|
||||
ui->syncNotice->setVisible(config()->get(Config::showHistorySyncNotice).toBool());
|
||||
ui->history->setHistoryModel(m_model);
|
||||
m_ctx->wallet->transactionHistoryModel()->amountPrecision = config()->get(Config::amountPrecision).toInt();
|
||||
|
||||
connect(websocketNotifier(), &WebsocketNotifier::FiatRatesReceived, [this]{
|
||||
ui->history->update();
|
||||
});
|
||||
|
||||
// Load view state
|
||||
QByteArray historyViewState = QByteArray::fromBase64(config()->get(Config::GUI_HistoryViewState).toByteArray());
|
||||
|
@ -88,9 +91,9 @@ void HistoryWidget::showContextMenu(const QPoint &point) {
|
|||
}
|
||||
|
||||
menu.addMenu(m_copyMenu);
|
||||
menu.addAction(icons()->icon("info2.svg"), "Show details", this, &HistoryWidget::showTxDetails);
|
||||
menu.addAction(icons()->icon("network.png"), "View on block explorer", this, &HistoryWidget::onViewOnBlockExplorer);
|
||||
menu.addAction("Create tx proof", this, &HistoryWidget::createTxProof);
|
||||
menu.addAction("Show details", this, &HistoryWidget::showTxDetails);
|
||||
menu.addAction("View on block explorer", this, &HistoryWidget::onViewOnBlockExplorer);
|
||||
menu.addAction("Create Tx Proof", this, &HistoryWidget::createTxProof);
|
||||
|
||||
menu.exec(ui->history->viewport()->mapToGlobal(point));
|
||||
}
|
||||
|
@ -121,6 +124,7 @@ void HistoryWidget::showTxDetails() {
|
|||
emit resendTransaction(txid);
|
||||
});
|
||||
dialog->show();
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
void HistoryWidget::onViewOnBlockExplorer() {
|
||||
|
@ -157,10 +161,13 @@ void HistoryWidget::copy(copyField field) {
|
|||
switch(field) {
|
||||
case copyField::TxID:
|
||||
return tx->hash();
|
||||
case copyField::Description:
|
||||
return tx->description();
|
||||
case copyField::Date:
|
||||
return tx->timestamp().toString("yyyy-MM-dd HH:mm");
|
||||
return tx->timestamp().toString(QString("%1 %2").arg(config()->get(Config::dateFormat).toString(),
|
||||
config()->get(Config::timeFormat).toString()));
|
||||
case copyField::Amount:
|
||||
return tx->displayAmount();
|
||||
return WalletManager::displayAmount(tx->balanceDelta());
|
||||
default:
|
||||
return QString("");
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
|
|||
// Ensure the destructor is called after closeEvent()
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
m_windowSettings = new Settings(m_ctx, this);
|
||||
m_windowCalc = new CalcWindow(this);
|
||||
m_splashDialog = new SplashDialog(this);
|
||||
|
||||
|
@ -68,21 +67,12 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
|
|||
#endif
|
||||
websocketNotifier()->emitCache(); // Get cached data
|
||||
|
||||
// Settings
|
||||
for (const auto &widget: m_priceTickerWidgets)
|
||||
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, widget, &PriceTickerWidget::updateDisplay);
|
||||
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_balanceTickerWidget, &BalanceTickerWidget::updateDisplay);
|
||||
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_ctx.get(), &AppContext::onPreferredFiatCurrencyChanged);
|
||||
connect(m_windowSettings, &Settings::preferredFiatCurrencyChanged, m_sendWidget, QOverload<>::of(&SendWidget::onPreferredFiatCurrencyChanged));
|
||||
connect(m_windowSettings, &Settings::amountPrecisionChanged, m_ctx.get(), &AppContext::onAmountPrecisionChanged);
|
||||
connect(m_windowSettings, &Settings::skinChanged, this, &MainWindow::skinChanged);
|
||||
QTimer::singleShot(1, [this]{this->updateWidgetIcons();});
|
||||
|
||||
connect(m_windowManager, &WindowManager::torSettingsChanged, m_ctx.get(), &AppContext::onTorSettingsChanged);
|
||||
connect(torManager(), &TorManager::connectionStateChanged, this, &MainWindow::onTorConnectionStateChanged);
|
||||
this->onTorConnectionStateChanged(torManager()->torConnected);
|
||||
|
||||
ColorScheme::updateFromWidget(this);
|
||||
QTimer::singleShot(1, [this]{this->updateWidgetIcons();});
|
||||
|
||||
// Timers
|
||||
connect(&m_updateBytes, &QTimer::timeout, this, &MainWindow::updateNetStats);
|
||||
|
@ -105,6 +95,10 @@ void MainWindow::initStatusBar() {
|
|||
this->statusBar()->setStyleSheet("QStatusBar::item {border: None;}");
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
this->patchStylesheetMac();
|
||||
#endif
|
||||
|
||||
this->statusBar()->setFixedHeight(30);
|
||||
|
||||
m_statusLabelStatus = new QLabel("Idle", this);
|
||||
|
@ -327,6 +321,7 @@ void MainWindow::initMenu() {
|
|||
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::menuAboutClicked);
|
||||
connect(ui->actionOfficialWebsite, &QAction::triggered, [this](){Utils::externalLinkWarning(this, "https://featherwallet.org");});
|
||||
connect(ui->actionDonate_to_Feather, &QAction::triggered, this, &MainWindow::donateButtonClicked);
|
||||
connect(ui->actionDocumentation, &QAction::triggered, this, &MainWindow::onShowDocumentaton);
|
||||
connect(ui->actionReport_bug, &QAction::triggered, this, &MainWindow::onReportBug);
|
||||
connect(ui->actionShow_debug_info, &QAction::triggered, this, &MainWindow::showDebugInfo);
|
||||
|
||||
|
@ -341,6 +336,7 @@ void MainWindow::initMenu() {
|
|||
ui->actionSettings->setShortcut(QKeySequence("Ctrl+Alt+S"));
|
||||
ui->actionUpdate_balance->setShortcut(QKeySequence("Ctrl+U"));
|
||||
ui->actionShow_Searchbar->setShortcut(QKeySequence("Ctrl+F"));
|
||||
ui->actionDocumentation->setShortcut(QKeySequence("F1"));
|
||||
}
|
||||
|
||||
void MainWindow::initHome() {
|
||||
|
@ -626,9 +622,9 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
|
|||
m_ctx->addCacheTransaction(tx->txid()[0], tx->signedTxToHex(0));
|
||||
|
||||
// Show advanced dialog on multi-destination transactions
|
||||
if (address.size() > 1) {
|
||||
if (address.size() > 1 || m_ctx->wallet->viewOnly()) {
|
||||
TxConfAdvDialog dialog_adv{m_ctx, m_ctx->tmpTxDescription, this};
|
||||
dialog_adv.setTransaction(tx);
|
||||
dialog_adv.setTransaction(tx, !m_ctx->wallet->viewOnly());
|
||||
dialog_adv.exec();
|
||||
return;
|
||||
}
|
||||
|
@ -642,7 +638,7 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
|
|||
break;
|
||||
}
|
||||
case QDialog::Accepted:
|
||||
m_ctx->commitTransaction(tx);
|
||||
m_ctx->commitTransaction(tx, m_ctx->tmpTxDescription);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -666,9 +662,10 @@ void MainWindow::onTransactionCommitted(bool status, PendingTransaction *tx, con
|
|||
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();
|
||||
auto *dialog = new TxInfoDialog(m_ctx, txInfo, this);
|
||||
connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
|
||||
dialog->show();
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
m_sendWidget->clearFields();
|
||||
|
@ -832,9 +829,14 @@ void MainWindow::menuAboutClicked() {
|
|||
}
|
||||
|
||||
void MainWindow::menuSettingsClicked() {
|
||||
m_windowSettings->raise();
|
||||
m_windowSettings->show();
|
||||
m_windowSettings->activateWindow();
|
||||
Settings settings{m_ctx, this};
|
||||
for (const auto &widget: m_priceTickerWidgets) {
|
||||
connect(&settings, &Settings::preferredFiatCurrencyChanged, widget, &PriceTickerWidget::updateDisplay);
|
||||
}
|
||||
connect(&settings, &Settings::preferredFiatCurrencyChanged, m_balanceTickerWidget, &BalanceTickerWidget::updateDisplay);
|
||||
connect(&settings, &Settings::preferredFiatCurrencyChanged, m_sendWidget, QOverload<>::of(&SendWidget::onPreferredFiatCurrencyChanged));
|
||||
connect(&settings, &Settings::skinChanged, this, &MainWindow::skinChanged);
|
||||
settings.exec();
|
||||
}
|
||||
|
||||
void MainWindow::menuSignVerifyClicked() {
|
||||
|
@ -851,6 +853,10 @@ void MainWindow::skinChanged(const QString &skinName) {
|
|||
m_windowManager->changeSkin(skinName);
|
||||
ColorScheme::updateFromWidget(this);
|
||||
this->updateWidgetIcons();
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
this->patchStylesheetMac();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::updateWidgetIcons() {
|
||||
|
@ -1042,7 +1048,7 @@ void MainWindow::showWSNodeExhaustedMessage() {
|
|||
}
|
||||
|
||||
void MainWindow::exportKeyImages() {
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Save key images to file", QDir::homePath(), "Key Images (*_keyImages)");
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Save key images to file", QString("%1/%2_%3").arg(QDir::homePath(), this->walletName(), QString::number(QDateTime::currentSecsSinceEpoch())), "Key Images (*_keyImages)");
|
||||
if (fn.isEmpty()) return;
|
||||
if (!fn.endsWith("_keyImages")) fn += "_keyImages";
|
||||
m_ctx->wallet->exportKeyImages(fn, true);
|
||||
|
@ -1068,7 +1074,7 @@ void MainWindow::importKeyImages() {
|
|||
}
|
||||
|
||||
void MainWindow::exportOutputs() {
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Save outputs to file", QDir::homePath(), "Outputs (*_outputs)");
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Save outputs to file", QString("%1/%2_%3").arg(QDir::homePath(), this->walletName(), QString::number(QDateTime::currentSecsSinceEpoch())), "Outputs (*_outputs)");
|
||||
if (fn.isEmpty()) return;
|
||||
if (!fn.endsWith("_outputs")) fn += "_outputs";
|
||||
m_ctx->wallet->exportOutputs(fn, true);
|
||||
|
@ -1464,14 +1470,12 @@ void MainWindow::onCreateDesktopEntry(bool checked) {
|
|||
QMessageBox::information(this, "Desktop entry", msg);
|
||||
}
|
||||
|
||||
void MainWindow::onShowDocumentaton() {
|
||||
Utils::externalLinkWarning(this, "https://docs.featherwallet.org");
|
||||
}
|
||||
|
||||
void MainWindow::onReportBug(bool checked) {
|
||||
QMessageBox::information(this, "Reporting Bugs",
|
||||
"<body>Please report any bugs as issues on our git repo:<br>\n"
|
||||
"<a href=\"https://git.featherwallet.org/feather/feather/issues\" style=\"color: #33A4DF\">https://git.featherwallet.org/feather/feather/issues</a><br/><br/>"
|
||||
"\n"
|
||||
"Before reporting a bug, upgrade to the most recent version of Feather "
|
||||
"(latest release or git HEAD), and include the version number in your report. "
|
||||
"Try to explain not only what the bug is, but how it occurs.</body>");
|
||||
Utils::externalLinkWarning(this, "https://docs.featherwallet.org/guides/report-an-issue");
|
||||
}
|
||||
|
||||
QString MainWindow::getPlatformTag() {
|
||||
|
@ -1590,6 +1594,14 @@ bool MainWindow::verifyPassword() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void MainWindow::patchStylesheetMac() {
|
||||
auto patch = Utils::fileOpenQRC(":assets/macStylesheet.patch");
|
||||
auto patch_text = Utils::barrayToString(patch);
|
||||
|
||||
QString styleSheet = qApp->styleSheet() + patch_text;
|
||||
qApp->setStyleSheet(styleSheet);
|
||||
}
|
||||
|
||||
void MainWindow::toggleSearchbar(bool visible) {
|
||||
config()->set(Config::showSearchbar, visible);
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ private slots:
|
|||
void onExportHistoryCSV(bool checked);
|
||||
void onExportContactsCSV(bool checked);
|
||||
void onCreateDesktopEntry(bool checked);
|
||||
void onShowDocumentaton();
|
||||
void onReportBug(bool checked);
|
||||
|
||||
// offline tx signing
|
||||
|
@ -214,6 +215,7 @@ private:
|
|||
void updateRecentlyOpenedMenu();
|
||||
void updateWidgetIcons();
|
||||
bool verifyPassword();
|
||||
void patchStylesheetMac();
|
||||
|
||||
QIcon hardwareDevicePairedIcon();
|
||||
QIcon hardwareDeviceUnpairedIcon();
|
||||
|
@ -222,7 +224,6 @@ private:
|
|||
WindowManager *m_windowManager;
|
||||
QSharedPointer<AppContext> m_ctx;
|
||||
|
||||
Settings *m_windowSettings = nullptr;
|
||||
CalcWindow *m_windowCalc = nullptr;
|
||||
SplashDialog *m_splashDialog = nullptr;
|
||||
|
||||
|
|
|
@ -465,10 +465,12 @@
|
|||
</property>
|
||||
<addaction name="actionAbout"/>
|
||||
<addaction name="actionOfficialWebsite"/>
|
||||
<addaction name="actionDonate_to_Feather"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDocumentation"/>
|
||||
<addaction name="actionReport_bug"/>
|
||||
<addaction name="actionShow_debug_info"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDonate_to_Feather"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
|
@ -803,6 +805,11 @@
|
|||
<string>Address checker</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDocumentation">
|
||||
<property name="text">
|
||||
<string>Documentation</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "dialog/PaymentRequestDialog.h"
|
||||
#include "dialog/QrCodeDialog.h"
|
||||
#include "model/ModelUtils.h"
|
||||
#include "utils/Icons.h"
|
||||
|
@ -43,8 +44,6 @@ ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
m_headerMenu = new QMenu(this);
|
||||
m_showFullAddressesAction = m_headerMenu->addAction("Show full addresses", this, &ReceiveWidget::setShowFullAddresses);
|
||||
m_showFullAddressesAction->setCheckable(true);
|
||||
m_showUsedAddressesAction = m_headerMenu->addAction("Show used addresses", this, &ReceiveWidget::setShowUsedAddresses);
|
||||
m_showUsedAddressesAction->setCheckable(true);
|
||||
connect(ui->addresses->header(), &QHeaderView::customContextMenuRequested, this, &ReceiveWidget::showHeaderMenu);
|
||||
|
||||
// context menu
|
||||
|
@ -60,6 +59,8 @@ ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
|
||||
connect(ui->check_showUsed, &QCheckBox::clicked, this, &ReceiveWidget::setShowUsedAddresses);
|
||||
connect(ui->check_showHidden, &QCheckBox::clicked, this, &ReceiveWidget::setShowHiddenAddresses);
|
||||
|
||||
connect(ui->btn_createPaymentRequest, &QPushButton::clicked, this, &ReceiveWidget::createPaymentRequest);
|
||||
}
|
||||
|
||||
void ReceiveWidget::setSearchbarVisible(bool visible) {
|
||||
|
@ -96,9 +97,9 @@ void ReceiveWidget::showContextMenu(const QPoint &point) {
|
|||
|
||||
auto *menu = new QMenu(ui->addresses);
|
||||
|
||||
menu->addAction(icons()->icon("copy.png"), "Copy address", this, &ReceiveWidget::copyAddress);
|
||||
menu->addAction(icons()->icon("copy.png"), "Copy label", this, &ReceiveWidget::copyLabel);
|
||||
menu->addAction(icons()->icon("edit.png"), "Edit label", this, &ReceiveWidget::editLabel);
|
||||
menu->addAction("Copy address", this, &ReceiveWidget::copyAddress);
|
||||
menu->addAction("Copy label", this, &ReceiveWidget::copyLabel);
|
||||
menu->addAction("Edit label", this, &ReceiveWidget::editLabel);
|
||||
|
||||
if (isUsed) {
|
||||
menu->addAction(m_showTransactionsAction);
|
||||
|
@ -106,7 +107,7 @@ void ReceiveWidget::showContextMenu(const QPoint &point) {
|
|||
|
||||
QStringList hiddenAddresses = this->getHiddenAddresses();
|
||||
if (hiddenAddresses.contains(address)) {
|
||||
menu->addAction("Show address", this, &ReceiveWidget::showAddress);
|
||||
menu->addAction("Unhide address", this, &ReceiveWidget::showAddress);
|
||||
} else {
|
||||
menu->addAction("Hide address", this, &ReceiveWidget::hideAddress);
|
||||
}
|
||||
|
@ -118,6 +119,18 @@ void ReceiveWidget::showContextMenu(const QPoint &point) {
|
|||
menu->popup(ui->addresses->viewport()->mapToGlobal(point));
|
||||
}
|
||||
|
||||
void ReceiveWidget::createPaymentRequest() {
|
||||
QModelIndex index = ui->addresses->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString address = index.model()->data(index.siblingAtColumn(SubaddressModel::Address), Qt::UserRole).toString();
|
||||
|
||||
PaymentRequestDialog dialog{this, m_ctx, address};
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void ReceiveWidget::onShowTransactions() {
|
||||
QModelIndex index = ui->addresses->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
|
@ -190,6 +203,7 @@ void ReceiveWidget::updateQrCode(){
|
|||
QModelIndex index = ui->addresses->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
ui->qrCode->clear();
|
||||
ui->btn_createPaymentRequest->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -199,6 +213,7 @@ void ReceiveWidget::updateQrCode(){
|
|||
int width = ui->qrCode->width() - 4;
|
||||
if (qrc.isValid()) {
|
||||
ui->qrCode->setPixmap(qrc.toPixmap(1).scaled(width, width, Qt::KeepAspectRatio));
|
||||
ui->btn_createPaymentRequest->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ public slots:
|
|||
void setShowHiddenAddresses(bool show);
|
||||
void setSearchFilter(const QString &filter);
|
||||
void onShowTransactions();
|
||||
void createPaymentRequest();
|
||||
|
||||
signals:
|
||||
void showTransactions(const QString& address);
|
||||
|
|
|
@ -69,6 +69,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_createPaymentRequest">
|
||||
<property name="text">
|
||||
<string>Payment Request</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -31,8 +31,8 @@ SendWidget::SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
|
||||
connect(m_ctx.get(), &AppContext::initiateTransaction, this, &SendWidget::onInitiateTransaction);
|
||||
connect(m_ctx.get(), &AppContext::endTransaction, this, &SendWidget::onEndTransaction);
|
||||
connect(m_ctx.get(), &AppContext::openAliasResolved, this, &SendWidget::onOpenAliasResolved);
|
||||
connect(m_ctx.get(), &AppContext::openAliasResolveError, this, &SendWidget::onOpenAliasResolveError);
|
||||
|
||||
connect(WalletManager::instance(), &WalletManager::openAliasResolved, this, &SendWidget::onOpenAliasResolved);
|
||||
|
||||
connect(ui->btnScan, &QPushButton::clicked, this, &SendWidget::scanClicked);
|
||||
connect(ui->btnSend, &QPushButton::clicked, this, &SendWidget::sendClicked);
|
||||
|
@ -140,7 +140,7 @@ void SendWidget::sendClicked() {
|
|||
QString recipient = ui->lineAddress->text().simplified().remove(' ');
|
||||
QString description = ui->lineDescription->text();
|
||||
if (recipient.isEmpty()) {
|
||||
QMessageBox::warning(this, "Malformed recipient", "The recipient address was not correct");
|
||||
QMessageBox::warning(this, "Malformed recipient", "No destination address was entered.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ void SendWidget::sendClicked() {
|
|||
amount = this->amount();
|
||||
bool sendAll = (ui->lineAmount->text() == "all");
|
||||
if (amount == 0 && !sendAll) {
|
||||
QMessageBox::warning(this, "Amount error", "Invalid amount specified.");
|
||||
QMessageBox::warning(this, "Amount error", "No amount was entered.");
|
||||
return;
|
||||
}
|
||||
m_ctx->onCreateTransaction(recipient, amount, description, sendAll);
|
||||
|
@ -193,8 +193,9 @@ void SendWidget::sendClicked() {
|
|||
}
|
||||
|
||||
void SendWidget::aliasClicked() {
|
||||
auto address = ui->lineAddress->text();
|
||||
m_ctx->onOpenAliasResolve(address);
|
||||
ui->btn_openAlias->setEnabled(false);
|
||||
auto alias = ui->lineAddress->text();
|
||||
WalletManager::instance()->resolveOpenAliasAsync(alias);
|
||||
}
|
||||
|
||||
void SendWidget::clearClicked() {
|
||||
|
@ -254,7 +255,26 @@ double SendWidget::amountDouble() {
|
|||
return amount / constants::cdiv;
|
||||
}
|
||||
|
||||
void SendWidget::onOpenAliasResolved(const QString &address, const QString &openAlias) {
|
||||
void SendWidget::onOpenAliasResolved(const QString &openAlias, const QString &address, bool dnssecValid) {
|
||||
ui->btn_openAlias->setEnabled(true);
|
||||
|
||||
if (address.isEmpty()) {
|
||||
this->onOpenAliasResolveError("Could not resolve OpenAlias.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dnssecValid) {
|
||||
this->onOpenAliasResolveError("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool valid = WalletManager::addressValid(address, constants::networkType);
|
||||
if (!valid) {
|
||||
this->onOpenAliasResolveError(QString("Address validation error. Perhaps it is of the wrong network type.\n\n"
|
||||
"OpenAlias: %1\nAddress: %2").arg(openAlias, address));
|
||||
return;
|
||||
}
|
||||
|
||||
this->fill(address, openAlias);
|
||||
ui->btn_openAlias->hide();
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public slots:
|
|||
void fillAddress(const QString &address);
|
||||
void updateConversionLabel();
|
||||
void onOpenAliasResolveError(const QString &err);
|
||||
void onOpenAliasResolved(const QString &address, const QString &openAlias);
|
||||
void onOpenAliasResolved(const QString &openAlias, const QString &address, bool dnssecValid);
|
||||
void onPreferredFiatCurrencyChanged();
|
||||
|
||||
void onInitiateTransaction();
|
||||
|
|
|
@ -79,8 +79,9 @@ Settings::Settings(QSharedPointer<AppContext> ctx, QWidget *parent)
|
|||
|
||||
// Preferred fiat currency combobox
|
||||
QStringList fiatCurrencies;
|
||||
for (int index = 0; index < ui->comboBox_fiatCurrency->count(); index++)
|
||||
for (int index = 0; index < ui->comboBox_fiatCurrency->count(); index++) {
|
||||
fiatCurrencies << ui->comboBox_fiatCurrency->itemText(index);
|
||||
}
|
||||
|
||||
auto preferredFiatCurrency = config()->get(Config::preferredFiatCurrency).toString();
|
||||
if(!preferredFiatCurrency.isEmpty())
|
||||
|
|
|
@ -102,14 +102,6 @@ void WindowManager::startupWarning() {
|
|||
this->showWarningMessageBox("Warning", worthlessWarning.arg("testnet"));
|
||||
config()->set(Config::warnOnTestnet, false);
|
||||
}
|
||||
|
||||
// Beta
|
||||
if (config()->get(Config::warnOnAlpha).toBool()) {
|
||||
QString warning = "Feather Wallet is currently in beta.\n\nPlease report any bugs "
|
||||
"you encounter on our Git repository, IRC or on /r/FeatherWallet.";
|
||||
this->showWarningMessageBox("Beta warning", warning);
|
||||
config()->set(Config::warnOnAlpha, false);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::showWarningMessageBox(const QString &title, const QString &message) {
|
||||
|
@ -460,8 +452,6 @@ void WindowManager::initTor() {
|
|||
torManager()->init();
|
||||
torManager()->start();
|
||||
|
||||
connect(torManager(), &TorManager::connectionStateChanged, &websocketNotifier()->websocketClient, &WebsocketClient::onToggleConnect);
|
||||
|
||||
this->onTorSettingsChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,6 @@ AppContext::AppContext(Wallet *wallet)
|
|||
|
||||
this->updateBalance();
|
||||
|
||||
// force trigger preferredFiat signal for history model
|
||||
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
|
||||
|
||||
connect(this->wallet->history(), &TransactionHistory::txNoteChanged, [this]{
|
||||
this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
|
||||
});
|
||||
|
@ -75,7 +72,8 @@ void AppContext::onCreateTransaction(const QString &address, quint64 amount, con
|
|||
|
||||
quint64 unlocked_balance = this->wallet->unlockedBalance();
|
||||
if (!all && amount > unlocked_balance) {
|
||||
emit createTransactionError("Not enough money to spend");
|
||||
emit createTransactionError(QString("Not enough money to spend.\n\n"
|
||||
"Spendable balance: %1").arg(WalletManager::displayAmount(unlocked_balance)));
|
||||
return;
|
||||
} else if (unlocked_balance == 0) {
|
||||
emit createTransactionError("No money to spend");
|
||||
|
@ -132,14 +130,14 @@ void AppContext::onCancelTransaction(PendingTransaction *tx, const QVector<QStri
|
|||
this->wallet->disposeTransaction(tx);
|
||||
}
|
||||
|
||||
void AppContext::commitTransaction(PendingTransaction *tx) {
|
||||
void AppContext::commitTransaction(PendingTransaction *tx, const QString &description) {
|
||||
// Nodes - even well-connected, properly configured ones - consistently fail to relay transactions
|
||||
// To mitigate transactions failing we just send the transaction to every node we know about over Tor
|
||||
if (config()->get(Config::multiBroadcast).toBool()) {
|
||||
this->onMultiBroadcast(tx);
|
||||
}
|
||||
|
||||
this->wallet->commitTransactionAsync(tx);
|
||||
this->wallet->commitTransactionAsync(tx, description);
|
||||
}
|
||||
|
||||
void AppContext::onMultiBroadcast(PendingTransaction *tx) {
|
||||
|
@ -167,21 +165,6 @@ QString AppContext::getCacheTransaction(const QString &txid) const {
|
|||
return txHex;
|
||||
}
|
||||
|
||||
// ################## Models ##################
|
||||
|
||||
void AppContext::onPreferredFiatCurrencyChanged(const QString &symbol) {
|
||||
auto *model = this->wallet->transactionHistoryModel();
|
||||
if (model != nullptr) {
|
||||
model->preferredFiatSymbol = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
void AppContext::onAmountPrecisionChanged(int precision) {
|
||||
auto *model = this->wallet->transactionHistoryModel();
|
||||
if (!model) return;
|
||||
model->amountPrecision = precision;
|
||||
}
|
||||
|
||||
// ################## Device ##################
|
||||
|
||||
void AppContext::onDeviceButtonRequest(quint64 code) {
|
||||
|
@ -228,48 +211,6 @@ void AppContext::onSetRestoreHeight(quint64 height){
|
|||
emit customRestoreHeightSet(height);
|
||||
}
|
||||
|
||||
void AppContext::onOpenAliasResolve(const QString &openAlias) {
|
||||
// @TODO: calling this freezes for about 1-2 seconds :/
|
||||
const auto result = WalletManager::instance()->resolveOpenAlias(openAlias);; // TODO: async call
|
||||
const auto spl = result.split("|");
|
||||
auto msg = QString("");
|
||||
if(spl.count() != 2) {
|
||||
msg = "Internal error";
|
||||
emit openAliasResolveError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &status = spl.at(0);
|
||||
const auto &address = spl.at(1);
|
||||
const auto valid = WalletManager::addressValid(address, constants::networkType);
|
||||
if(status == "false"){
|
||||
if(valid){
|
||||
msg = "Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed";
|
||||
emit openAliasResolveError(msg);
|
||||
return;
|
||||
} else {
|
||||
msg = "No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed";
|
||||
emit openAliasResolveError(msg);
|
||||
return;
|
||||
}
|
||||
} else if(status != "true") {
|
||||
msg = "Internal error";
|
||||
emit openAliasResolveError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if(valid){
|
||||
emit openAliasResolved(address, openAlias);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = QString("Address validation error.");
|
||||
if(!address.isEmpty())
|
||||
msg += QString(" Perhaps it is of the wrong network type."
|
||||
"\n\nOpenAlias: %1\nAddress: %2").arg(openAlias).arg(address);
|
||||
emit openAliasResolveError(msg);
|
||||
}
|
||||
|
||||
void AppContext::stopTimers() {
|
||||
m_storeTimer.stop();
|
||||
}
|
||||
|
@ -365,13 +306,6 @@ void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QStr
|
|||
}
|
||||
|
||||
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
|
||||
if (status) {
|
||||
for (const auto &entry: txid) {
|
||||
this->wallet->setUserNote(entry, this->tmpTxDescription);
|
||||
}
|
||||
this->tmpTxDescription = "";
|
||||
}
|
||||
|
||||
// Store wallet immediately so we don't risk losing tx key if wallet crashes
|
||||
this->wallet->store();
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "utils/os/whonix.h"
|
||||
#include "utils/networking.h"
|
||||
#include "utils/wsclient.h"
|
||||
#include "utils/FeatherSeed.h"
|
||||
#include "utils/daemonrpc.h"
|
||||
#include "utils/RestoreHeightLookup.h"
|
||||
|
@ -38,7 +37,7 @@ public:
|
|||
// libwalletqt
|
||||
bool refreshed = false;
|
||||
|
||||
void commitTransaction(PendingTransaction *tx);
|
||||
void commitTransaction(PendingTransaction *tx, const QString &description="");
|
||||
void syncStatusUpdated(quint64 height, quint64 target);
|
||||
void updateBalance();
|
||||
void refreshModels();
|
||||
|
@ -56,10 +55,7 @@ public slots:
|
|||
void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
|
||||
void onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs);
|
||||
void onCreateTransactionError(const QString &msg);
|
||||
void onOpenAliasResolve(const QString &openAlias);
|
||||
void onSetRestoreHeight(quint64 height);
|
||||
void onPreferredFiatCurrencyChanged(const QString &symbol);
|
||||
void onAmountPrecisionChanged(int precision);
|
||||
void onMultiBroadcast(PendingTransaction *tx);
|
||||
void onDeviceButtonRequest(quint64 code);
|
||||
void onDeviceButtonPressed();
|
||||
|
@ -89,8 +85,6 @@ signals:
|
|||
void createTransactionError(QString message);
|
||||
void createTransactionCancelled(const QVector<QString> &address, quint64 amount);
|
||||
void createTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address);
|
||||
void openAliasResolveError(const QString &msg);
|
||||
void openAliasResolved(const QString &address, const QString &openAlias);
|
||||
void setRestoreHeightError(const QString &msg);
|
||||
void customRestoreHeightSet(int height);
|
||||
void initiateTransaction();
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<qresource prefix="/">
|
||||
<file>assets/about.txt</file>
|
||||
<file>assets/ack.txt</file>
|
||||
<file>assets/contributors.txt</file>
|
||||
<file>assets/feather.desktop</file>
|
||||
<file>assets/macStylesheet.patch</file>
|
||||
<file>assets/nodes.json</file>
|
||||
<file>assets/gpg_keys/featherwallet.asc</file>
|
||||
<file>assets/images/appicons/32x32.png</file>
|
||||
|
@ -35,6 +35,7 @@
|
|||
<file>assets/images/copy.png</file>
|
||||
<file>assets/images/cutexmrfox.png</file>
|
||||
<file>assets/images/edit.png</file>
|
||||
<file>assets/images/external-link.svg</file>
|
||||
<file>assets/images/exchange.png</file>
|
||||
<file>assets/images/exchange_white.png</file>
|
||||
<file>assets/images/expired.png</file>
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
Feather <feather_version> (<feather_git_head>)
|
||||
|
||||
Website: https://featherwallet.org
|
||||
E-mail: dev@featherwallet.org
|
||||
|
||||
Created by dsc, tobtoht, and contributors.
|
||||
|
||||
Uses icons from the Icons8 icon pack (icons8.com).
|
||||
|
||||
Copyright (c) 2020-<current_year>, The Monero Project
|
||||
|
||||
All rights reserved.
|
||||
|
|
|
@ -1,12 +1,82 @@
|
|||
The wallet UI is heavily inspired by Electrum. We would like to recognize Thomas Voegtlin for his pioneering work on Bitcoin.
|
||||
• The wallet UI is heavily inspired by Electrum. We would like to recognize Thomas Voegtlin for his pioneering work on Bitcoin.
|
||||
|
||||
Feather uses monero-seed written by Tevador, for 14 word mnemonic seeds.
|
||||
• Feather uses the monero-seed libary written by Tevador for 14 word mnemonic seeds.
|
||||
|
||||
Wizard banner art was adapted from a paper wallet design by the themonera (themonera.art).
|
||||
• Wizard banner art was adapted from a paper wallet design by the themonera (themonera.art).
|
||||
|
||||
Initial CMake support for the Monero GUI was coded by TheCharlatan/xiphon.
|
||||
• Uses icons from the Icons8 icon pack (icons8.com).
|
||||
|
||||
Huge thanks to nioc, fluffypony, wowario, thrmo for help during development.
|
||||
• Initial CMake support for the Monero GUI was coded by TheCharlatan/xiphon.
|
||||
|
||||
Some more shoutouts for people for hosting nodes and/or having good ideas:
|
||||
dnale0r, dEBRUYNE, binaryFate, lza_menace, jwinterm, kico, wowario
|
||||
Shoutouts:
|
||||
|
||||
Alex_LocalMonero
|
||||
anhdres
|
||||
authentic
|
||||
BigNastyHammer
|
||||
binaryFate
|
||||
bits-of-change
|
||||
blasty
|
||||
boldsuck
|
||||
boogerlad
|
||||
bruh
|
||||
btsfav
|
||||
csd
|
||||
CzarekNakamoto
|
||||
deanguss
|
||||
dEBRUYNE
|
||||
dnale0r
|
||||
fluffypony
|
||||
geonic
|
||||
GhostintheQubes
|
||||
GriftKilla
|
||||
jberman
|
||||
john_r365
|
||||
jwinterm
|
||||
kayabaNerve
|
||||
kico
|
||||
kinghat
|
||||
lozbek
|
||||
Lyza
|
||||
lza_menace
|
||||
Matt Smith
|
||||
MoneroArbo
|
||||
moneromooo
|
||||
mrdeveloper
|
||||
Nekun
|
||||
netrik182
|
||||
nikg83
|
||||
nioc
|
||||
noobmaximus
|
||||
n-peugnet
|
||||
onionltd
|
||||
Paris
|
||||
phoenix1213
|
||||
qvqc
|
||||
rating89us
|
||||
rbrunner
|
||||
rehrar
|
||||
rottenwheel
|
||||
samsunggalaxyplayer
|
||||
samwhiskey
|
||||
scoobybejesus
|
||||
selsta
|
||||
sethsimmons
|
||||
Shakybeats
|
||||
SmashTR
|
||||
SovereignStreetArt
|
||||
spoontechtips
|
||||
stickyf00t
|
||||
strace
|
||||
rottenwheel
|
||||
tevador
|
||||
thrmo
|
||||
tinkerwithtor
|
||||
Vespco
|
||||
viperperidot
|
||||
witchman05
|
||||
wowario
|
||||
xiphon
|
||||
xmrscott
|
||||
xubuntu
|
||||
yanmaani
|
|
@ -1,5 +0,0 @@
|
|||
dsc
|
||||
tobtoht
|
||||
selsta
|
||||
Diego Salazar
|
||||
Matt Smith
|
1
src/assets/images/external-link.svg
Normal file
1
src/assets/images/external-link.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"><path d="M 5 3 C 3.9069372 3 3 3.9069372 3 5 L 3 19 C 3 20.093063 3.9069372 21 5 21 L 19 21 C 20.093063 21 21 20.093063 21 19 L 21 12 L 19 12 L 19 19 L 5 19 L 5 5 L 12 5 L 12 3 L 5 3 z M 14 3 L 14 5 L 17.585938 5 L 8.2929688 14.292969 L 9.7070312 15.707031 L 19 6.4140625 L 19 10 L 21 10 L 21 3 L 14 3 z"/></svg>
|
After Width: | Height: | Size: 415 B |
31
src/assets/macStylesheet.patch
Normal file
31
src/assets/macStylesheet.patch
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* From electrum/gui/qt/stylesheet_patcher.py */
|
||||
StatusBarButton {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
margin: 0px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
StatusBarButton:checked {
|
||||
background-color: transparent;
|
||||
border: 1px solid #1464A0;
|
||||
}
|
||||
|
||||
StatusBarButton:checked:disabled {
|
||||
border: 1px solid #14506E;
|
||||
}
|
||||
|
||||
StatusBarButton:pressed {
|
||||
margin: 1px;
|
||||
background-color: transparent;
|
||||
border: 1px solid #1464A0;
|
||||
}
|
||||
|
||||
StatusBarButton:disabled {
|
||||
border: none;
|
||||
}
|
||||
|
||||
StatusBarButton:hover {
|
||||
border: 1px solid #148CD2;
|
||||
}
|
|
@ -1,16 +1,22 @@
|
|||
{
|
||||
"mainnet": {
|
||||
"tor": [
|
||||
"sfprpc5klzs5vyitq2mrooicgk2wcs5ho2nm3niqduvzn5o6ylaslaqd.onion:18089",
|
||||
"sfprpc2fws6ltnq4hyr7lvpul3nank5layd7q7tyc5h4gy4h77gtabad.onion:18089",
|
||||
"mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion:18081",
|
||||
"moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18089",
|
||||
"rbpgdckle3h3vi4wwwrh75usqtoc5r3alohy7yyx57isynvay63nacyd.onion:18089",
|
||||
"6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion:18081",
|
||||
"56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089",
|
||||
"melo7jwjspngus3xhbt5kxeqc4njhokyvh55jfmehplglgmb7a6rb6yd.onion:18081"
|
||||
"melo7jwjspngus3xhbt5kxeqc4njhokyvh55jfmehplglgmb7a6rb6yd.onion:18081",
|
||||
"ip4zpbps7unk6xhlanqtw24f75akfbl3upeckfjqjks7ftfnk4i73oid.onion:18081",
|
||||
"ghziyspoobhmp5oun2xcomrmetqiwbvuaegmte3s47nnqv7hkaa64sid.onion:18089",
|
||||
"xmrnodesarnt4w35aqmu66aart3o324yw6qbnv6pglpof6uqaydzk5id.onion:18081",
|
||||
"usexmr2eeexmlwpuvsfe6tyjmdqliplb2b7uxju6yrrziq3n7fksnxyd.onion:18081"
|
||||
],
|
||||
"clearnet": [
|
||||
"node.melo.tools:18081",
|
||||
"node-1.sethsimmons.me:18089",
|
||||
"node.sethforprivacy.com:18089",
|
||||
"node2.sethforprivacy.com:18089",
|
||||
"selsta1.featherwallet.net:18081",
|
||||
"selsta2.featherwallet.net:18081",
|
||||
"node.monerooutreach.org:18081",
|
||||
|
|
|
@ -114,3 +114,11 @@ ClickableLabel::~ClickableLabel() = default;
|
|||
void ClickableLabel::mousePressEvent(QMouseEvent* event) {
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
WindowModalDialog::WindowModalDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
#ifndef Q_OS_MACOS
|
||||
this->setWindowModality(Qt::WindowModal);
|
||||
#endif
|
||||
}
|
|
@ -121,4 +121,11 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
class WindowModalDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WindowModalDialog(QWidget *parent);
|
||||
};
|
||||
|
||||
#endif //FEATHER_COMPONENTS_H
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
#include "utils/Utils.h"
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::AboutDialog)
|
||||
, m_model(new QStringListModel(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->setWindowIcon(QIcon("://assets/images/appicons/64x64.png"));
|
||||
|
||||
// cute fox (c) Diego "rehrar" Salazar :-D
|
||||
QPixmap p(":assets/images/cutexmrfox.png");
|
||||
ui->aboutImage->setPixmap(p.scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
|
@ -28,14 +27,6 @@ AboutDialog::AboutDialog(QWidget *parent)
|
|||
auto ack_text = Utils::barrayToString(ack);
|
||||
ui->ackText->setText(ack_text);
|
||||
|
||||
QString contributors = Utils::barrayToString(Utils::fileOpenQRC(":assets/contributors.txt"));
|
||||
QStringList contributor_list = contributors.split("\n");
|
||||
m_model->setStringList(contributor_list);
|
||||
|
||||
ui->authorView->setHeaderHidden(true);
|
||||
ui->authorView->setModel(this->m_model);
|
||||
ui->authorView->header()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
#include <QDialog>
|
||||
#include <QStringListModel>
|
||||
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class AboutDialog;
|
||||
}
|
||||
|
||||
class AboutDialog : public QDialog
|
||||
class AboutDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -21,7 +23,6 @@ public:
|
|||
|
||||
private:
|
||||
QScopedPointer<Ui::AboutDialog> ui;
|
||||
QStringListModel *m_model;
|
||||
};
|
||||
|
||||
#endif // FEATHER_ABOUT_H
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>a free, open-source Monero wallet</string>
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">Feather</span>: a free, open-source Monero wallet</p><p>Created by dsc, tobtoht and contributors</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
@ -71,18 +71,144 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="Authors">
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Authors</string>
|
||||
<string>Info</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTreeView" name="authorView">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Website:</string>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Docs:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Git:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Reddit:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>IRC:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Matrix:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Email:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>featherwallet.org</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>docs.featherwallet.org</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>git.featherwallet.org</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>/r/FeatherWallet</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>#feather on OFTC</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>#_oftc_#feather:matrix.org</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>dev@featherwallet.org</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Twitter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>@featherwallet</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "utils/Icons.h"
|
||||
|
||||
AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::AccountSwitcherDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
, m_model(m_ctx->wallet->subaddressAccountModel())
|
||||
|
@ -25,6 +25,8 @@ AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWi
|
|||
ui->label_totalBalance->setFont(ModelUtils::getMonospaceFont());
|
||||
ui->label_totalBalance->setText(WalletManager::displayAmount(m_ctx->wallet->balanceAll()));
|
||||
|
||||
this->setWindowModality(Qt::WindowModal);
|
||||
|
||||
ui->accounts->setModel(m_proxyModel);
|
||||
ui->accounts->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
ui->accounts->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "model/SubaddressAccountModel.h"
|
||||
|
||||
namespace Ui {
|
||||
class AccountSwitcherDialog;
|
||||
}
|
||||
|
||||
class AccountSwitcherDialog : public QDialog
|
||||
class AccountSwitcherDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "model/ModelUtils.h"
|
||||
|
||||
BalanceDialog::BalanceDialog(QWidget *parent, Wallet *wallet)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::BalanceDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "libwalletqt/Wallet.h"
|
||||
|
||||
namespace Ui {
|
||||
class BalanceDialog;
|
||||
}
|
||||
|
||||
class BalanceDialog : public QDialog
|
||||
class BalanceDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "utils/config.h"
|
||||
|
||||
CalcConfigDialog::CalcConfigDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::CalcConfigDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
#include <QDialog>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class CalcConfigDialog;
|
||||
}
|
||||
|
||||
class CalcConfigDialog : public QDialog
|
||||
class CalcConfigDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "ContactsDialog.h"
|
||||
|
||||
ContactsDialog::ContactsDialog(QWidget *parent, const QString &address, const QString &name)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::ContactsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class ContactsDialog;
|
||||
}
|
||||
|
||||
class ContactsDialog : public QDialog
|
||||
class ContactsDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "utils/WebsocketNotifier.h"
|
||||
|
||||
DebugInfoDialog::DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::DebugInfoDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "libwalletqt/Wallet.h"
|
||||
|
||||
namespace Ui {
|
||||
class DebugInfoDialog;
|
||||
}
|
||||
|
||||
class DebugInfoDialog : public QDialog
|
||||
class DebugInfoDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "ui_InfoDialog.h"
|
||||
|
||||
InfoDialog::InfoDialog(QWidget *parent, const QString &title, const QString &infoData)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::InfoDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class InfoDialog;
|
||||
}
|
||||
|
||||
class InfoDialog : public QDialog
|
||||
class InfoDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "ui_KeysDialog.h"
|
||||
|
||||
KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::KeysDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class KeysDialog;
|
||||
}
|
||||
|
||||
class KeysDialog : public QDialog
|
||||
class KeysDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "utils/Utils.h"
|
||||
|
||||
LocalMoneroInfoDialog::LocalMoneroInfoDialog(QWidget *parent, LocalMoneroModel *model, int row)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::LocalMoneroInfoDialog)
|
||||
, m_model(model)
|
||||
, m_row(row)
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
|
||||
#include "components.h"
|
||||
#include "model/LocalMoneroModel.h"
|
||||
|
||||
namespace Ui {
|
||||
class LocalMoneroInfoDialog;
|
||||
}
|
||||
|
||||
class LocalMoneroInfoDialog : public QDialog
|
||||
class LocalMoneroInfoDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "utils/Utils.h"
|
||||
|
||||
OutputInfoDialog::OutputInfoDialog(CoinsInfo *cInfo, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::OutputInfoDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "libwalletqt/Coins.h"
|
||||
#include "libwalletqt/CoinsInfo.h"
|
||||
|
||||
|
@ -13,7 +14,7 @@ namespace Ui {
|
|||
class OutputInfoDialog;
|
||||
}
|
||||
|
||||
class OutputInfoDialog : public QDialog
|
||||
class OutputInfoDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "libwalletqt/WalletManager.h"
|
||||
|
||||
OutputSweepDialog::OutputSweepDialog(QWidget *parent, quint64 amount)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::OutputSweepDialog)
|
||||
, m_amount(amount)
|
||||
{
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "libwalletqt/CoinsInfo.h"
|
||||
|
||||
namespace Ui {
|
||||
class OutputSweepDialog;
|
||||
}
|
||||
|
||||
class OutputSweepDialog : public QDialog
|
||||
class OutputSweepDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <QMessageBox>
|
||||
|
||||
PasswordChangeDialog::PasswordChangeDialog(QWidget *parent, Wallet *wallet)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::PasswordChangeDialog)
|
||||
, m_wallet(wallet)
|
||||
{
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "libwalletqt/Wallet.h"
|
||||
|
||||
namespace Ui {
|
||||
class PasswordChangeDialog;
|
||||
}
|
||||
|
||||
class PasswordChangeDialog : public QDialog
|
||||
class PasswordChangeDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "utils/Icons.h"
|
||||
|
||||
PasswordDialog::PasswordDialog(const QString &walletName, bool incorrectPassword, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::PasswordDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class PasswordDialog;
|
||||
}
|
||||
|
||||
class PasswordDialog : public QDialog
|
||||
class PasswordDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
82
src/dialog/PaymentRequestDialog.cpp
Normal file
82
src/dialog/PaymentRequestDialog.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020-2021, The Monero Project.
|
||||
|
||||
#include "PaymentRequestDialog.h"
|
||||
#include "ui_PaymentRequestDialog.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
#include "WalletManager.h"
|
||||
|
||||
PaymentRequestDialog::PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::PaymentRequestDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
, m_address(std::move(address))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QString amount_rx = R"(^\d{0,8}[\.]\d{0,12}|(all)$)";
|
||||
QRegExp rx;
|
||||
rx.setPattern(amount_rx);
|
||||
QValidator *validator = new QRegExpValidator(rx, this);
|
||||
ui->line_amountXMR->setValidator(validator);
|
||||
|
||||
connect(ui->line_amountXMR, &QLineEdit::textChanged, this, &PaymentRequestDialog::updatePaymentRequest);
|
||||
connect(ui->line_description, &QLineEdit::textChanged, this, &PaymentRequestDialog::updatePaymentRequest);
|
||||
connect(ui->line_recipient, &QLineEdit::textChanged, this, &PaymentRequestDialog::updatePaymentRequest);
|
||||
|
||||
connect(ui->btn_copyLink, &QPushButton::clicked, this, &PaymentRequestDialog::copyLink);
|
||||
connect(ui->btn_copyImage, &QPushButton::clicked, this, &PaymentRequestDialog::copyImage);
|
||||
connect(ui->btn_saveImage, &QPushButton::clicked, this, &PaymentRequestDialog::saveImage);
|
||||
|
||||
this->updatePaymentRequest();
|
||||
|
||||
ui->line_amountXMR->setFocus();
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
void PaymentRequestDialog::updatePaymentRequest() {
|
||||
QString description = ui->line_description->text();
|
||||
QString recipient = ui->line_recipient->text();
|
||||
quint64 amount = WalletManager::amountFromString(ui->line_amountXMR->text());
|
||||
|
||||
QString uri = m_ctx->wallet->make_uri(m_address, amount, description, recipient);
|
||||
|
||||
ui->line_paymentRequestUri->setText(uri);
|
||||
ui->line_paymentRequestUri->setCursorPosition(0);
|
||||
|
||||
// TODO: memory leak, cba to refactor now
|
||||
m_qrCode = new QrCode(uri, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::MEDIUM);
|
||||
if (m_qrCode->isValid()) {
|
||||
ui->qrWidget->setQrCode(m_qrCode);
|
||||
}
|
||||
}
|
||||
|
||||
void PaymentRequestDialog::copyLink() {
|
||||
Utils::copyToClipboard(ui->line_paymentRequestUri->text());
|
||||
QMessageBox::information(this, "Information", "Payment request link copied to clipboard.");
|
||||
}
|
||||
|
||||
void PaymentRequestDialog::copyImage() {
|
||||
QApplication::clipboard()->setPixmap(m_qrCode->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio));
|
||||
QMessageBox::information(this, "Information", "QR code copied to clipboard.");
|
||||
}
|
||||
|
||||
void PaymentRequestDialog::saveImage() {
|
||||
QString filename = QFileDialog::getSaveFileName(this, "Select where to save file", QDir::current().filePath("qrcode.png"));
|
||||
if (filename.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
m_qrCode->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio).save(&file, "PNG");
|
||||
QMessageBox::information(this, "Information", "QR code saved to file");
|
||||
}
|
||||
|
||||
PaymentRequestDialog::~PaymentRequestDialog() = default;
|
38
src/dialog/PaymentRequestDialog.h
Normal file
38
src/dialog/PaymentRequestDialog.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020-2021, The Monero Project.
|
||||
|
||||
#ifndef FEATHER_PAYMENTREQUESTDIALOG_H
|
||||
#define FEATHER_PAYMENTREQUESTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "qrcode/QrCode.h"
|
||||
|
||||
namespace Ui {
|
||||
class PaymentRequestDialog;
|
||||
}
|
||||
|
||||
class PaymentRequestDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address);
|
||||
~PaymentRequestDialog() override;
|
||||
|
||||
private slots:
|
||||
void updatePaymentRequest();
|
||||
void copyLink();
|
||||
void copyImage();
|
||||
void saveImage();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::PaymentRequestDialog> ui;
|
||||
QSharedPointer<AppContext> m_ctx;
|
||||
QString m_address;
|
||||
QrCode *m_qrCode;
|
||||
};
|
||||
|
||||
#endif //FEATHER_PAYMENTREQUESTDIALOG_H
|
203
src/dialog/PaymentRequestDialog.ui
Normal file
203
src/dialog/PaymentRequestDialog.ui
Normal file
|
@ -0,0 +1,203 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PaymentRequestDialog</class>
|
||||
<widget class="QDialog" name="PaymentRequestDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>658</width>
|
||||
<height>761</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create Payment Request</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QrCodeWidget" name="qrWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="line_paymentRequestUri">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Amount:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="line_amountXMR">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>XMR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="line_description"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Your name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="line_recipient"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_copyLink">
|
||||
<property name="text">
|
||||
<string>Copy Link</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_copyImage">
|
||||
<property name="text">
|
||||
<string>Copy Image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_saveImage">
|
||||
<property name="text">
|
||||
<string>Save Image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QrCodeWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/QrCodeWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>PaymentRequestDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PaymentRequestDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -9,7 +9,7 @@
|
|||
#include <QMessageBox>
|
||||
|
||||
QrCodeDialog::QrCodeDialog(QWidget *parent, QrCode *qrCode, const QString &title)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::QrCodeDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "qrcode/QrCode.h"
|
||||
#include "widgets/QrCodeWidget.h"
|
||||
|
||||
|
@ -13,7 +14,7 @@ namespace Ui {
|
|||
class QrCodeDialog;
|
||||
}
|
||||
|
||||
class QrCodeDialog : public QDialog
|
||||
class QrCodeDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <QDialogButtonBox>
|
||||
|
||||
RestoreHeightDialog::RestoreHeightDialog(QWidget *parent, quint64 currentRestoreHeight)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, m_restoreHeightWidget(new RestoreHeightWidget(this))
|
||||
{
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "widgets/RestoreHeightWidget.h"
|
||||
|
||||
class RestoreHeightDialog : public QDialog
|
||||
class RestoreHeightDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "constants.h"
|
||||
|
||||
SeedDialog::SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::SeedDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class SeedDialog;
|
||||
}
|
||||
|
||||
class SeedDialog : public QDialog
|
||||
class SeedDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "utils/Utils.h"
|
||||
|
||||
SignVerifyDialog::SignVerifyDialog(Wallet *wallet, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::SignVerifyDialog)
|
||||
, m_wallet(wallet)
|
||||
{
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
#include "libwalletqt/Wallet.h"
|
||||
|
||||
namespace Ui {
|
||||
class SignVerifyDialog;
|
||||
}
|
||||
|
||||
class SignVerifyDialog : public QDialog
|
||||
class SignVerifyDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "utils/Icons.h"
|
||||
|
||||
SplashDialog::SplashDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::SplashDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class SplashDialog;
|
||||
}
|
||||
|
||||
class SplashDialog : public QDialog
|
||||
class SplashDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "utils/NetworkManager.h"
|
||||
|
||||
TxBroadcastDialog::TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::TxBroadcastDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "utils/daemonrpc.h"
|
||||
|
||||
namespace Ui {
|
||||
class TxBroadcastDialog;
|
||||
}
|
||||
|
||||
class TxBroadcastDialog : public QDialog
|
||||
class TxBroadcastDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "constants.h"
|
||||
#include "dialog/QrCodeDialog.h"
|
||||
#include "libwalletqt/Input.h"
|
||||
#include "libwalletqt/Transfer.h"
|
||||
|
@ -14,7 +15,7 @@
|
|||
#include "qrcode/QrCode.h"
|
||||
|
||||
TxConfAdvDialog::TxConfAdvDialog(QSharedPointer<AppContext> ctx, const QString &description, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::TxConfAdvDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
, m_exportUnsignedMenu(new QMenu(this))
|
||||
|
@ -35,42 +36,51 @@ TxConfAdvDialog::TxConfAdvDialog(QSharedPointer<AppContext> ctx, const QString &
|
|||
m_exportTxKeyMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::txKeyCopy);
|
||||
ui->btn_exportTxKey->setMenu(m_exportTxKeyMenu);
|
||||
|
||||
if (m_ctx->wallet->viewOnly()) {
|
||||
ui->btn_exportSigned->hide();
|
||||
ui->btn_send->hide();
|
||||
}
|
||||
|
||||
ui->label_description->setText(QString("Description: %1").arg(description));
|
||||
ui->line_description->setText(description);
|
||||
|
||||
connect(ui->btn_sign, &QPushButton::clicked, this, &TxConfAdvDialog::signTransaction);
|
||||
connect(ui->btn_send, &QPushButton::clicked, this, &TxConfAdvDialog::broadcastTransaction);
|
||||
connect(ui->btn_close, &QPushButton::clicked, this, &TxConfAdvDialog::closeDialog);
|
||||
|
||||
ui->amount->setFont(ModelUtils::getMonospaceFont());
|
||||
ui->fee->setFont(ModelUtils::getMonospaceFont());
|
||||
ui->total->setFont(ModelUtils::getMonospaceFont());
|
||||
|
||||
ui->inputs->setFont(ModelUtils::getMonospaceFont());
|
||||
ui->outputs->setFont(ModelUtils::getMonospaceFont());
|
||||
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
void TxConfAdvDialog::setTransaction(PendingTransaction *tx) {
|
||||
void TxConfAdvDialog::setTransaction(PendingTransaction *tx, bool isSigned) {
|
||||
ui->btn_sign->hide();
|
||||
|
||||
if (!isSigned) {
|
||||
ui->btn_exportSigned->hide();
|
||||
ui->btn_send->hide();
|
||||
}
|
||||
|
||||
m_tx = tx;
|
||||
m_tx->refresh();
|
||||
PendingTransactionInfo *ptx = m_tx->transaction(0); //Todo: support split transactions
|
||||
|
||||
ui->txid->setText(tx->txid().first());
|
||||
// TODO: implement hasTxKey()
|
||||
if (!m_ctx->wallet->isHwBacked() && m_tx->transaction(0)->txKey() == "0100000000000000000000000000000000000000000000000000000000000000") {
|
||||
ui->btn_exportTxKey->hide();
|
||||
}
|
||||
|
||||
ui->amount->setText(WalletManager::displayAmount(tx->amount()));
|
||||
ui->fee->setText(WalletManager::displayAmount(ptx->fee()));
|
||||
ui->total->setText(WalletManager::displayAmount(tx->amount() + ptx->fee()));
|
||||
m_txid = tx->txid().first();
|
||||
ui->txid->setText(m_txid);
|
||||
|
||||
auto size_str = [this]{
|
||||
if (m_ctx->wallet->viewOnly()) {
|
||||
return QString("Size: %1 bytes (unsigned)").arg(QString::number(m_tx->unsignedTxToBin().size()));
|
||||
} else {
|
||||
this->setAmounts(tx->amount(), tx->fee());
|
||||
|
||||
auto size_str = [this, isSigned]{
|
||||
if (isSigned) {
|
||||
auto size = m_tx->signedTxToHex(0).size() / 2;
|
||||
return QString("Size: %1 bytes (%2 bytes unsigned)").arg(QString::number(size), QString::number(m_tx->unsignedTxToBin().size()));
|
||||
} else {
|
||||
|
||||
return QString("Size: %1 bytes (unsigned)").arg(QString::number(m_tx->unsignedTxToBin().size()));
|
||||
}
|
||||
}();
|
||||
ui->label_size->setText(size_str);
|
||||
|
@ -91,14 +101,38 @@ void TxConfAdvDialog::setUnsignedTransaction(UnsignedTransaction *utx) {
|
|||
ui->txid->setText("n/a");
|
||||
ui->label_size->setText("Size: n/a");
|
||||
|
||||
ui->amount->setText(WalletManager::displayAmount(utx->amount(0)));
|
||||
ui->fee->setText(WalletManager::displayAmount(utx->fee(0)));
|
||||
ui->total->setText(WalletManager::displayAmount(utx->amount(0) + utx->fee(0)));
|
||||
this->setAmounts(utx->amount(0), utx->fee(0));
|
||||
|
||||
ConstructionInfo *ci = m_utx->constructionInfo(0);
|
||||
this->setupConstructionData(ci);
|
||||
}
|
||||
|
||||
void TxConfAdvDialog::setAmounts(quint64 amount, quint64 fee) {
|
||||
QString preferredCur = config()->get(Config::preferredFiatCurrency).toString();
|
||||
|
||||
auto convert = [preferredCur](double amount){
|
||||
return QString::number(appData()->prices.convert("XMR", preferredCur, amount), 'f', 2);
|
||||
};
|
||||
|
||||
QString amount_str = WalletManager::displayAmount(amount);
|
||||
QString fee_str = WalletManager::displayAmount(fee);
|
||||
QString total = WalletManager::displayAmount(amount + fee);
|
||||
QVector<QString> amounts = {amount_str, fee_str, total};
|
||||
int maxLength = Utils::maxLength(amounts);
|
||||
std::for_each(amounts.begin(), amounts.end(), [maxLength](QString& amount){amount = amount.rightJustified(maxLength, ' ');});
|
||||
|
||||
QString amount_fiat = convert(amount / constants::cdiv);
|
||||
QString fee_fiat = convert(fee / constants::cdiv);
|
||||
QString total_fiat = convert((amount + fee) / constants::cdiv);
|
||||
QVector<QString> amounts_fiat = {amount_fiat, fee_fiat, total_fiat};
|
||||
int maxLengthFiat = Utils::maxLength(amounts_fiat);
|
||||
std::for_each(amounts_fiat.begin(), amounts_fiat.end(), [maxLengthFiat](QString& amount){amount = amount.rightJustified(maxLengthFiat, ' ');});
|
||||
|
||||
ui->amount->setText(QString("%1 (%2 %3)").arg(amounts[0], amounts_fiat[0], preferredCur));
|
||||
ui->fee->setText(QString("%1 (%2 %3)").arg(amounts[1], amounts_fiat[1], preferredCur));
|
||||
ui->total->setText(QString("%1 (%2 %3)").arg(amounts[2], amounts_fiat[2], preferredCur));
|
||||
}
|
||||
|
||||
void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
|
||||
QString inputs_str;
|
||||
auto inputs = ci->inputs();
|
||||
|
@ -122,7 +156,6 @@ void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
|
|||
ui->label_outputs->setText(QString("Outputs (%1)").arg(QString::number(outputs.size())));
|
||||
|
||||
ui->label_ringSize->setText(QString("Ring size: %1").arg(QString::number(ci->minMixinCount() + 1)));
|
||||
ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(QString::number(ci->unlockTime())));
|
||||
}
|
||||
|
||||
void TxConfAdvDialog::signTransaction() {
|
||||
|
@ -180,7 +213,7 @@ void TxConfAdvDialog::signedQrCode() {
|
|||
|
||||
void TxConfAdvDialog::broadcastTransaction() {
|
||||
if (m_tx == nullptr) return;
|
||||
m_ctx->commitTransaction(m_tx);
|
||||
m_ctx->commitTransaction(m_tx, ui->line_description->text());
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,14 @@
|
|||
#include <QTextCharFormat>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "libwalletqt/PendingTransaction.h"
|
||||
|
||||
namespace Ui {
|
||||
class TxConfAdvDialog;
|
||||
}
|
||||
|
||||
class TxConfAdvDialog : public QDialog
|
||||
class TxConfAdvDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -24,7 +25,7 @@ public:
|
|||
explicit TxConfAdvDialog(QSharedPointer<AppContext> ctx, const QString &description, QWidget *parent = nullptr);
|
||||
~TxConfAdvDialog() override;
|
||||
|
||||
void setTransaction(PendingTransaction *tx);
|
||||
void setTransaction(PendingTransaction *tx, bool isSigned = true); // #TODO: have libwallet return a UnsignedTransaction, this is just dumb
|
||||
void setUnsignedTransaction(UnsignedTransaction *utx);
|
||||
|
||||
private:
|
||||
|
@ -32,6 +33,7 @@ private:
|
|||
void signTransaction();
|
||||
void broadcastTransaction();
|
||||
void closeDialog();
|
||||
void setAmounts(quint64 amount, quint64 fee);
|
||||
|
||||
void unsignedCopy();
|
||||
void unsignedQrCode();
|
||||
|
@ -50,6 +52,7 @@ private:
|
|||
QMenu *m_exportUnsignedMenu;
|
||||
QMenu *m_exportSignedMenu;
|
||||
QMenu *m_exportTxKeyMenu;
|
||||
QString m_txid;
|
||||
};
|
||||
|
||||
#endif //FEATHER_TXCONFADVDIALOG_H
|
||||
|
|
|
@ -21,15 +21,15 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Transaction ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="txid">
|
||||
<property name="text">
|
||||
<string>txid</string>
|
||||
|
@ -42,14 +42,55 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_description">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<widget class="QLineEdit" name="line_description"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_size">
|
||||
<property name="text">
|
||||
<string>Size: </string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_ringSize">
|
||||
<property name="text">
|
||||
<string>Ringsize:</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
|
@ -112,57 +153,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_description">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_size">
|
||||
<property name="text">
|
||||
<string>Size: </string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_unlockTime">
|
||||
<property name="text">
|
||||
<string>Unlock time: </string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_ringSize">
|
||||
<property name="text">
|
||||
<string>Ringsize:</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "utils/ColorScheme.h"
|
||||
|
||||
TxConfDialog::TxConfDialog(QSharedPointer<AppContext> ctx, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::TxConfDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
, m_tx(tx)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "libwalletqt/PendingTransaction.h"
|
||||
#include "libwalletqt/WalletManager.h"
|
||||
|
||||
|
@ -14,7 +15,7 @@ namespace Ui {
|
|||
class TxConfDialog;
|
||||
}
|
||||
|
||||
class TxConfDialog : public QDialog
|
||||
class TxConfDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "utils/NetworkManager.h"
|
||||
|
||||
TxImportDialog::TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::TxImportDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
, m_loadTimer(new QTimer(this))
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "utils/daemonrpc.h"
|
||||
|
||||
namespace Ui {
|
||||
class TxImportDialog;
|
||||
}
|
||||
|
||||
class TxImportDialog : public QDialog
|
||||
class TxImportDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "appcontext.h"
|
||||
#include "config.h"
|
||||
#include "constants.h"
|
||||
#include "libwalletqt/Coins.h"
|
||||
#include "libwalletqt/CoinsInfo.h"
|
||||
#include "libwalletqt/TransactionHistory.h"
|
||||
|
@ -16,6 +17,7 @@
|
|||
#include "libwalletqt/WalletManager.h"
|
||||
#include "model/ModelUtils.h"
|
||||
#include "Utils.h"
|
||||
#include "utils/Icons.h"
|
||||
|
||||
TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txInfo, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
|
@ -26,11 +28,16 @@ TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txIn
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->btn_viewOnBlockExplorer->setIcon(icons()->icon("external-link.svg"));
|
||||
ui->btn_viewOnBlockExplorer->setToolTip("View on block explorer");
|
||||
connect(ui->btn_viewOnBlockExplorer, &QPushButton::clicked, this, &TxInfoDialog::viewOnBlockExplorer);
|
||||
|
||||
m_txid = txInfo->hash();
|
||||
ui->label_txid->setText(m_txid);
|
||||
|
||||
connect(ui->btn_CopyTxKey, &QPushButton::pressed, this, &TxInfoDialog::copyTxKey);
|
||||
connect(ui->btn_createTxProof, &QPushButton::pressed, this, &TxInfoDialog::createTxProof);
|
||||
connect(ui->btn_copyTxID, &QPushButton::clicked, this, &TxInfoDialog::copyTxID);
|
||||
connect(ui->btn_CopyTxKey, &QPushButton::clicked, this, &TxInfoDialog::copyTxKey);
|
||||
connect(ui->btn_createTxProof, &QPushButton::clicked, this, &TxInfoDialog::createTxProof);
|
||||
|
||||
connect(m_ctx->wallet, &Wallet::newBlock, this, &TxInfoDialog::updateData);
|
||||
|
||||
|
@ -43,6 +50,12 @@ TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txIn
|
|||
} else {
|
||||
ui->btn_rebroadcastTx->hide();
|
||||
}
|
||||
|
||||
if (txInfo->direction() == TransactionInfo::Direction_In) {
|
||||
ui->btn_CopyTxKey->setDisabled(true);
|
||||
ui->btn_CopyTxKey->setToolTip("No tx secret key available for incoming transactions.");
|
||||
}
|
||||
|
||||
//
|
||||
// if (txInfo->direction() == TransactionInfo::Direction_Out) {
|
||||
// // TODO: this will not properly represent coinjoin-like transactions.
|
||||
|
@ -78,6 +91,9 @@ TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txIn
|
|||
}
|
||||
|
||||
this->adjustSize();
|
||||
|
||||
// Don't autofocus any of the buttons. There is probably a better way for this.
|
||||
ui->label_txid->setFocus();
|
||||
}
|
||||
|
||||
void TxInfoDialog::adjustHeight(QTextEdit *textEdit, qreal docHeight) {
|
||||
|
@ -140,6 +156,10 @@ void TxInfoDialog::updateData() {
|
|||
this->setData(tx);
|
||||
}
|
||||
|
||||
void TxInfoDialog::copyTxID() {
|
||||
Utils::copyToClipboard(m_txid);
|
||||
}
|
||||
|
||||
void TxInfoDialog::copyTxKey() {
|
||||
m_ctx->wallet->getTxKeyAsync(m_txid, [this](QVariantMap map){
|
||||
QString txKey = map.value("tx_key").toString();
|
||||
|
@ -157,4 +177,8 @@ void TxInfoDialog::createTxProof() {
|
|||
m_txProofDialog->getTxKey();
|
||||
}
|
||||
|
||||
void TxInfoDialog::viewOnBlockExplorer() {
|
||||
Utils::externalLinkWarning(this, Utils::blockExplorerLink(config()->get(Config::blockExplorer).toString(), constants::networkType, m_txid));
|
||||
}
|
||||
|
||||
TxInfoDialog::~TxInfoDialog() = default;
|
|
@ -28,11 +28,13 @@ signals:
|
|||
void resendTranscation(const QString &txid);
|
||||
|
||||
private:
|
||||
void copyTxID();
|
||||
void copyTxKey();
|
||||
void createTxProof();
|
||||
void setData(TransactionInfo *tx);
|
||||
void updateData();
|
||||
void adjustHeight(QTextEdit *textEdit, qreal docHeight);
|
||||
void viewOnBlockExplorer();
|
||||
|
||||
QScopedPointer<Ui::TxInfoDialog> ui;
|
||||
QSharedPointer<AppContext> m_ctx;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>929</width>
|
||||
<height>631</height>
|
||||
<height>715</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -19,7 +19,7 @@
|
|||
<property name="title">
|
||||
<string>Transaction ID:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_txid">
|
||||
<property name="text">
|
||||
|
@ -30,6 +30,19 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_viewOnBlockExplorer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -205,17 +218,24 @@
|
|||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_copyTxID">
|
||||
<property name="text">
|
||||
<string>Copy Tx ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_CopyTxKey">
|
||||
<property name="text">
|
||||
<string>Copy Transaction Key</string>
|
||||
<string>Copy Tx Secret Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_createTxProof">
|
||||
<property name="text">
|
||||
<string>Create Transaction Proof</string>
|
||||
<string>Create Tx Proof</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "utils/Utils.h"
|
||||
|
||||
TxProofDialog::TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, TransactionInfo *txInfo)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::TxProofDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
@ -88,13 +88,13 @@ void TxProofDialog::selectOutProof() {
|
|||
m_mode = Mode::OutProof;
|
||||
this->resetFrames();
|
||||
|
||||
if (m_OutDestinations.empty()) {
|
||||
this->showWarning("This transaction did not spend any outputs owned by this wallet. Creating an OutProof is not possible.");
|
||||
if (m_txKey.isEmpty()) {
|
||||
this->showWarning("No transaction key stored for this transaction. Creating an OutProof is not possible.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_txKey.isEmpty()) {
|
||||
this->showWarning("No transaction key stored for this transaction. Creating an OutProof is not possible.");
|
||||
if (m_OutDestinations.empty()) {
|
||||
this->showWarning("This transaction did not send funds to any known addresses. Creating an OutProof is not possible.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,11 @@ void TxProofDialog::selectInProof() {
|
|||
m_mode = Mode::InProof;
|
||||
this->resetFrames();
|
||||
|
||||
if (m_direction == TransactionInfo::Direction_Out) {
|
||||
this->showWarning("Can't create InProofs for outgoing transactions.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_InDestinations.empty()) {
|
||||
this->showWarning("Your wallet did not receive any outputs in this transaction.");
|
||||
return;
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
#include "libwalletqt/TransactionInfo.h"
|
||||
|
||||
namespace Ui {
|
||||
class TxProofDialog;
|
||||
}
|
||||
|
||||
class TxProofDialog : public QDialog
|
||||
class TxProofDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -117,6 +117,11 @@ void UpdateDialog::onInstallUpdate() {
|
|||
ui->btn_installUpdate->hide();
|
||||
this->setStatus("Unzipping archive...");
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
this->installUpdateMac();
|
||||
return;
|
||||
#endif
|
||||
|
||||
zip_error_t err;
|
||||
zip_error_init(&err);
|
||||
|
||||
|
@ -172,14 +177,7 @@ void UpdateDialog::onInstallUpdate() {
|
|||
zip_fclose(zf);
|
||||
zip_close(zip_archive);
|
||||
|
||||
QString applicationPath = qgetenv("APPIMAGE");
|
||||
if (!applicationPath.isEmpty()) {
|
||||
applicationPath = QFileInfo(applicationPath).absoluteDir().path();
|
||||
} else {
|
||||
applicationPath = QCoreApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
QDir applicationDir(applicationPath);
|
||||
QDir applicationDir(Utils::applicationPath());
|
||||
QString filePath = applicationDir.filePath(name);
|
||||
m_updatePath = filePath;
|
||||
|
||||
|
@ -206,6 +204,41 @@ void UpdateDialog::onInstallUpdate() {
|
|||
ui->btn_restart->show();
|
||||
}
|
||||
|
||||
void UpdateDialog::installUpdateMac() {
|
||||
QString appPath = Utils::applicationPath();
|
||||
QDir appDir(appPath);
|
||||
if (appPath.endsWith("Contents/MacOS")) {
|
||||
appDir.cd("../../..");
|
||||
}
|
||||
QString appName = QString("feather-%1").arg(m_version);
|
||||
QString zipName = QString("%1.zip").arg(appName);
|
||||
QString fPath = appDir.filePath(zipName);
|
||||
|
||||
QFile file(fPath);
|
||||
qDebug() << "Writing zip file to " << fPath;
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
this->onInstallError(QString("Error: Could not write to application path: %1").arg(fPath));
|
||||
return;
|
||||
}
|
||||
|
||||
if (static_cast<size_t>(file.write(&m_updateZipArchive[0], m_updateZipArchive.size())) != m_updateZipArchive.size()) {
|
||||
this->onInstallError("Error: Unable to write file");
|
||||
return;
|
||||
}
|
||||
|
||||
QProcess unzip;
|
||||
unzip.start("/usr/bin/unzip", {"-n", fPath, "-d", appDir.path()});
|
||||
unzip.waitForFinished();
|
||||
|
||||
m_updatePath = QString("%1.app/Contents/MacOS/feather").arg(appDir.filePath(appName));
|
||||
|
||||
file.remove();
|
||||
|
||||
this->setStatus("Installation successful. Do you want to restart Feather now?");
|
||||
ui->btn_restart->show();
|
||||
}
|
||||
|
||||
void UpdateDialog::onInstallError(const QString &errMsg) {
|
||||
this->setStatus(errMsg);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ signals:
|
|||
|
||||
private:
|
||||
void setStatus(const QString &msg, bool success = false);
|
||||
void installUpdateMac();
|
||||
|
||||
QScopedPointer<Ui::UpdateDialog> ui;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "utils/Utils.h"
|
||||
|
||||
VerifyProofDialog::VerifyProofDialog(Wallet *wallet, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::VerifyProofDialog)
|
||||
, m_wallet(wallet)
|
||||
{
|
||||
|
@ -50,6 +50,9 @@ VerifyProofDialog::VerifyProofDialog(Wallet *wallet, QWidget *parent)
|
|||
}
|
||||
});
|
||||
|
||||
connect(m_wallet, &Wallet::transactionProofVerified, this, &VerifyProofDialog::onTxProofVerified);
|
||||
connect(m_wallet, &Wallet::spendProofVerified, this, &VerifyProofDialog::onSpendProofVerified);
|
||||
|
||||
ui->input_formattedProof->setFont(ModelUtils::getMonospaceFont());
|
||||
}
|
||||
|
||||
|
@ -69,31 +72,15 @@ void VerifyProofDialog::checkProof() {
|
|||
|
||||
void VerifyProofDialog::checkTxProof(const QString &txId, const QString &address, const QString &message,
|
||||
const QString &signature) {
|
||||
TxProofResult r = m_wallet->checkTxProof(txId, address, message, signature);
|
||||
|
||||
if (!r.success) {
|
||||
this->proofStatus(false, m_wallet->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!r.good) {
|
||||
this->proofStatus(false, "Proof is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
this->proofStatus(true, QString("Proof is valid.\n\nThis address received %1 XMR, with %2 confirmation(s)").arg(WalletManager::displayAmount(r.received), QString::number(r.confirmations)));
|
||||
ui->btn_verifyFormattedProof->setEnabled(false);
|
||||
ui->btn_verify->setEnabled(false);
|
||||
m_wallet->checkTxProofAsync(txId, address, message, signature);
|
||||
}
|
||||
|
||||
void VerifyProofDialog::checkSpendProof(const QString &txId, const QString &message, const QString &signature) {
|
||||
auto r = m_wallet->checkSpendProof(txId, message, signature);
|
||||
|
||||
if (!r.first) {
|
||||
this->proofStatus(false, m_wallet->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
r.second ? this->proofStatus(true, "Proof is valid")
|
||||
: this->proofStatus(false, "Proof is invalid");
|
||||
ui->btn_verifyFormattedProof->setEnabled(false);
|
||||
ui->btn_verify->setEnabled(false);
|
||||
m_wallet->checkSpendProofAsync(txId, message, signature);
|
||||
}
|
||||
|
||||
void VerifyProofDialog::checkOutProof() {
|
||||
|
@ -163,11 +150,37 @@ void VerifyProofDialog::proofStatus(bool success, const QString &message) {
|
|||
ui->frame_status->show();
|
||||
ui->label_icon->setPixmap(success ? m_success : m_failure);
|
||||
ui->label_status->setText(message);
|
||||
ui->btn_verifyFormattedProof->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui->btn_verify->setEnabled(true);
|
||||
success ? QMessageBox::information(this, "Information", message)
|
||||
: QMessageBox::warning(this, "Warning", message);
|
||||
}
|
||||
}
|
||||
|
||||
void VerifyProofDialog::onTxProofVerified(TxProofResult r) {
|
||||
if (!r.success) {
|
||||
this->proofStatus(false, m_wallet->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!r.good) {
|
||||
this->proofStatus(false, "Proof is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
this->proofStatus(true, QString("Proof is valid.\n\nThis address received %1 XMR, with %2 confirmation(s)").arg(WalletManager::displayAmount(r.received), QString::number(r.confirmations)));
|
||||
}
|
||||
|
||||
void VerifyProofDialog::onSpendProofVerified(QPair<bool, bool> r) {
|
||||
if (!r.first) {
|
||||
this->proofStatus(false, m_wallet->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
r.second ? this->proofStatus(true, "Proof is valid")
|
||||
: this->proofStatus(false, "Proof is invalid");
|
||||
}
|
||||
|
||||
VerifyProofDialog::~VerifyProofDialog() = default;
|
|
@ -7,13 +7,14 @@
|
|||
#include <QDialog>
|
||||
#include <QIcon>
|
||||
|
||||
#include "components.h"
|
||||
#include "libwalletqt/Wallet.h"
|
||||
|
||||
namespace Ui {
|
||||
class VerifyProofDialog;
|
||||
}
|
||||
|
||||
class VerifyProofDialog : public QDialog
|
||||
class VerifyProofDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -31,6 +32,8 @@ private:
|
|||
void checkInProof();
|
||||
void checkFormattedProof();
|
||||
void proofStatus(bool success, const QString &message);
|
||||
void onTxProofVerified(TxProofResult result);
|
||||
void onSpendProofVerified(QPair<bool, bool> result);
|
||||
|
||||
QScopedPointer<Ui::VerifyProofDialog> ui;
|
||||
Wallet *m_wallet;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <QMessageBox>
|
||||
|
||||
ViewOnlyDialog::ViewOnlyDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::ViewOnlyDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class ViewOnlyDialog;
|
||||
}
|
||||
|
||||
class ViewOnlyDialog : public QDialog
|
||||
class ViewOnlyDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "model/ModelUtils.h"
|
||||
|
||||
WalletCacheDebugDialog::WalletCacheDebugDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::WalletCacheDebugDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class WalletCacheDebugDialog;
|
||||
}
|
||||
|
||||
class WalletCacheDebugDialog : public QDialog
|
||||
class WalletCacheDebugDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <QDesktopServices>
|
||||
|
||||
WalletInfoDialog::WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::WalletInfoDialog)
|
||||
, m_ctx(std::move(ctx))
|
||||
{
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#include <QDialog>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "components.h"
|
||||
|
||||
namespace Ui {
|
||||
class WalletInfoDialog;
|
||||
}
|
||||
|
||||
class WalletInfoDialog : public QDialog
|
||||
class WalletInfoDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -71,15 +71,15 @@ quint64 Coins::count() const
|
|||
return m_tinfo.count();
|
||||
}
|
||||
|
||||
void Coins::freeze(int index) const
|
||||
void Coins::freeze(QString &publicKey) const
|
||||
{
|
||||
m_pimpl->setFrozen(index);
|
||||
m_pimpl->setFrozen(publicKey.toStdString());
|
||||
emit coinFrozen();
|
||||
}
|
||||
|
||||
void Coins::thaw(int index) const
|
||||
void Coins::thaw(QString &publicKey) const
|
||||
{
|
||||
m_pimpl->thaw(index);
|
||||
m_pimpl->thaw(publicKey.toStdString());
|
||||
emit coinThawed();
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,9 @@ QVector<CoinsInfo*> Coins::coins_from_txid(const QString &txid)
|
|||
return coins;
|
||||
}
|
||||
|
||||
void Coins::setDescription(int index, quint32 accountIndex, const QString &description)
|
||||
void Coins::setDescription(const QString &publicKey, quint32 accountIndex, const QString &description)
|
||||
{
|
||||
m_pimpl->setDescription(index, description.toStdString());
|
||||
m_pimpl->setDescription(publicKey.toStdString(), description.toStdString());
|
||||
this->refresh(accountIndex);
|
||||
emit descriptionChanged();
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue