Compare commits

...

31 Commits

Author SHA1 Message Date
mrdeveloper 0e7c773bfd Remove unused declared method
4 years ago
mrdeveloper 11f8406be3 History: don't show copy spend proof on incoming transactions
4 years ago
tobtoht 2c99454565 Merge pull request 'FutureScheduler: update with upstream v0.17.1.3' (#141) from tobtoht/feather:scheduler into master
4 years ago
tobtoht cd96abe545 FutureScheduler: update with upstream v0.17.1.3
4 years ago
tobtoht d76b688ec4 Merge pull request 'Libwalletqt: update with upstream' (#140) from tobtoht/feather:libwalletqt_syncing into master
4 years ago
tobtoht ed47e8e05c Merge pull request 'Added cryptonote-social mining pool to XMRig' (#136) from mrdeveloper/feather:cryptonote-social into master
4 years ago
tobtoht 268b87a803 Libwalletqt: update with upstream
4 years ago
tobtoht 318690681b Merge pull request 'Update for v0.17.1.3' (#139) from tobtoht/feather:v0.17.1.3 into master
4 years ago
tobtoht b1e37e714d Update for v0.17.1.3
4 years ago
mrdeveloper 18b514351d Added cryptonote-social mining pool to XMRig
4 years ago
tobtoht 63c120bdb0 Merge pull request 'Stylesheets: Breeze: misc fixes' (#135) from tobtoht/feather:stylesheet_breeze_fixes into master
4 years ago
tobtoht 96409ecc17 Stylesheets: Breeze: misc fixes
4 years ago
tobtoht c1cba44cba Merge pull request 'AppContext: updateBalance: don't throw runtime error' (#134) from tobtoht/feather:no_runtime_error into master
4 years ago
tobtoht 7a1ac42b1e AppContext: updateBalance: don't throw runtime error
4 years ago
tobtoht 87fd142ffd Merge pull request 'Settings: add hide balance feature' (#133) from tobtoht/feather:hide_balance into master
4 years ago
tobtoht 62ad0d9527 Settings: add hide balance feature
4 years ago
tobtoht 4f9e4ac93d Merge pull request 'Utils: add blockchair.com block explorer' (#132) from tobtoht/feather:blockchair into master
4 years ago
tobtoht cb6f2873a9 Utils: add blockchair.com block explorer
4 years ago
tobtoht 20b741d30d Merge pull request 'Coins: numerical sort for amount column' (#105) from tobtoht/feather:coins_amount_sort into master
4 years ago
tobtoht 7ed2ff15d5 Merge pull request 'CCSWidget: fix misspelling' (#131) from tobtoht/feather:fix_ccs into master
4 years ago
tobtoht da4b2d16ef CCSWidget: fix misspelling
4 years ago
tobtoht 4521223413 Merge pull request 'Simplify and remove white space on recipient (Pay to)' (#124) from mrdeveloper/feather:simplified-recipient-addr into master
4 years ago
mrdeveloper 0dd81c4873 Simplify and remove white space on recipient (Pay to)
4 years ago
dsc df2ff26c0f Merge pull request 'MacOS: add touchbar support' (#121) from dsc/feather:macos-touchbar-submodule into master
4 years ago
mrdeveloper e657e2a6b0 MacOS: add touchbar support
4 years ago
dsc 34a63897d6 Merge pull request 'BugFix: show message box if no wallet is selected' (#118) from mrdeveloper/feather:bug-wallet-select into master
4 years ago
dsc 6279591d1b Merge pull request 'Check if given node URL has https so we can append https for get_info call' (#120) from mrdeveloper/feather:node-check-for-https into master
4 years ago
mrdeveloper 403b8140b3 Check if given node URL has https so we can append https for get_info call
4 years ago
mrdeveloper 71ba9f6d4a BugFix: show message box if no wallet is selected
4 years ago
tobtoht 9b7849c5be Coins: numerical sort for amount column
4 years ago
tobtoht 51a0f86652 Move cdiv to globals.h
4 years ago

3
.gitmodules vendored

@ -7,3 +7,6 @@
[submodule "contrib/tor"] [submodule "contrib/tor"]
path = contrib/tor path = contrib/tor
url = https://git.torproject.org/tor.git url = https://git.torproject.org/tor.git
[submodule "contrib/KDMacTouchBar"]
path = contrib/KDMacTouchBar
url = https://github.com/KDAB/KDMacTouchBar.git

@ -30,7 +30,7 @@ if(DEBUG)
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
endif() endif()
set(MONERO_HEAD "a39fd7ea978053929da63dcdb8073806573be5ba") set(MONERO_HEAD "a6bf6dbb8f1637ccffee1a30d2285324a3ce4d66")
set(BUILD_GUI_DEPS ON) set(BUILD_GUI_DEPS ON)
set(ARCH "x86-64") set(ARCH "x86-64")
set(BUILD_64 ON) set(BUILD_64 ON)
@ -365,4 +365,8 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${C_SECURITY_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}")
if(APPLE)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/contrib/KDMacTouchBar")
endif()
add_subdirectory(src) add_subdirectory(src)

@ -0,0 +1 @@
Subproject commit 470c4316460bb8c3e23bfa37c79c8621ef3f1b4c

@ -1 +1 @@
Subproject commit a39fd7ea978053929da63dcdb8073806573be5ba Subproject commit a6bf6dbb8f1637ccffee1a30d2285324a3ce4d66

@ -201,6 +201,14 @@ target_link_libraries(feather
${QRENCODE_LIBRARY} ${QRENCODE_LIBRARY}
) )
if(APPLE)
target_link_libraries(feather
KDMacTouchBar
)
target_include_directories(feather
PUBLIC ../contrib/KDMacTouchBar)
endif()
if(NOT APPLE) if(NOT APPLE)
target_link_libraries(feather target_link_libraries(feather
Qt5::QSvgIconPlugin Qt5::QSvgIconPlugin

@ -9,12 +9,14 @@
#include <QDesktopWidget> #include <QDesktopWidget>
#include "appcontext.h" #include "appcontext.h"
#include "globals.h"
#include "utils/tails.h" #include "utils/tails.h"
#include "utils/whonix.h" #include "utils/whonix.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "utils/prices.h" #include "utils/prices.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "utils/wsclient.h" #include "utils/wsclient.h"
#include "utils/config.h"
// libwalletqt // libwalletqt
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
@ -28,7 +30,6 @@
#include "model/SubaddressModel.h" #include "model/SubaddressModel.h"
#include "utils/keysfiles.h" #include "utils/keysfiles.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "utils/config.h"
Prices *AppContext::prices = nullptr; Prices *AppContext::prices = nullptr;
@ -195,7 +196,7 @@ void AppContext::initWS() {
void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) { void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) {
// tx cancelled by user // tx cancelled by user
double amount = tx->amount() / AppContext::cdiv; double amount = tx->amount() / globals::cdiv;
emit createTransactionCancelled(address, amount); emit createTransactionCancelled(address, amount);
this->currentWallet->disposeTransaction(tx); this->currentWallet->disposeTransaction(tx);
} }
@ -234,8 +235,8 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return; return;
} }
auto balance = this->currentWallet->balance() / AppContext::cdiv; auto balance = this->currentWallet->balance() / globals::cdiv;
auto unlocked_balance = this->currentWallet->unlockedBalance() / AppContext::cdiv; auto unlocked_balance = this->currentWallet->unlockedBalance() / globals::cdiv;
if(!all && amount > unlocked_balance) { if(!all && amount > unlocked_balance) {
emit createTransactionError("Not enough money to spend"); emit createTransactionError("Not enough money to spend");
return; return;
@ -244,7 +245,7 @@ void AppContext::onCreateTransaction(const QString &address, const double amount
return; return;
} }
auto amount_num = static_cast<quint64>(amount * AppContext::cdiv); auto amount_num = static_cast<quint64>(amount * globals::cdiv);
qDebug() << "creating tx"; qDebug() << "creating tx";
if(all || amount == balance) if(all || amount == balance)
this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority); this->currentWallet->createTransactionAllAsync(address, "", this->tx_mixin, this->tx_priority);
@ -691,19 +692,19 @@ AppContext::~AppContext() {
// ############################################## LIBWALLET QT ######################################################### // ############################################## LIBWALLET QT #########################################################
void AppContext::onMoneySpent(const QString &txId, quint64 amount) { void AppContext::onMoneySpent(const QString &txId, quint64 amount) {
auto amount_num = amount / AppContext::cdiv; auto amount_num = amount / globals::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
} }
void AppContext::onMoneyReceived(const QString &txId, quint64 amount) { void AppContext::onMoneyReceived(const QString &txId, quint64 amount) {
// Incoming tx included in a block. // Incoming tx included in a block.
auto amount_num = amount / AppContext::cdiv; auto amount_num = amount / globals::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
} }
void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) { void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) {
// Incoming transaction in pool // Incoming transaction in pool
auto amount_num = amount / AppContext::cdiv; auto amount_num = amount / globals::cdiv;
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num); qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
if(this->currentWallet->synchronized()) { if(this->currentWallet->synchronized()) {
@ -790,12 +791,12 @@ void AppContext::storeWallet() {
void AppContext::updateBalance() { void AppContext::updateBalance() {
if(!this->currentWallet) if(!this->currentWallet)
throw std::runtime_error("this should not happen, ever"); return;
AppContext::balance = this->currentWallet->balance() / AppContext::cdiv; AppContext::balance = this->currentWallet->balance() / globals::cdiv;
auto balance_str = QString::number(balance, 'f'); auto balance_str = QString::number(balance, 'f');
double unlocked = this->currentWallet->unlockedBalance() / AppContext::cdiv; double unlocked = this->currentWallet->unlockedBalance() / globals::cdiv;
auto unlocked_str = QString::number(unlocked, 'f'); auto unlocked_str = QString::number(unlocked, 'f');
emit balanceUpdated(balance, unlocked, balance_str, unlocked_str); emit balanceUpdated(balance, unlocked, balance_str, unlocked_str);

@ -69,7 +69,6 @@ public:
const unsigned int kdfRounds = 1; const unsigned int kdfRounds = 1;
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low; PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
quint32 tx_mixin = static_cast<const quint32 &>(10); quint32 tx_mixin = static_cast<const quint32 &>(10);
static constexpr const double cdiv = 1e12;
QString seedLanguage = "English"; // 14 word `monero-seed` only has English QString seedLanguage = "English"; // 14 word `monero-seed` only has English
QNetworkAccessManager *network; QNetworkAccessManager *network;

@ -42,14 +42,14 @@ CoinsWidget::CoinsWidget(QWidget *parent)
// context menu // context menu
ui->coins->setContextMenuPolicy(Qt::CustomContextMenu); ui->coins->setContextMenuPolicy(Qt::CustomContextMenu);
m_thawOutputAction = new QAction("Thaw output"); m_thawOutputAction = new QAction("Thaw output", this);
m_freezeOutputAction = new QAction("Freeze output"); m_freezeOutputAction = new QAction("Freeze output", this);
m_freezeAllSelectedAction = new QAction("Freeze selected"); m_freezeAllSelectedAction = new QAction("Freeze selected", this);
m_thawAllSelectedAction = new QAction("Thaw selected"); m_thawAllSelectedAction = new QAction("Thaw selected", this);
m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details"); m_viewOutputAction = new QAction(QIcon(":/assets/images/info.png"), "Details", this);
m_sweepOutputAction = new QAction("Sweep output"); m_sweepOutputAction = new QAction("Sweep output", this);
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput); connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput);
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput); connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput); connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
@ -65,7 +65,7 @@ CoinsWidget::CoinsWidget(QWidget *parent)
void CoinsWidget::setModel(CoinsModel * model, Coins * coins) { void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
m_coins = coins; m_coins = coins;
m_model = model; m_model = model;
m_proxyModel = new CoinsProxyModel; m_proxyModel = new CoinsProxyModel(this);
m_proxyModel->setSourceModel(m_model); m_proxyModel->setSourceModel(m_model);
ui->coins->setModel(m_proxyModel); ui->coins->setModel(m_proxyModel);
ui->coins->setColumnHidden(CoinsModel::Spent, true); ui->coins->setColumnHidden(CoinsModel::Spent, true);
@ -207,6 +207,7 @@ void CoinsWidget::onSweepOutput() {
qCritical() << "key image: " << keyImage; qCritical() << "key image: " << keyImage;
emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs()); emit sweepOutput(keyImage, dialog->address(), dialog->churn(), dialog->outputs());
dialog->deleteLater();
} }
void CoinsWidget::copy(copyField field) { void CoinsWidget::copy(copyField field) {

@ -8,6 +8,7 @@
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "txconfadvdialog.h" #include "txconfadvdialog.h"
#include "globals.h"
#include <QMessageBox> #include <QMessageBox>
@ -31,15 +32,15 @@ TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QStrin
}; };
QString amount = WalletManager::displayAmount(tx->amount()); QString amount = WalletManager::displayAmount(tx->amount());
QString amount_fiat = convert(tx->amount() / AppContext::cdiv); QString amount_fiat = convert(tx->amount() / globals::cdiv);
ui->label_amount->setText(QString("%1 (%2 %3)").arg(amount, amount_fiat, preferredCur)); ui->label_amount->setText(QString("%1 (%2 %3)").arg(amount, amount_fiat, preferredCur));
QString fee = WalletManager::displayAmount(tx->fee()); QString fee = WalletManager::displayAmount(tx->fee());
QString fee_fiat = convert(tx->fee() / AppContext::cdiv); QString fee_fiat = convert(tx->fee() / globals::cdiv);
ui->label_fee->setText(QString("%1 (%2 %3)").arg(fee, fee_fiat, preferredCur)); ui->label_fee->setText(QString("%1 (%2 %3)").arg(fee, fee_fiat, preferredCur));
QString total = WalletManager::displayAmount(tx->amount() + tx->fee()); QString total = WalletManager::displayAmount(tx->amount() + tx->fee());
QString total_fiat = convert((tx->amount() + tx->fee()) / AppContext::cdiv); QString total_fiat = convert((tx->amount() + tx->fee()) / globals::cdiv);
ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur)); ui->label_total->setText(QString("%1 (%2 %3)").arg(total, total_fiat, preferredCur));
ui->label_address->setText(ModelUtils::displayAddress(address, 2)); ui->label_address->setText(ModelUtils::displayAddress(address, 2));

@ -0,0 +1,14 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef FEATHER_GLOBALS_H
#define FEATHER_GLOBALS_H
#include <QtGlobal>
namespace globals
{
const qreal cdiv = 1e12;
}
#endif //FEATHER_GLOBALS_H

@ -25,12 +25,17 @@ HistoryWidget::HistoryWidget(QWidget *parent)
m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);}); m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);});
m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);}); m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);});
m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);}); m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);});
m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof); auto spendProof = m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof);
ui->history->setContextMenuPolicy(Qt::CustomContextMenu); ui->history->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){ connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){
QModelIndex index = ui->history->indexAt(point); QModelIndex index = ui->history->indexAt(point);
if (index.isValid()) { if (index.isValid()) {
TransactionInfo::Direction direction;
m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction](TransactionInfo &tInfo) {
direction = tInfo.direction();
});
spendProof->setVisible(direction == TransactionInfo::Direction_Out);
m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point)); m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point));
} }
}); });

