Added logging window capability with termbin support.

knobtest
Elliott Liggett 2022-09-14 17:07:23 -07:00
rodzic c97f0f7826
commit 3290b64a0b
10 zmienionych plików z 547 dodań i 9 usunięć

Wyświetl plik

@ -3,6 +3,7 @@
Q_LOGGING_CATEGORY(logSystem, "system")
Q_LOGGING_CATEGORY(logSerial, "serial")
Q_LOGGING_CATEGORY(logGui, "gui")
Q_LOGGING_CATEGORY(logUser, "user")
Q_LOGGING_CATEGORY(logRig, "rig")
Q_LOGGING_CATEGORY(logAudio, "audio")
Q_LOGGING_CATEGORY(logUdp, "udp")

Wyświetl plik

@ -6,6 +6,7 @@
Q_DECLARE_LOGGING_CATEGORY(logSystem)
Q_DECLARE_LOGGING_CATEGORY(logSerial)
Q_DECLARE_LOGGING_CATEGORY(logGui)
Q_DECLARE_LOGGING_CATEGORY(logUser)
Q_DECLARE_LOGGING_CATEGORY(logRig)
Q_DECLARE_LOGGING_CATEGORY(logAudio)
Q_DECLARE_LOGGING_CATEGORY(logUdp)

152
loggingwindow.cpp 100644
Wyświetl plik

@ -0,0 +1,152 @@
#include "loggingwindow.h"
#include "ui_loggingwindow.h"
loggingWindow::loggingWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::loggingWindow)
{
ui->setupUi(this);
ui->logTextDisplay->setReadOnly(true);
ui->userAnnotationText->setFocus();
ui->annotateBtn->setDefault(true);
ui->logTextDisplay->setFocusPolicy(Qt::NoFocus);
ui->annotateBtn->setFocusPolicy(Qt::NoFocus);
#ifdef Q_OS_MAC
logFilename = QStandardPaths::standardLocations(QStandardPaths::DownloadLocation)[0] + "/wfview.log";
logDirectory = QStandardPaths::standardLocations(QStandardPaths::DownloadLocation)[0];
#else
logFilename= QStandardPaths::standardLocations(QStandardPaths::TempLocation)[0] + "/wfview.log";
logDirectory = QStandardPaths::standardLocations(QStandardPaths::TempLocation)[0];
#endif
clipboard = QApplication::clipboard();
socket = new QTcpSocket(this);
connect(socket, SIGNAL(connected()), this, SLOT(connectedToHost()));
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectedFromHost()));
connect(socket, SIGNAL(readyRead()), this, SLOT(handleDataFromLoggingHost()));
connect(socket, SIGNAL(hostFound()), this, SLOT(handleLoggingHostError()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(handleLoggingHostError(QAbstractSocket::SocketError)));
}
loggingWindow::~loggingWindow()
{
QMutexLocker lock(&textMutex);
delete ui;
}
void loggingWindow::acceptLogText(QString text)
{
QMutexLocker lock(&textMutex);
ui->logTextDisplay->appendPlainText(text);
}
void loggingWindow::sendToTermbin()
{
qInfo(logGui()) << "Sending data to termbin.com. Standby.";
socket->connectToHost("termbin.com", 9999);
ui->sendToPasteBtn->setDisabled(true);
}
void loggingWindow::handleDataFromLoggingHost()
{
qInfo(logGui()) << "Receiving data from logging host.";
QString URL;
QByteArray data = socket->readAll();
if(data.length() < 256)
{
URL = QString(data).trimmed();
if(!URL.isEmpty())
{
clipboard->setText(URL);
qInfo(logGui()) << "Sent log to URL: " << URL;
msgBox.setText("Your log has been posted, and the URL has been copied to the clipboard.");
msgBox.setInformativeText(URL);
msgBox.exec();
}
} else {
qDebug(logGui()) << "Error, return from logging host too large. Received " << data.length() << " bytes.";
}
}
void loggingWindow::disconnectedFromHost()
{
qInfo(logGui()) << "Disconnected from logging host";
ui->sendToPasteBtn->setDisabled(false);
}
void loggingWindow::connectedToHost()
{
qInfo(logGui()) << "Connected to logging host";
QMutexLocker lock(&textMutex);
QTextStream outText(socket);
outText << ui->logTextDisplay->toPlainText();
outText << "\n----------\nSent from wfview version ";
outText << WFVIEW_VERSION << "\n----------\n";
}
void loggingWindow::handleLoggingHostError(QAbstractSocket::SocketError error)
{
qInfo(logGui()) << "Error connecting to logging host. Check internet connection. Error code: " << error;
}
void loggingWindow::on_clearDisplayBtn_clicked()
{
QMutexLocker lock(&textMutex);
// Only clears the displayed text, not the log file.
ui->logTextDisplay->clear();
}
void loggingWindow::on_openDirBtn_clicked()
{
QString cmd;
#ifdef Q_OS_MAC
cmd = "open " + logDirectory;
#endif
#ifdef Q_OS_LINUX
cmd = "xdg-open " + logDirectory;
#endif
#ifdef Q_OS_WIN
cmd = "start " + logDirectory;
#endif
system(cmd.toLocal8Bit().data());
}
void loggingWindow::on_openLogFileBtn_clicked()
{
QString cmd;
#ifdef Q_OS_MAC
cmd = "open " + logFilename;
#endif
#ifdef Q_OS_LINUX
cmd = "xdg-open " + logFilename;
#endif
#ifdef Q_OS_WIN
cmd = "start " + logFilename;
#endif
system(cmd.toLocal8Bit().data());
}
void loggingWindow::on_sendToPasteBtn_clicked()
{
sendToTermbin();
}
void loggingWindow::on_annotateBtn_clicked()
{
QMutexLocker lock(&textMutex);
if(ui->userAnnotationText->text().isEmpty())
return;
qInfo(logUser()) << ui->userAnnotationText->text();
ui->userAnnotationText->clear();
}
void loggingWindow::on_userAnnotationText_returnPressed()
{
on_annotateBtn_clicked();
}
void loggingWindow::on_copyPathBtn_clicked()
{
clipboard->setText(logFilename);
}

