First implementation
This commit is contained in:
109
window/CanStatusWindow/CanStatusWindow.cpp
Normal file
109
window/CanStatusWindow/CanStatusWindow.cpp
Normal 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;
|
||||
}
|
||||
70
window/CanStatusWindow/CanStatusWindow.h
Normal file
70
window/CanStatusWindow/CanStatusWindow.h
Normal 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;
|
||||
};
|
||||
8
window/CanStatusWindow/CanStatusWindow.pri
Normal file
8
window/CanStatusWindow/CanStatusWindow.pri
Normal file
@@ -0,0 +1,8 @@
|
||||
SOURCES += \
|
||||
$$PWD/CanStatusWindow.cpp \
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/CanStatusWindow.h \
|
||||
|
||||
FORMS += \
|
||||
$$PWD/CanStatusWindow.ui \
|
||||
114
window/CanStatusWindow/CanStatusWindow.ui
Normal file
114
window/CanStatusWindow/CanStatusWindow.ui
Normal 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>
|
||||
136
window/GraphWindow/GraphWindow.cpp
Normal file
136
window/GraphWindow/GraphWindow.cpp
Normal 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;
|
||||
}
|
||||
58
window/GraphWindow/GraphWindow.h
Normal file
58
window/GraphWindow/GraphWindow.h
Normal 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;
|
||||
};
|
||||
8
window/GraphWindow/GraphWindow.pri
Normal file
8
window/GraphWindow/GraphWindow.pri
Normal file
@@ -0,0 +1,8 @@
|
||||
SOURCES += \
|
||||
$$PWD/GraphWindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/GraphWindow.h
|
||||
|
||||
FORMS += \
|
||||
$$PWD/GraphWindow.ui
|
||||
77
window/GraphWindow/GraphWindow.ui
Normal file
77
window/GraphWindow/GraphWindow.ui
Normal 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>
|
||||
62
window/LogWindow/LogWindow.cpp
Normal file
62
window/LogWindow/LogWindow.cpp
Normal 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();
|
||||
}
|
||||
51
window/LogWindow/LogWindow.h
Normal file
51
window/LogWindow/LogWindow.h
Normal 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;
|
||||
};
|
||||
10
window/LogWindow/LogWindow.pri
Normal file
10
window/LogWindow/LogWindow.pri
Normal file
@@ -0,0 +1,10 @@
|
||||
SOURCES += \
|
||||
$$PWD/LogWindow.cpp \
|
||||
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/LogWindow.h \
|
||||
|
||||
|
||||
FORMS += \
|
||||
$$PWD/LogWindow.ui \
|
||||
36
window/LogWindow/LogWindow.ui
Normal file
36
window/LogWindow/LogWindow.ui
Normal 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>
|
||||
735
window/RawTxWindow/RawTxWindow.cpp
Normal file
735
window/RawTxWindow/RawTxWindow.cpp
Normal 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();
|
||||
}
|
||||
|
||||
63
window/RawTxWindow/RawTxWindow.h
Normal file
63
window/RawTxWindow/RawTxWindow.h
Normal 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();
|
||||
|
||||
};
|
||||
8
window/RawTxWindow/RawTxWindow.pri
Normal file
8
window/RawTxWindow/RawTxWindow.pri
Normal file
@@ -0,0 +1,8 @@
|
||||
SOURCES += \
|
||||
$$PWD/RawTxWindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/RawTxWindow.h
|
||||
|
||||
FORMS += \
|
||||
$$PWD/RawTxWindow.ui
|
||||
1895
window/RawTxWindow/RawTxWindow.ui
Normal file
1895
window/RawTxWindow/RawTxWindow.ui
Normal file
File diff suppressed because it is too large
Load Diff
69
window/SetupDialog/SelectCanInterfacesDialog.cpp
Normal file
69
window/SetupDialog/SelectCanInterfacesDialog.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
47
window/SetupDialog/SelectCanInterfacesDialog.h
Normal file
47
window/SetupDialog/SelectCanInterfacesDialog.h
Normal 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;
|
||||
};
|
||||
154
window/SetupDialog/SelectCanInterfacesDialog.ui
Normal file
154
window/SetupDialog/SelectCanInterfacesDialog.ui
Normal 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>&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>
|
||||
340
window/SetupDialog/SetupDialog.cpp
Normal file
340
window/SetupDialog/SetupDialog.cpp
Normal 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());
|
||||
}
|
||||
|
||||
101
window/SetupDialog/SetupDialog.h
Normal file
101
window/SetupDialog/SetupDialog.h
Normal 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);
|
||||
|
||||
};
|
||||
15
window/SetupDialog/SetupDialog.pri
Normal file
15
window/SetupDialog/SetupDialog.pri
Normal 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
|
||||
315
window/SetupDialog/SetupDialog.ui
Normal file
315
window/SetupDialog/SetupDialog.ui
Normal 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 &Interface...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btRemoveInterface">
|
||||
<property name="text">
|
||||
<string>&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 &Database...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btRemoveDatabase">
|
||||
<property name="text">
|
||||
<string>&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>
|
||||
117
window/SetupDialog/SetupDialogTreeItem.cpp
Normal file
117
window/SetupDialog/SetupDialogTreeItem.cpp
Normal 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;
|
||||
}
|
||||
|
||||
74
window/SetupDialog/SetupDialogTreeItem.h
Normal file
74
window/SetupDialog/SetupDialogTreeItem.h
Normal 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;
|
||||
};
|
||||
263
window/SetupDialog/SetupDialogTreeModel.cpp
Normal file
263
window/SetupDialog/SetupDialogTreeModel.cpp
Normal 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();
|
||||
}
|
||||
|
||||
77
window/SetupDialog/SetupDialogTreeModel.h
Normal file
77
window/SetupDialog/SetupDialogTreeModel.h
Normal 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);
|
||||
};
|
||||
71
window/TraceWindow/AggregatedTraceViewItem.cpp
Normal file
71
window/TraceWindow/AggregatedTraceViewItem.cpp
Normal 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();
|
||||
}
|
||||
48
window/TraceWindow/AggregatedTraceViewItem.h
Normal file
48
window/TraceWindow/AggregatedTraceViewItem.h
Normal 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;
|
||||
|
||||
};
|
||||
220
window/TraceWindow/AggregatedTraceViewModel.cpp
Normal file
220
window/TraceWindow/AggregatedTraceViewModel.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
76
window/TraceWindow/AggregatedTraceViewModel.h
Normal file
76
window/TraceWindow/AggregatedTraceViewModel.h
Normal 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();
|
||||
};
|
||||
271
window/TraceWindow/BaseTraceViewModel.cpp
Normal file
271
window/TraceWindow/BaseTraceViewModel.cpp
Normal 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 ¤tMsg, 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 ¤tMsg, 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));
|
||||
}
|
||||
}
|
||||
76
window/TraceWindow/BaseTraceViewModel.h
Normal file
76
window/TraceWindow/BaseTraceViewModel.h
Normal 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 ¤tMsg, 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 ¤tMsg, const CanMessage &lastMsg) const;
|
||||
|
||||
private:
|
||||
Backend *_backend;
|
||||
timestamp_mode_t _timestampMode;
|
||||
|
||||
};
|
||||
143
window/TraceWindow/LinearTraceViewModel.cpp
Normal file
143
window/TraceWindow/LinearTraceViewModel.cpp
Normal 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();
|
||||
}
|
||||
53
window/TraceWindow/LinearTraceViewModel.h
Normal file
53
window/TraceWindow/LinearTraceViewModel.h
Normal 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;
|
||||
};
|
||||
41
window/TraceWindow/TraceFilterModel.cpp
Normal file
41
window/TraceWindow/TraceFilterModel.cpp
Normal 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;
|
||||
}
|
||||
21
window/TraceWindow/TraceFilterModel.h
Normal file
21
window/TraceWindow/TraceFilterModel.h
Normal 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
|
||||
30
window/TraceWindow/TraceViewTypes.h
Normal file
30
window/TraceWindow/TraceViewTypes.h
Normal 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;
|
||||
|
||||
217
window/TraceWindow/TraceWindow.cpp
Normal file
217
window/TraceWindow/TraceWindow.cpp
Normal 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();
|
||||
}
|
||||
82
window/TraceWindow/TraceWindow.h
Normal file
82
window/TraceWindow/TraceWindow.h
Normal 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;
|
||||
};
|
||||
19
window/TraceWindow/TraceWindow.pri
Normal file
19
window/TraceWindow/TraceWindow.pri
Normal 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
|
||||
96
window/TraceWindow/TraceWindow.ui
Normal file
96
window/TraceWindow/TraceWindow.ui
Normal 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>
|
||||
Reference in New Issue
Block a user