1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-10-31 15:07:12 -04:00

Commands: implemented run and output GUI

This commit is contained in:
f4exb 2018-01-04 20:15:33 +01:00
parent 89f98f504a
commit 069d9a7d07
14 changed files with 807 additions and 9 deletions

BIN
doc/img/kill.xcf Normal file

Binary file not shown.

View File

@ -18,12 +18,51 @@
#include "util/simpleserializer.h" #include "util/simpleserializer.h"
#include <QKeySequence> #include <QKeySequence>
#include <QProcess>
Command::Command() Command::Command() :
m_currentProcess(0),
m_currentProcessState(QProcess::NotRunning),
m_isInError(false),
m_currentProcessError(QProcess::UnknownError),
m_isFinished(true),
m_currentProcessExitCode(0),
m_currentProcessExitStatus(QProcess::NormalExit),
m_currentProcessPid(0)
{ {
m_currentProcessStartTimeStamp.tv_sec = 0;
m_currentProcessStartTimeStamp.tv_usec = 0;
m_currentProcessFinishTimeStamp.tv_sec = 0;
m_currentProcessFinishTimeStamp.tv_usec = 0;
resetToDefaults(); resetToDefaults();
} }
Command::Command(const Command& command) :
QObject(),
m_group(command.m_group),
m_description(command.m_description),
m_command(command.m_command),
m_argString(command.m_argString),
m_key(command.m_key),
m_keyModifiers(command.m_keyModifiers),
m_associateKey(command.m_associateKey),
m_release(command.m_release),
m_currentProcess(0),
m_currentProcessState(QProcess::NotRunning),
m_isInError(false),
m_currentProcessError(QProcess::UnknownError),
m_isFinished(true),
m_currentProcessExitCode(0),
m_currentProcessExitStatus(QProcess::NormalExit),
m_currentProcessPid(0)
{
m_currentProcessStartTimeStamp.tv_sec = 0;
m_currentProcessStartTimeStamp.tv_usec = 0;
m_currentProcessFinishTimeStamp.tv_sec = 0;
m_currentProcessFinishTimeStamp.tv_usec = 0;
}
Command::~Command() Command::~Command()
{} {}
@ -34,6 +73,7 @@ void Command::resetToDefaults()
m_command = ""; m_command = "";
m_argString = ""; m_argString = "";
m_key = static_cast<Qt::Key>(0); m_key = static_cast<Qt::Key>(0);
m_keyModifiers = Qt::NoModifier,
m_associateKey = false; m_associateKey = false;
m_release = false; m_release = false;
} }
@ -106,3 +146,150 @@ QString Command::getKeyLabel() const
return QKeySequence(m_key).toString(); return QKeySequence(m_key).toString();
} }
} }
void Command::run(const QString& apiAddress, int apiPort, int deviceSetIndex)
{
if (m_currentProcess)
{
qWarning("Command::run: process already running");
return;
}
QString args = m_argString;
if (m_argString.contains("%1"))
{
args = args.arg(apiAddress);
}
if (m_argString.contains("%2"))
{
args.replace("%2", "%1");
args = args.arg(apiPort);
}
if (m_argString.contains("%3"))
{
args.replace("%3", "%1");
args = args.arg(deviceSetIndex);
}
m_currentProcessCommandLine = QString("%1 %2").arg(m_command).arg(args);
qDebug("Command::run: %s", qPrintable(m_currentProcessCommandLine));
m_currentProcess = new QProcess(this);
m_isInError = false;
m_isFinished = false;
#if QT_VERSION < 0x051000
connect(m_currentProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#else
connect(m_currentProcess, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#endif
connect(m_currentProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
connect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState)));
m_currentProcess->setProcessChannelMode(QProcess::MergedChannels);
gettimeofday(&m_currentProcessStartTimeStamp, 0);
m_currentProcess->start(m_currentProcessCommandLine);
}
void Command::kill()
{
if (m_currentProcess)
{
qDebug("Command::kill: %lld", m_currentProcessPid);
m_currentProcess->kill();
#if QT_VERSION < 0x051000
disconnect(m_currentProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#else
disconnect(m_currentProcess, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#endif
disconnect(m_currentProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
disconnect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState)));
delete m_currentProcess;
m_currentProcess = 0;
}
}
QProcess::ProcessState Command::getLastProcessState() const
{
return m_currentProcessState;
}
bool Command::getLastProcessError(QProcess::ProcessError& error) const
{
if (m_isInError) {
error = m_currentProcessError;
}
return m_isInError;
}
bool Command::getLastProcessTermination(int& exitCode, QProcess::ExitStatus& exitStatus) const
{
if (m_isFinished)
{
exitCode = m_currentProcessExitCode;
exitStatus = m_currentProcessExitStatus;
}
return m_isFinished;
}
const QString& Command::getLastProcessLog() const
{
return m_log;
}
void Command::processStateChanged(QProcess::ProcessState newState)
{
if (newState == QProcess::Running) {
m_currentProcessPid = m_currentProcess->processId();
}
m_currentProcessState = newState;
}
void Command::processError(QProcess::ProcessError error)
{
gettimeofday(&m_currentProcessFinishTimeStamp, 0);
m_currentProcessError = error;
m_isInError = true;
m_isFinished = true;
m_log = m_currentProcess->readAllStandardOutput();
#if QT_VERSION < 0x051000
disconnect(m_currentProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#else
disconnect(m_currentProcess, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#endif
disconnect(m_currentProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
disconnect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState)));
delete m_currentProcess;
m_currentProcess = 0;
}
void Command::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
gettimeofday(&m_currentProcessFinishTimeStamp, 0);
m_currentProcessExitCode = exitCode;
m_currentProcessExitStatus = exitStatus;
m_isInError = false;
m_isFinished = true;
m_log = m_currentProcess->readAllStandardOutput();
#if QT_VERSION < 0x051000
disconnect(m_currentProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#else
disconnect(m_currentProcess, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
#endif
disconnect(m_currentProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
disconnect(m_currentProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState)));
delete m_currentProcess;
m_currentProcess = 0;
}

