diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml
index 33f2c585..ec53ec61 100644
--- a/components/ProgressBar.qml
+++ b/components/ProgressBar.qml
@@ -42,7 +42,7 @@ Item {
var progressLevel = ((currentBlock/targetBlock) * 100).toFixed(0);
fillLevel = progressLevel
progressText.text = qsTr("Synchronizing blocks %1/%2").arg(currentBlock.toFixed(0)).arg(targetBlock.toFixed(0));
- item.visible = (currentWallet.connected !== Wallet.ConnectionStatus_Disconnected) && (currentBlock < targetBlock)
+ progressBar.visible = currentBlock < targetBlock
}
}
diff --git a/main.qml b/main.qml
index d7f76b91..520b1397 100644
--- a/main.qml
+++ b/main.qml
@@ -55,7 +55,6 @@ ApplicationWindow {
property var transaction;
property var transactionDescription;
property alias password : passwordDialog.password
- property int splashCounter: 0
property bool isNewWallet: false
property int restoreHeight:0
property bool daemonSynced: false
@@ -265,10 +264,12 @@ ApplicationWindow {
return path.replace(/.*[\/\\]/, '').replace(/\.keys$/, '')
}
- function onWalletConnectionStatusChanged(){
+ function onWalletConnectionStatusChanged(status){
console.log("Wallet connection status changed")
middlePanel.updateStatus();
- }
+ leftPanel.networkStatus.connected = status
+ leftPanel.progressBar.visible = (status === Wallet.ConnectionStatus_Connected) && !daemonSynced
+ }
function onWalletOpened(wallet) {
walletName = usefulName(wallet.path)
@@ -310,7 +311,6 @@ ApplicationWindow {
console.log(">>> wallet updated")
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance);
middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance);
- console.log("time to unlock: ", currentWallet.history.minutesToUnlock);
// Update history if new block found since last update and balance is locked.
if(foundNewBlock && currentWallet.history.locked) {
foundNewBlock = false;
@@ -336,11 +336,16 @@ ApplicationWindow {
// Daemon fully synced
// TODO: implement onDaemonSynced or similar in wallet API and don't start refresh thread before daemon is synced
- daemonSynced = (currentWallet.connected != Wallet.ConnectionStatus_Disconnected && dCurrentBlock >= dTargetBlock)
+ daemonSynced = dCurrentBlock >= dTargetBlock
+ // Update daemon sync progress
leftPanel.progressBar.updateProgress(dCurrentBlock,dTargetBlock);
- updateSyncing((currentWallet.connected !== Wallet.ConnectionStatus_Disconnected) && (dCurrentBlock < dTargetBlock))
+ leftPanel.progressBar.visible = !daemonSynced && currentWallet.connected !== Wallet.ConnectionStatus_Disconnected
+ // Update wallet sync progress
+ updateSyncing((currentWallet.connected !== Wallet.ConnectionStatus_Disconnected) && !daemonSynced)
+ // Update transfer page status
middlePanel.updateStatus();
+
// If wallet isnt connected and no daemon is running - Ask
if(currentWallet.connected === Wallet.ConnectionStatus_Disconnected && !daemonManager.running() && !walletInitialized){
daemonManagerDialog.open();
@@ -392,17 +397,10 @@ ApplicationWindow {
daemonRunning = false;
}
- function onWalletNewBlock(blockHeight) {
- // Update progress bar
- var currHeight = blockHeight
- //fast refresh until restoreHeight is reached
- var increment = ((restoreHeight == 0) || currHeight < restoreHeight)? 1000 : 10
-
- if(currHeight > splashCounter + increment){
- splashCounter = currHeight
- leftPanel.progressBar.updateProgress(currHeight,currentWallet.daemonBlockChainTargetHeight());
- }
- foundNewBlock = true;
+ function onWalletNewBlock(blockHeight, targetHeight) {
+ // Update progress bar
+ leftPanel.progressBar.updateProgress(blockHeight,targetHeight);
+ foundNewBlock = true;
}
function onWalletMoneyReceived(txId, amount) {
@@ -712,7 +710,6 @@ ApplicationWindow {
// close wallet and show wizard
function showWizard(){
walletInitialized = false;
- splashCounter = 0;
closeWallet();
currentWallet = undefined;
wizard.restart();
diff --git a/pages/Settings.qml b/pages/Settings.qml
index e6088722..9bbb0ee3 100644
--- a/pages/Settings.qml
+++ b/pages/Settings.qml
@@ -324,8 +324,8 @@ Rectangle {
var newDaemon = daemonAddr.text + ":" + daemonPort.text
if(persistentSettings.daemon_address != newDaemon) {
persistentSettings.daemon_address = newDaemon
- //reconnect wallet
- appWindow.initialize();
+ //Reinit wallet
+ currentWallet.initAsync(newDaemon)
}
}
}
diff --git a/pages/Transfer.qml b/pages/Transfer.qml
index 28eebc22..79efc28d 100644
--- a/pages/Transfer.qml
+++ b/pages/Transfer.qml
@@ -682,7 +682,6 @@ Rectangle {
//TODO: enable send page when we're connected and daemon is synced
function updateStatus() {
- console.log("updated transfer page status")
if(typeof currentWallet === "undefined") {
statusText.text = qsTr("Wallet is not connected to daemon.") + "
" + root.startLinkText
return;
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index 2ade69bb..56121370 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -16,6 +16,8 @@
#include
#include
#include
+#include
+#include
namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10;
@@ -54,7 +56,7 @@ public:
virtual void newBlock(uint64_t height)
{
// qDebug() << __FUNCTION__;
- emit m_wallet->newBlock(height);
+ emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
}
virtual void updated()
@@ -103,17 +105,35 @@ bool Wallet::testnet() const
return m_walletImpl->testnet();
}
-Wallet::ConnectionStatus Wallet::connected() const
+
+void Wallet::updateConnectionStatusAsync()
{
- // cache connection status
- if (!m_initialized || m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl) {
- m_initialized = true;
- ConnectionStatus newStatus = static_cast(m_walletImpl->connected());
+ QFuture future = QtConcurrent::run(m_walletImpl, &Monero::Wallet::connected);
+ QFutureWatcher *connectionWatcher = new QFutureWatcher();
+
+ connect(connectionWatcher, &QFutureWatcher::finished, [=]() {
+ QFuture future = connectionWatcher->future();
+ connectionWatcher->deleteLater();
+ ConnectionStatus newStatus = static_cast(future.result());
if (newStatus != m_connectionStatus) {
m_connectionStatus = newStatus;
- emit connectionStatusChanged();
+ emit connectionStatusChanged(newStatus);
}
+ // Release lock
+ m_connectionStatusRunning = false;
+ });
+ connectionWatcher->setFuture(future);
+}
+
+Wallet::ConnectionStatus Wallet::connected(bool forceCheck)
+{
+ // cache connection status
+ if (forceCheck || !m_initialized || (m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl && !m_connectionStatusRunning) || m_connectionStatusTime.elapsed() > 30000) {
+ qDebug() << "Checking connection status";
+ m_connectionStatusRunning = true;
+ m_initialized = true;
m_connectionStatusTime.restart();
+ updateConnectionStatusAsync();
}
return m_connectionStatus;
@@ -151,17 +171,38 @@ bool Wallet::store(const QString &path)
bool Wallet::init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
{
- return m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit);
-}
-
-void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
-{
+ qDebug() << "init non async";
if (isRecovering){
qDebug() << "RESTORING";
m_walletImpl->setRecoveringFromSeed(true);
m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
}
- m_walletImpl->initAsync(daemonAddress.toStdString(), upperTransactionLimit);
+ m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit);
+ return true;
+}
+
+void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
+{
+ qDebug() << "initAsync: " + daemonAddress;
+ m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
+ emit connectionStatusChanged(m_connectionStatus);
+
+ QFuture future = QtConcurrent::run(this, &Wallet::init,
+ daemonAddress, upperTransactionLimit, isRecovering, restoreHeight);
+ QFutureWatcher * watcher = new QFutureWatcher();
+
+ connect(watcher, &QFutureWatcher::finished,
+ this, [this, watcher, daemonAddress, upperTransactionLimit, isRecovering, restoreHeight]() {
+ QFuture future = watcher->future();
+ watcher->deleteLater();
+ if(future.result()){
+ qDebug() << "init async finished - starting refresh";
+ connected(true);
+ m_walletImpl->startRefresh();
+
+ }
+ });
+ watcher->setFuture(future);
}
//! create a view only wallet
@@ -220,6 +261,7 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
if (m_daemonBlockChainTargetHeight == 0
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
+
// Target height is set to 0 if daemon is synced.
// Use current height from daemon when target height < current height
if (m_daemonBlockChainTargetHeight < m_daemonBlockChainHeight){
@@ -242,6 +284,7 @@ bool Wallet::refresh()
void Wallet::refreshAsync()
{
+ qDebug() << "refresh async";
m_walletImpl->refreshAsync();
}
@@ -273,13 +316,14 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
QFuture future = QtConcurrent::run(this, &Wallet::createTransaction,
dst_addr, payment_id,amount, mixin_count, priority);
QFutureWatcher * watcher = new QFutureWatcher();
- watcher->setFuture(future);
+
connect(watcher, &QFutureWatcher::finished,
this, [this, watcher,dst_addr,payment_id,mixin_count]() {
QFuture future = watcher->future();
watcher->deleteLater();
emit transactionCreated(future.result(),dst_addr,payment_id,mixin_count);
});
+ watcher->setFuture(future);
}
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
@@ -299,13 +343,14 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
QFuture future = QtConcurrent::run(this, &Wallet::createTransactionAll,
dst_addr, payment_id, mixin_count, priority);
QFutureWatcher * watcher = new QFutureWatcher();
- watcher->setFuture(future);
+
connect(watcher, &QFutureWatcher::finished,
this, [this, watcher,dst_addr,payment_id,mixin_count]() {
QFuture future = watcher->future();
watcher->deleteLater();
emit transactionCreated(future.result(),dst_addr,payment_id,mixin_count);
});
+ watcher->setFuture(future);
}
PendingTransaction *Wallet::createSweepUnmixableTransaction()
@@ -319,13 +364,14 @@ void Wallet::createSweepUnmixableTransactionAsync()
{
QFuture future = QtConcurrent::run(this, &Wallet::createSweepUnmixableTransaction);
QFutureWatcher * watcher = new QFutureWatcher();
- watcher->setFuture(future);
+
connect(watcher, &QFutureWatcher::finished,
this, [this, watcher]() {
QFuture future = watcher->future();
watcher->deleteLater();
emit transactionCreated(future.result(),"","",0);
});
+ watcher->setFuture(future);
}
UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
@@ -542,6 +588,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_daemonBlockChainHeightTime.restart();
m_daemonBlockChainTargetHeightTime.restart();
m_initialized = false;
+ m_connectionStatusRunning = false;
}
Wallet::~Wallet()
diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h
index 9aec45fc..7e9651e4 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -3,6 +3,8 @@
#include
#include
+#include
+#include
#include "wallet/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
#include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here;
@@ -75,7 +77,8 @@ public:
bool testnet() const;
//! returns whether the wallet is connected, and version status
- ConnectionStatus connected() const;
+ ConnectionStatus connected(bool forceCheck = false);
+ void updateConnectionStatusAsync();
//! returns true if wallet was ever synchronized
bool synchronized() const;
@@ -98,10 +101,10 @@ public:
Q_INVOKABLE bool store(const QString &path = "");
//! initializes wallet
- Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering = false, quint64 restoreHeight = 0);
+ Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, quint64 restoreHeight = 0);
//! initializes wallet asynchronously
- Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering = false, quint64 restoreHeight = 0);
+ Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, quint64 restoreHeight = 0);
//! create a view only wallet
Q_INVOKABLE bool createViewOnly(const QString &path, const QString &password) const;
@@ -231,13 +234,13 @@ signals:
void moneySpent(const QString &txId, quint64 amount);
void moneyReceived(const QString &txId, quint64 amount);
void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
- void newBlock(quint64 height);
+ void newBlock(quint64 height, quint64 targetHeight);
void historyModelChanged() const;
// emitted when transaction is created async
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
- void connectionStatusChanged() const;
+ void connectionStatusChanged(ConnectionStatus status) const;
private:
Wallet(QObject * parent = nullptr);
@@ -266,6 +269,8 @@ private:
mutable bool m_initialized;
AddressBook * m_addressBook;
mutable AddressBookModel * m_addressBookModel;
+ QMutex m_connectionStatusMutex;
+ bool m_connectionStatusRunning;
};
diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp
index 1db216cf..df0ffdbd 100644
--- a/src/libwalletqt/WalletManager.cpp
+++ b/src/libwalletqt/WalletManager.cpp
@@ -64,13 +64,14 @@ void WalletManager::openWalletAsync(const QString &path, const QString &password
QFuture future = QtConcurrent::run(this, &WalletManager::openWallet,
path, password, testnet);
QFutureWatcher * watcher = new QFutureWatcher();
- watcher->setFuture(future);
+
connect(watcher, &QFutureWatcher::finished,
this, [this, watcher]() {
QFuture future = watcher->future();
watcher->deleteLater();
emit walletOpened(future.result());
});
+ watcher->setFuture(future);
}
@@ -121,7 +122,6 @@ void WalletManager::closeWalletAsync()
{
QFuture future = QtConcurrent::run(this, &WalletManager::closeWallet);
QFutureWatcher * watcher = new QFutureWatcher();
- watcher->setFuture(future);
connect(watcher, &QFutureWatcher::finished,
this, [this, watcher]() {
@@ -129,6 +129,7 @@ void WalletManager::closeWalletAsync()
watcher->deleteLater();
emit walletClosed(future.result());
});
+ watcher->setFuture(future);
}
bool WalletManager::walletExists(const QString &path) const
@@ -256,6 +257,8 @@ double WalletManager::miningHashRate() const
bool WalletManager::isMining() const
{
+ if(!m_currentWallet->connected())
+ return false;
return m_pimpl->isMining();
}