diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,8 +57,15 @@ qt5_wrap_ui(UI_FILES
portcontrol.ui
about_dialog.ui
snapshotview.ui
+ commandpanel.ui
+ commandwidget.ui
)
-qt5_add_resources(RES_FILES misc/icons.qrc)
+
+if (WIN32)
+ qt5_add_resources(RES_FILES misc/icons.qrc misc/winicons.qrc)
+else (WIN32)
+ qt5_add_resources(RES_FILES misc/icons.qrc)
+endif (WIN32)
add_executable(${PROGRAM_NAME} WIN32
main.cpp
@@ -75,6 +82,9 @@ add_executable(${PROGRAM_NAME} WIN32
snapshotview.cpp
snapshotmanager.cpp
plotsnapshotoverlay.cpp
+ commandpanel.cpp
+ commandwidget.cpp
+ commandedit.cpp
${UI_FILES}
${RES_FILES}
misc/windows_icon.rc
diff --git a/commandedit.cpp b/commandedit.cpp
new file mode 100644
--- /dev/null
+++ b/commandedit.cpp
@@ -0,0 +1,142 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include
+
+#include
+
+#include "commandedit.h"
+
+class HexCommandValidator : public QRegExpValidator
+{
+public:
+ explicit HexCommandValidator(QObject* parent = 0);
+ QValidator::State validate(QString & input, int & pos) const;
+};
+
+HexCommandValidator::HexCommandValidator(QObject* parent) :
+ QRegExpValidator(parent)
+{
+ QRegExp regExp("^(?:(?:[0-9A-F]{2}[ ])+(?:[0-9A-F]{2}))|(?:[0-9A-F]{2})$");
+ setRegExp(regExp);
+}
+
+QValidator::State HexCommandValidator::validate(QString & input, int & pos) const
+{
+ input = input.toUpper();
+
+ // don't let pos to be altered at this stage
+ int orgPos = pos;
+ auto r = QRegExpValidator::validate(input, pos);
+ pos = orgPos;
+
+ // try fixing up spaces
+ if (r != QValidator::Acceptable)
+ {
+ input = input.replace(" ", "");
+ input.replace(QRegExp("([0-9A-F]{2}(?!$))"), "\\1 ");
+ if (pos == input.size()-1) pos = input.size();
+ r = QRegExpValidator::validate(input, pos);
+ }
+
+ return r;
+}
+
+CommandEdit::CommandEdit(QWidget *parent) :
+ QLineEdit(parent)
+{
+ hexValidator = new HexCommandValidator(this);
+ asciiValidator = new QRegExpValidator(QRegExp("[\\x0000-\\x007F]+"));
+ ascii_mode = true;
+ setValidator(asciiValidator);
+}
+
+CommandEdit::~CommandEdit()
+{
+ delete hexValidator;
+}
+
+QString unEscape(QString str);
+QString escape(QString str);
+
+void CommandEdit::setMode(bool ascii)
+{
+ ascii_mode = ascii;
+ if (ascii)
+ {
+ setValidator(asciiValidator);
+
+ auto hexText = text().remove(" ");
+ // try patching HEX string in case of missing nibble so that
+ // input doesn't turn into gibberish
+ if (hexText.size() % 2 == 1)
+ {
+ hexText.replace(hexText.size()-1, 1, "3F"); // 0x3F = '?'
+ qWarning() << "Broken byte in hex command is replaced. Check your command!";
+ }
+
+ setText(escape(QByteArray::fromHex(hexText.toLatin1())));
+ }
+ else
+ {
+ setValidator(hexValidator);
+ setText(unEscape(text()).toLatin1().toHex());
+ }
+}
+
+void CommandEdit::keyPressEvent(QKeyEvent * event)
+{
+ if (ascii_mode)
+ {
+ QLineEdit::keyPressEvent(event);
+ return;
+ }
+
+ if (event->key() == Qt::Key_Backspace && !hasSelectedText())
+ {
+ int cursor = cursorPosition();
+ if (cursor != 0 && text()[cursor-1] == ' ')
+ {
+ setCursorPosition(cursor-1);
+ }
+ }
+
+ QLineEdit::keyPressEvent(event);
+}
+
+QString CommandEdit::unEscapedText()
+{
+ return unEscape(text());
+}
+
+QString unEscape(QString str)
+{
+ str.replace("\\n", "\n");
+ str.replace("\\r", "\r");
+ str.replace("\\t", "\t");
+ return str;
+}
+
+QString escape(QString str)
+{
+ str.replace("\n", "\\n");
+ str.replace("\r", "\\r");
+ str.replace("\t", "\\t");
+ return str;
+}
diff --git a/commandedit.h b/commandedit.h
new file mode 100644
--- /dev/null
+++ b/commandedit.h
@@ -0,0 +1,46 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef COMMANDEDIT_H
+#define COMMANDEDIT_H
+
+#include
+#include
+#include
+
+class CommandEdit : public QLineEdit
+{
+ Q_OBJECT
+
+public:
+ explicit CommandEdit(QWidget *parent = 0);
+ ~CommandEdit();
+ void setMode(bool ascii); // true = ascii, false = hex
+ QString unEscapedText(); // return unescaped text(), used in ascii_mode only
+
+private:
+ bool ascii_mode;
+ QValidator* hexValidator;
+ QValidator* asciiValidator;
+
+protected:
+ void keyPressEvent(QKeyEvent * event) Q_DECL_OVERRIDE;
+};
+
+#endif // COMMANDEDIT_H
diff --git a/commandpanel.cpp b/commandpanel.cpp
new file mode 100644
--- /dev/null
+++ b/commandpanel.cpp
@@ -0,0 +1,68 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "commandpanel.h"
+#include "ui_commandpanel.h"
+
+#include
+#include
+
+CommandPanel::CommandPanel(QSerialPort* port, QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::CommandPanel)
+{
+ serialPort = port;
+
+ ui->setupUi(this);
+ ui->scrollAreaWidgetContents->setLayout(new QVBoxLayout);
+
+#ifdef Q_OS_WIN
+ ui->pbNew->setIcon(QIcon(":/icons/list-add"));
+#endif // Q_OS_WIN
+
+ connect(ui->pbNew, &QPushButton::clicked, this, &CommandPanel::newCommand);
+
+ newCommand(); // add an empty slot by default
+}
+
+CommandPanel::~CommandPanel()
+{
+ delete ui;
+}
+
+void CommandPanel::newCommand()
+{
+ auto command = new CommandWidget();
+ ui->scrollAreaWidgetContents->layout()->addWidget(command);
+ connect(command, &CommandWidget::sendCommand, this, &CommandPanel::sendCommand);
+}
+
+void CommandPanel::sendCommand(QByteArray command)
+{
+ if (!serialPort->isOpen())
+ {
+ qCritical() << "Port is not open!";
+ return;
+ }
+
+ if (serialPort->write(command) < 0)
+ {
+ qCritical() << "Send command failed!";
+ }
+}
diff --git a/commandpanel.h b/commandpanel.h
new file mode 100644
--- /dev/null
+++ b/commandpanel.h
@@ -0,0 +1,50 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef COMMANDPANEL_H
+#define COMMANDPANEL_H
+
+#include
+#include
+#include
+
+#include "commandwidget.h"
+
+namespace Ui {
+class CommandPanel;
+}
+
+class CommandPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit CommandPanel(QSerialPort* port, QWidget *parent = 0);
+ ~CommandPanel();
+
+private:
+ Ui::CommandPanel *ui;
+ QSerialPort* serialPort;
+
+private slots:
+ void newCommand();
+ void sendCommand(QByteArray command);
+};
+
+#endif // COMMANDPANEL_H
diff --git a/commandpanel.ui b/commandpanel.ui
new file mode 100644
--- /dev/null
+++ b/commandpanel.ui
@@ -0,0 +1,63 @@
+
+
+ CommandPanel
+
+
+
+ 0
+ 0
+ 583
+ 109
+
+
+
+ Form
+
+
+ false
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ true
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+
+
+ 0
+ 0
+ 563
+ 16
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+ -
+
+
+ New Command
+
+
+
+
+
+
+
+
+
+
+
diff --git a/commandwidget.cpp b/commandwidget.cpp
new file mode 100644
--- /dev/null
+++ b/commandwidget.cpp
@@ -0,0 +1,95 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "commandwidget.h"
+#include "ui_commandwidget.h"
+
+#include
+#include
+#include
+#include
+
+CommandWidget::CommandWidget(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::CommandWidget)
+{
+ ui->setupUi(this);
+
+#ifdef Q_OS_WIN
+ ui->pbDelete->setIcon(QIcon(":/icons/list-remove"));
+#endif // Q_OS_WIN
+
+ connect(ui->pbDelete, &QPushButton::clicked, this, &CommandWidget::onDeleteClicked);
+ connect(ui->pbSend, &QPushButton::clicked, this, &CommandWidget::onSendClicked);
+ connect(ui->pbASCII, &QPushButton::toggled, this, &CommandWidget::onASCIIToggled);
+}
+
+CommandWidget::~CommandWidget()
+{
+ delete ui;
+}
+
+void CommandWidget::onDeleteClicked()
+{
+ this->deleteLater();
+}
+
+void CommandWidget::onSendClicked()
+{
+ auto command = ui->leCommand->text();
+
+ if (command.isEmpty())
+ {
+ qWarning() << "Enter a command to send!";
+ ui->leCommand->setFocus(Qt::OtherFocusReason);
+ return;
+ }
+
+ if (isASCIIMode())
+ {
+ qDebug() << "Sending:" << command;
+ emit sendCommand(ui->leCommand->unEscapedText().toLatin1());
+ }
+ else // hex mode
+ {
+ command = command.remove(' ');
+ // check if nibbles are missing
+ if (command.size() % 2 == 1)
+ {
+ qWarning() << "HEX command is missing a nibble at the end!";
+ ui->leCommand->setFocus(Qt::OtherFocusReason);
+ // highlight the byte that is missing a nibble (last byte obviously)
+ int textSize = ui->leCommand->text().size();
+ ui->leCommand->setSelection(textSize-1, textSize);
+ return;
+ }
+ qDebug() << "Sending HEX:" << command;
+ emit sendCommand(QByteArray::fromHex(command.toLatin1()));
+ }
+}
+
+void CommandWidget::onASCIIToggled(bool checked)
+{
+ ui->leCommand->setMode(checked);
+}
+
+bool CommandWidget::isASCIIMode()
+{
+ return ui->pbASCII->isChecked();
+}
diff --git a/commandwidget.h b/commandwidget.h
new file mode 100644
--- /dev/null
+++ b/commandwidget.h
@@ -0,0 +1,58 @@
+/*
+ Copyright © 2015 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef COMMANDWIDGET_H
+#define COMMANDWIDGET_H
+
+#include
+#include
+
+namespace Ui {
+class CommandWidget;
+}
+
+class CommandWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit CommandWidget(QWidget *parent = 0);
+ ~CommandWidget();
+
+signals:
+ void deleteRequested(CommandWidget* thisWidget); // emitted when delete button is clicked
+
+ // emitted when send button is clicked
+ //
+ // in case of hex mode, command text should be a hexadecimal
+ // string containing hexadecimal characters only (not even spaces)
+ void sendCommand(QByteArray command);
+
+private:
+ Ui::CommandWidget *ui;
+
+ bool isASCIIMode(); // true: ascii mode, false hex mode
+
+private slots:
+ void onDeleteClicked();
+ void onSendClicked();
+ void onASCIIToggled(bool checked);
+};
+
+#endif // COMMANDWIDGET_H
diff --git a/commandwidget.ui b/commandwidget.ui
new file mode 100644
--- /dev/null
+++ b/commandwidget.ui
@@ -0,0 +1,173 @@
+
+
+ CommandWidget
+
+
+
+ 0
+ 0
+ 433
+ 34
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 30
+ 0
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ <html><head/><body><p>Enter your command here.</p><p>In ASCII mode you can use backslash '\' to send some special characters. These are:<br/><span style=" font-weight:600;">\n</span> : Line Feed (new line)<br/><span style=" font-weight:600;">\r</span> : Carriage Return<br/><span style=" font-weight:600;">\t</span> : Tab</p><p>Be careful though, you cannot escape the backslash character itself!</p></body></html>
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 40
+ 0
+
+
+
+ ASCII
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 40
+ 0
+
+
+
+ HEX
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Send
+
+
+
+
+
+
+
+ CommandEdit
+ QLineEdit
+
+
+
+
+
+
diff --git a/mainwindow.cpp b/mainwindow.cpp
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -54,10 +54,12 @@ MainWindow::MainWindow(QWidget *parent)
QMainWindow(parent),
ui(new Ui::MainWindow),
portControl(&serialPort),
+ commandPanel(&serialPort),
snapshotMan(this, &channelBuffers)
{
ui->setupUi(this);
ui->tabWidget->insertTab(0, &portControl, "Port");
+ ui->tabWidget->insertTab(3, &commandPanel, "Commands");
ui->tabWidget->setCurrentIndex(0);
addToolBar(portControl.toolBar());
diff --git a/mainwindow.h b/mainwindow.h
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -35,6 +35,7 @@
#include
#include "portcontrol.h"
+#include "commandpanel.h"
#include "ui_about_dialog.h"
#include "framebuffer.h"
#include "snapshotmanager.h"
@@ -100,6 +101,8 @@ private:
unsigned int sampleCount;
QTimer spsTimer;
+ CommandPanel commandPanel;
+
SnapshotManager snapshotMan;
// demo
diff --git a/misc/pseudo_device_2.py b/misc/pseudo_device_2.py
new file mode 100755
--- /dev/null
+++ b/misc/pseudo_device_2.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python3
+#
+# Copyright © 2015 Hasan Yavuz Özderya
+#
+# This file is part of serialplot.
+#
+# serialplot 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# serialplot 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 for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with serialplot. If not, see .
+#
+
+import os, pty, time
+
+def run():
+ # create the pseudo terminal
+ master, slave = pty.openpty()
+
+ slave_name = os.ttyname(slave)
+ print("Slave terminal: {}".format(slave_name))
+
+ masterw = os.fdopen(master, 'w')
+ masterr = os.fdopen(master, 'r')
+
+ while True:
+ line = masterr.read(4)
+ print(">" + line)
+ if (line.strip() == "data"):
+ masterw.write("1,1\r\n")
+ time.sleep(0.01)
+
+if __name__ == "__main__":
+ run()
diff --git a/misc/tango/license_notice b/misc/tango/license_notice
new file mode 100644
--- /dev/null
+++ b/misc/tango/license_notice
@@ -0,0 +1,3 @@
+Icon files in this directory are taken from Tango project
+(http://tango.freedesktop.org/). Please see referenced web page for
+more information.
\ No newline at end of file
diff --git a/misc/tango/list-add.png b/misc/tango/list-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..2acdd8f514c199a37b7b14f53081467f88ef7bff
GIT binary patch
literal 601
zc$@)Q0;c_mP)i&hw@usRe0Hlp%^VXF!>2}-I+fVC+BCh2Xu(H}=
zWwkR-i17&Q1@?r1slIQmGmt?bz+``iz=_N4nTEMJnWp6PdlDi4$xDysihSSRJ^#HD
zfm0WkcL*Ezw|WjD;wX`Y@`OQ$i>
zk~|wHA%P^W-+NY=qm+O%@!?CCIP&DpgbAGaz)s%w=F2r6?z`
z-r3~+=g{XtaVheZEby-7%X^w2a;hK35HfD6NN^I8P7V;(0mQ@Z@*Wtm@8FfUzLwkFPvfh|u~3@f)V
nN>6CzLo>o}j6Z`3{#X10^GpxssPJ~100000NkvXXu0mjfzW5Zm
diff --git a/misc/tango/list-remove.png b/misc/tango/list-remove.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5524f7284e4ecb40cbee1e3d3a449bd58a0e4a8
GIT binary patch
literal 317
zc$@(}0mA-?P)oXoi$Ept^qyG_6h*pUY)JY1xUgL61ap*$YU>o#o9`0ukRmwYg7fy
z#q{lyri8qE6g3Y4Q)K4C3`{ULEziwO932j7CF%n2voBs=XUn#u^MV%pm5i9iZx-vp
zUj3U@1pr3JL$sKN`)b!NVJ6&T
+
+ tango/list-add.png
+ tango/list-remove.png
+
+
diff --git a/serialplot.pro b/serialplot.pro
--- a/serialplot.pro
+++ b/serialplot.pro
@@ -46,7 +46,10 @@ SOURCES += main.cpp\
snapshotview.cpp \
snapshotmanager.cpp \
snapshot.cpp \
- plotsnapshotoverlay.cpp
+ plotsnapshotoverlay.cpp \
+ commandpanel.cpp \
+ commandwidget.cpp \
+ commandedit.cpp
HEADERS += mainwindow.h \
utils.h \
@@ -62,16 +65,24 @@ HEADERS += mainwindow.h \
snapshotview.h \
snapshotmanager.h \
snapshot.h \
- plotsnapshotoverlay.h
+ plotsnapshotoverlay.h \
+ commandpanel.h \
+ commandwidget.h \
+ commandedit.h
FORMS += mainwindow.ui \
about_dialog.ui \
portcontrol.ui \
- snapshotview.ui
+ snapshotview.ui \
+ commandpanel.ui \
+ commandwidget.ui
INCLUDEPATH += qmake/
CONFIG += c++11
-RESOURCES += \
- misc/icons.qrc
+RESOURCES += misc/icons.qrc
+
+win32 {
+ RESOURCES += misc/winicons.qrc
+}