View File

@ -21,11 +21,16 @@
#include <QByteArray> #include <QByteArray>
#include <QString> #include <QString>
#include <QMetaType> #include <QMetaType>
#include <QObject>
#include <QProcess>
#include <sys/time.h>
class Command class Command : public QObject
{ {
Q_OBJECT
public: public:
Command(); Command();
Command(const Command& command);
~Command(); ~Command();
void resetToDefaults(); void resetToDefaults();
@ -48,9 +53,19 @@ public:
bool getAssociateKey() const { return m_associateKey; } bool getAssociateKey() const { return m_associateKey; }
void setRelease(bool release) { m_release = release; } void setRelease(bool release) { m_release = release; }
bool getRelease() const { return m_release; } bool getRelease() const { return m_release; }
QString getKeyLabel() const; QString getKeyLabel() const;
void run(const QString& apiAddress, int apiPort, int deviceSetIndex);
void kill();
QProcess::ProcessState getLastProcessState() const;
bool getLastProcessError(QProcess::ProcessError& error) const;
bool getLastProcessTermination(int& exitCode, QProcess::ExitStatus& exitStatus) const;
const QString& getLastProcessLog() const;
struct timeval getLastProcessStartTimestamp() const { return m_currentProcessStartTimeStamp; }
struct timeval getLastProcessFinishTimestamp() const { return m_currentProcessFinishTimeStamp; }
const QString& getLastProcessCommandLine() const { return m_currentProcessCommandLine; }
qint64 getLastProcessPid() const { return m_currentProcessPid; }
static bool commandCompare(const Command *c1, Command *c2) static bool commandCompare(const Command *c1, Command *c2)
{ {
if (c1->m_group != c2->m_group) if (c1->m_group != c2->m_group)
@ -74,14 +89,31 @@ public:
} }
private: private:
QString m_command;
QString m_argString;
QString m_group; QString m_group;
QString m_description; QString m_description;
QString m_command;
QString m_argString;
Qt::Key m_key; Qt::Key m_key;
Qt::KeyboardModifiers m_keyModifiers; Qt::KeyboardModifiers m_keyModifiers;
bool m_associateKey; bool m_associateKey;
bool m_release; bool m_release;
QProcess *m_currentProcess;
QProcess::ProcessState m_currentProcessState;
bool m_isInError;
QProcess::ProcessError m_currentProcessError;
bool m_isFinished;
int m_currentProcessExitCode;
QProcess::ExitStatus m_currentProcessExitStatus;
QString m_log;
struct timeval m_currentProcessStartTimeStamp;
struct timeval m_currentProcessFinishTimeStamp;
QString m_currentProcessCommandLine;
qint64 m_currentProcessPid;
private slots:
void processStateChanged(QProcess::ProcessState newState);
void processError(QProcess::ProcessError error);
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
}; };
Q_DECLARE_METATYPE(const Command*); Q_DECLARE_METATYPE(const Command*);

