Fixed up ability to send frames while not connected and to show frames
that were sent within the same window as received frames. Added a new scripting window that can be used to create scripts that send and receive messages at runtime - not done but sort of working.
This commit is contained in:
+11
-5
@@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
QT += core gui
|
QT += core gui
|
||||||
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport printsupport
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport printsupport qml
|
||||||
|
|
||||||
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
|
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT
|
||||||
|
|
||||||
CONFIG += c++11
|
CONFIG += c++11
|
||||||
@@ -36,7 +35,10 @@ SOURCES += main.cpp\
|
|||||||
filecomparatorwindow.cpp \
|
filecomparatorwindow.cpp \
|
||||||
mainsettingsdialog.cpp \
|
mainsettingsdialog.cpp \
|
||||||
firmwareuploaderwindow.cpp \
|
firmwareuploaderwindow.cpp \
|
||||||
discretestatewindow.cpp
|
discretestatewindow.cpp \
|
||||||
|
scriptingwindow.cpp \
|
||||||
|
scriptcontainer.cpp \
|
||||||
|
canfilter.cpp
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
can_structs.h \
|
can_structs.h \
|
||||||
@@ -61,7 +63,10 @@ HEADERS += mainwindow.h \
|
|||||||
filecomparatorwindow.h \
|
filecomparatorwindow.h \
|
||||||
mainsettingsdialog.h \
|
mainsettingsdialog.h \
|
||||||
firmwareuploaderwindow.h \
|
firmwareuploaderwindow.h \
|
||||||
discretestatewindow.h
|
discretestatewindow.h \
|
||||||
|
scriptingwindow.h \
|
||||||
|
scriptcontainer.h \
|
||||||
|
canfilter.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
graphingwindow.ui \
|
graphingwindow.ui \
|
||||||
@@ -76,7 +81,8 @@ FORMS += mainwindow.ui \
|
|||||||
filecomparatorwindow.ui \
|
filecomparatorwindow.ui \
|
||||||
mainsettingsdialog.ui \
|
mainsettingsdialog.ui \
|
||||||
firmwareuploaderwindow.ui \
|
firmwareuploaderwindow.ui \
|
||||||
discretestatewindow.ui
|
discretestatewindow.ui \
|
||||||
|
scriptingwindow.ui
|
||||||
|
|
||||||
DISTFILES +=
|
DISTFILES +=
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#include "canfilter.h"
|
||||||
|
|
||||||
|
CANFilter::CANFilter()
|
||||||
|
{
|
||||||
|
ID = 0;
|
||||||
|
mask = 0;
|
||||||
|
bus = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CANFilter::setFilter(uint32_t id, uint32_t mask, int bus)
|
||||||
|
{
|
||||||
|
this->ID = id;
|
||||||
|
this->mask = mask;
|
||||||
|
this->bus = bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CANFilter::checkFilter(uint32_t id, int bus)
|
||||||
|
{
|
||||||
|
if (bus == -1 || bus == this->bus)
|
||||||
|
{
|
||||||
|
uint32_t result = id & this->mask;
|
||||||
|
if (result == this->ID) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef CANFILTER_H
|
||||||
|
#define CANFILTER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class CANFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CANFilter();
|
||||||
|
void setFilter(uint32_t id, uint32_t mask, int bus);
|
||||||
|
bool checkFilter(uint32_t id, int bus);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t ID;
|
||||||
|
uint32_t mask;
|
||||||
|
int bus;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CANFILTER_H
|
||||||
+16
-14
@@ -251,25 +251,27 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANFrameModel::addFrame(CANFrame &frame, bool autoRefresh = false)
|
void CANFrameModel::addFrame(const CANFrame &frame, bool autoRefresh = false)
|
||||||
{
|
{
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
frame.timestamp -= timeOffset;
|
CANFrame tempFrame;
|
||||||
|
tempFrame = frame;
|
||||||
|
tempFrame.timestamp -= timeOffset;
|
||||||
|
|
||||||
//if this ID isn't found in the filters list then add it and show it by default
|
//if this ID isn't found in the filters list then add it and show it by default
|
||||||
if (!filters.contains(frame.ID))
|
if (!filters.contains(tempFrame.ID))
|
||||||
{
|
{
|
||||||
filters.insert(frame.ID, true);
|
filters.insert(tempFrame.ID, true);
|
||||||
needFilterRefresh = true;
|
needFilterRefresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overwriteDups)
|
if (!overwriteDups)
|
||||||
{
|
{
|
||||||
frames.append(frame);
|
frames.append(tempFrame);
|
||||||
if (filters[frame.ID])
|
if (filters[tempFrame.ID])
|
||||||
{
|
{
|
||||||
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + 1);
|
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + 1);
|
||||||
filteredFrames.append(frame);
|
filteredFrames.append(tempFrame);
|
||||||
if (autoRefresh) endInsertRows();
|
if (autoRefresh) endInsertRows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,20 +280,20 @@ void CANFrameModel::addFrame(CANFrame &frame, bool autoRefresh = false)
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; i < frames.count(); i++)
|
for (int i = 0; i < frames.count(); i++)
|
||||||
{
|
{
|
||||||
if (frames[i].ID == frame.ID)
|
if (frames[i].ID == tempFrame.ID)
|
||||||
{
|
{
|
||||||
frames.replace(i, frame);
|
frames.replace(i, tempFrame);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
frames.append(frame);
|
frames.append(tempFrame);
|
||||||
if (filters[frame.ID])
|
if (filters[tempFrame.ID])
|
||||||
{
|
{
|
||||||
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + 1);
|
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count() + 1, filteredFrames.count() + 1);
|
||||||
filteredFrames.append(frame);
|
filteredFrames.append(tempFrame);
|
||||||
if (autoRefresh) endInsertRows();
|
if (autoRefresh) endInsertRows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,10 +301,10 @@ void CANFrameModel::addFrame(CANFrame &frame, bool autoRefresh = false)
|
|||||||
{
|
{
|
||||||
for (int j = 0; j < filteredFrames.count(); j++)
|
for (int j = 0; j < filteredFrames.count(); j++)
|
||||||
{
|
{
|
||||||
if (filteredFrames[j].ID == frame.ID)
|
if (filteredFrames[j].ID == tempFrame.ID)
|
||||||
{
|
{
|
||||||
if (autoRefresh) beginResetModel();
|
if (autoRefresh) beginResetModel();
|
||||||
filteredFrames.replace(j, frame);
|
filteredFrames.replace(j, tempFrame);
|
||||||
if (autoRefresh) endResetModel();
|
if (autoRefresh) endResetModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ public:
|
|||||||
int columnCount(const QModelIndex &) const;
|
int columnCount(const QModelIndex &) const;
|
||||||
int totalFrameCount();
|
int totalFrameCount();
|
||||||
|
|
||||||
void addFrame(CANFrame &, bool);
|
void addFrame(const CANFrame &, bool);
|
||||||
void sendRefresh();
|
void sendRefresh();
|
||||||
void sendRefresh(int);
|
void sendRefresh(int);
|
||||||
void sendBulkRefresh(int);
|
void sendBulkRefresh(int);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CONFIG
|
#ifndef CONFIG
|
||||||
#define CONFIG
|
#define CONFIG
|
||||||
|
|
||||||
#define VERSION 141
|
#define VERSION 142
|
||||||
|
|
||||||
//try to keep this in sync.
|
//try to keep this in sync.
|
||||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||||
|
|||||||
+1
-1
@@ -799,7 +799,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_4">
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Trigger Values</string>
|
<string>Data Seek Values</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
+19
-1
@@ -86,6 +86,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
worker = new SerialWorker(model);
|
worker = new SerialWorker(model);
|
||||||
worker->moveToThread(&serialWorkerThread);
|
worker->moveToThread(&serialWorkerThread);
|
||||||
connect(&serialWorkerThread, &QThread::finished, worker, &QObject::deleteLater);
|
connect(&serialWorkerThread, &QThread::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(&serialWorkerThread, SIGNAL(started()), worker, SLOT(run())); //setup timers within the proper thread
|
||||||
connect(this, &MainWindow::sendSerialPort, worker, &SerialWorker::setSerialPort, Qt::QueuedConnection);
|
connect(this, &MainWindow::sendSerialPort, worker, &SerialWorker::setSerialPort, Qt::QueuedConnection);
|
||||||
connect(worker, &SerialWorker::frameUpdateTick, this, &MainWindow::gotFrames, Qt::QueuedConnection);
|
connect(worker, &SerialWorker::frameUpdateTick, this, &MainWindow::gotFrames, Qt::QueuedConnection);
|
||||||
connect(this, &MainWindow::updateBaudRates, worker, &SerialWorker::updateBaudRates, Qt::QueuedConnection);
|
connect(this, &MainWindow::updateBaudRates, worker, &SerialWorker::updateBaudRates, Qt::QueuedConnection);
|
||||||
@@ -98,7 +99,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
connect(this, &MainWindow::stopFrameCapturing, worker, &SerialWorker::stopFrameCapture);
|
connect(this, &MainWindow::stopFrameCapturing, worker, &SerialWorker::stopFrameCapture);
|
||||||
connect(this, &MainWindow::settingsUpdated, worker, &SerialWorker::readSettings);
|
connect(this, &MainWindow::settingsUpdated, worker, &SerialWorker::readSettings);
|
||||||
serialWorkerThread.start();
|
serialWorkerThread.start();
|
||||||
serialWorkerThread.setPriority(QThread::HighPriority);
|
serialWorkerThread.setPriority(QThread::HighPriority);
|
||||||
|
|
||||||
graphingWindow = NULL;
|
graphingWindow = NULL;
|
||||||
frameInfoWindow = NULL;
|
frameInfoWindow = NULL;
|
||||||
@@ -110,6 +111,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
settingsDialog = NULL;
|
settingsDialog = NULL;
|
||||||
firmwareUploaderWindow = NULL;
|
firmwareUploaderWindow = NULL;
|
||||||
discreteStateWindow = NULL;
|
discreteStateWindow = NULL;
|
||||||
|
scriptingWindow = NULL;
|
||||||
dbcHandler = new DBCHandler;
|
dbcHandler = new DBCHandler;
|
||||||
bDirty = false;
|
bDirty = false;
|
||||||
inhibitFilterUpdate = false;
|
inhibitFilterUpdate = false;
|
||||||
@@ -143,6 +145,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
connect(ui->actionSave_Decoded_Frames, SIGNAL(triggered(bool)), this, SLOT(handleSaveDecoded()));
|
connect(ui->actionSave_Decoded_Frames, SIGNAL(triggered(bool)), this, SLOT(handleSaveDecoded()));
|
||||||
connect(ui->actionSingle_Multi_State, SIGNAL(triggered(bool)), this, SLOT(showSingleMultiWindow()));
|
connect(ui->actionSingle_Multi_State, SIGNAL(triggered(bool)), this, SLOT(showSingleMultiWindow()));
|
||||||
connect(ui->actionFile_Comparison, SIGNAL(triggered(bool)), this, SLOT(showComparisonWindow()));
|
connect(ui->actionFile_Comparison, SIGNAL(triggered(bool)), this, SLOT(showComparisonWindow()));
|
||||||
|
connect(ui->actionScripting_INterface, SIGNAL(triggered(bool)), this, SLOT(showScriptingWindow()));
|
||||||
connect(ui->btnNormalize, SIGNAL(clicked(bool)), this, SLOT(normalizeTiming()));
|
connect(ui->btnNormalize, SIGNAL(clicked(bool)), this, SLOT(normalizeTiming()));
|
||||||
connect(ui->actionPreferences, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog()));
|
connect(ui->actionPreferences, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog()));
|
||||||
connect(model, SIGNAL(updatedFiltersList()), this, SLOT(updateFilterList()));
|
connect(model, SIGNAL(updatedFiltersList()), this, SLOT(updateFilterList()));
|
||||||
@@ -237,6 +240,12 @@ MainWindow::~MainWindow()
|
|||||||
delete discreteStateWindow;
|
delete discreteStateWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scriptingWindow)
|
||||||
|
{
|
||||||
|
scriptingWindow->close();
|
||||||
|
delete scriptingWindow;
|
||||||
|
}
|
||||||
|
|
||||||
delete ui;
|
delete ui;
|
||||||
delete dbcHandler;
|
delete dbcHandler;
|
||||||
model->clearFrames();
|
model->clearFrames();
|
||||||
@@ -1035,6 +1044,15 @@ void MainWindow::showSingleMultiWindow()
|
|||||||
discreteStateWindow->show();
|
discreteStateWindow->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::showScriptingWindow()
|
||||||
|
{
|
||||||
|
if (!scriptingWindow)
|
||||||
|
{
|
||||||
|
scriptingWindow = new ScriptingWindow(model->getListReference());
|
||||||
|
}
|
||||||
|
scriptingWindow->show();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::showRangeWindow()
|
void MainWindow::showRangeWindow()
|
||||||
{
|
{
|
||||||
//not done yet
|
//not done yet
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "mainsettingsdialog.h"
|
#include "mainsettingsdialog.h"
|
||||||
#include "firmwareuploaderwindow.h"
|
#include "firmwareuploaderwindow.h"
|
||||||
#include "discretestatewindow.h"
|
#include "discretestatewindow.h"
|
||||||
|
#include "scriptingwindow.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
@@ -56,6 +57,7 @@ private slots:
|
|||||||
void showComparisonWindow();
|
void showComparisonWindow();
|
||||||
void showSettingsDialog();
|
void showSettingsDialog();
|
||||||
void showFirmwareUploaderWindow();
|
void showFirmwareUploaderWindow();
|
||||||
|
void showScriptingWindow();
|
||||||
void exitApp();
|
void exitApp();
|
||||||
void handleSaveDecoded();
|
void handleSaveDecoded();
|
||||||
void changeBaudRates();
|
void changeBaudRates();
|
||||||
@@ -121,6 +123,7 @@ private:
|
|||||||
MainSettingsDialog *settingsDialog;
|
MainSettingsDialog *settingsDialog;
|
||||||
DiscreteStateWindow *discreteStateWindow;
|
DiscreteStateWindow *discreteStateWindow;
|
||||||
FirmwareUploaderWindow *firmwareUploaderWindow;
|
FirmwareUploaderWindow *firmwareUploaderWindow;
|
||||||
|
ScriptingWindow *scriptingWindow;
|
||||||
|
|
||||||
//various private storage
|
//various private storage
|
||||||
QLabel lbStatusConnected;
|
QLabel lbStatusConnected;
|
||||||
|
|||||||
+7
-1
@@ -293,7 +293,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>800</width>
|
||||||
<height>21</height>
|
<height>27</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_RE_Tools">
|
<widget class="QMenu" name="menu_RE_Tools">
|
||||||
@@ -311,6 +311,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<addaction name="action_Playback"/>
|
<addaction name="action_Playback"/>
|
||||||
<addaction name="action_Custom"/>
|
<addaction name="action_Custom"/>
|
||||||
|
<addaction name="actionScripting_INterface"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@@ -442,6 +443,11 @@
|
|||||||
<string>Firmware Uploader</string>
|
<string>Firmware Uploader</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionScripting_INterface">
|
||||||
|
<property name="text">
|
||||||
|
<string>Scripting Interface</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
#include "scriptcontainer.h"
|
||||||
|
|
||||||
|
#include <QJSValueIterator>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
ScriptContainer::ScriptContainer()
|
||||||
|
{
|
||||||
|
fileName = QString();
|
||||||
|
filePath = QString();
|
||||||
|
scriptText = QString();
|
||||||
|
|
||||||
|
connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::compileScript()
|
||||||
|
{
|
||||||
|
QJSValue result = scriptEngine.evaluate(scriptText, fileName);
|
||||||
|
if (result.isError() && errorWidget)
|
||||||
|
{
|
||||||
|
errorWidget->clear();
|
||||||
|
errorWidget->addItem("SCRIPT EXCEPTION!");
|
||||||
|
errorWidget->addItem("Line: " + result.property("lineNumber").toString());
|
||||||
|
errorWidget->addItem(result.property("message").toString());
|
||||||
|
errorWidget->addItem("Stack:");
|
||||||
|
errorWidget->addItem(result.property("stack").toString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compiledScript = result;
|
||||||
|
|
||||||
|
QJSValue hostObj = scriptEngine.newQObject(this);
|
||||||
|
scriptEngine.globalObject().setProperty("host", hostObj);
|
||||||
|
|
||||||
|
setupFunction = scriptEngine.globalObject().property("setup");
|
||||||
|
gotFrameFunction = scriptEngine.globalObject().property("gotFrame");
|
||||||
|
tickFunction = scriptEngine.globalObject().property("tick");
|
||||||
|
|
||||||
|
if (setupFunction.isCallable())
|
||||||
|
{
|
||||||
|
qDebug() << "setup exists";
|
||||||
|
QJSValue res = setupFunction.call();
|
||||||
|
if (res.isError())
|
||||||
|
{
|
||||||
|
errorWidget->addItem("Error in setup function on line " + res.property("lineNumber").toString());
|
||||||
|
errorWidget->addItem(res.property("message").toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gotFrameFunction.isCallable()) qDebug() << "gotFrame exists";
|
||||||
|
if (tickFunction.isCallable()) qDebug() << "tick exists";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::setErrorWidget(QListWidget *list)
|
||||||
|
{
|
||||||
|
errorWidget = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::setFilter(QJSValue id, QJSValue mask, QJSValue bus)
|
||||||
|
{
|
||||||
|
qDebug() << "Called set filter";
|
||||||
|
qDebug() << id.toInt() << "*" << mask.toInt() << "*" << bus.toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::setTickInterval(QJSValue interval)
|
||||||
|
{
|
||||||
|
int intervalValue = interval.toInt();
|
||||||
|
qDebug() << "called set tick interval with value " << intervalValue;
|
||||||
|
if (intervalValue > 0)
|
||||||
|
{
|
||||||
|
timer.setInterval(intervalValue);
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
else timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::clearFilters()
|
||||||
|
{
|
||||||
|
qDebug() << "Called clear filters";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::sendFrame(QJSValue id, QJSValue length, QJSValue data)
|
||||||
|
{
|
||||||
|
qDebug() << "called send frame";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContainer::tick()
|
||||||
|
{
|
||||||
|
if (tickFunction.isCallable())
|
||||||
|
{
|
||||||
|
qDebug() << "Calling tick function";
|
||||||
|
QJSValue res = tickFunction.call();
|
||||||
|
if (res.isError())
|
||||||
|
{
|
||||||
|
errorWidget->addItem("Error in tick function on line " + res.property("lineNumber").toString());
|
||||||
|
errorWidget->addItem(res.property("message").toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef SCRIPTCONTAINER_H
|
||||||
|
#define SCRIPTCONTAINER_H
|
||||||
|
|
||||||
|
#include <QJSEngine>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <qlistwidget.h>
|
||||||
|
|
||||||
|
class ScriptContainer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptContainer();
|
||||||
|
QString fileName;
|
||||||
|
QString filePath;
|
||||||
|
QString scriptText;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void compileScript();
|
||||||
|
void setErrorWidget(QListWidget *list);
|
||||||
|
void setFilter(QJSValue id, QJSValue mask, QJSValue bus);
|
||||||
|
void setTickInterval(QJSValue interval);
|
||||||
|
void clearFilters();
|
||||||
|
void sendFrame(QJSValue id, QJSValue length, QJSValue data);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void tick();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QJSEngine scriptEngine;
|
||||||
|
QJSValue compiledScript;
|
||||||
|
QJSValue setupFunction;
|
||||||
|
QJSValue gotFrameFunction;
|
||||||
|
QJSValue tickFunction;
|
||||||
|
QTimer timer;
|
||||||
|
QListWidget *errorWidget;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCRIPTCONTAINER_H
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#include "scriptingwindow.h"
|
||||||
|
#include "ui_scriptingwindow.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
ScriptingWindow::ScriptingWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::ScriptingWindow)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
modelFrames = frames;
|
||||||
|
|
||||||
|
connect(ui->btnLoadScript, SIGNAL(pressed()), this, SLOT(loadNewScript()));
|
||||||
|
connect(ui->btnNewScript, SIGNAL(pressed()), this, SLOT(createNewScript()));
|
||||||
|
connect(ui->btnRecompile, SIGNAL(pressed()), this, SLOT(recompileScript()));
|
||||||
|
connect(ui->btnRemoveScript, SIGNAL(pressed()), this, SLOT(deleteCurrentScript()));
|
||||||
|
connect(ui->btnRevertScript, SIGNAL(pressed()), this, SLOT(revertScript()));
|
||||||
|
connect(ui->btnSaveScript, SIGNAL(pressed()), this, SLOT(saveScript()));
|
||||||
|
|
||||||
|
currentScript = new ScriptContainer();
|
||||||
|
currentScript->setErrorWidget(ui->listErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptingWindow::~ScriptingWindow()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::loadNewScript()
|
||||||
|
{
|
||||||
|
QString filename;
|
||||||
|
QFileDialog dialog;
|
||||||
|
bool result = false;
|
||||||
|
ScriptContainer *container;
|
||||||
|
|
||||||
|
QStringList filters;
|
||||||
|
filters.append(QString(tr("Javascript File (*.js)")));
|
||||||
|
|
||||||
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
|
dialog.setNameFilters(filters);
|
||||||
|
dialog.setViewMode(QFileDialog::Detail);
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
filename = dialog.selectedFiles()[0];
|
||||||
|
|
||||||
|
if (dialog.selectedNameFilter() == filters[0])
|
||||||
|
{
|
||||||
|
QFile scriptFile(filename);
|
||||||
|
|
||||||
|
if (scriptFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
QString contents = scriptFile.readAll();
|
||||||
|
scriptFile.close();
|
||||||
|
QStringList fileList = filename.split('/');
|
||||||
|
QString justFileName = fileList[fileList.length() - 1];
|
||||||
|
ui->listLoadedScripts->addItem(justFileName);
|
||||||
|
container = new ScriptContainer();
|
||||||
|
container->fileName = justFileName;
|
||||||
|
container->filePath = filename;
|
||||||
|
container->scriptText = contents;
|
||||||
|
container->setErrorWidget(ui->listErrors);
|
||||||
|
container->compileScript();
|
||||||
|
scripts.append(container);
|
||||||
|
currentScript = container;
|
||||||
|
ui->txtScriptSource->setText(container->scriptText);
|
||||||
|
ui->txtScriptSource->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::createNewScript()
|
||||||
|
{
|
||||||
|
ScriptContainer *container;
|
||||||
|
|
||||||
|
container = new ScriptContainer();
|
||||||
|
|
||||||
|
container->fileName = "UNNAMED_" + QString::number((qrand() % 10000)) + ".js";
|
||||||
|
container->filePath = QString();
|
||||||
|
container->scriptText = QString();
|
||||||
|
container->setErrorWidget(ui->listErrors);
|
||||||
|
scripts.append(container);
|
||||||
|
ui->listLoadedScripts->addItem(container->fileName);
|
||||||
|
currentScript = container;
|
||||||
|
ui->txtScriptSource->setText(container->scriptText);
|
||||||
|
ui->txtScriptSource->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::deleteCurrentScript()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::refreshSourceWindow()
|
||||||
|
{
|
||||||
|
ui->txtScriptSource->setText(currentScript->scriptText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::saveScript()
|
||||||
|
{
|
||||||
|
QString filename;
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
|
||||||
|
QStringList filters;
|
||||||
|
filters.append(QString(tr("Javascript File (*.js)")));
|
||||||
|
|
||||||
|
dialog.setFileMode(QFileDialog::AnyFile);
|
||||||
|
dialog.setNameFilters(filters);
|
||||||
|
dialog.setViewMode(QFileDialog::Detail);
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
filename = dialog.selectedFiles()[0];
|
||||||
|
if (!filename.contains('.')) filename += ".js";
|
||||||
|
if (dialog.selectedNameFilter() == filters[0])
|
||||||
|
{
|
||||||
|
QFile *outFile = new QFile(filename);
|
||||||
|
|
||||||
|
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
delete outFile;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outFile->write(ui->txtScriptSource->toPlainText().toUtf8());
|
||||||
|
outFile->close();
|
||||||
|
delete outFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::revertScript()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptingWindow::recompileScript()
|
||||||
|
{
|
||||||
|
currentScript->scriptText = ui->txtScriptSource->toPlainText();
|
||||||
|
currentScript->compileScript();
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef SCRIPTINGWINDOW_H
|
||||||
|
#define SCRIPTINGWINDOW_H
|
||||||
|
|
||||||
|
#include "can_structs.h"
|
||||||
|
#include "scriptcontainer.h"
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QJSEngine>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ScriptingWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScriptingWindow : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScriptingWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
||||||
|
~ScriptingWindow();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void loadNewScript();
|
||||||
|
void createNewScript();
|
||||||
|
void deleteCurrentScript();
|
||||||
|
void refreshSourceWindow();
|
||||||
|
void saveScript();
|
||||||
|
void revertScript();
|
||||||
|
void recompileScript();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ScriptingWindow *ui;
|
||||||
|
|
||||||
|
QList<ScriptContainer *> scripts;
|
||||||
|
ScriptContainer *currentScript;
|
||||||
|
const QVector<CANFrame> *modelFrames;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCRIPTINGWINDOW_H
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ScriptingWindow</class>
|
||||||
|
<widget class="QDialog" name="ScriptingWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>994</width>
|
||||||
|
<height>858</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Scripting Interface</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,4">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Loaded Scripts</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listLoadedScripts"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnLoadScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load New Script</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnNewScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>Create New Script</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnRemoveScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove Current Script</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,5,0,0,1">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Script Editing Window</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="txtScriptSource">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnSaveScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnRevertScript">
|
||||||
|
<property name="text">
|
||||||
|
<string>Revert</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnRecompile">
|
||||||
|
<property name="text">
|
||||||
|
<string>Recompile</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Current Scripting Errors</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listErrors"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
+27
-24
@@ -40,6 +40,19 @@ SerialWorker::~SerialWorker()
|
|||||||
if (ticker != NULL) ticker->stop();
|
if (ticker != NULL) ticker->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SerialWorker::run()
|
||||||
|
{
|
||||||
|
ticker = new QTimer;
|
||||||
|
connect(ticker, SIGNAL(timeout()), this, SLOT(handleTick()));
|
||||||
|
|
||||||
|
elapsedTime = new QTime;
|
||||||
|
elapsedTime->start();
|
||||||
|
|
||||||
|
ticker->setInterval(250); //tick four times per second
|
||||||
|
ticker->setSingleShot(false); //keep ticking
|
||||||
|
ticker->start();
|
||||||
|
}
|
||||||
|
|
||||||
void SerialWorker::readSettings()
|
void SerialWorker::readSettings()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
@@ -110,19 +123,6 @@ void SerialWorker::setSerialPort(QSerialPortInfo *port)
|
|||||||
else connected = true;
|
else connected = true;
|
||||||
connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
||||||
if (doValidation) QTimer::singleShot(1000, this, SLOT(connectionTimeout()));
|
if (doValidation) QTimer::singleShot(1000, this, SLOT(connectionTimeout()));
|
||||||
if (ticker == NULL)
|
|
||||||
{
|
|
||||||
ticker = new QTimer;
|
|
||||||
connect(ticker, SIGNAL(timeout()), this, SLOT(handleTick()));
|
|
||||||
}
|
|
||||||
if (elapsedTime == NULL)
|
|
||||||
{
|
|
||||||
elapsedTime = new QTime;
|
|
||||||
elapsedTime->start();
|
|
||||||
}
|
|
||||||
ticker->setInterval(250); //tick four times per second
|
|
||||||
ticker->setSingleShot(false); //keep ticking
|
|
||||||
ticker->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialWorker::connectionTimeout()
|
void SerialWorker::connectionTimeout()
|
||||||
@@ -158,6 +158,10 @@ void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0)
|
|||||||
|
|
||||||
//qDebug() << "Sending out frame with id " << frame->ID;
|
//qDebug() << "Sending out frame with id " << frame->ID;
|
||||||
|
|
||||||
|
//show our sent frames in the list too. This happens even if we're not connected.
|
||||||
|
canModel->addFrame(*frame, false);
|
||||||
|
gotFrames++;
|
||||||
|
|
||||||
if (!connected) return;
|
if (!connected) return;
|
||||||
|
|
||||||
ID = frame->ID;
|
ID = frame->ID;
|
||||||
@@ -181,10 +185,6 @@ void SerialWorker::sendFrame(const CANFrame *frame, int bus = 0)
|
|||||||
if (!serial->isOpen()) return;
|
if (!serial->isOpen()) return;
|
||||||
//qDebug() << "writing " << buffer.length() << " bytes to serial port";
|
//qDebug() << "writing " << buffer.length() << " bytes to serial port";
|
||||||
serial->write(buffer);
|
serial->write(buffer);
|
||||||
|
|
||||||
//show our sent frames in the list too.
|
|
||||||
canModel->addFrame(frame, false);
|
|
||||||
gotFrames++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//a simple way for another thread to pass us a bunch of frames to send.
|
//a simple way for another thread to pass us a bunch of frames to send.
|
||||||
@@ -426,14 +426,17 @@ void SerialWorker::handleTick()
|
|||||||
{
|
{
|
||||||
//qDebug() << "Tick!";
|
//qDebug() << "Tick!";
|
||||||
|
|
||||||
if (!gotValidated)
|
if (connected)
|
||||||
{
|
{
|
||||||
if (serial->isOpen()) //if it's still false we have a problem...
|
if (!gotValidated)
|
||||||
{
|
{
|
||||||
qDebug() << "Comm validation failed. ";
|
if (serial->isOpen()) //if it's still false we have a problem...
|
||||||
closeSerialPort(); //start by stopping everything.
|
{
|
||||||
QTimer::singleShot(500, this, SLOT(handleReconnect()));
|
qDebug() << "Comm validation failed. ";
|
||||||
return;
|
closeSerialPort(); //start by stopping everything.
|
||||||
|
QTimer::singleShot(500, this, SLOT(handleReconnect()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +445,7 @@ void SerialWorker::handleTick()
|
|||||||
emit frameUpdateTick(framesPerSec / 4, gotFrames); //sends stats to interested parties
|
emit frameUpdateTick(framesPerSec / 4, gotFrames); //sends stats to interested parties
|
||||||
canModel->sendBulkRefresh(gotFrames);
|
canModel->sendBulkRefresh(gotFrames);
|
||||||
gotFrames = 0;
|
gotFrames = 0;
|
||||||
if (doValidation) sendCommValidation();
|
if (doValidation && connected) sendCommValidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialWorker::handleReconnect()
|
void SerialWorker::handleReconnect()
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ private slots: //we receive things in slots
|
|||||||
void handleReconnect();
|
void handleReconnect();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void run();
|
||||||
void setSerialPort(QSerialPortInfo*);
|
void setSerialPort(QSerialPortInfo*);
|
||||||
void closeSerialPort();
|
void closeSerialPort();
|
||||||
void sendFrame(const CANFrame *, int);
|
void sendFrame(const CANFrame *, int);
|
||||||
|
|||||||
Reference in New Issue
Block a user