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");
65 cerr <<
"Unable to open input zcm log: " << logpath << endl;
69 auto processLog = [&inlog](function<void(const zcm::LogEvent* evt)> processEvent) {
70 const zcm::LogEvent* evt;
72 static int lastPrintPercent = 0;
74 fseeko(inlog.getFilePtr(), 0, SEEK_END);
75 off64_t logSize = ftello(inlog.getFilePtr());
76 fseeko(inlog.getFilePtr(), 0, SEEK_SET);
78 QProgressDialog progress_dialog;
79 progress_dialog.setLabelText(
"Loading... please wait");
80 progress_dialog.setWindowModality(Qt::ApplicationModal);
81 progress_dialog.setRange(0, 100);
82 progress_dialog.setAutoClose(
true);
83 progress_dialog.setAutoReset(
true);
84 progress_dialog.show();
86 bool interrupted =
false;
89 offset = ftello(inlog.getFilePtr());
91 int percent = 100.0 * offset / (logSize == 0 ? 1 : logSize);
92 if (percent != lastPrintPercent) {
94 cout <<
"\r" <<
"Percent Complete: " << percent << flush;
96 lastPrintPercent = percent;
98 progress_dialog.setValue(percent);
99 if (progress_dialog.wasCanceled()) {
105 evt = inlog.readNextEvent();
106 if (evt ==
nullptr)
break;
111 if (lastPrintPercent != 100 && !interrupted)
112 cout <<
"\r" <<
"Percent Complete: 100" << flush;
116 if (interrupted) progress_dialog.cancel();
119 processLog(processEvent);
128 _all_channels.clear();
129 _all_channels_filepath = filepath;
131 auto processEvent = [&](
const zcm::LogEvent* evt){
132 _all_channels.insert(evt->channel);
141 _dialog->restoreGeometry(settings.value(
"DataLoadZcm.geometry").toByteArray());
143 _ui->listWidgetChannels->clear();
144 for (
auto& c : _all_channels) {
145 auto chan = QString::fromStdString(c);
146 _ui->listWidgetChannels->addItem(chan);
148 _ui->listWidgetChannels->sortItems();
150 auto selected_channels = settings.value(
"DataLoadZcm.selected_channels").toStringList();
151 for (
int row = 0; row<_ui->listWidgetChannels->count(); row++) {
152 auto item = _ui->listWidgetChannels->item(row);
153 if (selected_channels.contains(item->text())) {
154 item->setSelected(
true);
157 selected_channels.clear();
159 int res = _dialog->exec();
160 settings.setValue(
"DataLoadZcm.geometry", _dialog->saveGeometry());
162 if (res == QDialog::Rejected) {
166 _selected_channels.clear();
168 QModelIndexList indexes = _ui->listWidgetChannels->selectionModel()->selectedRows();
169 for (
auto& i : indexes) {
170 auto item = _ui->listWidgetChannels->item(i.row());
171 _selected_channels.insert(item->text().toStdString());
172 selected_channels.push_back(item->text());
175 settings.setValue(
"DataLoadZcm.selected_channels", selected_channels);
177 return !indexes.empty();
180 template <
typename T>
182 return static_cast<double>(*
reinterpret_cast<const T*
>(
data));
191 const void*
data,
void* usr)
195 case ZCM_FIELD_INT8_T: v->
numerics.emplace_back(name, toDouble<int8_t>(data));
break;
196 case ZCM_FIELD_INT16_T: v->
numerics.emplace_back(name, toDouble<int16_t>(data));
break;
197 case ZCM_FIELD_INT32_T: v->
numerics.emplace_back(name, toDouble<int32_t>(data));
break;
198 case ZCM_FIELD_INT64_T: v->
numerics.emplace_back(name, toDouble<int64_t>(data));
break;
199 case ZCM_FIELD_BYTE: v->
numerics.emplace_back(name, toDouble<uint8_t>(data));
break;
200 case ZCM_FIELD_FLOAT: v->
numerics.emplace_back(name, toDouble<float>(data));
break;
201 case ZCM_FIELD_DOUBLE: v->
numerics.emplace_back(name, toDouble<double>(data));
break;
202 case ZCM_FIELD_BOOLEAN: v->
numerics.emplace_back(name, toDouble<bool>(data));
break;
203 case ZCM_FIELD_STRING: v->
strings.emplace_back(name,
string((
const char*)data));
break;
204 case ZCM_FIELD_USER_TYPE:
assert(
false &&
"Should not be possble");
210 string filepath = info->
filename.toStdString();
215 if (filepath != _all_channels_filepath) {
216 refreshChannels(filepath);
218 if (!launchDialog(filepath)) {
222 zcm::TypeDb types(_config_widget->getLibraries().toStdString());
225 QMessageBox::warning(
nullptr,
"Error",
"Failed to load zcmtypes");
229 vector<pair<string, double>> numerics;
230 vector<pair<string, string>> strings;
233 auto processEvent = [&](
const zcm::LogEvent* evt){
234 if (_selected_channels.find(evt->channel) == _selected_channels.end())
return;
235 zcm::Introspection::processEncodedType(evt->channel,
236 evt->data, evt->datalen,
240 auto itr = plot_data.
numeric.find(n.first);
242 itr->second.pushBack({ (double)evt->timestamp / 1e6, n.second });
245 auto itr = plot_data.
strings.find(
s.first);
247 itr->second.pushBack({ (double)evt->timestamp / 1e6,
s.second });
260 static QDomElement
serialize(
const unordered_set<string>& input,
261 QDomDocument& doc,
const string& name)
263 QDomElement
ret = doc.createElement(QString::fromStdString(name));
265 for (
const auto& item : input) {
266 QDomElement stringElement = doc.createElement(
"String");
267 QDomText textNode = doc.createTextNode(QString::fromStdString(item));
268 stringElement.appendChild(textNode);
269 ret.appendChild(stringElement);
277 unordered_set<string>
ret;
279 QDomNodeList childNodes = elt.childNodes();
280 for (
int i = 0; i < childNodes.size(); ++i) {
281 QDomNode node = childNodes.item(i);
282 if (node.isElement()) {
283 QDomElement element = node.toElement();
284 if (element.tagName() ==
"String") {
285 QString stringValue = element.text();
286 ret.insert(stringValue.toStdString());
297 parent_element.appendChild(
serialize(_selected_channels, doc,
"selected_channels"));
298 auto all_channels =
serialize(_all_channels, doc,
"all_channels");
299 all_channels.setAttribute(
"filepath", QString::fromStdString(_all_channels_filepath));
300 parent_element.appendChild(all_channels);
306 QDomElement all_channels = parent_element.firstChildElement(
"all_channels");
307 if (!all_channels.isNull()) {
309 if (all_channels.hasAttribute(
"filepath")) {
310 _all_channels_filepath = all_channels.attribute(
"filepath").toStdString();
314 QDomElement selected_channels = parent_element.firstChildElement(
"selected_channels");
315 if (!selected_channels.isNull()) {
316 _selected_channels =
deserialize(selected_channels);
318 QStringList selected_channels;
319 for (
auto& c : _selected_channels)
320 selected_channels.push_back(QString::fromStdString(c));
323 settings.setValue(
"DataLoadZcm.selected_channels", selected_channels);
bool launchDialog(const std::string &filepath)
const std::vector< const char * > & compatibleFileExtensions() const override
Provide a list of file extensions that this plugin can open.
QString filename
name of the file to open
bool readDataFromFile(PJ::FileLoadInfo *fileload_info, PlotDataMapRef &destination) override
double toDouble(const void *data)
TimeseriesMap numeric
Numerical timeseries.
#define assert(condition)
StringSeriesMap strings
Series of strings.
TimeseriesMap::iterator addNumeric(const std::string &name, PlotGroup::Ptr group={})
vector< pair< string, string > > & strings
vector< pair< string, double > > & numerics
StringSeriesMap::iterator addStringSeries(const std::string &name, PlotGroup::Ptr group={})
const char * name() const override
Name of the plugin type, NOT the particular instance.
static int processInputLog(const string &logpath, function< void(const zcm::LogEvent *evt)> processEvent)
bool xmlLoadState(const QDomElement &parent_element) override
Override this method to load the status of the plugin from XML.
static unordered_set< string > deserialize(const QDomElement &elt)
bool xmlSaveState(QDomDocument &doc, QDomElement &parent_element) const override
Override this method to save the status of the plugin to XML.
QDomDocument plugin_config
Saved configuration from a previous run or a Layout file.
bool refreshChannels(const std::string &filepath)
static void processData(const string &name, zcm_field_type_t type, const void *data, void *usr)
static QDomElement serialize(const unordered_set< string > &input, QDomDocument &doc, const string &name)