Merge pull request #200 from collin80/WIP

Merge WIP changes into Master
This commit is contained in:
Collin Kidder
2019-06-17 21:22:35 -04:00
committed by GitHub
43 changed files with 1127 additions and 181 deletions
+11
View File
@@ -71,6 +71,14 @@ Now run SavvyCAN
./SavvyCAN ./SavvyCAN
``` ```
### Compiling in debug mode for additional information
```sh
qmake CONFIG+=debug
make
```
## What to do if your compile failed? ## What to do if your compile failed?
The very first thing to do is try: The very first thing to do is try:
@@ -86,3 +94,6 @@ make
Did that fix it? Great! If not, ensure that you selected SerialBUS support Did that fix it? Great! If not, ensure that you selected SerialBUS support
when you installed Qt. when you installed Qt.
### What to do if `qmake` fails with error `Project ERROR: Unknown module(s) in QT: qml serialbus help` on Ubuntu? :
`sudo apt install libqt5serialbus5-dev qtdeclarative5-dev qttools5-dev`
+6 -3
View File
@@ -67,7 +67,8 @@ SOURCES += main.cpp\
helpwindow.cpp \ helpwindow.cpp \
blfhandler.cpp \ blfhandler.cpp \
re/sniffer/SnifferDelegate.cpp \ re/sniffer/SnifferDelegate.cpp \
connections/newconnectiondialog.cpp connections/newconnectiondialog.cpp \
re/temporalgraphwindow.cpp
HEADERS += mainwindow.h \ HEADERS += mainwindow.h \
can_structs.h \ can_structs.h \
@@ -125,7 +126,8 @@ HEADERS += mainwindow.h \
helpwindow.h \ helpwindow.h \
blfhandler.h \ blfhandler.h \
re/sniffer/SnifferDelegate.h \ re/sniffer/SnifferDelegate.h \
connections/newconnectiondialog.h connections/newconnectiondialog.h \
re/temporalgraphwindow.h
FORMS += ui/candatagrid.ui \ FORMS += ui/candatagrid.ui \
ui/connectionwindow.ui \ ui/connectionwindow.ui \
@@ -153,7 +155,8 @@ FORMS += ui/candatagrid.ui \
ui/bisectwindow.ui \ ui/bisectwindow.ui \
ui/signalviewerwindow.ui \ ui/signalviewerwindow.ui \
helpwindow.ui \ helpwindow.ui \
ui/newconnectiondialog.ui ui/newconnectiondialog.ui \
ui/temporalgraphwindow.ui
DISTFILES += DISTFILES +=
+2
View File
@@ -16,6 +16,7 @@ public:
uint32_t len; uint32_t len;
unsigned char data[8]; unsigned char data[8];
uint64_t timestamp; uint64_t timestamp;
uint64_t timedelta;
uint32_t frameCount; //used in overwrite mode uint32_t frameCount; //used in overwrite mode
friend bool operator<(const CANFrame& l, const CANFrame& r) friend bool operator<(const CANFrame& l, const CANFrame& r)
@@ -32,6 +33,7 @@ public:
isReceived = true; isReceived = true;
len = 0; len = 0;
timestamp = 0; timestamp = 0;
timedelta = 0;
frameCount = 1; frameCount = 1;
} }
}; };
+160 -21
View File
@@ -6,19 +6,6 @@
#include <QDateTime> #include <QDateTime>
#include "utility.h" #include "utility.h"
enum class Column {
TimeStamp = 0, ///< The timestamp when the frame was transmitted or received
FrameId = 1, ///< The frames CAN identifier (Standard: 11 or Extended: 29 bit)
Extended = 2, ///< True if the frames CAN identifier is 29 bit
Remote = 3, ///< True if the frames is a remote frame
Direction = 4, ///< Whether the frame was transmitted or received
Bus = 5, ///< The bus where the frame was transmitted or received
Length = 6, ///< The frames payload data length
ASCII = 7, ///< The payload interpreted as ASCII characters
Data = 8, ///< The frames payload data
NUM_COLUMN
};
CANFrameModel::~CANFrameModel() CANFrameModel::~CANFrameModel()
{ {
frames.clear(); frames.clear();
@@ -26,7 +13,6 @@ CANFrameModel::~CANFrameModel()
filters.clear(); filters.clear();
} }
int CANFrameModel::rowCount(const QModelIndex &parent) const int CANFrameModel::rowCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent); Q_UNUSED(parent);
@@ -82,6 +68,7 @@ CANFrameModel::CANFrameModel(QObject *parent)
needFilterRefresh = false; needFilterRefresh = false;
lastUpdateNumFrames = 0; lastUpdateNumFrames = 0;
timeFormat = "MMM-dd HH:mm:ss.zzz"; timeFormat = "MMM-dd HH:mm:ss.zzz";
sortDirAsc = false;
} }
void CANFrameModel::setHexMode(bool mode) void CANFrameModel::setHexMode(bool mode)
@@ -189,6 +176,119 @@ void CANFrameModel::setAllFilters(bool state)
sendRefresh(); sendRefresh();
} }
/*
* There is probably a more correct way to have done this but below are several functions that collectively implement
* quicksort on the columns and interpret the columns numerically. But, correct or not, this implementation is quite fast
* and sorts the columns properly.
*/
uint64_t CANFrameModel::getCANFrameVal(int row, Column col)
{
uint64_t temp = 0;
if (row >= frames.count()) return 0;
CANFrame frame = frames[row];
switch (col)
{
case Column::TimeStamp:
if (overwriteDups) return frame.timedelta;
return frame.timestamp;
case Column::FrameId:
return frame.ID;
case Column::Extended:
if (frame.extended) return 1;
return 0;
case Column::Remote:
if (overwriteDups) return frame.frameCount;
if (frame.remote) return 1;
return 0;
case Column::Direction:
if (frame.isReceived) return 1;
return 0;
case Column::Bus:
return frame.bus;
case Column::Length:
return frame.len;
case Column::ASCII: //sort both the same for now
case Column::Data:
for (int i = 0; i < frame.len; i++) temp += ((uint64_t)frame.data[i] << (56 - (8 * i)));
//qDebug() << temp;
return temp;
}
}
void CANFrameModel::qSortCANFrameAsc(QVector<CANFrame> *frames, Column column, int lowerBound, int upperBound)
{
int p, i, j;
qDebug() << "Lower " << lowerBound << " Upper" << upperBound;
if (lowerBound < upperBound)
{
uint64_t piv = getCANFrameVal(lowerBound + (upperBound - lowerBound) / 2, column);
i = lowerBound - 1;
j = upperBound + 1;
for (;;){
do {
i++;
} while ((i < upperBound) && getCANFrameVal(i, column) < piv);
do
{
j--;
} while ((j > lowerBound) && getCANFrameVal(j, column) > piv);
if (i < j) {
CANFrame temp = frames->at(i);
frames->replace(i, frames->at(j));
frames->replace(j, temp);
}
else {p = j; break;}
}
qSortCANFrameAsc(frames, column, lowerBound, p);
qSortCANFrameAsc(frames, column, p+1, upperBound);
}
}
void CANFrameModel::qSortCANFrameDesc(QVector<CANFrame> *frames, Column column, int lowerBound, int upperBound)
{
int p, i, j;
qDebug() << "Lower " << lowerBound << " Upper" << upperBound;
if (lowerBound < upperBound)
{
uint64_t piv = getCANFrameVal(lowerBound + (upperBound - lowerBound) / 2, column);
i = lowerBound - 1;
j = upperBound + 1;
for (;;){
do {
i++;
} while ((i < upperBound) && getCANFrameVal(i, column) > piv);
do
{
j--;
} while ((j > lowerBound) && getCANFrameVal(j, column) < piv);
if (i < j) {
CANFrame temp = frames->at(i);
frames->replace(i, frames->at(j));
frames->replace(j, temp);
}
else {p = j; break;}
}
qSortCANFrameDesc(frames, column, lowerBound, p);
qSortCANFrameDesc(frames, column, p+1, upperBound);
}
}
void CANFrameModel::sortByColumn(int column)
{
sortDirAsc = !sortDirAsc;
//beginResetModel();
if (sortDirAsc) qSortCANFrameAsc(&frames, Column(column), 0, frames.count()-1);
else qSortCANFrameDesc(&frames, Column(column), 0, frames.count()-1);
//endResetModel();
sendRefresh();
}
//End of custom sorting code
void CANFrameModel::recalcOverwrite() void CANFrameModel::recalcOverwrite()
{ {
if (!overwriteDups) return; //no need to do a thing if mode is disabled if (!overwriteDups) return; //no need to do a thing if mode is disabled
@@ -202,14 +302,24 @@ void CANFrameModel::recalcOverwrite()
beginResetModel(); beginResetModel();
//Look at the current list of frames and turn it into just a list of unique IDs //Look at the current list of frames and turn it into just a list of unique IDs
QHash<int, CANFrame> overWriteFrames; QHash<uint64_t, CANFrame> overWriteFrames;
uint64_t idAugmented; //id in lower 29 bits, bus number shifted up 29 bits
foreach(CANFrame frame, frames) foreach(CANFrame frame, frames)
{ {
if (!overWriteFrames.contains(frame.ID)) idAugmented = frame.ID;
idAugmented = idAugmented + (frame.bus << 29ull);
if (!overWriteFrames.contains(idAugmented))
{ {
overWriteFrames.insert(frame.ID, frame); frame.timedelta = 0;
frame.frameCount = 1;
overWriteFrames.insert(idAugmented, frame);
}
else
{
frame.timedelta = frame.timestamp - overWriteFrames[idAugmented].timestamp;
frame.frameCount = overWriteFrames[idAugmented].frameCount + 1;
overWriteFrames[idAugmented] = frame;
} }
else overWriteFrames[frame.ID] = frame;
} }
//Then replace the old list of frames with just the unique list //Then replace the old list of frames with just the unique list
frames.clear(); frames.clear();
@@ -283,6 +393,16 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
switch (Column(index.column())) switch (Column(index.column()))
{ {
case Column::TimeStamp: case Column::TimeStamp:
//Reformatting the output a bit with custom code
if (overwriteDups)
{
if (timeSeconds) return QString::number(thisFrame.timedelta / 1000000.0, 'f', 5);
return QString::number(thisFrame.timedelta);
}
else ts = Utility::formatTimestamp(thisFrame.timestamp);
if (ts.type() == QVariant::Double) return QString::number(ts.toDouble(), 'f', 5); //never scientific notation, 5 decimal places
if (ts.type() == QVariant::LongLong) return QString::number(ts.toLongLong()); //never scientific notion, all digits shown
if (ts.type() == QVariant::DateTime) return ts.toDateTime().toString(timeFormat); //custom set format for dates and times
return Utility::formatTimestamp(thisFrame.timestamp); return Utility::formatTimestamp(thisFrame.timestamp);
case Column::FrameId: case Column::FrameId:
return Utility::formatCANID(thisFrame.ID, thisFrame.extended); return Utility::formatCANID(thisFrame.ID, thisFrame.extended);
@@ -378,13 +498,14 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
switch (Column(section)) switch (Column(section))
{ {
case Column::TimeStamp: case Column::TimeStamp:
if (overwriteDups) return QString(tr("Time Delta"));
return QString(tr("Timestamp")); return QString(tr("Timestamp"));
case Column::FrameId: case Column::FrameId:
return QString(tr("ID")); return QString(tr("ID"));
case Column::Extended: case Column::Extended:
return QString(tr("Ext")); return QString(tr("Ext"));
case Column::Remote: case Column::Remote:
if (!overwriteDups) return QString(tr("Rem")); if (!overwriteDups) return QString(tr("RTR"));
return QString(tr("Cnt")); return QString(tr("Cnt"));
case Column::Direction: case Column::Direction:
return QString(tr("Dir")); return QString(tr("Dir"));
@@ -407,6 +528,18 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
return QVariant(); return QVariant();
} }
bool CANFrameModel::any_filters_are_configured(void)
{
for (auto const &val : filters)
{
if (val == true)
continue;
else
return true;
}
return false;
}
void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false) void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false)
{ {
@@ -421,6 +554,10 @@ void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false)
//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(tempFrame.ID)) if (!filters.contains(tempFrame.ID))
{ {
// if there are any filters already configured, leave the new filter disabled
if (any_filters_are_configured())
filters.insert(tempFrame.ID, false);
else
filters.insert(tempFrame.ID, true); filters.insert(tempFrame.ID, true);
needFilterRefresh = true; needFilterRefresh = true;
} }
@@ -441,9 +578,10 @@ void CANFrameModel::addFrame(const 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 == tempFrame.ID) if ( (frames[i].ID == tempFrame.ID) && (frames[i].bus == tempFrame.bus) )
{ {
tempFrame.frameCount = frames[i].frameCount + 1; tempFrame.frameCount = frames[i].frameCount + 1;
tempFrame.timedelta = tempFrame.timestamp - frames[i].timestamp;
frames.replace(i, tempFrame); frames.replace(i, tempFrame);
found = true; found = true;
break; break;
@@ -456,6 +594,7 @@ void CANFrameModel::addFrame(const CANFrame& frame, bool autoRefresh = false)
{ {
if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count(), filteredFrames.count()); if (autoRefresh) beginInsertRows(QModelIndex(), filteredFrames.count(), filteredFrames.count());
tempFrame.frameCount = 1; tempFrame.frameCount = 1;
tempFrame.timedelta = 0;
filteredFrames.append(tempFrame); filteredFrames.append(tempFrame);
if (autoRefresh) endInsertRows(); if (autoRefresh) endInsertRows();
} }
@@ -464,7 +603,7 @@ void CANFrameModel::addFrame(const 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 == tempFrame.ID) if ( (filteredFrames[j].ID == tempFrame.ID) && (filteredFrames[j].bus == tempFrame.bus) )
{ {
if (autoRefresh) beginResetModel(); if (autoRefresh) beginResetModel();
filteredFrames.replace(j, tempFrame); filteredFrames.replace(j, tempFrame);
+20
View File
@@ -10,6 +10,19 @@
#include "dbc/dbchandler.h" #include "dbc/dbchandler.h"
#include "connections/canconnection.h" #include "connections/canconnection.h"
enum class Column {
TimeStamp = 0, ///< The timestamp when the frame was transmitted or received
FrameId = 1, ///< The frames CAN identifier (Standard: 11 or Extended: 29 bit)
Extended = 2, ///< True if the frames CAN identifier is 29 bit
Remote = 3, ///< True if the frames is a remote frame
Direction = 4, ///< Whether the frame was transmitted or received
Bus = 5, ///< The bus where the frame was transmitted or received
Length = 6, ///< The frames payload data length
ASCII = 7, ///< The payload interpreted as ASCII characters
Data = 8, ///< The frames payload data
NUM_COLUMN
};
class CANFrameModel: public QAbstractTableModel class CANFrameModel: public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
@@ -43,6 +56,7 @@ public:
void recalcOverwrite(); void recalcOverwrite();
bool needsFilterRefresh(); bool needsFilterRefresh();
void insertFrames(const QVector<CANFrame> &newFrames); void insertFrames(const QVector<CANFrame> &newFrames);
void sortByColumn(int column);
int getIndexFromTimeID(unsigned int ID, double timestamp); int getIndexFromTimeID(unsigned int ID, double timestamp);
const QVector<CANFrame> *getListReference() const; //thou shalt not modify these frames externally! const QVector<CANFrame> *getListReference() const; //thou shalt not modify these frames externally!
const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO. const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO.
@@ -56,6 +70,11 @@ signals:
void updatedFiltersList(); void updatedFiltersList();
private: private:
void qSortCANFrameAsc(QVector<CANFrame>* frames, Column column, int lowerBound, int upperBound);
void qSortCANFrameDesc(QVector<CANFrame>* frames, Column column, int lowerBound, int upperBound);
uint64_t getCANFrameVal(int row, Column col);
bool any_filters_are_configured(void);
QVector<CANFrame> frames; QVector<CANFrame> frames;
QVector<CANFrame> filteredFrames; QVector<CANFrame> filteredFrames;
QMap<int, bool> filters; QMap<int, bool> filters;
@@ -71,6 +90,7 @@ private:
uint64_t timeOffset; uint64_t timeOffset;
int lastUpdateNumFrames; int lastUpdateNumFrames;
uint32_t preallocSize; uint32_t preallocSize;
bool sortDirAsc;
}; };
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef CONFIG #ifndef CONFIG
#define CONFIG #define CONFIG
#define VERSION 197 #define VERSION 199
//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
+5
View File
@@ -66,6 +66,11 @@ void CANConManager::remove(CANConnection* pConn_p)
mConns.removeOne(pConn_p); mConns.removeOne(pConn_p);
} }
void CANConManager::replace(int idx, CANConnection* pConn_p)
{
mConns.replace(idx, pConn_p);
}
//Get total number of buses currently registered with the program //Get total number of buses currently registered with the program
int CANConManager::getNumBuses() int CANConManager::getNumBuses()
{ {
+1
View File
@@ -17,6 +17,7 @@ public:
void add(CANConnection* pConn_p); void add(CANConnection* pConn_p);
void remove(CANConnection* pConn_p); void remove(CANConnection* pConn_p);
void replace(int idx, CANConnection* pConn_p);
QList<CANConnection*>& getConnections(); QList<CANConnection*>& getConnections();
void stopAllConnections(); void stopAllConnections();
+8
View File
@@ -126,6 +126,14 @@ void CANConnectionModel::remove(CANConnection* pConn_p)
endResetModel(); endResetModel();
} }
void CANConnectionModel::replace(int idx , CANConnection* pConn_p)
{
CANConManager* manager = CANConManager::getInstance();
beginResetModel();
manager->replace(idx, pConn_p);
endResetModel();
}
CANConnection* CANConnectionModel::getAtIdx(int pIdx) const CANConnection* CANConnectionModel::getAtIdx(int pIdx) const
{ {
+1
View File
@@ -25,6 +25,7 @@ public:
void add(CANConnection* pConn_p); void add(CANConnection* pConn_p);
void remove(CANConnection* pConn_p); void remove(CANConnection* pConn_p);
void replace(int idx , CANConnection* pConn_p);
CANConnection* getAtIdx(int) const; CANConnection* getAtIdx(int) const;
void refresh(int pIndex=-1); void refresh(int pIndex=-1);
+53 -24
View File
@@ -55,6 +55,7 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
connect(ui->ckEnableConsole, &QCheckBox::toggled, this, &ConnectionWindow::consoleEnableChanged); connect(ui->ckEnableConsole, &QCheckBox::toggled, this, &ConnectionWindow::consoleEnableChanged);
connect(ui->btnClearDebug, &QPushButton::clicked, this, &ConnectionWindow::handleClearDebugText); connect(ui->btnClearDebug, &QPushButton::clicked, this, &ConnectionWindow::handleClearDebugText);
connect(ui->btnNewConnection, &QPushButton::clicked, this, &ConnectionWindow::handleNewConn); connect(ui->btnNewConnection, &QPushButton::clicked, this, &ConnectionWindow::handleNewConn);
connect(ui->btnResetConn, &QPushButton::clicked, this, &ConnectionWindow::handleResetConn);
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged); connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged);
connect(ui->tabBuses, &QTabBar::currentChanged, this, &ConnectionWindow::currentTabChanged); connect(ui->tabBuses, &QTabBar::currentChanged, this, &ConnectionWindow::currentTabChanged);
connect(ui->btnSaveBus, &QPushButton::clicked, this, &ConnectionWindow::saveBusSettings); connect(ui->btnSaveBus, &QPushButton::clicked, this, &ConnectionWindow::saveBusSettings);
@@ -207,6 +208,53 @@ void ConnectionWindow::handleNewConn()
delete thisDialog; delete thisDialog;
} }
void ConnectionWindow::handleRemoveConn()
{
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
if (selIdx <0) return;
qDebug() << "remove connection at index: " << selIdx;
CANConnection* conn_p = connModel->getAtIdx(selIdx);
if(!conn_p) return;
/* remove connection from model & manager */
connModel->remove(conn_p);
/* stop and delete connection */
conn_p->stop();
delete conn_p;
/* select first connection in list */
ui->tableConnections->selectRow(0);
}
void ConnectionWindow::handleResetConn()
{
QString port, driver;
CANCon::type type;
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
if (selIdx <0) return;
qDebug() << "remove connection at index: " << selIdx;
CANConnection* conn_p = connModel->getAtIdx(selIdx);
if(!conn_p) return;
type = conn_p->getType();
port = conn_p->getPort();
driver = conn_p->getDriver();
/* stop and delete connection */
conn_p->stop();
conn_p = nullptr;
conn_p = create(type, port, driver);
if (conn_p) connModel->replace(selIdx, conn_p);
}
/* status */ /* status */
void ConnectionWindow::connectionStatus(CANConStatus pStatus) void ConnectionWindow::connectionStatus(CANConStatus pStatus)
{ {
@@ -277,8 +325,8 @@ void ConnectionWindow::populateBusDetails(int offset)
return; return;
} }
int busBase = CANConManager::getInstance()->getBusBase(conn_p); //int busBase = CANConManager::getInstance()->getBusBase(conn_p);
ui->lblBusNum->setText(QString::number(busBase + offset)); //ui->lblBusNum->setText(QString::number(busBase + offset));
ui->ckListenOnly->setChecked(bus.isListenOnly()); ui->ckListenOnly->setChecked(bus.isListenOnly());
ui->ckEnable->setChecked(bus.isActive()); ui->ckEnable->setChecked(bus.isActive());
@@ -328,7 +376,9 @@ void ConnectionWindow::currentRowChanged(const QModelIndex &current, const QMode
int numB = ui->tabBuses->count(); int numB = ui->tabBuses->count();
for (int i = 0; i < numB; i++) ui->tabBuses->removeTab(0); for (int i = 0; i < numB; i++) ui->tabBuses->removeTab(0);
if (numBuses > 1) for (int i = 0; i < numBuses; i++) ui->tabBuses->addTab(QString::number(i+1)); int busBase = CANConManager::getInstance()->getBusBase(conn_p);
/*if (numBuses > 1)*/ for (int i = 0; i < numBuses; i++) ui->tabBuses->addTab(QString::number(busBase + i));
populateBusDetails(0); populateBusDetails(0);
if (ui->ckEnableConsole->isChecked()) if (ui->ckEnableConsole->isChecked())
@@ -363,27 +413,6 @@ void ConnectionWindow::handleSendText() {
emit sendDebugData(bytes); emit sendDebugData(bytes);
} }
void ConnectionWindow::handleRemoveConn()
{
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
if (selIdx <0) return;
qDebug() << "remove connection at index: " << selIdx;
CANConnection* conn_p = connModel->getAtIdx(selIdx);
if(!conn_p) return;
/* remove connection from model & manager */
connModel->remove(conn_p);
/* stop and delete connection */
conn_p->stop();
delete conn_p;
/* select first connection in list */
ui->tableConnections->selectRow(0);
}
CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName, QString pDriver) CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName, QString pDriver)
{ {
CANConnection* conn_p; CANConnection* conn_p;
+1
View File
@@ -46,6 +46,7 @@ private slots:
void consoleEnableChanged(bool checked); void consoleEnableChanged(bool checked);
void handleRemoveConn(); void handleRemoveConn();
void handleNewConn(); void handleNewConn();
void handleResetConn();
void handleClearDebugText(); void handleClearDebugText();
void handleSendHex(); void handleSendHex();
void handleSendText(); void handleSendText();
+12 -1
View File
@@ -9,7 +9,18 @@ NewConnectionDialog::NewConnectionDialog(QVector<QString>* ips, QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->rbSocketCAN->setEnabled(isSerialBusAvailable()); if (isSerialBusAvailable())
{
ui->rbSocketCAN->setEnabled(true);
}
else
{
ui->rbSocketCAN->setEnabled(false);
QString errorString;
const QList<QCanBusDeviceInfo> devices = QCanBus::instance()->availableDevices(QStringLiteral("socketcan"), &errorString);
if (!errorString.isEmpty()) ui->rbSocketCAN->setToolTip(errorString);
}
connect(ui->rbGVRET, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbGVRET, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged);
connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged);
+4 -4
View File
@@ -36,7 +36,7 @@ s 5 47 46 45 44 43 42 41 40
So, the bits are 12, 11, 10, 9, 8, 23, 22, 21. Yes, that's confusing. They now go in reverse value order too. So, the bits are 12, 11, 10, 9, 8, 23, 22, 21. Yes, that's confusing. They now go in reverse value order too.
Bit 12 is worth 128, 11 is worth 64, etc until bit 21 is worth 1. Bit 12 is worth 128, 11 is worth 64, etc until bit 21 is worth 1.
*/ */
bool DBC_SIGNAL::processAsText(const CANFrame &frame, QString &outString) bool DBC_SIGNAL::processAsText(const CANFrame &frame, QString &outString, bool outputName)
{ {
int64_t result = 0; int64_t result = 0;
bool isSigned = false; bool isSigned = false;
@@ -95,16 +95,16 @@ bool DBC_SIGNAL::processAsText(const CANFrame &frame, QString &outString)
endResult = (*((double *)(&result)) * factor) + bias; endResult = (*((double *)(&result)) * factor) + bias;
} }
outString = makePrettyOutput(endResult, result); outString = makePrettyOutput(endResult, result, outputName);
cachedValue = endResult; cachedValue = endResult;
return true; return true;
} }
QString DBC_SIGNAL::makePrettyOutput(double floatVal, int64_t intVal) QString DBC_SIGNAL::makePrettyOutput(double floatVal, int64_t intVal, bool outputName)
{ {
QString outputString; QString outputString;
outputString = name + ": "; if (outputName) outputString = name + ": ";
if (valList.count() > 0) //if this is a value list type then look it up and display the proper string if (valList.count() > 0) //if this is a value list type then look it up and display the proper string
{ {
+2 -2
View File
@@ -101,10 +101,10 @@ public: //TODO: this is sloppy. It shouldn't all be public!
QList<DBC_ATTRIBUTE_VALUE> attributes; QList<DBC_ATTRIBUTE_VALUE> attributes;
QList<DBC_VAL_ENUM_ENTRY> valList; QList<DBC_VAL_ENUM_ENTRY> valList;
bool processAsText(const CANFrame &frame, QString &outString); bool processAsText(const CANFrame &frame, QString &outString, bool outputName = true);
bool processAsInt(const CANFrame &frame, int32_t &outValue); bool processAsInt(const CANFrame &frame, int32_t &outValue);
bool processAsDouble(const CANFrame &frame, double &outValue); bool processAsDouble(const CANFrame &frame, double &outValue);
QString makePrettyOutput(double floatVal, int64_t intVal); QString makePrettyOutput(double floatVal, int64_t intVal, bool outputName = true);
DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name); DBC_ATTRIBUTE_VALUE *findAttrValByName(QString name);
DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx); DBC_ATTRIBUTE_VALUE *findAttrValByIdx(int idx);
}; };
+12 -1
View File
@@ -7,6 +7,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QApplication> #include <QApplication>
#include <QPalette> #include <QPalette>
#include <QSettings>
#include "utility.h" #include "utility.h"
#include "connections/canconmanager.h" #include "connections/canconmanager.h"
@@ -460,10 +461,14 @@ DBC_SIGNAL* DBCFile::parseSignalLine(QString line, DBC_MESSAGE *msg)
if (!sig.receiver) sig.receiver = findNodeByIdx(0); //apply default if there was no match if (!sig.receiver) sig.receiver = findNodeByIdx(0); //apply default if there was no match
sig.parentMessage = msg; sig.parentMessage = msg;
if (msg)
{
msg->sigHandler->addSignal(sig); msg->sigHandler->addSignal(sig);
if (isMultiplexor) msg->multiplexorSignal = msg->sigHandler->findSignalByName(sig.name); if (isMultiplexor) msg->multiplexorSignal = msg->sigHandler->findSignalByName(sig.name);
return msg->sigHandler->findSignalByName(sig.name); return msg->sigHandler->findSignalByName(sig.name);
} }
else return nullptr;
}
return nullptr; return nullptr;
} }
@@ -1335,6 +1340,8 @@ void DBCFile::saveFile(QString fileName)
void DBCHandler::saveDBCFile(int idx) void DBCHandler::saveDBCFile(int idx)
{ {
QSettings settings;
if (loadedFiles.count() == 0) return; if (loadedFiles.count() == 0) return;
if (idx < 0) return; if (idx < 0) return;
if (idx >= loadedFiles.count()) return; if (idx >= loadedFiles.count()) return;
@@ -1345,6 +1352,7 @@ void DBCHandler::saveDBCFile(int idx)
QStringList filters; QStringList filters;
filters.append(QString(tr("DBC File (*.dbc)"))); filters.append(QString(tr("DBC File (*.dbc)")));
dialog.setDirectory(settings.value("DBC/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -1356,6 +1364,7 @@ void DBCHandler::saveDBCFile(int idx)
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
if (!filename.contains('.')) filename += ".dbc"; if (!filename.contains('.')) filename += ".dbc";
loadedFiles[idx].saveFile(filename); loadedFiles[idx].saveFile(filename);
settings.setValue("DBC/LoadSaveDirectory", dialog.directory().path());
} }
} }
@@ -1407,10 +1416,12 @@ DBCFile* DBCHandler::loadDBCFile(int idx)
QString filename; QString filename;
QFileDialog dialog; QFileDialog dialog;
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("DBC File (*.dbc)"))); filters.append(QString(tr("DBC File (*.dbc)")));
dialog.setDirectory(settings.value("DBC/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -1422,7 +1433,7 @@ DBCFile* DBCHandler::loadDBCFile(int idx)
DBCFile newFile; DBCFile newFile;
newFile.loadFile(filename); newFile.loadFile(filename);
loadedFiles.append(newFile); loadedFiles.append(newFile);
settings.setValue("DBC/LoadSaveDirectory", dialog.directory().path());
return &loadedFiles.last(); return &loadedFiles.last();
} }
+6
View File
@@ -15,6 +15,8 @@ DBCLoadSaveWindow::DBCLoadSaveWindow(const QVector<CANFrame> *frames, QWidget *p
ui->setupUi(this); ui->setupUi(this);
inhibitCellProcessing = false;
QStringList header; QStringList header;
header << "Filename" << "Associated Bus" << "J1939"; header << "Filename" << "Associated Bus" << "J1939";
ui->tableFiles->setColumnCount(3); ui->tableFiles->setColumnCount(3);
@@ -159,6 +161,7 @@ void DBCLoadSaveWindow::editFile()
void DBCLoadSaveWindow::cellChanged(int row, int col) void DBCLoadSaveWindow::cellChanged(int row, int col)
{ {
if (inhibitCellProcessing) return;
if (col == 1) //the bus column if (col == 1) //the bus column
{ {
DBCFile *file = dbcHandler->getFileByIdx(row); DBCFile *file = dbcHandler->getFileByIdx(row);
@@ -214,6 +217,7 @@ void DBCLoadSaveWindow::swapTableRows(bool up)
const int destIdx = (up ? idx-1 : idx+1); const int destIdx = (up ? idx-1 : idx+1);
Q_ASSERT(destIdx >= 0 && destIdx < ui->tableFiles->rowCount()); Q_ASSERT(destIdx >= 0 && destIdx < ui->tableFiles->rowCount());
inhibitCellProcessing = true;
// take whole rows // take whole rows
QList<QTableWidgetItem*> sourceItems = takeRow(idx); QList<QTableWidgetItem*> sourceItems = takeRow(idx);
QList<QTableWidgetItem*> destItems = takeRow(destIdx); QList<QTableWidgetItem*> destItems = takeRow(destIdx);
@@ -221,6 +225,8 @@ void DBCLoadSaveWindow::swapTableRows(bool up)
// set back in reverse order // set back in reverse order
setRow(idx, destItems); setRow(idx, destItems);
setRow(destIdx, sourceItems); setRow(destIdx, sourceItems);
inhibitCellProcessing = false;
} }
QList<QTableWidgetItem*> DBCLoadSaveWindow::takeRow(int row) QList<QTableWidgetItem*> DBCLoadSaveWindow::takeRow(int row)
+1
View File
@@ -35,6 +35,7 @@ private:
DBCFile *currentlyEditingFile; DBCFile *currentlyEditingFile;
const QVector<CANFrame> *referenceFrames; const QVector<CANFrame> *referenceFrames;
DBCMainEditor *editorWindow; DBCMainEditor *editorWindow;
bool inhibitCellProcessing;
void swapTableRows(bool up); void swapTableRows(bool up);
QList<QTableWidgetItem*> takeRow(int row); QList<QTableWidgetItem*> takeRow(int row);
Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

+22
View File
@@ -0,0 +1,22 @@
Temporal Window
=================
.
.. image:: ./images/TemporalWindow.png
Using the Temporal Window
=========================
This window gives a dual graphical representation of CAN IDs over time. For each frame in the capture a circle is placed
on the graph at a point given by the time when the frame came in on the X axis and the frame ID on the Y axis. That is, a frame with ID 0x300
that comes in at 23.543 seconds would be plotted at the point 23.543, 0x300. The graph background is color coded for "density." That brings up
the question "What do you mean by density?" The answer is somewhat nebulous but essentially the color coded density maps where there is a lot of
traffic within a small space on the graph. This could be because many frames with the same ID came in rapid fire or it could be because many
frames with similar IDs came in very close to each other - or both.
The general point of this window is to show how active the bus is at any given point in time and which IDs are most active (they'll create
bright streaks in the background color). There isn't a lot that can be done to modify the functionality of this window. All that can be done is
zooming and panning the view. If you get the view too messed up the R key will reset the view back to standard. As with the Graphing Window, it is
possible to select just the X or Y axis and zoom/pan that axis without affecting the other one. To do so, click on the axis marks of the axis you'd like
to independently control. To control both again click in the graph itself.
+10
View File
@@ -4,6 +4,7 @@
#include <QProgressDialog> #include <QProgressDialog>
#include <QDateTime> #include <QDateTime>
#include <QtEndian> #include <QtEndian>
#include <QSettings>
#include <iostream> #include <iostream>
#include "utility.h" #include "utility.h"
@@ -19,6 +20,7 @@ bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* fram
{ {
QString filename; QString filename;
QFileDialog dialog(qApp->activeWindow()); QFileDialog dialog(qApp->activeWindow());
QSettings settings;
bool result = false; bool result = false;
QStringList filters; QStringList filters;
@@ -35,6 +37,7 @@ bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* fram
filters.append(QString(tr("Cabana Log(*.csv *.CSV)"))); filters.append(QString(tr("Cabana Log(*.csv *.CSV)")));
filters.append(QString(tr("CANalyzer Ascii Log (*.asc *.ASC)"))); filters.append(QString(tr("CANalyzer Ascii Log (*.asc *.ASC)")));
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -125,6 +128,7 @@ bool FrameFileIO::saveFrameFile(QString &fileName, const QVector<CANFrame>* fram
{ {
QStringList fileList = filename.split('/'); QStringList fileList = filename.split('/');
fileName = fileList[fileList.length() - 1]; fileName = fileList[fileList.length() - 1];
settings.setValue("FileIO/LoadSaveDirectory", dialog.directory().path());
return true; return true;
} }
return false; return false;
@@ -136,6 +140,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
{ {
QString filename; QString filename;
QFileDialog dialog; QFileDialog dialog;
QSettings settings;
bool result = false; bool result = false;
QStringList filters; QStringList filters;
@@ -159,6 +164,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
filters.append(QString(tr("Cabana Log (*.csv *.CSV)"))); filters.append(QString(tr("Cabana Log (*.csv *.CSV)")));
filters.append(QString(tr("CANOpen Magic (*.csv *.CSV)"))); filters.append(QString(tr("CANOpen Magic (*.csv *.CSV)")));
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -203,6 +209,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
{ {
QStringList fileList = filename.split('/'); QStringList fileList = filename.split('/');
fileName = fileList[fileList.length() - 1]; fileName = fileList[fileList.length() - 1];
settings.setValue("FileIO/LoadSaveDirectory", dialog.directory().path());
return true; return true;
} }
else else
@@ -1575,10 +1582,12 @@ bool FrameFileIO::openContinuousNative()
{ {
QString filename; QString filename;
QFileDialog dialog(qApp->activeWindow()); QFileDialog dialog(qApp->activeWindow());
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("GVRET Logs (*.csv *.CSV)"))); filters.append(QString(tr("GVRET Logs (*.csv *.CSV)")));
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -1595,6 +1604,7 @@ bool FrameFileIO::openContinuousNative()
} }
continuousFile.write("Time Stamp,ID,Extended,Dir,Bus,LEN,D1,D2,D3,D4,D5,D6,D7,D8"); continuousFile.write("Time Stamp,ID,Extended,Dir,Bus,LEN,D1,D2,D3,D4,D5,D6,D7,D8");
continuousFile.write("\n"); continuousFile.write("\n");
settings.setValue("FileIO/LoadSaveDirectory", dialog.directory().path());
return true; return true;
} }
return false; return false;
+6
View File
@@ -173,10 +173,12 @@ void FramePlaybackWindow::saveFilters()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Filter list (*.ftl)"))); filters.append(QString(tr("Filter list (*.ftl)")));
dialog.setDirectory(settings.value("Filters/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -203,6 +205,7 @@ void FramePlaybackWindow::saveFilters()
} }
outFile->close(); outFile->close();
dialog.setDirectory(settings.value("Filters/LoadSaveDirectory", dialog.directory().path()).toString());
} }
} }
@@ -212,10 +215,12 @@ void FramePlaybackWindow::loadFilters()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Filter List (*.ftl)"))); filters.append(QString(tr("Filter List (*.ftl)")));
dialog.setDirectory(settings.value("Filters/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -264,6 +269,7 @@ void FramePlaybackWindow::loadFilters()
} }
} }
inFile->close(); inFile->close();
dialog.setDirectory(settings.value("Filters/LoadSaveDirectory", dialog.directory().path()).toString());
} }
} }
+6 -1
View File
@@ -241,10 +241,12 @@ void FrameSenderWindow::saveGrid()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Frame Sender Definition (*.fsd)"))); filters.append(QString(tr("Frame Sender Definition (*.fsd)")));
dialog.setDirectory(settings.value("FrameSender/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -258,6 +260,7 @@ void FrameSenderWindow::saveGrid()
{ {
if (!filename.contains('.')) filename += ".fsd"; if (!filename.contains('.')) filename += ".fsd";
saveSenderFile(filename); saveSenderFile(filename);
settings.setValue("FrameSender/LoadSaveDirectory", dialog.directory().path());
} }
} }
} }
@@ -266,10 +269,12 @@ void FrameSenderWindow::loadGrid()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Frame Sender Definition (*.fsd)"))); filters.append(QString(tr("Frame Sender Definition (*.fsd)")));
dialog.setDirectory(settings.value("FrameSender/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -281,6 +286,7 @@ void FrameSenderWindow::loadGrid()
if (dialog.selectedNameFilter() == filters[0]) if (dialog.selectedNameFilter() == filters[0])
{ {
loadSenderFile(filename); loadSenderFile(filename);
settings.setValue("FrameSender/LoadSaveDirectory", dialog.directory().path());
} }
} }
@@ -325,7 +331,6 @@ void FrameSenderWindow::saveSenderFile(QString filename)
outFile->close(); outFile->close();
delete outFile; delete outFile;
} }
void FrameSenderWindow::loadSenderFile(QString filename) void FrameSenderWindow::loadSenderFile(QString filename)
+6
View File
@@ -5,6 +5,12 @@ int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
//These things are used by QSettings to set up setting storage
a.setOrganizationName("EVTV");
a.setApplicationName("SavvyCAN");
a.setOrganizationDomain("evtv.me");
QSettings::setDefaultFormat(QSettings::IniFormat);
MainWindow w; MainWindow w;
QSettings settings; QSettings settings;
+44 -45
View File
@@ -6,6 +6,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::MainSettingsDialog) ui(new Ui::MainSettingsDialog)
{ {
QSettings settings;
ui->setupUi(this); ui->setupUi(this);
ui->comboSendingBus->addItem(tr("None")); ui->comboSendingBus->addItem(tr("None"));
@@ -14,29 +15,27 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
ui->comboSendingBus->addItem(tr("Both")); ui->comboSendingBus->addItem(tr("Both"));
ui->comboSendingBus->addItem(tr("From File")); ui->comboSendingBus->addItem(tr("From File"));
settings = new QSettings();
//update the GUI with all the settings we have stored giving things //update the GUI with all the settings we have stored giving things
//defaults if nothing was stored (if this is the first time) //defaults if nothing was stored (if this is the first time)
ui->cbDisplayHex->setChecked(settings->value("Main/UseHex", true).toBool()); ui->cbDisplayHex->setChecked(settings.value("Main/UseHex", true).toBool());
ui->cbFlowAutoRef->setChecked(settings->value("FlowView/AutoRef", false).toBool()); ui->cbFlowAutoRef->setChecked(settings.value("FlowView/AutoRef", false).toBool());
ui->cbFlowUseTimestamp->setChecked(settings->value("FlowView/UseTimestamp", true).toBool()); ui->cbFlowUseTimestamp->setChecked(settings.value("FlowView/UseTimestamp", true).toBool());
ui->cbInfoAutoExpand->setChecked(settings->value("InfoCompare/AutoExpand", false).toBool()); ui->cbInfoAutoExpand->setChecked(settings.value("InfoCompare/AutoExpand", false).toBool());
ui->cbMainAutoScroll->setChecked(settings->value("Main/AutoScroll", false).toBool()); ui->cbMainAutoScroll->setChecked(settings.value("Main/AutoScroll", false).toBool());
ui->cbPlaybackLoop->setChecked(settings->value("Playback/AutoLoop", false).toBool()); ui->cbPlaybackLoop->setChecked(settings.value("Playback/AutoLoop", false).toBool());
ui->cbRestorePositions->setChecked(settings->value("Main/SaveRestorePositions", true).toBool()); ui->cbRestorePositions->setChecked(settings.value("Main/SaveRestorePositions", true).toBool());
ui->cbValidate->setChecked(settings->value("Main/ValidateComm", true).toBool()); ui->cbValidate->setChecked(settings.value("Main/ValidateComm", true).toBool());
ui->spinPlaybackSpeed->setValue(settings->value("Playback/DefSpeed", 5).toInt()); ui->spinPlaybackSpeed->setValue(settings.value("Playback/DefSpeed", 5).toInt());
ui->lineClockFormat->setText(settings->value("Main/TimeFormat", "MMM-dd HH:mm:ss.zzz").toString()); ui->lineClockFormat->setText(settings.value("Main/TimeFormat", "MMM-dd HH:mm:ss.zzz").toString());
ui->lineRemoteHost->setText(settings->value("Remote/Host", "api.savvycan.com").toString()); ui->lineRemoteHost->setText(settings.value("Remote/Host", "api.savvycan.com").toString());
ui->lineRemotePort->setText(settings->value("Remote/Port", "21315").toString()); // = 0x5343 = SC. Yep, really creative port number ui->lineRemotePort->setText(settings.value("Remote/Port", "21315").toString()); // = 0x5343 = SC. Yep, really creative port number
ui->cbAutoStartRemote->setChecked(settings->value("Remote/AutoStart", false).toBool()); ui->cbAutoStartRemote->setChecked(settings.value("Remote/AutoStart", false).toBool());
ui->cbLoadConnections->setChecked(settings->value("Main/SaveRestoreConnections", false).toBool()); ui->cbLoadConnections->setChecked(settings.value("Main/SaveRestoreConnections", false).toBool());
ui->spinFontSize->setValue(settings->value("Main/FontSize", ui->cbDisplayHex->font().pointSize()).toUInt()); ui->spinFontSize->setValue(settings.value("Main/FontSize", ui->cbDisplayHex->font().pointSize()).toUInt());
bool secondsMode = settings->value("Main/TimeSeconds", false).toBool(); bool secondsMode = settings.value("Main/TimeSeconds", false).toBool();
bool clockMode = settings->value("Main/TimeClock", false).toBool(); bool clockMode = settings.value("Main/TimeClock", false).toBool();
if (clockMode) if (clockMode)
{ {
ui->rbSeconds->setChecked(false); ui->rbSeconds->setChecked(false);
@@ -59,9 +58,9 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
} }
} }
ui->comboSendingBus->setCurrentIndex(settings->value("Playback/SendingBus", 4).toInt()); ui->comboSendingBus->setCurrentIndex(settings.value("Playback/SendingBus", 4).toInt());
ui->cbUseFiltered->setChecked(settings->value("Main/UseFiltered", false).toBool()); ui->cbUseFiltered->setChecked(settings.value("Main/UseFiltered", false).toBool());
ui->cbUseOpenGL->setChecked(settings->value("Main/UseOpenGL", false).toBool()); ui->cbUseOpenGL->setChecked(settings.value("Main/UseOpenGL", false).toBool());
//just for simplicity they all call the same function and that function updates all settings at once //just for simplicity they all call the same function and that function updates all settings at once
connect(ui->cbDisplayHex, SIGNAL(toggled(bool)), this, SLOT(updateSettings())); connect(ui->cbDisplayHex, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
@@ -90,7 +89,6 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
MainSettingsDialog::~MainSettingsDialog() MainSettingsDialog::~MainSettingsDialog()
{ {
delete ui; delete ui;
delete settings;
} }
void MainSettingsDialog::closeEvent(QCloseEvent *event) void MainSettingsDialog::closeEvent(QCloseEvent *event)
@@ -98,7 +96,6 @@ void MainSettingsDialog::closeEvent(QCloseEvent *event)
Q_UNUSED(event); Q_UNUSED(event);
removeEventFilter(this); removeEventFilter(this);
updateSettings(); updateSettings();
settings->sync();
} }
bool MainSettingsDialog::eventFilter(QObject *obj, QEvent *event) bool MainSettingsDialog::eventFilter(QObject *obj, QEvent *event)
@@ -122,27 +119,29 @@ bool MainSettingsDialog::eventFilter(QObject *obj, QEvent *event)
void MainSettingsDialog::updateSettings() void MainSettingsDialog::updateSettings()
{ {
settings->setValue("Main/UseHex", ui->cbDisplayHex->isChecked()); QSettings settings;
settings->setValue("FlowView/AutoRef", ui->cbFlowAutoRef->isChecked());
settings->setValue("FlowView/UseTimestamp", ui->cbFlowUseTimestamp->isChecked());
settings->setValue("InfoCompare/AutoExpand", ui->cbInfoAutoExpand->isChecked());
settings->setValue("Main/AutoScroll", ui->cbMainAutoScroll->isChecked());
settings->setValue("Playback/AutoLoop", ui->cbPlaybackLoop->isChecked());
settings->setValue("Main/SaveRestorePositions", ui->cbRestorePositions->isChecked());
settings->setValue("Main/SaveRestoreConnections", ui->cbLoadConnections->isChecked());
settings->setValue("Main/ValidateComm", ui->cbValidate->isChecked());
settings->setValue("Playback/DefSpeed", ui->spinPlaybackSpeed->value());
settings->setValue("Main/TimeSeconds", ui->rbSeconds->isChecked());
settings->setValue("Main/TimeClock", ui->rbSysClock->isChecked());
settings->setValue("Playback/SendingBus", ui->comboSendingBus->currentIndex());
settings->setValue("Main/UseFiltered", ui->cbUseFiltered->isChecked());
settings->setValue("Main/UseOpenGL", ui->cbUseOpenGL->isChecked());
settings->setValue("Main/TimeFormat", ui->lineClockFormat->text());
settings->setValue("Main/FontSize", ui->spinFontSize->value());
settings->setValue("Remote/Host", ui->lineRemoteHost->text());
settings->setValue("Remote/Port", ui->lineRemotePort->text());
settings->setValue("Remote/AutoStart", ui->cbAutoStartRemote->isChecked());
settings->sync(); settings.setValue("Main/UseHex", ui->cbDisplayHex->isChecked());
settings.setValue("FlowView/AutoRef", ui->cbFlowAutoRef->isChecked());
settings.setValue("FlowView/UseTimestamp", ui->cbFlowUseTimestamp->isChecked());
settings.setValue("InfoCompare/AutoExpand", ui->cbInfoAutoExpand->isChecked());
settings.setValue("Main/AutoScroll", ui->cbMainAutoScroll->isChecked());
settings.setValue("Playback/AutoLoop", ui->cbPlaybackLoop->isChecked());
settings.setValue("Main/SaveRestorePositions", ui->cbRestorePositions->isChecked());
settings.setValue("Main/SaveRestoreConnections", ui->cbLoadConnections->isChecked());
settings.setValue("Main/ValidateComm", ui->cbValidate->isChecked());
settings.setValue("Playback/DefSpeed", ui->spinPlaybackSpeed->value());
settings.setValue("Main/TimeSeconds", ui->rbSeconds->isChecked());
settings.setValue("Main/TimeClock", ui->rbSysClock->isChecked());
settings.setValue("Playback/SendingBus", ui->comboSendingBus->currentIndex());
settings.setValue("Main/UseFiltered", ui->cbUseFiltered->isChecked());
settings.setValue("Main/UseOpenGL", ui->cbUseOpenGL->isChecked());
settings.setValue("Main/TimeFormat", ui->lineClockFormat->text());
settings.setValue("Main/FontSize", ui->spinFontSize->value());
settings.setValue("Remote/Host", ui->lineRemoteHost->text());
settings.setValue("Remote/Port", ui->lineRemotePort->text());
settings.setValue("Remote/AutoStart", ui->cbAutoStartRemote->isChecked());
settings.sync();
emit updatedSettings(); emit updatedSettings();
} }
-1
View File
@@ -24,7 +24,6 @@ public slots:
private: private:
Ui::MainSettingsDialog *ui; Ui::MainSettingsDialog *ui;
QSettings *settings;
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event);
+34 -13
View File
@@ -34,11 +34,6 @@ MainWindow::MainWindow(QWidget *parent) :
useHex = true; useHex = true;
//These things are used by QSettings to set up setting storage
QCoreApplication::setOrganizationName("EVTV");
QCoreApplication::setOrganizationDomain("evtv.me");
QCoreApplication::setApplicationName("SavvyCAN");
selfRef = this; selfRef = this;
this->setWindowTitle("Savvy CAN V" + QString::number(VERSION)); this->setWindowTitle("Savvy CAN V" + QString::number(VERSION));
@@ -55,9 +50,9 @@ MainWindow::MainWindow(QWidget *parent) :
readSettings(); readSettings();
QHeaderView *verticalHeader = ui->canFramesView->verticalHeader(); //QHeaderView *verticalHeader = ui->canFramesView->verticalHeader();
verticalHeader->setSectionResizeMode(QHeaderView::Fixed); //verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
verticalHeader->setDefaultSectionSize(10); //verticalHeader->setDefaultSectionSize(10);
QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader(); QHeaderView *HorzHdr = ui->canFramesView->horizontalHeader();
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int))); connect(HorzHdr, SIGNAL(sectionClicked(int)), this, SLOT(headerClicked(int)));
@@ -83,6 +78,7 @@ MainWindow::MainWindow(QWidget *parent) :
snifferWindow = nullptr; snifferWindow = nullptr;
bisectWindow = nullptr; bisectWindow = nullptr;
signalViewerWindow = nullptr; signalViewerWindow = nullptr;
temporalGraphWindow = nullptr;
dbcHandler = DBCHandler::getReference(); dbcHandler = DBCHandler::getReference();
bDirty = false; bDirty = false;
inhibitFilterUpdate = false; inhibitFilterUpdate = false;
@@ -131,6 +127,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow); connect(ui->actionCapture_Bisector, &QAction::triggered, this, &MainWindow::showBisectWindow);
connect(ui->actionSignal_Viewer, &QAction::triggered, this, &MainWindow::showSignalViewer); connect(ui->actionSignal_Viewer, &QAction::triggered, this, &MainWindow::showSignalViewer);
connect(ui->actionSave_Continuous_Logfile, &QAction::triggered, this, &MainWindow::handleContinousLogging); connect(ui->actionSave_Continuous_Logfile, &QAction::triggered, this, &MainWindow::handleContinousLogging);
connect(ui->actionTemporal_Graph, &QAction::triggered, this, &MainWindow::showTemporalGraphWindow);
connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames); connect(CANConManager::getInstance(), &CANConManager::framesReceived, model, &CANFrameModel::addFrames);
@@ -186,7 +183,6 @@ MainWindow::MainWindow(QWidget *parent) :
//so if you want to enable them and play with them then go for it. //so if you want to enable them and play with them then go for it.
ui->actionFirmware_Update->setVisible(false); ui->actionFirmware_Update->setVisible(false);
ui->actionMotorControlConfig->setVisible(false); ui->actionMotorControlConfig->setVisible(false);
ui->actionSignal_Viewer->setVisible(false);
ui->actionSingle_Multi_State_2->setVisible(false); ui->actionSingle_Multi_State_2->setVisible(false);
installEventFilter(this); installEventFilter(this);
@@ -227,6 +223,7 @@ void MainWindow::killEmAll()
killWindow(motorctrlConfigWindow); killWindow(motorctrlConfigWindow);
killWindow(signalViewerWindow); killWindow(signalViewerWindow);
killWindow(connectionWindow); killWindow(connectionWindow);
killWindow(temporalGraphWindow);
} }
//forcefully close the window, kill it, and salt the earth //forcefully close the window, kill it, and salt the earth
@@ -368,7 +365,8 @@ void MainWindow::updateConnectionSettings(QString connectionType, QString port,
void MainWindow::headerClicked(int logicalIndex) void MainWindow::headerClicked(int logicalIndex)
{ {
ui->canFramesView->sortByColumn(logicalIndex); //ui->canFramesView->sortByColumn(logicalIndex);
model->sortByColumn(logicalIndex);
} }
void MainWindow::gridClicked(QModelIndex idx) void MainWindow::gridClicked(QModelIndex idx)
@@ -647,10 +645,12 @@ void MainWindow::handleSaveFilters()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Filter list (*.ftl)"))); filters.append(QString(tr("Filter list (*.ftl)")));
dialog.setDirectory(settings.value("Filters/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -661,6 +661,7 @@ void MainWindow::handleSaveFilters()
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
if (!filename.contains('.')) filename += ".ftl"; if (!filename.contains('.')) filename += ".ftl";
if (dialog.selectedNameFilter() == filters[0]) model->saveFilterFile(filename); if (dialog.selectedNameFilter() == filters[0]) model->saveFilterFile(filename);
settings.setValue("Filters/LoadSaveDirectory", dialog.directory().path());
} }
} }
@@ -668,10 +669,12 @@ void MainWindow::handleLoadFilters()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Filter List (*.ftl)"))); filters.append(QString(tr("Filter List (*.ftl)")));
dialog.setDirectory(settings.value("Filters/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -681,19 +684,20 @@ void MainWindow::handleLoadFilters()
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
//right now there is only one file type that can be loaded here so just do it. //right now there is only one file type that can be loaded here so just do it.
model->loadFilterFile(filename); model->loadFilterFile(filename);
settings.setValue("Filters/LoadSaveDirectory", dialog.directory().path());
} }
} }
//lbStatusDatabase.setText(fileList[fileList.length() - 1] + tr(" loaded."));
void MainWindow::handleSaveDecoded() void MainWindow::handleSaveDecoded()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Text File (*.txt)"))); filters.append(QString(tr("Text File (*.txt)")));
dialog.setDirectory(settings.value("FileIO/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -704,6 +708,7 @@ void MainWindow::handleSaveDecoded()
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
if (!filename.contains('.')) filename += ".txt"; if (!filename.contains('.')) filename += ".txt";
saveDecodedTextFile(filename); saveDecodedTextFile(filename);
settings.setValue("FileIO/LoadSaveDirectory", dialog.directory().path());
} }
} }
@@ -837,6 +842,19 @@ void MainWindow::showGraphingWindow()
graphingWindow->show(); graphingWindow->show();
} }
void MainWindow::showTemporalGraphWindow()
{
//only create an instance of the object if we dont have one. Otherwise just display the existing one.
if (!temporalGraphWindow)
{
if (!useFiltered)
temporalGraphWindow = new TemporalGraphWindow(model->getListReference());
else
temporalGraphWindow = new TemporalGraphWindow(model->getFilteredListReference());
}
temporalGraphWindow->show();
}
void MainWindow::showFrameDataAnalysis() void MainWindow::showFrameDataAnalysis()
{ {
//only create an instance of the object if we dont have one. Otherwise just display the existing one. //only create an instance of the object if we dont have one. Otherwise just display the existing one.
@@ -1015,7 +1033,10 @@ void MainWindow::showSignalViewer()
{ {
if (!signalViewerWindow) if (!signalViewerWindow)
{ {
signalViewerWindow = new SignalViewerWindow(); if (!useFiltered)
signalViewerWindow = new SignalViewerWindow(model->getListReference());
else
signalViewerWindow = new SignalViewerWindow(model->getFilteredListReference());
} }
signalViewerWindow->show(); signalViewerWindow->show();
} }
+3
View File
@@ -31,6 +31,7 @@
#include "re/isotp_interpreterwindow.h" #include "re/isotp_interpreterwindow.h"
#include "motorcontrollerconfigwindow.h" #include "motorcontrollerconfigwindow.h"
#include "signalviewerwindow.h" #include "signalviewerwindow.h"
#include "re/temporalgraphwindow.h"
class CANConnection; class CANConnection;
class ConnectionWindow; class ConnectionWindow;
@@ -81,6 +82,7 @@ private slots:
void showSnifferWindow(); void showSnifferWindow();
void showBisectWindow(); void showBisectWindow();
void showSignalViewer(); void showSignalViewer();
void showTemporalGraphWindow();
void exitApp(); void exitApp();
void handleSaveDecoded(); void handleSaveDecoded();
void connectionStatusUpdated(int conns); void connectionStatusUpdated(int conns);
@@ -159,6 +161,7 @@ private:
MotorControllerConfigWindow *motorctrlConfigWindow; MotorControllerConfigWindow *motorctrlConfigWindow;
BisectWindow* bisectWindow; BisectWindow* bisectWindow;
SignalViewerWindow *signalViewerWindow; SignalViewerWindow *signalViewerWindow;
TemporalGraphWindow *temporalGraphWindow;
//various private storage //various private storage
QLabel lbStatusConnected; QLabel lbStatusConnected;
+3
View File
@@ -367,6 +367,7 @@ void FileComparatorWindow::saveDetails()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Text File (*.txt)"))); filters.append(QString(tr("Text File (*.txt)")));
@@ -375,10 +376,12 @@ void FileComparatorWindow::saveDetails()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("FileComparator/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
settings.setValue("FileComparator/LoadSaveDirectory", dialog.directory().path());
if (!filename.contains('.')) filename += ".txt"; if (!filename.contains('.')) filename += ".txt";
QFile *outFile = new QFile(filename); QFile *outFile = new QFile(filename);
+6
View File
@@ -297,6 +297,7 @@ void FlowViewWindow::saveFileGraph()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("PDF Files (*.pdf)"))); filters.append(QString(tr("PDF Files (*.pdf)")));
@@ -307,6 +308,7 @@ void FlowViewWindow::saveFileGraph()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("FlowView/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
@@ -327,6 +329,7 @@ void FlowViewWindow::saveFileGraph()
if (!filename.contains('.')) filename += ".jpg"; if (!filename.contains('.')) filename += ".jpg";
ui->graphView->saveJpg(filename, 1024, 768); ui->graphView->saveJpg(filename, 1024, 768);
} }
settings.setValue("FlowView/LoadSaveDirectory", dialog.directory().path());
} }
} }
@@ -334,6 +337,7 @@ void FlowViewWindow::saveFileFlow()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("PNG Files (*.png)"))); filters.append(QString(tr("PNG Files (*.png)")));
@@ -343,6 +347,7 @@ void FlowViewWindow::saveFileFlow()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("FlowView/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
@@ -358,6 +363,7 @@ void FlowViewWindow::saveFileFlow()
if (!filename.contains('.')) filename += ".jpg"; if (!filename.contains('.')) filename += ".jpg";
ui->flowView->saveImage(filename, 1024, 768); ui->flowView->saveImage(filename, 1024, 768);
} }
settings.setValue("FlowView/LoadSaveDirectory", dialog.directory().path());
} }
} }
+3
View File
@@ -477,6 +477,7 @@ void FrameInfoWindow::saveDetails()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Text File (*.txt)"))); filters.append(QString(tr("Text File (*.txt)")));
@@ -485,9 +486,11 @@ void FrameInfoWindow::saveDetails()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("FrameInfo/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
settings.setValue("FrameInfo/LoadSaveDirectory", dialog.directory().path());
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
if (!filename.contains('.')) filename += ".txt"; if (!filename.contains('.')) filename += ".txt";
if (dialog.selectedNameFilter() == filters[0]) if (dialog.selectedNameFilter() == filters[0])
+21 -2
View File
@@ -81,7 +81,7 @@ GraphingWindow::GraphingWindow(const QVector<CANFrame> *frames, QWidget *parent)
selectedPen.setWidth(1); selectedPen.setWidth(1);
selectedPen.setColor(Qt::blue); selectedPen.setColor(Qt::blue);
ui->graphingView->setAttribute(Qt::WA_AcceptTouchEvents); //ui->graphingView->setAttribute(Qt::WA_AcceptTouchEvents);
if (useOpenGL) if (useOpenGL)
{ {
@@ -245,11 +245,15 @@ void GraphingWindow::plottableDoubleClick(QCPAbstractPlottable* plottable, int d
double x, y; double x, y;
QCPGraph *graph = reinterpret_cast<QCPGraph *>(plottable); QCPGraph *graph = reinterpret_cast<QCPGraph *>(plottable);
graph->pixelsToCoords(event->localPos(), x, y); graph->pixelsToCoords(event->localPos(), x, y);
locationText->setText("X: " + QString::number(x) + " Y: " + QString::number(y)); x = ui->graphingView->xAxis->pixelToCoord(event->localPos().x());
itemTracer->setGraph(graph); itemTracer->setGraph(graph);
itemTracer->setVisible(true); itemTracer->setVisible(true);
itemTracer->setInterpolating(true);
itemTracer->setGraphKey(x); itemTracer->setGraphKey(x);
itemTracer->updatePosition();
qDebug() << "val " << itemTracer->position->value();
locationText->setText("X: " + QString::number(x) + " Y: " + QString::number(itemTracer->position->value()));
} }
void GraphingWindow::gotCenterTimeID(int32_t ID, double timestamp) void GraphingWindow::gotCenterTimeID(int32_t ID, double timestamp)
@@ -629,6 +633,7 @@ void GraphingWindow::saveGraphs()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("PDF Files (*.pdf)"))); filters.append(QString(tr("PDF Files (*.pdf)")));
@@ -639,10 +644,12 @@ void GraphingWindow::saveGraphs()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("Graphing/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
if (dialog.selectedNameFilter() == filters[0]) if (dialog.selectedNameFilter() == filters[0])
{ {
@@ -666,6 +673,7 @@ void GraphingWindow::saveSpreadsheet()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Spreadsheet (*.csv)"))); filters.append(QString(tr("Spreadsheet (*.csv)")));
@@ -674,10 +682,13 @@ void GraphingWindow::saveSpreadsheet()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("Graphing/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
if (!filename.contains('.')) filename += ".csv"; if (!filename.contains('.')) filename += ".csv";
QFile *outFile = new QFile(filename); QFile *outFile = new QFile(filename);
@@ -785,6 +796,7 @@ void GraphingWindow::saveDefinitions()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Graph definition (*.gdf)"))); filters.append(QString(tr("Graph definition (*.gdf)")));
@@ -793,10 +805,13 @@ void GraphingWindow::saveDefinitions()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("Graphing/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
if (!filename.contains('.')) filename += ".gdf"; if (!filename.contains('.')) filename += ".gdf";
QFile *outFile = new QFile(filename); QFile *outFile = new QFile(filename);
@@ -843,6 +858,7 @@ void GraphingWindow::loadDefinitions()
{ {
QString filename; QString filename;
QFileDialog dialog; QFileDialog dialog;
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Graph definition (*.gdf)"))); filters.append(QString(tr("Graph definition (*.gdf)")));
@@ -853,10 +869,13 @@ void GraphingWindow::loadDefinitions()
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setDirectory(settings.value("Graphing/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
settings.setValue("Graphing/LoadSaveDirectory", dialog.directory().path());
QFile *inFile = new QFile(filename); QFile *inFile = new QFile(filename);
QByteArray line; QByteArray line;
+21 -11
View File
@@ -93,8 +93,8 @@ void NewGraphDialog::checkSignalAgreement()
GraphParams testingParams; GraphParams testingParams;
bool bAgree = true; bool bAgree = true;
bool sigSigned = false; bool sigSigned = false;
DBC_SIGNAL *sig; DBC_SIGNAL *sig = nullptr;
DBC_MESSAGE *msg; DBC_MESSAGE *msg = nullptr;
if (dbcHandler == nullptr) return; if (dbcHandler == nullptr) return;
if (dbcHandler->getFileCount() == 0) return; if (dbcHandler->getFileCount() == 0) return;
@@ -104,6 +104,11 @@ void NewGraphDialog::checkSignalAgreement()
{ {
sig = msg->sigHandler->findSignalByName(ui->cbSignals->currentText()); sig = msg->sigHandler->findSignalByName(ui->cbSignals->currentText());
} }
else
{
ui->lblMsgStatus->setText("Msg ID doesn't exist in DBC");
return;
}
if (sig) if (sig)
{ {
@@ -118,13 +123,19 @@ void NewGraphDialog::checkSignalAgreement()
testingParams.numBits = dataLen; testingParams.numBits = dataLen;
if (testingParams.ID != msg->ID) bAgree = false; if (testingParams.ID != msg->ID) bAgree = false;
if (abs(testingParams.bias - sig->bias) > 0.01) bAgree = false; if (fabs(testingParams.bias - sig->bias) > 0.01) bAgree = false;
if (testingParams.isSigned != sigSigned) bAgree = false; if (testingParams.isSigned != sigSigned) bAgree = false;
if (testingParams.intelFormat != sig->intelByteOrder) bAgree = false; if (testingParams.intelFormat != sig->intelByteOrder) bAgree = false;
if (abs(testingParams.scale - sig->factor) > 0.01) bAgree = false; if (fabs(testingParams.scale - sig->factor) > 0.01) bAgree = false;
if (testingParams.startBit != sig->startBit) bAgree = false; if (testingParams.startBit != sig->startBit) bAgree = false;
if (testingParams.numBits != sig->signalSize) bAgree = false; if (testingParams.numBits != sig->signalSize) bAgree = false;
} }
else
{
ui->lblMsgStatus->setText("Signal name doesn't exist in DBC");
return;
}
if (bAgree) if (bAgree)
{ {
ui->lblMsgStatus->setText("Graph params match this signal"); ui->lblMsgStatus->setText("Graph params match this signal");
@@ -214,21 +225,19 @@ void NewGraphDialog::loadMessages()
if (assocSignal && msg->name == assocSignal->parentMessage->name) if (assocSignal && msg->name == assocSignal->parentMessage->name)
{ {
ui->cbMessages->setCurrentIndex(ui->cbMessages->count() -1); ui->cbMessages->setCurrentIndex(ui->cbMessages->count() -1);
qDebug() << "Found my parent"; //qDebug() << "Found my parent";
} }
} }
} }
} }
ui->cbMessages->model()->sort(0);
} }
void NewGraphDialog::loadSignals(int idx) void NewGraphDialog::loadSignals(int idx)
{ {
Q_UNUSED(idx); Q_UNUSED(idx);
//messages were placed into the list in the same order as they exist //search through all DBC files in order to try to find a message with the given name
//in the data structure so it should have been possible to just DBC_MESSAGE *msg = dbcHandler->findMessage(ui->cbMessages->currentText());
//look it up based on index but by name is probably safer and this operation
//is not time critical at all.
DBC_MESSAGE *msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByName(ui->cbMessages->currentText());
DBC_SIGNAL *sig; DBC_SIGNAL *sig;
if (msg == NULL) return; if (msg == NULL) return;
@@ -243,10 +252,11 @@ void NewGraphDialog::loadSignals(int idx)
if (assocSignal && sig->name == assocSignal->name) if (assocSignal && sig->name == assocSignal->name)
{ {
ui->cbSignals->setCurrentIndex(ui->cbSignals->count() - 1); ui->cbSignals->setCurrentIndex(ui->cbSignals->count() - 1);
qDebug() << "Found me"; //qDebug() << "Found me";
} }
} }
} }
ui->cbSignals->model()->sort(0);
checkSignalAgreement(); checkSignalAgreement();
} }
+407
View File
@@ -0,0 +1,407 @@
#include "temporalgraphwindow.h"
#include "ui_temporalgraphwindow.h"
#include "helpwindow.h"
#include "mainwindow.h"
QString HexTicker::getTickLabel (double tick, const QLocale& locale, QChar formatChar, int precision)
{
int valu = static_cast<int>(tick);
//qDebug() << valu;
return "0x" + QString::number(valu, 16).toUpper().rightJustified(3,'0');
}
TemporalGraphWindow::TemporalGraphWindow(const QVector<CANFrame> *frames, QWidget *parent) :
QDialog(parent),
ui(new Ui::TemporalGraphWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::Window);
readSettings();
modelFrames = frames;
ui->graphingView->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes);
ui->graphingView->xAxis->setRange(0, 8);
ui->graphingView->yAxis->setRange(0, 255);
ui->graphingView->axisRect()->setupFullAxesBox();
ui->graphingView->xAxis->setLabel("Elapsed Time");
ui->graphingView->yAxis->setLabel("ID");
ui->graphingView->xAxis->setNumberFormat("f");
ui->graphingView->xAxis->setNumberPrecision(6);
HexTicker *tick = new HexTicker;
QSharedPointer<QCPAxisTicker> sharedTicker(tick);
tick->setTickCount(10);
ui->graphingView->yAxis->setTicker(sharedTicker);
// connect slot that ties some axis selections together (especially opposite axes):
connect(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
connect(ui->graphingView, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress()));
connect(ui->graphingView, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
// make bottom and left axes transfer their ranges to top and right axes:
connect(ui->graphingView->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->graphingView->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->graphingView->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->graphingView->yAxis2, SLOT(setRange(QCPRange)));
if (useOpenGL)
{
ui->graphingView->setAntialiasedElements(QCP::aeAll);
//ui->graphingView->setNoAntialiasingOnDrag(true);
ui->graphingView->setOpenGl(true);
}
else
{
ui->graphingView->setOpenGl(false);
ui->graphingView->setAntialiasedElements(QCP::aeNone);
}
}
TemporalGraphWindow::~TemporalGraphWindow()
{
delete ui;
}
void TemporalGraphWindow::showEvent(QShowEvent* event)
{
QDialog::showEvent(event);
installEventFilter(this);
readSettings();
generateGraph();
ui->graphingView->replot();
}
void TemporalGraphWindow::closeEvent(QCloseEvent *event)
{
Q_UNUSED(event);
removeEventFilter(this);
writeSettings();
}
void TemporalGraphWindow::readSettings()
{
QSettings settings;
if (settings.value("Main/SaveRestorePositions", false).toBool())
{
resize(settings.value("Temporal/WindowSize", QSize(800, 600)).toSize());
move(settings.value("Temporal/WindowPos", QPoint(50, 50)).toPoint());
}
useOpenGL = settings.value("Main/UseOpenGL", false).toBool();
}
void TemporalGraphWindow::writeSettings()
{
QSettings settings;
if (settings.value("Main/SaveRestorePositions", false).toBool())
{
settings.setValue("Temporal/WindowSize", size());
settings.setValue("Temporal/WindowPos", pos());
}
}
void TemporalGraphWindow::updatedFrames(int numFrames)
{
CANFrame thisFrame;
QVector<double> x, y;
bool appendedToGraph = false;
bool needReplot = false;
if (numFrames == -1) //all frames deleted. Kill the display
{
//removeAllGraphs();
//now instead of removing the graphs regenerate them which will blank them out but leave them there in case
//more traffic that matches comes in or someone otherwise loads more data
ui->graphingView->clearGraphs(); //temporarily remove the graphs from the graph view
ui->graphingView->clearPlottables();
ui->graphingView->replot(); //now, redisplay them all
}
else if (numFrames == -2) //all new set of frames. Reset
{
//there shouldn't be any need to actually remove the graphs.
//regenerate them instead
ui->graphingView->clearGraphs(); //temporarily remove the graphs from the graph view
//needScaleSetup = true;
generateGraph();
//ui->graphingView->replot(); //now, redisplay them all
}
else //just got some new frames. See if they are relevant.
{
if (numFrames > modelFrames->count()) return;
appendedToGraph = false;
x.clear();
y.clear();
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
{
thisFrame = modelFrames->at(i);
/*
if (graphParams[j].ID == thisFrame.ID)
{
appendToGraph(graphParams[j], thisFrame, x, y);
appendedToGraph = true;
}*/
}
if (appendedToGraph)
{
//graphParams[j].ref->addData(x, y);
needReplot = true;
}
if (needReplot)
{
if (followGraphEnd)
{
//find the current X span and maintain that span but move the end of it over to match the new end
//of the actual graph. This causes the view to move with the data to always show the end
QCPRange range = ui->graphingView->xAxis->range();
double size = range.size();
bool foundRange;
QCPRange keyRange = ui->graphingView->graph()->getKeyRange(foundRange);
if (foundRange)
{
double end, start;
end = keyRange.upper;
start = end - size;
ui->graphingView->xAxis->setRange(start, end);
}
}
ui->graphingView->replot();
}
}
}
void TemporalGraphWindow::generateGraph()
{
if (modelFrames->count() == 0) return;
ui->graphingView->clearGraphs();
ui->graphingView->clearPlottables();
qDebug() << "Regenerating the graph";
ui->graphingView->addGraph();
graph = ui->graphingView->graph();
QVector<double> x, y;
int frameCount = modelFrames->count();
x.reserve(frameCount);
y.reserve(frameCount);
xminval = xmaxval = modelFrames->at(0).timestamp / 1000000.0;
yminval = ymaxval = modelFrames->at(0).ID;
for (int i = 0; i < frameCount; i++)
{
x.append(modelFrames->at(i).timestamp / 1000000.0);
y.append(modelFrames->at(i).ID);
if (x[i] > xmaxval) xmaxval = x[i];
if (x[i] < xminval) xminval = x[i];
if (y[i] > ymaxval) ymaxval = y[i];
if (y[i] < yminval) yminval = y[i];
}
ui->graphingView->graph()->setData(x,y);
ui->graphingView->graph()->setLineStyle(QCPGraph::lsNone); //no lines
ui->graphingView->graph()->setScatterStyle(QCPScatterStyle::ssCircle);
QPen graphPen;
graphPen.setColor(Qt::blue);
graphPen.setWidth(2);
ui->graphingView->graph()->setPen(graphPen);
qDebug() << "xmin: " << xminval;
qDebug() << "xmax: " << xmaxval;
qDebug() << "ymin: " << yminval;
qDebug() << "ymax: " << ymaxval;
ui->graphingView->xAxis->setRange(xminval, xmaxval);
ui->graphingView->yAxis->setRange(yminval, ymaxval);
ui->graphingView->axisRect()->setupFullAxesBox();
ui->graphingView->replot();
QCPColorMap *colorMap = new QCPColorMap(ui->graphingView->xAxis, ui->graphingView->yAxis);
int ySize = static_cast<int>(ymaxval - yminval) / 30 + 1;
int xSize = static_cast<int>((xmaxval - xminval) * 4.0) + 1;
colorMap->data()->setSize(xSize, ySize);
colorMap->data()->setRange(QCPRange(xminval, xmaxval), QCPRange(yminval, ymaxval));
for (int x = 0; x < xSize; ++x)
{
for (int y = 0; y < ySize; ++y)
{
colorMap->data()->setAlpha(x, y, 180);
colorMap->data()->setCell(x, y, 0.0);
}
}
for (int i = 0; i < frameCount; i++)
{
int x = static_cast<int>(((modelFrames->at(i).timestamp / 1000000.0) - xminval) * 4.0);
int y = static_cast<int>(modelFrames->at(i).ID - yminval) / 30;
double val = colorMap->data()->cell(x, y);
double inc;
inc = 1 / (val + 1); //logarithmic decay
inc = inc * inc; //square the increment to make it even more stark
val = val + inc;
qDebug() << "X: " << x << " Y: " << y << "Val: " << val;
colorMap->data()->setCell(x, y, val);
}
colorMap->setGradient(QCPColorGradient::gpJet);
colorMap->rescaleDataRange(true);
ui->graphingView->rescaleAxes();
ui->graphingView->replot();
}
void TemporalGraphWindow::selectionChanged()
{
/*
normally, axis base line, axis tick labels and axis labels are selectable separately, but we want
the user only to be able to select the axis as a whole, so we tie the selected states of the tick labels
and the axis base line together. However, the axis label shall be selectable individually.
The selection state of the left and right axes shall be synchronized as well as the state of the
bottom and top axes.
Further, we want to synchronize the selection of the graphs with the selection state of the respective
legend item belonging to that graph. So the user can select a graph by either clicking on the graph itself
or on its legend item.
*/
qDebug() << "SelectionChanged";
// make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
ui->graphingView->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
{
ui->graphingView->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
ui->graphingView->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
}
// make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
ui->graphingView->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->graphingView->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels))
{
ui->graphingView->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
ui->graphingView->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
}
}
void TemporalGraphWindow::mousePress()
{
// if an axis is selected, only allow the direction of that axis to be dragged
// if no axis is selected, both directions may be dragged
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
{
ui->graphingView->axisRect()->setRangeDrag(ui->graphingView->xAxis->orientation());
}
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
{
ui->graphingView->axisRect()->setRangeDrag(ui->graphingView->yAxis->orientation());
}
else
{
ui->graphingView->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
}
}
void TemporalGraphWindow::mouseWheel()
{
qDebug() << "Mouse WHeel";
// if an axis is selected, only allow the direction of that axis to be zoomed
// if no axis is selected, both directions may be zoomed
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
ui->graphingView->axisRect()->setRangeZoom(ui->graphingView->xAxis->orientation());
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
ui->graphingView->axisRect()->setRangeZoom(ui->graphingView->yAxis->orientation());
else
ui->graphingView->axisRect()->setRangeZoom(Qt::Horizontal|Qt::Vertical);
}
bool TemporalGraphWindow::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyRelease) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
switch (keyEvent->key())
{
case Qt::Key_Plus:
zoomIn();
break;
case Qt::Key_Minus:
zoomOut();
break;
case Qt::Key_R:
resetView();
break;
case Qt::Key_F1:
HelpWindow::getRef()->showHelp("temporalwindow.html");
break;
}
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
return false;
}
void TemporalGraphWindow::resetView()
{
ui->graphingView->xAxis->setRange(xminval, xmaxval);
ui->graphingView->yAxis->setRange(yminval, ymaxval);
ui->graphingView->axisRect()->setupFullAxesBox();
ui->graphingView->replot();
}
void TemporalGraphWindow::zoomIn()
{
QCPRange xrange = ui->graphingView->xAxis->range();
QCPRange yrange = ui->graphingView->yAxis->range();
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
{
ui->graphingView->xAxis->scaleRange(0.666, xrange.center());
}
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
{
ui->graphingView->yAxis->scaleRange(0.666, yrange.center());
}
else
{
ui->graphingView->xAxis->scaleRange(0.666, xrange.center());
ui->graphingView->yAxis->scaleRange(0.666, yrange.center());
}
ui->graphingView->replot();
}
void TemporalGraphWindow::zoomOut()
{
QCPRange xrange = ui->graphingView->xAxis->range();
QCPRange yrange = ui->graphingView->yAxis->range();
if (ui->graphingView->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
{
ui->graphingView->xAxis->scaleRange(1.5, xrange.center());
}
else if (ui->graphingView->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
{
ui->graphingView->yAxis->scaleRange(1.5, yrange.center());
}
else
{
ui->graphingView->xAxis->scaleRange(1.5, xrange.center());
ui->graphingView->yAxis->scaleRange(1.5, yrange.center());
}
ui->graphingView->replot();
}
+50
View File
@@ -0,0 +1,50 @@
#ifndef TEMPORALGRAPHWINDOW_H
#define TEMPORALGRAPHWINDOW_H
#include <QDialog>
#include "qcustomplot.h"
#include "can_structs.h"
namespace Ui {
class TemporalGraphWindow;
}
class HexTicker : public QCPAxisTicker
{
QString getTickLabel (double tick, const QLocale& locale, QChar formatChar, int precision);
};
class TemporalGraphWindow : public QDialog
{
Q_OBJECT
public:
explicit TemporalGraphWindow(const QVector<CANFrame> *, QWidget *parent = nullptr);
~TemporalGraphWindow();
void showEvent(QShowEvent*);
private slots:
void updatedFrames(int);
void mousePress();
void mouseWheel();
void resetView();
void zoomIn();
void zoomOut();
void selectionChanged();
private:
Ui::TemporalGraphWindow *ui;
const QVector<CANFrame> *modelFrames;
bool useOpenGL;
bool followGraphEnd;
QCPGraph *graph;
double xminval, xmaxval, yminval, ymaxval;
void closeEvent(QCloseEvent *event);
bool eventFilter(QObject *obj, QEvent *event);
void readSettings();
void writeSettings();
void generateGraph();
};
#endif // TEMPORALGRAPHWINDOW_H
+4
View File
@@ -145,6 +145,7 @@ void UDSScanWindow::saveResults()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Text File (*.txt)"))); filters.append(QString(tr("Text File (*.txt)")));
@@ -153,10 +154,13 @@ void UDSScanWindow::saveResults()
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setAcceptMode(QFileDialog::AcceptSave);
dialog.setDirectory(settings.value("UDSScan/LoadSaveDirectory", dialog.directory().path()).toString());
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
filename = dialog.selectedFiles()[0]; filename = dialog.selectedFiles()[0];
settings.setValue("UDSScan/LoadSaveDirectory", dialog.directory().path());
if (!filename.contains('.')) filename += ".txt"; if (!filename.contains('.')) filename += ".txt";
if (dialog.selectedNameFilter() == filters[0]) if (dialog.selectedNameFilter() == filters[0])
{ {
+6
View File
@@ -180,11 +180,13 @@ void ScriptingWindow::loadNewScript()
{ {
QString filename; QString filename;
QFileDialog dialog; QFileDialog dialog;
QSettings settings;
ScriptContainer *container; ScriptContainer *container;
QStringList filters; QStringList filters;
filters.append(QString(tr("Javascript File (*.js)"))); filters.append(QString(tr("Javascript File (*.js)")));
dialog.setDirectory(settings.value("ScriptingWindow/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::ExistingFile); dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -215,6 +217,7 @@ void ScriptingWindow::loadNewScript()
ui->listLoadedScripts->setCurrentRow(ui->listLoadedScripts->count() - 1); ui->listLoadedScripts->setCurrentRow(ui->listLoadedScripts->count() - 1);
changeCurrentScript(); changeCurrentScript();
settings.setValue("ScriptingWindow/LoadSaveDirectory", dialog.directory().path());
} }
} }
} }
@@ -287,10 +290,12 @@ void ScriptingWindow::saveScript()
{ {
QString filename; QString filename;
QFileDialog dialog(this); QFileDialog dialog(this);
QSettings settings;
QStringList filters; QStringList filters;
filters.append(QString(tr("Javascript File (*.js)"))); filters.append(QString(tr("Javascript File (*.js)")));
dialog.setDirectory(settings.value("ScriptingWindow/LoadSaveDirectory", dialog.directory().path()).toString());
dialog.setFileMode(QFileDialog::AnyFile); dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters); dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail); dialog.setViewMode(QFileDialog::Detail);
@@ -312,6 +317,7 @@ void ScriptingWindow::saveScript()
outFile->write(editor->toPlainText().toUtf8()); outFile->write(editor->toPlainText().toUtf8());
outFile->close(); outFile->close();
delete outFile; delete outFile;
settings.setValue("ScriptingWindow/LoadSaveDirectory", dialog.directory().path());
} }
} }
} }
+79 -8
View File
@@ -1,14 +1,18 @@
#include "signalviewerwindow.h" #include "signalviewerwindow.h"
#include "ui_signalviewerwindow.h" #include "ui_signalviewerwindow.h"
#include "helpwindow.h" #include "helpwindow.h"
#include "mainwindow.h"
#include <QDebug>
SignalViewerWindow::SignalViewerWindow(QWidget *parent) : SignalViewerWindow::SignalViewerWindow(const QVector<CANFrame> *frames, QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::SignalViewerWindow) ui(new Ui::SignalViewerWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowFlags(Qt::Window); setWindowFlags(Qt::Window);
modelFrames = frames;
QStringList headers; QStringList headers;
headers << "Signal" << "Value"; headers << "Signal" << "Value";
ui->tableViewer->setHorizontalHeaderLabels(headers); ui->tableViewer->setHorizontalHeaderLabels(headers);
@@ -21,6 +25,8 @@ SignalViewerWindow::SignalViewerWindow(QWidget *parent) :
connect(ui->cbMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSignals(int))); connect(ui->cbMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSignals(int)));
connect(ui->btnAdd, SIGNAL(clicked(bool)), this, SLOT(addSignal())); connect(ui->btnAdd, SIGNAL(clicked(bool)), this, SLOT(addSignal()));
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
connect(ui->btnRemove, SIGNAL(clicked(bool)), this, SLOT(removeSelectedSignal()));
loadMessages(); loadMessages();
} }
@@ -30,14 +36,79 @@ SignalViewerWindow::~SignalViewerWindow()
delete ui; delete ui;
} }
void SignalViewerWindow::updatedFrames(int numFrames)
{
CANFrame thisFrame;
if (numFrames == -1) //all frames deleted. Don't care
{
}
else if (numFrames == -2) //all new set of frames. Reset
{
for (int i = 0; i < modelFrames->count(); i++)
{
thisFrame = modelFrames->at(i);
processFrame(thisFrame);
}
}
else //just got some new frames. See if they are relevant.
{
if (numFrames > modelFrames->count()) return;
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
{
thisFrame = modelFrames->at(i);
processFrame(thisFrame);
}
}
}
void SignalViewerWindow::processFrame(CANFrame &frame)
{
QString sigString;
DBC_SIGNAL *sig;
for (int i = 0; i < signalList.count(); i++)
{
sig = signalList.at(i);
if (!sig) return;
if (sig->parentMessage->ID == frame.ID)
{
if (sig->processAsText(frame, sigString, false)) //if true we could interpret the signal so update it in the list
{
QTableWidgetItem *item = ui->tableViewer->item(i, 1);
if (!item)
{
item = new QTableWidgetItem(sigString);
ui->tableViewer->setItem(i, 1, item);
}
else item->setText(sigString);
}
}
}
}
void SignalViewerWindow::removeSelectedSignal()
{
int selRow = ui->tableViewer->currentRow();
if (selRow < 0) return; //no selected row
signalList.removeAt(selRow);
ui->tableViewer->removeRow(selRow);
}
void SignalViewerWindow::loadMessages() void SignalViewerWindow::loadMessages()
{ {
int numFiles;
ui->cbMessages->clear(); ui->cbMessages->clear();
if (dbcHandler == NULL) return; if (dbcHandler == nullptr) return;
if (dbcHandler->getFileCount() == 0) dbcHandler->createBlankFile(); if ((numFiles = dbcHandler->getFileCount()) == 0) return;
for (int x = 0; x < dbcHandler->getFileByIdx(0)->messageHandler->getCount(); x++) qDebug() << numFiles;
for (int f = 0; f < numFiles; f++)
{ {
ui->cbMessages->addItem(dbcHandler->getFileByIdx(0)->messageHandler->findMsgByIdx(x)->name); qDebug() << dbcHandler->getFileByIdx(f)->messageHandler->getCount();
for (int x = 0; x < dbcHandler->getFileByIdx(f)->messageHandler->getCount(); x++)
{
ui->cbMessages->addItem(dbcHandler->getFileByIdx(f)->messageHandler->findMsgByIdx(x)->name);
}
} }
} }
@@ -48,9 +119,9 @@ void SignalViewerWindow::loadSignals(int idx)
//in the data structure so it should have been possible to just //in the data structure so it should have been possible to just
//look it up based on index but by name is probably safer and this operation //look it up based on index but by name is probably safer and this operation
//is not time critical at all. //is not time critical at all.
DBC_MESSAGE *msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByName(ui->cbMessages->currentText()); DBC_MESSAGE *msg = dbcHandler->findMessage(ui->cbMessages->currentText());
if (msg == NULL) return; if (msg == nullptr) return;
ui->cbSignals->clear(); ui->cbSignals->clear();
for (int x = 0; x < msg->sigHandler->getCount(); x++) for (int x = 0; x < msg->sigHandler->getCount(); x++)
{ {
@@ -60,7 +131,7 @@ void SignalViewerWindow::loadSignals(int idx)
void SignalViewerWindow::addSignal() void SignalViewerWindow::addSignal()
{ {
DBC_MESSAGE *msg = dbcHandler->getFileByIdx(0)->messageHandler->findMsgByName(ui->cbMessages->currentText()); DBC_MESSAGE *msg = dbcHandler->findMessage(ui->cbMessages->currentText());
if (!msg) return; if (!msg) return;
DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(ui->cbSignals->currentText()); DBC_SIGNAL *sig = msg->sigHandler->findSignalByName(ui->cbSignals->currentText());
if (!sig) return; if (!sig) return;
+6 -1
View File
@@ -13,19 +13,24 @@ class SignalViewerWindow : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit SignalViewerWindow(QWidget *parent = 0); explicit SignalViewerWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
~SignalViewerWindow(); ~SignalViewerWindow();
private slots: private slots:
void loadMessages(); void loadMessages();
void loadSignals(int idx); void loadSignals(int idx);
void addSignal(); void addSignal();
void removeSelectedSignal();
void updatedFrames(int);
private: private:
Ui::SignalViewerWindow *ui; Ui::SignalViewerWindow *ui;
DBCHandler *dbcHandler; DBCHandler *dbcHandler;
QList<DBC_SIGNAL *> signalList; QList<DBC_SIGNAL *> signalList;
const QVector<CANFrame> *modelFrames;
void processFrame(CANFrame &frame);
}; };
#endif // SIGNALVIEWERWINDOW_H #endif // SIGNALVIEWERWINDOW_H
+13 -20
View File
@@ -43,6 +43,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="btnResetConn">
<property name="text">
<string>Reset Selected Device</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="btnDisconnect"> <widget class="QPushButton" name="btnDisconnect">
<property name="text"> <property name="text">
@@ -68,58 +75,44 @@
<item> <item>
<layout class="QFormLayout" name="formLayout_2"> <layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>CAN Bus Number:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblBusNum">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Speed:</string> <string>Speed:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="cbBusSpeed"/> <widget class="QComboBox" name="cbBusSpeed"/>
</item> </item>
<item row="2" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_11"> <widget class="QLabel" name="label_11">
<property name="text"> <property name="text">
<string>Listen Only:</string> <string>Listen Only:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="1">
<widget class="QCheckBox" name="ckListenOnly"> <widget class="QCheckBox" name="ckListenOnly">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_14"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string>Enable Bus:</string> <string>Enable Bus:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="2" column="1">
<widget class="QCheckBox" name="ckEnable"> <widget class="QCheckBox" name="ckEnable">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="3" column="1">
<widget class="QPushButton" name="btnSaveBus"> <widget class="QPushButton" name="btnSaveBus">
<property name="text"> <property name="text">
<string>Save Bus Settings</string> <string>Save Bus Settings</string>
+7 -1
View File
@@ -282,6 +282,7 @@
<addaction name="actionSniffer"/> <addaction name="actionSniffer"/>
<addaction name="actionCapture_Bisector"/> <addaction name="actionCapture_Bisector"/>
<addaction name="actionSignal_Viewer"/> <addaction name="actionSignal_Viewer"/>
<addaction name="actionTemporal_Graph"/>
</widget> </widget>
<widget class="QMenu" name="menuSend_Frames"> <widget class="QMenu" name="menuSend_Frames">
<property name="title"> <property name="title">
@@ -424,7 +425,7 @@
</action> </action>
<action name="actionSetup"> <action name="actionSetup">
<property name="text"> <property name="text">
<string>Open Connection WIndow</string> <string>Open Connection Window</string>
</property> </property>
</action> </action>
<action name="actionConnect"> <action name="actionConnect">
@@ -497,6 +498,11 @@
<string>Start Continuous Logging</string> <string>Start Continuous Logging</string>
</property> </property>
</action> </action>
<action name="actionTemporal_Graph">
<property name="text">
<string>Temporal Graph</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources/> <resources/>
+11
View File
@@ -14,6 +14,8 @@
<string>Signal Viewer</string> <string>Signal Viewer</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,1"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="3,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QTableWidget" name="tableViewer"> <widget class="QTableWidget" name="tableViewer">
<property name="columnCount"> <property name="columnCount">
@@ -32,6 +34,15 @@
<column/> <column/>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="btnRemove">
<property name="text">
<string>Remove Selected Signal</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TemporalGraphWindow</class>
<widget class="QDialog" name="TemporalGraphWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>886</width>
<height>683</height>
</rect>
</property>
<property name="windowTitle">
<string>Temporal Graph</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCustomPlot" name="graphingView" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>