Files
giesCANne/re/sniffer/sniffermodel.cpp
T
Collin Kidder 0baffa300f A partial commit that changes CANFrame over to be based on
QCanBusFrame so that things are more compatible with other Qt based
CAN bus code. Not complete yet but getting there.
2019-12-11 21:17:33 -05:00

337 lines
8.2 KiB
C++

#include <QDebug>
#include <Qt>
#include <QApplication>
#include "sniffermodel.h"
#include "snifferwindow.h"
#include "SnifferDelegate.h"
SnifferModel::SnifferModel(QObject *parent)
: QAbstractItemModel(parent),
mFilter(false),
mNeverExpire(false),
mFadeInactive(false),
mMuteNotched(false),
mTimeSequence(0)
{
QColor TextColor = QApplication::palette().color(QPalette::Text);
if (TextColor.red() + TextColor.green() + TextColor.blue() < 200)
{
mDarkMode = false;
}
else mDarkMode = true;
}
SnifferModel::~SnifferModel()
{
qDeleteAll(mMap);
mMap.clear();
mFilters.clear();
}
int SnifferModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : tc::LAST+1;
}
int SnifferModel::rowCount(const QModelIndex &parent) const
{
const QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
return parent.isValid() ? 0 : map.size();
}
QVariant SnifferModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
SnifferItem *item = static_cast<SnifferItem*>(index.internalPointer());
if(!item) QVariant();
int col = index.column();
switch(role)
{
case Qt::DisplayRole:
{
switch(col)
{
case tc::DELTA:
return QString::number(item->getDelta(), 'f');
case tc::ID:
return QString("%1").arg(item->getId(), 5, 16, QLatin1Char(' ')).toUpper();
default:
break;
}
if(tc::DATA_0<=col && col <=tc::DATA_7)
{
int data = item->getData(col-tc::DATA_0);
if(data >= 0)
{
return QString("%1").arg(data, 2, 16, QLatin1Char('0')).toUpper();
}
}
break;
}
case Qt::ForegroundRole:
{
if (!mFadeInactive || col < 2) return QApplication::palette().brush(QPalette::Text);
int v = item->getSeqInterval(col - 2) * 10;
//qDebug() << "mTS: " << mTimeSequence << " gDT(" << (col - 2) << ") " << item->getDataTimestamp(col - 2);
if (v > 225) v = 225;
if (v < 0) v = 0;
if (!mDarkMode) //text defaults to being dark
{
return QBrush(QColor(v,v,v,255));
}
else //text defaults to being light
{
return QBrush(QColor(255-v,255-v,255-v,255));
}
}
case Qt::BackgroundRole:
{
if(tc::ID==col)
{
if(item->elapsed() > 4000)
{
if (!mDarkMode) return QBrush(Qt::red);
return QBrush(QColor(128,0,0));
}
}
else if(tc::DATA_0<=col && col<=tc::DATA_7)
{
dc change = item->dataChange(col-tc::DATA_0);
switch(change)
{
case dc::INC:
if (!mDarkMode) return QBrush(Qt::green);
return QBrush(QColor(0,128,0));
case dc::DEINC:
if (!mDarkMode) return QBrush(Qt::red);
return QBrush(QColor(128,0,0));
default:
return QApplication::palette().brush(QPalette::Base);
}
}
break;
}
}
return QVariant();
}
Qt::ItemFlags SnifferModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return QAbstractItemModel::flags(index);
}
QVariant SnifferModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
switch(section)
{
case tc::DELTA:
return QString("Delta");
case tc::ID:
return QString("ID");
default:
break;
}
if(tc::DATA_0<=section && section <=tc::DATA_7)
return QString::number(section-tc::DATA_0);
}
return QVariant();
}
QModelIndex SnifferModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid())
return QModelIndex();
const QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
if(column>tc::LAST || row>=map.size())
return QModelIndex();
/* ugly but I can't find best without creating a list to keep indexes */
QMap<quint32, SnifferItem*>::const_iterator iter;
int i;
for(iter = map.begin(), i=0 ; i<row ; ++i, ++iter);
return createIndex(row, column, iter.value());
}
QModelIndex SnifferModel::parent(const QModelIndex &) const
{
return QModelIndex();
}
bool SnifferModel::getNeverExpire()
{
return mNeverExpire;
}
bool SnifferModel::getFadeInactive()
{
return mFadeInactive;
}
bool SnifferModel::getMuteNotched()
{
return mMuteNotched;
}
void SnifferModel::setNeverExpire(bool val)
{
mNeverExpire = val;
}
void SnifferModel::setFadeInactive(bool val)
{
mFadeInactive = val;
}
void SnifferModel::setMuteNotched(bool val)
{
mMuteNotched = val;
}
void SnifferModel::clear()
{
beginResetModel();
qDeleteAll(mMap);
mMap.clear();
mFilters.clear();
mFilter = false;
endResetModel();
}
//Called from window with a timer (currently 200ms)
void SnifferModel::refresh()
{
QMap<quint32, SnifferItem*>::iterator i;
QVector<quint32> toRemove;
SnifferItem* item;
mTimeSequence++;
/* update markers */
for (i = mMap.begin(); i != mMap.end(); ++i)
{
i.value()->updateMarker();
if(i.value()->elapsed()>5000 && !mNeverExpire)
toRemove.append(i.key());
}
if(toRemove.size())
{
beginResetModel();
foreach(quint32 id, toRemove)
{
/* remove element */
item = mMap.take(id);
mFilters.remove(id);
delete item;
/* send notification */
emit idChange(id, false);
}
endResetModel();
}
else
/* refresh data */
dataChanged(createIndex(0, 0),
createIndex(rowCount()-1, columnCount()-1), QVector<int>(Qt::DisplayRole));
}
void SnifferModel::filter(fltType pType, int pId)
{
beginResetModel();
switch(pType)
{
case fltType::NONE:
/* erase everything */
mFilter = true;
mFilters.clear();
break;
case fltType::ADD:
/* add filter to list */
mFilter = true;
mFilters[pId] = mMap[pId];
break;
case fltType::REMOVE:
/* remove filter */
if(!mFilter)
mFilters = mMap;
mFilter = true;
mFilters.remove(pId);
break;
case fltType::ALL:
/* stop filtering */
mFilter = false;
mFilters.clear();
break;
}
endResetModel();
}
/***********************************************/
/********** slots ****************/
/***********************************************/
void SnifferModel::update(CANConnection*, QVector<CANFrame>& pFrames)
{
foreach(const CANFrame& frame, pFrames)
{
if(!mMap.contains(frame.frameId()))
{
int index = std::distance(mMap.begin(), mMap.lowerBound(frame.frameId()));
/* add the frame */
beginInsertRows(QModelIndex(), index, index);
mMap[frame.frameId()] = new SnifferItem(frame, mTimeSequence);
mMap[frame.frameId()]->update(frame, mTimeSequence, mMuteNotched);
endInsertRows();
emit idChange(frame.frameId(), true);
}
else
//updateData
mMap[frame.frameId()]->update(frame, mTimeSequence, mMuteNotched);
}
}
void SnifferModel::notch()
{
QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
foreach(SnifferItem* item, map)
item->notch(true);
}
void SnifferModel::unNotch()
{
QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
foreach(SnifferItem* item, map)
item->notch(false);
}