59
loggingwindow.h 100644
Wyświetl plik

@ -0,0 +1,59 @@
#ifndef LOGGINGWINDOW_H
#define LOGGINGWINDOW_H
#include <QWidget>
#include <QMutexLocker>
#include <QMutex>
#include <QStandardPaths>
#include <QClipboard>
#include <QTcpSocket>
#include <QTextStream>
#include <QMessageBox>
#include "logcategories.h"
namespace Ui {
class loggingWindow;
}
class loggingWindow : public QWidget
{
Q_OBJECT
public:
explicit loggingWindow(QWidget *parent = nullptr);
~loggingWindow();
void acceptLogText(QString text);
private slots:
void connectedToHost();
void disconnectedFromHost();
void handleDataFromLoggingHost();
void handleLoggingHostError(QAbstractSocket::SocketError);
void on_clearDisplayBtn_clicked();
void on_openDirBtn_clicked();
void on_openLogFileBtn_clicked();
void on_sendToPasteBtn_clicked();
void on_annotateBtn_clicked();
void on_userAnnotationText_returnPressed();
void on_copyPathBtn_clicked();
private:
Ui::loggingWindow *ui;
QClipboard *clipboard;
QMessageBox msgBox;
QMutex textMutex;
QString logFilename;
QString logDirectory;
QTcpSocket *socket;
void sendToTermbin();
};
#endif // LOGGINGWINDOW_H

172
loggingwindow.ui 100644
Wyświetl plik

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>loggingWindow</class>
<widget class="QWidget" name="loggingWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>554</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="logTextDisplay">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="annotateLabel">
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>75</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Annotation:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="userAnnotationText">
<property name="minimumSize">
<size>
<width>290</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="annotateBtn">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Adds user-text to the log.</string>
</property>
<property name="text">
<string>Annotate</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="clearDisplayBtn">
<property name="toolTip">
<string>Clears the display. Does not clear the log file.</string>
</property>
<property name="text">
<string>Clear Display</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openDirBtn">
<property name="toolTip">
<string>Makes a best-effort to ask the host system to open the log file directory.</string>
</property>
<property name="text">
<string>Open Log Directory</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openLogFileBtn">
<property name="toolTip">
<string>Makes a best-effort to ask the host system to open the logfile.</string>
</property>
<property name="text">
<string>Open Log</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="copyPathBtn">
<property name="toolTip">
<string>Copy the path of the log file to your clipboard.</string>
</property>
<property name="text">
<string>Copy Path</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sendToPasteBtn">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sends text to termbin.com. Some personal information (such as your username) is in the log file, so do not click this button unless you are ok sharing your log file. This is a quick way to receive a URL, pointing to your log file text, that you can send to other people. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Send to Termbin.com</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Wyświetl plik

