mirror of
https://github.com/Serial-Studio/Serial-Studio.git
synced 2025-01-31 17:42:55 +08:00
Allow copying & exporting console data
This commit is contained in:
parent
99471c771f
commit
681952701e
@ -41,6 +41,13 @@ Control {
|
||||
//
|
||||
property alias text: textArea.text
|
||||
readonly property color consoleColor: "#8ecd9d"
|
||||
|
||||
//
|
||||
// Hacks to allow context menu to work
|
||||
//
|
||||
property int curPos
|
||||
property int selectEnd
|
||||
property int selectStart
|
||||
|
||||
//
|
||||
// Function to send through serial port data
|
||||
@ -62,6 +69,42 @@ Control {
|
||||
property alias displayMode: displayModeCombo.currentIndex
|
||||
}
|
||||
|
||||
//
|
||||
// Shortcut to copy selection of console
|
||||
//
|
||||
Shortcut {
|
||||
sequence: StandardKey.Copy
|
||||
onActivated: textArea.copy()
|
||||
}
|
||||
|
||||
//
|
||||
// Right-click context menu
|
||||
//
|
||||
Menu {
|
||||
id: contextMenu
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Copy")
|
||||
opacity: enabled ? 1 : 0.5
|
||||
onTriggered: textArea.copy()
|
||||
enabled: textArea.selectedText
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Clear")
|
||||
opacity: enabled ? 1 : 0.5
|
||||
enabled: textArea.length > 0
|
||||
onTriggered: Cpp_IO_Console.clear()
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
opacity: enabled ? 1 : 0.5
|
||||
text: qsTr("Save as") + "..."
|
||||
onTriggered: Cpp_IO_Console.save()
|
||||
enabled: Cpp_IO_Console.saveAvailable
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Controls
|
||||
//
|
||||
@ -111,18 +154,54 @@ Control {
|
||||
|
||||
TextEdit {
|
||||
id: textArea
|
||||
focus: true
|
||||
readOnly: true
|
||||
font.pixelSize: 12
|
||||
width: flick.width
|
||||
height: flick.height
|
||||
selectByMouse: true
|
||||
selectByKeyboard: true
|
||||
color: root.consoleColor
|
||||
persistentSelection: true
|
||||
wrapMode: TextEdit.NoWrap
|
||||
font.family: app.monoFont
|
||||
selectionColor: palette.highlight
|
||||
selectedTextColor: palette.highlightedText
|
||||
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
|
||||
onTextChanged: {
|
||||
if (Cpp_IO_Console.autoscroll)
|
||||
textArea.cursorPosition = textArea.length
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.RightButton
|
||||
|
||||
onClicked: {
|
||||
root.selectStart = textArea.selectionStart;
|
||||
root.selectEnd = textArea.selectionEnd;
|
||||
root.curPos = textArea.cursorPosition;
|
||||
contextMenu.x = mouse.x;
|
||||
contextMenu.y = mouse.y;
|
||||
contextMenu.open();
|
||||
textArea.cursorPosition = root.curPos;
|
||||
textArea.select(root.selectStart, root.selectEnd);
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
if (mouse.source === Qt.MouseEventNotSynthesized) {
|
||||
root.selectStart = textArea.selectionStart;
|
||||
root.selectEnd = textArea.selectionEnd;
|
||||
root.curPos = textArea.cursorPosition;
|
||||
contextMenu.x = mouse.x;
|
||||
contextMenu.y = mouse.y;
|
||||
contextMenu.open();
|
||||
textArea.cursorPosition = root.curPos;
|
||||
textArea.select(root.selectStart, root.selectEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,6 +325,18 @@ Control {
|
||||
|
||||
Button {
|
||||
height: 24
|
||||
Layout.maximumWidth: 32
|
||||
icon.color: palette.text
|
||||
opacity: enabled ? 1 : 0.5
|
||||
onClicked: Cpp_IO_Console.save()
|
||||
icon.source: "qrc:/icons/save.svg"
|
||||
enabled: Cpp_IO_Console.saveAvailable
|
||||
Behavior on opacity {NumberAnimation{}}
|
||||
}
|
||||
|
||||
Button {
|
||||
height: 24
|
||||
Layout.maximumWidth: 32
|
||||
icon.color: palette.text
|
||||
opacity: enabled ? 1 : 0.5
|
||||
enabled: textArea.length > 0
|
||||
|
@ -186,7 +186,7 @@ Control {
|
||||
//
|
||||
Label {
|
||||
opacity: enabled ? 1 : 0.5
|
||||
enabled: !Cpp_IO_Serial.connected
|
||||
enabled: !Cpp_IO_Manager.connected
|
||||
Behavior on opacity {NumberAnimation{}}
|
||||
text: qsTr("COM Port") + ":"
|
||||
} ComboBox {
|
||||
@ -200,7 +200,7 @@ Control {
|
||||
}
|
||||
|
||||
opacity: enabled ? 1 : 0.5
|
||||
enabled: !Cpp_IO_Serial.connected
|
||||
enabled: !Cpp_IO_Manager.connected
|
||||
Behavior on opacity {NumberAnimation{}}
|
||||
}
|
||||
|
||||
@ -209,7 +209,6 @@ Control {
|
||||
//
|
||||
Label {
|
||||
opacity: enabled ? 1 : 0.5
|
||||
enabled: !Cpp_IO_Serial.connected
|
||||
Behavior on opacity {NumberAnimation{}}
|
||||
text: qsTr("Baud Rate") + ":"
|
||||
} ComboBox {
|
||||
|
Binary file not shown.
@ -155,6 +155,18 @@
|
||||
<source>Show timestamp</source>
|
||||
<translation>Zeitstempel anzeigen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy</source>
|
||||
<translation>Kopieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation>Löschen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save as</source>
|
||||
<translation>Speichern als</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CsvPlayer</name>
|
||||
@ -459,6 +471,18 @@
|
||||
<source>Hexadecimal</source>
|
||||
<translation>Hexadezimal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Export console data</source>
|
||||
<translation>Konsolendaten exportieren</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Text files</source>
|
||||
<translation>Textdateien</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>File save error</source>
|
||||
<translation>Fehler beim Speichern der Datei</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IO::DataSources::Serial</name>
|
||||
|
Binary file not shown.
@ -151,6 +151,18 @@
|
||||
<source>Show timestamp</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save as</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CsvPlayer</name>
|
||||
@ -396,6 +408,18 @@
|
||||
<source>Hexadecimal</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Export console data</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Text files</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>File save error</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IO::DataSources::Serial</name>
|
||||
|
Binary file not shown.
@ -159,6 +159,18 @@
|
||||
<source>Show timestamp</source>
|
||||
<translation>Marca de tiempo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy</source>
|
||||
<translation>Copiar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation>Limpiar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save as</source>
|
||||
<translation>Guardar como</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CsvPlayer</name>
|
||||
@ -491,6 +503,18 @@
|
||||
<source>Hexadecimal</source>
|
||||
<translation>Hexadecimal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Export console data</source>
|
||||
<translation>Exportar datos de la consola</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Text files</source>
|
||||
<translation>Archivos de texto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>File save error</source>
|
||||
<translation>Error al intentar guardar el archivo</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IO::DataSources::Serial</name>
|
||||
|
Binary file not shown.
@ -155,6 +155,18 @@
|
||||
<source>Show timestamp</source>
|
||||
<translation>显示时间戳</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy</source>
|
||||
<translation>复制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clear</source>
|
||||
<translation>删除</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save as</source>
|
||||
<translation>另存为</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>CsvPlayer</name>
|
||||
@ -487,6 +499,18 @@
|
||||
<source>Hexadecimal</source>
|
||||
<translation>十六进制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Export console data</source>
|
||||
<translation>导出控制台数据</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Text files</source>
|
||||
<translation>文字档</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>File save error</source>
|
||||
<translation>文件保存错误</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IO::DataSources::Serial</name>
|
||||
|
@ -23,13 +23,21 @@
|
||||
#include "Console.h"
|
||||
#include "Manager.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <Logger.h>
|
||||
#include <QTextCodec>
|
||||
#include <QFileDialog>
|
||||
#include <Misc/Utilities.h>
|
||||
#include <ConsoleAppender.h>
|
||||
|
||||
using namespace IO;
|
||||
static Console *INSTANCE = nullptr;
|
||||
|
||||
/**
|
||||
* Set buffer size to 15 MB
|
||||
*/
|
||||
static const int MAX_BUFFER_SIZE = 1024 * 1024 * 15;
|
||||
|
||||
/**
|
||||
* Constructor function
|
||||
*/
|
||||
@ -45,6 +53,7 @@ Console::Console()
|
||||
, m_cursor(nullptr)
|
||||
, m_document(nullptr)
|
||||
{
|
||||
clear();
|
||||
auto m = Manager::getInstance();
|
||||
connect(m, &Manager::dataReceived, this, &Console::onDataReceived);
|
||||
LOG_INFO() << "Class initialized";
|
||||
@ -79,6 +88,14 @@ bool Console::autoscroll() const
|
||||
return m_autoscroll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns @c true if data buffer contains information that the user can export.
|
||||
*/
|
||||
bool Console::saveAvailable() const
|
||||
{
|
||||
return m_dataBuffer.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns @c true if a timestamp should be shown before each displayed data block.
|
||||
*/
|
||||
@ -190,15 +207,49 @@ QStringList Console::displayModes() const
|
||||
|
||||
void Console::copy() { }
|
||||
|
||||
void Console::save() { }
|
||||
/**
|
||||
* Allows the user to export the information displayed on the console
|
||||
*/
|
||||
void Console::save()
|
||||
{
|
||||
// No data buffer received, abort
|
||||
if (!saveAvailable())
|
||||
return;
|
||||
|
||||
// Get file name
|
||||
auto path
|
||||
= QFileDialog::getSaveFileName(Q_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_dataBuffer);
|
||||
file.close();
|
||||
|
||||
Misc::Utilities::revealFile(path);
|
||||
}
|
||||
|
||||
else
|
||||
Misc::Utilities::showMessageBox(tr("File save error"), file.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all the text displayed by the current QML text document
|
||||
*/
|
||||
void Console::clear()
|
||||
{
|
||||
// Clear console display
|
||||
if (document())
|
||||
document()->clear();
|
||||
|
||||
// Reserve 15 MB for data buffer
|
||||
m_dataBuffer.clear();
|
||||
m_dataBuffer.reserve(MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -383,10 +434,25 @@ void Console::setTextDocument(QQuickTextDocument *document)
|
||||
* Displays the given @a data in the console. @c QByteArray to ~@c QString conversion is
|
||||
* done by the @c dataToString() function, which displays incoming data either in UTF-8
|
||||
* or in hexadecimal mode.
|
||||
*
|
||||
* The incoming data is also added to a buffer so that the user can save the file if
|
||||
* needed.
|
||||
*/
|
||||
void Console::onDataReceived(const QByteArray &data)
|
||||
{
|
||||
// Display data
|
||||
append(dataToString(data));
|
||||
|
||||
// Append data to buffer
|
||||
m_dataBuffer.append(data);
|
||||
if (m_dataBuffer.size() > MAX_BUFFER_SIZE)
|
||||
{
|
||||
m_dataBuffer.clear();
|
||||
m_dataBuffer.reserve(MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
// Notify UI
|
||||
emit dataReceived();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,9 @@ class Console : public QObject
|
||||
READ showTimestamp
|
||||
WRITE setShowTimestamp
|
||||
NOTIFY showTimestampChanged)
|
||||
Q_PROPERTY(bool saveAvailable
|
||||
READ saveAvailable
|
||||
NOTIFY dataReceived)
|
||||
Q_PROPERTY(IO::Console::DataMode dataMode
|
||||
READ dataMode
|
||||
WRITE setDataMode
|
||||
@ -67,6 +70,7 @@ class Console : public QObject
|
||||
|
||||
signals:
|
||||
void echoChanged();
|
||||
void dataReceived();
|
||||
void dataModeChanged();
|
||||
void autoscrollChanged();
|
||||
void lineEndingChanged();
|
||||
@ -103,6 +107,7 @@ public:
|
||||
|
||||
bool echo() const;
|
||||
bool autoscroll() const;
|
||||
bool saveAvailable() const;
|
||||
bool showTimestamp() const;
|
||||
|
||||
DataMode dataMode() const;
|
||||
@ -145,6 +150,7 @@ private:
|
||||
|
||||
private:
|
||||
DataMode m_dataMode;
|
||||
QByteArray m_dataBuffer;
|
||||
LineEnding m_lineEnding;
|
||||
DisplayMode m_displayMode;
|
||||
|
||||
|
@ -46,6 +46,7 @@ Manager::Manager()
|
||||
, m_finishSequence("*/")
|
||||
{
|
||||
setWatchdogInterval(15);
|
||||
setMaxBufferSize(1024 * 1024);
|
||||
LOG_INFO() << "Class initialized";
|
||||
}
|
||||
|
||||
@ -310,6 +311,7 @@ void Manager::disconnectDevice()
|
||||
m_device = nullptr;
|
||||
m_receivedBytes = 0;
|
||||
m_dataBuffer.clear();
|
||||
m_dataBuffer.reserve(maxBufferSize());
|
||||
|
||||
// Update UI
|
||||
emit deviceChanged();
|
||||
@ -351,6 +353,8 @@ void Manager::setMaxBufferSize(const int maxBufferSize)
|
||||
{
|
||||
m_maxBuzzerSize = maxBufferSize;
|
||||
emit maxBufferSizeChanged();
|
||||
|
||||
m_dataBuffer.reserve(maxBufferSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user