@ -3,6 +3,10 @@
#include "Wallet.h" #include "Wallet.h"
#include <chrono>
#include <stdexcept>
#include <thread>
#include "PendingTransaction.h" #include "PendingTransaction.h"
#include "UnsignedTransaction.h" #include "UnsignedTransaction.h"
#include "TransactionHistory.h" #include "TransactionHistory.h"
@ -28,6 +32,8 @@
#include <QVector> #include <QVector>
#include <QMutexLocker> #include <QMutexLocker>
#include "utils/ScopeGuard.h"
namespace { namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5; static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30; static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@ -101,6 +107,20 @@ bool Wallet::disconnected() const
return m_disconnected; return m_disconnected;
} }
bool Wallet::refreshing() const
{
return m_refreshing;
}
void Wallet::refreshingSet(bool value)
{
if (m_refreshing.exchange(value) != value)
{
emit refreshingChanged();
}
}
void Wallet::setConnectionStatus(ConnectionStatus value) void Wallet::setConnectionStatus(ConnectionStatus value)
{ {
if (m_connectionStatus == value) if (m_connectionStatus == value)
@ -245,7 +265,7 @@ void Wallet::initAsync(
emit walletCreationHeightChanged(); emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh"; qDebug() << "init async finished - starting refresh";
connected(true); connected(true);
m_walletImpl->startRefresh(); startRefresh();
} }
}); });
if (future.first) if (future.first)
@ -456,20 +476,14 @@ bool Wallet::importOutputs(const QString& path) {
return m_walletImpl->importOutputs(path.toStdString()); return m_walletImpl->importOutputs(path.toStdString());
} }
bool Wallet::refresh() void Wallet::startRefresh()
{ {
qDebug() << "refresh async"; m_refreshEnabled = true;
m_walletImpl->refreshAsync();
} }
void Wallet::startRefresh() const void Wallet::pauseRefresh()
{ {
m_walletImpl->startRefresh(); m_refreshEnabled = false;
}
void Wallet::pauseRefresh() const
{
m_walletImpl->pauseRefresh();
} }
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id, PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@ -580,6 +594,29 @@ bool Wallet::submitTxFile(const QString &fileName) const
return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages"); return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages");
} }
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
{
refreshingSet(true);
const auto cleanup = sg::make_scope_guard([this]() noexcept {
refreshingSet(false);
});
{
QMutexLocker locker(&m_asyncMutex);
bool result = m_walletImpl->refresh();
if (historyAndSubaddresses)
{
m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
m_subaddressAccount->getAll();
}
if (result)
emit updated();
return result;
}
}
void Wallet::commitTransactionAsync(PendingTransaction *t) void Wallet::commitTransactionAsync(PendingTransaction *t)
{ {
m_scheduler.run([this, t] { m_scheduler.run([this, t] {
@ -1063,6 +1100,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_subaddressAccount(nullptr) , m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr) , m_subaddressAccountModel(nullptr)
, m_coinsModel(nullptr) , m_coinsModel(nullptr)
, m_refreshEnabled(false)
, m_refreshing(false)
, m_scheduler(this) , m_scheduler(this)
{ {
m_history = new TransactionHistory(m_walletImpl->history(), this); m_history = new TransactionHistory(m_walletImpl->history(), this);
@ -1081,12 +1120,17 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false; m_connectionStatusRunning = false;
m_daemonUsername = ""; m_daemonUsername = "";
m_daemonPassword = ""; m_daemonPassword = "";
startRefreshThread();
} }
Wallet::~Wallet() Wallet::~Wallet()
{ {
qDebug("~Wallet: Closing wallet"); qDebug("~Wallet: Closing wallet");
pauseRefresh();
m_walletImpl->stop();
m_scheduler.shutdownWaitForFinished(); m_scheduler.shutdownWaitForFinished();
delete m_addressBook; delete m_addressBook;
@ -1116,3 +1160,32 @@ Wallet::~Wallet()
m_walletListener = NULL; m_walletListener = NULL;
qDebug("m_walletImpl deleted"); qDebug("m_walletImpl deleted");
} }
void Wallet::startRefreshThread()
{
const auto future = m_scheduler.run([this] {
constexpr const std::chrono::seconds refreshInterval{10};
constexpr const std::chrono::milliseconds intervalResolution{100};
auto last = std::chrono::steady_clock::now();
while (!m_scheduler.stopping())
{
if (m_refreshEnabled)
{
const auto now = std::chrono::steady_clock::now();
const auto elapsed = now - last;
if (elapsed >= refreshInterval)
{
refresh(false);
last = std::chrono::steady_clock::now();
}
}
std::this_thread::sleep_for(intervalResolution);
}
});
if (!future.first)
{
throw std::runtime_error("failed to start auto refresh thread");
}
}

@ -50,6 +50,7 @@ class Wallet : public QObject, public PassprasePrompter
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged) Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
Q_PROPERTY(QString seed READ getSeed) Q_PROPERTY(QString seed READ getSeed)
Q_PROPERTY(QString seedLanguage READ getSeedLanguage) Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
@ -199,11 +200,11 @@ public:
Q_INVOKABLE bool importOutputs(const QString& path); Q_INVOKABLE bool importOutputs(const QString& path);
//! refreshes the wallet //! refreshes the wallet
Q_INVOKABLE bool refresh(); Q_INVOKABLE bool refresh(bool historyAndSubaddresses = false);
// pause/resume refresh // pause/resume refresh
Q_INVOKABLE void startRefresh() const; Q_INVOKABLE void startRefresh();
Q_INVOKABLE void pauseRefresh() const; Q_INVOKABLE void pauseRefresh();
//! returns current wallet's block height //! returns current wallet's block height
//! (can be less than daemon's blockchain height when wallet sync in progress) //! (can be less than daemon's blockchain height when wallet sync in progress)
@ -411,6 +412,7 @@ signals:
void currentSubaddressAccountChanged() const; void currentSubaddressAccountChanged() const;
void disconnectedChanged() const; void disconnectedChanged() const;
void proxyAddressChanged() const; void proxyAddressChanged() const;
void refreshingChanged() const;
private: private:
Wallet(QObject * parent = nullptr); Wallet(QObject * parent = nullptr);
@ -428,9 +430,13 @@ private:
const QString& proxyAddress); const QString& proxyAddress);
bool disconnected() const; bool disconnected() const;
bool refreshing() const;
void refreshingSet(bool value);
void setConnectionStatus(ConnectionStatus value); void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const; QString getProxyAddress() const;
void setProxyAddress(QString address); void setProxyAddress(QString address);
void startRefreshThread();
private: private:
friend class WalletManager; friend class WalletManager;

@ -351,6 +351,14 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
// window title // window title
connect(m_ctx, &AppContext::setTitle, this, &QMainWindow::setWindowTitle); connect(m_ctx, &AppContext::setTitle, this, &QMainWindow::setWindowTitle);
// init touchbar
#ifdef Q_OS_MAC
m_touchbar = new KDMacTouchBar(this);
m_touchbarActionWelcome = new QAction(QIcon(":/assets/images/feather.png"), "Welcome to Feather!");
m_touchbarWalletItems = {ui->actionSettings, ui->actionCalculator, ui->actionKeys, ui->actionDonate_to_Feather};
m_touchbarWizardItems = {m_touchbarActionWelcome};
#endif
// setup some UI // setup some UI
this->initMain(); this->initMain();
this->initWidgets(); this->initWidgets();
@ -382,6 +390,7 @@ void MainWindow::initMain() {
this->show(); this->show();
m_wizard = this->createWizard(WalletWizard::Page_Menu); m_wizard = this->createWizard(WalletWizard::Page_Menu);
m_wizard->show(); m_wizard->show();
this->touchbarShowWizard();
} }
void MainWindow::initMenu() { void MainWindow::initMenu() {
@ -545,6 +554,20 @@ void MainWindow::onWalletClosed(WalletWizard::Page page) {
this->showWizard(page); this->showWizard(page);
} }
void MainWindow::touchbarShowWizard() {
#ifdef Q_OS_MAC
m_touchbar->clear();
for(auto* action: m_touchbarWizardItems) m_touchbar->addAction(action);
#endif
}
void MainWindow::touchbarShowWallet() {
#ifdef Q_OS_MAC
m_touchbar->clear();
for(auto* action: m_touchbarWalletItems) m_touchbar->addAction(action);
#endif
}
void MainWindow::onWalletCreatedError(const QString &err) { void MainWindow::onWalletCreatedError(const QString &err) {
Utils::showMessageBox("Wallet creation error", err, true); Utils::showMessageBox("Wallet creation error", err, true);
this->showWizard(WalletWizard::Page_CreateWallet); this->showWizard(WalletWizard::Page_CreateWallet);
@ -571,6 +594,7 @@ void MainWindow::onWalletOpenedError(const QString &err) {
QMessageBox::warning(this, "Wallet open error", err); QMessageBox::warning(this, "Wallet open error", err);
this->setWindowTitle("Feather"); this->setWindowTitle("Feather");
this->showWizard(WalletWizard::Page_OpenWallet); this->showWizard(WalletWizard::Page_OpenWallet);
this->touchbarShowWizard();
} }
void MainWindow::onWalletCreated(Wallet *wallet) { void MainWindow::onWalletCreated(Wallet *wallet) {
@ -630,14 +654,24 @@ void MainWindow::onWalletOpened() {
connect(m_ctx->currentWallet->coins(), &Coins::coinThawed, [this]{ connect(m_ctx->currentWallet->coins(), &Coins::coinThawed, [this]{
m_ctx->storeWallet(); m_ctx->storeWallet();
}); });
this->touchbarShowWallet();
} }
void MainWindow::onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str) { void MainWindow::onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str) {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
bool hide = config()->get(Config::hideBalance).toBool();
auto label_str = QString("Balance: %1 XMR").arg(unlocked_str); auto label_str = QString("Balance: %1 XMR").arg(unlocked_str);
if(balance > unlocked) if(balance > unlocked)
label_str += QString(" (+%1 XMR unconfirmed)").arg(QString::number(balance - unlocked, 'f')); label_str += QString(" (+%1 XMR unconfirmed)").arg(QString::number(balance - unlocked, 'f'));
if (hide) {
label_str = "Balance: HIDDEN";
}
m_statusLabelBalance->setText(label_str); m_statusLabelBalance->setText(label_str);
m_balanceWidget->setHidden(hide);
} }
void MainWindow::onSynchronized() { void MainWindow::onSynchronized() {

@ -4,6 +4,10 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#ifdef Q_OS_MAC
#include "src/kdmactouchbar.h"
#endif
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QScreen> #include <QScreen>
@ -154,6 +158,8 @@ private:
void showNodeExhaustedMessage(); void showNodeExhaustedMessage();
void showWSNodeExhaustedMessage(); void showWSNodeExhaustedMessage();
void createUnsignedTxDialog(UnsignedTransaction *tx); void createUnsignedTxDialog(UnsignedTransaction *tx);
void touchbarShowWizard();
void touchbarShowWallet();
WalletWizard *createWizard(WalletWizard::Page startPage); WalletWizard *createWizard(WalletWizard::Page startPage);
@ -192,7 +198,12 @@ private:
SubaddressProxyModel *subaddressProxyModel; SubaddressProxyModel *subaddressProxyModel;
TransactionHistoryModel *txHistModel; TransactionHistoryModel *txHistModel;
CoinsModel *coinsModel; CoinsModel *coinsModel;
#ifdef Q_OS_MAC
QAction *m_touchbarActionWelcome;
KDMacTouchBar *m_touchbar;
QList<QAction *> m_touchbarWalletItems;
QList<QAction *> m_touchbarWizardItems;
#endif
QSignalMapper *m_tabShowHideSignalMapper; QSignalMapper *m_tabShowHideSignalMapper;
QMap<QString, ToggleTab*> m_tabShowHideMapper; QMap<QString, ToggleTab*> m_tabShowHideMapper;
WalletWizard *m_wizard = nullptr; WalletWizard *m_wizard = nullptr;

@ -6,6 +6,7 @@
#include "Coins.h" #include "Coins.h"
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include "ModelUtils.h" #include "ModelUtils.h"
#include "globals.h"
#include <QDebug> #include <QDebug>
#include <QHash> #include <QHash>
@ -190,10 +191,14 @@ QVariant CoinsModel::parseTransactionInfo(const CoinsInfo &cInfo, int column, in
case SpentHeight: case SpentHeight:
return cInfo.spentHeight(); return cInfo.spentHeight();
case Amount: case Amount:
return QString::number(cInfo.amount() / 1e12, 'f', 12); {
if (role == Qt::UserRole) {
return cInfo.amount() / globals::cdiv;
}
return QString::number(cInfo.amount() / globals::cdiv, 'f', 12);
}
case Frozen: case Frozen:
return cInfo.frozen(); return cInfo.frozen();
default: default:
{ {
qCritical() << "Unimplemented role"; qCritical() << "Unimplemented role";

@ -7,6 +7,7 @@
CoinsProxyModel::CoinsProxyModel(QObject *parent) CoinsProxyModel::CoinsProxyModel(QObject *parent)
: QSortFilterProxyModel(parent) : QSortFilterProxyModel(parent)
{ {
setSortRole(Qt::UserRole);
} }
bool CoinsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool CoinsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const

@ -4,6 +4,7 @@
#include "TransactionHistoryModel.h" #include "TransactionHistoryModel.h"
#include "TransactionHistory.h" #include "TransactionHistory.h"
#include "TransactionInfo.h" #include "TransactionInfo.h"
#include "globals.h"
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
@ -151,7 +152,7 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tI
} }
case Column::Amount: case Column::Amount:
{ {
QString amount = QString::number(tInfo.atomicAmount() / 1e12, 'f', 4); QString amount = QString::number(tInfo.atomicAmount() / globals::cdiv, 'f', 4);
amount = (tInfo.direction() == TransactionInfo::Direction_Out && tInfo.amount() > 0) ? "-" + amount : "+" + amount; amount = (tInfo.direction() == TransactionInfo::Direction_Out && tInfo.amount() > 0) ? "-" + amount : "+" + amount;
return amount; return amount;
} }

@ -74,7 +74,7 @@ void SendWidget::fillAddress(const QString &address) {
void SendWidget::sendClicked() { void SendWidget::sendClicked() {
double amount = 0.0; double amount = 0.0;
QString currency = ui->comboCurrencySelection->currentText(); QString currency = ui->comboCurrencySelection->currentText();
QString recipient = ui->lineAddress->text(); // @TODO: regex QString recipient = ui->lineAddress->text().simplified().remove(' ');
QString description = ui->lineDescription->text(); QString description = ui->lineDescription->text();
if(recipient.isEmpty()) { if(recipient.isEmpty()) {
QMessageBox::warning(this, "Malformed recipient", "The recipient address was not correct"); QMessageBox::warning(this, "Malformed recipient", "The recipient address was not correct");

@ -22,6 +22,11 @@ Settings::Settings(QWidget *parent) :
connect(ui->btnCopyToClipboard, &QPushButton::clicked, this, &Settings::copyToClipboard); connect(ui->btnCopyToClipboard, &QPushButton::clicked, this, &Settings::copyToClipboard);
connect(ui->checkBox_checkForAppUpdates, &QCheckBox::clicked, this, &Settings::checkboxExternalLinkWarn); connect(ui->checkBox_checkForAppUpdates, &QCheckBox::clicked, this, &Settings::checkboxExternalLinkWarn);
connect(ui->checkBox_externalLink, &QCheckBox::clicked, this, &Settings::checkboxExternalLinkWarn); connect(ui->checkBox_externalLink, &QCheckBox::clicked, this, &Settings::checkboxExternalLinkWarn);
connect(ui->checkBox_hideBalance, &QCheckBox::toggled, [this](bool toggled){
config()->set(Config::hideBalance, toggled);
m_ctx->updateBalance();
});
connect(ui->closeButton, &QDialogButtonBox::accepted, this, &Settings::close); connect(ui->closeButton, &QDialogButtonBox::accepted, this, &Settings::close);
// nodes // nodes
@ -32,6 +37,7 @@ Settings::Settings(QWidget *parent) :
// setup checkboxes // setup checkboxes
ui->checkBox_externalLink->setChecked(config()->get(Config::warnOnExternalLink).toBool()); ui->checkBox_externalLink->setChecked(config()->get(Config::warnOnExternalLink).toBool());
ui->checkBox_checkForAppUpdates->setChecked(config()->get(Config::checkForAppUpdates).toBool()); ui->checkBox_checkForAppUpdates->setChecked(config()->get(Config::checkForAppUpdates).toBool());
ui->checkBox_hideBalance->setChecked(config()->get(Config::hideBalance).toBool());
// setup comboboxes // setup comboboxes
auto settingsHomeWidget = config()->get(Config::homeWidget).toString(); auto settingsHomeWidget = config()->get(Config::homeWidget).toString();

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1019</width> <width>1019</width>
<height>358</height> <height>396</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -175,6 +175,11 @@
<string>moneroblocks.info</string> <string>moneroblocks.info</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>blockchair.com</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="4" column="0">
@ -191,6 +196,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0">
<widget class="QCheckBox" name="checkBox_hideBalance">
<property name="text">
<string>Hide balance</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_node"> <widget class="QWidget" name="tab_node">

@ -57,13 +57,13 @@ QWidget
outline: 0; outline: 0;
} }
QWidget:item:hover QWidget::item:hover
{ {
background-color: #3daee9; background-color: #3daee9;
color: #eff0f1; color: #eff0f1;
} }
QWidget:item:selected QWidget::item:selected
{ {
background-color: #3daee9; background-color: #3daee9;
} }
@ -525,7 +525,7 @@ QTextEdit
QPlainTextEdit QPlainTextEdit
{ {
background-color: #232629;; background-color: #232629;
color: #eff0f1; color: #eff0f1;
border-radius: 0.2ex; border-radius: 0.2ex;
border: 0.1ex solid #76797c; border: 0.1ex solid #76797c;

@ -54,13 +54,13 @@ QWidget
outline: 0; outline: 0;
} }
QWidget:item:hover QWidget::item:hover
{ {
background-color: #33A4DF; background-color: #33A4DF;
color: #31363B; color: #31363B;
} }
QWidget:item:selected QWidget::item:selected
{ {
background-color: #33A4DF; background-color: #33A4DF;
} }
@ -567,7 +567,7 @@ QMainWindow::separator:hover
color: white; color: white;
padding-left: 0.4ex; padding-left: 0.4ex;
border: 0.1ex solid #BAB9B8; border: 0.1ex solid #BAB9B8;
spacing: 0.2x; spacing: 0.2ex;
} }
QMenu::separator QMenu::separator
@ -1659,12 +1659,14 @@ QPushButton:flat {
border: none; border: none;
} }
QScrollBar::handle:vertical QScrollBar::handle:vertical,
QScrollBar::handle:horizontal
{ {
background-color: #BAB9B8; background-color: #BAB9B8;
} }
QScrollBar:vertical QScrollBar:vertical,
QScrollBar:horizontal
{ {
background-color: #eff0f1; background-color: #eff0f1;
border: 0.1ex transparent #eff0f1; border: 0.1ex transparent #eff0f1;

@ -47,6 +47,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::geometry, {QS("geometry"), {}}}, {Config::geometry, {QS("geometry"), {}}},
{Config::windowState, {QS("windowState"), {}}}, {Config::windowState, {QS("windowState"), {}}},
{Config::firstRun,{QS("firstRun"), false}}, {Config::firstRun,{QS("firstRun"), false}},
{Config::hideBalance, {QS("hideBalance"), false}}
}; };

@ -44,7 +44,8 @@ public:
showTabXMRig, showTabXMRig,
geometry, geometry,
windowState, windowState,
firstRun firstRun,
hideBalance
}; };
~Config() override; ~Config() override;

@ -25,6 +25,9 @@ struct FeatherNode {
FeatherNode(QString _address, unsigned int height, bool online) : height(height), online(online){ FeatherNode(QString _address, unsigned int height, bool online) : height(height), online(online){
// wonky ipv4/host parsing, should be fine(tm)(c). // wonky ipv4/host parsing, should be fine(tm)(c).
if(_address.isEmpty()) return; if(_address.isEmpty()) return;
if(_address.contains("https://")) {
this->isHttps = true;
}
_address = _address.replace("https://", ""); _address = _address.replace("https://", "");
_address = _address.replace("http://", ""); _address = _address.replace("http://", "");
if(_address.contains("@")){ // authentication, user/pass if(_address.contains("@")){ // authentication, user/pass
@ -56,6 +59,7 @@ struct FeatherNode {
bool tor = false; bool tor = false;
bool isConnecting = false; bool isConnecting = false;
bool isActive = false; bool isActive = false;
bool isHttps = false;
QString generateFull() { QString generateFull() {
QString auth; QString auth;
@ -65,7 +69,7 @@ struct FeatherNode {
} }
QString as_url() { QString as_url() {
return QString("http://%1/get_info").arg(this->full); return QString("%1://%2/get_info").arg(this->isHttps ? "https": "http",this->full);
} }
bool operator == (const FeatherNode &other) const { bool operator == (const FeatherNode &other) const {

@ -3,9 +3,17 @@
#include "scheduler.h" #include "scheduler.h"
#include <mutex>
#include <QThreadPool>
FutureScheduler::FutureScheduler(QObject *parent) FutureScheduler::FutureScheduler(QObject *parent)
: QObject(parent), Alive(0), Stopping(false) : QObject(parent), Alive(0), Stopping(false)
{ {
static std::once_flag once;
std::call_once(once, []() {
QThreadPool::globalInstance()->setMaxThreadCount(4);
});
} }
FutureScheduler::~FutureScheduler() FutureScheduler::~FutureScheduler()

@ -382,6 +382,11 @@ QString Utils::blockExplorerLink(const QString &blockExplorer, NetworkType::Type
return QString("https://moneroblocks.info/tx/%1").arg(txid); return QString("https://moneroblocks.info/tx/%1").arg(txid);
} }
} }
else if (blockExplorer == "blockchair.com") {
if (nettype == NetworkType::MAINNET) {
return QString("https://blockchair.com/monero/transaction/%1").arg(txid);
}
}
switch (nettype) { switch (nettype) {
case NetworkType::MAINNET: case NetworkType::MAINNET:

@ -7,6 +7,7 @@
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
#include "appcontext.h" #include "appcontext.h"
#include "globals.h"
#include "utils/xmrto.h" #include "utils/xmrto.h"
XmrToOrder::XmrToOrder(AppContext *ctx, UtilsNetworking *network, QString baseUrl, bool clearnet, XmrToRates *rates, QObject *parent) : XmrToOrder::XmrToOrder(AppContext *ctx, UtilsNetworking *network, QString baseUrl, bool clearnet, XmrToRates *rates, QObject *parent) :
@ -38,7 +39,7 @@ void XmrToOrder::onTransactionCancelled(const QString &address, double amount) {
void XmrToOrder::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid) { void XmrToOrder::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid) {
// listener for all outgoing transactions - will try to match the exact amount to this order. // listener for all outgoing transactions - will try to match the exact amount to this order.
if(this->state == OrderState::Status_OrderUnpaid){ if(this->state == OrderState::Status_OrderUnpaid){
if(tx->amount() / AppContext::cdiv == this->incoming_amount_total) { if(tx->amount() / globals::cdiv == this->incoming_amount_total) {
if(!status) { if(!status) {
this->errorMsg = "TX failed to commit"; this->errorMsg = "TX failed to commit";
this->changeState(OrderState::Status_OrderFailed); this->changeState(OrderState::Status_OrderFailed);
@ -221,7 +222,7 @@ void XmrToOrder::changeState(OrderState _state) {
case OrderState::Status_OrderUnpaid: case OrderState::Status_OrderUnpaid:
// need to send Monero // need to send Monero
if(!m_paymentRequested) { if(!m_paymentRequested) {
auto unlocked_balance = m_ctx->currentWallet->unlockedBalance() / AppContext::cdiv; auto unlocked_balance = m_ctx->currentWallet->unlockedBalance() / globals::cdiv;
if (this->incoming_amount_total >= unlocked_balance) { if (this->incoming_amount_total >= unlocked_balance) {
this->state = OrderState::Status_OrderFailed; this->state = OrderState::Status_OrderFailed;
emit orderFailed(this); emit orderFailed(this);

@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project. // Copyright (c) 2020, The Monero Project.
#include "cssprogressdelegate.h" #include "ccsprogressdelegate.h"
#include <QApplication> #include <QApplication>

@ -8,9 +8,9 @@
#include <QDesktopServices> #include <QDesktopServices>
#include "ccswidget.h" #include "ccswidget.h"
#include "ui_csswidget.h" #include "ui_ccswidget.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "cssprogressdelegate.h" #include "ccsprogressdelegate.h"
CCSWidget::CCSWidget(QWidget *parent) : CCSWidget::CCSWidget(QWidget *parent) :
QWidget(parent), QWidget(parent),

@ -59,7 +59,7 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Powered by css.getmonero.org</string> <string>Powered by ccs.getmonero.org</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>

@ -178,6 +178,11 @@ void XMRigWidget::onStartClicked() {
else else
address = config()->get(Config::xmrigPool).toString(); address = config()->get(Config::xmrigPool).toString();
if(address.contains("cryptonote.social") && !username.contains(".")) {
// cryptonote social requires <addr>.<username>, we'll just grab a few chars from primary addy
username = QString("%1.%2").arg(username, m_ctx->currentWallet->address(0, 0).mid(0, 6));
}
m_ctx->XMRig->start(xmrigPath, m_threads, address, username, password, ui->relayTor->isChecked(), ui->check_tls->isChecked()); m_ctx->XMRig->start(xmrigPath, m_threads, address, username, password, ui->relayTor->isChecked(), ui->check_tls->isChecked());
ui->btn_start->setEnabled(false); ui->btn_start->setEnabled(false);
ui->btn_stop->setEnabled(true); ui->btn_stop->setEnabled(true);

@ -57,7 +57,7 @@ private:
QMenu *m_contextMenu; QMenu *m_contextMenu;
unsigned int m_threads; unsigned int m_threads;
QStringList m_urls; QStringList m_urls;
QStringList m_pools{"pool.xmr.pt:9000", "pool.supportxmr.com:9000", "mine.xmrpool.net:443", "xmrpool.eu:9999", "xmr-eu1.nanopool.org:14433", "pool.minexmr.com:6666", "us-west.minexmr.com:6666", "monerohash.com:9999"}; QStringList m_pools{"pool.xmr.pt:9000", "pool.supportxmr.com:9000", "mine.xmrpool.net:443", "xmrpool.eu:9999", "xmr-eu1.nanopool.org:14433", "pool.minexmr.com:6666", "us-west.minexmr.com:6666", "monerohash.com:9999", "cryptonote.social:5555", "cryptonote.social:5556"};
}; };
#endif // REDDITWIDGET_H #endif // REDDITWIDGET_H

@ -66,6 +66,10 @@ int OpenWalletPage::nextId() const {
bool OpenWalletPage::validatePage() { bool OpenWalletPage::validatePage() {
QModelIndex index = ui->walletTable->currentIndex(); QModelIndex index = ui->walletTable->currentIndex();
if(!index.isValid()) {
Utils::showMessageBox("Wallet not selected", "Please select a wallet from the list.", true);
return false;
}
QString walletPath = index.model()->data(index.siblingAtColumn(WalletKeysFilesModel::ModelColumns::Path), Qt::UserRole).toString(); QString walletPath = index.model()->data(index.siblingAtColumn(WalletKeysFilesModel::ModelColumns::Path), Qt::UserRole).toString();
auto autoWallet = ui->openOnStartup->isChecked() ? QString("%1%2").arg(m_ctx->networkType).arg(walletPath) : ""; auto autoWallet = ui->openOnStartup->isChecked() ? QString("%1%2").arg(m_ctx->networkType).arg(walletPath) : "";

Loading…
Cancel
Save