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 #ifndef CONFIG
#define CONFIG #define CONFIG
#define VERSION 132 #define VERSION 133
//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
//less than this number. //less than this number.
#define CURRENT_GVRET_VER 322 #define CURRENT_GVRET_VER 323
#endif // CONFIG #endif // CONFIG
+352 -266
View File
@@ -2,6 +2,17 @@
#include "ui_framesenderwindow.h" #include "ui_framesenderwindow.h"
#include "utility.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) : FrameSenderWindow::FrameSenderWindow(const QVector<CANFrame> *frames, QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::FrameSenderWindow) ui(new Ui::FrameSenderWindow)
@@ -16,35 +27,295 @@ FrameSenderWindow::FrameSenderWindow(const QVector<CANFrame> *frames, QWidget *p
QStringList headers; QStringList headers;
headers << "En" << "Bus" << "ID" << "Len" << "Data" << "Trigger" << "Modifications" << "Count"; headers << "En" << "Bus" << "ID" << "Len" << "Data" << "Trigger" << "Modifications" << "Count";
ui->tableSender->setColumnCount(8); ui->tableSender->setColumnCount(8);
ui->tableSender->setColumnWidth(0, 40); ui->tableSender->setColumnWidth(0, 50);
ui->tableSender->setColumnWidth(1, 40); ui->tableSender->setColumnWidth(1, 50);
ui->tableSender->setColumnWidth(2, 40); ui->tableSender->setColumnWidth(2, 50);
ui->tableSender->setColumnWidth(3, 40); ui->tableSender->setColumnWidth(3, 50);
ui->tableSender->setColumnWidth(4, 200); ui->tableSender->setColumnWidth(4, 220);
ui->tableSender->setColumnWidth(5, 200); ui->tableSender->setColumnWidth(5, 220);
ui->tableSender->setColumnWidth(6, 200); ui->tableSender->setColumnWidth(6, 220);
ui->tableSender->setColumnWidth(7, 80); ui->tableSender->setColumnWidth(7, 80);
ui->tableSender->setHorizontalHeaderLabels(headers); ui->tableSender->setHorizontalHeaderLabels(headers);
ui->tableSender->insertRow(0); createBlankRow();
connect(ui->tableSender, SIGNAL(cellChanged(int,int)), this, SLOT(onCellChanged(int,int))); 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() FrameSenderWindow::~FrameSenderWindow()
{ {
delete ui; delete ui;
intervalTimer->stop(); intervalTimer->stop();
delete intervalTimer; 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) void FrameSenderWindow::onCellChanged(int row, int col)
{ {
if (inhibitChanged) return;
qDebug() << "onCellChanged";
if (row == ui->tableSender->rowCount() - 1) if (row == ui->tableSender->rowCount() - 1)
{ {
ui->tableSender->insertRow(ui->tableSender->rowCount()); createBlankRow();
} }
processCellChange(row, col);
} }
/// <summary> /// <summary>
@@ -54,29 +325,33 @@ void FrameSenderWindow::onCellChanged(int row, int col)
/// <param name="timerEventArgs"></param> /// <param name="timerEventArgs"></param>
void FrameSenderWindow::handleTick() void FrameSenderWindow::handleTick()
{ {
FrameSendData sendData; FrameSendData *sendData;
Trigger trigger; Trigger *trigger;
Modifier modifier; int elapsed = elapsedTimer.restart();
if (elapsed == 0) elapsed = 1;
//Modifier modifier;
for (int i = 0; i < sendingData.count(); i++) for (int i = 0; i < sendingData.count(); i++)
{ {
sendData = sendingData.at(i); sendData = &sendingData[i];
if (!sendData.enabled) continue; //abort any processing on this if it is not enabled. if (!sendData->enabled) continue; //abort any processing on this if it is not enabled.
if (sendData.triggers.count() == 0) return; if (sendData->triggers.count() == 0) return;
for (int j = 0; j < sendData.triggers.count(); j++) for (int j = 0; j < sendData->triggers.count(); j++)
{ {
trigger = sendData.triggers.at(j); 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->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 if (!trigger->readyCount) continue; //don't tick if not ready to tick
//is it time to fire? //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; trigger->msCounter = 0;
sendData.count++; sendData->count++;
trigger.currCount++; trigger->currCount++;
doModifiers(i); doModifiers(i);
//updateGridRow(i); updateGridRow(i);
//parent.SendCANFrame(sendingData[i], sendingData[i].bus); qDebug() << "About to try to send a frame";
if (trigger.ID > 0) trigger.readyCount = false; //reset flag if this is a timed ID trigger 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 shadowReg = 0; //shadow register we use to accumulate results
int first=0, second=0; int first=0, second=0;
FrameSendData sendData = sendingData.at(idx); FrameSendData *sendData = &sendingData[idx];
Modifier mod; Modifier *mod;
ModifierOp op; 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); mod = &sendData->modifiers[i];
for (int j = 0; j < mod.operations.count(); j++) for (int j = 0; j < mod->operations.count(); j++)
{ {
op = mod.operations.at(j); op = mod->operations.at(j);
if (op.first.ID == -1) if (op.first.ID == -1)
{ {
first = shadowReg; first = shadowReg;
@@ -135,7 +412,7 @@ void FrameSenderWindow::doModifiers(int idx)
} }
} }
//Finally, drop the result into the proper data byte //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> /// <returns></returns>
CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus) CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
{ {
CANFrame frame; if (!frameCache.contains(ID)) return NULL;
for (int a = 0; a < frameCache.count(); a++)
{ if (bus == -1 || frameCache[ID].bus == bus) return &frameCache[ID];
frame = frameCache.at(a);
if ((ID == frame.ID) && ((bus == frame.bus) || bus == -1))
{
return &frame;
}
}
return NULL; return NULL;
} }
@@ -188,6 +460,7 @@ CANFrame* FrameSenderWindow::lookupFrame(int ID, int bus)
/// <param name="line"></param> /// <param name="line"></param>
void FrameSenderWindow::processModifierText(int line) void FrameSenderWindow::processModifierText(int line)
{ {
qDebug() << "processModifierText";
QString modString; QString modString;
int numOps; int numOps;
@@ -266,6 +539,7 @@ void FrameSenderWindow::processModifierText(int line)
void FrameSenderWindow::processTriggerText(int line) void FrameSenderWindow::processTriggerText(int line)
{ {
qDebug() << "processTriggerText";
QString trigger; QString trigger;
//Example line: //Example line:
@@ -340,6 +614,7 @@ void FrameSenderWindow::processTriggerText(int line)
//Turn a set of tokens into an operand //Turn a set of tokens into an operand
void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &operand) void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &operand)
{ {
qDebug() << "parseOperandString";
//example string -> bus:0:id:200:d3 //example string -> bus:0:id:200:d3
operand.bus = -1; operand.bus = -1;
@@ -370,6 +645,7 @@ void FrameSenderWindow::parseOperandString(QStringList tokens, ModifierOperand &
ModifierOperationType FrameSenderWindow::parseOperation(QString op) ModifierOperationType FrameSenderWindow::parseOperation(QString op)
{ {
qDebug() << "parseOperation";
if (op == "+") return ADDITION; if (op == "+") return ADDITION;
if (op == "-") return SUBTRACTION; if (op == "-") return SUBTRACTION;
if (op == "*") return MULTIPLICATION; if (op == "*") return MULTIPLICATION;
@@ -382,113 +658,43 @@ ModifierOperationType FrameSenderWindow::parseOperation(QString op)
if (op == "XOR") return XOR; if (op == "XOR") return XOR;
return ADDITION; 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> /// <summary>
/// Updaet the DataGridView with the newest info from sendingData /// Update the DataGridView with the newest info from sendingData
/// </summary> /// </summary>
/// <param name="idx"></param> /// <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; int gridLine = idx;
StringBuilder dataString = new StringBuilder(); QString dataString;
dataGridView1.Rows[gridLine].Cells[7].Value = temp.count.ToString(); QTableWidgetItem *item = ui->tableSender->item(gridLine, 7);
for (int i = 0; i < temp.len; i++) 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(Utility::formatNumber(temp->data[i]));
dataString.Append(temp.data[i].ToString("X2")); dataString.append(" ");
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); void FrameSenderWindow::processCellChange(int line, int col)
/// <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)
{ {
qDebug() << "processCellChange";
FrameSendData tempData; FrameSendData tempData;
QStringList tokens;
int tempVal; int tempVal;
//if this is a new line then create the base object for the line //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(); FrameSendData tempData;
sendingData.Add(tempData); tempData.enabled = false;
sendingData.append(tempData);
} }
sendingData[line].count = 0; sendingData[line].count = 0;
@@ -496,28 +702,31 @@ private void processCellChange(int line, int col)
switch (col) switch (col)
{ {
case 0: //Enable check box 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; else sendingData[line].enabled = false;
qDebug() << "Setting enabled to " << sendingData[line].enabled;
break; break;
case 1: //Bus designation 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 < 0) tempVal = 0;
if (tempVal > 1) tempVal = 1; if (tempVal > 1) tempVal = 1;
sendingData[line].bus = tempVal; sendingData[line].bus = tempVal;
qDebug() << "Setting bus to " << tempVal;
break; break;
case 2: //ID field 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 < 1) tempVal = 1;
if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF; if (tempVal > 0x7FFFFFFF) tempVal = 0x7FFFFFFF;
sendingData[line].ID = tempVal; sendingData[line].ID = tempVal;
if (sendingData[line].ID <= 0x7FF) sendingData[line].extended = false; if (sendingData[line].ID <= 0x7FF) sendingData[line].extended = false;
else sendingData[line].extended = true; else sendingData[line].extended = true;
qDebug() << "setting ID to " << tempVal;
break; break;
case 3: //length field 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 < 0) tempVal = 0;
if (tempVal > 8) tempVal = 8; if (tempVal > 8) tempVal = 8;
sendingData[line].len = tempVal; sendingData[line].len = tempVal;
@@ -525,10 +734,10 @@ private void processCellChange(int line, int col)
case 4: //Data bytes case 4: //Data bytes
for (int i = 0; i < 8; i++) sendingData[line].data[i] = 0; for (int i = 0; i < 8; i++) sendingData[line].data[i] = 0;
string[] tokens = ((string)dataGridView1.Rows[line].Cells[4].Value).Split(' '); tokens = ui->tableSender->item(line, 4)->text().split(" ");
for (int j = 0; j < tokens.Length; j++) 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; break;
case 5: //triggers 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 <QDialog>
#include <QTimer> #include <QTimer>
#include <QElapsedTimer>
#include <QTime>
#include "can_structs.h" #include "can_structs.h"
#include "can_trigger_structs.h" #include "can_trigger_structs.h"
@@ -21,14 +23,26 @@ public:
private slots: private slots:
void onCellChanged(int, int); void onCellChanged(int, int);
void handleTick(); void handleTick();
void enableAll();
void disableAll();
void clearGrid();
void saveGrid();
void loadGrid();
void updatedFrames(int);
signals:
void sendCANFrame(const CANFrame *, int);
private: private:
Ui::FrameSenderWindow *ui; Ui::FrameSenderWindow *ui;
QList<FrameSendData> sendingData; 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; const QVector<CANFrame> *modelFrames;
QTimer *intervalTimer; QTimer *intervalTimer;
QElapsedTimer elapsedTimer;
bool inhibitChanged = false;
void createBlankRow();
void doModifiers(int); void doModifiers(int);
int fetchOperand(int, ModifierOperand); int fetchOperand(int, ModifierOperand);
CANFrame* lookupFrame(int, int); CANFrame* lookupFrame(int, int);
@@ -36,6 +50,12 @@ private:
void processTriggerText(int); void processTriggerText(int);
void parseOperandString(QStringList tokens, ModifierOperand&); void parseOperandString(QStringList tokens, ModifierOperand&);
ModifierOperationType parseOperation(QString); 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 #endif // FRAMESENDERWINDOW_H
+5 -5
View File
@@ -24,21 +24,21 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QPushButton" name="pushButton_2"> <widget class="QPushButton" name="btnEnableAll">
<property name="text"> <property name="text">
<string>Enable All</string> <string>Enable All</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_3"> <widget class="QPushButton" name="btnDisableAll">
<property name="text"> <property name="text">
<string>Disable All</string> <string>Disable All</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_5"> <widget class="QPushButton" name="btnClearGrid">
<property name="text"> <property name="text">
<string>Clear Grid</string> <string>Clear Grid</string>
</property> </property>
@@ -61,14 +61,14 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_4"> <widget class="QPushButton" name="btnLoadGrid">
<property name="text"> <property name="text">
<string>Load to Grid</string> <string>Load to Grid</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton"> <widget class="QPushButton" name="btnSaveGrid">
<property name="text"> <property name="text">
<string>Save Grid</string> <string>Save Grid</string>
</property> </property>