diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/daemon/DaemonManager.cpp | 142 | ||||
| -rw-r--r-- | src/daemon/DaemonManager.h | 43 | ||||
| -rw-r--r-- | src/libwalletqt/Wallet.cpp | 21 | ||||
| -rw-r--r-- | src/libwalletqt/Wallet.h | 6 |
4 files changed, 211 insertions, 1 deletions
diff --git a/src/daemon/DaemonManager.cpp b/src/daemon/DaemonManager.cpp new file mode 100644 index 00000000..185cde1e --- /dev/null +++ b/src/daemon/DaemonManager.cpp @@ -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); + } +} diff --git a/src/daemon/DaemonManager.h b/src/daemon/DaemonManager.h new file mode 100644 index 00000000..8f425fd5 --- /dev/null +++ b/src/daemon/DaemonManager.h @@ -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 diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 9d814d82..915b4d4f 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -15,6 +15,7 @@ namespace { static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10; 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 @@ -89,7 +90,18 @@ Wallet::Status Wallet::status() 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 @@ -424,9 +436,16 @@ Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent) , m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS) , m_daemonBlockChainTargetHeight(0) , 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_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() diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 492080d4..ad4c393e 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -200,6 +200,8 @@ signals: // emitted when transaction is created async void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount); + void connectionStatusChanged() const; + private: Wallet(QObject * parent = nullptr); Wallet(Bitmonero::Wallet *w, QObject * parent = 0); @@ -221,6 +223,10 @@ private: mutable QTime m_daemonBlockChainTargetHeightTime; mutable quint64 m_daemonBlockChainTargetHeight; int m_daemonBlockChainTargetHeightTtl; + mutable ConnectionStatus m_connectionStatus; + int m_connectionStatusTtl; + mutable QTime m_connectionStatusTime; + mutable bool m_initialized; }; |
