source: flair-src/trunk/tools/FlairGCS/src/file_ui.cpp@ 244

Last change on this file since 244 was 244, checked in by Sanahuja Guillaume, 6 years ago

modifs segfault when closing connection

File size: 14.3 KB
Line 
1// %flair:license{
2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
4// %flair:license}
5#include "file_ui.h"
6#include "communication.h"
7
8#include <stdio.h>
9#include <cstring>
10#include <cstdlib>
11#include <fstream>
12#include <iostream>
13#include <QDir>
14#include <QDate>
15#include <QTextStream>
16#include <QGridLayout>
17#include <io_hdfile.h>
18#include <QtEndian>
19#include <QComboBox>
20#include <QPushButton>
21#include <QTextEdit>
22#include <QDialog>
23#include <QStringList>
24#include <QFormLayout>
25#include <QThread>
26
27#include <unistd.h>
28using namespace std;
29
30file_ui::file_ui(UDTSOCKET socket,QString name): QObject() {
31 this->socket=socket;
32 this->name=name;
33
34 bool blocking = true;
35 if (UDT::setsockopt(socket, 0, UDT_SNDSYN, &blocking, sizeof(bool))!= 0) {
36 fprintf(stderr,"UDT::setsockopt error (UDT_SNDSYN) %s\n",UDT::getlasterror().getErrorMessage());
37 }
38
39 linger _linger;
40 _linger.l_onoff=1;
41 _linger.l_linger=180;
42
43 if (UDT::setsockopt(socket, 0, UDT_LINGER, &_linger, sizeof(struct linger)) != 0)
44 fprintf(stderr,"UDT::setsockopt error (UDT_LINGER) %s\n",UDT::getlasterror().getErrorMessage());
45
46 dialog = new QDialog();
47//ffprintf(stderr,stderr,"creator file ui %x\n",thread());
48 dialog->setWindowTitle("log files");
49 QGridLayout *main_layout = new QGridLayout(dialog);
50 ok_button = new QPushButton("Ok", dialog);
51 log_text = new QTextEdit(dialog);
52 log_text->setReadOnly(true);
53 input_text = new QTextEdit(dialog);
54 input_text->setText("add your log comment here");
55 input_cleared = false;
56 ok_button->setEnabled(false);
57
58 main_layout->addWidget(log_text, 0, 0);
59 main_layout->addWidget(input_text, 1, 0);
60
61 QWidget *widget = new QWidget(dialog);
62 QFormLayout *formLayout = new QFormLayout(widget);
63 csv_combo = new QComboBox(widget);
64 formLayout->addRow(tr("save all log with following base time"), csv_combo);
65 csv_combo->addItem("(no base time)");
66 main_layout->addWidget(widget, 2, 0);
67 main_layout->addWidget(ok_button, 3, 0);
68
69 //connect for multithreaded stuffs
70 connect(ok_button, SIGNAL(clicked()), this, SLOT(save()),Qt::QueuedConnection);
71 connect(input_text, SIGNAL(cursorPositionChanged()), this,SLOT(clearInputText()),Qt::DirectConnection);
72 connect(this, SIGNAL(appendToLog(QString)), log_text, SLOT(append(QString)));
73
74 file_names = new QStringList();
75
76 dialog->show();
77}
78
79file_ui::~file_ui() {
80 delete dialog;
81}
82
83void file_ui::receive(void) {
84 char *recv_buf;
85 int bytesRead;
86 bool flag_new_seq = true;
87 QString folder_name;
88//ffprintf(stderr,stderr,"file_ui thread %x\n",thread());
89 while(1) {
90 // receive file info
91 recv_buf = (char *)malloc(1024);
92 bytesRead = UDT::recvmsg(socket, recv_buf, 1024);
93 if (bytesRead <= 0) {
94 free(recv_buf);
95 break;
96 }
97
98 int size;
99 memcpy(&size, &recv_buf[1], sizeof(int));
100 if (recv_buf[0] == FILE_INFO_BIG_ENDIAN)
101 size = qFromBigEndian(size);
102
103 // fprintf(stderr,"file_ui recu %i %x\n",bytesRead,recv_buf[0]);
104 if ((recv_buf[0]==FILE_INFO_LITTLE_ENDIAN || recv_buf[0]==FILE_INFO_BIG_ENDIAN) && size>0) {
105 if (flag_new_seq == true) {
106 // create directory for storage
107 QDateTime dateTime = QDateTime::currentDateTime();
108 folder_name = dateTime.toString("yyyyMMdd_hhmm") + "_" + name;
109 if (QDir().exists(folder_name) == true) {
110 folder_name = dateTime.toString("yyyyMMdd_hhmm_ss") + "_" + name;
111 }
112 QDir().mkdir(folder_name);
113
114 flag_new_seq = false;
115 appendToLog("Creating directory " + folder_name);
116 }
117
118 QString file_name=QString::fromAscii((const char *)&recv_buf[5], bytesRead - 5);
119 QString file_path=folder_name+"/"+file_name;
120 appendToLog(QString("receiving %1 (%2 bytes)").arg(file_name).arg(size));
121 QFile fichier(file_path);
122
123 if (!fichier.open(QIODevice::WriteOnly)) {
124 appendToLog(" could not write to file!");
125 } else {
126 // receive file
127 recv_buf = (char *)realloc((void *)recv_buf, size);
128 bytesRead = UDT::recvmsg(socket, recv_buf, size);
129 if (bytesRead != size) {
130 appendToLog(QString(" error receiving file! (%1/%2)").arg(bytesRead).arg(size));
131 free(recv_buf);
132 break;
133 } else {
134 appendToLog(" ok");
135 }
136
137 QDataStream stream(&fichier);
138 stream.writeRawData(recv_buf, size);
139 fichier.close();
140
141 addFile(file_path);
142 }
143
144 free(recv_buf);
145 } else if (recv_buf[0] == END_SENDING_FILES) {
146 //end ack
147 UDT::sendmsg(socket,&recv_buf[0],1);
148 endOfFiles();
149 UDT::close(socket);
150 fprintf(stderr,"disconnected from log files\n");
151 break;
152 }
153 }
154}
155
156void file_ui::addFile(QString file_path) {
157 // framework sends dbt file then txt file
158 // when we receive txt, we have both files
159 // and we can convert it to .csv
160 if (file_path.endsWith(".dbt") == true) {
161 QString name =
162 file_path.section('/', -1); // remove path for displaying on combobox
163 csv_combo->addItem(name.replace(QString(".dbt"), QString(".csv")));
164 file_names->append(file_path.replace(QString(".dbt"), QString(".csv")));
165 }
166
167 if (file_path.endsWith(".txt") == true) {
168 dbt2csv(file_path.replace(QString(".txt"), QString(".dbt")));
169 }
170}
171
172void file_ui::endOfFiles(void) {
173 ok_button->setEnabled(true);
174
175 qint64 max_file_size = 0;
176 for (int i = 0; i < file_names->count(); i++) {
177 QFileInfo info(file_names->at(i));
178 if (info.size() > max_file_size) {
179 max_file_size = info.size();
180 csv_combo->setCurrentIndex(i+1); // first item of combobox is already taken
181 }
182 }
183}
184
185void file_ui::dbt2csv(QString file_path) {
186 hdfile_t *dbtFile = NULL;
187 char *data;
188 QStringList data_type;
189
190 QString filename =file_path.section('/', -1); // remove path for displaying on logs
191 appendToLog(QString("converting %1 to csv").arg(filename));
192
193 // open csv file
194 QString csv_filename = file_path;
195 csv_filename.replace(QString(".dbt"), QString(".csv"));
196 QFile csv_file(csv_filename);
197
198 if (!csv_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
199 appendToLog(" error opening csv file!");
200 return;
201 }
202 QTextStream out(&csv_file);
203
204 // open txt file
205 QString txt_filename = file_path;
206 txt_filename.replace(QString(".dbt"), QString(".txt"));
207 QFile txt_file(txt_filename);
208
209 if (!txt_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
210 appendToLog(" error opening txt file!");
211 return;
212 }
213
214 // read txt file
215 QTextStream txt_in(&txt_file);
216 txt_in.readLine(); // time us
217 txt_in.readLine(); // time ns
218 while (1) {
219 if (txt_in.atEnd() == true)
220 break;
221 QString txt_line = txt_in.readLine();
222 data_type.append(txt_line.section("(",-1)); // on part de la fin pour trouver la premiere parenthese ouvrante
223 // fprintf(stderr,"type %s\n",txt_line.section("(",-1).toLocal8Bit().constData());
224 }
225 txt_file.close();
226
227 dbtFile = open_hdfile(file_path.toLocal8Bit().data(), READ_MODE);
228
229 if (!dbtFile) {
230 appendToLog(" error opening dbt file!");
231 return;
232 }
233 data = (char *)malloc(dbtFile->h.DataSize);
234 if (data == NULL) {
235 appendToLog(" error malloc!");
236 return;
237 }
238
239 bool dataWritten = false;
240 while (1) {
241 road_time_t time;
242 road_timerange_t tr = 0;
243 int offset = 0;
244 QTextStream csv_line;
245
246 if (read_hdfile(dbtFile, (void *)data, &time, &tr) == 0) {
247 break;
248 }
249 dataWritten = true;
250
251 out << time << "," << tr;
252 for (int i = 0; i < data_type.size(); i++) {
253 if (data_type.at(i) == "double)") {
254 double *value = (double *)(data + offset);
255 offset += sizeof(double);
256 out << "," << *value;
257 } else if (data_type.at(i) == "float)") {
258 float *value = (float *)(data + offset);
259 offset += sizeof(float);
260 out << "," << *value;
261 } else if (data_type.at(i) == "int8_t)") {
262 int8_t *value = (int8_t *)(data + offset);
263 offset += sizeof(int8_t);
264 out << "," << *value;
265 } else if (data_type.at(i) == "uint8_t)") {
266 uint8_t *value = (uint8_t *)(data + offset);
267 offset += sizeof(uint8_t);
268 out << "," << *value;
269 } else if (data_type.at(i) == "int16_t)") {
270 int16_t *value = (int16_t *)(data + offset);
271 offset += sizeof(int16_t);
272 out << "," << *value;
273 } else if (data_type.at(i) == "uint16_t)") {
274 uint16_t *value = (uint16_t *)(data + offset);
275 offset += sizeof(uint16_t);
276 out << "," << *value;
277 } else {
278 appendToLog(QString(" unhandled type: %1").arg(data_type.at(i)));
279 }
280 }
281
282 out << "\n";
283 }
284
285 if (!dataWritten) {
286 // empty file!
287 out << "0,0"; // timr
288 for (int i = 0; i < data_type.size(); i++) {
289 out << ",0";
290 }
291 out << "\n";
292 }
293
294 csv_file.close();
295 close_hdfile(dbtFile);
296 if (data != NULL)
297 free(data);
298
299 appendToLog(" ok");
300}
301
302void file_ui::clearInputText(void) {
303 if (input_cleared == false) {
304 input_cleared = true;
305 input_text->clear();
306 }
307}
308
309void file_ui::save(void) {
310 save_comment();
311 if (csv_combo->currentIndex() != 0) {
312 save_csv();
313 save_txt();
314 }
315
316 emit finished();
317}
318
319void file_ui::save_comment(void) {
320 QString folder_name = file_names->at(0).section('/', 0, -2);
321
322 QString filename = folder_name + "/commentaire.txt";
323 QFile file(filename);
324 if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
325 fprintf(stderr,"file_ui::save_comment: erreur ouverture fichier %s\n",
326 filename.toLocal8Bit().constData());
327 QTextStream out(&file);
328
329 out << input_text->toPlainText();
330 file.close();
331}
332
333void file_ui::save_csv(void) {
334 // global csv file
335 QString folder_name = file_names->at(0).section('/', 0, -2);
336 QString filename = folder_name + "/all_logs.csv";
337 QFile global_file(filename);
338 if (!global_file.open(QIODevice::WriteOnly | QIODevice::Text))
339 fprintf(stderr,"file_ui::save_csv: erreur ouverture fichier %s\n",
340 filename.toLocal8Bit().constData());
341 QTextStream out(&global_file);
342
343 // reference csv file
344 filename = file_names->at(csv_combo->currentIndex() - 1);
345 QFile ref_file(filename);
346 // fprintf(stderr,"file_ui::save_csv: ref %s\n",filename.toLocal8Bit().constData());
347 if (!ref_file.open(QIODevice::ReadOnly | QIODevice::Text))
348 fprintf(stderr,"file_ui::save_csv: erreur ouverture ficher %s\n",
349 filename.toLocal8Bit().constData());
350
351 // other csv files
352 int j = 0;
353 QFile m_file[file_names->count() - 1];
354 QTextStream m_in[file_names->count() - 1];
355 for (int i = 0; i < file_names->count(); i++) {
356 if (i == csv_combo->currentIndex() - 1)
357 continue;
358 filename = file_names->at(i);
359 m_file[j].setFileName(filename);
360 if (!m_file[j].open(QIODevice::ReadOnly | QIODevice::Text))
361 fprintf(stderr,"file_ui::save_csv: erreur ouverture ficher %s\n",
362 filename.toLocal8Bit().constData());
363 m_in[j].setDevice(&m_file[j]);
364 j++;
365 }
366
367 // init
368 QTextStream ref_in(&ref_file);
369 QString m_line[file_names->count() - 1];
370 QString m_line_prev[file_names->count() - 1];
371 for (int i = 0; i < file_names->count() - 1; i++) {
372 m_line[i] = m_in[i].readLine();
373 m_line_prev[i] = m_line[i];
374 }
375
376 // organize csv files in one file
377 while (1) {
378 if (ref_in.atEnd() == true)
379 break;
380 QString ref_line = ref_in.readLine();
381
382 qint64 ref_us = ref_line.section(',', 0, 0).toLongLong();
383 int ref_ns = ref_line.section(',', 1, 1).toInt();
384 // fprintf(stderr,"ref %lld %i\n",ref_us,ref_ns);
385
386 for (int i = 0; i < file_names->count() - 1; i++) {
387 qint64 csv_us = m_line[i].section(',', 0, 0).toLongLong();
388 int csv_ns = m_line[i].section(',', 1, 1).toInt();
389 // fprintf(stderr,"m %lld %i\n",csv_us,csv_ns);
390
391 while (is_greater(ref_us, csv_us, ref_ns, csv_ns) == true) {
392 m_line_prev[i] = m_line[i];
393 if (m_in[i].atEnd() == true)
394 break;
395 m_line[i] = m_in[i].readLine();
396 csv_us = m_line[i].section(',', 0, 0).toLongLong();
397 csv_ns = m_line[i].section(',', 1, 1).toInt();
398 // fprintf(stderr,"m %lld %i\n",csv_us,csv_ns);
399 }
400 csv_us = m_line_prev[i].section(',', 0, 0).toLongLong();
401 csv_ns = m_line_prev[i].section(',', 1, 1).toInt();
402 // fprintf(stderr,"m ok %lld %i\n",csv_us,csv_ns);
403
404 ref_line += "," + m_line_prev[i].section(',', 2);
405 }
406
407 out << ref_line << "\n";
408 }
409
410 global_file.close();
411 ref_file.close();
412 for (int i = 0; i < file_names->count() - 1; i++)
413 m_file[i].close();
414}
415
416void file_ui::save_txt(void) {
417 // global txt file
418 QString folder_name = file_names->at(0).section('/', 0, -2);
419 QString filename = folder_name + "/all_logs.txt";
420 QFile global_file(filename);
421 if (!global_file.open(QIODevice::WriteOnly | QIODevice::Text))
422 fprintf(stderr,"file_ui::save_txt: erreur ouverture ficher %s\n",
423 filename.toLocal8Bit().constData());
424 QTextStream out(&global_file);
425
426 // reference txt file
427 filename = file_names->at(csv_combo->currentIndex() - 1);
428 filename.replace(QString(".csv"), QString(".txt"));
429 QFile ref_file(filename);
430 if (!ref_file.open(QIODevice::ReadOnly | QIODevice::Text))
431 fprintf(stderr,"file_ui::save_txt: erreur ouverture ficher %s\n",
432 filename.toLocal8Bit().constData());
433
434 QTextStream ref_in(&ref_file);
435 QString current_line = ref_in.readLine();
436 int nb_lines = 1;
437 while (current_line != NULL) {
438 out << current_line << "\n";
439 ;
440 current_line = ref_in.readLine();
441 nb_lines++;
442 }
443
444 // other txt files
445 for (int i = 0; i < file_names->count(); i++) {
446 if (i == csv_combo->currentIndex() - 1)
447 continue;
448 filename = file_names->at(i);
449 filename.replace(QString(".csv"), QString(".txt"));
450 QFile txt_file(filename);
451 if (!txt_file.open(QIODevice::ReadOnly | QIODevice::Text))
452 fprintf(stderr,"file_ui::save_txt: erreur ouverture ficher %s\n",
453 filename.toLocal8Bit().constData());
454 QTextStream txt_in(&txt_file);
455 txt_in.readLine(); // time us
456 txt_in.readLine(); // time ns
457 current_line = txt_in.readLine();
458 while (current_line != NULL) {
459 out << nb_lines << ":" << current_line.section(':', 1) << "\n";
460 ;
461 current_line = txt_in.readLine();
462 nb_lines++;
463 }
464 txt_file.close();
465 }
466 global_file.close();
467 ref_file.close();
468}
469
470bool file_ui::is_greater(qint64 ref_us, qint64 csv_us, int ref_ns, int csv_ns) {
471 if (ref_us == csv_us) {
472 if (ref_ns > csv_ns) {
473 return true;
474 } else {
475 return false;
476 }
477 }
478 if (ref_us > csv_us) {
479 return true;
480 } else {
481 return false;
482 }
483}
Note: See TracBrowser for help on using the repository browser.