start daemon automatically and detached

This commit is contained in:
Jaquee 2017-02-23 19:47:58 +01:00
parent c6688dc876
commit faacd3d6a1
No known key found for this signature in database
GPG key ID: 384E52B09F45DC39
11 changed files with 104 additions and 115 deletions

View file

@ -39,12 +39,14 @@ Window {
id: root
modality: Qt.ApplicationModal
flags: Qt.Window | Qt.FramelessWindowHint
property int countDown: 5;
signal rejected()
signal started();
function open() {
show()
countDown = 5;
timer.start();
}
// TODO: implement without hardcoding sizes
@ -61,15 +63,29 @@ Window {
//anchors {fill: parent; margins: 16 }
Layout.alignment: Qt.AlignHCenter
Label {
text: qsTr("Daemon doesn't appear to be running")
Timer {
id: timer
interval: 1000;
running: false;
repeat: true
onTriggered: {
countDown--;
if(countDown < 0){
running = false;
// Start daemon
root.close()
appWindow.startDaemon(persistentSettings.daemonFlags);
root.started();
}
}
}
Text {
text: qsTr("Starting Monero daemon in %1 seconds").arg(countDown);
font.pixelSize: 18
Layout.alignment: Qt.AlignHCenter
Layout.columnSpan: 2
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 24
font.family: "Arial"
color: "#555555"
}
}
@ -81,57 +97,39 @@ Window {
MoneroComponents.StandardButton {
id: okButton
width: 120
visible:false
fontSize: 14
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Start daemon")
text: qsTr("Start daemon (%1)").arg(countDown)
KeyNavigation.tab: cancelButton
onClicked: {
timer.stop();
root.close()
appWindow.startDaemon(daemonFlags.text);
appWindow.startDaemon(persistentSettings.daemonFlags);
root.started()
}
}
MoneroComponents.StandardButton {
id: cancelButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Cancel")
text: qsTr("Use custom settings")
onClicked: {
timer.stop();
root.close()
root.rejected()
}
}
}
RowLayout {
id: advancedRow
MoneroComponents.Label {
id: daemonFlagsLabel
color: "#4A4949"
text: qsTr("Daemon startup flags") + translationManager.emptyString
fontSize: 16
}
MoneroComponents.LineEdit {
id: daemonFlags
Layout.preferredWidth: 200
Layout.fillWidth: true
text: appWindow.persistentSettings.daemonFlags;
placeholderText: qsTr("(optional)")
}
}
}
}

View file