View File

@ -10,6 +10,7 @@ set(sdrgui_SOURCES
gui/clickablelabel.cpp gui/clickablelabel.cpp
gui/colormapper.cpp gui/colormapper.cpp
gui/commanditem.cpp gui/commanditem.cpp
gui/commandoutputdialog.cpp
gui/cwkeyergui.cpp gui/cwkeyergui.cpp
gui/editcommanddialog.cpp gui/editcommanddialog.cpp
gui/externalclockbutton.cpp gui/externalclockbutton.cpp
@ -63,6 +64,7 @@ set(sdrgui_HEADERS
gui/channelwindow.h gui/channelwindow.h
gui/colormapper.h gui/colormapper.h
gui/commanditem.h gui/commanditem.h
gui/commandoutputdialog.h
gui/cwkeyergui.h gui/cwkeyergui.h
gui/editcommanddialog.h gui/editcommanddialog.h
gui/externalclockbutton.h gui/externalclockbutton.h
@ -118,6 +120,7 @@ set(sdrgui_FORMS
gui/aboutdialog.ui gui/aboutdialog.ui
gui/addpresetdialog.ui gui/addpresetdialog.ui
gui/basicchannelsettingsdialog.ui gui/basicchannelsettingsdialog.ui
gui/commandoutputdialog.ui
gui/cwkeyergui.ui gui/cwkeyergui.ui
gui/editcommanddialog.ui gui/editcommanddialog.ui
gui/externalclockdialog.ui gui/externalclockdialog.ui

View File

@ -0,0 +1,160 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "commandoutputdialog.h"
#include "ui_commandoutputdialog.h"
#include "commands/command.h"
#include <QDateTime>
CommandOutputDialog::CommandOutputDialog(Command& command, QWidget* parent) :
QDialog(parent),
ui(new Ui::CommandOutputDialog),
m_command(command)
{
ui->setupUi(this);
refresh();
}
CommandOutputDialog::~CommandOutputDialog()
{
delete ui;
}
void CommandOutputDialog::refresh()
{
ui->commandText->setText(m_command.getLastProcessCommandLine());
ui->processPid->setText(QString("%1").arg(m_command.getLastProcessPid()));
if (m_command.getLastProcessStartTimestamp().tv_sec == 0) {
ui->startTime->setText(("..."));
}
else
{
struct timeval tv = m_command.getLastProcessStartTimestamp();
QDateTime dt = QDateTime::fromMSecsSinceEpoch(tv.tv_sec * 1000LL + tv.tv_usec / 1000LL);
QString dateStr = dt.toString("yyyy-MM-dd hh:mm:ss.zzz");
ui->startTime->setText(dateStr);
}
if (m_command.getLastProcessFinishTimestamp().tv_sec == 0) {
ui->endTime->setText(("..."));
}
else
{
struct timeval tv = m_command.getLastProcessFinishTimestamp();
QDateTime dt = QDateTime::fromMSecsSinceEpoch(tv.tv_sec * 1000LL + tv.tv_usec / 1000LL);
QString dateStr = dt.toString("yyyy-MM-dd hh:mm:ss.zzz");
ui->endTime->setText(dateStr);
}
ui->runningState->setChecked(m_command.getLastProcessState() == QProcess::Running);
QProcess::ProcessError processError;
if (m_command.getLastProcessStartTimestamp().tv_sec == 0)
{
ui->errorText->setText("...");
ui->exitCode->setText("-");
ui->exitText->setText("...");
ui->runningState->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
else if (m_command.getLastProcessState() != QProcess::NotRunning)
{
ui->errorText->setText("...");
ui->runningState->setStyleSheet("QToolButton { background-color : blue; }");
}
else if (m_command.getLastProcessError(processError))
{
ui->runningState->setStyleSheet("QToolButton { background-color : red; }");
setErrorText(processError);
ui->exitCode->setText("-");
ui->exitText->setText("...");
}
else
{
ui->runningState->setStyleSheet("QToolButton { background-color : green; }");
ui->errorText->setText("No error");
int processExitCode;
QProcess::ExitStatus processExitStatus;
if (m_command.getLastProcessTermination(processExitCode, processExitStatus))
{
ui->exitCode->setText(QString("%1").arg(processExitCode));
setExitText(processExitStatus);
}
else
{
ui->exitCode->setText("-");
ui->exitText->setText("...");
}
}
ui->logEdit->setPlainText(m_command.getLastProcessLog());
}
void CommandOutputDialog::setErrorText(const QProcess::ProcessError& processError)
{
switch(processError)
{
case QProcess::FailedToStart:
ui->errorText->setText("Failed to start");
break;
case QProcess::Crashed:
ui->errorText->setText("Crashed");
break;
case QProcess::Timedout:
ui->errorText->setText("Timed out");
break;
case QProcess::WriteError:
ui->errorText->setText("Write error");
break;
case QProcess::ReadError:
ui->errorText->setText("Read error");
break;
case QProcess::UnknownError:
default:
ui->errorText->setText("Unknown error");
break;
}
}
void CommandOutputDialog::setExitText(const QProcess::ExitStatus& processExit)
{
switch(processExit)
{
case QProcess::NormalExit:
ui->exitText->setText("Normal exit");
break;
case QProcess::CrashExit:
ui->exitText->setText("Program crashed");
break;
default:
ui->exitText->setText("Unknown state");
break;
}
}
void CommandOutputDialog::on_processRefresh_toggled(bool checked __attribute__((unused)))
{
refresh();
}
void CommandOutputDialog::on_processKill_toggled(bool checked __attribute__((unused)))
{
m_command.kill();
}

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRGUI_GUI_COMMANDOUTPUTDIALOG_H_
#define SDRGUI_GUI_COMMANDOUTPUTDIALOG_H_
#include <QDialog>
#include <QProcess>
namespace Ui {
class CommandOutputDialog;
}
class Command;
class CommandOutputDialog : public QDialog {
Q_OBJECT
public:
explicit CommandOutputDialog(Command& command, QWidget* parent = 0);
~CommandOutputDialog();
void fromCommand(const Command& command);
private:
Ui::CommandOutputDialog* ui;
Command& m_command;
void refresh();
void setErrorText(const QProcess::ProcessError& processError);
void setExitText(const QProcess::ExitStatus& processExit);
private slots:
void on_processRefresh_toggled(bool checked);
void on_processKill_toggled(bool checked);
};
#endif /* SDRGUI_GUI_COMMANDOUTPUTDIALOG_H_ */

View File

@ -0,0 +1,332 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CommandOutputDialog</class>
<widget class="QDialog" name="CommandOutputDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>380</height>
</rect>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Command output</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="processLayout">
<item>
<widget class="QToolButton" name="runningState">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Running state icon</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/stop.png</normaloff>
<normalon>:/play.png</normalon>:/stop.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="processRefresh">
<property name="toolTip">
<string>Refresh data</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="startTime">
<property name="minimumSize">
<size>
<width>146</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>Start time of last execution</string>
</property>
<property name="text">
<string>2015-01-01 00:00:00.000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="timeMidLabel">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="endTime">
<property name="minimumSize">
<size>
<width>146</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>End time of last execution</string>
</property>
<property name="text">
<string>2015-01-01 00:00:00.000</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="processPid">
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>Process PID</string>
</property>
<property name="text">
<string>00000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="processKill">
<property name="toolTip">
<string>Kill the process (SIGKILL)</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/kill.png</normaloff>:/kill.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="commandLayout">
<item>
<widget class="QLabel" name="commandLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Cmd:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="commandText">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Command that was executed</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="errorExitLayout">
<item>
<widget class="QLabel" name="errorLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Error:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="errorText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Process error status</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="exitLabel">
<property name="minimumSize">
<size>
<width>30</width>
<height>23</height>
</size>
</property>
<property name="text">
<string>Exit:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="exitCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Return code</string>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="exitText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Process exit status</string>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="logEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Output log (stdout + stderr)</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="../resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CommandOutputDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>203</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CommandOutputDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>314</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>203</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -140,7 +140,7 @@ void EditCommandDialog::on_showFileDialog_clicked(bool checked __attribute__((un
this, this,
tr("Select command"), tr("Select command"),
dirStr, dirStr,
tr("Python (*.py);;Shell (*.sh *.bat);;Binary (*.bin *.exe);;All (*.*)")); tr("Python (*.py);;Shell (*.sh *.bat);;Binary (*.bin *.exe);;All (*)"));
if (fileName != "") { if (fileName != "") {
ui->command->setText(fileName); ui->command->setText(fileName);
@ -249,4 +249,3 @@ void EditCommandDialog::setKeyAssociate()
ui->keyAssociate->setEnabled(true); ui->keyAssociate->setEnabled(true);
} }
} }

View File

@ -37,6 +37,7 @@
#include "gui/commanditem.h" #include "gui/commanditem.h"
#include "gui/addpresetdialog.h" #include "gui/addpresetdialog.h"
#include "gui/editcommanddialog.h" #include "gui/editcommanddialog.h"
#include "gui/commandoutputdialog.h"
#include "gui/pluginsdialog.h" #include "gui/pluginsdialog.h"
#include "gui/aboutdialog.h" #include "gui/aboutdialog.h"
#include "gui/rollupwidget.h" #include "gui/rollupwidget.h"
@ -934,6 +935,32 @@ void MainWindow::on_commandDelete_clicked()
} }
} }
void MainWindow::on_commandRun_clicked()
{
QTreeWidgetItem* item = ui->commandTree->currentItem();
if ((item != 0) && (item->type() == PItem))
{
const Command* command = qvariant_cast<const Command*>(item->data(0, Qt::UserRole));
Command* command_mod = const_cast<Command*>(command);
int currentDeviceSetIndex = ui->tabInputsSelect->currentIndex();
command_mod->run(m_apiServer->getHost(), m_apiServer->getPort(), currentDeviceSetIndex);
}
}
void MainWindow::on_commandOutput_clicked()
{
QTreeWidgetItem* item = ui->commandTree->currentItem();
if ((item != 0) && (item->type() == PItem))
{
const Command* command = qvariant_cast<const Command*>(item->data(0, Qt::UserRole));
Command* command_mod = const_cast<Command*>(command);
CommandOutputDialog commandOutputDialog(*command_mod);
commandOutputDialog.exec();
}
}
void MainWindow::on_presetSave_clicked() void MainWindow::on_presetSave_clicked()
{ {
QStringList groups; QStringList groups;

View File

@ -348,6 +348,8 @@ private slots:
void on_commandDuplicate_clicked(); void on_commandDuplicate_clicked();
void on_commandEdit_clicked(); void on_commandEdit_clicked();
void on_commandDelete_clicked(); void on_commandDelete_clicked();
void on_commandRun_clicked();
void on_commandOutput_clicked();
void on_action_Audio_triggered(); void on_action_Audio_triggered();
void on_action_Logging_triggered(); void on_action_Logging_triggered();
void on_action_DV_Serial_triggered(bool checked); void on_action_DV_Serial_triggered(bool checked);

View File

@ -672,9 +672,9 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QToolButton" name="commandViewOutput"> <widget class="QToolButton" name="commandOutput">
<property name="toolTip"> <property name="toolTip">
<string>View last run output</string> <string>View last run status and output</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>

BIN
sdrgui/resources/kill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

View File

@ -90,5 +90,6 @@
<file>save.png</file> <file>save.png</file>
<file>load.png</file> <file>load.png</file>
<file>keyboard.png</file> <file>keyboard.png</file>
<file>kill.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -51,6 +51,7 @@ SOURCES += mainwindow.cpp\
gui/clickablelabel.cpp\ gui/clickablelabel.cpp\
gui/colormapper.cpp\ gui/colormapper.cpp\
gui/commanditem.cpp\ gui/commanditem.cpp\
gui/commandoutputdialog.cpp\
gui/cwkeyergui.cpp\ gui/cwkeyergui.cpp\
gui/editcommanddialog.cpp\ gui/editcommanddialog.cpp\
gui/externalclockbutton.cpp\ gui/externalclockbutton.cpp\
@ -100,6 +101,7 @@ HEADERS += mainwindow.h\
gui/clickablelabel.h\ gui/clickablelabel.h\
gui/colormapper.h\ gui/colormapper.h\
gui/commanditem.h\ gui/commanditem.h\
gui/commandoutputdialog.h\
gui/cwkeyergui.h\ gui/cwkeyergui.h\
gui/editcommanddialog.h\ gui/editcommanddialog.h\
gui/externalclockbutton.h\ gui/externalclockbutton.h\
@ -135,6 +137,7 @@ FORMS += mainwindow.ui\
gui/scopewindow.ui\ gui/scopewindow.ui\
gui/addpresetdialog.ui\ gui/addpresetdialog.ui\
gui/basicchannelsettingsdialog.ui\ gui/basicchannelsettingsdialog.ui\
gui/commandoutputdialog.ui\
gui/cwkeyergui.ui\ gui/cwkeyergui.ui\
gui/editcommanddialog.ui\ gui/editcommanddialog.ui\
gui/externalclockdialog.ui\ gui/externalclockdialog.ui\