5 #include <QInputDialog>
8 #include <QProgressDialog>
11 #include <QTextStream>
13 #include <QFileDialog>
17 #include <zcm/zcm-cpp.hpp>
18 #include <zcm/tools/Introspection.hpp>
26 _dialog =
new QDialog();
27 _ui =
new Ui::DialogZcm();
28 _ui->setupUi(_dialog);
30 _config_widget =
new ConfigZCM(
"DataLoadZcm", _dialog);
31 _ui->mainLayout->insertWidget(0, _config_widget, 1);
33 _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
false);
35 _ui->listWidgetChannels->setSelectionMode(QAbstractItemView::ExtendedSelection);
37 connect(_ui->listWidgetChannels, &QListWidget::itemSelectionChanged,
this, [
this]() {
38 auto selected = _ui->listWidgetChannels->selectionModel()->selectedIndexes();
39 bool box_enabled = selected.size() > 0;
40 _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(box_enabled);
51 return "DataLoad Zcm";
56 static vector<const char*> extensions = {
"zcmlog" };
61 function<
void(
const zcm::LogEvent* evt)> processEvent)
63 zcm::LogFile inlog(logpath,
"r");
66 cerr <<
"Unable to open input zcm log: " << logpath << endl;
70 auto processLog = [&inlog](
function<
void(
const zcm::LogEvent* evt)> processEvent) {
71 const zcm::LogEvent* evt;
73 static int lastPrintPercent = 0;
75 fseeko(inlog.getFilePtr(), 0, SEEK_END);
76 off64_t logSize = ftello(inlog.getFilePtr());
77 fseeko(inlog.getFilePtr(), 0, SEEK_SET);
79 QProgressDialog progress_dialog;
80 progress_dialog.setLabelText(
"Loading... please wait");
81 progress_dialog.setWindowModality(Qt::ApplicationModal);
82 progress_dialog.setRange(0, 100);
83 progress_dialog.setAutoClose(
true);
84 progress_dialog.setAutoReset(
true);
85 progress_dialog.show();
87 bool interrupted =
false;
91 offset = ftello(inlog.getFilePtr());
93 int percent = 100.0 * offset / (logSize == 0 ? 1 : logSize);
94 if (percent != lastPrintPercent)
99 <<
"Percent Complete: " << percent << flush;
101 lastPrintPercent = percent;
103 progress_dialog.setValue(percent);
104 if (progress_dialog.wasCanceled())
111 evt = inlog.readNextEvent();
119 if (lastPrintPercent != 100 && !interrupted)
121 <<
"Percent Complete: 100" << flush;
126 progress_dialog.cancel();
129 processLog(processEvent);
138 _all_channels.clear();
139 _all_channels_filepath = filepath;
141 auto processEvent = [&](
const zcm::LogEvent* evt) {
142 _all_channels.insert(evt->channel);
151 _dialog->restoreGeometry(settings.value(
"DataLoadZcm.geometry").toByteArray());
153 _ui->listWidgetChannels->clear();
154 for (
auto& c : _all_channels)
156 auto chan = QString::fromStdString(c);
157 _ui->listWidgetChannels->addItem(chan);
159 _ui->listWidgetChannels->sortItems();
161 auto selected_channels = settings.value(
"DataLoadZcm.selected_channels").toStringList();
162 for (
int row = 0; row < _ui->listWidgetChannels->count(); row++)
164 auto item = _ui->listWidgetChannels->item(row);
165 if (selected_channels.contains(item->text()))
167 item->setSelected(
true);
170 selected_channels.clear();
172 int res = _dialog->exec();
173 settings.setValue(
"DataLoadZcm.geometry", _dialog->saveGeometry());
175 if (res == QDialog::Rejected)
180 _selected_channels.clear();
182 QModelIndexList indexes = _ui->listWidgetChannels->selectionModel()->selectedRows();
183 for (
auto& i : indexes)
185 auto item = _ui->listWidgetChannels->item(i.row());
186 _selected_channels.insert(item->text().toStdString());
187 selected_channels.push_back(item->text());
190 settings.setValue(
"DataLoadZcm.selected_channels", selected_channels);
192 return !indexes.empty();
195 template <
typename T>
198 return static_cast<double>(*
reinterpret_cast<const T*
>(
data));
212 case ZCM_FIELD_INT8_T:
215 case ZCM_FIELD_INT16_T:
216 v->
numerics.emplace_back(name, toDouble<int16_t>(
data));
218 case ZCM_FIELD_INT32_T:
219 v->
numerics.emplace_back(name, toDouble<int32_t>(
data));
221 case ZCM_FIELD_INT64_T:
222 v->
numerics.emplace_back(name, toDouble<int64_t>(
data));
225 v->
numerics.emplace_back(name, toDouble<uint8_t>(
data));
227 case ZCM_FIELD_FLOAT:
230 case ZCM_FIELD_DOUBLE:
233 case ZCM_FIELD_BOOLEAN:
236 case ZCM_FIELD_STRING:
237 v->
strings.emplace_back(name,
string((
const char*)
data));
239 case ZCM_FIELD_USER_TYPE:
240 assert(
false &&
"Should not be possble");
246 string filepath = info->
filename.toStdString();
252 if (filepath != _all_channels_filepath)
254 refreshChannels(filepath);
256 if (!launchDialog(filepath))
261 zcm::TypeDb types(_config_widget->getLibraries().toStdString());
264 QMessageBox::warning(
nullptr,
"Error",
"Failed to load zcmtypes");
268 vector<pair<string, double>> numerics;
269 vector<pair<string, string>> strings;
272 auto processEvent = [&](
const zcm::LogEvent* evt) {
273 if (_selected_channels.find(evt->channel) == _selected_channels.end())
278 if (evt->datalen == 0)
280 auto itr = plot_data.
numeric.find(evt->channel);
281 if (itr == plot_data.
numeric.end())
283 itr->second.pushBack({ (double)evt->timestamp / 1e6, 0 });
287 zcm::Introspection::processEncodedType(evt->channel, evt->data, evt->datalen,
"/",
291 auto itr = plot_data.
numeric.find(n.first);
292 if (itr == plot_data.
numeric.end())
294 itr->second.pushBack({ (double)evt->timestamp / 1e6, n.second });
298 auto itr = plot_data.
strings.find(
s.first);
299 if (itr == plot_data.
strings.end())
301 itr->second.pushBack({ (double)evt->timestamp / 1e6,
s.second });
314 static QDomElement
serialize(
const unordered_set<string>& input, QDomDocument& doc,
317 QDomElement
ret = doc.createElement(QString::fromStdString(name));
319 for (
const auto& item : input)
321 QDomElement stringElement = doc.createElement(
"String");
322 QDomText textNode = doc.createTextNode(QString::fromStdString(item));
323 stringElement.appendChild(textNode);
324 ret.appendChild(stringElement);
332 unordered_set<string>
ret;
334 QDomNodeList childNodes = elt.childNodes();
335 for (
int i = 0; i < childNodes.size(); ++i)
337 QDomNode node = childNodes.item(i);
338 if (node.isElement())
340 QDomElement element = node.toElement();
341 if (element.tagName() ==
"String")
343 QString stringValue = element.text();
344 ret.insert(stringValue.toStdString());
354 parent_element.appendChild(
serialize(_selected_channels, doc,
"selected_channels"));
355 auto all_channels =
serialize(_all_channels, doc,
"all_channels");
356 all_channels.setAttribute(
"filepath", QString::fromStdString(_all_channels_filepath));
357 parent_element.appendChild(all_channels);
363 QDomElement all_channels = parent_element.firstChildElement(
"all_channels");
364 if (!all_channels.isNull())
367 if (all_channels.hasAttribute(
"filepath"))
369 _all_channels_filepath = all_channels.attribute(
"filepath").toStdString();
373 QDomElement selected_channels = parent_element.firstChildElement(
"selected_channels");
374 if (!selected_channels.isNull())
376 _selected_channels =
deserialize(selected_channels);
378 QStringList selected_channels;
379 for (
auto& c : _selected_channels)
380 selected_channels.push_back(QString::fromStdString(c));
383 settings.setValue(
"DataLoadZcm.selected_channels", selected_channels);