Much work on custom frame sender window. It is reasonably functional now and tested for timed sending

This commit is contained in:
Collin Kidder
2015-08-16 20:00:35 -04:00
parent 3ec7638e7b
commit 3f5d8b6159
4 changed files with 380 additions and 274 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
#ifndef CONFIG
#define CONFIG
#define VERSION 132
#define VERSION 133
//try to keep this in sync.
//SavvyCAN will complain if you connect a GVRET board with a revision
//less than this number.
#define CURRENT_GVRET_VER 322
#define CURRENT_GVRET_VER 323
#endif // CONFIG
+352 -266
View File
@@ -2,6 +2,17 @@
#include "ui_framesenderwindow.h"
#include "utility.h"
#include <QFileDialog>
#include <QDebug>
#include "mainwindow.h"
/*
* notes: need to ensure that you grab pointers when modifying data structures and dont
* make copies. Also, check # of ms elapsed since last tick since they don't tend to come in at 1ms
* intervals like we asked.
* Also, rows default to enabled which is odd because the button state does not reflect that.
*/
FrameSenderWindow::FrameSenderWindow(const QVector<CANFrame> *frames, QWidget *parent) :
QDialog(parent),
ui(new Ui::FrameSenderWindow)
@@ -16,35 +27,295 @@ FrameSenderWindow::FrameSenderWindow(const QVector<CANFrame> *frames, QWidget *p
QStringList headers;
headers << "En" << "Bus" << "ID" << "Len" << "Data" << "Trigger" << "Modifications" << "Count";
ui->tableSender->setColumnCount(8);
ui->tableSender->setColumnWidth(0, 40);
ui->tableSender->setColumnWidth(1, 40);
ui->tableSender->setColumnWidth(2, 40);
ui->tableSender->setColumnWidth(3, 40);
ui->tableSender->setColumnWidth(4, 200);
ui->tableSender->setColumnWidth(5, 200);
ui->tableSender->setColumnWidth(6, 200);
ui->tableSender->setColumnWidth(0, 50);
ui->tableSender->setColumnWidth(1, 50);
ui->tableSender->setColumnWidth(2, 50);
ui->tableSender->setColumnWidth(3, 50);
ui->tableSender->setColumnWidth(4, 220);
ui->tableSender->setColumnWidth(5, 220);
ui->tableSender->setColumnWidth(6, 220);
ui->tableSender->setColumnWidth(7, 80);
ui->tableSender->setHorizontalHeaderLabels(headers);
ui->tableSender->insertRow(0);
createBlankRow();
connect(ui->tableSender, SIGNAL(cellChanged(int,int)), this, SLOT(onCellChanged(int,int)));
connect(intervalTimer, SIGNAL(timeout()), this, SLOT(handleTick()));
connect(ui->btnClearGrid, SIGNAL(clicked(bool)), this, SLOT(clearGrid()));
connect(ui->btnDisableAll, SIGNAL(clicked(bool)), this, SLOT(disableAll()));
connect(ui->btnEnableAll, SIGNAL(clicked(bool)), this, SLOT(enableAll()));
connect(ui->btnLoadGrid, SIGNAL(clicked(bool)), this, SLOT(loadGrid()));
connect(ui->btnSaveGrid, SIGNAL(clicked(bool)), this, SLOT(saveGrid()));
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
intervalTimer->start();
elapsedTimer.start();
}
FrameSenderWindow::~FrameSenderWindow()
{
delete ui;
intervalTimer->stop();
intervalTimer->stop();
delete intervalTimer;
}
void FrameSenderWindow::createBlankRow()
{
int row = ui->tableSender->rowCount();
ui->tableSender->insertRow(row);
QTableWidgetItem *item = new QTableWidgetItem();
item->setFlags(item->flags() |Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
inhibitChanged = true;
ui->tableSender->setItem(row, 0, item);
for (int i = 1; i < 8; i++)
{
item = new QTableWidgetItem("");
ui->tableSender->setItem(row, i, item);
}
inhibitChanged = false;
}
void FrameSenderWindow::buildFrameCache()
{
CANFrame thisFrame;
frameCache.clear();
for (int i = 0; i < modelFrames->count(); i++)
{
thisFrame = modelFrames->at(i);
if (!frameCache.contains(thisFrame.ID))
{
frameCache.insert(thisFrame.ID, thisFrame);
}
else
{
frameCache[thisFrame.ID] = thisFrame;
}
}
}
//remember, negative numbers are special -1 = all frames deleted, -2 = totally new set of frames.
void FrameSenderWindow::updatedFrames(int numFrames)
{
CANFrame thisFrame;
if (numFrames == -1) //all frames deleted.
{
}
else if (numFrames == -2) //all new set of frames.
{
buildFrameCache();
}
else //just got some new frames. See if they are relevant.
{
qDebug() << "New frames in sender window";
//run through the supposedly new frames in order
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
{
if (!frameCache.contains(thisFrame.ID))
{
frameCache.insert(thisFrame.ID, thisFrame);
}
else
{
frameCache[thisFrame.ID] = thisFrame;
}
processIncomingFrame(&thisFrame);
}
}
}
void FrameSenderWindow::processIncomingFrame(CANFrame *frame)
{
for (int sd = 0; sd < sendingData.count(); sd++)
{
if (sendingData[sd].triggers.count() == 0) continue;
for (int trig = 0; trig < sendingData[sd].triggers.count(); trig++)
{
Trigger thisTrigger = sendingData[sd].triggers[trig];
if (thisTrigger.ID > 0 && thisTrigger.ID == frame->ID)
{
if (thisTrigger.bus == frame->bus || thisTrigger.bus == -1)
{
if (thisTrigger.currCount < thisTrigger.maxCount)
{
if (thisTrigger.milliseconds == 0) //immediate reply
{
thisTrigger.currCount++;
sendingData[sd].count++;
doModifiers(sd);
updateGridRow(sd);
sendCANFrame(&sendingData[sd], sendingData[sd].bus);
}
else //delayed sending frame
{
thisTrigger.readyCount = true;
}
}
}
}
}
}
}
void FrameSenderWindow::enableAll()
{
for (int i = 0; i < ui->tableSender->rowCount() - 1; i++)
{
ui->tableSender->item(i, 0)->setCheckState(Qt::Checked);
sendingData[i].enabled = true;
}
}
void FrameSenderWindow::disableAll()
{
for (int i = 0; i < ui->tableSender->rowCount() - 1; i++)
{
ui->tableSender->item(i, 0)->setCheckState(Qt::Unchecked);
sendingData[i].enabled = false;
}
}
void FrameSenderWindow::clearGrid()
{
if (ui->tableSender->rowCount() == 1) return;
for (int i = ui->tableSender->rowCount() - 2; i >= 0; i--)
{
sendingData[i].enabled = false;
sendingData.removeAt(i);
ui->tableSender->removeRow(i);
}
}
void FrameSenderWindow::saveGrid()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("Frame Sender Definition (*.fsd)")));
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
if (dialog.selectedNameFilter() == filters[0])
{
if (!filename.contains('.')) filename += ".fsd";
saveSenderFile(filename);
}
}
}
void FrameSenderWindow::loadGrid()
{
QString filename;
QFileDialog dialog(this);
QStringList filters;
filters.append(QString(tr("Frame Sender Definition (*.fsd)")));
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters);
dialog.setViewMode(QFileDialog::Detail);
if (dialog.exec() == QDialog::Accepted)
{
filename = dialog.selectedFiles()[0];
if (dialog.selectedNameFilter() == filters[0])
{
loadSenderFile(filename);
}
}
}
void FrameSenderWindow::saveSenderFile(QString filename)
{
QFile *outFile = new QFile(filename);
QString outString;
if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text))
{
delete outFile;
return;
}
for (int c = 0; c < sendingData.count(); c++)
{
outString.clear();
if (ui->tableSender->item(c, 0)->checkState() == Qt::Checked)
{
outString = "T#";
}
else outString = "F#";
for (int i = 1; i < 7; i++)
{
outString.append(ui->tableSender->item(c, i)->text());
outString.append("#");
}
outString.append("\n");
outFile->write(outString.toUtf8());
}
outFile->close();
delete outFile;
}
void FrameSenderWindow::loadSenderFile(QString filename)
{
QFile *inFile = new QFile(filename);
QByteArray line;
if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text))
{
delete inFile;
return;
}
ui->tableSender->clear();
sendingData.clear();
while (!inFile->atEnd()) {
line = inFile->readLine().simplified();
if (line.length() > 2)
{
QList<QByteArray> tokens = line.split('#');
int row = ui->tableSender->rowCount();
ui->tableSender->insertRow(row);
ui->tableSender->item(row, 0)->setFlags(Qt::ItemIsUserCheckable);
if (tokens[0] == "T")
{
ui->tableSender->item(row, 0)->setCheckState(Qt::Checked);
}
else ui->tableSender->item(row, 0)->setCheckState(Qt::Unchecked);
for (int i = 0; i < 7; i++) ui->tableSender->item(row, i)->setText(tokens[i]);
for (int k = 0; k < 7; k++) processCellChange(row, k);
}
}
inFile->close();
delete inFile;
}
void FrameSenderWindow::onCellChanged(int row, int col)
{
if (inhibitChanged) return;
qDebug() << "onCellChanged";
if (row == ui->tableSender->rowCount() - 1)
{
ui->tableSender->insertRow(ui->tableSender->rowCount());
createBlankRow();
}
processCellChange(row, col);
}
/// <summary>
@@ -54,29 +325,33 @@ void FrameSenderWindow::onCellChanged(int row, int col)
/// <param name="timerEventArgs"></param>
void FrameSenderWindow::handleTick()
{
FrameSendData sendData;
Trigger trigger;
Modifier modifier;
FrameSendData *sendData;
Trigger *trigger;
int elapsed = elapsedTimer.restart();
if (elapsed == 0) elapsed = 1;
//Modifier modifier;
for (int i = 0; i < sendingData.count(); i++)
{
sendData = sendingData.at(i);
if (!sendData.enabled) continue; //abort any processing on this if it is not enabled.
if (sendData.triggers.count() == 0) return;
for (int j = 0; j < sendData.triggers.count(); j++)
sendData = &sendingData[i];
if (!sendData->enabled) continue; //abort any processing on this if it is not enabled.
if (sendData->triggers.count() == 0) return;
for (int j = 0; j < sendData->triggers.count(); j++)
{
trigger = sendData.triggers.at(j);
if (trigger.currCount >= trigger.maxCount) continue; //don't process if we've sent max frames we were supposed to
if (!trigger.readyCount) continue; //don't tick if not ready to tick
trigger = &sendData->triggers[j];
if (trigger->currCount >= trigger->maxCount) continue; //don't process if we've sent max frames we were supposed to
if (!trigger->readyCount) continue; //don't tick if not ready to tick
//is it time to fire?
if (++trigger.msCounter >= trigger.milliseconds)
trigger->msCounter += elapsed; //gives proper tracking even if timer doesn't fire as fast as it should
if (trigger->msCounter >= trigger->milliseconds)
{
trigger.msCounter = 0;
sendData.count++;
trigger.currCount++;
trigger->msCounter = 0;
sendData->count++;
trigger->currCount++;
doModifiers(i);
//updateGridRow(i);
//parent.SendCANFrame(sendingData[i], sendingData[i].bus);
if (trigger.ID > 0) trigger.readyCount = false; //reset flag if this is a timed ID trigger
updateGridRow(i);
qDebug() << "About to try to send a frame";
emit sendCANFrame(&sendingData[i], sendingData[i].bus);
if (trigger->ID > 0) trigger->readyCount = false; //reset flag if this is a timed ID trigger
}
}
}
@@ -91,18 +366,20 @@ void FrameSenderWindow::doModifiers(int idx)
int shadowReg = 0; //shadow register we use to accumulate results
int first=0, second=0;
FrameSendData sendData = sendingData.at(idx);
Modifier mod;
FrameSendData *sendData = &sendingData[idx];
Modifier *mod;
ModifierOp op;
if (sendData.modifiers.count() == 0) return; //if no modifiers just leave right now
if (sendData->modifiers.count() == 0) return; //if no modifiers just leave right now
for (int i = 0; i < sendData.modifiers.count(); i++)
qDebug() << "Doin' dem mods son";
for (int i = 0; i < sendData->modifiers.count(); i++)
{
mod = sendData.modifiers.at(i);
for (int j = 0; j < mod.operations.count(); j++)
mod = &sendData->modifiers[i];
for (int j = 0; j < mod->operations.count(); j++)
{
op = mod.operations.at(j);
op = mod->operations.at(j);
if (op.first.ID == -1)
{
first = shadowReg;
@@ -135,7 +412,7 @@ void FrameSenderWindow::doModifiers(int idx)
}
}
//Finally, drop the result into the proper data byte
mod.destByte = (unsigned char) shadowReg;
sendData->data[mod->destByte] = (unsigned char) shadowReg;
}
}
@@ -169,15 +446,10 @@ int FrameSenderWindow::fetchOperand(int idx, ModifierOperand op)
/// <returns></returns>
CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
{
CANFrame frame;
for (int a = 0; a < frameCache.count(); a++)
{
frame = frameCache.at(a);
if ((ID == frame.ID) && ((bus == frame.bus) || bus == -1))
{
return &frame;
}
}
if (!frameCache.contains(ID)) return NULL;
if (bus == -1 || frameCache[ID].bus == bus) return &frameCache[ID];
return NULL;
}
@@ -188,6 +460,7 @@ CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
/// <param name="line"></param>
void FrameSenderWindow::processModifierText(int line)
{
qDebug() << "processModifierText";
QString modString;
int numOps;
@@ -266,6 +539,7 @@ void FrameSenderWindow::processModifierText(int line)
void FrameSenderWindow::processTriggerText(int line)
{
qDebug() << "processTriggerText";
QString trigger;
//Example line:
@@ -340,6 +614,7 @@ void FrameSenderWindow::processTriggerText(int line)
//Turn a set of tokens into an operand
void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &operand)
{
qDebug() << "parseOperandString";
//example string -> bus:0:id:200:d3
operand.bus = -1;
@@ -370,6 +645,7 @@ void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &
ModifierOperationType FrameSenderWindow::parseOperation(QString op)
{
qDebug() << "parseOperation";
if (op == "+") return ADDITION;
if (op == "-") return SUBTRACTION;
if (op == "*") return MULTIPLICATION;
@@ -382,113 +658,43 @@ ModifierOperationType FrameSenderWindow::parseOperation(QString op)
if (op == "XOR") return XOR;
return ADDITION;
}
//The below is c# code from the old project. It won't run as-is and must be ported to C++/Qt
/*
/// <summary>
/// Updaet the DataGridView with the newest info from sendingData
/// Update the DataGridView with the newest info from sendingData
/// </summary>
/// <param name="idx"></param>
private void updateGridRow(int idx)
void FrameSenderWindow::updateGridRow(int idx)
{
FrameSendData temp = sendingData[idx];
qDebug() << "updateGridRow";
inhibitChanged = true;
FrameSendData *temp = &sendingData[idx];
int gridLine = idx;
StringBuilder dataString = new StringBuilder();
dataGridView1.Rows[gridLine].Cells[7].Value = temp.count.ToString();
for (int i = 0; i < temp.len; i++)
QString dataString;
QTableWidgetItem *item = ui->tableSender->item(gridLine, 7);
if (item == NULL) item = new QTableWidgetItem();
item->setText(QString::number(temp->count));
for (int i = 0; i < temp->len; i++)
{
dataString.Append("0x");
dataString.Append(temp.data[i].ToString("X2"));
dataString.Append(" ");
dataString.append(Utility::formatNumber(temp->data[i]));
dataString.append(" ");
}
dataGridView1.Rows[gridLine].Cells[4].Value = dataString.ToString();
ui->tableSender->item(gridLine, 4)->setText(dataString);
inhibitChanged = false;
}
public delegate void GotCANDelegate(CANFrame frame);
/// <summary>
/// Event callback for reception of canbus frames
/// </summary>
/// <param name="frame">The frame that came in</param>
public void GotCANFrame(CANFrame frame)
{
if (this.InvokeRequired)
{
this.Invoke(new GotCANDelegate(GotCANFrame), frame);
}
else
{
//search list of frames and add if no frame with this ID is found
//or update if one was found.
bool found = false;
for (int a = 0; a < frames.Count; a++)
{
if ((frame.ID == frames[a].ID) && (frame.bus == frames[a].bus))
{
found = true;
frames[a].len = frame.len;
frames[a].data = frame.data;
}
}
if (!found)
{
frames.Add(frame);
}
//now that frame cache has been updated, try to see if this incoming frame
//satisfies any triggers
for (int b = 0; b < sendingData.Count; b++)
{
if (sendingData[b].triggers == null) continue;
for (int c = 0; c < sendingData[b].triggers.Length; c++)
{
Trigger thisTrigger = sendingData[b].triggers[c];
if (thisTrigger.ID > 0)
{
if ((thisTrigger.bus == frame.bus) || (thisTrigger.bus == -1))
{
if (thisTrigger.ID == frame.ID)
{
//seems to match this trigger.
if (thisTrigger.currCount < thisTrigger.maxCount)
{
if (thisTrigger.milliseconds == 0) //don't want to time the frame, send it right away
{
sendingData[b].triggers[c].currCount++;
sendingData[b].count++;
doModifiers(b);
updateGridRow(b);
parent.SendCANFrame(sendingData[b], sendingData[b].bus);
}
else //instead of immediate sending we start the timer
{
sendingData[b].triggers[c].readyCount = true;
}
}
}
}
}
}
}
}
}
private void dataGridView1_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
{
int rec = e.RowIndex;
if (rec != -1) sendingData.RemoveAt(rec);
}
private void processCellChange(int line, int col)
void FrameSenderWindow::processCellChange(int line, int col)
{
qDebug() << "processCellChange";
FrameSendData tempData;
QStringList tokens;
int tempVal;
//if this is a new line then create the base object for the line
if ((line >= sendingData.Count) || (sendingData[line] == null))
if (line >= sendingData.count())
{
tempData = new FrameSendData();
sendingData.Add(tempData);
FrameSendData tempData;
tempData.enabled = false;
sendingData.append(tempData);
}
sendingData[line].count = 0;
@@ -496,28 +702,31 @@ private void processCellChange(int line, int col)
switch (col)
{
case 0: //Enable check box
if (dataGridView1.Rows[line].Cells[0].Value != null)
if (ui->tableSender->item(line, 0)->checkState() == Qt::Checked)
{
sendingData[line].enabled = (bool)dataGridView1.Rows[line].Cells[0].Value;
sendingData[line].enabled = true;
}
else sendingData[line].enabled = false;
qDebug() << "Setting enabled to " << sendingData[line].enabled;
break;
case 1: //Bus designation
tempVal = Utility.ParseStringToNum((string)dataGridView1.Rows[line].Cells[1].Value);
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 1)->text());
if (tempVal < 0) tempVal = 0;
if (tempVal > 1) tempVal = 1;
sendingData[line].bus = tempVal;
qDebug() << "Setting bus to " << tempVal;
break;
case 2: //ID field
tempVal = Utility.ParseStringToNum((string)dataGridView1.Rows[line].Cells[2].Value);
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 2)->text());
if (tempVal < 1) tempVal = 1;
if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF;
sendingData[line].ID = tempVal;
if (sendingData[line].ID <= 0x7FF) sendingData[line].extended = false;
else sendingData[line].extended = true;
qDebug() << "setting ID to " << tempVal;
break;
case 3: //length field
tempVal = Utility.ParseStringToNum((string)dataGridView1.Rows[line].Cells[3].Value);
tempVal = Utility::ParseStringToNum(ui->tableSender->item(line, 3)->text());
if (tempVal < 0) tempVal = 0;
if (tempVal > 8) tempVal = 8;
sendingData[line].len = tempVal;
@@ -525,10 +734,10 @@ private void processCellChange(int line, int col)
case 4: //Data bytes
for (int i = 0; i < 8; i++) sendingData[line].data[i] = 0;
string[] tokens = ((string)dataGridView1.Rows[line].Cells[4].Value).Split(' ');
for (int j = 0; j < tokens.Length; j++)
tokens = ui->tableSender->item(line, 4)->text().split(" ");
for (int j = 0; j < tokens.count(); j++)
{
sendingData[line].data[j] = (byte)Utility.ParseStringToNum(tokens[j]);
sendingData[line].data[j] = (uint8_t)Utility::ParseStringToNum(tokens[j]);
}
break;
case 5: //triggers
@@ -540,126 +749,3 @@ private void processCellChange(int line, int col)
}
}
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
processCellChange(e.RowIndex, e.ColumnIndex);
}
private void loadFromFileToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult res;
//First zap all existing data. Ask first. Might not need to actually ask here since you can abort the file open
//and be OK that way too.
if (sendingData.Count > 0)
{
res = MessageBox.Show("Proceding will erase the current\ncontents of the grid.", "Warning", MessageBoxButtons.YesNo);
if (res == DialogResult.No) return;
}
res = openFileDialog1.ShowDialog();
if (res == DialogResult.OK)
{
sendingData.Clear();
dataGridView1.Rows.Clear();
Stream inputFile = openFileDialog1.OpenFile();
StreamReader inputReader = new StreamReader(inputFile);
string line;
int row;
try
{
while (!inputReader.EndOfStream)
{
line = inputReader.ReadLine();
string[] tokens = line.Split('#');
row = dataGridView1.Rows.Add();
if (tokens[0] == "T")
{
dataGridView1.Rows[row].Cells[0].Value = true;
}
else dataGridView1.Rows[row].Cells[0].Value = false;
for (int j = 1; j < 7; j++)
{
dataGridView1.Rows[row].Cells[j].Value = tokens[j];
}
for (int k = 0; k < 7; k++) processCellChange(row, k);
}
}
catch (Exception ee)
{
Debug.Print(ee.ToString());
}
}
}
private void saveGridToolStripMenuItem_Click(object sender, EventArgs e)
{
StringBuilder buildStr = new StringBuilder();
DialogResult res;
res = saveFileDialog1.ShowDialog();
if (res == DialogResult.OK)
{
Stream outputFile = saveFileDialog1.OpenFile();
StreamWriter outputWriter = new StreamWriter(outputFile);
try
{
for (int i = 0; i < sendingData.Count; i++)
{
buildStr.Clear();
if (dataGridView1.Rows[i].Cells[0].Value != null)
{
if ((bool)dataGridView1.Rows[i].Cells[0].Value == true)
{
buildStr.Append("T");
}
else buildStr.Append("F");
}
else buildStr.Append("F");
buildStr.Append("#");
for (int j = 1; j < 7; j++)
{
buildStr.Append(dataGridView1.Rows[i].Cells[j].Value);
buildStr.Append("#");
}
outputWriter.WriteLine(buildStr.ToString());
}
}
catch (Exception ee)
{
Debug.Print(ee.ToString());
}
outputWriter.Flush();
outputWriter.Close();
}
}
//Note for the below three functions that they all handle the fact that a data view grid will always have an extra row that is blank
//and available for a new record. Because of this the grid count is always one too high.
private void button1_Click(object sender, EventArgs e) //enable all lines in the grid
{
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
dataGridView1.Rows[i].Cells[0].Value = true;
sendingData[i].enabled = true;
}
}
private void button2_Click(object sender, EventArgs e) //disable all lines in the grid
{
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
dataGridView1.Rows[i].Cells[0].Value = false;
sendingData[i].enabled = false;
}
}
private void button3_Click(object sender, EventArgs e) //delete all entries in the grid and data struct
{
if (dataGridView1.Rows.Count == 1) return;
for (int i = dataGridView1.Rows.Count - 2; i >= 0; i--)
{
sendingData[i].enabled = false;
sendingData.RemoveAt(i);
dataGridView1.Rows.RemoveAt(i);
}
}
*/
+21 -1
View File
@@ -3,6 +3,8 @@
#include <QDialog>
#include <QTimer>
#include <QElapsedTimer>
#include <QTime>
#include "can_structs.h"
#include "can_trigger_structs.h"
@@ -21,14 +23,26 @@ public:
private slots:
void onCellChanged(int, int);
void handleTick();
void enableAll();
void disableAll();
void clearGrid();
void saveGrid();
void loadGrid();
void updatedFrames(int);
signals:
void sendCANFrame(const CANFrame *, int);
private:
Ui::FrameSenderWindow *ui;
QList<FrameSendData> sendingData;
QList<CANFrame> frameCache;
QHash<int, CANFrame> frameCache; //hash with frame ID as the key and the most recent frame as the value
const QVector<CANFrame> *modelFrames;
QTimer *intervalTimer;
QElapsedTimer elapsedTimer;
bool inhibitChanged = false;
void createBlankRow();
void doModifiers(int);
int fetchOperand(int, ModifierOperand);
CANFrame* lookupFrame(int, int);
@@ -36,6 +50,12 @@ private:
void processTriggerText(int);
void parseOperandString(QStringList tokens, ModifierOperand&);
ModifierOperationType parseOperation(QString);
void saveSenderFile(QString filename);
void loadSenderFile(QString filename);
void updateGridRow(int idx);
void processCellChange(int line, int col);
void buildFrameCache();
void processIncomingFrame(CANFrame *frame);
};
#endif // FRAMESENDERWINDOW_H
+5 -5
View File
@@ -24,21 +24,21 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButton_2">
<widget class="QPushButton" name="btnEnableAll">
<property name="text">
<string>Enable All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<widget class="QPushButton" name="btnDisableAll">
<property name="text">
<string>Disable All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<widget class="QPushButton" name="btnClearGrid">
<property name="text">
<string>Clear Grid</string>
</property>
@@ -61,14 +61,14 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_4">
<widget class="QPushButton" name="btnLoadGrid">
<property name="text">
<string>Load to Grid</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<widget class="QPushButton" name="btnSaveGrid">
<property name="text">
<string>Save Grid</string>
</property>