diff --git a/re/flowviewwindow.cpp b/re/flowviewwindow.cpp index 6c9d719..62be6d4 100644 --- a/re/flowviewwindow.cpp +++ b/re/flowviewwindow.cpp @@ -104,6 +104,19 @@ FlowViewWindow::FlowViewWindow(const QVector *frames, QWidget *parent) connect(ui->txtTrigger5, SIGNAL(textEdited(QString)), this, SLOT(updateTriggerValues())); connect(ui->txtTrigger6, SIGNAL(textEdited(QString)), this, SLOT(updateTriggerValues())); connect(ui->txtTrigger7, SIGNAL(textEdited(QString)), this, SLOT(updateTriggerValues())); + connect(ui->graphRangeSlider, &QSlider::valueChanged, this, &FlowViewWindow::graphRangeChanged); + connect(ui->check_0, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_1, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_2, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_3, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_4, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_5, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_6, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + connect(ui->check_7, &QCheckBox::stateChanged, this, &FlowViewWindow::changeGraphVisibility); + +// ui->timelineSlider->setTracking(true); + connect(ui->timelineSlider, &QSlider::sliderPressed, this, &FlowViewWindow::btnPauseClick); + connect(ui->timelineSlider, &QSlider::valueChanged, this, &FlowViewWindow::gotoFrame); // Using lambda expression to strip away the possible filter label before passing the ID to updateDetailsWindow connect(ui->listFrameID, &QListWidget::currentTextChanged, @@ -234,6 +247,21 @@ bool FlowViewWindow::eventFilter(QObject *obj, QEvent *event) } } +void FlowViewWindow::changeGraphVisibility(int state){ + QCheckBox *sender = qobject_cast(QObject::sender()); + if(sender){ + sender->objectName(); + int graphId = sender->objectName().right(1).toInt(); + for (int k = 0; k < 8; k++) + { + if (k == graphId && graphRef[k] && graphRef[k]->data()){ + graphRef[k]->setVisible(state); + } + } + + ui->graphView->replot(); + } +} void FlowViewWindow::gotCellClick(int x, int y) { int bitnum = (7-x) + (8 * y); @@ -243,6 +271,11 @@ void FlowViewWindow::gotCellClick(int x, int y) qDebug() << "Bit Num: " << bitnum << " Hex of trigger bits: " << QString::number(triggerBits, 16); } +void FlowViewWindow::graphRangeChanged(int range) { + ui->rangeValue->setText(QString::number(range)); + updateGraphLocation(); +} + void FlowViewWindow::updateTriggerValues() { triggerValues[0] = Utility::ParseStringToNum(ui->txtTrigger0->text()); @@ -623,10 +656,19 @@ void FlowViewWindow::changeID(QString newID) memcpy(refBytes, currBytes, 8); updateDataView(); + ui->check_0->setChecked(true); + ui->check_1->setChecked(true); + ui->check_2->setChecked(true); + ui->check_3->setChecked(true); + ui->check_4->setChecked(true); + ui->check_5->setChecked(true); + ui->check_6->setChecked(true); + ui->check_7->setChecked(true); } void FlowViewWindow::btnBackOneClick() { + ui->cbLiveMode->setChecked(false); playbackTimer->stop(); //pushing this button halts automatic playback playbackActive = false; @@ -636,6 +678,7 @@ void FlowViewWindow::btnBackOneClick() void FlowViewWindow::btnPauseClick() { + ui->cbLiveMode->setChecked(false); playbackActive = false; playbackTimer->stop(); updateDataView(); @@ -643,6 +686,7 @@ void FlowViewWindow::btnPauseClick() void FlowViewWindow::btnReverseClick() { + ui->cbLiveMode->setChecked(false); playbackActive = true; playbackForward = false; playbackTimer->start(); @@ -650,6 +694,7 @@ void FlowViewWindow::btnReverseClick() void FlowViewWindow::btnStopClick() { + ui->cbLiveMode->setChecked(false); playbackTimer->stop(); //pushing this button halts automatic playback playbackActive = false; currentPosition = 0; @@ -664,6 +709,7 @@ void FlowViewWindow::btnStopClick() void FlowViewWindow::btnPlayClick() { + ui->cbLiveMode->setChecked(false); playbackActive = true; playbackForward = true; playbackTimer->start(); @@ -671,6 +717,7 @@ void FlowViewWindow::btnPlayClick() void FlowViewWindow::btnFwdOneClick() { + ui->cbLiveMode->setChecked(false); playbackTimer->stop(); playbackActive = false; updatePosition(true); @@ -736,6 +783,9 @@ void FlowViewWindow::updateDataView() ui->flowView->setReference(refBytes, false); ui->flowView->updateData(currBytes, true); + ui->timelineSlider->setMaximum(frameCache.count() - 1); + ui->timelineSlider->setValue(currentPosition); + for (int i = 0; i < 8; i++) { if (currBytes[i] == triggerValues[i]) @@ -752,6 +802,13 @@ void FlowViewWindow::updateDataView() } +void FlowViewWindow::gotoFrame(int frame) { + if (frameCache.count() >= frame) currentPosition = frame; + else currentPosition = 0; + + if (ui->cbSync->checkState() == Qt::Checked) emit sendCenterTimeID(frameCache[currentPosition].frameId(), frameCache[currentPosition].timeStamp().microSeconds() / 1000000.0); +} + void FlowViewWindow::updatePosition(bool forward) { @@ -795,14 +852,15 @@ void FlowViewWindow::updatePosition(bool forward) memcpy(currBytes, frameCache.at(currentPosition).payload().constData(), 8); if (ui->cbSync->checkState() == Qt::Checked) emit sendCenterTimeID(frameCache[currentPosition].frameId(), frameCache[currentPosition].timeStamp().microSeconds() / 1000000.0); + ui->timelineSlider->setValue(currentPosition); } void FlowViewWindow::updateGraphLocation() { if (frameCache.count() == 0) return; - int start = currentPosition - 5; + int start = currentPosition - ui->graphRangeSlider->value(); if (start < 0) start = 0; - int end = currentPosition + 5; + int end = currentPosition + ui->graphRangeSlider->value(); if (end >= frameCache.count()) end = frameCache.count() - 1; if (ui->cbTimeGraph->isChecked()) { diff --git a/re/flowviewwindow.h b/re/flowviewwindow.h index 826912e..e2705c1 100644 --- a/re/flowviewwindow.h +++ b/re/flowviewwindow.h @@ -2,6 +2,8 @@ #define FLOWVIEWWINDOW_H #include +#include +#include #include "qcustomplot.h" #include "can_structs.h" @@ -38,6 +40,8 @@ private slots: void gotCenterTimeID(int32_t ID, double timestamp); void updateTriggerValues(); void gotCellClick(int x, int y); + void graphRangeChanged(int range); + void changeGraphVisibility(int state); signals: void sendCenterTimeID(uint32_t ID, double timestamp); @@ -65,6 +69,7 @@ private: void refreshIDList(); void updateFrameLabel(); void updatePosition(bool forward); + void gotoFrame(int frame); void updateDataView(); void removeAllGraphs(); void createGraph(int); diff --git a/re/frameinfowindow.cpp b/re/frameinfowindow.cpp index a6508be..b545b50 100644 --- a/re/frameinfowindow.cpp +++ b/re/frameinfowindow.cpp @@ -34,6 +34,15 @@ FrameInfoWindow::FrameInfoWindow(const QVector *frames, QWidget *paren connect(MainWindow::getReference(), &MainWindow::framesUpdated, this, &FrameInfoWindow::updatedFrames); connect(ui->btnSave, &QAbstractButton::clicked, this, &FrameInfoWindow::saveDetails); + connect(ui->check_0, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_1, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_2, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_3, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_4, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_5, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_6, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + connect(ui->check_7, &QCheckBox::stateChanged, this, &FrameInfoWindow::changeGraphVisibility); + ui->graphHistogram->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables); @@ -631,7 +640,7 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) ui->graphBytes->clearGraphs(); for (int graphs = 0; graphs < 8; graphs++) { - ui->graphBytes->addGraph(); + graphRef[graphs] = ui->graphBytes->addGraph(); ui->graphBytes->graph()->setData(byteGraphX, byteGraphY[graphs]); ui->graphBytes->graph()->setPen(bytePens[graphs]); } @@ -652,6 +661,15 @@ void FrameInfoWindow::updateDetailsWindow(QString newID) ui->timeHistogram->axisRect()->setupFullAxesBox(); ui->timeHistogram->rescaleAxes(); ui->timeHistogram->replot(); + + ui->check_0->setChecked(true); + ui->check_1->setChecked(true); + ui->check_2->setChecked(true); + ui->check_3->setChecked(true); + ui->check_4->setChecked(true); + ui->check_5->setChecked(true); + ui->check_6->setChecked(true); + ui->check_7->setChecked(true); } else { @@ -726,6 +744,24 @@ void FrameInfoWindow::saveDetails() } } +void FrameInfoWindow::changeGraphVisibility(int state){ + QCheckBox *sender = qobject_cast(QObject::sender()); + if(sender){ + sender->objectName(); + int graphId = sender->objectName().right(1).toInt(); + for (int k = 0; k < 8; k++) + { + if (k == graphId && graphRef[k] && graphRef[k]->data()){ + graphRef[k]->setVisible(state); + qDebug() << graphId << state << k; + } + } + qDebug() << graphId << state; + + ui->graphBytes->replot(); + } +} + void FrameInfoWindow::dumpNode(QTreeWidgetItem* item, QFile *file, int indent) { for (int i = 0; i < indent; i++) file->write("\t"); diff --git a/re/frameinfowindow.h b/re/frameinfowindow.h index 72e7a47..5196d93 100644 --- a/re/frameinfowindow.h +++ b/re/frameinfowindow.h @@ -9,6 +9,8 @@ #include "bus_protocols/j1939_handler.h" #include "dbc/dbchandler.h" +#include "qcustomplot.h" + namespace Ui { class FrameInfoWindow; } @@ -26,6 +28,7 @@ private slots: void updateDetailsWindow(QString); void updatedFrames(int); void saveDetails(); + void changeGraphVisibility(int state); private: Ui::FrameInfoWindow *ui; @@ -39,6 +42,8 @@ private: static QPen bytePens[8]; DBCHandler *dbcHandler; + QCPGraph *graphRef[8]; + void refreshIDList(); void closeEvent(QCloseEvent *event); bool eventFilter(QObject *obj, QEvent *event); diff --git a/re/sniffer/sniffermodel.cpp b/re/sniffer/sniffermodel.cpp index 87a2422..01d1353 100644 --- a/re/sniffer/sniffermodel.cpp +++ b/re/sniffer/sniffermodel.cpp @@ -65,8 +65,10 @@ QVariant SnifferModel::data(const QModelIndex &index, int role) const { case tc::DELTA: return QString::number(item->getDelta(), 'f'); + case tc::FREQUENCY: + return QString("%1 hz").arg(qRound(1.00 / item->getDelta())); case tc::ID: - return QString("%1").arg(item->getId(), 5, 16, QLatin1Char(' ')).toUpper(); + return "0x" + QString("%1").arg(item->getId(), 5, 16, QLatin1Char(' ')).toUpper(); default: break; } @@ -148,6 +150,8 @@ QVariant SnifferModel::headerData(int section, Qt::Orientation orientation, int { case tc::DELTA: return QString("Delta"); + case tc::FREQUENCY: + return QString("Frequency"); case tc::ID: return QString("ID"); default: diff --git a/re/sniffer/snifferwindow.cpp b/re/sniffer/snifferwindow.cpp index 13e1d05..e0ecfb8 100644 --- a/re/sniffer/snifferwindow.cpp +++ b/re/sniffer/snifferwindow.cpp @@ -82,15 +82,16 @@ void SnifferWindow::readSettings() resize(settings.value("Sniffer/WindowSize", QSize(1100, 750)).toSize()); move(Utility::constrainedWindowPos(settings.value("Sniffer/WindowPos", QPoint(50, 50)).toPoint())); ui->treeView->setColumnWidth(0, settings.value("Sniffer/DeltaColumn", 110).toUInt()); - ui->treeView->setColumnWidth(1, settings.value("Sniffer/IDColumn", 70).toUInt()); - ui->treeView->setColumnWidth(2, settings.value("Sniffer/Data0Column", 92).toUInt()); - ui->treeView->setColumnWidth(3, settings.value("Sniffer/Data1Column", 92).toUInt()); - ui->treeView->setColumnWidth(4, settings.value("Sniffer/Data2Column", 92).toUInt()); - ui->treeView->setColumnWidth(5, settings.value("Sniffer/Data3Column", 92).toUInt()); - ui->treeView->setColumnWidth(6, settings.value("Sniffer/Data4Column", 92).toUInt()); - ui->treeView->setColumnWidth(7, settings.value("Sniffer/Data5Column", 92).toUInt()); - ui->treeView->setColumnWidth(8, settings.value("Sniffer/Data6Column", 92).toUInt()); - ui->treeView->setColumnWidth(9, settings.value("Sniffer/Data7Column", 92).toUInt()); + ui->treeView->setColumnWidth(1, settings.value("Sniffer/FrequencyColumn", 110).toUInt()); + ui->treeView->setColumnWidth(2, settings.value("Sniffer/IDColumn", 70).toUInt()); + ui->treeView->setColumnWidth(3, settings.value("Sniffer/Data0Column", 92).toUInt()); + ui->treeView->setColumnWidth(4, settings.value("Sniffer/Data1Column", 92).toUInt()); + ui->treeView->setColumnWidth(5, settings.value("Sniffer/Data2Column", 92).toUInt()); + ui->treeView->setColumnWidth(6, settings.value("Sniffer/Data3Column", 92).toUInt()); + ui->treeView->setColumnWidth(7, settings.value("Sniffer/Data4Column", 92).toUInt()); + ui->treeView->setColumnWidth(8, settings.value("Sniffer/Data5Column", 92).toUInt()); + ui->treeView->setColumnWidth(9, settings.value("Sniffer/Data6Column", 92).toUInt()); + ui->treeView->setColumnWidth(10, settings.value("Sniffer/Data7Column", 92).toUInt()); } } @@ -103,15 +104,16 @@ void SnifferWindow::writeSettings() settings.setValue("Sniffer/WindowSize", size()); settings.setValue("Sniffer/WindowPos", pos()); settings.setValue("Sniffer/DeltaColumn", ui->treeView->columnWidth(0)); - settings.setValue("Sniffer/IDColumn", ui->treeView->columnWidth(1)); - settings.setValue("Sniffer/Data0Column", ui->treeView->columnWidth(2)); - settings.setValue("Sniffer/Data1Column", ui->treeView->columnWidth(3)); - settings.setValue("Sniffer/Data2Column", ui->treeView->columnWidth(4)); - settings.setValue("Sniffer/Data3Column", ui->treeView->columnWidth(5)); - settings.setValue("Sniffer/Data4Column", ui->treeView->columnWidth(6)); - settings.setValue("Sniffer/Data5Column", ui->treeView->columnWidth(7)); - settings.setValue("Sniffer/Data6Column", ui->treeView->columnWidth(8)); - settings.setValue("Sniffer/Data7Column", ui->treeView->columnWidth(9)); + settings.setValue("Sniffer/FrequencyColumn", ui->treeView->columnWidth(1)); + settings.setValue("Sniffer/IDColumn", ui->treeView->columnWidth(2)); + settings.setValue("Sniffer/Data0Column", ui->treeView->columnWidth(3)); + settings.setValue("Sniffer/Data1Column", ui->treeView->columnWidth(4)); + settings.setValue("Sniffer/Data2Column", ui->treeView->columnWidth(5)); + settings.setValue("Sniffer/Data3Column", ui->treeView->columnWidth(6)); + settings.setValue("Sniffer/Data4Column", ui->treeView->columnWidth(7)); + settings.setValue("Sniffer/Data5Column", ui->treeView->columnWidth(8)); + settings.setValue("Sniffer/Data6Column", ui->treeView->columnWidth(9)); + settings.setValue("Sniffer/Data7Column", ui->treeView->columnWidth(10)); } } diff --git a/re/sniffer/snifferwindow.h b/re/sniffer/snifferwindow.h index 3852761..ceab3f9 100644 --- a/re/sniffer/snifferwindow.h +++ b/re/sniffer/snifferwindow.h @@ -13,6 +13,7 @@ class snifferWindow; enum tc { DELTA = 0, + FREQUENCY, ID, DATA_0, DATA_1, diff --git a/ui/flowviewwindow.ui b/ui/flowviewwindow.ui index b9034ba..71424c6 100644 --- a/ui/flowviewwindow.ui +++ b/ui/flowviewwindow.ui @@ -6,63 +6,66 @@ 0 0 - 1078 - 623 + 906 + 568 Flow View - - - - - - - - - - 0 - 0 - - - - Frame IDs Found: - - - - - - - - 0 - 0 - - - - - 120 - 16777215 - - - - - - - + + + QLayout::SetNoConstraint + + + + + Qt::Horizontal + + - - + + + + + 0 + 0 + + + + + 200 + 16777215 + + Playback Control + + Qt::AlignCenter + + + false + + + + 0 + 0 + + + + + 40 + 16777215 + + @@ -74,6 +77,18 @@ + + + 0 + 0 + + + + + 60 + 16777215 + + @@ -85,6 +100,18 @@ + + + 0 + 0 + + + + + 40 + 16777215 + + @@ -100,6 +127,18 @@ + + + 0 + 0 + + + + + 40 + 16777215 + + @@ -111,6 +150,18 @@ + + + 0 + 0 + + + + + 60 + 16777215 + + @@ -122,6 +173,18 @@ + + + 0 + 0 + + + + + 40 + 16777215 + + @@ -148,6 +211,18 @@ + + + 0 + 0 + + + + + 200 + 16777215 + + 5000 @@ -197,6 +272,12 @@ + + + 0 + 0 + + Live Mode (No Playback) @@ -217,6 +298,12 @@ + + + 0 + 0 + + Graph by timestamp @@ -237,8 +324,8 @@ - - + + @@ -300,12 +387,6 @@ 0 - - - 40 - 0 - - 40 @@ -328,12 +409,6 @@ 0 - - - 40 - 0 - - 40 @@ -356,12 +431,6 @@ 0 - - - 40 - 0 - - 40 @@ -384,12 +453,6 @@ 0 - - - 40 - 0 - - 40 @@ -448,12 +511,6 @@ 0 - - - 40 - 0 - - 40 @@ -470,12 +527,6 @@ 0 - - - 40 - 0 - - 40 @@ -492,12 +543,6 @@ 0 - - - 40 - 0 - - 40 @@ -514,12 +559,6 @@ 0 - - - 40 - 0 - - 40 @@ -587,12 +626,6 @@ 0 - - - 40 - 0 - - 40 @@ -609,12 +642,6 @@ 0 - - - 40 - 0 - - 40 @@ -631,12 +658,6 @@ 0 - - - 40 - 0 - - 40 @@ -653,12 +674,6 @@ 0 - - - 40 - 0 - - 40 @@ -711,12 +726,6 @@ 0 - - - 40 - 0 - - 40 @@ -733,12 +742,6 @@ 0 - - - 40 - 0 - - 40 @@ -755,12 +758,6 @@ 0 - - - 40 - 0 - - 40 @@ -777,12 +774,6 @@ 0 - - - 40 - 0 - - 40 @@ -798,6 +789,12 @@ + + + 0 + 0 + + Data Seek Values @@ -844,12 +841,6 @@ 0 - - - 40 - 0 - - 40 @@ -1030,121 +1021,25 @@ - - - - Data Byte Colors: - - - - - - - - - - - - 0 - 0 - 255 - - - - - - - - - 0 - 0 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - - 0 = Blue - - - - - - - 2 = Black - - - - - - - - - - - - 255 - 0 - 0 - - - - - - - - - 255 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - - 3 = Red - - - - + + + + 0 + 0 + + - 133 - 133 - 199 + 252 + 233 + 79 @@ -1153,9 +1048,9 @@ - 133 - 133 - 199 + 252 + 233 + 79 @@ -1173,21 +1068,157 @@ + + + 13 + 75 + true + + - 4 = Gray + 5 + + + true - + + + + 0 + 0 + + - 0 - 170 + 78 + 154 + 6 + + + + + + + + + 78 + 154 + 6 + + + + + + + + + 120 + 120 + 120 + + + + + + + + + 13 + 75 + true + + + + 1 + + + true + + + + + + + + 0 + 0 + + + + + + + + + 136 + 138 + 133 + + + + + + + + + 136 + 138 + 133 + + + + + + + + + 120 + 120 + 120 + + + + + + + + + 13 + 75 + true + + + + 4 + + + true + + + + + + + + 0 + 0 + + + + + + + + + 204 + 0 0 @@ -1197,8 +1228,8 @@ - 0 - 170 + 204 + 0 0 @@ -1217,22 +1248,158 @@ + + + 13 + 75 + true + + - 1 = Green + 3 + + + true + + + + + + + + 0 + 0 + + + + + + + + + 52 + 101 + 164 + + + + + + + + + 52 + 101 + 164 + + + + + + + + + 120 + 120 + 120 + + + + + + + + + 13 + 75 + true + + + + 0 + + + true + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + + + 13 + 75 + true + + + + 2 + + + true - + + + + 0 + 0 + + - 203 - 203 - 0 + 114 + 159 + 207 @@ -1241,9 +1408,9 @@ - 203 - 203 - 0 + 114 + 159 + 207 @@ -1261,22 +1428,38 @@ + + + 13 + 75 + true + + - 5 = Yellow + 6 + + + true - - + + + + + 0 + 0 + + - 68 - 204 - 204 + 173 + 127 + 168 @@ -1285,9 +1468,9 @@ - 68 - 204 - 204 + 173 + 127 + 168 @@ -1305,52 +1488,18 @@ - - 6 = Cyan - - - - - - - - - - - - 180 - 0 - 180 - - - - - - - - - 180 - 0 - 180 - - - - - - - - - 120 - 120 - 120 - - - - - + + + 13 + 75 + true + - 7 = Dk Magenta + 7 + + + true @@ -1358,17 +1507,131 @@ - - + + + + QLayout::SetMaximumSize + - - - - - - - - + + + + + + + + + + + + + 0 + 0 + + + + + + + + 0 + 0 + + + + Chart range + + + + + + + + 0 + 0 + + + + + 75 + true + + + + 50 + + + + + + + + + + + 0 + 0 + + + + 1 + + + 500 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + + + + + + Timeline: + + + + + + + + + + 0 + 0 + + + + Frame IDs Found: + + + + + + + + 0 + 0 + + + + + 120 + 16777215 + + + diff --git a/ui/frameinfowindow.ui b/ui/frameinfowindow.ui index 28904e9..406b02a 100644 --- a/ui/frameinfowindow.ui +++ b/ui/frameinfowindow.ui @@ -133,7 +133,7 @@ - + @@ -162,9 +162,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -181,10 +181,13 @@ 0 + + true + - + @@ -213,9 +216,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -232,10 +235,50 @@ 1 + + true + - + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + 13 @@ -246,10 +289,13 @@ 2 + + true + - + @@ -278,9 +324,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -297,10 +343,13 @@ 3 + + true + - + @@ -329,9 +378,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -348,10 +397,13 @@ 4 + + true + - + @@ -380,9 +432,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -399,10 +451,13 @@ 5 + + true + - + @@ -431,9 +486,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -450,10 +505,13 @@ 6 + + true + - + @@ -482,9 +540,9 @@ - 190 - 190 - 190 + 120 + 120 + 120 @@ -501,6 +559,9 @@ 7 + + true +