Merge branch 'master' of github.com:qurrent-llc/SavvyCAN
This commit is contained in:
@@ -110,6 +110,7 @@ public: //TODO: this is sloppy. It shouldn't all be public!
|
||||
QList<DBC_VAL_ENUM_ENTRY> valList;
|
||||
QList<DBC_SIGNAL *> multiplexedChildren;
|
||||
DBC_SIGNAL *multiplexParent;
|
||||
DBC_SIGNAL *self;
|
||||
|
||||
DBC_SIGNAL();
|
||||
bool processAsText(const CANFrame &frame, QString &outString, bool outputName = true);
|
||||
|
||||
+24
-10
@@ -441,12 +441,21 @@ void DBCFile::findAttributesByType(DBC_ATTRIBUTE_TYPE typ, QList<DBC_ATTRIBUTE>
|
||||
}
|
||||
}
|
||||
|
||||
//there's no external way to clear the flag. It is only cleared when the file is saved by this object.
|
||||
void DBCFile::setDirtyFlag()
|
||||
{
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
//BE CAREFUL HERE. Do not clear the dirty flag unless you're absolutely sure nothing has changed.
|
||||
//Currently the signal editor clears this flag if the entire undo buffer is emptied but still
|
||||
//it's possible that signals or messages were deleted or added so this is potentially not that safe
|
||||
//It would be better if every node, message, and signal had a dirty flag. Then the DBCFile getDirtyFlag
|
||||
//function could traverse the tree and see if anything is dirty.
|
||||
void DBCFile::clearDirtyFlag()
|
||||
{
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
bool DBCFile::getDirtyFlag()
|
||||
{
|
||||
return isDirty;
|
||||
@@ -1294,7 +1303,7 @@ bool DBCFile::saveFile(QString fileName)
|
||||
int msgNumber = 1;
|
||||
int sigNumber = 1;
|
||||
QFile *outFile = new QFile(fileName);
|
||||
QString nodesOutput, msgOutput, commentsOutput, valuesOutput;
|
||||
QString nodesOutput, msgOutput, commentsOutput, valuesOutput, extMultiplexOutput;
|
||||
QString defaultsOutput, attrValOutput;
|
||||
bool hasExtendedMultiplexing = false;
|
||||
|
||||
@@ -1512,6 +1521,9 @@ bool DBCFile::saveFile(QString fileName)
|
||||
msgOutput.clear(); //got to reset it after writing
|
||||
}
|
||||
|
||||
outFile->write(commentsOutput.toUtf8());
|
||||
commentsOutput.clear();
|
||||
|
||||
//Now dump out all of the stored attributes
|
||||
for (int x = 0; x < dbc_attributes.count(); x++)
|
||||
{
|
||||
@@ -1573,6 +1585,8 @@ bool DBCFile::saveFile(QString fileName)
|
||||
defaultsOutput.append("\"" + dbc_attributes[x].enumVals[dbc_attributes[x].defaultValue.toInt()] + "\";\n");
|
||||
break;
|
||||
case ATTR_INT:
|
||||
defaultsOutput.append(QString::number(dbc_attributes[x].defaultValue.toLongLong()) + ";\n");
|
||||
break;
|
||||
case ATTR_FLOAT:
|
||||
defaultsOutput.append(dbc_attributes[x].defaultValue.toString() + ";\n");
|
||||
break;
|
||||
@@ -1592,7 +1606,7 @@ bool DBCFile::saveFile(QString fileName)
|
||||
uint32_t ID = msg->ID;
|
||||
if (msg->ID > 0x7FF || msg->extendedID)
|
||||
{
|
||||
msg->ID += 0x80000000ul; //set bit 31 if this ID is extended.
|
||||
ID += 0x80000000ul; //set bit 31 if this ID is extended.
|
||||
}
|
||||
|
||||
for (int s = 0; s < msg->sigHandler->getCount(); s++)
|
||||
@@ -1605,7 +1619,7 @@ bool DBCFile::saveFile(QString fileName)
|
||||
msgOutput.append(sig->name + " " + sig->multiplexParent->name + " ");
|
||||
msgOutput.append(QString::number(sig->multiplexLowValue) + "-" + QString::number(sig->multiplexHighValue) + ";");
|
||||
msgOutput.append("\n");
|
||||
outFile->write(msgOutput.toUtf8());
|
||||
extMultiplexOutput.append(msgOutput);
|
||||
msgOutput.clear(); //got to reset it after writing
|
||||
}
|
||||
}
|
||||
@@ -1613,15 +1627,15 @@ bool DBCFile::saveFile(QString fileName)
|
||||
}
|
||||
|
||||
//now write out all of the accumulated comments and value tables from above
|
||||
outFile->write(attrValOutput.toUtf8());
|
||||
outFile->write(defaultsOutput.toUtf8());
|
||||
outFile->write(commentsOutput.toUtf8());
|
||||
outFile->write(attrValOutput.toUtf8());
|
||||
outFile->write(valuesOutput.toUtf8());
|
||||
outFile->write(extMultiplexOutput.toUtf8());
|
||||
|
||||
attrValOutput.clear();
|
||||
defaultsOutput.clear();
|
||||
commentsOutput.clear();
|
||||
valuesOutput.clear();
|
||||
extMultiplexOutput.clear();
|
||||
|
||||
outFile->close();
|
||||
delete outFile;
|
||||
@@ -2235,14 +2249,14 @@ DBCHandler::DBCHandler()
|
||||
qDebug() << "Previously loaded DBC file count: " << filecount;
|
||||
for (int i=0; i<filecount; i++)
|
||||
{
|
||||
QString filename = settings.value("DBC/Filename_" + QString(i),"").toString();
|
||||
QString filename = settings.value("DBC/Filename_" + QString::number(i),"").toString();
|
||||
DBCFile * file = loadDBCFile(filename);
|
||||
if (file)
|
||||
{
|
||||
int bus = settings.value("DBC/AssocBus_" + QString(i),0).toInt();
|
||||
int bus = settings.value("DBC/AssocBus_" + QString::number(i),0).toInt();
|
||||
file->setAssocBus(bus);
|
||||
|
||||
MatchingCriteria_t matchingCriteria = (MatchingCriteria_t)settings.value("DBC/MatchingCriteria_" + QString(i),0).toInt();
|
||||
MatchingCriteria_t matchingCriteria = (MatchingCriteria_t)settings.value("DBC/MatchingCriteria_" + QString::number(i),0).toInt();
|
||||
|
||||
DBC_ATTRIBUTE attr;
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
void setAssocBus(int bus);
|
||||
void setDirtyFlag();
|
||||
bool getDirtyFlag();
|
||||
void clearDirtyFlag();
|
||||
void sort();
|
||||
|
||||
DBCMessageHandler *messageHandler;
|
||||
|
||||
@@ -108,10 +108,10 @@ void DBCLoadSaveWindow::updateSettings()
|
||||
qDebug() << "Save DBC settings #" << i << " File: " << file->getFullFilename()
|
||||
<< "Bus: " << file->getAssocBus() << "MC: " << file->messageHandler->getMatchingCriteria()
|
||||
<< "Filter Labeling: " << (file->messageHandler->filterLabeling() ? "enabled" : "disabled");
|
||||
settings.setValue("DBC/Filename_" + QString(i), file->getFullFilename());
|
||||
settings.setValue("DBC/AssocBus_" + QString(i), file->getAssocBus());
|
||||
settings.setValue("DBC/MatchingCriteria_" + QString(i), file->messageHandler->getMatchingCriteria());
|
||||
settings.setValue("DBC/FilterLabeling_" + QString(i), file->messageHandler->filterLabeling());
|
||||
settings.setValue("DBC/Filename_" + QString::number(i), file->getFullFilename());
|
||||
settings.setValue("DBC/AssocBus_" + QString::number(i), file->getAssocBus());
|
||||
settings.setValue("DBC/MatchingCriteria_" + QString::number(i), file->messageHandler->getMatchingCriteria());
|
||||
settings.setValue("DBC/FilterLabeling_" + QString::number(i), file->messageHandler->filterLabeling());
|
||||
}
|
||||
}
|
||||
emit updatedDBCSettings();
|
||||
@@ -200,7 +200,7 @@ void DBCLoadSaveWindow::loadFile()
|
||||
|
||||
DBC_ATTRIBUTE *attr = file->findAttributeByName("matchingcriteria");
|
||||
QComboBox * mc_item = addMatchingCriteriaCombobox(idx);
|
||||
if (attr && attr->defaultValue > 0)
|
||||
if (attr && attr->defaultValue.toInt() > 0)
|
||||
{
|
||||
mc_item->setCurrentIndex(attr->defaultValue.toInt());
|
||||
}
|
||||
@@ -208,7 +208,7 @@ void DBCLoadSaveWindow::loadFile()
|
||||
attr = file->findAttributeByName("filterlabeling");
|
||||
QTableWidgetItem *item = new QTableWidgetItem("");
|
||||
ui->tableFiles->setItem(idx, 3, item);
|
||||
if (attr && attr->defaultValue > 0)
|
||||
if (attr && attr->defaultValue.toInt() > 0)
|
||||
{
|
||||
item->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
@@ -675,6 +675,9 @@ void DBCMainEditor::newMessage()
|
||||
msgItem = nodeItem->parent();
|
||||
nodeItem = msgItem->parent();
|
||||
}
|
||||
if (typ == DBCItemTypes::NODE){
|
||||
msgItem = nodeItem;
|
||||
}
|
||||
|
||||
//if there was a comment this will find the location of the comment and snip it out.
|
||||
QString nodeName = nodeItem->data(0, Qt::DisplayRole).toString().split(" - ")[0];
|
||||
@@ -702,6 +705,7 @@ void DBCMainEditor::newMessage()
|
||||
msg.name = nodeName + "Msg" + QString::number(randGen.bounded(500));
|
||||
msg.ID = 0;
|
||||
msg.len = 8;
|
||||
msg.bgColor = QApplication::palette().color(QPalette::Base);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+316
-131
@@ -37,7 +37,9 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
|
||||
ui->bitfield->setMode(GridMode::SIGNAL_VIEW);
|
||||
|
||||
connect(ui->bitfield, SIGNAL(gridClicked(int)), this, SLOT(bitfieldClicked(int)));
|
||||
connect(ui->bitfield, SIGNAL(gridClicked(int)), this, SLOT(bitfieldLeftClicked(int)));
|
||||
connect(ui->bitfield, SIGNAL(gridRightClicked(int)), this, SLOT(bitfieldRightClicked(int)));
|
||||
|
||||
connect(ui->valuesTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onCustomMenuValues(QPoint)));
|
||||
ui->valuesTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->valuesTable, SIGNAL(cellChanged(int,int)), this, SLOT(onValuesCellChanged(int,int)));
|
||||
@@ -47,18 +49,29 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
[=]()
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
if (currentSignal->intelByteOrder != ui->cbIntelFormat->isChecked()) dbcFile->setDirtyFlag();
|
||||
currentSignal->intelByteOrder = ui->cbIntelFormat->isChecked();
|
||||
fillSignalForm(currentSignal);
|
||||
if (currentSignal->intelByteOrder != ui->cbIntelFormat->isChecked())
|
||||
{
|
||||
dbcFile->setDirtyFlag();
|
||||
pushToUndoBuffer();
|
||||
currentSignal->intelByteOrder = ui->cbIntelFormat->isChecked();
|
||||
//fillSignalForm(currentSignal);
|
||||
refreshBitGrid();
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->comboReceiver, &QComboBox::currentTextChanged,
|
||||
[=]()
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
if (inhibitMsgProc) return;
|
||||
|
||||
DBC_NODE *node = dbcFile->findNodeByName(ui->comboReceiver->currentText());
|
||||
if (currentSignal->receiver != node) dbcFile->setDirtyFlag();
|
||||
currentSignal->receiver = node;
|
||||
if (currentSignal->receiver != node)
|
||||
{
|
||||
dbcFile->setDirtyFlag();
|
||||
pushToUndoBuffer();
|
||||
currentSignal->receiver = node;
|
||||
}
|
||||
});
|
||||
connect(ui->comboType, &QComboBox::currentTextChanged,
|
||||
[=]()
|
||||
@@ -67,38 +80,66 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
switch (ui->comboType->currentIndex())
|
||||
{
|
||||
case 0:
|
||||
currentSignal->valType = UNSIGNED_INT;
|
||||
if (currentSignal->valType != UNSIGNED_INT)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
currentSignal->valType = UNSIGNED_INT;
|
||||
dbcFile->setDirtyFlag();
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
currentSignal->valType = SIGNED_INT;
|
||||
if (currentSignal->valType != SIGNED_INT)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
currentSignal->valType = SIGNED_INT;
|
||||
dbcFile->setDirtyFlag();
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
currentSignal->valType = SP_FLOAT;
|
||||
if (dbcMessage) //if we have a good msg reference we can use it to get the # of bytes expected.
|
||||
if (currentSignal->valType != SP_FLOAT)
|
||||
{
|
||||
int maxBit = ((dbcMessage->len * 8) - 32 + 7);
|
||||
if (maxBit < 0) maxBit = 0;
|
||||
if (currentSignal->startBit > maxBit) currentSignal->startBit = maxBit;
|
||||
pushToUndoBuffer();
|
||||
currentSignal->valType = SP_FLOAT;
|
||||
dbcFile->setDirtyFlag();
|
||||
if (dbcMessage) //if we have a good msg reference we can use it to get the # of bytes expected.
|
||||
{
|
||||
int maxBit = ((dbcMessage->len * 8) - 32 + 7);
|
||||
if (maxBit < 0) maxBit = 0;
|
||||
if (currentSignal->startBit > maxBit) currentSignal->startBit = maxBit;
|
||||
}
|
||||
else if (currentSignal->startBit > 39) currentSignal->startBit = 39;
|
||||
currentSignal->signalSize = 32;
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
else if (currentSignal->startBit > 39) currentSignal->startBit = 39;
|
||||
currentSignal->signalSize = 32;
|
||||
break;
|
||||
case 3:
|
||||
currentSignal->valType = DP_FLOAT;
|
||||
if (dbcMessage)
|
||||
if (currentSignal->valType != DP_FLOAT)
|
||||
{
|
||||
int maxBit = ((dbcMessage->len * 8) - 64 + 7);
|
||||
if (currentSignal->startBit > maxBit) currentSignal->startBit = maxBit;
|
||||
pushToUndoBuffer();
|
||||
currentSignal->valType = DP_FLOAT;
|
||||
dbcFile->setDirtyFlag();
|
||||
if (dbcMessage)
|
||||
{
|
||||
int maxBit = ((dbcMessage->len * 8) - 64 + 7);
|
||||
if (currentSignal->startBit > maxBit) currentSignal->startBit = maxBit;
|
||||
}
|
||||
else currentSignal->startBit = 7; //has to be!
|
||||
currentSignal->signalSize = 64;
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
else currentSignal->startBit = 7; //has to be!
|
||||
currentSignal->signalSize = 64;
|
||||
break;
|
||||
case 4:
|
||||
currentSignal->valType = STRING;
|
||||
if (currentSignal->valType != STRING)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
currentSignal->valType = STRING;
|
||||
dbcFile->setDirtyFlag();
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
dbcFile->setDirtyFlag();
|
||||
fillSignalForm(currentSignal);
|
||||
});
|
||||
connect(ui->txtBias, &QLineEdit::editingFinished,
|
||||
[=]()
|
||||
@@ -109,8 +150,12 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
temp = ui->txtBias->text().toDouble(&result);
|
||||
if (result)
|
||||
{
|
||||
if (currentSignal->bias != temp) dbcFile->setDirtyFlag();
|
||||
currentSignal->bias = temp;
|
||||
if (currentSignal->bias != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->bias = temp;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -123,8 +168,12 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
temp = ui->txtMaxVal->text().toDouble(&result);
|
||||
if (result)
|
||||
{
|
||||
if (currentSignal->max != temp) dbcFile->setDirtyFlag();
|
||||
currentSignal->max = temp;
|
||||
if (currentSignal->max != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->max = temp;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -137,10 +186,15 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
temp = ui->txtMinVal->text().toDouble(&result);
|
||||
if (result)
|
||||
{
|
||||
if (currentSignal->min != temp) dbcFile->setDirtyFlag();
|
||||
currentSignal->min = temp;
|
||||
if (currentSignal->min != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->min = temp;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtScale, &QLineEdit::editingFinished,
|
||||
[=]()
|
||||
{
|
||||
@@ -150,26 +204,40 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
temp = ui->txtScale->text().toDouble(&result);
|
||||
if (result)
|
||||
{
|
||||
if (currentSignal->factor != temp) dbcFile->setDirtyFlag();
|
||||
currentSignal->factor = temp;
|
||||
if (currentSignal->factor != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->factor = temp;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtComment, &QLineEdit::editingFinished,
|
||||
[=]()
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
if (currentSignal->comment != ui->txtComment->text().simplified().replace(' ','_')) dbcFile->setDirtyFlag();
|
||||
currentSignal->comment = ui->txtComment->text().simplified().replace(' ', '_');
|
||||
emit updatedTreeInfo(currentSignal);
|
||||
if (currentSignal->comment != ui->txtComment->text().simplified().replace(' ','_'))
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->comment = ui->txtComment->text().simplified().replace(' ', '_');
|
||||
emit updatedTreeInfo(currentSignal);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtUnitName, &QLineEdit::editingFinished,
|
||||
[=]()
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
if (currentSignal->unitName != ui->txtUnitName->text().simplified().replace(' ','_')) dbcFile->setDirtyFlag();
|
||||
currentSignal->unitName = ui->txtUnitName->text().simplified().replace(' ', '_');
|
||||
if (currentSignal->unitName != ui->txtUnitName->text().simplified().replace(' ','_'))
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->unitName = ui->txtUnitName->text().simplified().replace(' ', '_');
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtBitLength, &QLineEdit::textChanged,
|
||||
[=]()
|
||||
{
|
||||
@@ -182,20 +250,35 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
if (temp > (int)(dbcMessage->len * 8)) return;
|
||||
}
|
||||
else if (temp > 64) return;
|
||||
if (currentSignal->signalSize != temp) dbcFile->setDirtyFlag();
|
||||
if (currentSignal->valType != SP_FLOAT && currentSignal->valType != DP_FLOAT)
|
||||
|
||||
if (currentSignal->valType == SP_FLOAT) temp = 32;
|
||||
if (currentSignal->valType == DP_FLOAT) temp = 64;
|
||||
|
||||
if (currentSignal->signalSize != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->signalSize = temp;
|
||||
fillSignalForm(currentSignal);
|
||||
//fillSignalForm(currentSignal);
|
||||
refreshBitGrid();
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtName, &QLineEdit::editingFinished,
|
||||
[=]()
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
QString tempNameStr = ui->txtName->text().simplified().replace(' ', '_');
|
||||
if (currentSignal->name != tempNameStr) dbcFile->setDirtyFlag();
|
||||
if (tempNameStr.length() > 0) currentSignal->name = tempNameStr;
|
||||
//need to update the tree too.
|
||||
emit updatedTreeInfo(currentSignal);
|
||||
if (tempNameStr.length() == 0) return; //can't do that!
|
||||
if (currentSignal->name != tempNameStr)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->name = tempNameStr;
|
||||
refreshBitGrid();
|
||||
//need to update the tree too.
|
||||
emit updatedTreeInfo(currentSignal);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtMultiplexLow, &QLineEdit::editingFinished,
|
||||
@@ -204,9 +287,13 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
if (currentSignal == nullptr) return;
|
||||
int temp;
|
||||
temp = Utility::ParseStringToNum(ui->txtMultiplexLow->text());
|
||||
if (currentSignal->multiplexLowValue != temp) dbcFile->setDirtyFlag();
|
||||
//TODO: could look up the multiplexor and ensure that the value is within a range that the multiplexor could return
|
||||
currentSignal->multiplexLowValue = temp;
|
||||
if (currentSignal->multiplexLowValue != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
//TODO: could look up the multiplexor and ensure that the value is within a range that the multiplexor could return
|
||||
currentSignal->multiplexLowValue = temp;
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->txtMultiplexHigh, &QLineEdit::editingFinished,
|
||||
@@ -215,78 +302,98 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
if (!currentSignal) return;
|
||||
int temp;
|
||||
temp = Utility::ParseStringToNum(ui->txtMultiplexHigh->text());
|
||||
if (currentSignal->multiplexHighValue != temp) dbcFile->setDirtyFlag();
|
||||
//TODO: could look up the multiplexor and ensure that the value is within a range that the multiplexor could return
|
||||
currentSignal->multiplexHighValue = temp;
|
||||
if (currentSignal->multiplexHighValue != temp)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
//TODO: could look up the multiplexor and ensure that the value is within a range that the multiplexor could return
|
||||
currentSignal->multiplexHighValue = temp;
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->rbExtended, &QRadioButton::toggled,
|
||||
[=](bool state)
|
||||
{
|
||||
if (!currentSignal) return;
|
||||
if (state && currentSignal) //signal is now set as an extended multiplex/multiplexor
|
||||
if (!state) return; //we only need to handle the case where it is true
|
||||
|
||||
//only do anything if this is different from the current state. It should be because we're in a toggle event but let's be sure
|
||||
if (!currentSignal->isMultiplexed || !currentSignal->isMultiplexor)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->isMultiplexed = true;
|
||||
currentSignal->isMultiplexor = true;
|
||||
//an extended multi signal cannot be the root multiplexor for a message so make sure to remove it if it was.
|
||||
if (dbcMessage->multiplexorSignal == currentSignal) dbcMessage->multiplexorSignal = nullptr;
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
dbcFile->setDirtyFlag();
|
||||
});
|
||||
|
||||
connect(ui->rbMultiplexed, &QRadioButton::toggled,
|
||||
[=](bool state)
|
||||
{
|
||||
if (!currentSignal) return;
|
||||
if (state && currentSignal) //signal is now set as a multiplexed signal
|
||||
if (!state) return; //we only need to handle the case where it is true
|
||||
|
||||
//only do anything if this is different from the current state. It should be because we're in a toggle event but let's be sure
|
||||
if (!currentSignal->isMultiplexed || currentSignal->isMultiplexor)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->isMultiplexed = true;
|
||||
currentSignal->isMultiplexor = false;
|
||||
//if the set multiplexor for the message was this signal then clear it
|
||||
if (dbcMessage->multiplexorSignal == currentSignal) dbcMessage->multiplexorSignal = nullptr;
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
dbcFile->setDirtyFlag();
|
||||
});
|
||||
|
||||
connect(ui->rbMultiplexor, &QRadioButton::toggled,
|
||||
[=](bool state)
|
||||
{
|
||||
if (!currentSignal) return;
|
||||
if (state && currentSignal) //signal is now set as a multiplexed signal
|
||||
if (!state) return; //we only need to handle the case where it is true
|
||||
|
||||
if (currentSignal->isMultiplexed || !currentSignal->isMultiplexor)
|
||||
{
|
||||
//don't allow this signal to be a multiplexor if there is already one for this message.
|
||||
//if (dbcMessage->multiplexorSignal != currentSignal && dbcMessage->multiplexorSignal != nullptr) return; //I spoke too soon above...
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->isMultiplexed = false;
|
||||
currentSignal->isMultiplexor = true;
|
||||
//we just set that this is the multiplexor so update the message to show that as well.
|
||||
dbcMessage->multiplexorSignal = currentSignal;
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
dbcFile->setDirtyFlag();
|
||||
});
|
||||
|
||||
connect(ui->rbNotMulti, &QRadioButton::toggled,
|
||||
[=](bool state)
|
||||
{
|
||||
if (!currentSignal) return;
|
||||
if (state && currentSignal) //signal is now set as a multiplexed signal
|
||||
if (!state) return; //we only need to handle the case where it is true
|
||||
|
||||
if (currentSignal->isMultiplexed || currentSignal->isMultiplexor)
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
currentSignal->isMultiplexed = false;
|
||||
currentSignal->isMultiplexor = false;
|
||||
if (dbcMessage->multiplexorSignal == currentSignal) dbcMessage->multiplexorSignal = nullptr;
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
ui->txtMultiplexLow->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->txtMultiplexHigh->setEnabled(currentSignal->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(currentSignal->isMultiplexed);
|
||||
dbcFile->setDirtyFlag();
|
||||
});
|
||||
|
||||
connect(ui->cbMultiplexParent, &QComboBox::textActivated,
|
||||
@@ -294,17 +401,20 @@ DBCSignalEditor::DBCSignalEditor(QWidget *parent) :
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
if (inhibitMsgProc) return;
|
||||
|
||||
//qDebug() << "Curr text: :" << ui->cbMultiplexParent->currentText();
|
||||
//try to look up the signal that we're set to now, remove this signal from existing children list
|
||||
//add it to this one, update this signal's parent multiplexor
|
||||
DBC_SIGNAL *newSig = dbcMessage->sigHandler->findSignalByName(ui->cbMultiplexParent->currentText());
|
||||
DBC_SIGNAL *oldParent = currentSignal->multiplexParent;
|
||||
if (newSig && oldParent)
|
||||
if (newSig && oldParent && (newSig != oldParent))
|
||||
{
|
||||
pushToUndoBuffer();
|
||||
dbcFile->setDirtyFlag();
|
||||
oldParent->multiplexedChildren.removeOne(currentSignal);
|
||||
currentSignal->multiplexParent = newSig;
|
||||
newSig->multiplexedChildren.append(currentSignal);
|
||||
dbcFile->setDirtyFlag();
|
||||
refreshBitGrid();
|
||||
emit updatedTreeInfo(currentSignal);
|
||||
}
|
||||
});
|
||||
@@ -333,6 +443,12 @@ bool DBCSignalEditor::eventFilter(QObject *obj, QEvent *event)
|
||||
case Qt::Key_F1:
|
||||
HelpWindow::getRef()->showHelp("signaleditor.md");
|
||||
break;
|
||||
case Qt::Key_Z:
|
||||
if (keyEvent->modifiers() == Qt::ControlModifier)
|
||||
{
|
||||
popFromUndoBuffer();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@@ -392,18 +508,6 @@ void DBCSignalEditor::showEvent(QShowEvent* event)
|
||||
|
||||
fillSignalForm(currentSignal);
|
||||
fillValueTable(currentSignal);
|
||||
|
||||
ui->bitfield->clearSignalNames();
|
||||
for (int x = 0; x < dbcMessage->sigHandler->getCount(); x++)
|
||||
{
|
||||
DBC_SIGNAL *sig = dbcMessage->sigHandler->findSignalByIdx(x);
|
||||
//only set a signal name for signals which match multiplexparent with our currentsignal
|
||||
if (!sig->multiplexParent || ((sig->multiplexParent == currentSignal->multiplexParent) && (sig->multiplexHighValue == currentSignal->multiplexHighValue)) )
|
||||
{
|
||||
ui->bitfield->setSignalNames(x, sig->name);
|
||||
qDebug() << sig->name << sig->multiplexParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBCSignalEditor::refreshView()
|
||||
@@ -467,12 +571,14 @@ void DBCSignalEditor::deleteCurrentValue()
|
||||
/* WARNING: fillSignalForm can be called recursively since it is in the listener of cbIntelFormat */
|
||||
void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
{
|
||||
unsigned char bitpattern[64];
|
||||
//sanity checks
|
||||
if (!dbcMessage) return;
|
||||
if (!dbcMessage->sigHandler) return;
|
||||
|
||||
inhibitMsgProc = true;
|
||||
|
||||
if (sig == nullptr) {
|
||||
ui->groupBox->setEnabled(false);
|
||||
//ui->groupBox->setEnabled(false);
|
||||
ui->txtName->setText("");
|
||||
ui->txtBias->setText("");
|
||||
ui->txtBitLength->setText("");
|
||||
@@ -486,9 +592,6 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
ui->rbMultiplexed->setChecked(false);
|
||||
ui->rbMultiplexor->setChecked(false);
|
||||
ui->rbNotMulti->setChecked(true);
|
||||
memset(bitpattern, 0, 64); //clear it out
|
||||
ui->bitfield->setReference(bitpattern, false);
|
||||
ui->bitfield->updateData(bitpattern, true);
|
||||
ui->comboReceiver->setCurrentIndex(0);
|
||||
ui->comboType->setCurrentIndex(0);
|
||||
inhibitMsgProc = false;
|
||||
@@ -496,9 +599,8 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
}
|
||||
|
||||
/* we have a signal */
|
||||
ui->groupBox->setEnabled(true);
|
||||
//ui->groupBox->setEnabled(true);
|
||||
|
||||
generateUsedBits();
|
||||
ui->txtName->setText(sig->name);
|
||||
ui->txtBias->setText(QString::number(sig->bias));
|
||||
ui->txtBitLength->setText(QString::number(sig->signalSize));
|
||||
@@ -532,7 +634,9 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
DBC_SIGNAL *sig_iter = dbcMessage->sigHandler->findSignalByIdx(i);
|
||||
if (sig_iter && sig_iter->isMultiplexor && (sig_iter != sig))
|
||||
{
|
||||
ui->cbMultiplexParent->addItem(sig_iter->name);
|
||||
//only add this entry if there are no other entries with that name yet
|
||||
if (ui->cbMultiplexParent->findText(sig_iter->name) == -1)
|
||||
ui->cbMultiplexParent->addItem(sig_iter->name);
|
||||
if (sig->multiplexParent == sig_iter) ui->cbMultiplexParent->setCurrentIndex(ui->cbMultiplexParent->count() - 1);
|
||||
}
|
||||
}
|
||||
@@ -541,42 +645,6 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
ui->txtMultiplexHigh->setEnabled(sig->isMultiplexed);
|
||||
ui->cbMultiplexParent->setEnabled(sig->isMultiplexed);
|
||||
|
||||
memset(bitpattern, 0, 64); //clear it out first.
|
||||
|
||||
int startBit, endBit;
|
||||
|
||||
startBit = sig->startBit;
|
||||
|
||||
bitpattern[startBit / 8] |= 1 << (startBit % 8); //make the start bit a different color to set it apart
|
||||
ui->bitfield->setReference(bitpattern, false);
|
||||
|
||||
if (sig->intelByteOrder)
|
||||
{
|
||||
endBit = startBit + sig->signalSize - 1;
|
||||
if (startBit < 0) startBit = 0;
|
||||
if (endBit > 511) endBit = 511;
|
||||
for (int y = startBit; y <= endBit; y++)
|
||||
{
|
||||
int byt = y / 8;
|
||||
bitpattern[byt] |= 1 << (y % 8);
|
||||
}
|
||||
}
|
||||
else //big endian / motorola format
|
||||
{
|
||||
//much more irritating than the intel version...
|
||||
int size = sig->signalSize;
|
||||
while (size > 0)
|
||||
{
|
||||
int byt = startBit / 8;
|
||||
bitpattern[byt] |= 1 << (startBit % 8);
|
||||
size--;
|
||||
if ((startBit % 8) == 0) startBit += 15;
|
||||
else startBit--;
|
||||
if (startBit > 511) startBit = 511;
|
||||
}
|
||||
}
|
||||
|
||||
ui->bitfield->updateData(bitpattern, true);
|
||||
ui->cbIntelFormat->setChecked(sig->intelByteOrder);
|
||||
|
||||
switch (sig->valType)
|
||||
@@ -607,9 +675,71 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig)
|
||||
}
|
||||
}
|
||||
|
||||
refreshBitGrid();
|
||||
|
||||
inhibitMsgProc = false;
|
||||
}
|
||||
|
||||
void DBCSignalEditor::refreshBitGrid()
|
||||
{
|
||||
unsigned char bitpattern[64];
|
||||
|
||||
memset(bitpattern, 0, 64); //clear it out
|
||||
ui->bitfield->setReference(bitpattern, false);
|
||||
ui->bitfield->updateData(bitpattern, true);
|
||||
|
||||
ui->bitfield->clearSignalNames();
|
||||
for (int x = 0; x < dbcMessage->sigHandler->getCount(); x++)
|
||||
{
|
||||
DBC_SIGNAL *sig = dbcMessage->sigHandler->findSignalByIdx(x);
|
||||
//only set a signal name for signals which match multiplexparent with our currentsignal
|
||||
if (!sig->multiplexParent || ((sig->multiplexParent == currentSignal->multiplexParent) && (sig->multiplexHighValue == currentSignal->multiplexHighValue)) )
|
||||
{
|
||||
ui->bitfield->setSignalNames(x, sig->name);
|
||||
//qDebug() << sig->name << sig->multiplexParent;
|
||||
}
|
||||
}
|
||||
|
||||
generateUsedBits();
|
||||
memset(bitpattern, 0, 64); //clear it out first.
|
||||
|
||||
int startBit, endBit;
|
||||
|
||||
startBit = currentSignal->startBit;
|
||||
|
||||
bitpattern[startBit / 8] |= 1 << (startBit % 8); //make the start bit a different color to set it apart
|
||||
ui->bitfield->setReference(bitpattern, false);
|
||||
|
||||
if (currentSignal->intelByteOrder)
|
||||
{
|
||||
endBit = startBit + currentSignal->signalSize - 1;
|
||||
if (startBit < 0) startBit = 0;
|
||||
if (endBit > 511) endBit = 511;
|
||||
for (int y = startBit; y <= endBit; y++)
|
||||
{
|
||||
int byt = y / 8;
|
||||
bitpattern[byt] |= 1 << (y % 8);
|
||||
}
|
||||
}
|
||||
else //big endian / motorola format
|
||||
{
|
||||
//much more irritating than the intel version...
|
||||
int size = currentSignal->signalSize;
|
||||
while (size > 0)
|
||||
{
|
||||
int byt = startBit / 8;
|
||||
bitpattern[byt] |= 1 << (startBit % 8);
|
||||
size--;
|
||||
if ((startBit % 8) == 0) startBit += 15;
|
||||
else startBit--;
|
||||
if (startBit > 511) startBit = 511;
|
||||
}
|
||||
}
|
||||
|
||||
ui->bitfield->updateData(bitpattern, true);
|
||||
|
||||
}
|
||||
|
||||
/* fillValueTable also handles "enabled" state */
|
||||
void DBCSignalEditor::fillValueTable(DBC_SIGNAL *sig)
|
||||
{
|
||||
@@ -644,9 +774,12 @@ void DBCSignalEditor::fillValueTable(DBC_SIGNAL *sig)
|
||||
inhibitCellChanged = false;
|
||||
}
|
||||
|
||||
void DBCSignalEditor::bitfieldClicked(int bit)
|
||||
//Left clicking the grid sets the "starting bit" for the current signal
|
||||
void DBCSignalEditor::bitfieldLeftClicked(int bit)
|
||||
{
|
||||
if (currentSignal == nullptr) return;
|
||||
|
||||
pushToUndoBuffer();
|
||||
currentSignal->startBit = bit;
|
||||
if (currentSignal->valType == SP_FLOAT)
|
||||
{
|
||||
@@ -672,6 +805,28 @@ void DBCSignalEditor::bitfieldClicked(int bit)
|
||||
fillSignalForm(currentSignal);
|
||||
}
|
||||
|
||||
//Right clicking the grid starts editing on whichever signal currently "owns" that bit.
|
||||
//If there is no other signal then nothing happens (right now).
|
||||
//Would be possible to create a new signal in that case
|
||||
void DBCSignalEditor::bitfieldRightClicked(int bit)
|
||||
{
|
||||
//will return -1 if there is no signal there. Otherwise, returns signal number
|
||||
//which is quite luckily also the index into the signal handler table
|
||||
int sigNum = ui->bitfield->getUsedSignalNum(bit);
|
||||
if (sigNum < 0) return;
|
||||
|
||||
pushToUndoBuffer(); // undo to resume editing the previous signal
|
||||
|
||||
currentSignal = dbcMessage->sigHandler->findSignalByIdx(sigNum);
|
||||
|
||||
if (currentSignal)
|
||||
{
|
||||
fillSignalForm(currentSignal);
|
||||
fillValueTable(currentSignal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DBCSignalEditor::generateUsedBits()
|
||||
{
|
||||
uint8_t usedBits[64];
|
||||
@@ -728,3 +883,33 @@ void DBCSignalEditor::generateUsedBits()
|
||||
ui->bitfield->setUsed(usedBits, false);
|
||||
ui->bitfield->setBytesToDraw(dbcMessage->len);
|
||||
}
|
||||
|
||||
//Copy the current signal in its entirety to the undo buffer. Just for safe keeping
|
||||
//Called before an edit is done to save the state so we can revert if necessary
|
||||
void DBCSignalEditor::pushToUndoBuffer()
|
||||
{
|
||||
if (!currentSignal) return;
|
||||
//store a copy of the pointer so that if we need to pop we can pop to the proper place
|
||||
currentSignal->self = currentSignal;
|
||||
undoBuffer.append(*currentSignal); //save the whole thing
|
||||
qDebug() << "Pushing to undo buffer";
|
||||
}
|
||||
|
||||
//Pop the last copy of a signal from the stack and begin editing it
|
||||
void DBCSignalEditor::popFromUndoBuffer()
|
||||
{
|
||||
if (undoBuffer.empty())
|
||||
{
|
||||
dbcFile->clearDirtyFlag(); //TODO: Don't do this. Implement per-item dirty flags.
|
||||
qDebug() << "Undo buffer empty";
|
||||
return; //can't pop if there are no stored entries!
|
||||
}
|
||||
qDebug() << "Popping undo buffer";
|
||||
DBC_SIGNAL sig = undoBuffer.back();
|
||||
undoBuffer.pop_back();
|
||||
currentSignal = sig.self; //restore the pointer
|
||||
*currentSignal = sig; //write the contents into the memory pointed to
|
||||
|
||||
fillSignalForm(currentSignal);
|
||||
fillValueTable(currentSignal);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ signals:
|
||||
void updatedTreeInfo(DBC_SIGNAL *sig);
|
||||
|
||||
private slots:
|
||||
void bitfieldClicked(int bit);
|
||||
void bitfieldLeftClicked(int bit);
|
||||
void bitfieldRightClicked(int bit);
|
||||
void onValuesCellChanged(int row,int col);
|
||||
void onCustomMenuValues(QPoint);
|
||||
void deleteCurrentValue();
|
||||
@@ -36,6 +37,7 @@ private:
|
||||
DBCHandler *dbcHandler;
|
||||
DBC_MESSAGE *dbcMessage;
|
||||
DBC_SIGNAL *currentSignal;
|
||||
QList<DBC_SIGNAL> undoBuffer;
|
||||
DBCFile *dbcFile;
|
||||
bool inhibitCellChanged;
|
||||
bool inhibitMsgProc;
|
||||
@@ -43,11 +45,14 @@ private:
|
||||
void fillSignalForm(DBC_SIGNAL *sig);
|
||||
void fillValueTable(DBC_SIGNAL *sig);
|
||||
void generateUsedBits();
|
||||
void refreshBitGrid();
|
||||
|
||||
void closeEvent(QCloseEvent *event);
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
void pushToUndoBuffer();
|
||||
void popFromUndoBuffer();
|
||||
};
|
||||
|
||||
#endif // DBCSIGNALEDITOR_H
|
||||
|
||||
Reference in New Issue
Block a user