1 #include <QDebug>
2 #include <Qt>
3 #include <QApplication>
4 #include "sniffermodel.h"
5 #include "snifferwindow.h"
6 #include "SnifferDelegate.h"
7
SnifferModel(QObject * parent)8 SnifferModel::SnifferModel(QObject *parent)
9 : QAbstractItemModel(parent),
10 mFilter(false),
11 mNeverExpire(false),
12 mFadeInactive(false),
13 mMuteNotched(false),
14 mTimeSequence(0)
15 {
16 QColor TextColor = QApplication::palette().color(QPalette::Text);
17 if (TextColor.red() + TextColor.green() + TextColor.blue() < 200)
18 {
19 mDarkMode = false;
20 }
21 else mDarkMode = true;
22 }
23
~SnifferModel()24 SnifferModel::~SnifferModel()
25 {
26 qDeleteAll(mMap);
27 mMap.clear();
28 mFilters.clear();
29 }
30
31
columnCount(const QModelIndex & parent) const32 int SnifferModel::columnCount(const QModelIndex &parent) const
33 {
34 return parent.isValid() ? 0 : tc::LAST+1;
35 }
36
37
rowCount(const QModelIndex & parent) const38 int SnifferModel::rowCount(const QModelIndex &parent) const
39 {
40 const QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
41 return parent.isValid() ? 0 : map.size();
42 }
43
44
data(const QModelIndex & index,int role) const45 QVariant SnifferModel::data(const QModelIndex &index, int role) const
46 {
47 if (!index.isValid())
48 return QVariant();
49
50 SnifferItem *item = static_cast<SnifferItem*>(index.internalPointer());
51 if(!item) QVariant();
52
53 int col = index.column();
54
55 switch(role)
56 {
57 case Qt::DisplayRole:
58 {
59 switch(col)
60 {
61 case tc::DELTA:
62 return QString::number(item->getDelta(), 'f');
63 case tc::ID:
64 return QString("%1").arg(item->getId(), 5, 16, QLatin1Char(' ')).toUpper();
65 default:
66 break;
67 }
68 if(tc::DATA_0<=col && col <=tc::DATA_7)
69 {
70 int data = item->getData(col-tc::DATA_0);
71 if(data >= 0)
72 {
73 return QString("%1").arg((uint8_t)data, 2, 16, QLatin1Char('0')).toUpper();
74 }
75 }
76 break;
77 }
78 case Qt::ForegroundRole:
79 {
80 if (!mFadeInactive || col < 2) return QApplication::palette().brush(QPalette::Text);
81 int v = item->getSeqInterval(col - 2) * 10;
82 //qDebug() << "mTS: " << mTimeSequence << " gDT(" << (col - 2) << ") " << item->getDataTimestamp(col - 2);
83 if (v > 225) v = 225;
84 if (v < 0) v = 0;
85
86 if (!mDarkMode) //text defaults to being dark
87 {
88 return QBrush(QColor(v,v,v,255));
89 }
90 else //text defaults to being light
91 {
92 return QBrush(QColor(255-v,255-v,255-v,255));
93 }
94 }
95
96 case Qt::BackgroundRole:
97 {
98 if(tc::ID==col)
99 {
100 if(item->elapsed() > 4000)
101 {
102 if (!mDarkMode) return QBrush(Qt::red);
103 return QBrush(QColor(128,0,0));
104 }
105 }
106 else if(tc::DATA_0<=col && col<=tc::DATA_7)
107 {
108 dc change = item->dataChange(col-tc::DATA_0);
109 switch(change)
110 {
111 case dc::INC:
112 if (!mDarkMode) return QBrush(Qt::green);
113 return QBrush(QColor(0,128,0));
114 case dc::DEINC:
115 if (!mDarkMode) return QBrush(Qt::red);
116 return QBrush(QColor(128,0,0));
117 default:
118 return QApplication::palette().brush(QPalette::Base);
119 }
120 }
121 break;
122 }
123 }
124
125 return QVariant();
126 }
127
128
flags(const QModelIndex & index) const129 Qt::ItemFlags SnifferModel::flags(const QModelIndex &index) const
130 {
131 if (!index.isValid())
132 return 0;
133
134 return QAbstractItemModel::flags(index);
135 }
136
137
headerData(int section,Qt::Orientation orientation,int role) const138 QVariant SnifferModel::headerData(int section, Qt::Orientation orientation, int role) const
139 {
140 if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
141 {
142 switch(section)
143 {
144 case tc::DELTA:
145 return QString("Delta");
146 case tc::ID:
147 return QString("ID");
148 default:
149 break;
150 }
151 if(tc::DATA_0<=section && section <=tc::DATA_7)
152 return QString::number(section-tc::DATA_0);
153 }
154
155 return QVariant();
156 }
157
158
index(int row,int column,const QModelIndex & parent) const159 QModelIndex SnifferModel::index(int row, int column, const QModelIndex &parent) const
160 {
161 if (parent.isValid())
162 return QModelIndex();
163
164 const QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
165
166 if(column>tc::LAST || row>=map.size())
167 return QModelIndex();
168
169 /* ugly but I can't find best without creating a list to keep indexes */
170 QMap<quint32, SnifferItem*>::const_iterator iter;
171 int i;
172 for(iter = map.begin(), i=0 ; i<row ; ++i, ++iter);
173
174 return createIndex(row, column, iter.value());
175 }
176
177
parent(const QModelIndex &) const178 QModelIndex SnifferModel::parent(const QModelIndex &) const
179 {
180 return QModelIndex();
181 }
182
getNeverExpire()183 bool SnifferModel::getNeverExpire()
184 {
185 return mNeverExpire;
186 }
187
getFadeInactive()188 bool SnifferModel::getFadeInactive()
189 {
190 return mFadeInactive;
191 }
192
getMuteNotched()193 bool SnifferModel::getMuteNotched()
194 {
195 return mMuteNotched;
196 }
197
setNeverExpire(bool val)198 void SnifferModel::setNeverExpire(bool val)
199 {
200 mNeverExpire = val;
201 }
202
setFadeInactive(bool val)203 void SnifferModel::setFadeInactive(bool val)
204 {
205 mFadeInactive = val;
206 }
207
setMuteNotched(bool val)208 void SnifferModel::setMuteNotched(bool val)
209 {
210 mMuteNotched = val;
211 }
212
clear()213 void SnifferModel::clear()
214 {
215 beginResetModel();
216 qDeleteAll(mMap);
217 mMap.clear();
218 mFilters.clear();
219 mFilter = false;
220 endResetModel();
221 }
222
223 //Called from window with a timer (currently 200ms)
refresh()224 void SnifferModel::refresh()
225 {
226 QMap<quint32, SnifferItem*>::iterator i;
227 QVector<quint32> toRemove;
228 SnifferItem* item;
229
230 mTimeSequence++;
231
232 /* update markers */
233
234
235 for (i = mMap.begin(); i != mMap.end(); ++i)
236 {
237 i.value()->updateMarker();
238 if(i.value()->elapsed()>5000 && !mNeverExpire)
239 toRemove.append(i.key());
240 }
241
242 if(toRemove.size())
243 {
244 beginResetModel();
245 foreach(quint32 id, toRemove)
246 {
247 /* remove element */
248 item = mMap.take(id);
249 mFilters.remove(id);
250 delete item;
251 /* send notification */
252 emit idChange(id, false);
253 }
254 endResetModel();
255 }
256 else
257 /* refresh data */
258 dataChanged(createIndex(0, 0),
259 createIndex(rowCount()-1, columnCount()-1), QVector<int>(Qt::DisplayRole));
260 }
261
262
filter(fltType pType,int pId)263 void SnifferModel::filter(fltType pType, int pId)
264 {
265 beginResetModel();
266 switch(pType)
267 {
268 case fltType::NONE:
269 /* erase everything */
270 mFilter = true;
271 mFilters.clear();
272 break;
273 case fltType::ADD:
274 /* add filter to list */
275 mFilter = true;
276 mFilters[pId] = mMap[pId];
277 break;
278 case fltType::REMOVE:
279 /* remove filter */
280 if(!mFilter)
281 mFilters = mMap;
282 mFilter = true;
283 mFilters.remove(pId);
284 break;
285 case fltType::ALL:
286 /* stop filtering */
287 mFilter = false;
288 mFilters.clear();
289 break;
290 }
291 endResetModel();
292 }
293
294
295 /***********************************************/
296 /********** slots ****************/
297 /***********************************************/
298
update(CANConnection *,QVector<CANFrame> & pFrames)299 void SnifferModel::update(CANConnection*, QVector<CANFrame>& pFrames)
300 {
301 foreach(const CANFrame& frame, pFrames)
302 {
303 if(!mMap.contains(frame.frameId()))
304 {
305 int index = std::distance(mMap.begin(), mMap.lowerBound(frame.frameId()));
306 /* add the frame */
307 beginInsertRows(QModelIndex(), index, index);
308 mMap[frame.frameId()] = new SnifferItem(frame, mTimeSequence);
309 mMap[frame.frameId()]->update(frame, mTimeSequence, mMuteNotched);
310 endInsertRows();
311
312 emit idChange(frame.frameId(), true);
313 }
314 else
315 //updateData
316 mMap[frame.frameId()]->update(frame, mTimeSequence, mMuteNotched);
317 }
318 }
319
notch()320 void SnifferModel::notch()
321 {
322 QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
323
324 foreach(SnifferItem* item, map)
325 item->notch(true);
326 }
327
unNotch()328 void SnifferModel::unNotch()
329 {
330 QMap<quint32, SnifferItem*>& map = mFilter ? mFilters : mMap;
331
332 foreach(SnifferItem* item, map)
333 item->notch(false);
334 }
335
336
337