@ -12,13 +12,16 @@
#include <iostream>
#include "wfmain.h"
// Copyright 2017-2022 Elliott H. Liggett
#include "logcategories.h"
// Copyright 2017-2021 Elliott H. Liggett
#ifdef BUILD_WFSERVER
// Smart pointer to log file
QScopedPointer<QFile> m_logFile;
QMutex logMutex;
#endif
bool debugMode=false;
#ifdef BUILD_WFSERVER
@ -42,9 +45,9 @@ bool debugMode=false;
#endif
}
#endif
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
#endif
int main(int argc, char *argv[])
{
@ -65,7 +68,7 @@ int main(int argc, char *argv[])
#endif
#ifdef QT_DEBUG
debugMode = true;
//debugMode = true;
#endif
QString serialPortCL;
@ -160,12 +163,15 @@ int main(int argc, char *argv[])
}
#ifdef BUILD_WFSERVER
// Set the logging file before doing anything else.
m_logFile.reset(new QFile(logFilename));
// Open the file logging
m_logFile.data()->open(QFile::WriteOnly | QFile::Truncate | QFile::Text);
// Set handler
qInstallMessageHandler(messageHandler);
#endif
qInfo(logSystem()) << version;
qDebug(logSystem()) << QString("SerialPortCL as set by parser: %1").arg(serialPortCL);
@ -183,7 +189,7 @@ int main(int argc, char *argv[])
w = new servermain(serialPortCL, hostCL, settingsFile);
#else
a.setWheelScrollLines(1); // one line per wheel click
wfmain w(serialPortCL, hostCL, settingsFile);
wfmain w(serialPortCL, hostCL, settingsFile, debugMode);
w.show();
#endif
@ -191,6 +197,7 @@ int main(int argc, char *argv[])
}
#ifdef BUILD_WFSERVER
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
@ -201,6 +208,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
}
QMutexLocker locker(&logMutex);
QTextStream out(m_logFile.data());
QString text;
// Write the date of recording
out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ");
@ -229,5 +237,8 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
#ifdef BUILD_WFSERVER
std::cout << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ").toLocal8Bit().toStdString() << msg.toLocal8Bit().toStdString() << "\n";
#endif
text = out.readAll();
out.flush(); // Clear the buffered data
//mainwindow.handleLogText(test);
}
#endif

Wyświetl plik

@ -5,10 +5,22 @@
#include "rigidentities.h"
#include "logcategories.h"
// This code is copyright 2017-2020 Elliott H. Liggett
// This code is copyright 2017-2022 Elliott H. Liggett
// All rights reserved
wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString settingsFile, QWidget *parent ) :
// Log support:
//static void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
QScopedPointer<QFile> m_logFile;
QMutex logMutex;
QMutex logTextMutex;
QVector<QString> logStringBuffer;
#ifdef QT_DEBUG
bool debugModeLogging = true;
#else
bool debugModeLogging = false;
#endif
wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString settingsFile, bool debugMode, QWidget *parent ) :
QMainWindow(parent),
ui(new Ui::wfmain)
{
@ -16,10 +28,14 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString s
QGuiApplication::setApplicationName(QString("wfview"));
setWindowIcon(QIcon( QString(":resources/wfview.png")));
this->debugMode = debugMode;
debugModeLogging = debugMode;
ui->setupUi(this);
setWindowTitle(QString("wfview"));
initLogging();
this->serialPortCL = serialPortCL;
this->hostCL = hostCL;
@ -29,6 +45,7 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, const QString s
trxadj = new transceiverAdjustments();
abtBox = new aboutbox();
selRad = new selectRadio();
logWindow = new loggingWindow();
qRegisterMetaType<udpPreferences>(); // Needs to be registered early.
qRegisterMetaType<rigCapabilities>();
@ -6932,3 +6949,104 @@ void wfmain::on_colorSavePresetBtn_clicked()
settings->endGroup();
settings->sync();
}
void wfmain::on_showLogBtn_clicked()
{
logWindow->show();
}
void wfmain::initLogging()
{
#ifdef Q_OS_MAC
logFilename= QStandardPaths::standardLocations(QStandardPaths::DownloadLocation)[0] + "/wfview.log";
#else
logFilename= QStandardPaths::standardLocations(QStandardPaths::TempLocation)[0] + "/wfview.log";
#endif
// Set the logging file before doing anything else.
m_logFile.reset(new QFile(logFilename));
// Open the file logging
m_logFile.data()->open(QFile::WriteOnly | QFile::Truncate | QFile::Text);
// Set handler
qInstallMessageHandler(messageHandler);
logCheckingTimer.setInterval(50);
connect(&logCheckingTimer, SIGNAL(timeout()), this, SLOT(logCheck()));
logCheckingTimer.start();
}
void wfmain::logCheck()
{
// This is called by a timer to check for new log messages and copy
// the messages into the logWindow.
QMutexLocker locker(&logTextMutex);
int size = logStringBuffer.size();
for(int i=0; i < size; i++)
{
handleLogText(logStringBuffer.back());
logStringBuffer.pop_back();
}
}
void wfmain::handleLogText(QString text)
{
// This function is just a pass-through
logWindow->acceptLogText(text);
}
void wfmain::messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
// Open stream file writes
// TODO: Fix this parameter:
if (type == QtDebugMsg && !debugModeLogging)
{
return;
}
QMutexLocker locker(&logMutex);
QTextStream out(m_logFile.data());
QString text;
// Write the date of recording
out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz ");
text.append(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz "));
// By type determine to what level belongs message
switch (type)
{
case QtDebugMsg:
out << "DBG ";
text.append("DBG ");
break;
case QtInfoMsg:
out << "INF ";
text.append("INF ");
break;
case QtWarningMsg:
out << "WRN ";
text.append("WRN ");
break;
case QtCriticalMsg:
out << "CRT ";
text.append("CRT ");
break;
case QtFatalMsg:
out << "FTL ";
text.append("FLT ");
break;
}
// Write to the output category of the message and the message itself
out << context.category << ": " << msg << "\n";
out.flush(); // Clear the buffered data
text.append(context.category);
text.append(": ");
text.append(msg);
logTextMutex.lock();
logStringBuffer.push_back(text);
logTextMutex.unlock();
//logStringBuffer[logStringBufferPosition%logStringBufferSize] = text;
//logStringBufferPosition++;
}

