forked from Public/monero-gui
Merge pull request #217
3752ec7send page: check daemon status after every refresh (Jaquee)01549a3walletManager: coding conventions (Jaquee)0ae3d67daemon console -> log + adjusted height (Jaquee)0e8cd14Wallet: add m_initialized (Jaquee)c7232e1set wallet connection status before querying sync status (Jaquee)3f8e05dWallet: Cache connection status query (Jaquee)36a6b89connect onWalletConnectionStatusChanged() (Jaquee)93a8200Transfer: new connectionStatus handling + show status msg (Jaquee)76e6ae8remove reference to old pw-dialog (Jaquee)18b7a67Wallet: add connectionStatusChanged signal (Jaquee)d9f4ab4daemonManager: wait for daemon stop on app close (Jaquee)f62bb68daemonManagerDialog: use new ConnectionStatus enum (Jaquee)dd01f59hide daemon sync progress after disconnecting wallet (Jaquee)8d19a03DaemonManager: add stateChanged() (Jaquee)760e01bdaemonManagerDialog: show processdialog when starting (Jaquee)bb881d9show processingSplash when starting/stopping daemon (Jaquee)8361ddaresolve rebase conflict (Jaquee)8dfa79eShutdown daemon and close wallet properly on app exit (Jaquee)7876957DaemonManager::closing() (Jacob Brydolf)065b060main: debug messages (Jacob Brydolf)b4eb489DaemonManager: forward command line arguments to monerod (Jacob Brydolf)752ff26forward command line arguments to DaemonManager (Jaquee)7840dabDaemonManager: console debug output (Jacob Brydolf)14a5bd5settings: added daemon console (Jacob Brydolf)b53ef00history tx details: resized popup (Jacob Brydolf)b4f29b2StandardDialog: changed default sizes (Jacob Brydolf)5855700daemonManagerDialog: added starting signal (Jacob Brydolf)3a43154DaemonManager: added console updated signals (Jacob Brydolf)3df9e44DaemonManager: windows support (Jacob Brydolf)5da9f8fstandardDialog: close window before continue (Jacob Brydolf)5a110f4replace message dialog with custom dialog (Jacob Brydolf)d465780resized standard dialog (Jacob Brydolf)482bd30settings: enable/disable daemon start/stop buttons (Jacob Brydolf)4e7de8cproper daemon shutdown on app exit (Jaquee)48471f3onDaemonStarted/stopped signals/slots (Jaquee)de635cbpw dialog: close popup before continue (Jacob Brydolf)86772beadded standardDialog component (Jacob Brydolf)ae977afsettings: add daemon manager (Jacob Brydolf)2775124small error in daemon manager dialog (Jacob Brydolf)82c39e0WalletManager: include dependencies (Jaquee)1c6884eShow daemon manager dialog if daemon isnt started (Jacob Brydolf)9fbfbc4daemonManager: embed as context property (Jaquee)4cdc258WalletManager: basic functionality (Jacob Brydolf)
This commit is contained in:
@@ -32,6 +32,7 @@ import QtQuick 2.2
|
|||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
|
import moneroComponents.Wallet 1.0
|
||||||
|
|
||||||
import "./pages"
|
import "./pages"
|
||||||
|
|
||||||
@@ -56,9 +57,6 @@ Rectangle {
|
|||||||
signal generatePaymentIdInvoked()
|
signal generatePaymentIdInvoked()
|
||||||
signal checkPaymentClicked(string address, string txid, string txkey);
|
signal checkPaymentClicked(string address, string txid, string txkey);
|
||||||
|
|
||||||
// Disable transfer page if daemon isnt fully synced
|
|
||||||
enabled: (currentView !== transferView || appWindow.daemonSynced)
|
|
||||||
|
|
||||||
color: "#F0EEEE"
|
color: "#F0EEEE"
|
||||||
|
|
||||||
onCurrentViewChanged: {
|
onCurrentViewChanged: {
|
||||||
@@ -72,6 +70,10 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateStatus(){
|
||||||
|
transferView.updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// XXX: just for memo, to be removed
|
// XXX: just for memo, to be removed
|
||||||
// states: [
|
// states: [
|
||||||
@@ -292,14 +294,6 @@ Rectangle {
|
|||||||
color: "#DBDBDB"
|
color: "#DBDBDB"
|
||||||
|
|
||||||
}
|
}
|
||||||
Rectangle {
|
|
||||||
id:desaturate
|
|
||||||
color:"black"
|
|
||||||
anchors.fill: parent
|
|
||||||
opacity: 0.1
|
|
||||||
visible: (root.enabled)? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* connect "payment" click */
|
/* connect "payment" click */
|
||||||
Connections {
|
Connections {
|
||||||
|
|||||||
120
components/DaemonManagerDialog.qml
Normal file
120
components/DaemonManagerDialog.qml
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
// Copyright (c) 2014-2015, 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.
|
||||||
|
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
|
||||||
|
import "../components" as MoneroComponents
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: root
|
||||||
|
modality: Qt.ApplicationModal
|
||||||
|
flags: Qt.Window | Qt.FramelessWindowHint
|
||||||
|
|
||||||
|
signal rejected()
|
||||||
|
signal started();
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement without hardcoding sizes
|
||||||
|
width: 480
|
||||||
|
height: 200
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: mainLayout
|
||||||
|
spacing: 10
|
||||||
|
anchors { fill: parent; margins: 35 }
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: column
|
||||||
|
//anchors {fill: parent; margins: 16 }
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Daemon doesn't appear to be running")
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: 24
|
||||||
|
font.family: "Arial"
|
||||||
|
color: "#555555"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: buttons
|
||||||
|
spacing: 60
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: okButton
|
||||||
|
width: 120
|
||||||
|
fontSize: 14
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
text: qsTr("Start daemon")
|
||||||
|
KeyNavigation.tab: cancelButton
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
appWindow.startDaemon();
|
||||||
|
root.started()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: cancelButton
|
||||||
|
width: 120
|
||||||
|
fontSize: 14
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
root.rejected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
|
import moneroComponents.Wallet 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: item
|
id: item
|
||||||
@@ -45,7 +46,7 @@ Item {
|
|||||||
|
|
||||||
// TODO: lower daemon block height cache, ttl and refresh interval?
|
// TODO: lower daemon block height cache, ttl and refresh interval?
|
||||||
|
|
||||||
item.visible = (currentBlock < targetBlock)
|
item.visible = (currentWallet.connected !== Wallet.ConnectionStatus_Disconnected) && (currentBlock < targetBlock)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ ListView {
|
|||||||
|
|
||||||
StandardDialog {
|
StandardDialog {
|
||||||
id: detailsPopup
|
id: detailsPopup
|
||||||
|
width:600
|
||||||
cancelVisible: false
|
cancelVisible: false
|
||||||
okVisible: true
|
okVisible: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,8 +152,8 @@ Window {
|
|||||||
text: qsTr("Cancel")
|
text: qsTr("Cancel")
|
||||||
KeyNavigation.tab: passwordInput
|
KeyNavigation.tab: passwordInput
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.rejected()
|
|
||||||
root.close()
|
root.close()
|
||||||
|
root.rejected()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MoneroComponents.StandardButton {
|
MoneroComponents.StandardButton {
|
||||||
@@ -167,8 +167,8 @@ Window {
|
|||||||
text: qsTr("Ok")
|
text: qsTr("Ok")
|
||||||
KeyNavigation.tab: cancelButton
|
KeyNavigation.tab: cancelButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.accepted()
|
|
||||||
root.close()
|
root.close()
|
||||||
|
root.accepted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,12 @@ Window {
|
|||||||
modality: Qt.ApplicationModal
|
modality: Qt.ApplicationModal
|
||||||
flags: Qt.Window | Qt.FramelessWindowHint
|
flags: Qt.Window | Qt.FramelessWindowHint
|
||||||
property alias title: dialogTitle.text
|
property alias title: dialogTitle.text
|
||||||
property alias content: dialogContent.text
|
property alias text: dialogContent.text
|
||||||
|
property alias content: root.text
|
||||||
property alias cancelVisible: cancelButton.visible
|
property alias cancelVisible: cancelButton.visible
|
||||||
property alias okVisible: okButton.visible
|
property alias okVisible: okButton.visible
|
||||||
|
property alias textArea: dialogContent
|
||||||
|
property var icon
|
||||||
|
|
||||||
// same signals as Dialog has
|
// same signals as Dialog has
|
||||||
signal accepted()
|
signal accepted()
|
||||||
@@ -54,8 +57,8 @@ Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement without hardcoding sizes
|
// TODO: implement without hardcoding sizes
|
||||||
width: 600
|
width: 480
|
||||||
height: 480
|
height: 280
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: mainLayout
|
id: mainLayout
|
||||||
@@ -81,6 +84,7 @@ Window {
|
|||||||
TextArea {
|
TextArea {
|
||||||
id : dialogContent
|
id : dialogContent
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
textFormat: TextEdit.AutoText
|
textFormat: TextEdit.AutoText
|
||||||
readOnly: true
|
readOnly: true
|
||||||
@@ -105,8 +109,9 @@ Window {
|
|||||||
text: qsTr("Ok")
|
text: qsTr("Ok")
|
||||||
KeyNavigation.tab: cancelButton
|
KeyNavigation.tab: cancelButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.accepted()
|
|
||||||
root.close()
|
root.close()
|
||||||
|
root.accepted()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,8 +125,8 @@ Window {
|
|||||||
pressedColor: "#FF4304"
|
pressedColor: "#FF4304"
|
||||||
text: qsTr("Cancel")
|
text: qsTr("Cancel")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.rejected()
|
|
||||||
root.close()
|
root.close()
|
||||||
|
root.rejected()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
main.cpp
8
main.cpp
@@ -31,6 +31,7 @@
|
|||||||
#include <QtQml>
|
#include <QtQml>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
#include "clipboardAdapter.h"
|
#include "clipboardAdapter.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "oscursor.h"
|
#include "oscursor.h"
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
#include "TransactionHistory.h"
|
#include "TransactionHistory.h"
|
||||||
#include "model/TransactionHistoryModel.h"
|
#include "model/TransactionHistoryModel.h"
|
||||||
#include "model/TransactionHistorySortFilterModel.h"
|
#include "model/TransactionHistorySortFilterModel.h"
|
||||||
|
#include "daemon/DaemonManager.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -88,6 +90,8 @@ int main(int argc, char *argv[])
|
|||||||
qmlRegisterUncreatableType<TransactionInfo>("moneroComponents.TransactionInfo", 1, 0, "TransactionInfo",
|
qmlRegisterUncreatableType<TransactionInfo>("moneroComponents.TransactionInfo", 1, 0, "TransactionInfo",
|
||||||
"TransactionHistory can't be instantiated directly");
|
"TransactionHistory can't be instantiated directly");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<DaemonManager>("moneroComponents.DaemonManager", 1, 0, "DaemonManager",
|
||||||
|
"DaemonManager can't be instantiated directly");
|
||||||
qRegisterMetaType<PendingTransaction::Priority>();
|
qRegisterMetaType<PendingTransaction::Priority>();
|
||||||
qRegisterMetaType<TransactionInfo::Direction>();
|
qRegisterMetaType<TransactionInfo::Direction>();
|
||||||
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||||
@@ -104,6 +108,10 @@ int main(int argc, char *argv[])
|
|||||||
engine.rootContext()->setContextProperty("translationManager", TranslationManager::instance());
|
engine.rootContext()->setContextProperty("translationManager", TranslationManager::instance());
|
||||||
|
|
||||||
engine.addImageProvider(QLatin1String("qrcode"), new QRCodeImageProvider());
|
engine.addImageProvider(QLatin1String("qrcode"), new QRCodeImageProvider());
|
||||||
|
const QStringList arguments = QCoreApplication::arguments();
|
||||||
|
DaemonManager * daemonManager = DaemonManager::instance(&arguments);
|
||||||
|
QObject::connect(&app, SIGNAL(aboutToQuit()), daemonManager, SLOT(closing()));
|
||||||
|
engine.rootContext()->setContextProperty("daemonManager", daemonManager);
|
||||||
|
|
||||||
// export to QML monero accounts root directory
|
// export to QML monero accounts root directory
|
||||||
// wizard is talking about where
|
// wizard is talking about where
|
||||||
|
|||||||
70
main.qml
70
main.qml
@@ -59,6 +59,7 @@ ApplicationWindow {
|
|||||||
property int restoreHeight:0
|
property int restoreHeight:0
|
||||||
property bool daemonSynced: false
|
property bool daemonSynced: false
|
||||||
property int maxWindowHeight: (Screen.height < 900)? 720 : 800;
|
property int maxWindowHeight: (Screen.height < 900)? 720 : 800;
|
||||||
|
property bool daemonRunning: false
|
||||||
|
|
||||||
// true if wallet ever synchronized
|
// true if wallet ever synchronized
|
||||||
property bool walletInitialized : false
|
property bool walletInitialized : false
|
||||||
@@ -212,6 +213,7 @@ ApplicationWindow {
|
|||||||
currentWallet.moneySpent.disconnect(onWalletMoneySent)
|
currentWallet.moneySpent.disconnect(onWalletMoneySent)
|
||||||
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
|
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
|
||||||
currentWallet.transactionCreated.disconnect(onTransactionCreated)
|
currentWallet.transactionCreated.disconnect(onTransactionCreated)
|
||||||
|
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
|
||||||
|
|
||||||
currentWallet.refreshed.connect(onWalletRefresh)
|
currentWallet.refreshed.connect(onWalletRefresh)
|
||||||
currentWallet.updated.connect(onWalletUpdate)
|
currentWallet.updated.connect(onWalletUpdate)
|
||||||
@@ -219,6 +221,7 @@ ApplicationWindow {
|
|||||||
currentWallet.moneySpent.connect(onWalletMoneySent)
|
currentWallet.moneySpent.connect(onWalletMoneySent)
|
||||||
currentWallet.moneyReceived.connect(onWalletMoneyReceived)
|
currentWallet.moneyReceived.connect(onWalletMoneyReceived)
|
||||||
currentWallet.transactionCreated.connect(onTransactionCreated)
|
currentWallet.transactionCreated.connect(onTransactionCreated)
|
||||||
|
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
|
||||||
|
|
||||||
|
|
||||||
console.log("initializing with daemon address: ", persistentSettings.daemon_address)
|
console.log("initializing with daemon address: ", persistentSettings.daemon_address)
|
||||||
@@ -232,6 +235,11 @@ ApplicationWindow {
|
|||||||
return wallet_path;
|
return wallet_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onWalletConnectionStatusChanged(){
|
||||||
|
console.log("Wallet connection status changed")
|
||||||
|
middlePanel.updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
function onWalletOpened(wallet) {
|
function onWalletOpened(wallet) {
|
||||||
console.log(">>> wallet opened: " + wallet)
|
console.log(">>> wallet opened: " + wallet)
|
||||||
if (wallet.status !== Wallet.Status_Ok) {
|
if (wallet.status !== Wallet.Status_Ok) {
|
||||||
@@ -280,18 +288,23 @@ ApplicationWindow {
|
|||||||
hideProcessingSplash()
|
hideProcessingSplash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Daemon connected
|
||||||
|
leftPanel.networkStatus.connected = currentWallet.connected
|
||||||
|
|
||||||
// Check daemon status
|
// Check daemon status
|
||||||
var dCurrentBlock = currentWallet.daemonBlockChainHeight();
|
var dCurrentBlock = currentWallet.daemonBlockChainHeight();
|
||||||
var dTargetBlock = currentWallet.daemonBlockChainTargetHeight();
|
var dTargetBlock = currentWallet.daemonBlockChainTargetHeight();
|
||||||
leftPanel.daemonProgress.updateProgress(dCurrentBlock,dTargetBlock);
|
|
||||||
|
|
||||||
// Daemon connected
|
|
||||||
leftPanel.networkStatus.connected = currentWallet.connected
|
|
||||||
|
|
||||||
// Daemon fully synced
|
// Daemon fully synced
|
||||||
// TODO: implement onDaemonSynced or similar in wallet API and don't start refresh thread before daemon is 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 = (currentWallet.connected != Wallet.ConnectionStatus_Disconnected && dCurrentBlock >= dTargetBlock)
|
||||||
|
leftPanel.daemonProgress.updateProgress(dCurrentBlock,dTargetBlock);
|
||||||
|
middlePanel.updateStatus();
|
||||||
|
|
||||||
|
// If wallet isnt connected and no daemon is running - Ask
|
||||||
|
if(currentWallet.connected === Wallet.ConnectionStatus_Disconnected && !daemonManager.running() && !walletInitialized){
|
||||||
|
daemonManagerDialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
// Refresh is succesfull if blockchain height > 1
|
// Refresh is succesfull if blockchain height > 1
|
||||||
if (currentWallet.blockChainHeight() > 1){
|
if (currentWallet.blockChainHeight() > 1){
|
||||||
@@ -317,10 +330,29 @@ ApplicationWindow {
|
|||||||
walletInitialized = true
|
walletInitialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onWalletUpdate();
|
onWalletUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startDaemon(){
|
||||||
|
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
|
||||||
|
daemonManager.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopDaemon(){
|
||||||
|
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."))
|
||||||
|
daemonManager.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDaemonStarted(){
|
||||||
|
console.log("daemon started");
|
||||||
|
daemonRunning = true;
|
||||||
|
}
|
||||||
|
function onDaemonStopped(){
|
||||||
|
console.log("daemon stopped");
|
||||||
|
daemonRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function onWalletNewBlock(blockHeight) {
|
function onWalletNewBlock(blockHeight) {
|
||||||
if (splash.visible) {
|
if (splash.visible) {
|
||||||
var currHeight = blockHeight
|
var currHeight = blockHeight
|
||||||
@@ -633,6 +665,9 @@ ApplicationWindow {
|
|||||||
walletManager.walletOpened.connect(onWalletOpened);
|
walletManager.walletOpened.connect(onWalletOpened);
|
||||||
walletManager.walletClosed.connect(onWalletClosed);
|
walletManager.walletClosed.connect(onWalletClosed);
|
||||||
|
|
||||||
|
daemonManager.daemonStarted.connect(onDaemonStarted);
|
||||||
|
daemonManager.daemonStopped.connect(onDaemonStopped);
|
||||||
|
|
||||||
if(!walletsFound()) {
|
if(!walletsFound()) {
|
||||||
rootItem.state = "wizard"
|
rootItem.state = "wizard"
|
||||||
} else {
|
} else {
|
||||||
@@ -668,11 +703,11 @@ ApplicationWindow {
|
|||||||
// TODO: replace with customized popups
|
// TODO: replace with customized popups
|
||||||
|
|
||||||
// Information dialog
|
// Information dialog
|
||||||
MessageDialog {
|
StandardDialog {
|
||||||
// dynamically change onclose handler
|
// dynamically change onclose handler
|
||||||
property var onCloseCallback
|
property var onCloseCallback
|
||||||
id: informationPopup
|
id: informationPopup
|
||||||
standardButtons: StandardButton.Ok
|
cancelVisible: false
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
if (onCloseCallback) {
|
if (onCloseCallback) {
|
||||||
onCloseCallback()
|
onCloseCallback()
|
||||||
@@ -681,10 +716,10 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Confrirmation aka question dialog
|
// Confrirmation aka question dialog
|
||||||
MessageDialog {
|
StandardDialog {
|
||||||
id: transactionConfirmationPopup
|
id: transactionConfirmationPopup
|
||||||
standardButtons: StandardButton.Ok + StandardButton.Cancel
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
|
close();
|
||||||
handleTransactionConfirmed()
|
handleTransactionConfirmed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -721,6 +756,10 @@ ApplicationWindow {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DaemonManagerDialog {
|
||||||
|
id: daemonManagerDialog
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ProcessingSplash {
|
ProcessingSplash {
|
||||||
id: splash
|
id: splash
|
||||||
@@ -1032,10 +1071,13 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClosing: {
|
onClosing: {
|
||||||
// Close and save to disk on app close
|
// Make sure wallet is closed before app exit (~Wallet() isn't always invoked)
|
||||||
if (currentWallet != undefined) {
|
// Daemon shutdown is handled with signal/slot in main.cpp
|
||||||
walletManager.closeWallet(currentWallet);
|
if (currentWallet != undefined) {
|
||||||
currentWallet = undefined
|
walletManager.closeWallet(currentWallet);
|
||||||
}
|
currentWallet = undefined
|
||||||
|
}
|
||||||
|
// Stop daemon
|
||||||
|
daemonManager.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ HEADERS += \
|
|||||||
src/model/TransactionHistorySortFilterModel.h \
|
src/model/TransactionHistorySortFilterModel.h \
|
||||||
src/QR-Code-generator/BitBuffer.hpp \
|
src/QR-Code-generator/BitBuffer.hpp \
|
||||||
src/QR-Code-generator/QrCode.hpp \
|
src/QR-Code-generator/QrCode.hpp \
|
||||||
src/QR-Code-generator/QrSegment.hpp
|
src/QR-Code-generator/QrSegment.hpp \
|
||||||
|
src/daemon/DaemonManager.h
|
||||||
|
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
@@ -49,7 +50,8 @@ SOURCES += main.cpp \
|
|||||||
src/model/TransactionHistorySortFilterModel.cpp \
|
src/model/TransactionHistorySortFilterModel.cpp \
|
||||||
src/QR-Code-generator/BitBuffer.cpp \
|
src/QR-Code-generator/BitBuffer.cpp \
|
||||||
src/QR-Code-generator/QrCode.cpp \
|
src/QR-Code-generator/QrCode.cpp \
|
||||||
src/QR-Code-generator/QrSegment.cpp
|
src/QR-Code-generator/QrSegment.cpp \
|
||||||
|
src/daemon/DaemonManager.cpp
|
||||||
|
|
||||||
lupdate_only {
|
lupdate_only {
|
||||||
SOURCES = *.qml \
|
SOURCES = *.qml \
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ import "../components"
|
|||||||
import moneroComponents.Clipboard 1.0
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
||||||
property var daemonAddress
|
property var daemonAddress
|
||||||
|
|
||||||
color: "#F0EEEE"
|
color: "#F0EEEE"
|
||||||
@@ -272,15 +271,94 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Label {
|
||||||
|
id: manageDaemonLabel
|
||||||
|
color: "#4A4949"
|
||||||
|
text: qsTr("Manage daemon") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
visible: true
|
||||||
|
enabled: !appWindow.daemonRunning
|
||||||
|
id: startDaemonButton
|
||||||
|
width: 110
|
||||||
|
text: qsTr("Start daemon") + translationManager.emptyString
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
onClicked: {
|
||||||
|
appWindow.startDaemon()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
visible: true
|
||||||
|
enabled: appWindow.daemonRunning
|
||||||
|
id: stopDaemonButton
|
||||||
|
width: 110
|
||||||
|
text: qsTr("Stop daemon") + translationManager.emptyString
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
onClicked: {
|
||||||
|
appWindow.stopDaemon()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
visible: true
|
||||||
|
// enabled: appWindow.daemonRunning
|
||||||
|
id: daemonConsolePopupButton
|
||||||
|
width: 110
|
||||||
|
text: qsTr("Show log") + translationManager.emptyString
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
onClicked: {
|
||||||
|
daemonConsolePopup.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Daemon console
|
||||||
|
StandardDialog {
|
||||||
|
id: daemonConsolePopup
|
||||||
|
height:500
|
||||||
|
width:800
|
||||||
|
cancelVisible: false
|
||||||
|
title: qsTr("Daemon log")
|
||||||
|
onAccepted: {
|
||||||
|
close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// fires on every page load
|
||||||
function onPageCompleted() {
|
function onPageCompleted() {
|
||||||
console.log("Settings page loaded");
|
console.log("Settings page loaded");
|
||||||
initSettings();
|
initSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fires only once
|
||||||
|
Component.onCompleted: {
|
||||||
|
daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDaemonConsoleUpdated(message){
|
||||||
|
// Update daemon console
|
||||||
|
daemonConsolePopup.textArea.append(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import moneroComponents.PendingTransaction 1.0
|
import moneroComponents.PendingTransaction 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
|
import moneroComponents.Wallet 1.0
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -331,4 +332,69 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id:desaturate
|
||||||
|
color:"black"
|
||||||
|
anchors.fill: parent
|
||||||
|
opacity: 0.1
|
||||||
|
visible: (root.enabled)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
x: root.width/2 - width/2
|
||||||
|
y: root.height/2 - height/2
|
||||||
|
height:statusText.paintedHeight + 50
|
||||||
|
width:statusText.paintedWidth + 40
|
||||||
|
visible: statusText.text != ""
|
||||||
|
opacity: 0.9
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: statusText
|
||||||
|
anchors.fill:parent
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
//Disable password page until enabled by updateStatus
|
||||||
|
root.enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// fires on every page load
|
||||||
|
function onPageCompleted() {
|
||||||
|
console.log("transfer page loaded")
|
||||||
|
updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Add daemon sync status
|
||||||
|
//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.")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (currentWallet.connected) {
|
||||||
|
case Wallet.ConnectionStatus_Disconnected:
|
||||||
|
statusText.text = qsTr("Wallet is not connected to daemon.")
|
||||||
|
break
|
||||||
|
case Wallet.ConnectionStatus_WrongVersion:
|
||||||
|
statusText.text = qsTr("Connected daemon is not compatible with GUI. \n" +
|
||||||
|
"Please upgrade or connect to another daemon")
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
if(!appWindow.daemonSynced){
|
||||||
|
statusText.text = qsTr("Waiting on daemon synchronization to finish")
|
||||||
|
} else {
|
||||||
|
// everything OK, enable transfer page
|
||||||
|
root.enabled = true;
|
||||||
|
statusText.text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
qml.qrc
2
qml.qrc
@@ -120,5 +120,7 @@
|
|||||||
<file>components/DaemonProgress.qml</file>
|
<file>components/DaemonProgress.qml</file>
|
||||||
<file>components/StandardDialog.qml</file>
|
<file>components/StandardDialog.qml</file>
|
||||||
<file>pages/Sign.qml</file>
|
<file>pages/Sign.qml</file>
|
||||||
|
<file>components/DaemonManagerDialog.qml</file>
|
||||||
|
<file>components/StandardDialog.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
142
src/daemon/DaemonManager.cpp
Normal file
142
src/daemon/DaemonManager.cpp
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#include "DaemonManager.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
DaemonManager * DaemonManager::m_instance = nullptr;
|
||||||
|
QStringList DaemonManager::m_clArgs;
|
||||||
|
|
||||||
|
DaemonManager *DaemonManager::instance(const QStringList *args)
|
||||||
|
{
|
||||||
|
if (!m_instance) {
|
||||||
|
m_instance = new DaemonManager;
|
||||||
|
// store command line arguments for later use
|
||||||
|
m_clArgs = *args;
|
||||||
|
m_clArgs.removeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonManager::start()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
QString process;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
process = QApplication::applicationDirPath() + "/monerod.exe";
|
||||||
|
#elif defined(Q_OS_UNIX)
|
||||||
|
process = QApplication::applicationDirPath() + "/monerod";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (process.length() == 0) {
|
||||||
|
qDebug() << "no daemon binary defined for current platform";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// prepare command line arguments and pass to monerod
|
||||||
|
QStringList arguments;
|
||||||
|
foreach (const QString &str, m_clArgs) {
|
||||||
|
qDebug() << QString(" [%1] ").arg(str);
|
||||||
|
arguments << str;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "starting monerod " + process;
|
||||||
|
qDebug() << "With command line arguments " << arguments;
|
||||||
|
|
||||||
|
m_daemon = new QProcess();
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
// Connect output slots
|
||||||
|
connect (m_daemon, SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput()));
|
||||||
|
connect (m_daemon, SIGNAL(readyReadStandardError()), this, SLOT(printError()));
|
||||||
|
|
||||||
|
// Start monerod
|
||||||
|
m_daemon->start(process,arguments);
|
||||||
|
bool started = m_daemon->waitForStarted();
|
||||||
|
|
||||||
|
// add state changed listener
|
||||||
|
connect(m_daemon,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(stateChanged(QProcess::ProcessState)));
|
||||||
|
|
||||||
|
if (!started) {
|
||||||
|
qDebug() << "Daemon start error: " + m_daemon->errorString();
|
||||||
|
} else {
|
||||||
|
emit daemonStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
return started;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonManager::stop()
|
||||||
|
{
|
||||||
|
if (initialized) {
|
||||||
|
qDebug() << "stopping daemon";
|
||||||
|
// we can't use QProcess::terminate() on windows console process
|
||||||
|
// write exit command to stdin
|
||||||
|
m_daemon->write("exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonManager::stateChanged(QProcess::ProcessState state)
|
||||||
|
{
|
||||||
|
qDebug() << "STATE CHANGED: " << state;
|
||||||
|
if (state == QProcess::NotRunning) {
|
||||||
|
emit daemonStopped();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonManager::printOutput()
|
||||||
|
{
|
||||||
|
QByteArray byteArray = m_daemon->readAllStandardOutput();
|
||||||
|
QStringList strLines = QString(byteArray).split("\n");
|
||||||
|
|
||||||
|
foreach (QString line, strLines) {
|
||||||
|
emit daemonConsoleUpdated(line);
|
||||||
|
qDebug() << "Daemon: " + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonManager::printError()
|
||||||
|
{
|
||||||
|
QByteArray byteArray = m_daemon->readAllStandardError();
|
||||||
|
QStringList strLines = QString(byteArray).split("\n");
|
||||||
|
|
||||||
|
foreach (QString line, strLines) {
|
||||||
|
emit daemonConsoleUpdated(line);
|
||||||
|
qDebug() << "Daemon ERROR: " + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonManager::running() const
|
||||||
|
{
|
||||||
|
if (initialized) {
|
||||||
|
qDebug() << m_daemon->state();
|
||||||
|
qDebug() << QProcess::NotRunning;
|
||||||
|
// m_daemon->write("status\n");
|
||||||
|
return m_daemon->state() > QProcess::NotRunning;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DaemonManager::DaemonManager(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonManager::closing()
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
stop();
|
||||||
|
// Wait for daemon to stop before exiting (max 10 secs)
|
||||||
|
if (initialized) {
|
||||||
|
m_daemon->waitForFinished(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/daemon/DaemonManager.h
Normal file
43
src/daemon/DaemonManager.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef DAEMONMANAGER_H
|
||||||
|
#define DAEMONMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
class DaemonManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static DaemonManager * instance(const QStringList *args);
|
||||||
|
|
||||||
|
Q_INVOKABLE bool start();
|
||||||
|
Q_INVOKABLE bool stop();
|
||||||
|
|
||||||
|
// return true if daemon process is started
|
||||||
|
Q_INVOKABLE bool running() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void daemonStarted();
|
||||||
|
void daemonStopped();
|
||||||
|
void daemonConsoleUpdated(QString message);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void printOutput();
|
||||||
|
void printError();
|
||||||
|
void closing();
|
||||||
|
void stateChanged(QProcess::ProcessState state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
explicit DaemonManager(QObject *parent = 0);
|
||||||
|
static DaemonManager * m_instance;
|
||||||
|
static QStringList m_clArgs;
|
||||||
|
QProcess *m_daemon;
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DAEMONMANAGER_H
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10;
|
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10;
|
||||||
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 60;
|
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 60;
|
||||||
|
static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletListenerImpl : public Bitmonero::WalletListener
|
class WalletListenerImpl : public Bitmonero::WalletListener
|
||||||
@@ -89,7 +90,18 @@ Wallet::Status Wallet::status() const
|
|||||||
|
|
||||||
Wallet::ConnectionStatus Wallet::connected() const
|
Wallet::ConnectionStatus Wallet::connected() const
|
||||||
{
|
{
|
||||||
return static_cast<ConnectionStatus>(m_walletImpl->connected());
|
// cache connection status
|
||||||
|
if (!m_initialized || m_connectionStatusTime.elapsed() / 1000 > m_connectionStatusTtl) {
|
||||||
|
m_initialized = true;
|
||||||
|
ConnectionStatus newStatus = static_cast<ConnectionStatus>(m_walletImpl->connected());
|
||||||
|
if (newStatus != m_connectionStatus) {
|
||||||
|
m_connectionStatus = newStatus;
|
||||||
|
emit connectionStatusChanged();
|
||||||
|
}
|
||||||
|
m_connectionStatusTime.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_connectionStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wallet::synchronized() const
|
bool Wallet::synchronized() const
|
||||||
@@ -424,9 +436,16 @@ Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent)
|
|||||||
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
||||||
, m_daemonBlockChainTargetHeight(0)
|
, m_daemonBlockChainTargetHeight(0)
|
||||||
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
|
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
|
||||||
|
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
||||||
{
|
{
|
||||||
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
||||||
m_walletImpl->setListener(new WalletListenerImpl(this));
|
m_walletImpl->setListener(new WalletListenerImpl(this));
|
||||||
|
m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
|
||||||
|
// start cache timers
|
||||||
|
m_connectionStatusTime.restart();
|
||||||
|
m_daemonBlockChainHeightTime.restart();
|
||||||
|
m_daemonBlockChainTargetHeightTime.restart();
|
||||||
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet::~Wallet()
|
Wallet::~Wallet()
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ signals:
|
|||||||
// emitted when transaction is created async
|
// emitted when transaction is created async
|
||||||
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
||||||
|
|
||||||
|
void connectionStatusChanged() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Wallet(QObject * parent = nullptr);
|
Wallet(QObject * parent = nullptr);
|
||||||
Wallet(Bitmonero::Wallet *w, QObject * parent = 0);
|
Wallet(Bitmonero::Wallet *w, QObject * parent = 0);
|
||||||
@@ -221,6 +223,10 @@ private:
|
|||||||
mutable QTime m_daemonBlockChainTargetHeightTime;
|
mutable QTime m_daemonBlockChainTargetHeightTime;
|
||||||
mutable quint64 m_daemonBlockChainTargetHeight;
|
mutable quint64 m_daemonBlockChainTargetHeight;
|
||||||
int m_daemonBlockChainTargetHeightTtl;
|
int m_daemonBlockChainTargetHeightTtl;
|
||||||
|
mutable ConnectionStatus m_connectionStatus;
|
||||||
|
int m_connectionStatusTtl;
|
||||||
|
mutable QTime m_connectionStatusTime;
|
||||||
|
mutable bool m_initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user