CANdevStudio
Development tool for CAN bus simulation
Loading...
Searching...
No Matches
canrawview_p.h
Go to the documentation of this file.
1#ifndef CANRAWVIEW_P_H
2#define CANRAWVIEW_P_H
3
4#include "gui/crvgui.h"
5#include <QtCore/QElapsedTimer>
6#include <QtCore/QJsonArray>
7#include <QtCore/QJsonObject>
8#include <QtGui/QStandardItemModel>
9#include <QtSerialBus/QCanBusFrame>
10#include <log.h>
11#include <memory>
12#include <sortenums.h>
13#include <sortmodel.h>
14
15namespace {
16const int32_t rowCountMax = 2000;
17const QString remoteFrameData = "R";
18}
19
20class CanRawViewPrivate : public QObject {
21 Q_OBJECT
22 Q_DECLARE_PUBLIC(CanRawView)
23
24public:
26 : _ctx(std::move(ctx))
27 , _simStarted(false)
28 , _ui(_ctx.get<CRVGuiInterface>())
29 , _columnsOrder({ "rowID", "time", "id", "dir", "len", "data" })
30 , q_ptr(q)
31 {
32 initProps();
33
34 _tvModel.setHorizontalHeaderLabels(_columnsOrder);
35 _tvModelUnique.setHorizontalHeaderLabels(_columnsOrder);
36
38 _tvModelSort.setSourceModel(&_tvModel);
39 _tvModelUniqueSort.setSourceModel(&_tvModelUnique);
41
42 _ui.setClearCbk(std::bind(&CanRawViewPrivate::clear, this));
43 _ui.setSectionClikedCbk(std::bind(&CanRawViewPrivate::sort, this, std::placeholders::_1));
44 _ui.setFilterCbk(std::bind(&CanRawViewPrivate::setFilter, this, std::placeholders::_1));
45 _ui.setDockUndockCbk([this] {
46 docked = !docked;
48 });
49
50 _tvModel.setHeaderData(0, Qt::Horizontal, QVariant::fromValue(ColType::uint_type), Qt::UserRole); // rowID
51 _tvModel.setHeaderData(1, Qt::Horizontal, QVariant::fromValue(ColType::double_type), Qt::UserRole); // time
52 _tvModel.setHeaderData(2, Qt::Horizontal, QVariant::fromValue(ColType::hex_type), Qt::UserRole); // frame ID
53 _tvModel.setHeaderData(3, Qt::Horizontal, QVariant::fromValue(ColType::str_type), Qt::UserRole); // direction
54 _tvModel.setHeaderData(4, Qt::Horizontal, QVariant::fromValue(ColType::uint_type), Qt::UserRole); // length
55 _tvModel.setHeaderData(5, Qt::Horizontal, QVariant::fromValue(ColType::str_type), Qt::UserRole); // data
56
57 _tvModelUnique.setHeaderData(0, Qt::Horizontal, QVariant::fromValue(ColType::uint_type), Qt::UserRole); // rowID
58 _tvModelUnique.setHeaderData(
59 1, Qt::Horizontal, QVariant::fromValue(ColType::double_type), Qt::UserRole); // time
60 _tvModelUnique.setHeaderData(
61 2, Qt::Horizontal, QVariant::fromValue(ColType::hex_type), Qt::UserRole); // frame ID
62 _tvModelUnique.setHeaderData(
63 3, Qt::Horizontal, QVariant::fromValue(ColType::str_type), Qt::UserRole); // direction
64 _tvModelUnique.setHeaderData(
65 4, Qt::Horizontal, QVariant::fromValue(ColType::uint_type), Qt::UserRole); // length
66 _tvModelUnique.setHeaderData(5, Qt::Horizontal, QVariant::fromValue(ColType::str_type), Qt::UserRole); // data
67 }
68
70
71 void saveSettings(QJsonObject& json)
72 {
73 QJsonArray viewModelsArray;
74
75 writeColumnsOrder(json);
76 json["scrolling"] = _ui.isViewFrozen();
77 }
78
79 void frameView(const QCanBusFrame& frame, const QString& direction)
80 {
81 if (!_simStarted) {
82 cds_debug("send/received frame while simulation stopped");
83 return;
84 }
85
86 auto payHex = frame.payload().toHex();
87 // insert space between bytes, skip the end
88 for (int ii = payHex.size() - 2; ii >= 2; ii -= 2) {
89 payHex.insert(ii, ' ');
90 }
91
92 int idPadding = 3;
93 if (frame.hasExtendedFrameFormat()) {
94 idPadding = 8;
95 }
96
97 QString frameID = QString("0x" + QString::number(frame.frameId(), 16).rightJustified(idPadding, '0'));
98 QString time = QString::number((_timer.elapsed() / 1000.0), 'f', 2);
99 QString size, data;
100 if (QCanBusFrame::RemoteRequestFrame == frame.frameType()) {
101 size.clear();
102 data = remoteFrameData;
103 } else {
104 size = QString::number(frame.payload().size());
105 data = QString::fromUtf8(payHex.data(), payHex.size());
106 }
107
108 QList<QStandardItem*> list;
109
110 if (_tvModel.rowCount() < rowCountMax) {
111 list.append(new QStandardItem(QString::number(_rowID)));
112 list.append(new QStandardItem(time));
113 list.append(new QStandardItem(frameID));
114 list.append(new QStandardItem(direction));
115 list.append(new QStandardItem(size));
116 list.append(new QStandardItem(data));
117 } else {
118 list = _tvModel.takeRow(0);
119 auto it = list.begin();
120
121 (*it++)->setText(QString::number(_rowID));
122 (*it++)->setText(time);
123 (*it++)->setText(frameID);
124 (*it++)->setText(direction);
125 (*it++)->setText(size);
126 (*it++)->setText(data);
127 }
128
129 _tvModel.appendRow(list);
130
131 quint32 fId = frame.frameId();
132 if (frame.hasExtendedFrameFormat()) {
133 // Frame id has 29 bits. Set 31 bit if we are dealing with EFF.
134 // This will separate frames in unique view
135 fId |= 0x80000000;
136 }
137
138 if (direction == "RX") {
139 if (_uniqueRxMap.count(fId)) {
140 auto& row = _uniqueRxMap[fId];
141
142 std::get<0>(row)->setText(QString::number(_rowID));
143 std::get<1>(row)->setText(time);
144 std::get<2>(row)->setText(frameID);
145 std::get<3>(row)->setText(direction);
146 std::get<4>(row)->setText(size);
147 std::get<5>(row)->setText(data);
148 } else {
149 auto rowEl = new QStandardItem(QString::number(_rowID));
150 auto timeEl = new QStandardItem(time);
151 auto frameEl = new QStandardItem(frameID);
152 auto dirEl = new QStandardItem(direction);
153 auto sizeEl = new QStandardItem(size);
154 auto dataEl = new QStandardItem(data);
155
156 _tvModelUnique.appendRow({ rowEl, timeEl, frameEl, dirEl, sizeEl, dataEl });
157 _uniqueRxMap[fId] = std::make_tuple(rowEl, timeEl, frameEl, dirEl, sizeEl, dataEl);
158 }
159 } else if (direction == "TX") {
160 if (_uniqueTxMap.count(fId)) {
161 auto& row = _uniqueTxMap[fId];
162
163 std::get<0>(row)->setText(QString::number(_rowID));
164 std::get<1>(row)->setText(time);
165 std::get<2>(row)->setText(frameID);
166 std::get<3>(row)->setText(direction);
167 std::get<4>(row)->setText(size);
168 std::get<5>(row)->setText(data);
169 } else {
170 auto rowEl = new QStandardItem(QString::number(_rowID));
171 auto timeEl = new QStandardItem(time);
172 auto frameEl = new QStandardItem(frameID);
173 auto dirEl = new QStandardItem(direction);
174 auto sizeEl = new QStandardItem(size);
175 auto dataEl = new QStandardItem(data);
176
177 _tvModelUnique.appendRow({ rowEl, timeEl, frameEl, dirEl, sizeEl, dataEl });
178 _uniqueTxMap[fId] = std::make_tuple(rowEl, timeEl, frameEl, dirEl, sizeEl, dataEl);
179 }
180 } else {
181 cds_warn("Invalid direction string: {}", direction.toStdString());
182 }
183
184 if (!_ui.isViewFrozen()) {
186 }
187
188 _rowID++;
189 }
190
191 bool restoreConfiguration(const QJsonObject& json)
192 {
193 if (columnAdopt(json) == false) {
194 return false;
195 }
196 if (scrollingAdopt(json) == false) {
197 return false;
198 }
199 return true;
200 }
201
205 {
206 return _supportedProps;
207 }
208
209private:
210 void writeColumnsOrder(QJsonObject& json) const
211 {
212 int ii = 0;
213 QJsonArray columnArray;
214 for (const auto& column : _columnsOrder) {
215 if (_ui.isColumnHidden(ii) == false) {
216 QJsonObject columnProper;
217 int vIdx;
218 _ui.getColumnProper(ii, vIdx);
219 columnProper["name"] = column;
220 columnProper["vIdx"] = vIdx;
221 columnArray.append(columnProper);
222 }
223 ++ii;
224 }
225 json["viewColumns"] = std::move(columnArray);
226 }
227
228 /* In the future to create log file below code can be used.
229 * Temporarily commented.
230 void writeViewModel(QJsonArray& jsonArray) const
231 {
232 for (auto row = 0; row < _tvModel.rowCount(); ++row) {
233 QJsonArray lineIter;
234 for (auto column = 0; column < _tvModel.columnCount(); ++column) {
235 if (_ui.isColumnHidden(column) == false) {
236 auto pp = _tvModel.data(_tvModel.index(row, column));
237 lineIter.append(std::move(pp.toString()));
238 }
239 }
240 jsonArray.append(std::move(lineIter));
241 }
242 }
243 */
244
245 bool scrollingAdopt(QJsonObject const& json)
246 {
247 auto scrolling = json.find("scrolling");
248 if (scrolling == json.end()) {
249 cds_error("Scrolling item not found");
250 return false;
251 }
252
253 if (scrolling.value().type() != QJsonValue::Bool) {
254 cds_error("Scrolling format is different than bool");
255 return false;
256 }
257 auto frozen = json["scrolling"].toBool();
258 if (_ui.isViewFrozen() != frozen) {
259 _ui.setViewFrozen(frozen);
260 }
261
262 cds_info("Scrolling was restored correctly");
263 return true;
264 }
265
266 bool columnAdopt(QJsonObject const& json)
267 {
268 auto columnIter = json.find("viewColumns");
269 if (columnIter == json.end()) {
270 cds_error("Columns item not found");
271 return false;
272 }
273
274 if (columnIter.value().type() != QJsonValue::Array) {
275 cds_error("Columns format is different than array");
276 return false;
277 }
278
279 auto colArray = json["viewColumns"].toArray();
280 if (colArray.size() != 5) {
281 cds_error("Columns array size must be 5 not {}", std::to_string(colArray.size()));
282 return false;
283 }
284
285 // Structure declaration that will be used to grab information about column settings
286 struct ref {
287 int id;
288 int vIdxConf;
289 bool operator<(const ref& rhs) const
290 {
291 return vIdxConf < rhs.vIdxConf;
292 }
293 };
294 std::vector<ref> refContener;
295
296 auto ii = 0;
297 for (const auto& column : _columnsOrder) {
298 if (_ui.isColumnHidden(ii) == false) {
299 auto jj = 0;
300 for (; jj < colArray.size(); ++jj) {
301 // Check column name
302 //==================
303 if (colArray[jj].isObject() == false) {
304 cds_error("Columns description is not an object.");
305 return false;
306 }
307 auto colObj = colArray[jj].toObject();
308 if (colObj.contains("name") == false) {
309 cds_error("Columns description does not contain name field.");
310 return false;
311 }
312 if (colObj["name"].isString() == false) {
313 cds_error("name is not a String format.");
314 return false;
315 }
316 // auto nameConf = colObj["name"].toString();
317 if (colObj["name"].toString() != column) {
318 // The name does not pass - get next
319 continue;
320 }
321
322 // Check vIdx
323 //===========
324 if (colObj.contains("vIdx") == false) {
325 cds_error("Columns description does not contain vIdx field.");
326 return false;
327 }
328 if (colObj["vIdx"].isDouble() == false) {
329 cds_error("vIdx is not a Number format.");
330 return false;
331 }
332 auto vIdxConf = colObj["vIdx"].toInt();
333
334 refContener.push_back({ ii, vIdxConf });
335 break;
336 }
337 if (jj == colArray.size()) {
338 cds_error("Required parameter in column description was not found.");
339 return false;
340 }
341 }
342 ++ii;
343 }
344 std::sort(refContener.rbegin(), refContener.rend());
345 for (const auto& pp : refContener) {
346 int vIdx;
347 _ui.getColumnProper(pp.id, vIdx);
348 if (vIdx != pp.vIdxConf) {
349 _ui.setColumnProper(vIdx, pp.vIdxConf);
350 }
351 }
352 cds_info("Column properties were restored correctly");
353
354 return true;
355 }
356
357 void initProps()
358 {
359 for (const auto& p : _supportedProps) {
361 }
362 }
363
364private slots:
370 void clear()
371 {
372 _tvModel.removeRows(0, _tvModel.rowCount());
373 _tvModelUnique.removeRows(0, _tvModelUnique.rowCount());
374 _uniqueRxMap.clear();
375 _uniqueTxMap.clear();
376 _rowID = 0;
377 }
378
383 void sort(const int clickedIndex)
384 {
385 _currentSortOrder = _ui.getSortOrder();
386 _sortIndex = clickedIndex;
387
388 if (_prevIndex == clickedIndex) {
389 if (_currentSortOrder == Qt::DescendingOrder) {
390 _ui.setSorting(_sortIndex, Qt::DescendingOrder);
391 } else {
392 _ui.setSorting(0, Qt::AscendingOrder);
393 _prevIndex = 0;
394 _sortIndex = 0;
395 }
396 } else {
397 _ui.setSorting(_sortIndex, Qt::AscendingOrder);
398 _prevIndex = clickedIndex;
399 }
400 }
401
405 void setFilter(bool enabled)
406 {
409
410 if (enabled) {
412 } else {
414 }
415
416 _currentSortOrder = _ui.getSortOrder();
417 _ui.setSorting(_sortIndex, _currentSortOrder);
418 }
419
420public:
422 QElapsedTimer _timer;
423 QStandardItemModel _tvModel;
424 QStandardItemModel _tvModelUnique;
427 bool docked{ true };
428 std::map<QString, QVariant> _props;
431
432private:
433 int _rowID{ 0 };
434 int _prevIndex{ 0 };
435 int _sortIndex{ 0 };
436 Qt::SortOrder _currentSortOrder{ Qt::AscendingOrder };
437 QStringList _columnsOrder;
438 CanRawView* q_ptr;
439 std::map<uint32_t,
440 std::tuple<QStandardItem*, QStandardItem*, QStandardItem*, QStandardItem*, QStandardItem*, QStandardItem*>>
441 _uniqueTxMap;
442 std::map<uint32_t,
443 std::tuple<QStandardItem*, QStandardItem*, QStandardItem*, QStandardItem*, QStandardItem*, QStandardItem*>>
444 _uniqueRxMap;
445
446 const QString _nameProperty = "name";
447
448 // workaround for clang 3.5
450
451 // clang-format off
453 std::make_tuple(_nameProperty, QVariant::String, true, cf(nullptr))
454 };
455 // clang-format on
456};
457#endif // CANRAWVIEW_P_H
Definition canrawview.h:14
void mainWidgetDockToggled(QWidget *widget) override
Definition canrawview_p.h:20
std::map< QString, QVariant > _props
Definition canrawview_p.h:428
bool _simStarted
Definition canrawview_p.h:425
void frameView(const QCanBusFrame &frame, const QString &direction)
Definition canrawview_p.h:79
void saveSettings(QJsonObject &json)
Definition canrawview_p.h:71
CanRawViewCtx _ctx
Definition canrawview_p.h:421
~CanRawViewPrivate()
Definition canrawview_p.h:69
QElapsedTimer _timer
Definition canrawview_p.h:422
SortModel _tvModelSort
Definition canrawview_p.h:429
QStandardItemModel _tvModel
Definition canrawview_p.h:423
CanRawViewPrivate(CanRawView *q, CanRawViewCtx &&ctx=CanRawViewCtx(new CRVGui))
Definition canrawview_p.h:25
ComponentInterface::ComponentProperties getSupportedProperties() const
Used to get list of properties supported by component.
Definition canrawview_p.h:204
SortModel _tvModelUniqueSort
Definition canrawview_p.h:430
QStandardItemModel _tvModelUnique
Definition canrawview_p.h:424
bool restoreConfiguration(const QJsonObject &json)
Definition canrawview_p.h:191
CRVGuiInterface & _ui
Definition canrawview_p.h:426
bool docked
Definition canrawview_p.h:427
Definition sortmodel.h:6
void setFilterActive(bool enabled)
Definition sortmodel.cpp:50
Context< CRVGuiInterface > CanRawViewCtx
Definition context.h:48
#define cds_debug(fmt,...)
Definition log.h:13
#define cds_warn(fmt,...)
Definition log.h:17
#define cds_error(fmt,...)
Definition log.h:21
#define cds_info(fmt,...)
Definition log.h:25
Definition crvgui.h:11
Definition crvguiinterface.h:10
virtual void setViewFrozen(bool state)=0
virtual QWidget * mainWidget()=0
virtual void scrollToBottom()=0
virtual void setDockUndockCbk(const dockUndock_t &cb)=0
virtual void setModel(QAbstractItemModel *model)=0
virtual bool isViewFrozen()=0
virtual void getColumnProper(int ndx, int &vIdx)=0
virtual void setClearCbk(const clear_t &cb)=0
virtual void setSectionClikedCbk(const sectionClicked_t &cb)=0
virtual bool isColumnHidden(int ndx)=0
virtual void initTableView(QAbstractItemModel &tvModel)=0
virtual void setSorting(int sortNdx, Qt::SortOrder order)=0
virtual Qt::SortOrder getSortOrder()=0
virtual void setFilterCbk(const filter_t &cb)=0
virtual void setColumnProper(int vIdxFrom, int vIdxTo)=0
std::vector< ComponentProperty > ComponentProperties
Definition componentinterface.h:66
std::function< QWidget *(void)> CustomEditFieldCbk
Definition componentinterface.h:64
static constexpr const QString & propertyName(const ComponentProperty &p)
Definition componentinterface.h:69