Wyświetl plik

@ -38,6 +38,7 @@
#include "aboutbox.h"
#include "selectradio.h"
#include "colorprefs.h"
#include "loggingwindow.h"
#include <qcustomplot.h>
#include <qserialportinfo.h>
@ -63,10 +64,12 @@ class wfmain : public QMainWindow
Q_OBJECT
public:
explicit wfmain(const QString serialPortCL, const QString hostCL, const QString settingsFile, QWidget *parent = 0);
explicit wfmain(const QString serialPortCL, const QString hostCL, const QString settingsFile, bool debugMode, QWidget *parent = 0);
QString serialPortCL;
QString hostCL;
~wfmain();
static void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
void handleLogText(QString text);
signals:
// Basic to rig:
@ -292,6 +295,7 @@ private slots:
void radioSelection(QList<radio_cap_packet> radios);
void setRadioTimeDateSend();
void logCheck();
// void on_getFreqBtn_clicked();
@ -636,9 +640,12 @@ private slots:
void on_colorSavePresetBtn_clicked();
void on_showLogBtn_clicked();
private:
Ui::wfmain *ui;
void closeEvent(QCloseEvent *event);
bool debugMode;
QSettings *settings=Q_NULLPTR;
void loadSettings();
void saveSettings();
@ -646,6 +653,11 @@ private:
void createSettingsListItems();
void connectSettingsList();
void initLogging();
QTimer logCheckingTimer;
int logCheckingOldPosition = 0;
QString logFilename;
QCustomPlot *plot; // line plot
QCustomPlot *wf; // waterfall image
QCPItemLine * freqIndicatorLine;
@ -976,6 +988,7 @@ private:
transceiverAdjustments *trxadj;
aboutbox *abtBox;
selectRadio *selRad;
loggingWindow *logWindow;
udpServer* udp = Q_NULLPTR;
rigCtlD* rigCtl = Q_NULLPTR;
@ -1027,6 +1040,7 @@ Q_DECLARE_METATYPE(enum spectrumMode)
Q_DECLARE_METATYPE(QList<radio_cap_packet>)
Q_DECLARE_METATYPE(rigstate*)
//void (*wfmain::logthistext)(QString text) = NULL;
#endif // WFMAIN_H
#endif

Wyświetl plik

@ -3262,7 +3262,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>767</width>
<width>204</width>
<height>582</height>
</rect>
</property>
@ -4609,6 +4609,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="showLogBtn">
<property name="text">
<string>Log</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">

Wyświetl plik

@ -147,6 +147,7 @@ win32:INCLUDEPATH += ../r8brain-free-src
INCLUDEPATH += resampler
SOURCES += main.cpp\
loggingwindow.cpp \
wfmain.cpp \
commhandler.cpp \
rigcommander.cpp \
@ -178,6 +179,7 @@ SOURCES += main.cpp\
HEADERS += wfmain.h \
colorprefs.h \
commhandler.h \
loggingwindow.h \
rigcommander.h \
freqmemory.h \
rigidentities.h \
@ -213,6 +215,7 @@ HEADERS += wfmain.h \
FORMS += wfmain.ui \
calibrationwindow.ui \
loggingwindow.ui \
satellitesetup.ui \
selectradio.ui \
repeatersetup.ui \