First implementation

This commit is contained in:
Yury Shuvakin
2024-07-03 19:08:19 +09:00
parent a953095a5c
commit 6f85ac3b13
126 changed files with 21667 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
/*
Copyright (c) 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanStatusWindow.h"
#include "ui_CanStatusWindow.h"
#include <QStringList>
#include <QTimer>
#include <core/Backend.h>
#include <core/MeasurementSetup.h>
#include <core/MeasurementNetwork.h>
#include <core/MeasurementInterface.h>
CanStatusWindow::CanStatusWindow(QWidget *parent, Backend &backend) :
ConfigurableWidget(parent),
ui(new Ui::CanStatusWindow),
_backend(backend),
_timer(new QTimer(this))
{
ui->setupUi(this);
ui->treeWidget->setHeaderLabels(QStringList()
<< "Driver" << "Interface" << "State"
<< "Rx Frames" << "Rx Errors" << "Rx Overrun"
<< "Tx Frames" << "Tx Errors" << "Tx Dropped"
<< "# Warning" << "# Passive" << "# Bus Off" << " #Restarts"
);
ui->treeWidget->setColumnWidth(0, 80);
ui->treeWidget->setColumnWidth(1, 70);
connect(&backend, SIGNAL(beginMeasurement()), this, SLOT(beginMeasurement()));
connect(&backend, SIGNAL(endMeasurement()), this, SLOT(endMeasurement()));
connect(_timer, SIGNAL(timeout()), this, SLOT(update()));
}
CanStatusWindow::~CanStatusWindow()
{
delete ui;
}
void CanStatusWindow::beginMeasurement()
{
ui->treeWidget->clear();
foreach (CanInterfaceId ifid, backend().getInterfaceList()) {
CanInterface *intf = backend().getInterfaceById(ifid);
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
item->setData(0, Qt::UserRole, QVariant::fromValue((void*)intf));
item->setText(column_driver, intf->getDriver()->getName());
item->setText(column_interface, intf->getName());
item->setTextAlignment(column_driver, Qt::AlignLeft);
item->setTextAlignment(column_interface, Qt::AlignLeft);
item->setTextAlignment(column_state, Qt::AlignCenter);
for (int i=column_rx_frames; i<column_count; i++) {
item->setTextAlignment(i, Qt::AlignRight);
}
ui->treeWidget->addTopLevelItem(item);
}
update();
_timer->start(100);
}
void CanStatusWindow::endMeasurement()
{
_timer->stop();
}
void CanStatusWindow::update()
{
for (QTreeWidgetItemIterator it(ui->treeWidget); *it; ++it) {
QTreeWidgetItem *item = *it;
CanInterface *intf = (CanInterface *)item->data(0, Qt::UserRole).value<void *>();
if (intf) {
intf->updateStatistics();
item->setText(column_state, intf->getStateText());
item->setText(column_rx_frames, QString().number(intf->getNumRxFrames()));
item->setText(column_rx_errors, QString().number(intf->getNumRxErrors()));
item->setText(column_rx_overrun, QString().number(intf->getNumRxOverruns()));
item->setText(column_tx_frames, QString().number(intf->getNumTxFrames()));
item->setText(column_tx_errors, QString().number(intf->getNumTxErrors()));
item->setText(column_tx_dropped, QString().number(intf->getNumTxDropped()));
}
}
}
Backend &CanStatusWindow::backend()
{
return _backend;
}

View File

@@ -0,0 +1,70 @@
/*
Copyright (c) 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <core/ConfigurableWidget.h>
namespace Ui {
class CanStatusWindow;
}
class Backend;
class QTimer;
class CanStatusWindow : public ConfigurableWidget
{
Q_OBJECT
public:
enum {
column_driver,
column_interface,
column_state,
column_rx_frames,
column_rx_errors,
column_rx_overrun,
column_tx_frames,
column_tx_errors,
column_tx_dropped,
column_num_warning,
column_num_passive,
column_num_busoff,
column_num_restarts,
column_count
};
public:
explicit CanStatusWindow(QWidget *parent, Backend &backend);
~CanStatusWindow();
private slots:
void beginMeasurement();
void endMeasurement();
void update();
private:
Ui::CanStatusWindow *ui;
Backend &_backend;
Backend &backend();
QTimer *_timer;
};

View File

@@ -0,0 +1,8 @@
SOURCES += \
$$PWD/CanStatusWindow.cpp \
HEADERS += \
$$PWD/CanStatusWindow.h \
FORMS += \
$$PWD/CanStatusWindow.ui \

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CanStatusWindow</class>
<widget class="QWidget" name="CanStatusWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>756</width>
<height>459</height>
</rect>
</property>
<property name="windowTitle">
<string>Can Status</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="indentation">
<number>0</number>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="columnCount">
<number>13</number>
</property>
<attribute name="headerDefaultSectionSize">
<number>80</number>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">3</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">4</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">5</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">6</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">7</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">8</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">9</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">10</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">11</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">12</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">13</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,136 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GraphWindow.h"
#include "ui_GraphWindow.h"
#include <QDomDocument>
#include <core/Backend.h>
#include <QtCharts/QChartView>
#define NUM_GRAPH_POINTS 20
GraphWindow::GraphWindow(QWidget *parent, Backend &backend) :
ConfigurableWidget(parent),
ui(new Ui::GraphWindow),
_backend(backend)
{
ui->setupUi(this);
data_series = new QLineSeries();
for(uint32_t i=0; i<NUM_GRAPH_POINTS; i++)
{
data_series->append(i, i);
}
data_chart = new QChart();
data_chart->legend()->hide();
data_chart->addSeries(data_series);
data_chart->createDefaultAxes();
data_chart->setTitle("Simple line chart example");
// Have a box pop up that allows the user to select a signal from the loaded DBC to graph
// On OK, add that CanDbMessage to a list.
// Either sample the values regularly with a timer or somehow emit a signal when the message
// is received that we catch here...
//backend.findDbMessage()
// CanDbMessage *result = 0;
// foreach (MeasurementNetwork *network, _networks) {
// foreach (pCanDb db, network->_canDbs) {
// result = db->getMessageById(msg.getRawId());
// if (result != 0) {
// return result;
// }
// }
// }
// return result;
ui->chartView->setChart(data_chart);
ui->chartView->setRenderHint(QPainter::Antialiasing);
// connect(ui->buttonTest, SIGNAL(released()), this, SLOT(testAddData()));
}
void GraphWindow::testAddData(qreal new_yval)
{
QLineSeries* serbuf = new QLineSeries();
// Start autorange at first point
qreal ymin = data_series->at(1).y();
qreal ymax = ymin;
// Copy all points but first one
for(uint32_t i=1; i < data_series->count(); i++)
{
serbuf->append(data_series->at(i).x()-1, data_series->at(i).y());
// Autoranging
if(data_series->at(i).y() < ymin)
ymin = data_series->at(i).y();
if(data_series->at(i).y() > ymax)
ymax = data_series->at(i).y();
}
// Apply Y margin and set range
ymin -= 1;
ymax += 1;
data_chart->axisY()->setRange(ymin, ymax);
// Add new point in
serbuf->append(serbuf->points().at(serbuf->count()-1).x() + 1, new_yval);
testcount++;
// Replace data
data_series->replace(serbuf->points());
delete serbuf;
}
GraphWindow::~GraphWindow()
{
delete ui;
delete data_chart;
delete data_series;
}
bool GraphWindow::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
if (!ConfigurableWidget::saveXML(backend, xml, root)) { return false; }
root.setAttribute("type", "GraphWindow");
return true;
}
bool GraphWindow::loadXML(Backend &backend, QDomElement &el)
{
if (!ConfigurableWidget::loadXML(backend, el)) { return false; }
return true;
}

View File

@@ -0,0 +1,58 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <core/Backend.h>
#include <core/ConfigurableWidget.h>
#include <core/MeasurementSetup.h>
#include <QtCharts/QChartView>
#include <QtCharts/QtCharts>
#include <QtCharts/QLineSeries>
namespace Ui {
class GraphWindow;
}
class QDomDocument;
class QDomElement;
class GraphWindow : public ConfigurableWidget
{
Q_OBJECT
public:
explicit GraphWindow(QWidget *parent, Backend &backend);
~GraphWindow();
virtual bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
virtual bool loadXML(Backend &backend, QDomElement &el);
private slots:
void testAddData(qreal new_yval);
private:
QLineSeries *data_series;
QChart *data_chart;
uint32_t testcount;
Ui::GraphWindow *ui;
Backend &_backend;
};

View File

@@ -0,0 +1,8 @@
SOURCES += \
$$PWD/GraphWindow.cpp
HEADERS += \
$$PWD/GraphWindow.h
FORMS += \
$$PWD/GraphWindow.ui

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GraphWindow</class>
<widget class="QWidget" name="GraphWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>870</width>
<height>274</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>301</width>
<height>274</height>
</size>
</property>
<property name="windowTitle">
<string>Graph</string>
</property>
<widget class="QChartView" name="chartView">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>281</width>
<height>231</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>281</width>
<height>231</height>
</size>
</property>
</widget>
<widget class="QPushButton" name="buttonTest">
<property name="geometry">
<rect>
<x>210</x>
<y>250</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Test</string>
</property>
</widget>
<widget class="QChartView" name="graphicsView">
<property name="geometry">
<rect>
<x>390</x>
<y>30</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QChartView</class>
<extends>QGraphicsView</extends>
<header>QtCharts</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,62 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LogWindow.h"
#include "ui_LogWindow.h"
#include <QDomDocument>
#include <core/Backend.h>
#include <core/LogModel.h>
LogWindow::LogWindow(QWidget *parent, Backend &backend) :
ConfigurableWidget(parent),
ui(new Ui::LogWindow)
{
connect(&backend.getLogModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted(QModelIndex,int,int)));
ui->setupUi(this);
ui->treeView->setModel(&backend.getLogModel());
}
LogWindow::~LogWindow()
{
delete ui;
}
bool LogWindow::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
if (!ConfigurableWidget::saveXML(backend, xml, root)) { return false; }
root.setAttribute("type", "LogWindow");
return true;
}
bool LogWindow::loadXML(Backend &backend, QDomElement &el)
{
return ConfigurableWidget::loadXML(backend, el);
}
void LogWindow::rowsInserted(const QModelIndex &parent, int first, int last)
{
(void) parent;
(void) first;
(void) last;
ui->treeView->scrollToBottom();
}

View File

@@ -0,0 +1,51 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <core/ConfigurableWidget.h>
#include <core/Backend.h>
namespace Ui {
class LogWindow;
}
class QDomDocument;
class QDomElement;
class LogModel;
class LogWindow : public ConfigurableWidget
{
Q_OBJECT
public:
explicit LogWindow(QWidget *parent, Backend &backend);
~LogWindow();
virtual bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
virtual bool loadXML(Backend &backend, QDomElement &el);
private slots:
void rowsInserted(const QModelIndex & parent, int first, int last);
private:
Ui::LogWindow *ui;
};

View File

@@ -0,0 +1,10 @@
SOURCES += \
$$PWD/LogWindow.cpp \
HEADERS += \
$$PWD/LogWindow.h \
FORMS += \
$$PWD/LogWindow.ui \

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LogWindow</class>
<widget class="QWidget" name="LogWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Log</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="treeView"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,735 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "RawTxWindow.h"
#include "ui_RawTxWindow.h"
#include <QDomDocument>
#include <QTimer>
#include <core/Backend.h>
#include <driver/CanInterface.h>
RawTxWindow::RawTxWindow(QWidget *parent, Backend &backend) :
ConfigurableWidget(parent),
ui(new Ui::RawTxWindow),
_backend(backend)
{
ui->setupUi(this);
connect(ui->singleSendButton, SIGNAL(released()), this, SLOT(sendRawMessage()));
connect(ui->repeatSendButton, SIGNAL(toggled(bool)), this, SLOT(sendRepeatMessage(bool)));
connect(ui->spinBox_RepeatRate, SIGNAL(valueChanged(int)), this, SLOT(changeRepeatRate(int)));
connect(ui->comboBoxInterface, SIGNAL(currentIndexChanged(int)), this, SLOT(updateCapabilities()));
connect(ui->checkbox_FD, SIGNAL(stateChanged(int)), this, SLOT(updateCapabilities()));
connect(&backend, SIGNAL(beginMeasurement()), this, SLOT(refreshInterfaces()));
// Timer for repeating messages
repeatmsg_timer = new QTimer(this);
connect(repeatmsg_timer, SIGNAL(timeout()), this, SLOT(sendRawMessage()));
// TODO: Grey out checkboxes that are invalid depending on DLC spinbox state
//connect(ui->fieldDLC, SIGNAL(valueChanged(int)), this, SLOT(changeDLC(int)));
connect(ui->comboBoxDLC, SIGNAL(currentIndexChanged(int)), this, SLOT(changeDLC()));
// Disable TX until interfaces are present
this->setDisabled(1);
}
RawTxWindow::~RawTxWindow()
{
delete ui;
}
void RawTxWindow::changeDLC()
{
ui->fieldByte0_0->setEnabled(true);
ui->fieldByte1_0->setEnabled(true);
ui->fieldByte2_0->setEnabled(true);
ui->fieldByte3_0->setEnabled(true);
ui->fieldByte4_0->setEnabled(true);
ui->fieldByte5_0->setEnabled(true);
ui->fieldByte6_0->setEnabled(true);
ui->fieldByte7_0->setEnabled(true);
ui->fieldByte0_1->setEnabled(true);
ui->fieldByte1_1->setEnabled(true);
ui->fieldByte2_1->setEnabled(true);
ui->fieldByte3_1->setEnabled(true);
ui->fieldByte4_1->setEnabled(true);
ui->fieldByte5_1->setEnabled(true);
ui->fieldByte6_1->setEnabled(true);
ui->fieldByte7_1->setEnabled(true);
ui->fieldByte0_2->setEnabled(true);
ui->fieldByte1_2->setEnabled(true);
ui->fieldByte2_2->setEnabled(true);
ui->fieldByte3_2->setEnabled(true);
ui->fieldByte4_2->setEnabled(true);
ui->fieldByte5_2->setEnabled(true);
ui->fieldByte6_2->setEnabled(true);
ui->fieldByte7_2->setEnabled(true);
ui->fieldByte0_3->setEnabled(true);
ui->fieldByte1_3->setEnabled(true);
ui->fieldByte2_3->setEnabled(true);
ui->fieldByte3_3->setEnabled(true);
ui->fieldByte4_3->setEnabled(true);
ui->fieldByte5_3->setEnabled(true);
ui->fieldByte6_3->setEnabled(true);
ui->fieldByte7_3->setEnabled(true);
ui->fieldByte0_4->setEnabled(true);
ui->fieldByte1_4->setEnabled(true);
ui->fieldByte2_4->setEnabled(true);
ui->fieldByte3_4->setEnabled(true);
ui->fieldByte4_4->setEnabled(true);
ui->fieldByte5_4->setEnabled(true);
ui->fieldByte6_4->setEnabled(true);
ui->fieldByte7_4->setEnabled(true);
ui->fieldByte0_5->setEnabled(true);
ui->fieldByte1_5->setEnabled(true);
ui->fieldByte2_5->setEnabled(true);
ui->fieldByte3_5->setEnabled(true);
ui->fieldByte4_5->setEnabled(true);
ui->fieldByte5_5->setEnabled(true);
ui->fieldByte6_5->setEnabled(true);
ui->fieldByte7_5->setEnabled(true);
ui->fieldByte0_6->setEnabled(true);
ui->fieldByte1_6->setEnabled(true);
ui->fieldByte2_6->setEnabled(true);
ui->fieldByte3_6->setEnabled(true);
ui->fieldByte4_6->setEnabled(true);
ui->fieldByte5_6->setEnabled(true);
ui->fieldByte6_6->setEnabled(true);
ui->fieldByte7_6->setEnabled(true);
ui->fieldByte0_7->setEnabled(true);
ui->fieldByte1_7->setEnabled(true);
ui->fieldByte2_7->setEnabled(true);
ui->fieldByte3_7->setEnabled(true);
ui->fieldByte4_7->setEnabled(true);
ui->fieldByte5_7->setEnabled(true);
ui->fieldByte6_7->setEnabled(true);
ui->fieldByte7_7->setEnabled(true);
uint8_t dlc = ui->comboBoxDLC->currentData().toUInt();
switch(dlc)
{
case 0:
ui->fieldByte0_0->setEnabled(false);
//fallthrough
case 1:
ui->fieldByte1_0->setEnabled(false);
//fallthrough
case 2:
ui->fieldByte2_0->setEnabled(false);
//fallthrough
case 3:
ui->fieldByte3_0->setEnabled(false);
//fallthrough
case 4:
ui->fieldByte4_0->setEnabled(false);
//fallthrough
case 5:
ui->fieldByte5_0->setEnabled(false);
//fallthrough
case 6:
ui->fieldByte6_0->setEnabled(false);
//fallthrough
case 7:
ui->fieldByte7_0->setEnabled(false);
//fallthrough
case 8:
ui->fieldByte0_1->setEnabled(false);
ui->fieldByte1_1->setEnabled(false);
ui->fieldByte2_1->setEnabled(false);
ui->fieldByte3_1->setEnabled(false);
//fallthrough
case 12:
ui->fieldByte4_1->setEnabled(false);
ui->fieldByte5_1->setEnabled(false);
ui->fieldByte6_1->setEnabled(false);
ui->fieldByte7_1->setEnabled(false);
//fallthrough
case 16:
ui->fieldByte0_2->setEnabled(false);
ui->fieldByte1_2->setEnabled(false);
ui->fieldByte2_2->setEnabled(false);
ui->fieldByte3_2->setEnabled(false);
//fallthrough
case 20:
ui->fieldByte4_2->setEnabled(false);
ui->fieldByte5_2->setEnabled(false);
ui->fieldByte6_2->setEnabled(false);
ui->fieldByte7_2->setEnabled(false);
//fallthrough
case 24:
ui->fieldByte0_3->setEnabled(false);
ui->fieldByte1_3->setEnabled(false);
ui->fieldByte2_3->setEnabled(false);
ui->fieldByte3_3->setEnabled(false);
ui->fieldByte4_3->setEnabled(false);
ui->fieldByte5_3->setEnabled(false);
ui->fieldByte6_3->setEnabled(false);
ui->fieldByte7_3->setEnabled(false);
//fallthrough
case 32:
ui->fieldByte0_4->setEnabled(false);
ui->fieldByte1_4->setEnabled(false);
ui->fieldByte2_4->setEnabled(false);
ui->fieldByte3_4->setEnabled(false);
ui->fieldByte4_4->setEnabled(false);
ui->fieldByte5_4->setEnabled(false);
ui->fieldByte6_4->setEnabled(false);
ui->fieldByte7_4->setEnabled(false);
ui->fieldByte0_5->setEnabled(false);
ui->fieldByte1_5->setEnabled(false);
ui->fieldByte2_5->setEnabled(false);
ui->fieldByte3_5->setEnabled(false);
ui->fieldByte4_5->setEnabled(false);
ui->fieldByte5_5->setEnabled(false);
ui->fieldByte6_5->setEnabled(false);
ui->fieldByte7_5->setEnabled(false);
//fallthrough
case 48:
ui->fieldByte0_6->setEnabled(false);
ui->fieldByte1_6->setEnabled(false);
ui->fieldByte2_6->setEnabled(false);
ui->fieldByte3_6->setEnabled(false);
ui->fieldByte4_6->setEnabled(false);
ui->fieldByte5_6->setEnabled(false);
ui->fieldByte6_6->setEnabled(false);
ui->fieldByte7_6->setEnabled(false);
ui->fieldByte0_7->setEnabled(false);
ui->fieldByte1_7->setEnabled(false);
ui->fieldByte2_7->setEnabled(false);
ui->fieldByte3_7->setEnabled(false);
ui->fieldByte4_7->setEnabled(false);
ui->fieldByte5_7->setEnabled(false);
ui->fieldByte6_7->setEnabled(false);
ui->fieldByte7_7->setEnabled(false);
}
// repeatmsg_timer->setInterval(ms);
}
void RawTxWindow::updateCapabilities()
{
// check if intf suports fd, if, enable, else dis
//CanInterface *intf = _backend.getInterfaceById(idx);
if(ui->comboBoxInterface->count() > 0)
{
// By default BRS should be available
CanInterface *intf = _backend.getInterfaceById((CanInterfaceId)ui->comboBoxInterface->currentData().toUInt());
if(intf == NULL)
{
return;
}
int idx_restore = ui->comboBoxDLC->currentIndex();
// If CANFD is available
if(intf->getCapabilities() & intf->capability_canfd)
{
ui->comboBoxDLC->clear();
ui->comboBoxDLC->addItem("0", 0);
ui->comboBoxDLC->addItem("1", 1);
ui->comboBoxDLC->addItem("2", 2);
ui->comboBoxDLC->addItem("3", 3);
ui->comboBoxDLC->addItem("4", 4);
ui->comboBoxDLC->addItem("5", 5);
ui->comboBoxDLC->addItem("6", 6);
ui->comboBoxDLC->addItem("7", 7);
ui->comboBoxDLC->addItem("8", 8);
ui->comboBoxDLC->addItem("12", 12);
ui->comboBoxDLC->addItem("16", 16);
ui->comboBoxDLC->addItem("20", 20);
ui->comboBoxDLC->addItem("24", 24);
ui->comboBoxDLC->addItem("32", 32);
ui->comboBoxDLC->addItem("48", 48);
ui->comboBoxDLC->addItem("64", 64);
// Restore previous selected DLC if available
if(idx_restore > 1 && idx_restore < ui->comboBoxDLC->count())
ui->comboBoxDLC->setCurrentIndex(idx_restore);
ui->checkbox_FD->setDisabled(0);
// Enable BRS if this is an FD frame
if(ui->checkbox_FD->isChecked())
{
// Enable BRS if FD enabled
ui->checkbox_BRS->setDisabled(0);
// Disable RTR if FD enabled
ui->checkBox_IsRTR->setDisabled(1);
ui->checkBox_IsRTR->setChecked(false);
}
else
{
// Disable BRS if FD disabled
ui->checkbox_BRS->setDisabled(1);
ui->checkbox_BRS->setChecked(false);
// Enable RTR if FD disabled
ui->checkBox_IsRTR->setDisabled(0);
}
showFDFields();
}
else
{
// CANFD not available
ui->comboBoxDLC->clear();
ui->comboBoxDLC->addItem("0", 0);
ui->comboBoxDLC->addItem("1", 1);
ui->comboBoxDLC->addItem("2", 2);
ui->comboBoxDLC->addItem("3", 3);
ui->comboBoxDLC->addItem("4", 4);
ui->comboBoxDLC->addItem("5", 5);
ui->comboBoxDLC->addItem("6", 6);
ui->comboBoxDLC->addItem("7", 7);
ui->comboBoxDLC->addItem("8", 8);
// Restore previous selected DLC if available
if(idx_restore > 1 && idx_restore < ui->comboBoxDLC->count())
ui->comboBoxDLC->setCurrentIndex(idx_restore);
// Unset/disable FD / BRS checkboxes
ui->checkbox_FD->setDisabled(1);
ui->checkbox_BRS->setDisabled(1);
ui->checkbox_FD->setChecked(false);
ui->checkbox_BRS->setChecked(false);
// Enable RTR (could be disabled by FD checkbox being set)
ui->checkBox_IsRTR->setDisabled(0);
hideFDFields();
}
}
}
void RawTxWindow::changeRepeatRate(int ms)
{
repeatmsg_timer->setInterval(ms);
}
void RawTxWindow::sendRepeatMessage(bool enable)
{
if(enable)
{
repeatmsg_timer->start(ui->spinBox_RepeatRate->value());
}
else
{
repeatmsg_timer->stop();
}
}
void RawTxWindow::disableTxWindow(int disable)
{
if(disable)
{
this->setDisabled(1);
}
else
{
// Only enable if an interface is present
if(_backend.getInterfaceList().count() > 0)
this->setDisabled(0);
else
this->setDisabled(1);
}
}
void RawTxWindow::refreshInterfaces()
{
ui->comboBoxInterface->clear();
int cb_idx = 0;
// TODO: Only show interfaces that are included in active MeasurementInterfaces!
foreach (CanInterfaceId ifid, _backend.getInterfaceList()) {
CanInterface *intf = _backend.getInterfaceById(ifid);
if(intf->isOpen())
{
ui->comboBoxInterface->addItem(intf->getName() + " " + intf->getDriver()->getName());
ui->comboBoxInterface->setItemData(cb_idx, QVariant(ifid));
cb_idx++;
}
}
if(cb_idx == 0)
disableTxWindow(1);
else
disableTxWindow(0);
updateCapabilities();
}
void RawTxWindow::sendRawMessage()
{
CanMessage msg;
bool en_extended = ui->checkBox_IsExtended->isChecked();
bool en_rtr = ui->checkBox_IsRTR->isChecked();
uint8_t data_int[64];
int data_ctr = 0;
data_int[data_ctr++] = ui->fieldByte0_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_0->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_1->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_2->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_3->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_4->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_5->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_6->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte0_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte1_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte2_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte3_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte4_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte5_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte6_7->text().toUpper().toInt(NULL, 16);
data_int[data_ctr++] = ui->fieldByte7_7->text().toUpper().toInt(NULL, 16);
uint32_t address = ui->fieldAddress->text().toUpper().toUInt(NULL, 16);
// If address is beyond std address namespace, force extended
if(address > 0x7ff)
{
en_extended = true;
ui->checkBox_IsExtended->setChecked(true);
}
// If address is larger than max for extended, clip
if(address >= 0x1FFFFFFF)
{
address = address & 0x1FFFFFFF;
ui->fieldAddress->setText(QString::number( address, 16 ).toUpper());
}
uint8_t dlc =ui->comboBoxDLC->currentData().toUInt();
// If DLC > 8, must be FD
if(dlc > 8)
{
ui->checkbox_FD->setChecked(true);
}
// Set payload data
for(int i=0; i<dlc; i++)
{
msg.setDataAt(i, data_int[i]);
}
msg.setId(address);
msg.setLength(dlc);
msg.setExtended(en_extended);
msg.setRTR(en_rtr);
msg.setErrorFrame(false);
if(ui->checkbox_BRS->isChecked())
msg.setBRS(true);
if(ui->checkbox_FD->isChecked())
msg.setFD(true);
CanInterface *intf = _backend.getInterfaceById((CanInterfaceId)ui->comboBoxInterface->currentData().toUInt());
intf->sendMessage(msg);
char outmsg[256];
snprintf(outmsg, 256, "Send [%s] to %d on port %s [ext=%u rtr=%u err=%u fd=%u brs=%u]",
msg.getDataHexString().toLocal8Bit().constData(), msg.getId(), intf->getName().toLocal8Bit().constData(),
msg.isExtended(), msg.isRTR(), msg.isErrorFrame(), msg.isFD(), msg.isBRS());
log_info(outmsg);
}
bool RawTxWindow::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
if (!ConfigurableWidget::saveXML(backend, xml, root)) { return false; }
root.setAttribute("type", "RawTxWindow");
return true;
}
bool RawTxWindow::loadXML(Backend &backend, QDomElement &el)
{
if (!ConfigurableWidget::loadXML(backend, el)) { return false; }
return true;
}
void RawTxWindow::hideFDFields()
{
ui->label_col21->hide();
ui->label_col22->hide();
ui->label_col23->hide();
ui->label_col24->hide();
ui->label_col25->hide();
ui->label_col26->hide();
ui->label_col27->hide();
ui->label_col28->hide();
ui->label_pay2->hide();
ui->label_pay3->hide();
ui->label_pay4->hide();
ui->label_pay5->hide();
ui->label_pay6->hide();
ui->label_pay7->hide();
ui->label_pay8->hide();
ui->fieldByte0_1->hide();
ui->fieldByte1_1->hide();
ui->fieldByte2_1->hide();
ui->fieldByte3_1->hide();
ui->fieldByte4_1->hide();
ui->fieldByte5_1->hide();
ui->fieldByte6_1->hide();
ui->fieldByte7_1->hide();
ui->fieldByte0_2->hide();
ui->fieldByte1_2->hide();
ui->fieldByte2_2->hide();
ui->fieldByte3_2->hide();
ui->fieldByte4_2->hide();
ui->fieldByte5_2->hide();
ui->fieldByte6_2->hide();
ui->fieldByte7_2->hide();
ui->fieldByte0_3->hide();
ui->fieldByte1_3->hide();
ui->fieldByte2_3->hide();
ui->fieldByte3_3->hide();
ui->fieldByte4_3->hide();
ui->fieldByte5_3->hide();
ui->fieldByte6_3->hide();
ui->fieldByte7_3->hide();
ui->fieldByte0_4->hide();
ui->fieldByte1_4->hide();
ui->fieldByte2_4->hide();
ui->fieldByte3_4->hide();
ui->fieldByte4_4->hide();
ui->fieldByte5_4->hide();
ui->fieldByte6_4->hide();
ui->fieldByte7_4->hide();
ui->fieldByte0_5->hide();
ui->fieldByte1_5->hide();
ui->fieldByte2_5->hide();
ui->fieldByte3_5->hide();
ui->fieldByte4_5->hide();
ui->fieldByte5_5->hide();
ui->fieldByte6_5->hide();
ui->fieldByte7_5->hide();
ui->fieldByte0_6->hide();
ui->fieldByte1_6->hide();
ui->fieldByte2_6->hide();
ui->fieldByte3_6->hide();
ui->fieldByte4_6->hide();
ui->fieldByte5_6->hide();
ui->fieldByte6_6->hide();
ui->fieldByte7_6->hide();
ui->fieldByte0_7->hide();
ui->fieldByte1_7->hide();
ui->fieldByte2_7->hide();
ui->fieldByte3_7->hide();
ui->fieldByte4_7->hide();
ui->fieldByte5_7->hide();
ui->fieldByte6_7->hide();
ui->fieldByte7_7->hide();
}
void RawTxWindow::showFDFields()
{
ui->label_col21->show();
ui->label_col22->show();
ui->label_col23->show();
ui->label_col24->show();
ui->label_col25->show();
ui->label_col26->show();
ui->label_col27->show();
ui->label_col28->show();
ui->label_pay2->show();
ui->label_pay3->show();
ui->label_pay4->show();
ui->label_pay5->show();
ui->label_pay6->show();
ui->label_pay7->show();
ui->label_pay8->show();
ui->fieldByte0_1->show();
ui->fieldByte1_1->show();
ui->fieldByte2_1->show();
ui->fieldByte3_1->show();
ui->fieldByte4_1->show();
ui->fieldByte5_1->show();
ui->fieldByte6_1->show();
ui->fieldByte7_1->show();
ui->fieldByte0_2->show();
ui->fieldByte1_2->show();
ui->fieldByte2_2->show();
ui->fieldByte3_2->show();
ui->fieldByte4_2->show();
ui->fieldByte5_2->show();
ui->fieldByte6_2->show();
ui->fieldByte7_2->show();
ui->fieldByte0_3->show();
ui->fieldByte1_3->show();
ui->fieldByte2_3->show();
ui->fieldByte3_3->show();
ui->fieldByte4_3->show();
ui->fieldByte5_3->show();
ui->fieldByte6_3->show();
ui->fieldByte7_3->show();
ui->fieldByte0_4->show();
ui->fieldByte1_4->show();
ui->fieldByte2_4->show();
ui->fieldByte3_4->show();
ui->fieldByte4_4->show();
ui->fieldByte5_4->show();
ui->fieldByte6_4->show();
ui->fieldByte7_4->show();
ui->fieldByte0_5->show();
ui->fieldByte1_5->show();
ui->fieldByte2_5->show();
ui->fieldByte3_5->show();
ui->fieldByte4_5->show();
ui->fieldByte5_5->show();
ui->fieldByte6_5->show();
ui->fieldByte7_5->show();
ui->fieldByte0_6->show();
ui->fieldByte1_6->show();
ui->fieldByte2_6->show();
ui->fieldByte3_6->show();
ui->fieldByte4_6->show();
ui->fieldByte5_6->show();
ui->fieldByte6_6->show();
ui->fieldByte7_6->show();
ui->fieldByte0_7->show();
ui->fieldByte1_7->show();
ui->fieldByte2_7->show();
ui->fieldByte3_7->show();
ui->fieldByte4_7->show();
ui->fieldByte5_7->show();
ui->fieldByte6_7->show();
ui->fieldByte7_7->show();
}

View File

@@ -0,0 +1,63 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <core/Backend.h>
#include <core/ConfigurableWidget.h>
#include <core/MeasurementSetup.h>
namespace Ui {
class RawTxWindow;
}
class QDomDocument;
class QDomElement;
class RawTxWindow : public ConfigurableWidget
{
Q_OBJECT
public:
explicit RawTxWindow(QWidget *parent, Backend &backend);
~RawTxWindow();
virtual bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
virtual bool loadXML(Backend &backend, QDomElement &el);
private slots:
void changeDLC();
void updateCapabilities();
void changeRepeatRate(int ms);
void sendRepeatMessage(bool enable);
void disableTxWindow(int disable);
void refreshInterfaces();
void sendRawMessage();
private:
Ui::RawTxWindow *ui;
Backend &_backend;
QTimer *repeatmsg_timer;
void hideFDFields();
void showFDFields();
};

View File

@@ -0,0 +1,8 @@
SOURCES += \
$$PWD/RawTxWindow.cpp
HEADERS += \
$$PWD/RawTxWindow.h
FORMS += \
$$PWD/RawTxWindow.ui

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SelectCanInterfacesDialog.h"
#include "ui_SelectCanInterfacesDialog.h"
#include <core/Backend.h>
SelectCanInterfacesDialog::SelectCanInterfacesDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SelectCanInterfacesDialog)
{
ui->setupUi(this);
ui->treeWidget->setHeaderLabels(QStringList() << "Device" << "Driver" << "Description");
}
SelectCanInterfacesDialog::~SelectCanInterfacesDialog()
{
delete ui;
}
bool SelectCanInterfacesDialog::selectInterfaces(Backend &backend, CanInterfaceIdList &selectedInterfaces, const CanInterfaceIdList &excludeInterfaces)
{
ui->treeWidget->clear();
CanInterfaceIdList allInterfaces;
foreach (CanInterfaceId intf, backend.getInterfaceList()) {
if (!excludeInterfaces.contains(intf)) {
allInterfaces.append(intf);
}
}
foreach (CanInterfaceId intf, allInterfaces) {
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui->treeWidget);
treeItem->setText(0, backend.getInterfaceName(intf));
treeItem->setText(1, backend.getDriverName(intf));
treeItem->setText(2, "");
}
if (exec()==QDialog::Accepted) {
selectedInterfaces.clear();
foreach (QModelIndex idx, ui->treeWidget->selectionModel()->selectedRows()) {
if (idx.isValid()) {
selectedInterfaces.append(allInterfaces[idx.row()]);
}
}
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,47 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QDialog>
#include <QList>
#include <driver/CanDriver.h>
#include <driver/CanInterface.h>
class Backend;
namespace Ui {
class SelectCanInterfacesDialog;
}
class SelectCanInterfacesDialog : public QDialog
{
Q_OBJECT
public:
explicit SelectCanInterfacesDialog(QWidget *parent = 0);
~SelectCanInterfacesDialog();
bool selectInterfaces(Backend &backend, CanInterfaceIdList &selectedInterfaces, const CanInterfaceIdList &excludeInterfaces);
private:
Ui::SelectCanInterfacesDialog *ui;
};

View File

@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SelectCanInterfacesDialog</class>
<widget class="QDialog" name="SelectCanInterfacesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>570</width>
<height>438</height>
</rect>
</property>
<property name="windowTitle">
<string>Select CAN Interface(s)</string>
</property>
<property name="windowIcon">
<iconset resource="../../cangaroo.qrc">
<normaloff>:/assets/cangaroo.png</normaloff>:/assets/cangaroo.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="indentation">
<number>0</number>
</property>
<property name="columnCount">
<number>3</number>
</property>
<attribute name="headerDefaultSectionSize">
<number>100</number>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">3</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>&amp;Create Interface...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../cangaroo.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SelectCanInterfacesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SelectCanInterfacesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,340 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SetupDialog.h"
#include "ui_SetupDialog.h"
#include <QItemSelectionModel>
#include <QMenu>
#include <QFileDialog>
#include <QTreeWidget>
#include <core/Backend.h>
#include <core/MeasurementSetup.h>
#include <driver/CanInterface.h>
#include <driver/CanDriver.h>
#include "SetupDialogTreeModel.h"
#include "SetupDialogTreeItem.h"
#include "SelectCanInterfacesDialog.h"
SetupDialog::SetupDialog(Backend &backend, QWidget *parent) :
QDialog(parent),
ui(new Ui::SetupDialog),
_backend(&backend),
_currentNetwork(0)
{
ui->setupUi(this);
QIcon icon(":/assets/cangaroo.png");
setWindowIcon(icon);
_actionAddInterface = new QAction("Add...", this);
_actionDeleteInterface = new QAction("Delete", this);
_actionAddCanDb = new QAction("Add...", this);
_actionDeleteCanDb = new QAction("Delete", this);
_actionReloadCanDbs = new QAction("Reload", this);
model = new SetupDialogTreeModel(_backend, this);
ui->treeView->setModel(model);
ui->interfacesTreeView->setModel(model);
ui->candbsTreeView->setModel(model);
for (int i=0; i<model->columnCount(); i++) {
ui->treeView->setColumnHidden(i, true);
ui->interfacesTreeView->setColumnHidden(i, true);
ui->candbsTreeView->setColumnHidden(i, true);
}
ui->treeView->setColumnHidden(SetupDialogTreeModel::column_device, false);
ui->interfacesTreeView->setColumnHidden(SetupDialogTreeModel::column_device, false);
ui->interfacesTreeView->setColumnHidden(SetupDialogTreeModel::column_driver, false);
ui->interfacesTreeView->setColumnHidden(SetupDialogTreeModel::column_bitrate, false);
ui->candbsTreeView->setColumnHidden(SetupDialogTreeModel::column_filename, false);
ui->candbsTreeView->setColumnHidden(SetupDialogTreeModel::column_path, false);
connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(treeViewContextMenu(QPoint)));
connect(ui->edNetworkName, SIGNAL(textChanged(QString)), this, SLOT(edNetworkNameChanged()));
connect(ui->treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(treeViewSelectionChanged(QItemSelection,QItemSelection)));
connect(ui->candbsTreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateButtons()));
connect(ui->interfacesTreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateButtons()));
connect(ui->btReloadDatabases, SIGNAL (released()), this, SLOT(executeReloadCanDbs()));
connect(ui->btRefreshNetworks, SIGNAL(released()), this, SLOT(on_btRefreshNetwork_clicked()));
connect(_actionAddCanDb, SIGNAL(triggered()), this, SLOT(executeAddCanDb()));
connect(_actionDeleteCanDb, SIGNAL(triggered()), this, SLOT(executeDeleteCanDb()));
connect(_actionAddInterface, SIGNAL(triggered()), this, SLOT(executeAddInterface()));
connect(_actionDeleteInterface, SIGNAL(triggered()), this, SLOT(executeDeleteInterface()));
emit backend.onSetupDialogCreated(*this);
}
SetupDialog::~SetupDialog()
{
delete ui;
delete model;
}
void SetupDialog::addPage(QWidget *widget)
{
ui->stackedWidget->addWidget(widget);
}
void SetupDialog::displayPage(QWidget *widget)
{
ui->stackedWidget->setCurrentWidget(widget);
}
bool SetupDialog::showSetupDialog(MeasurementSetup &setup)
{
model->load(setup);
ui->treeView->expandAll();
QModelIndex first = model->index(0, 0, QModelIndex());
ui->treeView->setCurrentIndex(first);
updateButtons();
return exec()==QDialog::Accepted;
}
void SetupDialog::treeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
(void) selected;
(void) deselected;
_currentNetwork = 0;
if (selected.isEmpty()) {
ui->stackedWidget->setCurrentWidget(ui->emptyPage);
updateButtons();
return;
}
QModelIndex idx = selected.first().topLeft();
SetupDialogTreeItem *item = static_cast<SetupDialogTreeItem *>(idx.internalPointer());
_currentNetwork = item->network;
if (item->network) {
ui->edNetworkName->setText(item->network->name());
}
if (item) {
switch (item->getType()) {
case SetupDialogTreeItem::type_network:
ui->stackedWidget->setCurrentWidget(ui->networkPage);
break;
case SetupDialogTreeItem::type_interface_root:
ui->stackedWidget->setCurrentWidget(ui->interfacesPage);
ui->interfacesTreeView->setRootIndex(getSelectedIndex());
break;
case SetupDialogTreeItem::type_interface:
emit onShowInterfacePage(*this, item->intf);
break;
case SetupDialogTreeItem::type_candb_root:
ui->stackedWidget->setCurrentWidget(ui->candbsPage);
ui->candbsTreeView->setRootIndex(getSelectedIndex());
break;
default:
ui->stackedWidget->setCurrentWidget(ui->emptyPage);
break;
}
}
updateButtons();
}
QModelIndex SetupDialog::getSelectedIndex()
{
QModelIndexList list = ui->treeView->selectionModel()->selectedRows();
if (list.isEmpty()) {
return QModelIndex();
} else {
return list.first();
}
}
SetupDialogTreeItem *SetupDialog::getSelectedItem()
{
const QModelIndex index = getSelectedIndex();
SetupDialogTreeItem *item = static_cast<SetupDialogTreeItem *>(index.internalPointer());
return item;
}
void SetupDialog::treeViewContextMenu(const QPoint &pos)
{
(void) pos;
QMenu contextMenu;
SetupDialogTreeItem *item = getSelectedItem();
if (item) {
switch (item->getType()) {
case SetupDialogTreeItem::type_interface_root:
contextMenu.addAction(_actionAddInterface);
break;
case SetupDialogTreeItem::type_interface:
contextMenu.addAction(_actionDeleteInterface);
break;
case SetupDialogTreeItem::type_candb_root:
contextMenu.addAction(_actionAddCanDb);
break;
case SetupDialogTreeItem::type_candb:
contextMenu.addAction(_actionDeleteCanDb);
contextMenu.addAction(_actionReloadCanDbs);
break;
default:
break;
}
}
QPoint globalPos = ui->treeView->mapToGlobal(pos);
contextMenu.exec(globalPos);
}
void SetupDialog::edNetworkNameChanged()
{
if (_currentNetwork) {
_currentNetwork->setName(ui->edNetworkName->text());
model->dataChanged(getSelectedIndex(), getSelectedIndex());
}
}
void SetupDialog::addInterface(const QModelIndex &parent)
{
SelectCanInterfacesDialog dlg(0);
CanInterfaceIdList list;
if (dlg.selectInterfaces(*_backend, list, _currentNetwork->getReferencedCanInterfaces())) {
foreach (CanInterfaceId intf, list) {
model->addInterface(parent, intf);
}
}
}
void SetupDialog::executeAddInterface()
{
addInterface(ui->treeView->selectionModel()->currentIndex());
}
void SetupDialog::on_btAddInterface_clicked()
{
addInterface(ui->treeView->selectionModel()->currentIndex());
}
void SetupDialog::executeDeleteInterface()
{
model->deleteInterface(ui->treeView->selectionModel()->currentIndex());
}
void SetupDialog::on_btRemoveInterface_clicked()
{
model->deleteInterface(ui->interfacesTreeView->selectionModel()->currentIndex());
}
void SetupDialog::addCanDb(const QModelIndex &parent)
{
QString filename = QFileDialog::getOpenFileName(this, "Load CAN Database", "", "Vector DBC Files (*.dbc)");
if (!filename.isNull()) {
pCanDb candb = _backend->loadDbc(filename);
model->addCanDb(parent, candb);
}
}
void SetupDialog::reloadCanDbs(const QModelIndex &parent)
{
SetupDialogTreeItem *parentItem = static_cast<SetupDialogTreeItem*>(parent.internalPointer());
parentItem->network->reloadCanDbs(_backend);
}
void SetupDialog::executeAddCanDb()
{
addCanDb(ui->treeView->selectionModel()->currentIndex());
}
void SetupDialog::executeReloadCanDbs()
{
reloadCanDbs(ui->treeView->selectionModel()->currentIndex());
}
void SetupDialog::on_btAddDatabase_clicked()
{
addCanDb(ui->treeView->selectionModel()->currentIndex());
}
void SetupDialog::executeDeleteCanDb()
{
model->deleteCanDb(getSelectedIndex());
}
void SetupDialog::on_btRemoveDatabase_clicked()
{
model->deleteCanDb(ui->candbsTreeView->selectionModel()->currentIndex());
}
void SetupDialog::updateButtons()
{
ui->btRemoveDatabase->setEnabled(ui->candbsTreeView->selectionModel()->hasSelection());
// ui->btReloadDatabases->setEnabled(ui->candbsTreeView->children.count() > 0);
ui->btRemoveInterface->setEnabled(ui->interfacesTreeView->selectionModel()->hasSelection());
SetupDialogTreeItem *item = getSelectedItem();
ui->btRemoveNetwork->setEnabled(ui->treeView->selectionModel()->hasSelection() && item && (item->getType()==SetupDialogTreeItem::type_network));
}
void SetupDialog::on_btAddNetwork_clicked()
{
QModelIndex idx = model->indexOfItem(model->addNetwork());
ui->treeView->expand(idx);
ui->treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect);
}
void SetupDialog::on_btRemoveNetwork_clicked()
{
model->deleteNetwork(getSelectedIndex());
}
void SetupDialog::on_btRefreshNetworks_clicked()
{
_backend->setDefaultSetup();
showSetupDialog(_backend->getSetup());
}

View File

@@ -0,0 +1,101 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QDialog>
#include <QAction>
class Backend;
class MeasurementSetup;
class MeasurementNetwork;
class MeasurementInterface;
class QItemSelection;
class SetupDialogTreeItem;
class SetupDialogTreeModel;
namespace Ui {
class SetupDialog;
}
class SetupDialog : public QDialog
{
Q_OBJECT
public:
explicit SetupDialog(Backend &backend, QWidget *parent = 0);
~SetupDialog();
bool showSetupDialog(MeasurementSetup &setup);
void addPage(QWidget *widget);
void displayPage(QWidget *widget);
signals:
void onShowInterfacePage(SetupDialog &dlg, MeasurementInterface *mi);
public slots:
void treeViewSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
void treeViewContextMenu(const QPoint& pos);
private slots:
void edNetworkNameChanged();
void on_btAddInterface_clicked();
void on_btRemoveInterface_clicked();
void on_btAddDatabase_clicked();
void on_btRemoveDatabase_clicked();
void updateButtons();
void executeAddCanDb();
void executeReloadCanDbs();
void executeDeleteCanDb();
void executeAddInterface();
void executeDeleteInterface();
void on_btAddNetwork_clicked();
void on_btRemoveNetwork_clicked();
void on_btRefreshNetworks_clicked();
private:
Ui::SetupDialog *ui;
Backend *_backend;
QAction *_actionDeleteInterface;
QAction *_actionDeleteCanDb;
QAction *_actionAddInterface;
QAction *_actionAddCanDb;
QAction *_actionReloadCanDbs;
SetupDialogTreeModel *model;
MeasurementNetwork *_currentNetwork;
QModelIndex getSelectedIndex();
SetupDialogTreeItem *getSelectedItem();
void addCanDb(const QModelIndex &parent);
void reloadCanDbs(const QModelIndex &parent);
void addInterface(const QModelIndex &parent);
};

View File

@@ -0,0 +1,15 @@
SOURCES += \
$$PWD/SetupDialog.cpp \
$$PWD/SetupDialogTreeModel.cpp \
$$PWD/SetupDialogTreeItem.cpp \
$$PWD/SelectCanInterfacesDialog.cpp
HEADERS += \
$$PWD/SetupDialog.h \
$$PWD/SetupDialogTreeModel.h \
$$PWD/SetupDialogTreeItem.h \
$$PWD/SelectCanInterfacesDialog.h
FORMS += \
$$PWD/SetupDialog.ui \
$$PWD/SelectCanInterfacesDialog.ui

View File

@@ -0,0 +1,315 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetupDialog</class>
<widget class="QDialog" name="SetupDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1036</width>
<height>835</height>
</rect>
</property>
<property name="windowTitle">
<string>Measurement Setup</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="widget_4" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="treeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_5" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btAddNetwork">
<property name="text">
<string>Add Network</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btRemoveNetwork">
<property name="text">
<string>Remove Network</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btRefreshNetworks">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="emptyPage"/>
<widget class="QWidget" name="networkPage">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Network name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="edNetworkName"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="interfacesPage">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>CAN interfaces assigned to this network:</string>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="interfacesTreeView"/>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btAddInterface">
<property name="text">
<string>Add &amp;Interface...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btRemoveInterface">
<property name="text">
<string>&amp;Remove Interface</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="candbsPage">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="candbsTreeView">
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_3" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btAddDatabase">
<property name="text">
<string>Add &amp;Database...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btRemoveDatabase">
<property name="text">
<string>&amp;Remove Database</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btReloadDatabases">
<property name="text">
<string>Reload Databases</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SetupDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>266</x>
<y>825</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SetupDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>825</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,117 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SetupDialogTreeItem.h"
#include <QModelIndex>
#include <driver/CanDriver.h>
#include "SetupDialogTreeModel.h"
SetupDialogTreeItem::SetupDialogTreeItem(item_type type, Backend *backend, SetupDialogTreeItem *parent)
: setup(0), network(0), intf(0), candb(0), _backend(backend), _type(type), _parent(parent)
{
}
SetupDialogTreeItem::~SetupDialogTreeItem()
{
qDeleteAll(_children);
}
SetupDialogTreeItem *SetupDialogTreeItem::getParentItem() const
{
return _parent;
}
int SetupDialogTreeItem::getChildCount() const
{
return _children.length();
}
void SetupDialogTreeItem::appendChild(SetupDialogTreeItem *child)
{
_children.append(child);
}
void SetupDialogTreeItem::removeChild(SetupDialogTreeItem *child)
{
_children.removeAll(child);
}
SetupDialogTreeItem *SetupDialogTreeItem::child(int row) const
{
return _children.value(row);
}
int SetupDialogTreeItem::row() const
{
if (_parent) {
return _parent->_children.indexOf(const_cast<SetupDialogTreeItem*>(this));
} else {
return 0;
}
}
QVariant SetupDialogTreeItem::dataInterface(const QModelIndex &index) const
{
switch (index.column()) {
case SetupDialogTreeModel::column_device:
return _backend->getInterfaceName(intf->canInterface());
case SetupDialogTreeModel::column_driver:
return _backend->getDriverName(intf->canInterface());
case SetupDialogTreeModel::column_bitrate:
return intf->bitrate();
default:
return QVariant();
}
}
QVariant SetupDialogTreeItem::dataCanDb(const QModelIndex &index) const
{
switch (index.column()) {
case SetupDialogTreeModel::column_device:
return candb->getFileName();
case SetupDialogTreeModel::column_filename:
return candb->getFileName();
case SetupDialogTreeModel::column_path:
return candb->getDirectory();
default:
return QVariant();
}
}
QVariant SetupDialogTreeItem::dataDisplayRole(const QModelIndex &index) const
{
switch (_type) {
case type_root: return "Setup";
case type_network: return (network!=0) ? network->name() : QVariant();
case type_interface_root: return "Interfaces";
case type_interface: return dataInterface(index);
case type_candb_root: return "Can Databases";
case type_candb: return dataCanDb(index);
}
return QVariant();
}
SetupDialogTreeItem::item_type SetupDialogTreeItem::getType()
{
return _type;
}

View File

@@ -0,0 +1,74 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QList>
#include <QVariant>
#include <core/Backend.h>
#include <core/MeasurementSetup.h>
#include <core/MeasurementNetwork.h>
#include <core/MeasurementInterface.h>
#include <core/CanDb.h>
class SetupDialogTreeItem
{
public:
typedef enum {
type_root,
type_network,
type_interface_root,
type_interface,
type_candb_root,
type_candb,
} item_type;
public:
SetupDialogTreeItem(item_type type, Backend *backend, SetupDialogTreeItem *parent=0);
virtual ~SetupDialogTreeItem();
MeasurementSetup *setup;
MeasurementNetwork *network;
MeasurementInterface *intf;
pCanDb candb;
SetupDialogTreeItem *getParentItem() const;
int getChildCount() const;
void appendChild(SetupDialogTreeItem *child);
void removeChild(SetupDialogTreeItem *child);
SetupDialogTreeItem *child(int row) const;
int row() const;
QVariant dataDisplayRole(const QModelIndex &index) const;
item_type getType();
private:
Backend *_backend;
item_type _type;
SetupDialogTreeItem *_parent;
QList<SetupDialogTreeItem*> _children;
QVariant dataInterface(const QModelIndex &index) const;
QVariant dataCanDb(const QModelIndex &index) const;
};

View File

@@ -0,0 +1,263 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SetupDialogTreeModel.h"
SetupDialogTreeModel::SetupDialogTreeModel(Backend *backend, QObject *parent)
: QAbstractItemModel(parent),
_backend(backend),
_rootItem(0)
{
}
SetupDialogTreeModel::~SetupDialogTreeModel()
{
if (_rootItem) {
delete _rootItem;
}
}
QVariant SetupDialogTreeModel::data(const QModelIndex &index, int role) const
{
SetupDialogTreeItem *item = static_cast<SetupDialogTreeItem*>(index.internalPointer());
if (item) {
if (role==Qt::DisplayRole) {
return item->dataDisplayRole(index);
}
}
return QVariant();
}
QVariant SetupDialogTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
(void) orientation;
if (role==Qt::DisplayRole) {
switch (section) {
case column_device: return "Device";
case column_driver: return "Driver";
case column_bitrate: return "Bitrate";
case column_filename: return "Filename";
case column_path: return "Path";
default: return "";
}
} else {
return QVariant();
}
}
QModelIndex SetupDialogTreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
} else {
SetupDialogTreeItem *parentItem = itemOrRoot(parent);
SetupDialogTreeItem *childItem = parentItem->child(row);
return childItem ? createIndex(row, column, childItem) : QModelIndex();
}
}
QModelIndex SetupDialogTreeModel::parent(const QModelIndex &index) const
{
if (!index.isValid()) { return QModelIndex(); }
SetupDialogTreeItem *childItem = static_cast<SetupDialogTreeItem*>(index.internalPointer());
SetupDialogTreeItem *parentItem = childItem->getParentItem();
return (parentItem == _rootItem) ? QModelIndex() : createIndex(parentItem->row(), 0, parentItem);
}
int SetupDialogTreeModel::rowCount(const QModelIndex &parent) const
{
int retval = 0;
if (parent.column() <= 0) {
SetupDialogTreeItem *item = itemOrRoot(parent);
if (item) {
retval = item->getChildCount();
}
}
return retval;
}
int SetupDialogTreeModel::columnCount(const QModelIndex &parent) const
{
(void) parent;
return column_count;
}
QModelIndex SetupDialogTreeModel::indexOfItem(const SetupDialogTreeItem *item) const
{
return createIndex(item->row(), 0, (void*)item);
}
SetupDialogTreeItem *SetupDialogTreeModel::addNetwork()
{
QString s;
int i=0;
while (true) {
s = QString("Network %1").arg(++i);
if (_rootItem->setup->getNetworkByName(s)==0) {
break;
}
}
beginInsertRows(QModelIndex(), _rootItem->getChildCount(), _rootItem->getChildCount());
MeasurementNetwork *network = _rootItem->setup->createNetwork();
network->setName(s);
SetupDialogTreeItem *item = loadNetwork(_rootItem, *network);
endInsertRows();
return item;
}
void SetupDialogTreeModel::deleteNetwork(const QModelIndex &index)
{
SetupDialogTreeItem *item = static_cast<SetupDialogTreeItem*>(index.internalPointer());
beginRemoveRows(index.parent(), index.row(), index.row());
_rootItem->removeChild(item);
_rootItem->setup->removeNetwork(item->network);
endRemoveRows();
}
SetupDialogTreeItem *SetupDialogTreeModel::addCanDb(const QModelIndex &parent, pCanDb db)
{
SetupDialogTreeItem *parentItem = static_cast<SetupDialogTreeItem*>(parent.internalPointer());
if (!parentItem) { return 0; }
SetupDialogTreeItem *item = 0;
if (parentItem->network) {
beginInsertRows(parent, rowCount(parent), rowCount(parent));
parentItem->network->addCanDb(db);
item = loadCanDb(*parentItem, db);
endInsertRows();
}
return item;
}
void SetupDialogTreeModel::deleteCanDb(const QModelIndex &index)
{
SetupDialogTreeItem *item = static_cast<SetupDialogTreeItem*>(index.internalPointer());
if (!item) { return; }
SetupDialogTreeItem *parentItem = item->getParentItem();
if (parentItem && parentItem->network && parentItem->network->_canDbs.contains(item->candb)) {
parentItem->network->_canDbs.removeAll(item->candb);
beginRemoveRows(index.parent(), item->row(), item->row());
item->getParentItem()->removeChild(item);
endRemoveRows();
}
}
SetupDialogTreeItem *SetupDialogTreeModel::addInterface(const QModelIndex &parent, CanInterfaceId &interface)
{
SetupDialogTreeItem *parentItem = static_cast<SetupDialogTreeItem*>(parent.internalPointer());
if (!parentItem) { return 0; }
SetupDialogTreeItem *item = 0;
if (parentItem && parentItem->network) {
beginInsertRows(parent, parentItem->getChildCount(), parentItem->getChildCount());
MeasurementInterface *mi = parentItem->network->addCanInterface(interface);
item = loadMeasurementInterface(*parentItem, mi);
endInsertRows();
}
return item;
}
void SetupDialogTreeModel::deleteInterface(const QModelIndex &index)
{
SetupDialogTreeItem *item = static_cast<SetupDialogTreeItem*>(index.internalPointer());
if (!item) { return; }
SetupDialogTreeItem *parentItem = item->getParentItem();
if (parentItem && parentItem->network && parentItem->network->interfaces().contains(item->intf)) {
parentItem->network->removeInterface(item->intf);
beginRemoveRows(index.parent(), item->row(), item->row());
item->getParentItem()->removeChild(item);
endRemoveRows();
}
}
SetupDialogTreeItem *SetupDialogTreeModel::itemOrRoot(const QModelIndex &index) const
{
return index.isValid() ? static_cast<SetupDialogTreeItem*>(index.internalPointer()) : _rootItem;
}
SetupDialogTreeItem *SetupDialogTreeModel::loadMeasurementInterface(SetupDialogTreeItem &parent, MeasurementInterface *intf)
{
SetupDialogTreeItem *item = new SetupDialogTreeItem(SetupDialogTreeItem::type_interface, _backend, &parent);
item->intf = intf;
parent.appendChild(item);
return item;
}
SetupDialogTreeItem *SetupDialogTreeModel::loadCanDb(SetupDialogTreeItem &parent, pCanDb &db)
{
SetupDialogTreeItem *item = new SetupDialogTreeItem(SetupDialogTreeItem::type_candb, _backend, &parent);
item->candb = db;
parent.appendChild(item);
return item;
}
SetupDialogTreeItem *SetupDialogTreeModel::loadNetwork(SetupDialogTreeItem *root, MeasurementNetwork &network)
{
SetupDialogTreeItem *item_network = new SetupDialogTreeItem(SetupDialogTreeItem::type_network, _backend, root);
item_network->network = &network;
SetupDialogTreeItem *item_intf_root = new SetupDialogTreeItem(SetupDialogTreeItem::type_interface_root, _backend, item_network);
item_intf_root->network = &network;
item_network->appendChild(item_intf_root);
SetupDialogTreeItem *item_candb_root = new SetupDialogTreeItem(SetupDialogTreeItem::type_candb_root, _backend, item_network);
item_candb_root->network = &network;
item_network->appendChild(item_candb_root);
foreach (MeasurementInterface *intf, network.interfaces()) {
loadMeasurementInterface(*item_intf_root, intf);
}
foreach (pCanDb candb, network._canDbs) {
loadCanDb(*item_candb_root, candb);
}
root->appendChild(item_network);
return item_network;
}
void SetupDialogTreeModel::load(MeasurementSetup &setup)
{
SetupDialogTreeItem *_newRoot = new SetupDialogTreeItem(SetupDialogTreeItem::type_root, 0);
_newRoot->setup = &setup;
foreach (MeasurementNetwork *network, setup.getNetworks()) {
loadNetwork(_newRoot, *network);
}
beginResetModel();
SetupDialogTreeItem *_oldRoot = _rootItem;
_rootItem = _newRoot;
delete _oldRoot;
endResetModel();
}

View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "SetupDialogTreeItem.h"
#include <QAbstractItemModel>
#include <core/Backend.h>
#include <core/MeasurementSetup.h>
class SetupDialogTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum {
column_device,
column_driver,
column_bitrate,
column_filename,
column_path,
column_count
};
public:
explicit SetupDialogTreeModel(Backend *backend, QObject *parent=0);
virtual ~SetupDialogTreeModel();
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
QModelIndex indexOfItem(const SetupDialogTreeItem *item) const;
void load(MeasurementSetup &setup);
SetupDialogTreeItem *addNetwork();
void deleteNetwork(const QModelIndex &index);
int getNetworkCount();
SetupDialogTreeItem *addCanDb(const QModelIndex &parent, pCanDb db);
void deleteCanDb(const QModelIndex &index);
SetupDialogTreeItem *addInterface(const QModelIndex &parent, CanInterfaceId &interface);
void deleteInterface(const QModelIndex &index);
private:
Backend *_backend;
SetupDialogTreeItem *_rootItem;
SetupDialogTreeItem *itemOrRoot(const QModelIndex &index) const;
SetupDialogTreeItem *loadNetwork(SetupDialogTreeItem *root, MeasurementNetwork &network);
SetupDialogTreeItem *loadMeasurementInterface(SetupDialogTreeItem &parent, MeasurementInterface *intf);
SetupDialogTreeItem *loadCanDb(SetupDialogTreeItem &parent, pCanDb &db);
};

View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AggregatedTraceViewItem.h"
AggregatedTraceViewItem::AggregatedTraceViewItem(AggregatedTraceViewItem *parent)
: _parent(parent)
{
}
AggregatedTraceViewItem::~AggregatedTraceViewItem()
{
qDeleteAll(_children);
}
void AggregatedTraceViewItem::appendChild(AggregatedTraceViewItem *child)
{
_children.append(child);
}
AggregatedTraceViewItem *AggregatedTraceViewItem::child(int row) const
{
return _children.value(row);
}
int AggregatedTraceViewItem::childCount() const
{
return _children.count();
}
int AggregatedTraceViewItem::row() const
{
if (_parent) {
return _parent->_children.indexOf(const_cast<AggregatedTraceViewItem*>(this));
} else {
return 0;
}
}
AggregatedTraceViewItem *AggregatedTraceViewItem::parent() const
{
return _parent;
}
AggregatedTraceViewItem *AggregatedTraceViewItem::firstChild() const
{
return _children.first();
}
AggregatedTraceViewItem *AggregatedTraceViewItem::lastChild() const
{
return _children.last();
}

View File

@@ -0,0 +1,48 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <sys/time.h>
#include <core/CanMessage.h>
#include <QList>
class AggregatedTraceViewItem
{
public:
AggregatedTraceViewItem(AggregatedTraceViewItem *parent);
virtual ~AggregatedTraceViewItem();
void appendChild(AggregatedTraceViewItem *child);
AggregatedTraceViewItem *child(int row) const;
int childCount() const;
int row() const;
AggregatedTraceViewItem *parent() const;
AggregatedTraceViewItem *firstChild() const;
AggregatedTraceViewItem *lastChild() const;
CanMessage _lastmsg, _prevmsg;
private:
AggregatedTraceViewItem *_parent;
QList<AggregatedTraceViewItem *> _children;
};

View File

@@ -0,0 +1,220 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AggregatedTraceViewModel.h"
#include <QColor>
#include <core/Backend.h>
#include <core/CanTrace.h>
#include <core/CanDbMessage.h>
AggregatedTraceViewModel::AggregatedTraceViewModel(Backend &backend)
: BaseTraceViewModel(backend)
{
_rootItem = new AggregatedTraceViewItem(0);
connect(backend.getTrace(), SIGNAL(beforeAppend(int)), this, SLOT(beforeAppend(int)));
connect(backend.getTrace(), SIGNAL(beforeClear()), this, SLOT(beforeClear()));
connect(backend.getTrace(), SIGNAL(afterClear()), this, SLOT(afterClear()));
connect(&backend, SIGNAL(onSetupChanged()), this, SLOT(onSetupChanged()));
}
void AggregatedTraceViewModel::createItem(const CanMessage &msg)
{
AggregatedTraceViewItem *item = new AggregatedTraceViewItem(_rootItem);
item->_lastmsg = msg;
CanDbMessage *dbmsg = backend()->findDbMessage(msg);
if (dbmsg) {
for (int i=0; i<dbmsg->getSignals().length(); i++) {
item->appendChild(new AggregatedTraceViewItem(item));
}
}
_rootItem->appendChild(item);
_map[makeUniqueKey(msg)] = item;
}
void AggregatedTraceViewModel::updateItem(const CanMessage &msg)
{
AggregatedTraceViewItem *item = _map.value(makeUniqueKey(msg));
if (item) {
item->_prevmsg = item->_lastmsg;
item->_lastmsg = msg;
}
}
void AggregatedTraceViewModel::onUpdateModel()
{
if (!_pendingMessageInserts.isEmpty()) {
beginInsertRows(QModelIndex(), _rootItem->childCount(), _rootItem->childCount()+_pendingMessageInserts.size()-1);
foreach (CanMessage msg, _pendingMessageInserts) {
createItem(msg);
}
endInsertRows();
_pendingMessageInserts.clear();
}
if (!_pendingMessageUpdates.isEmpty()) {
foreach (CanMessage msg, _pendingMessageUpdates) {
updateItem(msg);
}
_pendingMessageUpdates.clear();
}
if (_rootItem->childCount()>0) {
dataChanged(createIndex(0, 0, _rootItem->firstChild()), createIndex(_rootItem->childCount()-1, column_count-1, _rootItem->lastChild()));
}
}
void AggregatedTraceViewModel::onSetupChanged()
{
beginResetModel();
endResetModel();
}
void AggregatedTraceViewModel::beforeAppend(int num_messages)
{
CanTrace *trace = backend()->getTrace();
int start_id = trace->size();
for (int i=start_id; i<start_id + num_messages; i++) {
const CanMessage *msg = trace->getMessage(i);
unique_key_t key = makeUniqueKey(*msg);
if (_map.contains(key) || _pendingMessageInserts.contains(key)) {
_pendingMessageUpdates.append(*msg);
} else {
_pendingMessageInserts[key] = *msg;
}
}
onUpdateModel();
}
void AggregatedTraceViewModel::beforeClear()
{
beginResetModel();
delete _rootItem;
_map.clear();
_rootItem = new AggregatedTraceViewItem(0);
}
void AggregatedTraceViewModel::afterClear()
{
endResetModel();
}
AggregatedTraceViewModel::unique_key_t AggregatedTraceViewModel::makeUniqueKey(const CanMessage &msg) const
{
return ((uint64_t)msg.getInterfaceId() << 32) | msg.getRawId();
}
double AggregatedTraceViewModel::getTimeDiff(const timeval t1, const timeval t2) const
{
double diff = t2.tv_sec - t1.tv_sec;
diff += ((double)(t2.tv_usec - t1.tv_usec)) / 1000000;
return diff;
}
QModelIndex AggregatedTraceViewModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
const AggregatedTraceViewItem *parentItem = parent.isValid() ? static_cast<AggregatedTraceViewItem*>(parent.internalPointer()) : _rootItem;
const AggregatedTraceViewItem *childItem = parentItem->child(row);
if (childItem) {
return createIndex(row, column, const_cast<AggregatedTraceViewItem*>(childItem));
} else {
return QModelIndex();
}
}
QModelIndex AggregatedTraceViewModel::parent(const QModelIndex &index) const
{
if (!index.isValid()) {
return QModelIndex();
}
AggregatedTraceViewItem *childItem = (AggregatedTraceViewItem*) index.internalPointer();
AggregatedTraceViewItem *parentItem = childItem->parent();
if (parentItem == _rootItem) {
return QModelIndex();
}
return createIndex(parentItem->row(), 0, parentItem);
}
int AggregatedTraceViewModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0) {
return 0;
}
AggregatedTraceViewItem *parentItem;
if (parent.isValid()) {
parentItem = (AggregatedTraceViewItem*)parent.internalPointer();
} else {
parentItem = _rootItem;
}
return parentItem->childCount();
}
QVariant AggregatedTraceViewModel::data_DisplayRole(const QModelIndex &index, int role) const
{
AggregatedTraceViewItem *item = (AggregatedTraceViewItem *)index.internalPointer();
if (!item) { return QVariant(); }
if (item->parent() == _rootItem) { // CanMessage row
return data_DisplayRole_Message(index, role, item->_lastmsg, item->_prevmsg);
} else { // CanSignal Row
return data_DisplayRole_Signal(index, role, item->parent()->_lastmsg);
}
}
QVariant AggregatedTraceViewModel::data_TextColorRole(const QModelIndex &index, int role) const
{
(void) role;
AggregatedTraceViewItem *item = (AggregatedTraceViewItem *)index.internalPointer();
if (!item) { return QVariant(); }
if (item->parent() == _rootItem) { // CanMessage row
struct timeval now;
gettimeofday(&now, 0);
int color = getTimeDiff(item->_lastmsg.getTimestamp(), now)*100;
if (color>200) { color = 200; }
if (color<0) { color = 0; }
return QVariant::fromValue(QColor(color, color, color));
} else { // CanSignal Row
return data_TextColorRole_Signal(index, role, item->parent()->_lastmsg);
}
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QAbstractItemModel>
#include <QMap>
#include <QList>
#include <sys/time.h>
#include "BaseTraceViewModel.h"
#include <core/CanMessage.h>
#include <driver/CanInterface.h>
#include "AggregatedTraceViewItem.h"
class CanTrace;
class AggregatedTraceViewModel : public BaseTraceViewModel
{
Q_OBJECT
public:
typedef uint64_t unique_key_t;
typedef QMap<unique_key_t, AggregatedTraceViewItem*> CanIdMap;
public:
AggregatedTraceViewModel(Backend &backend);
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const;
virtual QModelIndex parent(const QModelIndex &child) const;
virtual int rowCount(const QModelIndex &parent) const;
private:
CanIdMap _map;
AggregatedTraceViewItem *_rootItem;
QList<CanMessage> _pendingMessageUpdates;
QMap<unique_key_t, CanMessage> _pendingMessageInserts;
unique_key_t makeUniqueKey(const CanMessage &msg) const;
void createItem(const CanMessage &msg, AggregatedTraceViewItem *item, unique_key_t key);
double getTimeDiff(const timeval t1, const timeval t2) const;
protected:
virtual QVariant data_DisplayRole(const QModelIndex &index, int role) const;
virtual QVariant data_TextColorRole(const QModelIndex &index, int role) const;
private slots:
void createItem(const CanMessage &msg);
void updateItem(const CanMessage &msg);
void onUpdateModel();
void onSetupChanged();
void beforeAppend(int num_messages);
void beforeClear();
void afterClear();
};

View File

@@ -0,0 +1,271 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BaseTraceViewModel.h"
#include <QDateTime>
#include <QColor>
#include <core/Backend.h>
#include <core/CanTrace.h>
#include <core/CanMessage.h>
#include <core/CanDbMessage.h>
BaseTraceViewModel::BaseTraceViewModel(Backend &backend)
{
_backend = &backend;
}
int BaseTraceViewModel::columnCount(const QModelIndex &parent) const
{
(void) parent;
return column_count;
}
QVariant BaseTraceViewModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
switch (section) {
case column_timestamp:
return QString("Timestamp");
case column_channel:
return QString("Channel");
case column_direction:
return QString("Rx/Tx");
case column_canid:
return QString("CAN ID");
case column_sender:
return QString("Sender");
case column_name:
return QString("Name");
case column_dlc:
return QString("DLC");
case column_data:
return QString("Data");
case column_comment:
return QString("Comment");
}
}
}
return QVariant();
}
QVariant BaseTraceViewModel::data(const QModelIndex &index, int role) const
{
switch (role) {
case Qt::DisplayRole:
return data_DisplayRole(index, role);
case Qt::TextAlignmentRole:
return data_TextAlignmentRole(index, role);
case Qt::TextColorRole:
return data_TextColorRole(index, role);
default:
return QVariant();
}
}
Backend *BaseTraceViewModel::backend() const
{
return _backend;
}
CanTrace *BaseTraceViewModel::trace() const
{
return _backend->getTrace();
}
timestamp_mode_t BaseTraceViewModel::timestampMode() const
{
return _timestampMode;
}
void BaseTraceViewModel::setTimestampMode(timestamp_mode_t timestampMode)
{
_timestampMode = timestampMode;
}
QVariant BaseTraceViewModel::formatTimestamp(timestamp_mode_t mode, const CanMessage &currentMsg, const CanMessage &lastMsg) const
{
if (mode==timestamp_mode_delta) {
double t_current = currentMsg.getFloatTimestamp();
double t_last = lastMsg.getFloatTimestamp();
if (t_last==0) {
return QVariant();
} else {
return QString().sprintf("%.04lf", t_current-t_last);
}
} else if (mode==timestamp_mode_absolute) {
return currentMsg.getDateTime().toString("hh:mm:ss.zzz");
} else if (mode==timestamp_mode_relative) {
double t_current = currentMsg.getFloatTimestamp();
return QString().sprintf("%.04lf", t_current - backend()->getTimestampAtMeasurementStart());
}
return QVariant();
}
QVariant BaseTraceViewModel::data_DisplayRole(const QModelIndex &index, int role) const
{
(void) index;
(void) role;
return QVariant();
}
QVariant BaseTraceViewModel::data_DisplayRole_Message(const QModelIndex &index, int role, const CanMessage &currentMsg, const CanMessage &lastMsg) const
{
(void) role;
CanDbMessage *dbmsg = backend()->findDbMessage(currentMsg);
switch (index.column()) {
case column_timestamp:
return formatTimestamp(_timestampMode, currentMsg, lastMsg);
case column_channel:
return backend()->getInterfaceName(currentMsg.getInterfaceId());
case column_direction:
return "rx";
case column_canid:
return currentMsg.getIdString();
case column_name:
return (dbmsg) ? dbmsg->getName() : "";
case column_sender:
return (dbmsg) ? dbmsg->getSender()->name() : "";
case column_dlc:
return currentMsg.getLength();
case column_data:
return currentMsg.getDataHexString();
case column_comment:
return (dbmsg) ? dbmsg->getComment() : "";
default:
return QVariant();
}
}
QVariant BaseTraceViewModel::data_DisplayRole_Signal(const QModelIndex &index, int role, const CanMessage &msg) const
{
(void) role;
uint64_t raw_data;
QString value_name;
QString unit;
CanDbMessage *dbmsg = backend()->findDbMessage(msg);
if (!dbmsg) { return QVariant(); }
CanDbSignal *dbsignal = dbmsg->getSignal(index.row());
if (!dbsignal) { return QVariant(); }
switch (index.column()) {
case column_name:
return dbsignal->name();
case column_data:
if (dbsignal->isPresentInMessage(msg)) {
raw_data = dbsignal->extractRawDataFromMessage(msg);
} else {
if (!trace()->getMuxedSignalFromCache(dbsignal, &raw_data)) {
return QVariant();
}
}
value_name = dbsignal->getValueName(raw_data);
if (value_name.isEmpty()) {
unit = dbsignal->getUnit();
if (unit.isEmpty()) {
return dbsignal->convertRawValueToPhysical(raw_data);
} else {
return QString("%1 %2").arg(dbsignal->convertRawValueToPhysical(raw_data)).arg(unit);
}
} else {
return QString("%1 - %2").arg(raw_data).arg(value_name);
}
case column_comment:
return dbsignal->comment().replace('\n', ' ');
default:
return QVariant();
}
}
QVariant BaseTraceViewModel::data_TextAlignmentRole(const QModelIndex &index, int role) const
{
(void) role;
switch (index.column()) {
case column_timestamp: return Qt::AlignRight + Qt::AlignVCenter;
case column_channel: return Qt::AlignCenter + Qt::AlignVCenter;
case column_direction: return Qt::AlignCenter + Qt::AlignVCenter;
case column_canid: return Qt::AlignRight + Qt::AlignVCenter;
case column_sender: return Qt::AlignLeft + Qt::AlignVCenter;
case column_name: return Qt::AlignLeft + Qt::AlignVCenter;
case column_dlc: return Qt::AlignCenter + Qt::AlignVCenter;
case column_data: return Qt::AlignLeft + Qt::AlignVCenter;
case column_comment: return Qt::AlignLeft + Qt::AlignVCenter;
default: return QVariant();
}
}
QVariant BaseTraceViewModel::data_TextColorRole(const QModelIndex &index, int role) const
{
(void) index;
(void) role;
return QVariant();
}
QVariant BaseTraceViewModel::data_TextColorRole_Signal(const QModelIndex &index, int role, const CanMessage &msg) const
{
(void) role;
CanDbMessage *dbmsg = backend()->findDbMessage(msg);
if (!dbmsg) { return QVariant(); }
CanDbSignal *dbsignal = dbmsg->getSignal(index.row());
if (!dbsignal) { return QVariant(); }
if (dbsignal->isPresentInMessage(msg)) {
return QVariant(); // default text color
} else {
return QVariant::fromValue(QColor(200,200,200));
}
}

View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QAbstractItemModel>
#include "TraceViewTypes.h"
class Backend;
class CanTrace;
class CanMessage;
class CanDbSignal;
class BaseTraceViewModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum {
column_timestamp,
column_channel,
column_direction,
column_canid,
column_sender,
column_name,
column_dlc,
column_data,
column_comment,
column_count
};
public:
BaseTraceViewModel(Backend &backend);
virtual int columnCount(const QModelIndex &parent) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual QVariant data(const QModelIndex &index, int role) const;
Backend *backend() const;
CanTrace *trace() const;
timestamp_mode_t timestampMode() const;
void setTimestampMode(timestamp_mode_t timestampMode);
protected:
virtual QVariant data_DisplayRole(const QModelIndex &index, int role) const;
virtual QVariant data_DisplayRole_Message(const QModelIndex &index, int role, const CanMessage &currentMsg, const CanMessage &lastMsg) const;
virtual QVariant data_DisplayRole_Signal(const QModelIndex &index, int role, const CanMessage &msg) const;
virtual QVariant data_TextAlignmentRole(const QModelIndex &index, int role) const;
virtual QVariant data_TextColorRole(const QModelIndex &index, int role) const;
virtual QVariant data_TextColorRole_Signal(const QModelIndex &index, int role, const CanMessage &msg) const;
QVariant formatTimestamp(timestamp_mode_t mode, const CanMessage &currentMsg, const CanMessage &lastMsg) const;
private:
Backend *_backend;
timestamp_mode_t _timestampMode;
};

View File

@@ -0,0 +1,143 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LinearTraceViewModel.h"
#include <iostream>
#include <stddef.h>
#include <core/Backend.h>
LinearTraceViewModel::LinearTraceViewModel(Backend &backend)
: BaseTraceViewModel(backend)
{
connect(backend.getTrace(), SIGNAL(beforeAppend(int)), this, SLOT(beforeAppend(int)));
connect(backend.getTrace(), SIGNAL(afterAppend()), this, SLOT(afterAppend()));
connect(backend.getTrace(), SIGNAL(beforeClear()), this, SLOT(beforeClear()));
connect(backend.getTrace(), SIGNAL(afterClear()), this, SLOT(afterClear()));
}
QModelIndex LinearTraceViewModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid() && parent.internalId()) {
return createIndex(row, column, (unsigned int)(0x80000000 | parent.internalId()));
} else {
return createIndex(row, column, row+1);
}
}
QModelIndex LinearTraceViewModel::parent(const QModelIndex &child) const
{
(void) child;
quintptr id = child.internalId();
if (id & 0x80000000) {
return createIndex(id & 0x7FFFFFFF, 0, (unsigned int)(id & 0x7FFFFFFF));
}
return QModelIndex();
}
int LinearTraceViewModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
quintptr id = parent.internalId();
if (id & 0x80000000) { // node of a message
return 0;
} else { // a message
const CanMessage *msg = trace()->getMessage(id-1);
if (msg) {
CanDbMessage *dbmsg = backend()->findDbMessage(*msg);
return (dbmsg!=0) ? dbmsg->getSignals().length() : 0;
} else {
return 0;
}
}
} else {
return trace()->size();
}
}
int LinearTraceViewModel::columnCount(const QModelIndex &parent) const
{
(void) parent;
return column_count;
}
bool LinearTraceViewModel::hasChildren(const QModelIndex &parent) const
{
return rowCount(parent)>0;
}
void LinearTraceViewModel::beforeAppend(int num_messages)
{
beginInsertRows(QModelIndex(), trace()->size(), trace()->size()+num_messages-1);
}
void LinearTraceViewModel::afterAppend()
{
endInsertRows();
}
void LinearTraceViewModel::beforeClear()
{
beginResetModel();
}
void LinearTraceViewModel::afterClear()
{
endResetModel();
}
QVariant LinearTraceViewModel::data_DisplayRole(const QModelIndex &index, int role) const
{
quintptr id = index.internalId();
int msg_id = (id & ~0x80000000)-1;
const CanMessage *msg = trace()->getMessage(msg_id);
if (!msg) { return QVariant(); }
if (id & 0x80000000) {
return data_DisplayRole_Signal(index, role, *msg);
} else if (id) {
if (msg_id>1) {
const CanMessage *prev_msg = trace()->getMessage(msg_id-1);
return data_DisplayRole_Message(index, role, *msg, *prev_msg);
} else {
return data_DisplayRole_Message(index, role, *msg, CanMessage());
}
}
return QVariant();
}
QVariant LinearTraceViewModel::data_TextColorRole(const QModelIndex &index, int role) const
{
(void) role;
quintptr id = index.internalId();
if (id & 0x80000000) { // CanSignal row
int msg_id = (id & ~0x80000000)-1;
const CanMessage *msg = trace()->getMessage(msg_id);
if (msg) {
return data_TextColorRole_Signal(index, role, *msg);
}
}
return QVariant();
}

View File

@@ -0,0 +1,53 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QAbstractItemModel>
#include <core/CanDb.h>
#include <core/CanTrace.h>
#include "BaseTraceViewModel.h"
class Backend;
class LinearTraceViewModel : public BaseTraceViewModel
{
Q_OBJECT
public:
LinearTraceViewModel(Backend &backend);
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const;
virtual QModelIndex parent(const QModelIndex &child) const;
virtual int rowCount(const QModelIndex &parent) const;
virtual int columnCount(const QModelIndex &parent) const;
virtual bool hasChildren(const QModelIndex &parent) const;
private slots:
void beforeAppend(int num_messages);
void afterAppend();
void beforeClear();
void afterClear();
private:
virtual QVariant data_DisplayRole(const QModelIndex &index, int role) const;
virtual QVariant data_TextColorRole(const QModelIndex &index, int role) const;
};

View File

@@ -0,0 +1,41 @@
#include "TraceFilterModel.h"
TraceFilterModel::TraceFilterModel(QObject *parent)
: QSortFilterProxyModel{parent},
_filterText("")
{
setRecursiveFilteringEnabled(false);
}
void TraceFilterModel::setFilterText(QString filtertext)
{
_filterText = filtertext;
}
bool TraceFilterModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
{
// Pass all on no filter
if(_filterText.length() == 0)
return true;
QModelIndex idx0 = sourceModel()->index(source_row, 1, source_parent); // Channel
QModelIndex idx1 = sourceModel()->index(source_row, 3, source_parent); // CAN ID
QModelIndex idx2 = sourceModel()->index(source_row, 4, source_parent); // Sender
QModelIndex idx3 = sourceModel()->index(source_row, 5, source_parent); // Name
QString datastr0 = sourceModel()->data(idx0).toString();
QString datastr1 = sourceModel()->data(idx1).toString();
QString datastr2 = sourceModel()->data(idx2).toString();
QString datastr3 = sourceModel()->data(idx3).toString();
fprintf(stderr, "Data for acceptance is %s\r\n", datastr1.toStdString().c_str());
if( datastr0.contains(_filterText) ||
datastr1.contains(_filterText) ||
datastr2.contains(_filterText) ||
datastr3.contains(_filterText))
return true;
else
return false;
}

View File

@@ -0,0 +1,21 @@
#ifndef TRACEFILTER_H
#define TRACEFILTER_H
#include <QSortFilterProxyModel>
class TraceFilterModel : public QSortFilterProxyModel
{
public:
explicit TraceFilterModel(QObject *parent = nullptr);
public slots:
void setFilterText(QString filtertext);
private:
QString _filterText;
protected:
virtual bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override;
};
#endif // TRACEFILTER_H

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
typedef enum timestamp_mode {
timestamp_mode_absolute,
timestamp_mode_relative,
timestamp_mode_delta,
timestamp_modes_count
} timestamp_mode_t;

View File

@@ -0,0 +1,217 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TraceWindow.h"
#include "ui_TraceWindow.h"
#include <QDomDocument>
#include <QSortFilterProxyModel>
#include "LinearTraceViewModel.h"
#include "AggregatedTraceViewModel.h"
#include "TraceFilterModel.h"
TraceWindow::TraceWindow(QWidget *parent, Backend &backend) :
ConfigurableWidget(parent),
ui(new Ui::TraceWindow),
_backend(&backend)
{
ui->setupUi(this);
_linearTraceViewModel = new LinearTraceViewModel(backend);
_linearProxyModel = new QSortFilterProxyModel(this);
_linearProxyModel->setSourceModel(_linearTraceViewModel);
_linearProxyModel->setDynamicSortFilter(true);
_aggregatedTraceViewModel = new AggregatedTraceViewModel(backend);
_aggregatedProxyModel = new QSortFilterProxyModel(this);
_aggregatedProxyModel->setSourceModel(_aggregatedTraceViewModel);
_aggregatedProxyModel->setDynamicSortFilter(true);
_aggFilteredModel = new TraceFilterModel(this);
_aggFilteredModel->setSourceModel(_aggregatedProxyModel);
_linFilteredModel = new TraceFilterModel(this);
_linFilteredModel->setSourceModel(_linearProxyModel);
setMode(mode_aggregated);
setAutoScroll(false);
QFont font("Monospace");
font.setStyleHint(QFont::TypeWriter);
ui->tree->setFont(font);
ui->tree->setAlternatingRowColors(true);
ui->tree->setUniformRowHeights(true);
ui->tree->setColumnWidth(0, 120);
ui->tree->setColumnWidth(1, 70);
ui->tree->setColumnWidth(2, 50);
ui->tree->setColumnWidth(3, 90);
ui->tree->setColumnWidth(4, 200);
ui->tree->setColumnWidth(5, 200);
ui->tree->setColumnWidth(6, 50);
ui->tree->setColumnWidth(7, 200);
ui->tree->sortByColumn(BaseTraceViewModel::column_canid, Qt::AscendingOrder);
ui->cbTimestampMode->addItem("absolute", 0);
ui->cbTimestampMode->addItem("relative", 1);
ui->cbTimestampMode->addItem("delta", 2);
setTimestampMode(timestamp_mode_delta);
connect(_linearTraceViewModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted(QModelIndex,int,int)));
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(on_cbFilterChanged()));
}
TraceWindow::~TraceWindow()
{
delete ui;
delete _aggregatedTraceViewModel;
delete _linearTraceViewModel;
}
void TraceWindow::setMode(TraceWindow::mode_t mode)
{
bool isChanged = (_mode != mode);
_mode = mode;
if (_mode==mode_linear) {
ui->tree->setSortingEnabled(false);
ui->tree->setModel(_linFilteredModel); //_linearTraceViewModel);
ui->cbAutoScroll->setEnabled(true);
} else {
ui->tree->setSortingEnabled(true);
ui->tree->setModel(_aggFilteredModel); //_aggregatedProxyModel);
ui->cbAutoScroll->setEnabled(false);
}
if (isChanged) {
ui->cbAggregated->setChecked(_mode==mode_aggregated);
emit(settingsChanged(this));
}
}
void TraceWindow::setAutoScroll(bool doAutoScroll)
{
if (doAutoScroll != _doAutoScroll) {
_doAutoScroll = doAutoScroll;
ui->cbAutoScroll->setChecked(_doAutoScroll);
emit(settingsChanged(this));
}
}
void TraceWindow::setTimestampMode(int mode)
{
timestamp_mode_t new_mode;
if ( (mode>=0) && (mode<timestamp_modes_count) ) {
new_mode = (timestamp_mode_t) mode;
} else {
new_mode = timestamp_mode_absolute;
}
_aggregatedTraceViewModel->setTimestampMode(new_mode);
_linearTraceViewModel->setTimestampMode(new_mode);
if (new_mode != _timestampMode) {
_timestampMode = new_mode;
for (int i=0; i<ui->cbTimestampMode->count(); i++) {
if (ui->cbTimestampMode->itemData(i).toInt() == new_mode) {
ui->cbTimestampMode->setCurrentIndex(i);
}
}
emit(settingsChanged(this));
}
}
bool TraceWindow::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
if (!ConfigurableWidget::saveXML(backend, xml, root)) {
return false;
}
root.setAttribute("type", "TraceWindow");
root.setAttribute("mode", (_mode==mode_linear) ? "linear" : "aggregated");
root.setAttribute("TimestampMode", _timestampMode);
QDomElement elLinear = xml.createElement("LinearTraceView");
elLinear.setAttribute("AutoScroll", (ui->cbAutoScroll->checkState() == Qt::Checked) ? 1 : 0);
root.appendChild(elLinear);
QDomElement elAggregated = xml.createElement("AggregatedTraceView");
elAggregated.setAttribute("SortColumn", _aggregatedProxyModel->sortColumn());
root.appendChild(elAggregated);
return true;
}
bool TraceWindow::loadXML(Backend &backend, QDomElement &el)
{
if (!ConfigurableWidget::loadXML(backend, el)) {
return false;
}
setMode((el.attribute("mode", "linear") == "linear") ? mode_linear : mode_aggregated);
setTimestampMode(el.attribute("TimestampMode", "0").toInt());
QDomElement elLinear = el.firstChildElement("LinearTraceView");
setAutoScroll(elLinear.attribute("AutoScroll", "0").toInt() != 0);
QDomElement elAggregated = el.firstChildElement("AggregatedTraceView");
int sortColumn = elAggregated.attribute("SortColumn", "-1").toInt();
ui->tree->sortByColumn(sortColumn);
return true;
}
void TraceWindow::rowsInserted(const QModelIndex &parent, int first, int last)
{
(void) parent;
(void) first;
(void) last;
if ((_mode==mode_linear) && (ui->cbAutoScroll->checkState() == Qt::Checked)) {
ui->tree->scrollToBottom();
}
}
void TraceWindow::on_cbAggregated_stateChanged(int i)
{
setMode( (i==Qt::Checked) ? mode_aggregated : mode_linear );
}
void TraceWindow::on_cbAutoScroll_stateChanged(int i)
{
setAutoScroll(i==Qt::Checked);
}
void TraceWindow::on_cbTimestampMode_currentIndexChanged(int index)
{
setTimestampMode((timestamp_mode_t)ui->cbTimestampMode->itemData(index).toInt());
}
void TraceWindow::on_cbFilterChanged()
{
_aggFilteredModel->setFilterText(ui->filterLineEdit->text());
_linFilteredModel->setFilterText(ui->filterLineEdit->text());
_aggFilteredModel->invalidate();
_linFilteredModel->invalidate();
}

View File

@@ -0,0 +1,82 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <core/ConfigurableWidget.h>
#include "TraceViewTypes.h"
#include "TraceFilterModel.h"
namespace Ui {
class TraceWindow;
}
class QDomDocument;
class QDomElement;
class QSortFilterProxyModel;
class LinearTraceViewModel;
class AggregatedTraceViewModel;
class Backend;
class TraceWindow : public ConfigurableWidget
{
Q_OBJECT
public:
typedef enum mode {
mode_linear,
mode_aggregated
} mode_t;
explicit TraceWindow(QWidget *parent, Backend &backend);
~TraceWindow();
void setMode(mode_t mode);
void setAutoScroll(bool doAutoScroll);
void setTimestampMode(int mode);
virtual bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
virtual bool loadXML(Backend &backend, QDomElement &el);
public slots:
void rowsInserted(const QModelIndex & parent, int first, int last);
private slots:
void on_cbAggregated_stateChanged(int i);
void on_cbAutoScroll_stateChanged(int i);
void on_cbTimestampMode_currentIndexChanged(int index);
void on_cbFilterChanged(void);
private:
Ui::TraceWindow *ui;
Backend *_backend;
mode_t _mode;
bool _doAutoScroll;
timestamp_mode_t _timestampMode;
TraceFilterModel * _aggFilteredModel;
TraceFilterModel * _linFilteredModel;
LinearTraceViewModel *_linearTraceViewModel;
AggregatedTraceViewModel *_aggregatedTraceViewModel;
QSortFilterProxyModel *_aggregatedProxyModel;
QSortFilterProxyModel *_linearProxyModel;
};

View File

@@ -0,0 +1,19 @@
SOURCES += \
$$PWD/TraceFilterModel.cpp \
$$PWD/LinearTraceViewModel.cpp \
$$PWD/AggregatedTraceViewModel.cpp \
$$PWD/BaseTraceViewModel.cpp \
$$PWD/AggregatedTraceViewItem.cpp \
$$PWD/TraceWindow.cpp \
HEADERS += \
$$PWD/LinearTraceViewModel.h \
$$PWD/AggregatedTraceViewModel.h \
$$PWD/BaseTraceViewModel.h \
$$PWD/AggregatedTraceViewItem.h \
$$PWD/TraceFilterModel.h \
$$PWD/TraceWindow.h \
$$PWD/TraceViewTypes.h \
FORMS += \
$$PWD/TraceWindow.ui

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TraceWindow</class>
<widget class="QWidget" name="TraceWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>918</width>
<height>616</height>
</rect>
</property>
<property name="windowTitle">
<string>Trace View</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Timestamps:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbTimestampMode"/>
</item>
<item>
<widget class="QCheckBox" name="cbAggregated">
<property name="text">
<string>aggregate by ID</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbAutoScroll">
<property name="text">
<string>auto scroll</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Filter: </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="filterLineEdit"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTreeView" name="tree">
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>