Merge pull request #217
pull/2/head3752ec7
send page: check daemon status after every refresh (Jaquee)01549a3
walletManager: coding conventions (Jaquee)0ae3d67
daemon console -> log + adjusted height (Jaquee)0e8cd14
Wallet: add m_initialized (Jaquee)c7232e1
set wallet connection status before querying sync status (Jaquee)3f8e05d
Wallet: Cache connection status query (Jaquee)36a6b89
connect onWalletConnectionStatusChanged() (Jaquee)93a8200
Transfer: new connectionStatus handling + show status msg (Jaquee)76e6ae8
remove reference to old pw-dialog (Jaquee)18b7a67
Wallet: add connectionStatusChanged signal (Jaquee)d9f4ab4
daemonManager: wait for daemon stop on app close (Jaquee)f62bb68
daemonManagerDialog: use new ConnectionStatus enum (Jaquee)dd01f59
hide daemon sync progress after disconnecting wallet (Jaquee)8d19a03
DaemonManager: add stateChanged() (Jaquee)760e01b
daemonManagerDialog: show processdialog when starting (Jaquee)bb881d9
show processingSplash when starting/stopping daemon (Jaquee)8361dda
resolve rebase conflict (Jaquee)8dfa79e
Shutdown daemon and close wallet properly on app exit (Jaquee)7876957
DaemonManager::closing() (Jacob Brydolf)065b060
main: debug messages (Jacob Brydolf)b4eb489
DaemonManager: forward command line arguments to monerod (Jacob Brydolf)752ff26
forward command line arguments to DaemonManager (Jaquee)7840dab
DaemonManager: console debug output (Jacob Brydolf)14a5bd5
settings: added daemon console (Jacob Brydolf)b53ef00
history tx details: resized popup (Jacob Brydolf)b4f29b2
StandardDialog: changed default sizes (Jacob Brydolf)5855700
daemonManagerDialog: added starting signal (Jacob Brydolf)3a43154
DaemonManager: added console updated signals (Jacob Brydolf)3df9e44
DaemonManager: windows support (Jacob Brydolf)5da9f8f
standardDialog: close window before continue (Jacob Brydolf)5a110f4
replace message dialog with custom dialog (Jacob Brydolf)d465780
resized standard dialog (Jacob Brydolf)482bd30
settings: enable/disable daemon start/stop buttons (Jacob Brydolf)4e7de8c
proper daemon shutdown on app exit (Jaquee)48471f3
onDaemonStarted/stopped signals/slots (Jaquee)de635cb
pw dialog: close popup before continue (Jacob Brydolf)86772be
added standardDialog component (Jacob Brydolf)ae977af
settings: add daemon manager (Jacob Brydolf)2775124
small error in daemon manager dialog (Jacob Brydolf)82c39e0
WalletManager: include dependencies (Jaquee)1c6884e
Show daemon manager dialog if daemon isnt started (Jacob Brydolf)9fbfbc4
daemonManager: embed as context property (Jaquee)4cdc258
WalletManager: basic functionality (Jacob Brydolf)
commit
bfcdf113f9
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
Reference in new issue