@ -61,7 +61,7 @@ Window {
id: messageTitle
text: "Please wait..."
font {
pointSize: 22
pixelSize: 22
}
horizontalAlignment: Text.AlignHCenter
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
@ -72,7 +72,7 @@ Window {
Text {
id: heightProgress
font {
pointSize: 18
pixelSize: 18
}
horizontalAlignment: Text.AlignHCenter
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter

View file

@ -64,6 +64,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
int main(int argc, char *argv[])
{
Monero::Wallet::init(argv[0], "monero-wallet-gui");
qInstallMessageHandler(messageHandler);
QApplication app(argc, argv);
@ -141,7 +142,6 @@ int main(int argc, char *argv[])
// Exclude daemon manager from IOS
#ifndef Q_OS_IOS
DaemonManager * daemonManager = DaemonManager::instance(&arguments);
QObject::connect(&app, SIGNAL(aboutToQuit()), daemonManager, SLOT(closing()));
engine.rootContext()->setContextProperty("daemonManager", daemonManager);
#endif

View file

@ -147,6 +147,11 @@ ApplicationWindow {
function mousePressed(obj, mouseX, mouseY) {}
function mouseReleased(obj, mouseX, mouseY) {}
function loadPage(page) {
middlePanel.state = page;
leftPanel.selectItem(page);
}
function openWalletFromFile(){
persistentSettings.restore_height = 0
restoreHeight = 0;
@ -274,7 +279,7 @@ ApplicationWindow {
leftPanel.progressBar.visible = (status === Wallet.ConnectionStatus_Connected) && !daemonSynced
// If wallet isnt connected and no daemon is running - Ask
if(!walletInitialized && status === Wallet.ConnectionStatus_Disconnected && !daemonManager.running()){
if(!walletInitialized && status === Wallet.ConnectionStatus_Disconnected && !daemonManager.running(persistentSettings.testnet)){
daemonManagerDialog.open();
}
// initialize transaction history once wallet is initialized first time;
@ -341,7 +346,7 @@ ApplicationWindow {
}
// Daemon connected
leftPanel.networkStatus.connected = currentWallet.connected
leftPanel.networkStatus.connected = currentWallet.connected()
// Check daemon status
var dCurrentBlock = currentWallet.daemonBlockChainHeight();
@ -352,9 +357,9 @@ ApplicationWindow {
daemonSynced = dCurrentBlock >= dTargetBlock
// Update daemon sync progress
leftPanel.progressBar.updateProgress(dCurrentBlock,dTargetBlock);
leftPanel.progressBar.visible = !daemonSynced && currentWallet.connected !== Wallet.ConnectionStatus_Disconnected
leftPanel.progressBar.visible = !daemonSynced && currentWallet.connected() !== Wallet.ConnectionStatus_Disconnected
// Update wallet sync progress
updateSyncing((currentWallet.connected !== Wallet.ConnectionStatus_Disconnected) && !daemonSynced)
updateSyncing((currentWallet.connected() !== Wallet.ConnectionStatus_Disconnected) && !daemonSynced)
// Update transfer page status
middlePanel.updateStatus();
@ -380,23 +385,25 @@ ApplicationWindow {
function startDaemon(flags){
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
daemonManager.start(flags);
daemonManager.start(flags, persistentSettings.testnet);
persistentSettings.daemonFlags = flags
}
function stopDaemon(){
appWindow.showProcessingSplash(qsTr("Waiting for daemon to stop..."))
daemonManager.stop();
daemonManager.stop(persistentSettings.testnet);
}
function onDaemonStarted(){
console.log("daemon started");
daemonRunning = true;
hideProcessingSplash();
}
function onDaemonStopped(){
console.log("daemon stopped");
hideProcessingSplash();
daemonRunning = false;
currentWallet.connected(true);
}
function onWalletNewBlock(blockHeight, targetHeight) {
@ -438,7 +445,7 @@ ApplicationWindow {
if (transaction.status !== PendingTransaction.Status_Ok) {
console.error("Can't create transaction: ", transaction.errorString);
informationPopup.title = qsTr("Error") + translationManager.emptyString;
if (currentWallet.connected == Wallet.ConnectionStatus_WrongVersion)
if (currentWallet.connected() == Wallet.ConnectionStatus_WrongVersion)
informationPopup.text = qsTr("Can't create transaction: Wrong daemon version: ") + transaction.errorString
else
informationPopup.text = qsTr("Can't create transaction: ") + transaction.errorString
@ -870,6 +877,9 @@ ApplicationWindow {
DaemonManagerDialog {
id: daemonManagerDialog
onRejected: {
loadPage("Settings");
}
}
@ -1220,7 +1230,5 @@ ApplicationWindow {
onClosing: {
// Close wallet non async on exit
walletManager.closeWallet();
// Stop daemon and pool miner
daemonManager.stop();
}
}

View file

@ -96,7 +96,7 @@ Rectangle {
setTrackingLineText("-")
return
}
if (appWindow.currentWallet.connected == Wallet.ConnectionStatus_Disconnected) {
if (appWindow.currentWallet.connected() == Wallet.ConnectionStatus_Disconnected) {
setTrackingLineText(qsTr("WARNING: no connection to daemon"))
return
}

View file

@ -171,23 +171,10 @@ Rectangle {
}
}
StandardButton {
visible: true
id: daemonConsolePopupButton
text: qsTr("Show log") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
onClicked: {
daemonConsolePopup.open();
}
}
StandardButton {
visible: true
id: daemonStatusButton
text: qsTr("Status") + translationManager.emptyString
text: qsTr("Show status") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
@ -420,6 +407,7 @@ Rectangle {
console.log("Settings page loaded");
initSettings();
viewOnly = currentWallet.viewOnly;
daemonManager.running(persistentSettings.testnet)
}
// fires only once

View file

@ -700,7 +700,7 @@ Rectangle {
}
pageRoot.enabled = false;
switch (currentWallet.connected) {
switch (currentWallet.connected()) {
case Wallet.ConnectionStatus_Disconnected:
statusText.text = qsTr("Wallet is not connected to daemon.") + "<br>" + root.startLinkText
break

View file

@ -23,10 +23,14 @@ DaemonManager *DaemonManager::instance(const QStringList *args)
return m_instance;
}
bool DaemonManager::start(const QString &flags)
bool DaemonManager::start(const QString &flags, bool testnet)
{
// prepare command line arguments and pass to monerod
QStringList arguments;
arguments << "--detach";
if(testnet)
arguments << "--testnet";
foreach (const QString &str, m_clArgs) {
qDebug() << QString(" [%1] ").arg(str);
if (!str.isEmpty())
@ -52,8 +56,7 @@ bool DaemonManager::start(const QString &flags)
connect (m_daemon, SIGNAL(readyReadStandardError()), this, SLOT(printError()));
// Start monerod
m_daemon->start(m_monerod, arguments);
bool started = m_daemon->waitForStarted();
bool started = m_daemon->startDetached(m_monerod, arguments);
// add state changed listener
connect(m_daemon,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(stateChanged(QProcess::ProcessState)));
@ -67,16 +70,14 @@ bool DaemonManager::start(const QString &flags)
return started;
}
bool DaemonManager::stop()
bool DaemonManager::stop(bool testnet)
{
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;
QString message;
bool stopped = sendCommand("exit",testnet,message);
qDebug() << message;
if(stopped)
emit daemonStopped();
return stopped;
}
void DaemonManager::stateChanged(QProcess::ProcessState state)
@ -109,40 +110,42 @@ void DaemonManager::printError()
}
}
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;
}
bool DaemonManager::sendCommand(const QString &cmd,bool testnet)
{
// If daemon is started by GUI - interactive mode
if (initialized && running()) {
m_daemon->write(cmd.toUtf8() +"\n");
bool DaemonManager::running(bool testnet) const
{
QString status;
sendCommand("status",testnet, status);
qDebug() << status;
// `./monerod status` returns BUSY when syncing.
// Treat busy as connected, until fixed upstream.
if (status.contains("Height:") || status.contains("BUSY") ) {
emit daemonStarted();
return true;
}
emit daemonStopped();
return false;
}
bool DaemonManager::sendCommand(const QString &cmd,bool testnet) const
{
QString message;
return sendCommand(cmd, testnet, message);
}
// else send external command
bool DaemonManager::sendCommand(const QString &cmd,bool testnet, QString &message) const
{
QProcess p;
QString external_cmd = m_monerod + " " + cmd;
qDebug() << "sending external cmd: " << external_cmd;
// Add nestnet flag if needed
// Add testnet flag if needed
if (testnet)
external_cmd += " --testnet";
external_cmd += "\n";
p.start(external_cmd);
bool started = p.waitForFinished(-1);
QString p_stdout = p.readAllStandardOutput();
qDebug() << p_stdout;
emit daemonConsoleUpdated(p_stdout);
bool started = p.waitForFinished(-1);
message = p.readAllStandardOutput();
emit daemonConsoleUpdated(message);
return started;
}
@ -162,13 +165,3 @@ DaemonManager::DaemonManager(QObject *parent)
m_has_daemon = false;
}
}
void DaemonManager::closing()
{
qDebug() << __FUNCTION__;
stop();
// Wait for daemon to stop before exiting (max 10 secs)
if (initialized) {
m_daemon->waitForFinished(10000);
}
}

View file

@ -13,26 +13,27 @@ public:
static DaemonManager * instance(const QStringList *args);
Q_INVOKABLE bool start(const QString &flags);
Q_INVOKABLE bool stop();
Q_INVOKABLE bool start(const QString &flags, bool testnet);
Q_INVOKABLE bool stop(bool testnet);
// return true if daemon process is started
Q_INVOKABLE bool running() const;
Q_INVOKABLE bool sendCommand(const QString &cmd, bool testnet);
Q_INVOKABLE bool running(bool testnet) const;
// Send daemon command from qml and prints output in console window.
Q_INVOKABLE bool sendCommand(const QString &cmd, bool testnet) const;
private:
bool sendCommand(const QString &cmd, bool testnet, QString &message) const;
signals:
void daemonStarted();
void daemonStopped();
void daemonConsoleUpdated(QString message);
void daemonStarted() const;
void daemonStopped() const;
void daemonConsoleUpdated(QString message) const;
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;

View file

@ -20,7 +20,7 @@
#include <QMutexLocker>
namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 10;
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 60;
static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
}
@ -118,6 +118,7 @@ void Wallet::updateConnectionStatusAsync()
if (newStatus != m_connectionStatus || !m_initialized) {
m_initialized = true;
m_connectionStatus = newStatus;
qDebug() << "NEW STATUS " << newStatus;
emit connectionStatusChanged(newStatus);
}
// Release lock

View file

@ -28,7 +28,7 @@ class Wallet : public QObject
Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status)
Q_PROPERTY(bool testnet READ testnet)
Q_PROPERTY(ConnectionStatus connected READ connected)
// Q_PROPERTY(ConnectionStatus connected READ connected)
Q_PROPERTY(bool synchronized READ synchronized)
Q_PROPERTY(QString errorString READ errorString)
Q_PROPERTY(QString address READ address)
@ -77,7 +77,7 @@ public:
bool testnet() const;
//! returns whether the wallet is connected, and version status
ConnectionStatus connected(bool forceCheck = false);
Q_INVOKABLE ConnectionStatus connected(bool forceCheck = false);
void updateConnectionStatusAsync();
//! returns true if wallet was ever synchronized