First implementation
This commit is contained in:
71
cpp/window/TraceWindow/AggregatedTraceViewItem.cpp
Normal file
71
cpp/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
cpp/window/TraceWindow/AggregatedTraceViewItem.h
Normal file
48
cpp/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
cpp/window/TraceWindow/AggregatedTraceViewModel.cpp
Normal file
220
cpp/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
cpp/window/TraceWindow/AggregatedTraceViewModel.h
Normal file
76
cpp/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
cpp/window/TraceWindow/BaseTraceViewModel.cpp
Normal file
271
cpp/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
cpp/window/TraceWindow/BaseTraceViewModel.h
Normal file
76
cpp/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
cpp/window/TraceWindow/LinearTraceViewModel.cpp
Normal file
143
cpp/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
cpp/window/TraceWindow/LinearTraceViewModel.h
Normal file
53
cpp/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
cpp/window/TraceWindow/TraceFilterModel.cpp
Normal file
41
cpp/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
cpp/window/TraceWindow/TraceFilterModel.h
Normal file
21
cpp/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
cpp/window/TraceWindow/TraceViewTypes.h
Normal file
30
cpp/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
cpp/window/TraceWindow/TraceWindow.cpp
Normal file
217
cpp/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
cpp/window/TraceWindow/TraceWindow.h
Normal file
82
cpp/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
cpp/window/TraceWindow/TraceWindow.pri
Normal file
19
cpp/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
cpp/window/TraceWindow/TraceWindow.ui
Normal file
96
cpp/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