From ef1d7f92f766f85d17427d0173e5b28f91e25ec5 Mon Sep 17 00:00:00 2001 From: Jaquee Date: Sun, 22 Jan 2017 23:04:46 +0100 Subject: [PATCH] send custom commands to daemon + status button requires #1618 --- components/DaemonConsole.qml | 148 +++++++++++++++++++++++++++++++++++ components/LineEdit.qml | 2 + pages/Settings.qml | 20 ++++- qml.qrc | 1 + src/daemon/DaemonManager.cpp | 57 ++++++++++---- src/daemon/DaemonManager.h | 3 + src/libwalletqt/Wallet.cpp | 5 ++ src/libwalletqt/Wallet.h | 4 + 8 files changed, 221 insertions(+), 19 deletions(-) create mode 100644 components/DaemonConsole.qml diff --git a/components/DaemonConsole.qml b/components/DaemonConsole.qml new file mode 100644 index 00000000..8d4f90b6 --- /dev/null +++ b/components/DaemonConsole.qml @@ -0,0 +1,148 @@ +// 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 + property alias title: dialogTitle.text + property alias text: dialogContent.text + property alias content: root.text + property alias okVisible: okButton.visible + property alias textArea: dialogContent + property var icon + + // same signals as Dialog has + signal accepted() + signal rejected() + + + function open() { + show() + } + + // TODO: implement without hardcoding sizes + width: 480 + height: 280 + + ColumnLayout { + id: mainLayout + spacing: 10 + anchors { fill: parent; margins: 35 } + + RowLayout { + id: column + //anchors {fill: parent; margins: 16 } + Layout.alignment: Qt.AlignHCenter + + Label { + id: dialogTitle + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 32 + font.family: "Arial" + color: "#555555" + } + + } + + RowLayout { + TextArea { + id : dialogContent + Layout.fillWidth: true + Layout.fillHeight: true + font.family: "Arial" + textFormat: TextEdit.AutoText + readOnly: true + font.pixelSize: 12 + } + } + + // Ok/Cancel buttons + 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("Close") + KeyNavigation.tab: cancelButton + onClicked: { + root.close() + root.accepted() + + } + } + + MoneroComponents.LineEdit { + id: sendCommandText + width: 300 + placeholderText: qsTr("command + enter (e.g help)") + onAccepted: { + if(text.length > 0) + daemonManager.sendCommand(text,currentWallet.testnet); + text = "" + } + } + + // Status button +// MoneroComponents.StandardButton { +// id: sendCommandButton +// enabled: sendCommandText.text.length > 0 +// fontSize: 14 +// shadowReleasedColor: "#FF4304" +// shadowPressedColor: "#B32D00" +// releasedColor: "#FF6C3C" +// pressedColor: "#FF4304" +// text: qsTr("Send command") +// onClicked: { +// daemonManager.sendCommand(sendCommandText.text,currentWallet.testnet); +// } +// } + } + } + +} + + + diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 49eee0b1..96954344 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -38,6 +38,7 @@ Item { property int fontSize: 18 property bool error: false signal editingFinished() + signal accepted(); height: 37 @@ -69,5 +70,6 @@ Item { anchors.rightMargin: 30 font.pixelSize: parent.fontSize onEditingFinished: item.editingFinished() + onAccepted: item.accepted(); } } diff --git a/pages/Settings.qml b/pages/Settings.qml index 0027e0da..e6088722 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -241,6 +241,23 @@ Rectangle { daemonConsolePopup.open(); } } + + StandardButton { + visible: true + id: daemonStatusButton + text: qsTr("Status") + translationManager.emptyString + shadowReleasedColor: "#FF4304" + shadowPressedColor: "#B32D00" + releasedColor: "#FF6C3C" + pressedColor: "#FF4304" + onClicked: { + daemonManager.sendCommand("status",currentWallet.testnet); + daemonConsolePopup.open(); + } + } + + + } RowLayout { @@ -416,11 +433,10 @@ Rectangle { } // Daemon console - StandardDialog { + DaemonConsole { id: daemonConsolePopup height:500 width:800 - cancelVisible: false title: qsTr("Daemon log") onAccepted: { close(); diff --git a/qml.qrc b/qml.qrc index a4a76ce5..630826d9 100644 --- a/qml.qrc +++ b/qml.qrc @@ -124,5 +124,6 @@ version.js wizard/WizardPasswordUI.qml wizard/WizardCreateViewOnlyWallet.qml + components/DaemonConsole.qml diff --git a/src/daemon/DaemonManager.cpp b/src/daemon/DaemonManager.cpp index e85db709..5298743a 100644 --- a/src/daemon/DaemonManager.cpp +++ b/src/daemon/DaemonManager.cpp @@ -25,20 +25,6 @@ DaemonManager *DaemonManager::instance(const QStringList *args) bool DaemonManager::start(const QString &flags) { - // - 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) { @@ -55,8 +41,8 @@ bool DaemonManager::start(const QString &flags) } - qDebug() << "starting monerod " + process; - qDebug() << "With command line arguments " << arguments; + qDebug() << "starting monerod " + m_monerod; + qDebug() << "With command line arguments " << m_monerod; m_daemon = new QProcess(); initialized = true; @@ -66,7 +52,7 @@ bool DaemonManager::start(const QString &flags) connect (m_daemon, SIGNAL(readyReadStandardError()), this, SLOT(printError())); // Start monerod - m_daemon->start(process,arguments); + m_daemon->start(m_monerod, arguments); bool started = m_daemon->waitForStarted(); // add state changed listener @@ -134,10 +120,47 @@ bool DaemonManager::running() const 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"); + return true; + } + + // else send external command + QProcess p; + QString external_cmd = m_monerod + " " + cmd; + + // Add nestnet 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); + + return started; +} + DaemonManager::DaemonManager(QObject *parent) : QObject(parent) { + // Platform depetent path to monerod +#ifdef Q_OS_WIN + m_monerod = QApplication::applicationDirPath() + "/monerod.exe"; +#elif defined(Q_OS_UNIX) + m_monerod = QApplication::applicationDirPath() + "/monerod"; +#endif + + if (m_monerod.length() == 0) { + qCritical() << "no daemon binary defined for current platform"; + m_has_daemon = false; + } } void DaemonManager::closing() diff --git a/src/daemon/DaemonManager.h b/src/daemon/DaemonManager.h index 7c9730e8..2a2b38df 100644 --- a/src/daemon/DaemonManager.h +++ b/src/daemon/DaemonManager.h @@ -18,6 +18,7 @@ public: // return true if daemon process is started Q_INVOKABLE bool running() const; + Q_INVOKABLE bool sendCommand(const QString &cmd, bool testnet); signals: void daemonStarted(); @@ -37,6 +38,8 @@ private: static QStringList m_clArgs; QProcess *m_daemon; bool initialized = false; + QString m_monerod; + bool m_has_daemon = true; }; diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 6147e1cb..2ade69bb 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -98,6 +98,11 @@ Wallet::Status Wallet::status() const return static_cast(m_walletImpl->status()); } +bool Wallet::testnet() const +{ + return m_walletImpl->testnet(); +} + Wallet::ConnectionStatus Wallet::connected() const { // cache connection status diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 2fb0ba6e..9aec45fc 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -25,6 +25,7 @@ class Wallet : public QObject Q_PROPERTY(QString seed READ getSeed) 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(bool synchronized READ synchronized) Q_PROPERTY(QString errorString READ errorString) @@ -70,6 +71,9 @@ public: //! returns last operation's status Status status() const; + //! returns true testnet wallet. + bool testnet() const; + //! returns whether the wallet is connected, and version status ConnectionStatus connected() const;