You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
20 KiB

2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "mainwindow.h"
  2. #include <QDateTime>
  3. #include <QMessageBox>
  4. #include <QtConcurrent>
  5. #include <QtSerialPort/QSerialPort>
  6. #include <QtSerialPort/QSerialPortInfo>
  7. #include "./ui_mainwindow.h"
  8. #include "electrocardiograph_tester.hpp"
  9. #include "logger.hpp"
  10. #include "qt_serial_datachannel.hpp"
  11. #include "widgetplot2d.h"
  12. #include "zexception.hpp"
  13. WidgetPlot2D *wp2d;
  14. using namespace std;
  15. using namespace iflytop;
  16. typedef enum {
  17. kone_lead_ecg,
  18. kthree_lead_ecg,
  19. kone_lead_ecg_v2,
  20. } device_type_t;
  21. static MainWindow *m_mainWindow;
  22. static QTDataChannel G_QTDataChannel;
  23. static device_type_t m_devicetype;
  24. #define TAG "MainWindow"
  25. static const char *fmt(const char *fmt, ...) {
  26. va_list args;
  27. va_start(args, fmt);
  28. static char buf[1024] = {0};
  29. vsnprintf(buf, sizeof(buf), fmt, args);
  30. va_end(args);
  31. return buf;
  32. }
  33. void MainWindow::log_output(QtMsgType type, const QMessageLogContext &context, const QString &msg) {}
  34. void MainWindow::doinui_slot(QFunction func) {
  35. if (func.get()) func.get()();
  36. }
  37. void MainWindow::instructionPreviewShow(const char *fmt, ...) {
  38. va_list args;
  39. va_start(args, fmt);
  40. char buf[1024] = {0};
  41. vsnprintf(buf, sizeof(buf), fmt, args);
  42. va_end(args);
  43. QString text(buf);
  44. QString info;
  45. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  46. info.append(" |");
  47. info.append(text);
  48. emit doinui_signal(QFunction([this, info]() { ui->instructionPreview->append(info); }));
  49. }
  50. void MainWindow::instructionPreviewClear() { ui->instructionPreview->document()->clear(); }
  51. void MainWindow::reportPreviewShow(const char *fmt, ...) {
  52. va_list args;
  53. va_start(args, fmt);
  54. char buf[1024] = {0};
  55. vsnprintf(buf, sizeof(buf), fmt, args);
  56. va_end(args);
  57. QString text(buf);
  58. QString info;
  59. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  60. info.append(text);
  61. emit doinui_signal(QFunction([this, info]() {
  62. if (ui->reportPreview->document()->lineCount() > 1000) {
  63. ui->reportPreview->document()->clear();
  64. }
  65. ui->reportPreview->append(info);
  66. }));
  67. }
  68. void MainWindow::blockDataUploadPreviewShow(const char *fmt, ...) {
  69. va_list args;
  70. va_start(args, fmt);
  71. char buf[1024] = {0};
  72. vsnprintf(buf, sizeof(buf), fmt, args);
  73. va_end(args);
  74. QString text(buf);
  75. QString info;
  76. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz "));
  77. info.append(text);
  78. emit doinui_signal(QFunction([this, info]() {
  79. if (ui->uploadDataPreview->document()->lineCount() > 1000) {
  80. ui->uploadDataPreview->document()->clear();
  81. }
  82. ui->uploadDataPreview->append(info);
  83. }));
  84. }
  85. void MainWindow::rawDataPreviewShow(const char *fmt, ...) {
  86. va_list args;
  87. va_start(args, fmt);
  88. char buf[1024] = {0};
  89. vsnprintf(buf, sizeof(buf), fmt, args);
  90. va_end(args);
  91. QString text(buf);
  92. QString info;
  93. info.append(QDateTime::currentDateTime().toString("hh:mm:ss.zzz"));
  94. info.append(text);
  95. emit doinui_signal(QFunction([this, info]() {
  96. if (ui->rawDataPreview->document()->lineCount() > 1000) {
  97. ui->rawDataPreview->document()->clear();
  98. }
  99. ui->rawDataPreview->append(info);
  100. }));
  101. }
  102. // uploadDataPreview
  103. #pragma pack(push, 1)
  104. typedef struct {
  105. uint16_t header;
  106. int16_t wave1;
  107. int16_t wave2;
  108. int16_t wave3;
  109. int16_t wave4;
  110. int16_t wave5;
  111. uint8_t check;
  112. uint16_t tail;
  113. } Wave_t;
  114. #pragma pack(pop)
  115. void MainWindow::displayInfo(bool suc, QString info) {}
  116. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  117. /*******************************************************************************
  118. * QT初始化 *
  119. *******************************************************************************/
  120. ui->setupUi(this);
  121. m_mainWindow = this;
  122. qRegisterMetaType<int32_t>("int32_t");
  123. qRegisterMetaType<uint32_t>("uint32_t");
  124. qRegisterMetaType<float>("float");
  125. qRegisterMetaType<function<void()>>("function<void()>");
  126. qRegisterMetaType<QFunction>("QFunction");
  127. connect(this, SIGNAL(doinui_signal(QFunction)), this, SLOT(doinui_slot(QFunction)));
  128. // qInstallMessageHandler(log_output);
  129. wp2d = new WidgetPlot2D();
  130. wp2d->initGraphName(QStringList() << "心电");
  131. /*******************************************************************************
  132. * *
  133. *******************************************************************************/
  134. constructUI();
  135. /*******************************************************************************
  136. * *
  137. *******************************************************************************/
  138. G_QTDataChannel.init();
  139. ElectrocardiographTester::ins()->initialize(&G_QTDataChannel);
  140. }
  141. MainWindow::~MainWindow() { delete ui; }
  142. /*******************************************************************************
  143. * UI相关构造 *
  144. *******************************************************************************/
  145. void MainWindow::constructUI() {
  146. /*******************************************************************************
  147. * UI *
  148. *******************************************************************************/
  149. {
  150. const auto infos = QSerialPortInfo::availablePorts();
  151. for (const QSerialPortInfo &info : infos) {
  152. ui->serialPortCB->addItem(info.portName());
  153. }
  154. }
  155. ui->serialBaudrateCB->addItem("9600");
  156. ui->serialBaudrateCB->addItem("14400");
  157. ui->serialBaudrateCB->addItem("19200");
  158. ui->serialBaudrateCB->addItem("38400");
  159. ui->serialBaudrateCB->addItem("57600");
  160. ui->serialBaudrateCB->addItem("115200");
  161. ui->serialBaudrateCB->addItem("460800");
  162. ui->serialBaudrateCB->addItem("500000");
  163. ui->serialBaudrateCB->setCurrentIndex(6);
  164. connect(ui->serialPortRefreshKey, &QPushButton::clicked, this, [this](bool check) {
  165. ui->serialPortCB->clear();
  166. const auto infos = QSerialPortInfo::availablePorts();
  167. for (const QSerialPortInfo &info : infos) {
  168. ui->serialPortCB->addItem(info.portName());
  169. }
  170. });
  171. connect(ui->serialOpenKey, &QPushButton::clicked, this, [=](bool check) {
  172. // 打开串口
  173. if (ui->serialOpenKey->text() == "打开") {
  174. G_QTDataChannel.setPortName(ui->serialPortCB->currentText().toStdString());
  175. G_QTDataChannel.setBaudRate(ui->serialBaudrateCB->currentText().toInt());
  176. G_QTDataChannel.setDataBits(QSerialPort::Data8);
  177. G_QTDataChannel.setParity(QSerialPort::NoParity);
  178. G_QTDataChannel.setFlowControl(QSerialPort::NoFlowControl);
  179. G_QTDataChannel.setStopBits(QSerialPort::OneStop);
  180. if (!G_QTDataChannel.open()) {
  181. QMessageBox::about(NULL, "提示", "串口无法打开,串口不存在或已被占??");
  182. return;
  183. }
  184. ui->serialOpenKey->setText("关闭");
  185. // 下拉菜单控件使能
  186. ui->serialBaudrateCB->setEnabled(false);
  187. ui->serialPortCB->setEnabled(false);
  188. ui->serialPortRefreshKey->setEnabled(false);
  189. } else {
  190. G_QTDataChannel.close();
  191. ui->serialOpenKey->setText("打开");
  192. ui->serialBaudrateCB->setEnabled(true);
  193. ui->serialPortCB->setEnabled(true);
  194. ui->serialPortRefreshKey->setEnabled(true);
  195. }
  196. });
  197. /*******************************************************************************
  198. * UI *
  199. *******************************************************************************/
  200. {
  201. ui->deviceType->addItem("单导联一代(M1001)");
  202. ui->deviceType->addItem("三导联一代(M1002)");
  203. ui->deviceType->addItem("单导联二代(M1003)");
  204. ui->deviceType->setCurrentIndex(0);
  205. connect(ui->deviceType, &QComboBox::currentTextChanged, this, [this](const QString &text) {
  206. if (text == "单导联一代(M1001)") {
  207. m_devicetype = kone_lead_ecg;
  208. } else if (text == "三导联一代(M1002)") {
  209. m_devicetype = kthree_lead_ecg;
  210. } else if (text == "单导联二代(M1003)") {
  211. m_devicetype = kone_lead_ecg_v2;
  212. }
  213. });
  214. }
  215. // 事件填充
  216. ElectrocardiographTester::ins()->regReportCB([this](bool checkok, ify_hrs_packet_t *report_packet, size_t len) {
  217. int reportType = report_packet->cmd;
  218. switch (reportType) {
  219. case ify_hrs_report_heartrate_data: {
  220. heartrate_report_packet_t *heartrate_report = (heartrate_report_packet_t *)report_packet;
  221. if (m_devicetype == kone_lead_ecg) {
  222. static uint32_t lastpacket_index = 0;
  223. static uint32_t lostpacket = 0;
  224. if ((lastpacket_index + 5) != (heartrate_report->sample_data_index)) {
  225. lostpacket++;
  226. }
  227. lastpacket_index = heartrate_report->sample_data_index;
  228. reportPreviewShow("[preview data ] lost:%d index %d", lostpacket, heartrate_report->sample_data_index);
  229. if (checkok) {
  230. uint16_t data0 = (uint16_t)(heartrate_report->data[0]) + ((uint16_t)heartrate_report->data[1] << 8);
  231. uint16_t data1 = (uint16_t)(heartrate_report->data[2]) + ((uint16_t)heartrate_report->data[3] << 8);
  232. uint16_t data2 = (uint16_t)(heartrate_report->data[4]) + ((uint16_t)heartrate_report->data[5] << 8);
  233. uint16_t data3 = (uint16_t)(heartrate_report->data[6]) + ((uint16_t)heartrate_report->data[7] << 8);
  234. uint16_t data4 = (uint16_t)(heartrate_report->data[8]) + ((uint16_t)heartrate_report->data[9] << 8);
  235. emit doinui_signal(QFunction([this, data0, data1, data2, data3, data4]() { //
  236. wp2d->addData("心电", data0, 0);
  237. wp2d->addData("心电", data1, 2);
  238. wp2d->addData("心电", data2, 4);
  239. wp2d->addData("心电", data3, 6);
  240. wp2d->addData("心电", data4, 8);
  241. // wp2d->addData("心电", data2);
  242. // wp2d->addData("心电", data3);
  243. // wp2d->addData("心电", data4);
  244. }));
  245. }
  246. } else if (m_devicetype == kthree_lead_ecg) {
  247. } else if (m_devicetype == kone_lead_ecg_v2) {
  248. if (checkok) {
  249. uint32_t packetlen = len - sizeof(heartrate_report_packet_t);
  250. static uint32_t lastpacket_index = 0;
  251. static uint32_t lostpacket = 0;
  252. if ((lastpacket_index + 50) != (heartrate_report->sample_data_index)) {
  253. lostpacket++;
  254. }
  255. lastpacket_index = heartrate_report->sample_data_index;
  256. reportPreviewShow("[preview data ] lost:%d index %d %d", lostpacket, heartrate_report->sample_data_index, packetlen);
  257. int32_t *frame = (int32_t *)heartrate_report->data;
  258. for (int i = 0; i < 50; i++) {
  259. int32_t data = frame[i];
  260. int32_t frameIndex = heartrate_report->sample_data_index + i;
  261. emit doinui_signal(QFunction([this, data, frameIndex]() { wp2d->addData("心电", data, frameIndex); }));
  262. }
  263. }
  264. }
  265. break;
  266. }
  267. case ify_hrs_report_battery_level: {
  268. reportPreviewShow("[battery_level ]");
  269. break;
  270. }
  271. case ify_hrs_report_low_battey_level: {
  272. reportPreviewShow("[low_battey ]");
  273. break;
  274. }
  275. case ify_hrs_report_sample_finish_end: {
  276. reportPreviewShow("[sample_finish ]");
  277. break;
  278. }
  279. case ify_hrs_report_sensor_drop_detect: {
  280. sensor_drop_event_report_packet_t *sensor_drop_report = (sensor_drop_event_report_packet_t *)report_packet->data;
  281. reportPreviewShow("[sensor_drop ] %s %s", zhex2binary(sensor_drop_report->drop_state0).c_str(), zhex2binary(sensor_drop_report->drop_state1).c_str());
  282. break;
  283. }
  284. case ify_hrs_report_record_upload_end: {
  285. uint32_t checksum = *(uint32_t *)report_packet->data;
  286. reportPreviewShow("[upload end ] checksum: 0x%08x", checksum);
  287. break;
  288. }
  289. default:
  290. break;
  291. }
  292. });
  293. ElectrocardiographTester::ins()->regCh4CheckSumPacketReport([this](uint32_t rxcnt, uint32_t report_packet_checksum) { //
  294. blockDataUploadPreviewShow("RXCNT %d CHECKSUM 0x%08x", rxcnt, report_packet_checksum);
  295. });
  296. ElectrocardiographTester::ins()->regRawDataCB([this](raw_data_type_t type, uint8_t *hex, uint32_t hexlen) {
  297. if (type == kcmd_cmd) {
  298. rawDataPreviewShow("[CMD ] %s", zhex2str(hex, hexlen).c_str());
  299. } else if (type == kcmd_receipt) {
  300. rawDataPreviewShow("[RECEIPT] %s", zhex2str(hex, hexlen).c_str());
  301. } else if (type == kcmd_report) {
  302. rawDataPreviewShow("[REPORT ] %s", zhex2str(hex, hexlen).c_str());
  303. } else if (type == kcmd_ch4_data) {
  304. // rawDataPreviewShow("[CH4 ] %s", zhex2str(hex, hexlen).c_str());
  305. }
  306. });
  307. }
  308. void MainWindow::processException(zexception &e) { instructionPreviewShow("%s:%s", e.what(), hrs_ecode2str((ify_hrs_error_code_t)e.ecode())); }
  309. void MainWindow::on_readDeviceVersion_clicked() {
  310. instructionPreviewClear();
  311. try {
  312. device_version_info_receipt_t version;
  313. ElectrocardiographTester::ins()->readDeviceVersion(&version);
  314. instructionPreviewShow("-------------- version ----------------");
  315. instructionPreviewShow(" blestack_version: %d", version.blestack_version);
  316. instructionPreviewShow(" bootloader_version: %d", version.bootloader_version);
  317. instructionPreviewShow(" firmware_version: %d", version.firmware_version);
  318. instructionPreviewShow(" hardware_version: %d", version.hardware_version);
  319. } catch (zexception &exception) {
  320. processException(exception);
  321. }
  322. }
  323. void MainWindow::on_readDeviceState_clicked() {
  324. instructionPreviewClear();
  325. try {
  326. device_state_receipt_t state;
  327. ElectrocardiographTester::ins()->readDeviceState(&state);
  328. instructionPreviewShow("-------------- state ----------------");
  329. instructionPreviewShow(" drop_state0: %s", zhex2binary(state.drop_state0).c_str());
  330. instructionPreviewShow(" drop_state1: %s", zhex2binary(state.drop_state1).c_str());
  331. instructionPreviewShow(" sampling_state: %d", state.device_state0.sampling_state);
  332. instructionPreviewShow(" report_state: %d", state.device_state0.report_state);
  333. instructionPreviewShow(" low_battery: %d", state.device_state0.low_battery);
  334. instructionPreviewShow(" full_storge: %d", state.device_state0.full_storge);
  335. instructionPreviewShow(" holder: %d", state.device_state0.holder);
  336. instructionPreviewShow(" powerlevel: %d", state.powerlevel);
  337. instructionPreviewShow(" storage_item_num: %d", state.storage_item_num);
  338. } catch (zexception &exception) {
  339. processException(exception);
  340. }
  341. }
  342. void MainWindow::on_readTime_clicked() {
  343. instructionPreviewClear();
  344. try {
  345. read_time_receipt_t time;
  346. ElectrocardiographTester::ins()->readTime(&time);
  347. instructionPreviewShow("-------------- time ----------------");
  348. instructionPreviewShow(" %d/%d/%d %d:%d:%d", time.year + 2000, time.month, time.day, time.hour, time.minute, time.second);
  349. } catch (zexception &exception) {
  350. processException(exception);
  351. }
  352. }
  353. void MainWindow::on_syncTime_clicked() {
  354. instructionPreviewClear();
  355. try {
  356. // 获取系统时间
  357. QDateTime now = QDateTime::currentDateTime();
  358. ElectrocardiographTester::ins()->syncTime(now.date().year() - 2000, now.date().month(), now.date().day(), now.time().hour(), now.time().minute(), now.time().second());
  359. instructionPreviewShow("sync time success!");
  360. } catch (zexception &exception) {
  361. processException(exception);
  362. }
  363. }
  364. std::string zhex2time(const uint8_t *hex, size_t len) {
  365. std::string str;
  366. if (len < 6) return str;
  367. str.append(fmt("%d/%d/%d %2d:%2d:%2d", hex[0] + 2000, hex[1], hex[2], hex[3], hex[4], hex[5]));
  368. return str;
  369. }
  370. void MainWindow::on_readAllRecords_clicked() {
  371. // 读取当前有多少条记录
  372. instructionPreviewClear();
  373. try {
  374. device_state_receipt_t state;
  375. ElectrocardiographTester::ins()->readDeviceState(&state);
  376. instructionPreviewShow("index recordid frameNum dataSize sensorNum captRate captPrec compAlgo checksum");
  377. for (int32_t i = 0; i < state.storage_item_num; i++) {
  378. read_record_info_receipt_t record;
  379. ElectrocardiographTester::ins()->readRecordsInfo(i, &record);
  380. instructionPreviewShow("%d %s %8d %8d %8d %8d %8d %8d 0x%08x", i, zhex2time(record.record_id, 6).c_str(), record.frameNum, record.dataSize, record.sensorNum, record.captureRate, record.capturePrecision, record.compressAlgorithm, record.checksum);
  381. }
  382. } catch (zexception &exception) {
  383. processException(exception);
  384. }
  385. }
  386. void MainWindow::on_startUploadRecord_clicked() {
  387. instructionPreviewClear();
  388. int reportIndex = ui->startUploadRecord_p0->toPlainText().toInt();
  389. try {
  390. read_record_info_receipt_t record;
  391. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  392. ElectrocardiographTester::ins()->startUploadRecord(record.record_id);
  393. instructionPreviewShow("start upload record [%s] success", zhex2time(record.record_id, 6).c_str());
  394. } catch (zexception &exception) {
  395. processException(exception);
  396. }
  397. }
  398. void MainWindow::on_readSensorInfo_clicked() {
  399. instructionPreviewClear();
  400. try {
  401. sensor_info_receipt_t sensor;
  402. ElectrocardiographTester::ins()->readSensorInfo(&sensor);
  403. instructionPreviewShow("-------------- sensor ----------------");
  404. instructionPreviewShow(" sensor_num: %d", sensor.sensor_num);
  405. instructionPreviewShow(" sensor_precision: %d", sensor.sensor_precision);
  406. instructionPreviewShow(" sensor_sample_rate:%d", sensor.sensor_sample_rate);
  407. instructionPreviewShow(" sensor0_pos: %d", sensor.sensor0_pos);
  408. instructionPreviewShow(" sensor1_pos: %d", sensor.sensor1_pos);
  409. instructionPreviewShow(" sensor2_pos: %d", sensor.sensor2_pos);
  410. } catch (zexception &exception) {
  411. processException(exception);
  412. }
  413. }
  414. void MainWindow::on_readSN_clicked() {
  415. instructionPreviewClear();
  416. try {
  417. string sn;
  418. ElectrocardiographTester::ins()->readSn(sn);
  419. instructionPreviewShow("-------------- sn ----------------");
  420. instructionPreviewShow(" sn: %s", sn.c_str());
  421. } catch (zexception &exception) {
  422. processException(exception);
  423. }
  424. }
  425. void MainWindow::on_stopUploadRecord_clicked() {
  426. instructionPreviewClear();
  427. try {
  428. ElectrocardiographTester::ins()->stopUploadRecord();
  429. instructionPreviewShow("stop upload record success");
  430. } catch (zexception &exception) {
  431. processException(exception);
  432. }
  433. }
  434. void MainWindow::on_delRecord_clicked() {
  435. instructionPreviewClear();
  436. int reportIndex = ui->delRecord_p0->toPlainText().toInt();
  437. try {
  438. read_record_info_receipt_t record;
  439. ElectrocardiographTester::ins()->readRecordsInfo(reportIndex, &record);
  440. ElectrocardiographTester::ins()->delRecord(record.record_id);
  441. instructionPreviewShow("delete record [%s] success", zhex2time(record.record_id, 6).c_str());
  442. } catch (zexception &exception) {
  443. processException(exception);
  444. }
  445. }
  446. void MainWindow::on_startCapture_clicked() {
  447. instructionPreviewClear();
  448. try {
  449. ElectrocardiographTester::ins()->startCapture();
  450. instructionPreviewShow("start capture success");
  451. } catch (zexception &exception) {
  452. processException(exception);
  453. }
  454. }
  455. void MainWindow::on_stopCapture_clicked() {
  456. instructionPreviewClear();
  457. try {
  458. ElectrocardiographTester::ins()->stopCapture();
  459. instructionPreviewShow("stop capture success");
  460. } catch (zexception &exception) {
  461. processException(exception);
  462. }
  463. }
  464. void MainWindow::on_startRealtimeReport_clicked() {
  465. instructionPreviewClear();
  466. try {
  467. ElectrocardiographTester::ins()->startRealtimeReport();
  468. instructionPreviewShow("start realtime report success");
  469. wp2d->show();
  470. } catch (zexception &exception) {
  471. processException(exception);
  472. }
  473. }
  474. void MainWindow::on_stopRealtimeReport_clicked() {
  475. instructionPreviewClear();
  476. try {
  477. ElectrocardiographTester::ins()->stopRealtimeReport();
  478. instructionPreviewShow("stop realtime report success");
  479. wp2d->hide();
  480. } catch (zexception &exception) {
  481. processException(exception);
  482. }
  483. }
  484. void MainWindow::on_clearPreview_clicked() {
  485. ui->reportPreview->document()->clear();
  486. ui->uploadDataPreview->document()->clear();
  487. ui->rawDataPreview->document()->clear();
  488. ui->instructionPreview->document()->clear();
  489. }