From e05af1d83092b0c94c0ade9e8ec4ecad1d80cec2 Mon Sep 17 00:00:00 2001 From: Alex Spataru Date: Sat, 4 Jan 2025 23:42:31 -0500 Subject: [PATCH] Add option to export real-time console data (@AnnabellePundaky) --- app/CMakeLists.txt | 4 +- app/qml/MainWindow/Panes/Setup.qml | 81 +++++-- .../MainWindow/Panes/SetupPanes/Hardware.qml | 1 + app/qml/Widgets/Dashboard/Terminal.qml | 42 ---- app/src/CSV/Export.cpp | 38 ++-- app/src/CSV/Export.h | 1 - app/src/IO/Console.cpp | 84 +------ app/src/IO/Console.h | 7 - app/src/IO/ConsoleExport.cpp | 209 ++++++++++++++++++ app/src/IO/ConsoleExport.h | 79 +++++++ app/src/Misc/ModuleManager.cpp | 4 + 11 files changed, 369 insertions(+), 181 deletions(-) create mode 100644 app/src/IO/ConsoleExport.cpp create mode 100644 app/src/IO/ConsoleExport.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 6899cdee..567405f5 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -54,7 +54,6 @@ find_package( Bluetooth SerialPort Positioning - PrintSupport LinguistTools QuickControls2 ) @@ -98,6 +97,7 @@ set(SOURCES src/IO/Checksum.cpp src/IO/Console.cpp src/IO/Manager.cpp + src/IO/ConsoleExport.cpp src/IO/FileTransmission.cpp src/IO/FrameReader.cpp src/JSON/FrameParser.cpp @@ -145,6 +145,7 @@ set(HEADERS src/IO/Manager.h src/IO/HAL_Driver.h src/IO/Checksum.h + src/IO/ConsoleExport.h src/IO/CircularBuffer.h src/IO/FileTransmission.h src/IO/FrameReader.h @@ -223,7 +224,6 @@ target_link_libraries( Qt6::Bluetooth Qt6::SerialPort Qt6::Positioning - Qt6::PrintSupport Qt6::QuickControls2 simde diff --git a/app/qml/MainWindow/Panes/Setup.qml b/app/qml/MainWindow/Panes/Setup.qml index 3dc94b2f..02739d3d 100644 --- a/app/qml/MainWindow/Panes/Setup.qml +++ b/app/qml/MainWindow/Panes/Setup.qml @@ -67,11 +67,11 @@ Widgets.Pane { Settings { category: "SetupPanel" - property alias tabIndex: tab.currentIndex - property alias csvExport: csvLogging.checked - property alias driver: driverCombo.currentIndex property alias language: settings.language + property alias csvExport: csvLogging.checked property alias tcpPlugins: settings.tcpPlugins + property alias consoleExport: consoleLogging.checked + property alias selectedDriver: driverCombo.currentIndex } // @@ -122,7 +122,7 @@ Widgets.Pane { } // - // Device type selector + // Driver selection // Label { text: qsTr("Device Setup") + ":" @@ -140,23 +140,6 @@ Widgets.Pane { } } - // - // CSV generator - // - Switch { - id: csvLogging - Layout.leftMargin: -6 - text: qsTr("Create CSV File") - Layout.alignment: Qt.AlignLeft - checked: Cpp_CSV_Export.exportEnabled - palette.highlight: Cpp_ThemeManager.colors["csv_switch"] - - onCheckedChanged: { - if (Cpp_CSV_Export.exportEnabled !== checked) - Cpp_CSV_Export.exportEnabled = checked - } - } - // // Spacer // @@ -173,6 +156,7 @@ Widgets.Pane { color: Cpp_ThemeManager.colors["pane_section_label"] Component.onCompleted: font.capitalization = Font.AllUppercase } RadioButton { + Layout.leftMargin: -6 Layout.maximumHeight: 18 Layout.maximumWidth: root.maxItemWidth text: qsTr("No Parsing (Device Sends JSON Data)") @@ -183,6 +167,7 @@ Widgets.Pane { Cpp_JSON_FrameBuilder.operationMode = SerialStudio.DeviceSendsJSON } } RadioButton { + Layout.leftMargin: -6 Layout.maximumHeight: 18 Layout.maximumWidth: root.maxItemWidth text: qsTr("Quick Plot (Comma Separated Values)") @@ -193,6 +178,7 @@ Widgets.Pane { Cpp_JSON_FrameBuilder.operationMode = SerialStudio.QuickPlot } } RadioButton { + Layout.leftMargin: -6 Layout.maximumHeight: 18 Layout.maximumWidth: root.maxItemWidth text: qsTr("Parse via JSON Project File") @@ -225,6 +211,59 @@ Widgets.Pane { implicitHeight: 4 } + // + // Data export switches + // + Label { + text: qsTr("Data Export") + ":" + font: Cpp_Misc_CommonFonts.customUiFont(0.8, true) + color: Cpp_ThemeManager.colors["pane_section_label"] + Component.onCompleted: font.capitalization = Font.AllUppercase + } + + // + // CSV generator + // + CheckBox { + id: csvLogging + Layout.leftMargin: -6 + Layout.maximumHeight: 18 + text: qsTr("Create CSV File") + Layout.alignment: Qt.AlignLeft + checked: Cpp_CSV_Export.exportEnabled + Layout.maximumWidth: root.maxItemWidth + + onCheckedChanged: { + if (Cpp_CSV_Export.exportEnabled !== checked) + Cpp_CSV_Export.exportEnabled = checked + } + } + + // + // Console data export + // + CheckBox { + id: consoleLogging + Layout.leftMargin: -6 + Layout.maximumHeight: 18 + Layout.alignment: Qt.AlignLeft + text: qsTr("Export Console Data") + Layout.maximumWidth: root.maxItemWidth + checked: Cpp_IO_ConsoleExport.exportEnabled + + onCheckedChanged: { + if (Cpp_IO_ConsoleExport.exportEnabled !== checked) + Cpp_IO_ConsoleExport.exportEnabled = checked + } + } + + // + // Spacer + // + Item { + implicitHeight: 4 + } + // // Tab bar // diff --git a/app/qml/MainWindow/Panes/SetupPanes/Hardware.qml b/app/qml/MainWindow/Panes/SetupPanes/Hardware.qml index 00f39f53..506dd240 100644 --- a/app/qml/MainWindow/Panes/SetupPanes/Hardware.qml +++ b/app/qml/MainWindow/Panes/SetupPanes/Hardware.qml @@ -34,6 +34,7 @@ Item { // QtSettings.Settings { category: "DeviceSetup" + property alias serialDtr: serial.dtr property alias serialParity: serial.parity property alias serialBaudRate: serial.baudRate diff --git a/app/qml/Widgets/Dashboard/Terminal.qml b/app/qml/Widgets/Dashboard/Terminal.qml index 63e5da5e..d5321290 100644 --- a/app/qml/Widgets/Dashboard/Terminal.qml +++ b/app/qml/Widgets/Dashboard/Terminal.qml @@ -152,23 +152,6 @@ Item { text: qsTr("Clear") opacity: enabled ? 1 : 0.5 onTriggered: root.clear() - enabled: Cpp_IO_Console.saveAvailable - } - - MenuSeparator {} - - MenuItem { - opacity: enabled ? 1 : 0.5 - text: qsTr("Print") - enabled: Cpp_IO_Console.saveAvailable - onTriggered: Cpp_IO_Console.print() - } - - MenuItem { - opacity: enabled ? 1 : 0.5 - text: qsTr("Save as") + "..." - onTriggered: Cpp_IO_Console.save() - enabled: Cpp_IO_Console.saveAvailable } } @@ -421,30 +404,6 @@ Item { } } - Button { - icon.width: 18 - icon.height: 18 - implicitHeight: 24 - Layout.maximumWidth: 32 - opacity: enabled ? 1 : 0.5 - onClicked: Cpp_IO_Console.save() - enabled: Cpp_IO_Console.saveAvailable - icon.source: "qrc:/rcc/icons/buttons/save.svg" - icon.color: Cpp_ThemeManager.colors["button_text"] - } - - Button { - icon.width: 18 - icon.height: 18 - implicitHeight: 24 - Layout.maximumWidth: 32 - opacity: enabled ? 1 : 0.5 - onClicked: Cpp_IO_Console.print() - enabled: Cpp_IO_Console.saveAvailable - icon.source: "qrc:/rcc/icons/buttons/print.svg" - icon.color: Cpp_ThemeManager.colors["button_text"] - } - Button { icon.width: 18 icon.height: 18 @@ -452,7 +411,6 @@ Item { onClicked: root.clear() Layout.maximumWidth: 32 opacity: enabled ? 1 : 0.5 - enabled: Cpp_IO_Console.saveAvailable icon.source: "qrc:/rcc/icons/buttons/clear.svg" icon.color: Cpp_ThemeManager.colors["button_text"] } diff --git a/app/src/CSV/Export.cpp b/app/src/CSV/Export.cpp index 9aba40a1..13903df7 100644 --- a/app/src/CSV/Export.cpp +++ b/app/src/CSV/Export.cpp @@ -25,8 +25,8 @@ #include #include #include -#include #include +#include #include "IO/Manager.h" #include "CSV/Player.h" @@ -36,8 +36,8 @@ #include "JSON/FrameBuilder.h" /** - * Connect JSON Parser & Serial Manager signals to begin registering JSON - * dataframes into JSON list. + * Constructor function, configures the path in which Serial Studio shall + * automatically write generated CSV files. */ CSV::Export::Export() : m_exportEnabled(true) @@ -49,7 +49,7 @@ CSV::Export::Export() } /** - * Close file & finnish write-operations before destroying the class + * Close file & finnish write-operations before destroying the class. */ CSV::Export::~Export() { @@ -57,7 +57,7 @@ CSV::Export::~Export() } /** - * Returns a pointer to the only instance of this class + * Returns a pointer to the only instance of this class. */ CSV::Export &CSV::Export::instance() { @@ -66,7 +66,7 @@ CSV::Export &CSV::Export::instance() } /** - * Returns @c true if the CSV output file is open + * Returns @c true if the CSV output file is open. */ bool CSV::Export::isOpen() const { @@ -74,25 +74,13 @@ bool CSV::Export::isOpen() const } /** - * Returns @c true if CSV export is enabled + * Returns @c true if CSV export is enabled. */ bool CSV::Export::exportEnabled() const { return m_exportEnabled; } -/** - * Open the current CSV file in the Explorer/Finder window - */ -void CSV::Export::openCurrentCsv() -{ - if (isOpen()) - Misc::Utilities::revealFile(m_csvFile.fileName()); - else - Misc::Utilities::showMessageBox(tr("CSV file not open"), - tr("Cannot find CSV export file!")); -} - /** * Configures the signal/slot connections with the rest of the modules of the * application. @@ -108,7 +96,7 @@ void CSV::Export::setupExternalConnections() } /** - * Enables or disables data export + * Enables or disables data export. */ void CSV::Export::setExportEnabled(const bool enabled) { @@ -124,7 +112,7 @@ void CSV::Export::setExportEnabled(const bool enabled) } /** - * Write all remaining JSON frames & close the CSV file + * Write all remaining JSON frames & close the CSV file. */ void CSV::Export::closeFile() { @@ -238,8 +226,8 @@ CSV::Export::createCsvFile(const CSV::TimestampFrame &frame) const auto &rxTime = frame.rxDateTime; // Get file name - const auto fileName - = rxTime.toString(QStringLiteral("yyyy_MMM_dd HH_mm_ss")) + ".csv"; + const auto fileName = rxTime.toString(QStringLiteral("yyyy_MMM_dd HH_mm_ss")) + + QStringLiteral(".csv"); // Get path const QString path = QStringLiteral("%1/%2/").arg(m_csvPath, data.title()); @@ -247,7 +235,7 @@ CSV::Export::createCsvFile(const CSV::TimestampFrame &frame) // Generate file path if required QDir dir(path); if (!dir.exists()) - dir.mkpath("."); + dir.mkpath(QStringLiteral(".")); // Open file m_csvFile.setFileName(dir.filePath(fileName)); @@ -314,7 +302,7 @@ CSV::Export::createCsvFile(const CSV::TimestampFrame &frame) } /** - * Appends the latest frame from the device to the output buffer + * Appends the latest frame from the device to the output buffer. */ void CSV::Export::registerFrame(const JSON::Frame &frame) { diff --git a/app/src/CSV/Export.h b/app/src/CSV/Export.h index bf73fa60..5e82b69b 100644 --- a/app/src/CSV/Export.h +++ b/app/src/CSV/Export.h @@ -84,7 +84,6 @@ public: public slots: void closeFile(); - void openCurrentCsv(); void setupExternalConnections(); void setExportEnabled(const bool enabled); diff --git a/app/src/IO/Console.cpp b/app/src/IO/Console.cpp index f85f820e..86261b1d 100644 --- a/app/src/IO/Console.cpp +++ b/app/src/IO/Console.cpp @@ -20,17 +20,11 @@ */ #include -#include #include -#include -#include -#include #include "IO/Manager.h" #include "IO/Console.h" -#include "Misc/Utilities.h" #include "Misc/Translator.h" -#include "Misc/CommonFonts.h" /** * Generates a hexdump of the given data @@ -88,7 +82,7 @@ IO::Console::Console() , m_showTimestamp(false) , m_isStartingLine(true) , m_lastCharWasCR(false) - , m_textBuffer(1024 * 1024) + , m_textBuffer(10 * 1024) { clear(); } @@ -110,14 +104,6 @@ bool IO::Console::echo() const return m_echo; } -/** - * Returns @c true if data buffer contains information that the user can export. - */ -bool IO::Console::saveAvailable() const -{ - return m_textBuffer.size() > 0; -} - /** * Returns @c true if a timestamp should be shown before each displayed data * block. @@ -313,37 +299,6 @@ QByteArray IO::Console::hexToBytes(const QString &data) return array; } -/** - * Allows the user to export the information displayed on the console - */ -void IO::Console::save() -{ - // No data buffer received, abort - if (!saveAvailable()) - return; - - // Get file name - auto path = QFileDialog::getSaveFileName(nullptr, tr("Export Console Data"), - QDir::homePath(), - tr("Text Files") + " (*.txt)"); - - // Create file - if (!path.isEmpty()) - { - QFile file(path); - if (file.open(QFile::WriteOnly)) - { - file.write(m_textBuffer.peek(m_textBuffer.size())); - file.close(); - Misc::Utilities::revealFile(path); - } - - else - Misc::Utilities::showMessageBox(tr("Error while exporting console data"), - file.errorString()); - } -} - /** * Deletes all the text displayed by the current QML text document */ @@ -352,7 +307,6 @@ void IO::Console::clear() m_textBuffer.clear(); m_isStartingLine = true; m_lastCharWasCR = false; - Q_EMIT saveAvailableChanged(); } /** @@ -451,35 +405,6 @@ void IO::Console::send(const QString &data) Manager::instance().writeData(bin); } -/** - * Creates a text document with current console output & prints it using native - * system libraries/toolkits. - */ -void IO::Console::print() -{ - // Create text document - QTextDocument document; - document.setPlainText( - QString::fromUtf8(m_textBuffer.peek(m_textBuffer.size()))); - - // Set font - auto font = Misc::CommonFonts::instance().customMonoFont(0.8); - document.setDefaultFont(font); - - // Create printer object - QPrinter printer(QPrinter::PrinterResolution); - printer.setFullPage(true); - printer.setDocName(qApp->applicationDisplayName()); - printer.setPageOrientation(QPageLayout::Portrait); - - // Show print dialog - QPrintDialog printDialog(&printer, nullptr); - if (printDialog.exec() == QDialog::Accepted) - { - document.print(&printer); - } -} - /** * Enables/disables displaying a timestamp of each received data block. */ @@ -544,9 +469,6 @@ void IO::Console::append(const QString &string, const bool addTimestamp) if (string.isEmpty()) return; - // Check if we should update the save available feature - const bool previousSaveAvailable = saveAvailable(); - // Omit leading \n if a trailing \r was already rendered from previous payload auto data = string; if (m_lastCharWasCR && data.startsWith('\n')) @@ -606,10 +528,6 @@ void IO::Console::append(const QString &string, const bool addTimestamp) // Add data to saved text buffer m_textBuffer.append(processedString.toUtf8()); - // Update save avaialable - if (saveAvailable() != previousSaveAvailable) - Q_EMIT saveAvailableChanged(); - // Update UI QMetaObject::invokeMethod( this, [=] { Q_EMIT displayString(processedString); }, diff --git a/app/src/IO/Console.h b/app/src/IO/Console.h index 55588939..e7ed1366 100644 --- a/app/src/IO/Console.h +++ b/app/src/IO/Console.h @@ -48,9 +48,6 @@ class Console : public QObject READ showTimestamp WRITE setShowTimestamp NOTIFY showTimestampChanged) - Q_PROPERTY(bool saveAvailable - READ saveAvailable - NOTIFY saveAvailableChanged) Q_PROPERTY(IO::Console::DataMode dataMode READ dataMode WRITE setDataMode @@ -86,7 +83,6 @@ signals: void historyItemChanged(); void textDocumentChanged(); void showTimestampChanged(); - void saveAvailableChanged(); void displayString(const QString &text); private: @@ -123,7 +119,6 @@ public: static Console &instance(); [[nodiscard]] bool echo() const; - [[nodiscard]] bool saveAvailable() const; [[nodiscard]] bool showTimestamp() const; [[nodiscard]] DataMode dataMode() const; @@ -141,9 +136,7 @@ public: static QByteArray hexToBytes(const QString &data); public slots: - void save(); void clear(); - void print(); void historyUp(); void historyDown(); void setupExternalConnections(); diff --git a/app/src/IO/ConsoleExport.cpp b/app/src/IO/ConsoleExport.cpp new file mode 100644 index 00000000..bf2975b4 --- /dev/null +++ b/app/src/IO/ConsoleExport.cpp @@ -0,0 +1,209 @@ +/* + * Serial Studio - https://serial-studio.github.io/ + * + * Copyright (C) 2020-2025 Alex Spataru + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later OR Commercial + */ + +#include "ConsoleExport.h" + +#include +#include +#include +#include +#include +#include + +#include "IO/Console.h" +#include "IO/Manager.h" +#include "Misc/Utilities.h" +#include "Misc/TimerEvents.h" + +/** + * Constructor function, configures the path in which Serial Studio shall + * automatically write generated console log files. + */ +IO::ConsoleExport::ConsoleExport() + : m_exportEnabled(true) +{ + m_filePath = QStringLiteral("%1/%2/Console") + .arg(QStandardPaths::writableLocation( + QStandardPaths::DocumentsLocation), + qApp->applicationDisplayName()); +} + +/** + * Close file & finnish write-operations before destroying the class. + */ +IO::ConsoleExport::~ConsoleExport() +{ + closeFile(); +} + +/** + * Returns a pointer to the only instance of this class. + */ +IO::ConsoleExport &IO::ConsoleExport::instance() +{ + static ConsoleExport instance; + return instance; +} + +/** + * Returns @c true if the console output file is open. + */ +bool IO::ConsoleExport::isOpen() const +{ + return m_file.isOpen(); +} + +/** + * Returns @c true if console log export is enabled. + */ +bool IO::ConsoleExport::exportEnabled() const +{ + return m_exportEnabled; +} + +/** + * Write all remaining console data & close the output file. + */ +void IO::ConsoleExport::closeFile() +{ + if (isOpen()) + { + if (m_buffer.size() > 0) + writeData(); + + m_file.close(); + m_textStream.setDevice(nullptr); + + Q_EMIT openChanged(); + } +} + +/** + * Configures the signal/slot connections with the modules of the application + * that this module depends upon. + */ +void IO::ConsoleExport::setupExternalConnections() +{ + connect(&IO::Console::instance(), &IO::Console::displayString, this, + &IO::ConsoleExport::registerData); + connect(&IO::Manager::instance(), &IO::Manager::connectedChanged, this, + &IO::ConsoleExport::closeFile); + connect(&Misc::TimerEvents::instance(), &Misc::TimerEvents::timeout1Hz, this, + &IO::ConsoleExport::writeData); +} + +/** + * Enables or disables data export. + */ +void IO::ConsoleExport::setExportEnabled(const bool enabled) +{ + m_exportEnabled = enabled; + Q_EMIT enabledChanged(); + + if (!exportEnabled() && isOpen()) + { + m_buffer.clear(); + closeFile(); + } +} + +/** + * Writes current buffer data to the output file, and creates a new file + * if needed. + */ +void IO::ConsoleExport::writeData() +{ + // Device not connected, abort + if (!IO::Manager::instance().connected()) + return; + + // Export is disabled, abort + if (!exportEnabled()) + return; + + // Write data to the file + if (m_buffer.size() > 0) + { + // Create a new file if required + if (!isOpen()) + createFile(); + + // Write data to hard disk + if (m_textStream.device()) + { + m_textStream << m_buffer; + m_textStream.flush(); + m_buffer.clear(); + } + } +} + +/** + * Creates a new console log output file based on the current date/time. + */ +void IO::ConsoleExport::createFile() +{ + // Close current file (if any) + if (isOpen()) + closeFile(); + + // Get filename + const auto dateTime = QDateTime::currentDateTime(); + const auto fileName + = dateTime.toString(QStringLiteral("yyyy_MMM_dd HH_mm_ss")) + + QStringLiteral(".txt"); + + // Generate file path if required + QDir dir(m_filePath); + if (!dir.exists()) + dir.mkpath(QStringLiteral(".")); + + // Open file + m_file.setFileName(dir.filePath(fileName)); + if (!m_file.open(QIODeviceBase::WriteOnly | QIODevice::Text)) + { + Misc::Utilities::showMessageBox(tr("Console Output File Error"), + tr("Cannot open file for writing!")); + closeFile(); + return; + } + + // Configure text stream + m_textStream.setDevice(&m_file); + m_textStream.setGenerateByteOrderMark(true); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + m_textStream.setCodec("UTF-8"); +#else + m_textStream.setEncoding(QStringConverter::Utf8); +#endif + + // Emit signals + Q_EMIT openChanged(); +} + +/** + * Appends the given console data to the output buffer. + */ +void IO::ConsoleExport::registerData(const QString &data) +{ + if (!data.isEmpty() && exportEnabled()) + m_buffer.append(data); +} diff --git a/app/src/IO/ConsoleExport.h b/app/src/IO/ConsoleExport.h new file mode 100644 index 00000000..1b983c15 --- /dev/null +++ b/app/src/IO/ConsoleExport.h @@ -0,0 +1,79 @@ +/* + * Serial Studio - https://serial-studio.github.io/ + * + * Copyright (C) 2020-2025 Alex Spataru + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later OR Commercial + */ + +#pragma once + +#include +#include +#include + +namespace IO +{ +class ConsoleExport : public QObject +{ + // clang-format off + Q_OBJECT + Q_PROPERTY(bool isOpen + READ isOpen + NOTIFY openChanged) + Q_PROPERTY(bool exportEnabled + READ exportEnabled + WRITE setExportEnabled + NOTIFY enabledChanged) + // clang-format on + +signals: + void openChanged(); + void enabledChanged(); + +private: + explicit ConsoleExport(); + ConsoleExport(ConsoleExport &&) = delete; + ConsoleExport(const ConsoleExport &) = delete; + ConsoleExport &operator=(ConsoleExport &&) = delete; + ConsoleExport &operator=(const ConsoleExport &) = delete; + + ~ConsoleExport(); + +public: + static ConsoleExport &instance(); + + [[nodiscard]] bool isOpen() const; + [[nodiscard]] bool exportEnabled() const; + +public slots: + void closeFile(); + void setupExternalConnections(); + void setExportEnabled(const bool enabled); + +private slots: + void writeData(); + void createFile(); + void registerData(const QString &data); + +private: + QFile m_file; + QString m_buffer; + QString m_filePath; + bool m_exportEnabled; + QTextStream m_textStream; +}; +} // namespace IO diff --git a/app/src/Misc/ModuleManager.cpp b/app/src/Misc/ModuleManager.cpp index b4623565..03bad5a3 100644 --- a/app/src/Misc/ModuleManager.cpp +++ b/app/src/Misc/ModuleManager.cpp @@ -37,6 +37,7 @@ #include "IO/Manager.h" #include "IO/Console.h" +#include "IO/ConsoleExport.h" #include "IO/FileTransmission.h" #include "IO/Drivers/Serial.h" @@ -255,6 +256,7 @@ void Misc::ModuleManager::initializeQmlInterface() auto projectModel = &JSON::ProjectModel::instance(); auto miscTimerEvents = &Misc::TimerEvents::instance(); auto miscCommonFonts = &Misc::CommonFonts::instance(); + auto ioConsoleExport = &IO::ConsoleExport::instance(); auto miscThemeManager = &Misc::ThemeManager::instance(); auto ioBluetoothLE = &IO::Drivers::BluetoothLE::instance(); auto ioFileTransmission = &IO::FileTransmission::instance(); @@ -294,6 +296,7 @@ void Misc::ModuleManager::initializeQmlInterface() c->setContextProperty("Cpp_JSON_FrameBuilder", frameBuilder); c->setContextProperty("Cpp_Misc_TimerEvents", miscTimerEvents); c->setContextProperty("Cpp_Misc_CommonFonts", miscCommonFonts); + c->setContextProperty("Cpp_IO_ConsoleExport", ioConsoleExport); c->setContextProperty("Cpp_IO_FileTransmission", ioFileTransmission); // Register app info with QML @@ -318,6 +321,7 @@ void Misc::ModuleManager::initializeQmlInterface() ioManager->setupExternalConnections(); projectModel->setupExternalConnections(); frameBuilder->setupExternalConnections(); + ioConsoleExport->setupExternalConnections(); // Install custom message handler to redirect qDebug output to console qInstallMessageHandler(MessageHandler);