diff --git a/dbchandler.cpp b/dbchandler.cpp index ce2b652..396c095 100644 --- a/dbchandler.cpp +++ b/dbchandler.cpp @@ -739,7 +739,7 @@ bool DBCHandler::processSignalDouble(const CANFrame &frame, const DBC_SIGNAL &si { result = Utility::processIntegerSignal(frame.data, sig.startBit, sig.signalSize, sig.intelByteOrder, isSigned); endResult = ((double)result * sig.factor) + sig.bias; - result = (int64_t)endResult; + result = (int64_t)endResult; } else if (sig.valType == SP_FLOAT) { diff --git a/graphingwindow.cpp b/graphingwindow.cpp index cc33d57..70aae97 100644 --- a/graphingwindow.cpp +++ b/graphingwindow.cpp @@ -799,178 +799,43 @@ void GraphingWindow::addNewGraph() void GraphingWindow::appendToGraph(GraphParams ¶ms, CANFrame &frame) { int64_t tempVal; //64 bit temp value. - if (params.endByte == -1 || params.startByte == params.endByte) + if (params.isDBCSignal) { - tempVal = (frame.data[params.startByte] & params.mask); - if (params.isSigned && tempVal > 127) - { - tempVal = tempVal - 256; - } - if (secondsMode) - { - params.x.append((double)(frame.timestamp) / 1000000.0 - params.xbias); - } - else - { - params.x.append(frame.timestamp - params.xbias); - } - params.y.append((tempVal * params.scale) + params.bias); + } - else if (params.endByte > params.startByte) //big endian + else { - float tempValue; - int64_t tempValInt; - int numBytes = (params.endByte - params.startByte) + 1; - int64_t shiftRef = 1 << (numBytes * 8); - uint64_t maskShifter; - uint8_t tempByte; - tempValInt = 0; - int64_t expon = 1; - maskShifter = params.mask; - for (int c = 0; c < numBytes; c++) + if (params.endByte == -1 || params.startByte == params.endByte) { - tempByte = frame.data[params.endByte - c]; - tempByte &= maskShifter; - tempValInt += (tempByte * expon); - expon *= 256; - maskShifter = maskShifter >> 8; - } - - tempValInt &= params.mask; - - int64_t twocompPoint = params.mask; - if (shiftRef < twocompPoint || twocompPoint == -1) twocompPoint = shiftRef; - //qDebug() << "two comp point: " << twocompPoint; - if (params.isSigned && tempValInt > ((twocompPoint / 2))) - { - tempValInt = tempValInt - twocompPoint; - } - - tempValue = (float)tempValInt; - - if (secondsMode) - { - params.x.append((double)(frame.timestamp) / 1000000.0 - params.xbias); - } - else - { - params.x.append(frame.timestamp - params.xbias); - } - - params.y.append((tempValue * params.scale) + params.bias); - } - else //little endian - { - float tempValue; - int64_t tempValInt; - int numBytes = (params.startByte - params.endByte) + 1; - int64_t shiftRef = 1 << (numBytes * 8); - uint64_t maskShifter; - uint8_t tempByte; - tempValInt = 0; - int64_t expon = 1; - maskShifter = params.mask; - for (int c = 0; c < numBytes; c++) - { - tempByte = frame.data[params.endByte + c]; - tempByte &= maskShifter; - tempValInt += tempByte * expon; - expon *= 256; - maskShifter = maskShifter >> 8; - } - tempValInt &= params.mask; - - int64_t twocompPoint = params.mask; - if (shiftRef < twocompPoint || twocompPoint == -1) twocompPoint = shiftRef; - //qDebug() << "two comp point: " << twocompPoint; - if (params.isSigned && tempValInt > ((twocompPoint / 2))) - { - tempValInt = tempValInt - twocompPoint; - } - - tempValue = (float)tempValInt; - - if (secondsMode) - { - params.x.append((double)(frame.timestamp) / 1000000.0 - params.xbias); - } - else - { - params.x.append(frame.timestamp - params.xbias); - } - - params.y.append((tempValue * params.scale) + params.bias); - } - - params.ref->setData(params.x,params.y); -} - -void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam) -{ - int64_t tempVal; //64 bit temp value. - float yminval=10000000.0, ymaxval = -1000000.0; - float xminval=10000000000.0, xmaxval = -10000000000.0; - GraphParams *refParam = ¶ms; - - qDebug() << "New Graph ID: " << params.ID; - qDebug() << "Start byte: " << params.startByte; - qDebug() << "End Byte: " << params.endByte; - qDebug() << "Mask: " << params.mask; - - frameCache.clear(); - for (int i = 0; i < modelFrames->count(); i++) - { - CANFrame thisFrame = modelFrames->at(i); - if (thisFrame.ID == params.ID) frameCache.append(thisFrame); - } - - int numEntries = frameCache.count() / params.stride; - - params.x.reserve(numEntries); - params.y.reserve(numEntries); - params.x.fill(0, numEntries); - params.y.fill(0, numEntries); - - if (params.endByte == -1 || params.startByte == params.endByte) - { - for (int j = 0; j < numEntries; j++) - { - tempVal = (frameCache[j * params.stride].data[params.startByte] & params.mask); + tempVal = (frame.data[params.startByte] & params.mask); if (params.isSigned && tempVal > 127) { tempVal = tempVal - 256; } if (secondsMode) { - params.x[j] = (double)(frameCache[j].timestamp) / 1000000.0; + params.x.append((double)(frame.timestamp) / 1000000.0 - params.xbias); } else { - params.x[j] = frameCache[j].timestamp; + params.x.append(frame.timestamp - params.xbias); } - params.y[j] = (tempVal * params.scale) + params.bias; - if (params.y[j] < yminval) yminval = params.y[j]; - if (params.y[j] > ymaxval) ymaxval = params.y[j]; - if (params.x[j] < xminval) xminval = params.x[j]; - if (params.x[j] > xmaxval) xmaxval = params.x[j]; + params.y.append((tempVal * params.scale) + params.bias); } - } - else if (params.endByte > params.startByte) //big endian - { - float tempValue; - int64_t tempValInt; - int numBytes = (params.endByte - params.startByte) + 1; - int64_t shiftRef = (uint64_t)1 << (numBytes * 8); - uint64_t maskShifter; - uint8_t tempByte; - for (int j = 0; j < numEntries; j++) + else if (params.endByte > params.startByte) //big endian { + float tempValue; + int64_t tempValInt; + int numBytes = (params.endByte - params.startByte) + 1; + int64_t shiftRef = 1 << (numBytes * 8); + uint64_t maskShifter; + uint8_t tempByte; tempValInt = 0; int64_t expon = 1; maskShifter = params.mask; for (int c = 0; c < numBytes; c++) { - tempByte = frameCache[j * params.stride].data[params.endByte - c]; + tempByte = frame.data[params.endByte - c]; tempByte &= maskShifter; tempValInt += (tempByte * expon); expon *= 256; @@ -991,36 +856,29 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam) if (secondsMode) { - params.x[j] = (double)(frameCache[j].timestamp) / 1000000.0; + params.x.append((double)(frame.timestamp) / 1000000.0 - params.xbias); } else { - params.x[j] = frameCache[j].timestamp; + params.x.append(frame.timestamp - params.xbias); } - params.y[j] = (tempValue * params.scale) + params.bias; - if (params.y[j] < yminval) yminval = params.y[j]; - if (params.y[j] > ymaxval) ymaxval = params.y[j]; - if (params.x[j] < xminval) xminval = params.x[j]; - if (params.x[j] > xmaxval) xmaxval = params.x[j]; + params.y.append((tempValue * params.scale) + params.bias); } - } - else //little endian - { - float tempValue; - int64_t tempValInt; - int numBytes = (params.startByte - params.endByte) + 1; - int64_t shiftRef = (uint64_t)1 << (numBytes * 8); - uint64_t maskShifter; - uint8_t tempByte; - for (int j = 0; j < numEntries; j++) + else //little endian { + float tempValue; + int64_t tempValInt; + int numBytes = (params.startByte - params.endByte) + 1; + int64_t shiftRef = 1 << (numBytes * 8); + uint64_t maskShifter; + uint8_t tempByte; tempValInt = 0; int64_t expon = 1; maskShifter = params.mask; for (int c = 0; c < numBytes; c++) { - tempByte = frameCache[j * params.stride].data[params.endByte + c]; + tempByte = frame.data[params.endByte + c]; tempByte &= maskShifter; tempValInt += tempByte * expon; expon *= 256; @@ -1040,33 +898,214 @@ void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam) if (secondsMode) { - params.x[j] = (double)(frameCache[j].timestamp) / 1000000.0; + params.x.append((double)(frame.timestamp) / 1000000.0 - params.xbias); } else { - params.x[j] = frameCache[j].timestamp; + params.x.append(frame.timestamp - params.xbias); } - params.y[j] = (tempValue * params.scale) + params.bias; - if (params.y[j] < yminval) yminval = params.y[j]; - if (params.y[j] > ymaxval) ymaxval = params.y[j]; - if (params.x[j] < xminval) xminval = params.x[j]; - if (params.x[j] > xmaxval) xmaxval = params.x[j]; + params.y.append((tempValue * params.scale) + params.bias); + } + } + + params.ref->setData(params.x,params.y); +} + +void GraphingWindow::createGraph(GraphParams ¶ms, bool createGraphParam) +{ + int64_t tempVal; //64 bit temp value. + float yminval=10000000.0, ymaxval = -1000000.0; + float xminval=10000000000.0, xmaxval = -10000000000.0; + GraphParams *refParam = ¶ms; + + if (params.isDBCSignal) + { + qDebug() << "New signal graph: " << params.signal->name <<" in ID:" << params.ID; + } + else + { + qDebug() << "New Graph ID: " << params.ID; + qDebug() << "Start byte: " << params.startByte; + qDebug() << "End Byte: " << params.endByte; + qDebug() << "Mask: " << params.mask; + } + + frameCache.clear(); + for (int i = 0; i < modelFrames->count(); i++) + { + CANFrame thisFrame = modelFrames->at(i); + if (thisFrame.ID == params.ID) frameCache.append(thisFrame); + } + + int numEntries = frameCache.count() / params.stride; + + params.x.reserve(numEntries); + params.y.reserve(numEntries); + params.x.fill(0, numEntries); + params.y.fill(0, numEntries); + + if (params.isDBCSignal) + { + double tempValue; + int l = 0; + for (int j = 0; j < numEntries; j++) + { + //if the given signal was found and successfully processed in this frame then add it to the graph + if (dbcHandler->processSignalDouble(frameCache[j], *params.signal, tempValue)) + { + //qDebug() << "tempValue: " << tempValue; + if (secondsMode) + { + params.x[l] = (double)(frameCache[j].timestamp) / 1000000.0; + } + else + { + params.x[l] = frameCache[j].timestamp; + } + params.y[l] = tempValue; + if (params.y[l] < yminval) yminval = params.y[l]; + if (params.y[l] > ymaxval) ymaxval = params.y[l]; + if (params.x[l] < xminval) xminval = params.x[l]; + if (params.x[l] > xmaxval) xmaxval = params.x[l]; + l++; + } + } + params.x.resize(l); + params.y.resize(l); + params.x.squeeze(); + params.y.squeeze(); + } + else + { + + if (params.endByte == -1 || params.startByte == params.endByte) + { + for (int j = 0; j < numEntries; j++) + { + tempVal = (frameCache[j * params.stride].data[params.startByte] & params.mask); + if (params.isSigned && tempVal > 127) + { + tempVal = tempVal - 256; + } + if (secondsMode) + { + params.x[j] = (double)(frameCache[j].timestamp) / 1000000.0; + } + else + { + params.x[j] = frameCache[j].timestamp; + } + params.y[j] = (tempVal * params.scale) + params.bias; + if (params.y[j] < yminval) yminval = params.y[j]; + if (params.y[j] > ymaxval) ymaxval = params.y[j]; + if (params.x[j] < xminval) xminval = params.x[j]; + if (params.x[j] > xmaxval) xmaxval = params.x[j]; + } + } + else if (params.endByte > params.startByte) //big endian + { + float tempValue; + int64_t tempValInt; + int numBytes = (params.endByte - params.startByte) + 1; + int64_t shiftRef = (uint64_t)1 << (numBytes * 8); + uint64_t maskShifter; + uint8_t tempByte; + for (int j = 0; j < numEntries; j++) + { + tempValInt = 0; + int64_t expon = 1; + maskShifter = params.mask; + for (int c = 0; c < numBytes; c++) + { + tempByte = frameCache[j * params.stride].data[params.endByte - c]; + tempByte &= maskShifter; + tempValInt += (tempByte * expon); + expon *= 256; + maskShifter = maskShifter >> 8; + } + + tempValInt &= params.mask; + + int64_t twocompPoint = params.mask; + if (shiftRef < twocompPoint || twocompPoint == -1) twocompPoint = shiftRef; + //qDebug() << "two comp point: " << twocompPoint; + if (params.isSigned && tempValInt > ((twocompPoint / 2))) + { + tempValInt = tempValInt - twocompPoint; + } + + tempValue = (float)tempValInt; + + if (secondsMode) + { + params.x[j] = (double)(frameCache[j].timestamp) / 1000000.0; + } + else + { + params.x[j] = frameCache[j].timestamp; + } + + params.y[j] = (tempValue * params.scale) + params.bias; + if (params.y[j] < yminval) yminval = params.y[j]; + if (params.y[j] > ymaxval) ymaxval = params.y[j]; + if (params.x[j] < xminval) xminval = params.x[j]; + if (params.x[j] > xmaxval) xmaxval = params.x[j]; + } + } + else //little endian + { + float tempValue; + int64_t tempValInt; + int numBytes = (params.startByte - params.endByte) + 1; + int64_t shiftRef = (uint64_t)1 << (numBytes * 8); + uint64_t maskShifter; + uint8_t tempByte; + for (int j = 0; j < numEntries; j++) + { + tempValInt = 0; + int64_t expon = 1; + maskShifter = params.mask; + for (int c = 0; c < numBytes; c++) + { + tempByte = frameCache[j * params.stride].data[params.endByte + c]; + tempByte &= maskShifter; + tempValInt += tempByte * expon; + expon *= 256; + maskShifter = maskShifter >> 8; + } + tempValInt &= params.mask; + + int64_t twocompPoint = params.mask; + if (shiftRef < twocompPoint || twocompPoint == -1) twocompPoint = shiftRef; + //qDebug() << "two comp point: " << twocompPoint; + if (params.isSigned && tempValInt > ((twocompPoint / 2))) + { + tempValInt = tempValInt - twocompPoint; + } + + tempValue = (float)tempValInt; + + if (secondsMode) + { + params.x[j] = (double)(frameCache[j].timestamp) / 1000000.0; + } + else + { + params.x[j] = frameCache[j].timestamp; + } + + params.y[j] = (tempValue * params.scale) + params.bias; + if (params.y[j] < yminval) yminval = params.y[j]; + if (params.y[j] > ymaxval) ymaxval = params.y[j]; + if (params.x[j] < xminval) xminval = params.x[j]; + if (params.x[j] > xmaxval) xmaxval = params.x[j]; + } } } params.xbias = 0; - /* - for (int ct = 0; ct < params.x.count(); ct++) - { - params.x[ct] -= xminval; - } - params.xbias = xminval; - xmaxval -= xminval; - xminval = 0; - */ - ui->graphingView->addGraph(); params.ref = ui->graphingView->graph(); if (createGraphParam) diff --git a/graphingwindow.h b/graphingwindow.h index 7c29e70..0c8f449 100644 --- a/graphingwindow.h +++ b/graphingwindow.h @@ -24,7 +24,9 @@ public: QColor color; QCPGraph *ref; QString graphName; - //the below stuff is used for internal purposes only + bool isDBCSignal; //is this graph actually a DBC signal? If so the below pointer should be filled out + DBC_SIGNAL *signal; + //the below stuff is used for internal purposes only - code should be refactored so these can be private QVector x, y; double xbias; }; diff --git a/mainwindow.cpp b/mainwindow.cpp index 3596f8e..baeca16 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -9,14 +9,17 @@ #include "serialworker.h" /* -Things that were planned for the GVRET-PC project but never completed. +Some notes on things I'd like to put into the program but haven't put on github (yet) Single / Multi state - The goal is to find bits that change based on toggles or discrete state items (shifters, etc) fuzzy scope - Try to find potential places where a given value might be stored - offer guesses and the program tries to find candidates for you or, try to find things that appear to be multi-byte integers -Change dbc editor to be able to do multiplexed signals +Make the graphing window use signals either exclusively or as an option for each signal graphed +Allow multiple DBC files to be loaded in the program and also allow them to be associated with a bus +Allow scripts to read/write signals from DBC files +allow scripts to load DBC files in support of the script */ QString MainWindow::loadedFileName = ""; diff --git a/newgraphdialog.cpp b/newgraphdialog.cpp index 41aa28f..8f491dc 100644 --- a/newgraphdialog.cpp +++ b/newgraphdialog.cpp @@ -25,6 +25,8 @@ NewGraphDialog::NewGraphDialog(DBCHandler *handler, QWidget *parent) : connect(ui->cbMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(loadSignals(int))); connect(ui->cbSignals, SIGNAL(currentIndexChanged(int)), this, SLOT(fillFormFromSignal(int))); + connect(ui->rbSignalGraph, SIGNAL(toggled(bool)), this, SLOT(setSignalActive(bool))); + connect(ui->rbStandardGraph, SIGNAL(toggled(bool)), this, SLOT(setStandardActive(bool))); loadMessages(); } @@ -58,28 +60,41 @@ void NewGraphDialog::clearParams() ui->txtStride->clear(); ui->txtName->clear(); ui->txtData->clear(); + ui->rbStandardGraph->setChecked(true); + setStandardActive(true); } void NewGraphDialog::setParams(GraphParams ¶ms) { - ui->txtID->setText(Utility::formatNumber(params.ID)); - ui->txtBias->setText(QString::number(params.bias)); - ui->txtMask->setText(Utility::formatNumber(params.mask)); - ui->txtScale->setText(QString::number(params.scale)); - ui->txtStride->setText(QString::number(params.stride)); - ui->cbSigned->setChecked(params.isSigned); - ui->txtName->setText(params.graphName); - - if (params.endByte > -1) + if (params.isDBCSignal) { - ui->txtData->setText(QString::number(params.startByte) + "-" + QString::number(params.endByte)); + clearParams(); + setSignalActive(true); + //loadMessages(); + } else { - ui->txtData->setText(QString::number(params.startByte)); + setStandardActive(true); + ui->txtID->setText(Utility::formatNumber(params.ID)); + ui->txtBias->setText(QString::number(params.bias)); + ui->txtMask->setText(Utility::formatNumber(params.mask)); + ui->txtScale->setText(QString::number(params.scale)); + ui->txtStride->setText(QString::number(params.stride)); + ui->cbSigned->setChecked(params.isSigned); + + if (params.endByte > -1) + { + ui->txtData->setText(QString::number(params.startByte) + "-" + QString::number(params.endByte)); + } + else + { + ui->txtData->setText(QString::number(params.startByte)); + } } + ui->txtName->setText(params.graphName); QPalette p = ui->colorSwatch->palette(); p.setColor(QPalette::Button, params.color); ui->colorSwatch->setPalette(p); @@ -87,31 +102,50 @@ void NewGraphDialog::setParams(GraphParams ¶ms) void NewGraphDialog::getParams(GraphParams ¶ms) { - params.ID = Utility::ParseStringToNum(ui->txtID->text()); - params.bias = ui->txtBias->text().toFloat(); + params.isDBCSignal = ui->rbSignalGraph->isChecked(); params.color = ui->colorSwatch->palette().button().color(); - params.isSigned = ui->cbSigned->isChecked(); - params.mask = Utility::ParseStringToNum(ui->txtMask->text()); - params.scale = ui->txtScale->text().toFloat(); - params.stride = Utility::ParseStringToNum(ui->txtStride->text()); - - QStringList values = ui->txtData->text().split('-'); - params.startByte = -1; - params.endByte = -1; - if (values.count() > 0) - { - params.startByte = values[0].toInt(); - if (values.count() > 1) - { - params.endByte = values[1].toInt(); - } - } - - //now catch stupidity and bring it to defaults - if (params.mask == 0) params.mask = 0xFFFFFFFF; - if (fabs(params.scale) < 0.00000001) params.scale = 1.0f; - if (params.stride < 1) params.stride = 1; params.graphName = ui->txtName->text(); + + if (params.isDBCSignal) + { + DBC_MESSAGE *msg = dbcHandler->findMsgByName(ui->cbMessages->currentText()); + if (msg != NULL) + params.signal = dbcHandler->findSignalByName(msg, ui->cbSignals->currentText()); + params.ID = params.signal->parentMessage->ID; + params.bias = 0; + params.isSigned = false; + params.mask = 0; + params.scale = 1; + params.bias = 0; + params.stride = 1; + + } + else { + params.ID = Utility::ParseStringToNum(ui->txtID->text()); + params.bias = ui->txtBias->text().toFloat(); + params.isSigned = ui->cbSigned->isChecked(); + params.mask = Utility::ParseStringToNum(ui->txtMask->text()); + params.scale = ui->txtScale->text().toFloat(); + params.stride = Utility::ParseStringToNum(ui->txtStride->text()); + params.signal = NULL; + + QStringList values = ui->txtData->text().split('-'); + params.startByte = -1; + params.endByte = -1; + if (values.count() > 0) + { + params.startByte = values[0].toInt(); + if (values.count() > 1) + { + params.endByte = values[1].toInt(); + } + } + + //now catch stupidity and bring it to defaults + if (params.mask == 0) params.mask = 0xFFFFFFFF; + if (fabs(params.scale) < 0.00000001) params.scale = 1.0f; + if (params.stride < 1) params.stride = 1; + } } void NewGraphDialog::loadMessages() @@ -154,14 +188,15 @@ void NewGraphDialog::fillFormFromSignal(int idx) if (sig == NULL) return; params.graphName = sig->name; - params.ID = msg->ID; - params.bias = sig->bias; - params.scale = sig->factor; - params.stride = 1; - params.mask = (1 << (sig->signalSize)) - 1; - if (sig->valType == SIGNED_INT) params.isSigned = true; - else params.isSigned = false; + //params.ID = msg->ID; + //params.bias = sig->bias; + //params.scale = sig->factor; + //params.stride = 1; + //params.mask = (1 << (sig->signalSize)) - 1; + //if (sig->valType == SIGNED_INT) params.isSigned = true; + //else params.isSigned = false; params.color = ui->colorSwatch->palette().color(QPalette::Button); + /* if (sig->intelByteOrder) { //for this ordering the byte order is reserved and starting byte @@ -175,6 +210,38 @@ void NewGraphDialog::fillFormFromSignal(int idx) params.startByte = sig->startBit / 8; params.endByte = (sig->startBit + sig->signalSize - 1) / 8; } - + */ setParams(params); } + +void NewGraphDialog::setSignalActive(bool state) +{ + if (!state) return; + ui->rbSignalGraph->setChecked(true); + ui->rbStandardGraph->setChecked(false); + ui->cbMessages->setEnabled(true); + ui->cbSignals->setEnabled(true); + ui->cbSigned->setEnabled(false); + ui->txtBias->setEnabled(false); + ui->txtData->setEnabled(false); + ui->txtID->setEnabled(false); + ui->txtMask->setEnabled(false); + ui->txtScale->setEnabled(false); + ui->txtStride->setEnabled(false); +} + +void NewGraphDialog::setStandardActive(bool state) +{ + if (!state) return; + ui->rbStandardGraph->setChecked(true); + ui->rbSignalGraph->setChecked(false); + ui->cbMessages->setEnabled(false); + ui->cbSignals->setEnabled(false); + ui->cbSigned->setEnabled(true); + ui->txtBias->setEnabled(true); + ui->txtData->setEnabled(true); + ui->txtID->setEnabled(true); + ui->txtMask->setEnabled(true); + ui->txtScale->setEnabled(true); + ui->txtStride->setEnabled(true); +} diff --git a/newgraphdialog.h b/newgraphdialog.h index 9c9686f..67fe5f0 100644 --- a/newgraphdialog.h +++ b/newgraphdialog.h @@ -26,6 +26,8 @@ private slots: void loadMessages(); void loadSignals(int idx); void fillFormFromSignal(int idx); + void setSignalActive(bool); + void setStandardActive(bool); private: Ui::NewGraphDialog *ui; diff --git a/newgraphdialog.ui b/newgraphdialog.ui index 48b32b0..dcb7f12 100644 --- a/newgraphdialog.ui +++ b/newgraphdialog.ui @@ -7,13 +7,37 @@ 0 0 492 - 309 + 340 Graph Settings + + + + + + Standard Graph + + + true + + + + + + + DBC Signal Graph + + + false + + + + +