Added first project implementation
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
CMakeLists.txt.user
|
||||
52
CMakeLists.txt
Normal file
52
CMakeLists.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(M1300LogViewer VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Widgets Charts)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
main.cpp
|
||||
|
||||
MainWindow.cpp
|
||||
MainWindow.h
|
||||
MainWindow.ui
|
||||
|
||||
DataTypes.h
|
||||
DataTypes.cpp
|
||||
|
||||
LogParser.h
|
||||
LogParser.cpp
|
||||
|
||||
InteractiveChartView.h
|
||||
InteractiveChartView.cpp
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_executable(M1300LogViewer
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(M1300LogViewer PRIVATE Qt5::Widgets Qt5::Charts)
|
||||
|
||||
set_target_properties(M1300LogViewer PROPERTIES
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX ../M1300LogViewerDeploy)
|
||||
|
||||
# deploy commands
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_PREFIX_PATH}/bin/windeployqt.exe --dir ${CMAKE_INSTALL_PREFIX} --no-quick-import --no-translations ${CMAKE_BINARY_DIR}/M1300LogViewer.exe WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
|
||||
install(CODE "file(COPY ${CMAKE_BINARY_DIR}/M1300LogViewer.exe DESTINATION ${CMAKE_INSTALL_PREFIX})")
|
||||
install(CODE "message(\"Installation finished!\")")
|
||||
120
DataTypes.cpp
Normal file
120
DataTypes.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "DataTypes.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QString DataTypes::messageString(MessageType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MessageType::LTM_REASON_NONE:
|
||||
return QObject::tr("No reason", "DataTypes");
|
||||
case MessageType::LTM_REASON_AFTER_POWER_ON:
|
||||
return QObject::tr("M1300 Enabling", "DataTypes");
|
||||
case MessageType::LTM_REASON_NO_CANBUS_WITH_CONTROL_BOARD:
|
||||
return QObject::tr("No CAN Bus link with PWR", "DataTypes");
|
||||
case MessageType::LTM_REASON_NO_CANBUS:
|
||||
return QObject::tr("CAN Bus error with PWR", "DataTypes");
|
||||
case MessageType::LTM_REASON_NO_INPUT_LONG_TIME:
|
||||
return QObject::tr("No input voltage long time", "DataTypes");
|
||||
case MessageType::LTM_REASON_MAS_SHUTDOWN:
|
||||
return QObject::tr("On any M1300 disabling", "DataTypes");
|
||||
case MessageType::LTM_REASON_ANY_UNDERVOLTAGE:
|
||||
return QObject::tr("On any under-voltage", "DataTypes");
|
||||
case MessageType::LTM_REASON_ANY_OVERVOLTAGE:
|
||||
return QObject::tr("On any over-voltage", "DataTypes");
|
||||
case MessageType::LTM_REASON_NOT_ALLOWED_TO_START_INPUT_VOLTAGE_OUT_OF_RANGE:
|
||||
return QObject::tr("Voltage out of range", "DataTypes");
|
||||
case MessageType::LTM_REASON_FIRST_START:
|
||||
return QObject::tr("M1300 First start", "DataTypes");
|
||||
case MessageType::LTM_REASON_CHECK_BE_K1:
|
||||
return QObject::tr("K1 Feedback error", "DataTypes");
|
||||
case MessageType::LTM_REASON_K1_NO_CONTROL_FEEDBACK:
|
||||
return QObject::tr("K1 Feedback exists without control", "DataTypes");
|
||||
case MessageType::LTM_REASON_K1_NO_FEEDBACK:
|
||||
return QObject::tr("K1 Feedback error", "DataTypes");
|
||||
case MessageType::LTM_REASON_TURN_OFF_DUE_K1_VS_DC_LINK:
|
||||
return QObject::tr("K1 Enabled, no DC-Link", "DataTypes");
|
||||
case MessageType::LTM_REASON_K2_WRONG_WAY_WORK:
|
||||
return QObject::tr("K2 enabled if K1 enabled", "DataTypes");
|
||||
case MessageType::LTM_REASON_CHECK_BE_K2:
|
||||
return QObject::tr("K2 Feedback error", "DataTypes");
|
||||
case MessageType::LTM_REASON_CHECK_TR_FEEDBACK:
|
||||
return QObject::tr("Protection Block feedback error", "DataTypes");
|
||||
case MessageType::LTM_REASON_TR_NO_FEEDBACK:
|
||||
return QObject::tr("Protection Block no feedback", "DataTypes");
|
||||
case MessageType::LTM_REASON_TR_TEST_FAULT:
|
||||
return QObject::tr("Protection Block test error", "DataTypes");
|
||||
case MessageType::LTM_REASON_LOCKED_DUE_TR:
|
||||
return QObject::tr("Protection Block error", "DataTypes");
|
||||
case MessageType::LTM_REASON_TURN_OFF_DUE_TR:
|
||||
return QObject::tr("Protection Block error", "DataTypes");
|
||||
case MessageType::LTM_REASON_TR_CONNECT_RESISTORS_DUE_LOW_VOLTAGE:
|
||||
return QObject::tr("Charge resistors enabling on under-voltage", "DataTypes");
|
||||
case MessageType::LTM_REASON_TURN_OFF_DUE_HIGH_INPUT_VOLTAGE_LONG_TIME:
|
||||
return QObject::tr("System disabling on over-voltage long time", "DataTypes");
|
||||
case MessageType::LTM_REASON_TR_CONNECT_RESISTORS_DUE_HIGH_INPUT_VOLTAGE_FAST:
|
||||
return QObject::tr("Charge resistors enabling on fast over-voltage", "DataTypes");
|
||||
case MessageType::LTM_REASON_TR_CONNECT_RESISTORS_DUE_HIGH_INPUT_VOLTAGE:
|
||||
return QObject::tr("Charge resistors enabling on over-voltage", "DataTypes");
|
||||
case MessageType::LTM_REASON_TURN_OFF_DUE_RESISTORS_ENERGY:
|
||||
return QObject::tr("System disabling on Charge Resistors over-energy", "DataTypes");
|
||||
case MessageType::LTM_REASON_TR_CONNECT_RESISTORS_DUE_HIGH_INPUT_CURRENT:
|
||||
return QObject::tr("Charge resistors enabling on over-current", "DataTypes");
|
||||
case MessageType::LTM_REASON_TURN_OFF_DUE_INPUT_CURRENT:
|
||||
return QObject::tr("System disabling on over-current", "DataTypes");
|
||||
case MessageType::LTM_REASON_HUR_NO_CONNECTION:
|
||||
return QObject::tr("No CAN Bus link with HUR", "DataTypes");
|
||||
case MessageType::LTM_REASON_HBU_LOCK_CAUSE_HUR:
|
||||
return QObject::tr("LTM_REASON_NONE", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURS_TEMP_HIGH:
|
||||
return QObject::tr("HUR Slave over-temperature", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURS_TEMP_DEFEKT:
|
||||
return QObject::tr("HUR Slave temp sensor fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURM_TEMP_HIGH:
|
||||
return QObject::tr("HUR Master over-temperature", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURM_TEMP_DEFEKT:
|
||||
return QObject::tr("HUR Master temp sensor fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURM_HSS_DEFEKT:
|
||||
return QObject::tr("HUR Master HSS fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURM_WR_DEFEKT:
|
||||
return QObject::tr("HUR Master WR fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURS_HSS_DEFEKT:
|
||||
return QObject::tr("HUR Slave HSS fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_HURS_WR_DEFEKT:
|
||||
return QObject::tr("HUR Slave WR fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_HBU_LOCK_CAUSE_PWR:
|
||||
return QObject::tr("PWR Fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_OVERHEATING:
|
||||
return QObject::tr("PWR overheat", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_OVERCURRENT_FAST:
|
||||
return QObject::tr("PWR fast over-current", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_OVERCURRENT_LONG_TIME:
|
||||
return QObject::tr("PWR long over-current", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_FAULT_1:
|
||||
return QObject::tr("PWR Phase A Fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_FAULT_2:
|
||||
return QObject::tr("PWR Phase B Fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_FAULT_3:
|
||||
return QObject::tr("PWR Phase C Fault", "DataTypes");
|
||||
case MessageType::LTM_REASON_PWR_LOCKED:
|
||||
return QObject::tr("PWR Locked", "DataTypes");
|
||||
case MessageType::LTM_PARAMS_MSG:
|
||||
return QObject::tr("Params Msg Status", "DataTypes");
|
||||
case MessageType::LTM_PARAMS_OUT:
|
||||
return QObject::tr("Params Msg Outs", "DataTypes");
|
||||
case MessageType::LTM_PARAMS_ADC:
|
||||
return QObject::tr("Params Msg ADC", "DataTypes");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool DataTypes::isErrorMessage(MessageType type)
|
||||
{
|
||||
return type != MessageType::LTM_REASON_NONE &&
|
||||
type != MessageType::LTM_PARAMS_MSG &&
|
||||
type != MessageType::LTM_PARAMS_OUT &&
|
||||
type != MessageType::LTM_PARAMS_ADC;
|
||||
}
|
||||
77
DataTypes.h
Normal file
77
DataTypes.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef DATATYPES_H
|
||||
#define DATATYPES_H
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
namespace DataTypes
|
||||
{
|
||||
enum class MessageType
|
||||
{
|
||||
LTM_REASON_NONE = 0, ///< No reason
|
||||
LTM_REASON_AFTER_POWER_ON = 1, ///< [Unused] M1300 Enabling
|
||||
LTM_REASON_NO_CANBUS_WITH_CONTROL_BOARD = 2, ///< No CAN Bus link with PWR
|
||||
LTM_REASON_NO_CANBUS = 3, ///< CAN Bus error with PWR
|
||||
LTM_REASON_NO_INPUT_LONG_TIME = 4, ///< No input voltage long time
|
||||
LTM_REASON_MAS_SHUTDOWN = 5, ///< On any M1300 disabling
|
||||
LTM_REASON_ANY_UNDERVOLTAGE = 6, ///< On any under-voltage
|
||||
LTM_REASON_ANY_OVERVOLTAGE = 7, ///< On any over-voltage
|
||||
LTM_REASON_NOT_ALLOWED_TO_START_INPUT_VOLTAGE_OUT_OF_RANGE = 8, ///< Voltage out of range
|
||||
LTM_REASON_FIRST_START = 9, ///< M1300 First start
|
||||
LTM_REASON_CHECK_BE_K1 = 10, ///< K1 Feedback error
|
||||
LTM_REASON_K1_NO_CONTROL_FEEDBACK = 11, ///< K1 Feedback exists without control
|
||||
LTM_REASON_K1_NO_FEEDBACK = 12, ///< K1 Feedback error
|
||||
LTM_REASON_TURN_OFF_DUE_K1_VS_DC_LINK = 13, ///< K1 Enabled, no DC-Link
|
||||
LTM_REASON_K2_WRONG_WAY_WORK = 14, ///< K2 enabled if K1 enabled
|
||||
LTM_REASON_CHECK_BE_K2 = 15, ///< K2 Feedback error
|
||||
LTM_REASON_CHECK_TR_FEEDBACK = 16, ///< Protection Block feedback error
|
||||
LTM_REASON_TR_NO_FEEDBACK = 17, ///< Protection Block no feedback
|
||||
LTM_REASON_TR_TEST_FAULT = 18, ///< Protection Block test error
|
||||
LTM_REASON_LOCKED_DUE_TR = 19, ///< [Unused] Protection Block error
|
||||
LTM_REASON_TURN_OFF_DUE_TR = 20, ///< Protection Block error
|
||||
LTM_REASON_TR_CONNECT_RESISTORS_DUE_LOW_VOLTAGE = 21, ///< Charge resistors enabling on under-voltage
|
||||
LTM_REASON_TURN_OFF_DUE_HIGH_INPUT_VOLTAGE_LONG_TIME = 22, ///< System disabling on over-voltage long time
|
||||
LTM_REASON_TR_CONNECT_RESISTORS_DUE_HIGH_INPUT_VOLTAGE_FAST = 23, ///< Charge resistors enabling on fast over-voltage
|
||||
LTM_REASON_TR_CONNECT_RESISTORS_DUE_HIGH_INPUT_VOLTAGE = 24, ///< Charge resistors enabling on over-voltage
|
||||
LTM_REASON_TURN_OFF_DUE_RESISTORS_ENERGY = 25, ///< System disabling on Charge Resistors over-energy
|
||||
LTM_REASON_TR_CONNECT_RESISTORS_DUE_HIGH_INPUT_CURRENT = 26, ///< Charge resistors enabling on over-current
|
||||
LTM_REASON_TURN_OFF_DUE_INPUT_CURRENT = 27, ///< System disabling on over-current
|
||||
LTM_REASON_HUR_NO_CONNECTION = 28, ///< No CAN Bus link with HUR
|
||||
LTM_REASON_HBU_LOCK_CAUSE_HUR = 29, ///< HUR fault
|
||||
LTM_REASON_HURS_TEMP_HIGH = 30, ///< HUR Slave over-temperature
|
||||
LTM_REASON_HURS_TEMP_DEFEKT = 31, ///< HUR Slave temp sensor fault
|
||||
LTM_REASON_HURM_TEMP_HIGH = 32, ///< HUR Master over-temperature
|
||||
LTM_REASON_HURM_TEMP_DEFEKT = 33, ///< HUR Master temp sensor fault
|
||||
LTM_REASON_HURM_HSS_DEFEKT = 34, ///< HUR Master HSS fault
|
||||
LTM_REASON_HURM_WR_DEFEKT = 35, ///< HUR Master WR fault
|
||||
LTM_REASON_HURS_HSS_DEFEKT = 36, ///< HUR Slave HSS fault
|
||||
LTM_REASON_HURS_WR_DEFEKT = 37, ///< HUR Slave WR fault
|
||||
LTM_REASON_HBU_LOCK_CAUSE_PWR = 38, ///< PWR Fault
|
||||
LTM_REASON_PWR_OVERHEATING = 39, ///< PWR overheat
|
||||
LTM_REASON_PWR_OVERCURRENT_FAST = 40, ///< PWR fast over-current
|
||||
LTM_REASON_PWR_OVERCURRENT_LONG_TIME = 41, ///< PWR long over-current
|
||||
LTM_REASON_PWR_FAULT_1 = 42, ///< PWR Phase A Fault
|
||||
LTM_REASON_PWR_FAULT_2 = 43, ///< PWR Phase B Fault
|
||||
LTM_REASON_PWR_FAULT_3 = 44, ///< PWR Phase C Fault
|
||||
LTM_REASON_PWR_LOCKED = 45, ///< PWR Locked
|
||||
|
||||
LTM_PARAMS_MSG = 0xFF-3, // Params Msg Status
|
||||
LTM_PARAMS_OUT = 0xFF-2, // Params Msg Outs
|
||||
LTM_PARAMS_ADC = 0xFF-1, // Params Msg ADC
|
||||
};
|
||||
|
||||
struct LogMessage
|
||||
{
|
||||
QDateTime dateTime;
|
||||
quint64 startupTime;
|
||||
MessageType type;
|
||||
qint64 f1;
|
||||
qint64 f2;
|
||||
qint64 f3;
|
||||
qint64 f4;
|
||||
};
|
||||
|
||||
QString messageString(MessageType type);
|
||||
bool isErrorMessage(MessageType type);
|
||||
}
|
||||
|
||||
#endif // DATATYPES_H
|
||||
22
InteractiveChartView.cpp
Normal file
22
InteractiveChartView.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "InteractiveChartView.h"
|
||||
|
||||
void InteractiveChartView::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
qreal factor;
|
||||
if (event->delta() > 0)
|
||||
factor = 2.0;
|
||||
else
|
||||
factor = 0.5;
|
||||
|
||||
QRectF r = QRectF(chart()->plotArea().left(),
|
||||
chart()->plotArea().top(),
|
||||
chart()->plotArea().width() / factor,
|
||||
chart()->plotArea().height() / factor);
|
||||
QPointF mousePos = mapFromGlobal(QCursor::pos());
|
||||
r.moveCenter(mousePos);
|
||||
chart()->zoomIn(r);
|
||||
QPointF delta = chart()->plotArea().center() - mousePos;
|
||||
chart()->scroll(delta.x(), -delta.y());
|
||||
|
||||
QChartView::wheelEvent(event);
|
||||
}
|
||||
19
InteractiveChartView.h
Normal file
19
InteractiveChartView.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef INTERACTIVECHARTVIEW_H
|
||||
#define INTERACTIVECHARTVIEW_H
|
||||
|
||||
#include <QChartView>
|
||||
|
||||
class InteractiveChartView : public QtCharts::QChartView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QChartView::QChartView;
|
||||
|
||||
protected:
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
|
||||
private:
|
||||
qreal factor = 1.0;
|
||||
};
|
||||
|
||||
#endif // INTERACTIVECHARTVIEW_H
|
||||
112
LogParser.cpp
Normal file
112
LogParser.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "LogParser.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
LogParser::LogParser(QObject* parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
logFolder = "C:/Users/Yury/Documents/M1300LogFolder";
|
||||
}
|
||||
|
||||
LogParser::~LogParser()
|
||||
{
|
||||
}
|
||||
|
||||
void LogParser::setLogFolder(const QString& folder)
|
||||
{
|
||||
logFolder = folder;
|
||||
}
|
||||
|
||||
void LogParser::setStartDateTime(const QDateTime& dateTime)
|
||||
{
|
||||
startDateTime = dateTime;
|
||||
}
|
||||
|
||||
void LogParser::setEndDateTime(const QDateTime& dateTime)
|
||||
{
|
||||
endDateTime = dateTime;
|
||||
}
|
||||
|
||||
QString LogParser::getLogFolder() const
|
||||
{
|
||||
return logFolder;
|
||||
}
|
||||
|
||||
QDateTime LogParser::getStartDateTime() const
|
||||
{
|
||||
return startDateTime;
|
||||
}
|
||||
|
||||
QDateTime LogParser::getEndDateTime() const
|
||||
{
|
||||
return endDateTime;
|
||||
}
|
||||
|
||||
QStringList LogParser::logFilesByDateTime() const
|
||||
{
|
||||
QStringList files;
|
||||
for (const auto& fileInfo: QDir(logFolder).entryInfoList())
|
||||
{
|
||||
const auto fileTime = fileInfo.baseName();
|
||||
auto date = QDateTime::fromString(fileTime, "yyMMdd_hhmmss");
|
||||
if (date.date().year() < 2000)
|
||||
{
|
||||
date = date.addYears(100);
|
||||
}
|
||||
|
||||
if (date.isValid() && date >= startDateTime && date <= endDateTime)
|
||||
{
|
||||
files.append(fileInfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
QList<DataTypes::LogMessage> LogParser::logMessagesByDateTime() const
|
||||
{
|
||||
QList<DataTypes::LogMessage> logMessages;
|
||||
|
||||
const auto logFiles = logFilesByDateTime();
|
||||
for (const auto& logFile: logFiles)
|
||||
{
|
||||
QFile file(logFile);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
qWarning() << "Can't open" << logFile;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (!file.atEnd())
|
||||
{
|
||||
const auto line = QString::fromUtf8(file.readLine());
|
||||
if (line.startsWith("RTC"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto parameters = line.split(';');
|
||||
if (parameters.size() < 7)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DataTypes::LogMessage message;
|
||||
message.dateTime = QDateTime::fromSecsSinceEpoch(parameters.at(0).toULongLong());
|
||||
message.startupTime = parameters.at(1).toULongLong();
|
||||
message.type = static_cast<DataTypes::MessageType>(parameters.at(2).toUInt());
|
||||
message.f1 = parameters.at(3).toLongLong();
|
||||
message.f2 = parameters.at(4).toLongLong();
|
||||
message.f3 = parameters.at(5).toLongLong();
|
||||
message.f4 = parameters.at(6).toLongLong();
|
||||
|
||||
// qDebug() << message.dateTime << message.startupTime << int(message.type);
|
||||
logMessages.append(message);
|
||||
}
|
||||
}
|
||||
|
||||
return logMessages;
|
||||
}
|
||||
33
LogParser.h
Normal file
33
LogParser.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef LOGPARSER_H
|
||||
#define LOGPARSER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "DataTypes.h"
|
||||
|
||||
class LogParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LogParser(QObject* parent = nullptr);
|
||||
~LogParser();
|
||||
|
||||
public slots:
|
||||
void setLogFolder(const QString& folder);
|
||||
void setStartDateTime(const QDateTime& dateTime);
|
||||
void setEndDateTime(const QDateTime& dateTime);
|
||||
|
||||
public:
|
||||
QString getLogFolder() const;
|
||||
QDateTime getStartDateTime() const;
|
||||
QDateTime getEndDateTime() const;
|
||||
|
||||
QStringList logFilesByDateTime() const;
|
||||
QList<DataTypes::LogMessage> logMessagesByDateTime() const;
|
||||
|
||||
private:
|
||||
QString logFolder;
|
||||
QDateTime startDateTime;
|
||||
QDateTime endDateTime;
|
||||
};
|
||||
|
||||
#endif // LOGPARSER_H
|
||||
211
MainWindow.cpp
Normal file
211
MainWindow.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
#include "MainWindow.h"
|
||||
#include "./ui_MainWindow.h"
|
||||
|
||||
#include "LogParser.h"
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QStorageInfo>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <QChart>
|
||||
#include <QLineSeries>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
, logParser(new LogParser)
|
||||
, logItemModel(new QStandardItemModel)
|
||||
, inputChart(new QtCharts::QChart)
|
||||
, outputChart(new QtCharts::QChart)
|
||||
, adcChart(new QtCharts::QChart)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
for (const auto& volume: QStorageInfo::mountedVolumes())
|
||||
{
|
||||
if (volume.displayName().contains("Drive"))
|
||||
{
|
||||
logParser->setLogFolder(volume.rootPath());
|
||||
}
|
||||
|
||||
qDebug() << volume.device() << volume.displayName() << volume.fileSystemType()
|
||||
<< volume.name() << volume.rootPath() << volume.subvolume();
|
||||
}
|
||||
|
||||
if (logParser->getLogFolder().isEmpty())
|
||||
{
|
||||
logParser->setLogFolder(QDir::homePath());
|
||||
}
|
||||
|
||||
ui->startDateTimeEdit->setDateTime(QDateTime::currentDateTime().addMonths(-3));
|
||||
ui->endDateTimeEdit->setDateTime(QDateTime::currentDateTime());
|
||||
|
||||
logParser->setStartDateTime(ui->startDateTimeEdit->dateTime());
|
||||
logParser->setEndDateTime(ui->endDateTimeEdit->dateTime());
|
||||
|
||||
const QStringList labels =
|
||||
{
|
||||
tr("Date"), tr("Startup time"), tr("Type"), tr("F1"), tr("F2"), tr("F3"), tr("F4"), tr("Description")
|
||||
};
|
||||
logItemModel->setHorizontalHeaderLabels(labels);
|
||||
|
||||
ui->logTableView->setModel(logItemModel.get());
|
||||
ui->logTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
ui->logTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
ui->logTableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
ui->inputChartView->setRenderHint(QPainter::Antialiasing);
|
||||
ui->inputChartView->setChart(inputChart.data());
|
||||
ui->inputChartView->setRubberBand(QtCharts::QChartView::RectangleRubberBand);
|
||||
|
||||
ui->outputChartView->setRenderHint(QPainter::Antialiasing);
|
||||
ui->outputChartView->setChart(outputChart.data());
|
||||
ui->outputChartView->setRubberBand(QtCharts::QChartView::RectangleRubberBand);
|
||||
|
||||
ui->adcChartView->setRenderHint(QPainter::Antialiasing);
|
||||
ui->adcChartView->setChart(adcChart.data());
|
||||
ui->adcChartView->setRubberBand(QtCharts::QChartView::RectangleRubberBand);
|
||||
|
||||
ui->pathLineEdit->setText(logParser->getLogFolder());
|
||||
ui->pathLineEdit->setReadOnly(true);
|
||||
|
||||
connect(ui->applyDateTimeButton, &QPushButton::clicked, this, &MainWindow::applyDateTimeFilter);
|
||||
connect(ui->browseButton, &QPushButton::clicked, this, &MainWindow::changePath);
|
||||
|
||||
updateLogMessages();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void MainWindow::changePath()
|
||||
{
|
||||
const auto directory = QFileDialog::getExistingDirectory(this, tr("Choose log folder"));
|
||||
if (directory.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ui->pathLineEdit->setText(directory);
|
||||
logParser->setLogFolder(directory);
|
||||
|
||||
updateLogMessages();
|
||||
}
|
||||
|
||||
void MainWindow::applyDateTimeFilter()
|
||||
{
|
||||
logParser->setStartDateTime(ui->startDateTimeEdit->dateTime());
|
||||
logParser->setEndDateTime(ui->endDateTimeEdit->dateTime());
|
||||
|
||||
updateLogMessages();
|
||||
}
|
||||
|
||||
void MainWindow::updateLogMessages()
|
||||
{
|
||||
logMessages = logParser->logMessagesByDateTime();
|
||||
updateLogTable();
|
||||
updateCharts();
|
||||
}
|
||||
|
||||
void MainWindow::updateLogTable()
|
||||
{
|
||||
logItemModel->removeRows(0, logItemModel->rowCount());
|
||||
|
||||
for (const auto& message: qAsConst(logMessages))
|
||||
{
|
||||
if (!DataTypes::isErrorMessage(message.type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dateItem = new QStandardItem();
|
||||
dateItem->setData(message.dateTime, Qt::DisplayRole);
|
||||
|
||||
auto startupItem = new QStandardItem();
|
||||
startupItem->setData(message.startupTime, Qt::DisplayRole);
|
||||
|
||||
auto typeItem = new QStandardItem();
|
||||
typeItem->setData(static_cast<int>(message.type), Qt::DisplayRole);
|
||||
|
||||
auto f1Item = new QStandardItem();
|
||||
f1Item->setData(message.f1, Qt::DisplayRole);
|
||||
|
||||
auto f2Item = new QStandardItem();
|
||||
f2Item->setData(message.f2, Qt::DisplayRole);
|
||||
|
||||
auto f3Item = new QStandardItem();
|
||||
f3Item->setData(message.f3, Qt::DisplayRole);
|
||||
|
||||
auto f4Item = new QStandardItem();
|
||||
f4Item->setData(message.f4, Qt::DisplayRole);
|
||||
|
||||
auto descriptionItem = new QStandardItem();
|
||||
descriptionItem->setData(DataTypes::messageString(message.type), Qt::DisplayRole);
|
||||
|
||||
logItemModel->appendRow({dateItem, startupItem, typeItem, f1Item, f2Item, f3Item, f4Item, descriptionItem});
|
||||
}
|
||||
|
||||
ui->logTableView->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
void MainWindow::updateCharts()
|
||||
{
|
||||
updateChart(inputChart.get(), [](const DataTypes::LogMessage& message){ return message.type == DataTypes::MessageType::LTM_PARAMS_MSG; });
|
||||
updateChart(outputChart.get(), [](const DataTypes::LogMessage& message){ return message.type == DataTypes::MessageType::LTM_PARAMS_OUT; });
|
||||
updateChart(adcChart.get(), [](const DataTypes::LogMessage& message){ return message.type == DataTypes::MessageType::LTM_PARAMS_ADC; });
|
||||
}
|
||||
|
||||
void MainWindow::updateChart(QtCharts::QChart* chart, std::function<bool (const DataTypes::LogMessage&)> condition)
|
||||
{
|
||||
QList<QPointF> voltagePoints;
|
||||
QList<QPointF> currentPoints;
|
||||
|
||||
for (const auto& message: qAsConst(logMessages))
|
||||
{
|
||||
if (condition(message))
|
||||
{
|
||||
voltagePoints.append({static_cast<qreal>(message.startupTime), static_cast<qreal>(message.f1)});
|
||||
currentPoints.append({static_cast<qreal>(message.startupTime), static_cast<qreal>(message.f2)});
|
||||
}
|
||||
}
|
||||
|
||||
QPen yellowPen(Qt::yellow);
|
||||
yellowPen.setWidth(3);
|
||||
|
||||
QPen redPen(Qt::red);
|
||||
redPen.setWidth(3);
|
||||
|
||||
auto voltageSeries = new QtCharts::QLineSeries();
|
||||
voltageSeries->setPen(yellowPen);
|
||||
voltageSeries->append(voltagePoints);
|
||||
voltageSeries->setName(tr("Voltage"));
|
||||
|
||||
auto currentSeries = new QtCharts::QLineSeries();
|
||||
currentSeries->setPen(redPen);
|
||||
currentSeries->append(currentPoints);
|
||||
currentSeries->setName(tr("Current"));
|
||||
|
||||
clearChart(chart);
|
||||
|
||||
chart->addSeries(voltageSeries);
|
||||
chart->addSeries(currentSeries);
|
||||
chart->createDefaultAxes();
|
||||
}
|
||||
|
||||
void MainWindow::clearChart(QtCharts::QChart* chart)
|
||||
{
|
||||
for (auto series: chart->series())
|
||||
{
|
||||
chart->removeSeries(series);
|
||||
delete series;
|
||||
}
|
||||
|
||||
for (auto axis: chart->axes())
|
||||
{
|
||||
chart->removeAxis(axis);
|
||||
delete axis;
|
||||
}
|
||||
}
|
||||
50
MainWindow.h
Normal file
50
MainWindow.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "DataTypes.h"
|
||||
|
||||
class QStandardItemModel;
|
||||
class LogParser;
|
||||
|
||||
namespace QtCharts
|
||||
{
|
||||
class QChart;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
public slots:
|
||||
void changePath();
|
||||
void applyDateTimeFilter();
|
||||
|
||||
void updateLogMessages();
|
||||
void updateLogTable();
|
||||
void updateCharts();
|
||||
|
||||
private:
|
||||
void updateChart(QtCharts::QChart* chart, std::function<bool(const DataTypes::LogMessage&)> condition);
|
||||
void clearChart(QtCharts::QChart* chart);
|
||||
|
||||
QScopedPointer<Ui::MainWindow> ui;
|
||||
|
||||
QScopedPointer<LogParser> logParser;
|
||||
QScopedPointer<QStandardItemModel> logItemModel;
|
||||
QList<DataTypes::LogMessage> logMessages;
|
||||
|
||||
QScopedPointer<QtCharts::QChart> inputChart;
|
||||
QScopedPointer<QtCharts::QChart> outputChart;
|
||||
QScopedPointer<QtCharts::QChart> adcChart;
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
184
MainWindow.ui
Normal file
184
MainWindow.ui
Normal file
@@ -0,0 +1,184 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>M1300 Log Viewer</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="1,1">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Date and time range</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDateTimeEdit" name="endDateTimeEdit">
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>End:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="applyDateTimeButton">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Start:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDateTimeEdit" name="startDateTimeEdit">
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Log location</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="pathLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="browseButton">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QTableView" name="logTableView"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="inputTab">
|
||||
<attribute name="title">
|
||||
<string>Input parameters</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="InteractiveChartView" name="inputChartView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="outputTab">
|
||||
<attribute name="title">
|
||||
<string>Output parameters</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="InteractiveChartView" name="outputChartView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="adcTab">
|
||||
<attribute name="title">
|
||||
<string>ADC data</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="InteractiveChartView" name="adcChartView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InteractiveChartView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>InteractiveChartView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user