Adds q2 repos to migrate

This commit is contained in:
torsten committed 2026-07-14 12:07:36 +02:00
1 parent ad1f62c4ee
commit 17f1c61c9e
991 files changed
+178451

No files matched your search

Executable
+289
View File
@@ -0,0 +1,289 @@
#
# Haupt CMakeLists.txt für das Projekt TDS
#
# $Id$
# $HeadURL$
# $Author$
#
# Setzen von CMAKE_INSTALL_PREFIX auf "/shd/CTC" falls nicht über Kommandozeile angegeben
#
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.0)
IF(POLICY CMP0069)
CMAKE_POLICY(SET CMP0069 NEW) # cmake >= 3.9.0 - INTERPROCEDURAL_OPTIMIZATION behavior
ENDIF()
IF(POLICY CMP0071)
CMAKE_POLICY(SET CMP0071 NEW) # cmake >= 3.10.0 - automatically process generated sources with AUTOMOC
ENDIF()
IF(POLICY CMP0072)
CMAKE_POLICY(SET CMP0072 NEW) # cmake >= 3.11.0 - prefer libOpenGL.so over legacy libGL.so
ENDIF()
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/shd/CTC" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
ENDIF()
#
# # Setzen von CMAKE_BUILD_TYPE auf "Debug" falls nicht über Kommandozeile angegeben
#
IF(NOT DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
ENDIF()
ADD_DEFINITIONS(-DEXPORT_BDV_TOPIC_AS_JSON)
SET(_ver "1.2.0")
IF(DEFINED LTS_VERSION_MAJOR AND DEFINED LTS_VERSION_MINOR AND DEFINED LTS_VERSION_PATCH)
SET(_ver "${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
ENDIF()
PROJECT(LTS VERSION ${_ver})
MESSAGE(STATUS "LTS Version: ${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
SET(LTS_VERSION_DATE "01.01.2018" CACHE STRING "The date when this software was compiled")
ADD_DEFINITIONS(-DLTS_VERSION_MAJOR=\"${LTS_VERSION_MAJOR}\")
ADD_DEFINITIONS(-DLTS_VERSION_MINOR=\"${LTS_VERSION_MINOR}\")
ADD_DEFINITIONS(-DLTS_VERSION_PATCH=\"${LTS_VERSION_PATCH}\")
ADD_DEFINITIONS(-DLTS_VERSION_DATE=\"${LTS_VERSION_DATE}\")
IF(JENKINS_BUILD_NUMBER)
ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"${JENKINS_BUILD_NUMBER}\")
ELSE()
ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"unknown\")
ENDIF()
ADD_DEFINITIONS(-DAPP6C)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_CXX_STANDARD 14)
SET(CMAKE_CXX_STANDARD_REQUIRED 14)
SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
IF(CMAKE_VERSION VERSION_GREATER 3.15.9)
OPTION(USE_UNITY_BUILDS "Use Unity builds to speed up compilation (cmake 3.16 or newer required!)" OFF)
IF (USE_UNITY_BUILDS)
SET(CMAKE_UNITY_BUILD ON)
SET(CMAKE_UNITY_BUILD_BATCH_SIZE 40)
ENDIF()
ENDIF()
IF(WIN32)
SET(EXTERNAL_LIBRARY_DIR "C:/Development/Projekte/SituationMap/ExtFw" CACHE STRING "Library dir with all external dependencies")
LIST(APPEND CMAKE_PREFIX_PATH "${EXTERNAL_LIBRARY_DIR}")
LIST(APPEND CMAKE_PROGRAM_PATH "${EXTERNAL_LIBRARY_DIR}/bin;${EXTERNAL_LIBRARY_DIR}/dev-utils/bin")
ENDIF()
ENABLE_TESTING()
INCLUDE(CTest)
CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY)
CONFIGURE_FILE(lts-cc.conf ${CMAKE_BINARY_DIR}/lts-cc.conf.distrib COPYONLY)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
IF(WIN32)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
ELSE(WIN32)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
ENDIF()
#
# Disallow in-source build
#
INCLUDE(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("In-Source build nicht erlaubt!")
#
# Qt ist wichtig - zuerst suchen
#
SET(CMAKE_AUTOMOC TRUE)
SET(QT_USE_IMPORTED_TARGETS TRUE)
FIND_PACKAGE(Qt5 5.9.0 COMPONENTS Concurrent Core Gui Location LinguistTools
Network OpenGL PrintSupport Sensors Multimedia
Sql Svg SerialPort Test UiTools WebSockets
WebEngineCore WebEngineWidgets Widgets
Xml XmlPatterns
REQUIRED)
MESSAGE(STATUS "Qt version is ${Qt5Core_VERSION}")
ADD_DEFINITIONS(-DQT_USE_QSTRINGBUILDER)
ADD_DEFINITIONS(-DQT_NO_CAST_TO_ASCII)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_ASCII)
ADD_DEFINITIONS(-DQT_NO_URL_CAST_FROM_STRING)
ADD_DEFINITIONS(-DQT_DEPRECATED_WARNINGS)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_BYTEARRAY)
#ADD_DEFINITIONS(-DQT_NO_DEPRECATED)
ADD_DEFINITIONS(-DQT_DISABLE_DEPRECATED_BEFORE=0x050900)
ADD_DEFINITIONS(-DQT_NO_FOREACH)
IF(NOT WIN32)
ADD_DEFINITIONS(-DQT_STRICT_ITERATORS)
ENDIF()
#
# Ein paar NGL-spezifische Macros
#
INCLUDE(NGLMacros)
#
# Projektspezifische Einstellungen?
#
NGL_INSTALL(SV AAR WS FILES lts-cc.conf DESTINATION . RENAME lts-cc.conf.distrib)
OPTION(ETS_MODE "Build for ETS (No B-Contamination etc)" OFF)
IF(ETS_MODE)
ADD_DEFINITIONS(-DETS_MODE)
ENDIF()
OPTION(TABLET_MODE "Build for TABLET " OFF)
IF(TABLET_MODE)
ADD_DEFINITIONS(-DTABLET_MODE)
ENDIF()
OPTION(GUEZ_MODE "Build for GUEZ " ON)
IF(GUEZ_MODE)
ADD_DEFINITIONS(-DGUEZ_MODE)
ENDIF()
#
# Doxygen
#
INCLUDE(DoxygenMacros)
IF(NOT DOXYGEN_OUT_DIR)
SET(DOXYGEN_OUT_DIR ${CMAKE_BINARY_DIR}/doxygen)
ENDIF()
ADD_DOXYGEN_TARGET(TDS ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
${DOXYGEN_OUT_DIR})
IF(NOT DOXYGEN_OUT_DIR_2025)
SET(DOXYGEN_OUT_DIR_2025 ${CMAKE_BINARY_DIR}/doxygen2025)
ENDIF()
ADD_DOXYGEN_TARGET(TDS2025 ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile2025.in ${CMAKE_BINARY_DIR}/Doxyfile
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
${DOXYGEN_OUT_DIR_2025})
#
# Compilerflags
#
IF(WIN32)
ADD_DEFINITIONS(-DWIN32 -D_USE_MATH_DEFINES -D_WIN32_WINNT=0x0501 -DUNICODE)
ELSE()
ADD_DEFINITIONS(-D_LINUX)
ENDIF()
IF(MSVC)
# C4250: 'class1' : inherits 'class2::member' via dominance
# C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
# C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
# C4496: 'function': was declared deprecated
# C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data
ADD_DEFINITIONS(-wd4250
-wd4251
-wd4290
-wd4496
-wd4267
-D_CRT_SECURE_NO_DEPRECATE
-D_CRT_NONSTDC_NO_DEPRECATE
-D_SCL_SECURE_NO_WARNINGS
-D_WINSOCK_DEPRECATED_NO_WARNINGS
/bigobj
)
# komplette Programmoptimierung
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
# .pdb - Datei nicht gefunden
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4099")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4099")
# min() und max() nicht als Macros
ADD_DEFINITIONS(-DNOMINMAX)
SET(CMAKE_MSVCIDE_RUN_PATH "" CACHE PATH "Run path to use when starting programs from MSVC")
ENDIF()
IF(UNIX)
# Alle Warnungen aktivieren
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -Wmissing-include-dirs")
# disable
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overloaded-virtual")
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.0)
MESSAGE(FATAL_ERROR "gcc 4.8 or higher is required to build TDS: ${CMAKE_CXX_COMPILER_VERSION}")
ENDIF()
IF(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.99)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-attribute=const")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-types")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-methods")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
ENDIF()
ENDIF()
ENDIF()
OPTION(USE_IPO "Use interprocedural optimizations (cmake 3.9 or higher required)" OFF)
IF (USE_IPO AND CMAKE_VERSION VERSION_GREATER 3.8.9)
INCLUDE(CheckIPOSupported)
check_ipo_supported(RESULT result OUTPUT output)
IF(result)
SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
ELSE()
MESSAGE(WARNING "IPO is not supported: ${output}")
ENDIF()
ENDIF()
OPTION(USE_ASAN "Use Address Sanitizer (current Clang only)" OFF)
IF (USE_ASAN)
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
MESSAGE(STATUS "enable Address Sanitizer with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
ELSE()
MESSAGE(STATUS "Address Sanitizer only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
ENDIF()
ENDIF(USE_ASAN)
OPTION(USE_UBSAN "Use UndefinedBehavior Sanitizer (current Clang only)" OFF)
IF (USE_UBSAN)
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
ELSE()
MESSAGE(STATUS "UndefinedBehavior only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
ENDIF()
ENDIF(USE_UBSAN)
OPTION(BUILD_RPM "Build a RPM - install script in scripts subdir" OFF)
IF(BUILD_RPM)
ADD_SUBDIRECTORY(scripts)
ELSE()
ADD_DEFINITIONS(-DLTS_DEBUG)
ENDIF()
IF (NOT DEFINED _pname)
IF(GUEZ_MODE)
SET (_pname "guez")
ADD_DEFINITIONS(-DPROJECTBUILD="guez")
MESSAGE(STATUS "NO ProjectName givin! BUT GUEZ_MODE set PROJECTBUILD to guez")
ELSE()
MESSAGE(WARNING "NO ProjectName givin! Can't install coresponding lts-cc.conf! and PROJECTBUILD is empty")
ADD_DEFINITIONS(-DPROJECTBUILD="")
ENDIF()
ELSE()
MESSAGE(STATUS "ProjectName givin! PROJECTBUILD is ${_pname} ")
ADD_DEFINITIONS(-DPROJECTBUILD=\"${_pname}\")
ENDIF()
#
# DDS benoetigt zwingend RTI
#
FIND_PACKAGE(RTI REQUIRED)
ADD_SUBDIRECTORY(TetraIF)
ADD_SUBDIRECTORY(Z/src)
ADD_SUBDIRECTORY(Lts)
# at last, to make sure we get all targets in NGL_TS_TARGETS property
ADD_SUBDIRECTORY(translations)
#-----------------------------------------------------------------------------------------------------
OPTION(BUILD_QAV "Build script for local QAV analysis" OFF)
IF (BUILD_QAV)
ADD_SUBDIRECTORY(qav)
ENDIF()
+9
View File
@@ -0,0 +1,9 @@
#
# $Id$
# $HeadURL$
# $Author$
#
ADD_SUBDIRECTORY(CoPrtCnv)
ADD_SUBDIRECTORY(LogView)
ADD_SUBDIRECTORY(PrtCnv)
+30
View File
@@ -0,0 +1,30 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(my_SRCS
tetra_telegram_ids.h
CoPrtCnvCentralTelegram.cpp
CoPrtCnvCentralTelegram.hpp
CoPrtCnvHexDumpHelper.cpp
CoPrtCnvHexDumpHelper.hpp
CoPrtCnvInjectionHeader.hpp
CoPrtCnvLogHeader.hpp
CoPrtCnvRadioTelegram.cpp
CoPrtCnvRadioTelegram.hpp
CoPrtCnvTelegramConverter.hpp
CoPrtCnvTelegramConverterNewIcd.cpp
)
NGL_ADD_LIBRARY2(AAR SV CoPrtCnv SHARED ${my_SRCS} ${my_HDRS})
NGL_TARGET_LINK_LIBRARIES(CoPrtCnv
PUBLIC
NGLLogger
tabTelegrams
)
NGL_TARGET_INCLUDE_DIRECTORIES(CoPrtCnv
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/../
)
@@ -0,0 +1,82 @@
#include "CoPrtCnvCentralTelegram.hpp"
#include <QJsonDocument>
namespace N_CoPrtCnv
{
void CoPrtCnvCentralTelegram::setData(const QByteArray &data)
{
m_data = data;
m_json = QJsonObject();
}
QByteArray CoPrtCnvCentralTelegram::data()
{
ensureByteArray();
return m_data;
}
QJsonObject CoPrtCnvCentralTelegram::json()
{
ensureJson();
return m_json;
}
QJsonObject CoPrtCnvCentralTelegram::jsonData()
{
return json()[QStringLiteral("data")].toObject();
}
TrainingAreaBase::TetraIcd::TelegramId CoPrtCnvCentralTelegram::telegramId()
{
if (m_telegramId != TrainingAreaBase::TetraIcd::UNKNOWN)
return m_telegramId;
ensureJson();
m_telegramId = static_cast<TrainingAreaBase::TetraIcd::TelegramId>(m_json[QStringLiteral("typeId")].toInt());
return m_telegramId;
}
void CoPrtCnvCentralTelegram::setCounter(qint32 counter)
{
if (m_json.isEmpty())
m_json = QJsonDocument::fromJson(m_data).object();
m_json[QStringLiteral("counter")] = counter;
m_data.clear();
}
qint32 CoPrtCnvCentralTelegram::counter()
{
ensureJson();
const QString key(QStringLiteral("counter"));
const QJsonValue sendCounter(m_json[key]);
if (!sendCounter.isDouble())
throw TrainingAreaBase::TetraIcd::JsonException(m_json, key);
return sendCounter.toInt(-1);
}
void CoPrtCnvCentralTelegram::ensureJson()
{
if (m_json.isEmpty())
{
if (m_data.isEmpty())
return;
m_json = QJsonDocument::fromJson(m_data).object();
}
}
void CoPrtCnvCentralTelegram::ensureByteArray()
{
if (m_data.isEmpty())
{
if (m_json.isEmpty())
return;
m_data = QJsonDocument(m_json).toJson(QJsonDocument::Compact);
}
}
}
@@ -0,0 +1,60 @@
#pragma once
#include <QJsonObject>
#include <QByteArray>
#include <CoPrtCnv/coprtcnv_export.h>
#include <TrainingAreaBase/training_area_telegrams.h>
namespace N_CoPrtCnv
{
class COPRTCNV_EXPORT CoPrtCnvCentralTelegram final
{
public:
explicit CoPrtCnvCentralTelegram(TrainingAreaBase::TetraIcd::TelegramId telegramId)
: m_telegramId(telegramId)
{}
explicit CoPrtCnvCentralTelegram(const QByteArray &data)
: m_data(data)
, m_telegramId(TrainingAreaBase::TetraIcd::UNKNOWN)
{}
CoPrtCnvCentralTelegram(const QByteArray &data, TrainingAreaBase::TetraIcd::TelegramId telegramId)
: m_data(data)
, m_telegramId(telegramId)
{}
CoPrtCnvCentralTelegram(const QByteArray &data, const QJsonObject &json, TrainingAreaBase::TetraIcd::TelegramId telegramId)
: m_data(data)
, m_json(json)
, m_telegramId(telegramId)
{}
explicit CoPrtCnvCentralTelegram(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram &tele)
: m_telegramId(tele.id())
{
m_json[QStringLiteral("type")] = tele.type();
m_json[QStringLiteral("typeId")] = tele.id();
m_json[QStringLiteral("data")] = tele.toJson();
}
void setData(const QByteArray &data);
QByteArray data();
QJsonObject json();
QJsonObject jsonData();
TrainingAreaBase::TetraIcd::TelegramId telegramId();
void setCounter(qint32 counter);
qint32 counter();
private:
void ensureJson();
void ensureByteArray();
private:
QByteArray m_data;
QJsonObject m_json;
TrainingAreaBase::TetraIcd::TelegramId m_telegramId;
};
}
+240
View File
@@ -0,0 +1,240 @@
#include "CoPrtCnvHexDumpHelper.hpp"
#include "CoPrtCnvRadioTelegram.hpp"
#include <QtCore/QByteArray>
#include <NGLLogger/NGLLoggerBootstrap.h>
static std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegram* sammelTelegram)
{
const int ANZAHL_POS = 5;
const int SIZE_POS = sammelTelegram->getTelID() == GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN ? 2 : 1;
std::stringstream sstream;
unsigned int cnt = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS, SIZE_POS);
for (unsigned int i = 0; i < cnt; ++i) {
uint16_t telId = sammelTelegram->getPayloadDataUInt32(ANZAHL_POS + SIZE_POS + 2 * i, 2);
sstream << telId << " ";
}
return sstream.str();
}
QByteArray telegramId2String(gef_telegramm_id_et telId)
{
const char *str = nullptr;
switch (telId)
{
case GEF_BESTAETIGUNG: str = "GEF_BESTAETIGUNG"; break;
case GEF_INIT: str = "GEF_INIT"; break;
case GEF_MANIPULATIONSMELDUNG: str = "GEF_MANIPULATIONSMELDUNG"; break;
case GEF_UMGEBUNGS_MELDUNG2: str = "GEF_UMGEBUNGS_MELDUNG2"; break;
case GEF_AUFFORDERUNG_BITE_MELDUNG: str = "GEF_AUFFORDERUNG_BITE_MELDUNG"; break;
case GEF_BITE_MELDUNG2: str = "GEF_BITE_MELDUNG2"; break;
case GEF_LIZENSIERUNG_TNE: str = "GEF_LIZENSIERUNG_TNE"; break;
case GEF_BETRIEBSZUSTAND_AUSSTATTUNG: str = "GEF_BETRIEBSZUSTAND_AUSSTATTUNG"; break;
case GEF_KONFIGURATION_WIRKMODELL: str = "GEF_KONFIGURATION_WIRKMODELL"; break;
case GEF_ANFORDERUNG_KONFIGURATIONSDATEN: str = "GEF_ANFORDERUNG_KONFIGURATIONSDATEN"; break;
case GEF_KONFIGURATIONSMELDUNG: str = "GEF_KONFIGURATIONSMELDUNG"; break;
case GEF_FEHLERMELDUNG_GFD: str = "GEF_FEHLERMELDUNG_GFD"; break;
case GEF_WIEDERHERSTELLUNG_FUNKBEREITSCHAFT: str = "GEF_WIEDERHERSTELLUNG_FUNKBEREITSCHAFT"; break;
case GEF_POSITIONS_MELDUNG: str = "GEF_POSITIONS_MELDUNG"; break;
case GEF_POSITIONS_MELDUNG_MIT_TEILNEHMER: str = "GEF_POSITIONS_MELDUNG_MIT_TEILNEHMER"; break;
case GEF_POSITIONS_MELDUNG_LFZ: str = "GEF_POSITIONS_MELDUNG_LFZ"; break;
case GEF_IPS_POSITIONSDATEN: str = "GEF_IPS_POSITIONSDATEN"; break;
case GEF_SCHIEDSRICHTERKOMMANDO: str = "GEF_SCHIEDSRICHTERKOMMANDO"; break;
case GEF_WIRKFELD_EINZELGESCHOSS: str = "GEF_WIRKFELD_EINZELGESCHOSS"; break;
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER: str = "GEF_WIRKFELD_FLAECHENDECKENDES_FEUER"; break;
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP: str = "GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP"; break;
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN: str = "GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN"; break;
case GEF_WIRKFELD_MINENSPERRE: str = "GEF_WIRKFELD_MINENSPERRE"; break;
case GEF_WIRKFELD_STATUS_MINENSPERRE: str = "GEF_WIRKFELD_STATUS_MINENSPERRE"; break;
case GEF_WIRKFELD_A_KAMPFMITTEL: str = "GEF_WIRKFELD_A_KAMPFMITTEL"; break;
case GEF_WIRKFELD_C_KAMPFMITTEL: str = "GEF_WIRKFELD_C_KAMPFMITTEL"; break;
case GEF_DEAKTIVIERUNG_WIRKFELD: str = "GEF_DEAKTIVIERUNG_WIRKFELD"; break;
case GEF_WIRKFELD_AENDERUNG_BEZEICHNER: str = "GEF_WIRKFELD_AENDERUNG_BEZEICHNER"; break;
case GEF_DEAKTIVIERUNG_EINZELMINE: str = "GEF_DEAKTIVIERUNG_EINZELMINE"; break;
case GEF_REAKTIVIERUNG_DUS_MINE: str = "GEF_REAKTIVIERUNG_DUS_MINE"; break;
case GEF_DEFINITION_IED: str = "GEF_DEFINITION_IED"; break;
case GEF_ZUSTAND_IED: str = "GEF_ZUSTAND_IED"; break;
case GEF_STATUS_EINZELMINENSIMULATOR: str = "GEF_STATUS_EINZELMINENSIMULATOR"; break;
case GEF_WIRKFELD_EINZELMINENSIMULATOR: str = "GEF_WIRKFELD_EINZELMINENSIMULATOR"; break;
case GEF_TREFFER_EREIGNIS_DUS: str = "GEF_TREFFER_EREIGNIS_DUS"; break;
case GEF_TREFFER_EREIGNIS_WIRKSIMULATION: str = "GEF_TREFFER_EREIGNIS_WIRKSIMULATION"; break;
case GEF_TREFFER_AUSLOESUNG: str = "GEF_TREFFER_AUSLOESUNG"; break;
case GEF_SCHIEDSRICHTEREINGRIFF: str = "GEF_SCHIEDSRICHTEREINGRIFF"; break;
case GEF_SELEKTIVE_AUFMUNITIONIERUNG: str = "GEF_SELEKTIVE_AUFMUNITIONIERUNG"; break;
case GEF_TREFFER_EREIGNIS_SEKUNDAERWIRKUNG: str = "GEF_TREFFER_EREIGNIS_SEKUNDAERWIRKUNG"; break;
case GEF_TREFFER_EREIGNIS_DUS_IPS: str = "GEF_TREFFER_EREIGNIS_DUS_IPS"; break;
case GEF_TREFFER_EREIGNIS_WIRKSIMULATION_IPS: str = "GEF_TREFFER_EREIGNIS_WIRKSIMULATION_IPS"; break;
case GEF_TAKTISCHER_STATUS: str = "GEF_TAKTISCHER_STATUS"; break;
case GEF_FUNKTIONSRAUM: str = "GEF_FUNKTIONSRAUM"; break;
case GEF_EINTRETEN_FUNKTIONSRAUM: str = "GEF_EINTRETEN_FUNKTIONSRAUM"; break;
case GEF_DEAKTIVIEREN_FUNKTIONSRAUM: str = "GEF_DEAKTIVIEREN_FUNKTIONSRAUM"; break;
case GEF_DATENVERKEHR_SRT_TDS: str = "GEF_DATENVERKEHR_SRT_TDS"; break;
case GEF_DATENVERKEHR_TDS_SRT: str = "GEF_DATENVERKEHR_TDS_SRT"; break;
case GEF_DATENVERKEHR_DMF_TDS: str = "GEF_DATENVERKEHR_DMF_TDS"; break;
case GEF_DATENVERKEHR_TDS_DMF: str = "GEF_DATENVERKEHR_TDS_DMF"; break;
case GEF_NACHFORDERUNG_BROADCAST_TELEGRAMME: str = "GEF_NACHFORDERUNG_BROADCAST_TELEGRAMME"; break;
case GEF_NOP: str = "GEF_NOP"; break;
case GEF_SONDERSENSORIK_BETRIEBSZUSTAND: str = "GEF_SONDERSENSORIK_BETRIEBSZUSTAND"; break;
case GEF_SONDERSENSORIK_FAHRSPUR: str = "GEF_SONDERSENSORIK_FAHRSPUR"; break;
case GEF_SONDERSENSORIK_DATEN: str = "GEF_SONDERSENSORIK_DATEN"; break;
case GEF_SONDERSENSORIK_MIVANH_VERLEGEDATEN: str = "GEF_SONDERSENSORIK_MIVANH_VERLEGEDATEN"; break;
case GEF_SONDERSENSORIK_WMIV_VERLEGEDATEN: str = "GEF_SONDERSENSORIK_WMIV_VERLEGEDATEN"; break;
case GEF_SONDERSENSORIK_MIVANH_VERLEGEPOSITION: str = "GEF_SONDERSENSORIK_MIVANH_VERLEGEPOSITION"; break;
case GEF_SPRACHAUSWAHL: str = "GEF_SPRACHAUSWAHL"; break;
case GEF_ALLGEMEINE_NACHRICHT: str = "GEF_ALLGEMEINE_NACHRICHT"; break;
case GEF_ECHO_ON_OFF: str = "GEF_ECHO_ON_OFF"; break;
case GEF_ESW_MELDUNG: str = "GEF_ESW_MELDUNG"; break;
case GEF_WF_SAMMELDEAKTIVIERUNG: str = "GEF_WF_SAMMELDEAKTIVIERUNG"; break;
case GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN: str = "GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN"; break;
case GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM: str = "GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM"; break;
case GEF_DATENVERKEHR_GEOP_TDS: str = "GEF_DATENVERKEHR_GEOP_TDS"; break;
case GEF_DATENVERKEHR_TDS_GEOP: str = "GEF_DATENVERKEHR_TDS_GEOP"; break;
case GEF_DATENVERKEHR_TGTC_TDS: str = "GEF_DATENVERKEHR_TGTC_TDS"; break;
case GEF_DATENVERKEHR_TDS_TGTC: str = "GEF_DATENVERKEHR_TDS_TGTC"; break;
case GEF_GERAETEEREIGNIS: str = "GEF_GERAETEEREIGNIS"; break;
case GEF_WAFFENZUORDNUNG: str = "GEF_WAFFENZUORDNUNG"; break;
case GEF_MUNITIONSVORRAT_EINER_ZUGEORDNETEN_WAFFE: str = "GEF_MUNITIONSVORRAT_EINER_ZUGEORDNETEN_WAFFE"; break;
case GEF_FEUEREREIGNIS_MIT_WAFFENZUORDNUNG: str = "GEF_FEUEREREIGNIS_MIT_WAFFENZUORDNUNG"; break;
case GEF_AUSLOESUNG_DUS_TREFFER: str = "GEF_AUSLOESUNG_DUS_TREFFER"; break;
case GEF_ANFORDERUNG_SW_VERSION: str = "GEF_ANFORDERUNG_SW_VERSION"; break;
case GEF_SW_VERSIONSMELDUNG: str = "GEF_SW_VERSIONSMELDUNG"; break;
case GEF_TECHNIK_FUNKTIONSRAUM: str = "GEF_TECHNIK_FUNKTIONSRAUM"; break;
case GEF_TEILNEHMERMODE_SETZEN: str = "GEF_TEILNEHMERMODE_SETZEN"; break;
case GEF_TEILNEHMERMODE_MELDUNG: str = "GEF_TEILNEHMERMODE_MELDUNG"; break;
case GEF_TEILNEHMERMODE_ANFORDERN: str = "GEF_TEILNEHMERMODE_ANFORDERN"; break;
case GEF_TEILNEHMER_KONFIG_ANTWORT: str = "GEF_TEILNEHMER_KONFIG_ANTWORT"; break;
case GEF_TEILNEHMER_KONFIG_SETZEN: str = "GEF_TEILNEHMER_KONFIG_SETZEN"; break;
case GEF_TEILNEHMER_KONFIG_ANFORDERN: str = "GEF_TEILNEHMER_KONFIG_ANFORDERN"; break;
case GEF_SANITAETSDIENST_INSTANDSETZUNG: str = "GEF_SANITAETSDIENST_INSTANDSETZUNG"; break;
case GEF_SANITAETSDIENST_INSTANDSETZUNG_PVSAN: str = "GEF_SANITAETSDIENST_INSTANDSETZUNG_PVSAN"; break;
case GEF_BESTANDSMELDUNG_SANITAETSMATERIAL: str = "GEF_BESTANDSMELDUNG_SANITAETSMATERIAL"; break;
case GEF_GEFECHTSFELDTELEGRAMM: str = "GEF_GEFECHTSFELDTELEGRAMM"; break;
}
Q_ASSERT(str);
if (!str)
str = "Unknown";
return str + QByteArray(" (") + QByteArray::number(int(telId)) + ")";
}
QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wirkfeldTyp)
{
switch(wirkfeldTyp)
{
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::MineArea:
return QLatin1String("MINENSPERRE");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionArea:
return QLatin1String("FLAECHENFEUER");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionSingle:
return QLatin1String("EINZELFEUER");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::NContamination:
return QLatin1String("A_KAMPF");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::CContamination:
return QLatin1String("C_KAMPF");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::FunctionalArea:
return QLatin1String("FUNKTIONS_RAUM");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::TechnicalArea:
return QLatin1String("FUNKTIONS_RAUM_TECHNIK");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::GasPipeDetonation:
return QLatin1String("GAS_PIPE_DETONATION");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::SpecialArea:
return QLatin1String("SPECIAL_AREA");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::Unknown:
return QLatin1String("DUS");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DusSingleMineSimulator:
return QLatin1String("DUS_SINGLE_MINE_SIMULATOR");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::BeStillWarning:
return QLatin1String("BE_STILL_WARNING");
}
return QStringLiteral("Unknown Wirkfeldtyp <%1>").arg(static_cast<int>(wirkfeldTyp));
}
static inline QString wirkfeldTyp2Str(int typ)
{
return wirkfeldTyp2Str(static_cast<TrainingAreaBase::TetraIcd::AreaEffectSimulationType>(typ));
}
void dumpTelegram(NGL::INGLLogger &m_logger, int id, N_CoPrtCnv::CoPrtCnvRadioTelegram *a_radioTelegram, const char *prefix)
{
if(!m_logger.isDebugEnabled())
return;
if (!prefix)
prefix = "";
const QByteArray commonLog(prefix + QByteArray("BC: ") + QByteArray::number(id) +
", " + telegramId2String(a_radioTelegram->getTelID()));
switch (a_radioTelegram->getTelID())
{
case GEF_DEAKTIVIERUNG_WIRKFELD:
case GEF_WIRKFELD_AENDERUNG_BEZEICHNER:
{
uint8_t wirkfeldTyp = a_radioTelegram->getPayloadDataUInt32(5, 1);
uint16_t wirkfeldKennung = a_radioTelegram->getPayloadDataUInt32(6, 2);
DEBUG_LOG(m_logger) << commonLog
<< ", type: " << wirkfeldTyp2Str(wirkfeldTyp) << ", kennung: "
<< wirkfeldKennung;
break;
}
case GEF_DEAKTIVIERUNG_EINZELMINE: {
uint32_t wirkfeldKennung = a_radioTelegram->getPayloadDataUInt32(9, 2);
uint32_t minenKennung = a_radioTelegram->getPayloadDataUInt32(11, 2);
DEBUG_LOG(m_logger) << commonLog
<< ", kennung: " << wirkfeldKennung << ", mineId: " << minenKennung;
break;
}
case GEF_WIRKFELD_STATUS_MINENSPERRE:
case GEF_WIRKFELD_A_KAMPFMITTEL:
case GEF_WIRKFELD_MINENSPERRE:
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER:
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP:
case GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN:
case GEF_FUNKTIONSRAUM:
case GEF_DEAKTIVIEREN_FUNKTIONSRAUM:
{
uint16_t wirkfeldKennung = a_radioTelegram->getPayloadDataUInt32(5, 2);
DEBUG_LOG(m_logger) << commonLog << ", kennung: " << wirkfeldKennung;
break;
}
case GEF_TECHNIK_FUNKTIONSRAUM:
{
uint16_t funktionsraumkennung = a_radioTelegram->getPayloadDataUInt32(5, 2);
uint8_t funktionsraumtyp = a_radioTelegram->getPayloadDataUInt32(7, 1);
DEBUG_LOG(m_logger) << commonLog
<< ", kennung: " << funktionsraumkennung
<< " type: " << int(funktionsraumtyp);
break;
}
case GEF_WF_SAMMELDEAKTIVIERUNG:
case GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN:
case GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM:
DEBUG_LOG(m_logger) << commonLog << ", Ids: " << dumpSammeldeaktivierung(a_radioTelegram);
break;
case GEF_NOP:
{
uint16_t bcFrom = a_radioTelegram->getPayloadDataUInt32(3, 2);
uint16_t bcTo = a_radioTelegram->getPayloadDataUInt32(5, 2);
DEBUG_LOG(m_logger) << prefix
<< commonLog
<< ", from BC " << bcFrom << " to " << bcTo;
break;
}
default:
DEBUG_LOG(m_logger) << commonLog;
break;
}
}
@@ -0,0 +1,32 @@
#pragma once
#include <QtCore/QString>
#include <NGLLogger/INGLLogger.h>
#include <TrainingAreaBase/training_area_telegrams.h>
#include <CoPrtCnv/coprtcnv_export.h>
#include "tetra_telegram_ids.h"
namespace N_CoPrtCnv
{
class CoPrtCnvRadioTelegram;
}
COPRTCNV_EXPORT QByteArray telegramId2String(gef_telegramm_id_et telId);
COPRTCNV_EXPORT void dumpTelegram(NGL::INGLLogger &m_logger,
int id,
N_CoPrtCnv::CoPrtCnvRadioTelegram *a_radioTelegram,
const char *prefix = nullptr);
COPRTCNV_EXPORT QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wirkfeldTyp);
@@ -0,0 +1,52 @@
#pragma once
#include <stdint.h>
namespace N_CoPrtCnv
{
struct CoPrtCnvInjectionHeader
{
uint32_t m_Id1;
uint32_t m_Id2;
enum Destination
{
eUnknown = 0,
eCentral = 1,
eRadio = 2
} m_Kind;
uint16_t m_Size;
CoPrtCnvInjectionHeader()
: m_Id1(0x12345678),
m_Id2(0x78236239),
m_Kind(eUnknown),
m_Size(0)
{}
bool isIdCorrect() const { return (m_Id1 == 0x12345678 && m_Id2 == 0x78236239); }
};
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include <stdint.h>
namespace N_CoPrtCnv
{
struct CoPrtCnvLogHeader
{
enum E_CoPrtCnvProtocol
{
e_DestProtocolCentral = 0,
e_DestProtocolWls = 1,
e_DestProtocolTetra = 5,
e_DestProtocolMax = 6,
e_DestProtocolMask = 0x0000000F,
e_DestDirectionMask = 0xC0000000,
e_DestReceive = 0x40000000,
e_DestSend = 0xC0000000
};
short m_Length = 0;
short m_Version = 0;
int m_Priority = 0;
int m_Protocol = 0;
int m_Reserved = 0;
uint64_t m_Time = 0;
};
}
File diff suppressed because it is too large. Load diff
+604
View File
@@ -0,0 +1,604 @@
#pragma once
#include <set>
#include <map>
#include <memory>
#include <vector>
#include <QByteArray>
#include <CoPrtCnv/coprtcnv_export.h>
#include "tetra_telegram_ids.h"
namespace NGL
{
class INGLLogger;
}
namespace N_CoPrtCnv
{
enum class E_LicensingKind
{
Success = 0,
Rejected = 1,
Unlicense = 2
};
enum class E_LicensingErrorCode
{
Ok = 0,
Selftest = 1,
Battery = 2,
Configuration = 3,
Unlicense = 4,
IdentityDenied = 5
};
class COPRTCNV_EXPORT CoPrtCnvRadioTelegram
{
public:
enum E_Flags
{
e_FlagsNone = 0x00,
e_StorageAllowed = 0x10,
e_GroupServiceOrOnlyStandardReportAllowed = 0x20,
e_ReceivedConfirmationRequested = 0x40,
e_ConsumedConfirmationRequested = 0x80
};
enum E_ProtocolIdentifier
{
e_SimpleTextMessagingWithoutSDS_TL = 0x02,
e_SimpleGPS_WithoutSDS_TL = 0x03,
e_TDSMessageWithoutSDS_TL = 0x50,
e_UsingSDS_TL = 0x80,
e_SimpleTextMessagingUsingSDS_TL = 0x82,
e_SimpleGPS_UsingSDS_TL = 0x83,
e_LoginTest = 0x1D
};
enum E_FragmentStatus
{
e_NotFragmented = 0x00,
e_FirstFragment = 0x40,
e_MiddleFragment = 0xC0,
e_LastFragment = 0x80,
e_FragmentStatusMask = 0xC0,
e_Checksum = 0x20,
e_CounterMask = 0x0F,
e_NormalTelegram = 0x00,
e_LoginTelegram = 0x02,
e_DgpsTelegram = 0x03
};
struct PrtCnvRadioGwHeader
{
uint8_t m_MagicNumber;
uint8_t m_Counter;
uint16_t m_Length;
};
enum E_PDU_Type
{
e_RegisterInd = 0,
e_RegisterRsp = 1,
e_DataIndReq = 2,
e_ReportIndReq = 3,
e_StatusIndReq = 4,
e_GroupMonitorReq = 6,
e_AirInterfaceLoadReq = 8,
e_AirLoadHyterra = 19
};
enum E_RegistrationStatus
{
e_IssiSuccessfulRegistered = 0,
e_DuplicateISSI = 1,
e_InvalidISSI = 2,
e_InvalidIpAddress = 3
};
enum E_DeliveryStatusForTL_Report
{
e_SDS_ReceiptAcknowledgedByDestination = 0x00,
e_SDS_ConsumedByDestination = 0x02,
e_SourceIsNotAuthorizedForSDS = 0x43,
e_DestinationIsNotAuthorizedForSDS = 0x44,
e_UnknownDestinationAddress = 0x45,
e_DeliveryFailed = 0x4A,
e_DestinationNotRegisteredOnSystem = 0x4B,
e_DestinationQueueFull = 0x4C,
e_MessageTooLong = 0x4D,
e_DestinationHostPC_NotConnected = 0x4F,
e_ProtocolNotSupported = 0x50,
e_DataCodingSchemeNotSupported = 0x51,
e_DestinationNotReachable = 0x5A
};
enum E_LoginStatus
{
e_LoginRequest = 0x40,
e_LoginAccept = 0x80,
e_LoginReject = 0xC0,
e_LoginStatusMask = 0xC0,
e_LoginMastering = 0x20,
e_LoginNoExerciseAssignment = 0x00,
e_LoginOtherEqId = 0x02,
e_LoginOtherISSI = 0x04,
e_LoginOtherExercise = 0x06,
};
static constexpr uint8_t MAGIC_NUMBER = 0xA5;
static constexpr uint16_t DATA_IND_REQ_WITH_TL_HEADER_LENGTH = 22;
static constexpr uint16_t DATA_IND_REQ_HEADER_LENGTH = 27;
static constexpr uint16_t DATA_IND_REQ_HEADER_LENGTH_WITHOUT_PAYLOAD_HEADER = DATA_IND_REQ_HEADER_LENGTH -1;
static constexpr uint16_t DATA_IND_REQ_NO_TL_HEADER_LENGTH = 14;
static constexpr uint16_t MAX_RADIO_TELEGRAM_PAYLOAD_LENGTH = 249;
static constexpr uint16_t PAYLOAD_STATUS_LENGTH = 1;
static constexpr uint8_t MAX_NBR_OF_FRAGMENTS = 16;
explicit CoPrtCnvRadioTelegram(const uint32_t a_sourceISSI);
explicit CoPrtCnvRadioTelegram(const uint32_t a_sourceISSI, const std::set<uint32_t> &groups);
explicit CoPrtCnvRadioTelegram(const uint32_t a_sourceISSI, const E_DeliveryStatusForTL_Report a_delivery);
explicit CoPrtCnvRadioTelegram(const QByteArray &a_data);
explicit CoPrtCnvRadioTelegram(const gef_telegramm_id_et a_telegramId, const uint16_t a_payloadSize, const uint16_t a_identity);
explicit CoPrtCnvRadioTelegram(const E_LoginStatus a_loginTelegramStatus, const uint16_t a_identity, uint32_t a_issi);
void setLoginIssis(int hostIssi, int groupIssi1, int groupIssi2);
explicit CoPrtCnvRadioTelegram(const std::shared_ptr<CoPrtCnvRadioTelegram> &a_bigTelegram,
const uint8_t a_fragmentIndex, bool &a_error);
virtual ~CoPrtCnvRadioTelegram();
void fixupTelegramIdForEts(bool convertToEtsId);
static void setEtsMode(bool bIsEtsMode);
void setPayload1Byte(uint8_t a_value);
void setPayload2Byte(uint16_t a_value);
void setPayload3Byte(uint32_t a_value);
void setPayload4Byte(uint32_t a_value);
void setPayloadData(uint32_t a_value, const uint8_t a_size);
void setPayloadData(const uint8_t a_value) { return setPayload1Byte(a_value); }
void setPayloadData(const uint8_t *a_data, const uint16_t a_size);
const char *getData() const { return m_data.data(); }
char *getData() { return m_data.data(); }
QByteArray data() const { return m_data; }
int getSize() const { return m_data.size(); }
gef_telegramm_id_et getTelID() const;
uint8_t zaehler() const;
void setZaehler(const uint8_t a_counter);
uint32_t getPayloadDataUInt32(size_t a_offset, uint16_t a_size) const;
uint8_t getPayloadDataUInt8(size_t a_offset) const;
uint32_t getDestISSI() const;
uint16_t getIdentity() const;
void setSrcISSI(const uint32_t a_ISSI);
bool mustBroadcastBeSet() const;
void setBroadcastIndex(const uint16_t a_broadcastIndex);
void setDestISSI(const uint32_t a_ISSI);
CoPrtCnvRadioTelegram::E_PDU_Type getPDU_Type() const;
CoPrtCnvRadioTelegram::E_FragmentStatus getFragmentStatus() const;
uint8_t getFragmentCounter() const;
bool isCrcOk() const;
uint32_t getSrcISSI() const;
bool isLoginTelegram() const;
bool mustBeFragmented() const;
const uint8_t *getPayloadDataPtr(uint16_t a_offset) const;
uint8_t *getPayloadDataPtr(uint16_t a_offset);
virtual uint16_t getPayloadSize() const;
static QByteArray getUnfragmentedData(const std::multimap<uint16_t, CoPrtCnvRadioTelegram *> &a_fragTelegramList);
static bool isTelegramLengthOk(const uint16_t a_lengthWithoutFrame);
bool isNormalTelegram() const;
uint8_t getPriority() const;
uint16_t getBroadcastIndex() const;
void setPayloadDataWithIndex(const uint16_t a_index, const uint32_t a_value, const uint16_t a_size);
void setPayloadDataComplete(const QByteArray &payload);
void resetPayloadSize(const uint16_t a_newPayloadSize);
void setIdentity(const uint16_t a_identity);
void setProtocolIdentifier(const E_ProtocolIdentifier a_ProtocolIdentifier);
void setMessageReference(const uint8_t a_MessageReference);
bool isSDSTL() const;
CoPrtCnvRadioTelegram::E_RegistrationStatus getRegistrationStatus() const;
std::string getRegistrationStatusAsText() const;
CoPrtCnvRadioTelegram::E_ProtocolIdentifier getProtocolIdentifier() const;
std::string getProtocolIdentifierAsText() const;
uint8_t getMessageReference() const;
uint8_t getAreaSelection() const;
uint8_t getValidityPeriod() const;
uint32_t getForwardAddress() const;
CoPrtCnvRadioTelegram::E_Flags getFlags() const;
std::string getFlagsAsText() const;
uint16_t getLengthInBits() const;
uint16_t getLengthInBytes() const;
bool getWithCrc() const;
CoPrtCnvRadioTelegram::E_DeliveryStatusForTL_Report getDelivery() const;
std::string getDeliveryAsText() const;
int32_t getPayloadDataSInt24(uint16_t a_offset) const;
bool needsLicensing() const;
bool hasExpired() const;
uint32_t getExpireTime() const;
bool isContentValid();
bool mustBeSentAsBroadcast(time_t a_currentTime, bool &a_wasLastBroadcast, const bool a_updateBroadcastCounter = true);
static void setBroadcastDelayTimes(int a_2ndDelay, int a_3rdDelay);
static void setMaxBroadcastSendCnt(int a_maxSendCnt);
bool isMovedToBroadcastList() const;
void setBroadcastOnly(const bool a_doSet = true);
bool isBroadcastOnly() const;
void setBroadcastonlyTelegram(const std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> &a_radioTelegram);
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> getBroadcastonlyTelegram() const;
uint16_t getBroadcastCounter() const;
protected:
QByteArray m_data;
uint16_t m_PayloadIndex;
uint16_t m_BroadcastCounter;
time_t m_NextSendTime;
static int s_2ndDelay;
static int s_3rdDelay;
static int s_maxBroadcastSendCnt;
bool m_IsBroadcastOnly;
std::shared_ptr<N_CoPrtCnv::CoPrtCnvRadioTelegram> m_BroadcastOnlyTelegram;
static bool s_etsMode;
bool isPayloadLengthOk(uint16_t a_minLength,
const uint16_t a_dataAmountOffset,
const uint8_t a_variableDataElementSize) const;
bool isPayloadLengthOk(uint16_t a_minLength,
uint16_t a_maxLength) const;
bool isPayloadLengthOk(uint16_t a_length) const;
bool isPayloadLengthOk(const std::vector<uint16_t> &a_lengths) const;
static void set1Byte(QByteArray &a_data, uint16_t a_offset, uint8_t a_value);
static void set2Byte(QByteArray &a_data, uint16_t a_offset, uint16_t a_value);
static void set4Byte(QByteArray &a_data, uint16_t a_offset, uint32_t a_value);
uint8_t getUInt8(const uint16_t a_offset) const { return static_cast<uint8_t>(m_data.at(a_offset)); }
uint16_t getUInt16(const uint16_t a_offset) const;
uint32_t getUInt32(const uint16_t a_offset) const;
static void setHeader(QByteArray &data, E_PDU_Type pduType);
static void fillDataIndReqHeader(QByteArray &a_data);
static void setSrcISSI_Internal(QByteArray &data, const uint32_t issi);
static void setDestISSI_Internal(QByteArray &data, const uint32_t issi);
private:
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,57 @@
#pragma once
#include <CoPrtCnv/coprtcnv_export.h>
namespace TrainingAreaBase
{
namespace TetraIcd
{
struct TrainingAreaTelegram;
}
}
namespace N_CoPrtCnv
{
class CoPrtCnvRadioTelegram;
class CoPrtCnvCentralTelegram;
namespace CoPrtCnvTelegramConverter
{
COPRTCNV_EXPORT CoPrtCnvRadioTelegram *convertToRadio(CoPrtCnvCentralTelegram *a_telegram);
COPRTCNV_EXPORT CoPrtCnvRadioTelegram *convertToRadio(const TrainingAreaBase::TetraIcd::TrainingAreaTelegram *a_telegram);
COPRTCNV_EXPORT CoPrtCnvCentralTelegram *convertToCentral(const CoPrtCnvRadioTelegram *a_radioTelegram);
COPRTCNV_EXPORT TrainingAreaBase::TetraIcd::TrainingAreaTelegram *convertToTabTele(const CoPrtCnvRadioTelegram *a_radioTelegram);
COPRTCNV_EXPORT void setTetraTextCodec(const char *codecName);
COPRTCNV_EXPORT void setUse2BytesForSingleFireDiameter(bool bUse);
COPRTCNV_EXPORT void setUsePvSan(bool bUse);
}
}
File diff suppressed because it is too large. Load diff
+116
View File
@@ -0,0 +1,116 @@
#pragma once
enum gef_telegramm_id_et
{
GEF_BESTAETIGUNG = 0,
GEF_INIT = 1,
GEF_MANIPULATIONSMELDUNG = 2,
GEF_UMGEBUNGS_MELDUNG2 = 203,
GEF_AUFFORDERUNG_BITE_MELDUNG = 4,
GEF_BITE_MELDUNG2 = 205,
GEF_LIZENSIERUNG_TNE = 6,
GEF_BETRIEBSZUSTAND_AUSSTATTUNG = 7,
GEF_KONFIGURATION_WIRKMODELL = 9,
GEF_ANFORDERUNG_KONFIGURATIONSDATEN = 10,
GEF_KONFIGURATIONSMELDUNG = 11,
GEF_FEHLERMELDUNG_GFD = 12,
GEF_WIEDERHERSTELLUNG_FUNKBEREITSCHAFT = 13,
GEF_POSITIONS_MELDUNG = 21,
GEF_POSITIONS_MELDUNG_MIT_TEILNEHMER = 22,
GEF_POSITIONS_MELDUNG_LFZ = 23,
GEF_IPS_POSITIONSDATEN = 201,
GEF_SCHIEDSRICHTERKOMMANDO = 25,
GEF_WIRKFELD_EINZELGESCHOSS = 31,
GEF_WIRKFELD_FLAECHENDECKENDES_FEUER = 32,
GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_STOP = 33,
GEF_WIRKFELD_FLAECHENDECKENDES_FEUER_FORTSETZEN = 34,
GEF_WIRKFELD_MINENSPERRE = 35,
GEF_WIRKFELD_STATUS_MINENSPERRE = 36,
GEF_WIRKFELD_A_KAMPFMITTEL = 37,
GEF_WIRKFELD_C_KAMPFMITTEL = 38,
GEF_DEAKTIVIERUNG_WIRKFELD = 39,
GEF_WIRKFELD_AENDERUNG_BEZEICHNER = 40,
GEF_DEAKTIVIERUNG_EINZELMINE = 41,
GEF_REAKTIVIERUNG_DUS_MINE = 42,
GEF_DEFINITION_IED = 43,
GEF_ZUSTAND_IED = 44,
GEF_STATUS_EINZELMINENSIMULATOR = 45,
GEF_WIRKFELD_EINZELMINENSIMULATOR = 46,
GEF_SELEKTIVE_AUFMUNITIONIERUNG = 56,
GEF_TREFFER_EREIGNIS_DUS = 52,
GEF_TREFFER_EREIGNIS_WIRKSIMULATION = 53,
GEF_TREFFER_AUSLOESUNG = 54,
GEF_SCHIEDSRICHTEREINGRIFF = 55,
GEF_TREFFER_EREIGNIS_SEKUNDAERWIRKUNG = 218,
GEF_TREFFER_EREIGNIS_DUS_IPS = 228,
GEF_TREFFER_EREIGNIS_WIRKSIMULATION_IPS = 229,
GEF_TAKTISCHER_STATUS = 61,
GEF_FUNKTIONSRAUM = 62,
GEF_EINTRETEN_FUNKTIONSRAUM = 63,
GEF_DEAKTIVIEREN_FUNKTIONSRAUM = 64,
GEF_DATENVERKEHR_SRT_TDS = 71,
GEF_DATENVERKEHR_TDS_SRT = 72,
GEF_DATENVERKEHR_DMF_TDS = 73,
GEF_DATENVERKEHR_TDS_DMF = 74,
GEF_NACHFORDERUNG_BROADCAST_TELEGRAMME = 82,
GEF_NOP = 83,
GEF_SONDERSENSORIK_BETRIEBSZUSTAND = 91,
GEF_SONDERSENSORIK_FAHRSPUR = 92,
GEF_SONDERSENSORIK_DATEN = 93,
GEF_SONDERSENSORIK_MIVANH_VERLEGEDATEN = 95,
GEF_SONDERSENSORIK_WMIV_VERLEGEDATEN = 96,
GEF_SONDERSENSORIK_MIVANH_VERLEGEPOSITION = 97,
GEF_SPRACHAUSWAHL = 101,
GEF_ALLGEMEINE_NACHRICHT = 102,
GEF_ECHO_ON_OFF = 103,
GEF_ESW_MELDUNG = 104,
GEF_WF_SAMMELDEAKTIVIERUNG = 105,
GEF_WF_SAMMELDEAKTIVIERUNG_DUS_MINEN = 106,
GEF_WF_SAMMELDEAKTIVIERUNG_FUNKTIONSRAUM = 107,
GEF_DATENVERKEHR_GEOP_TDS = 181,
GEF_DATENVERKEHR_TDS_GEOP = 182,
GEF_DATENVERKEHR_TGTC_TDS = 183,
GEF_DATENVERKEHR_TDS_TGTC = 184,
GEF_GERAETEEREIGNIS = 185,
GEF_WAFFENZUORDNUNG = 200,
GEF_MUNITIONSVORRAT_EINER_ZUGEORDNETEN_WAFFE = 202,
GEF_FEUEREREIGNIS_MIT_WAFFENZUORDNUNG = 210,
GEF_AUSLOESUNG_DUS_TREFFER = 211,
GEF_ANFORDERUNG_SW_VERSION = 212,
GEF_SW_VERSIONSMELDUNG = 213,
GEF_TECHNIK_FUNKTIONSRAUM = 219,
GEF_TEILNEHMERMODE_SETZEN = 230,
GEF_TEILNEHMERMODE_MELDUNG = 231,
GEF_TEILNEHMERMODE_ANFORDERN = 232,
GEF_TEILNEHMER_KONFIG_ANTWORT = 233,
GEF_TEILNEHMER_KONFIG_SETZEN = 234,
GEF_TEILNEHMER_KONFIG_ANFORDERN = 235,
GEF_SANITAETSDIENST_INSTANDSETZUNG = 240,
GEF_BESTANDSMELDUNG_SANITAETSMATERIAL = 241,
GEF_SANITAETSDIENST_INSTANDSETZUNG_PVSAN = 242,
GEF_LASER_TARGET_DESIGNATOR_UPDATE = 214,
GEF_GEFECHTSFELDTELEGRAMM = 300
};
+104
View File
@@ -0,0 +1,104 @@
#
# $Id$
# $HeadURL$
# $Author$
#
ADD_SUBDIRECTORY(Console)
SET(my_SRCS
IntegerCalculator.cpp
IntegerCalculator.hpp
logger.cpp
logger.h
LogViewBooleanEdit.cpp
LogViewBooleanEdit.hpp
LogViewDateTimeEdit.cpp
LogViewDateTimeEdit.hpp
LogViewEnumEdit.cpp
LogViewEnumEdit.hpp
LogViewField.cpp
LogViewField.hpp
LogViewGui.cpp
LogViewGui.hpp
LogViewInjectionThread.cpp
LogViewInjectionThread.hpp
LogViewMain.cpp
LogViewModels.cpp
LogViewModels.hpp
LogViewOptionDialog.cpp
LogViewOptionDialog.hpp
LogViewSpinBox.cpp
LogViewSpinBox.hpp
LogViewTableWidget.cpp
LogViewTableWidget.hpp
LogViewTabWidget.cpp
LogViewTabWidget.hpp
LogViewTelegram.cpp
LogViewTelegramDialog.cpp
LogViewTelegramDialog.hpp
LogViewTelegramEdit.cpp
LogViewTelegramEdit.hpp
LogViewTelegramEditModel.cpp
LogViewTelegramEditModel.hpp
LogViewTelegram.hpp
LogViewTelegramSelectionDialog.cpp
LogViewTelegramSelectionDialog.hpp
LogViewTetraTelegramsParser.cpp
LogViewTetraTelegramsParser.hpp
LogViewTextEdit.cpp
LogViewTextEdit.hpp
LogViewValueEdit.cpp
LogViewValueEdit.hpp
LogViewWidget.cpp
LogViewWidget.hpp
LogViewXdrElement.cpp
LogViewXdrElement.hpp
LogViewXdrParser.cpp
LogViewXdrParser.hpp
LogViewXdrStandardType.cpp
LogViewXdrStandardType.hpp
LogViewXdrStruct.cpp
LogViewXdrStruct.hpp
LogViewXdrType.cpp
LogViewXdrType.hpp
LogViewXdrValue.cpp
LogViewXdrValue.hpp
zsksxd_tetraForLogView.x
)
QT5_ADD_RESOURCES(my_SRCS LogViewResources.qrc)
NGL_ADD_TOOL_ICON(my_SRCS)
NGL_ADD_EXECUTABLE(AAR SV NO_TRANSLATION LogView ${my_SRCS})
NGL_TARGET_LINK_LIBRARIES(LogView
Qt5::Core
Qt5::Gui
Qt5::Network
CoPrtCnv
nglwidgets
NGLLogger
nglapplication
ngltools
)
NGL_INSTALL_TARGET(LogView)
NGL_INSTALL(AAR SV FILES LogView_log4cxx.props DESTINATION bin)
# install on RPM build and copy for local builds so that LogView automatically finds the zsksxd_tetraForLogView.x file
if (BUILD_RPM)
add_custom_target(zsksxd_tetraForLogView.x_bin) # empty target so that LogView still builds on RPM build
NGL_INSTALL(AAR SV FILES zsksxd_tetraForLogView.x DESTINATION bin)
else()
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/zsksxd_tetraForLogView.x ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/zsksxd_tetraForLogView.x
COMMENT "[Local build] Copy zsksxd_tetraForLogView.x for LogView into bin/"
)
add_custom_target(zsksxd_tetraForLogView.x_bin DEPENDS ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x)
endif()
if (TARGET LogView)
add_dependencies(LogView zsksxd_tetraForLogView.x_bin training_area_telegrams.h_bin)
endif()
+17
View File
@@ -0,0 +1,17 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(console_SRCS
main.cpp
)
NGL_ADD_TOOL_ICON(console_SRCS)
NGL_ADD_EXECUTABLE(AAR SV LogView_console ${console_SRCS})
NGL_INSTALL_TARGET(LogView_console)
NGL_TARGET_LINK_LIBRARIES(LogView_console
CoPrtCnv
NGLLogger
)
+201
View File
@@ -0,0 +1,201 @@
#include <QCoreApplication>
#include <QStringList>
#include <QFile>
#include <QByteArray>
#include <QDateTime>
#include <QBuffer>
#include <QSet>
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <TrainingAreaBase/training_area_telegrams.h>
static QSet<int> s_eqIds;
template <typename T>
bool validEqId(const T &tele)
{
if (!s_eqIds.isEmpty() && !s_eqIds.contains(tele.header.equipmentNumber))
return false;
return true;
}
QByteArray formatTime(quint64 t)
{
const quint64 secs = t >> 32;
const quint64 usecs = t & 0xFFFFFFFF;
const quint64 msecs = usecs / 1000;
return QDateTime::fromMSecsSinceEpoch(secs * 1000 + msecs).toString(QLatin1String("yy-MM-dd hh:mm:ss.zzz")).toUtf8();
}
int main(int argc, char **argv)
{
using namespace TrainingAreaBase::TetraIcd;
QCoreApplication app(argc, argv);
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_tetra.props", false);
NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger());
if (app.arguments().count() < 3)
{
ERROR_LOG(logger) << "Usage: " << app.arguments().at(0)
<< " <logfile> <telId> <equipId>";
return 1;
}
QFile telegramFile(app.arguments().at(1));
if (!telegramFile.open(QIODevice::ReadOnly))
{
ERROR_LOG(logger) << "Error opening " << telegramFile.fileName()
<< " for reading: " << telegramFile.errorString();
return 2;
}
bool bOk;
int telIdToSearch = app.arguments().at(2).toUShort(&bOk);
if (!bOk)
{
ERROR_LOG(logger) << "Error reading telId - not a (valid) number: "
<< app.arguments().at(2);
return 3;
}
s_eqIds.clear();
for (int i = 3; i < app.arguments().size(); ++i)
{
int eqId = app.arguments().at(i).toUShort(&bOk);
if (!bOk)
{
ERROR_LOG(logger) << "Error reading equipId - not a (valid) number: "
<< app.arguments().at(i);
return 4;
}
s_eqIds += eqId;
}
while (true)
{
N_CoPrtCnv::CoPrtCnvLogHeader lh;
if (sizeof(lh) == telegramFile.read((char *)&lh, sizeof(lh)))
{
if (lh.m_Version == 3)
{
qint64 telegramLength = lh.m_Length - sizeof(lh);
QByteArray telegramData(telegramLength, Qt::Uninitialized);
if (telegramLength == telegramFile.read(telegramData.data(), telegramLength))
{
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)
(lh.m_Protocol & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask);
switch (dest)
{
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral:
{
const QJsonObject obj = QJsonDocument::fromJson(telegramData).object();
int telId = obj.value(QStringLiteral("typeId")).toInt();
if (telIdToSearch != telId)
continue;
const QJsonObject objData = obj.value(QStringLiteral("data")).toObject();
const QByteArray tBA = formatTime(lh.m_Time);
const char *timeStr = tBA.constData();
switch (telId)
{
case Constraints<CreateFunctionalArea>::id():
{
const CreateFunctionalArea tele(CreateFunctionalArea::fromJson(objData));
if (!validEqId(tele))
break;
fprintf(stdout, "%s, FUNKTIONSRAUM: '%s', %d, %d\n",
timeStr,
tele.name.c_str(),
tele.aesDdsId,
tele.header.equipmentNumber
);
break;
}
case Constraints<DeactivateEffectSimulation>::id():
{
const DeactivateEffectSimulation tele(DeactivateEffectSimulation::fromJson(objData));
fprintf(stdout, "%s, DEAKTIVIERUNG_WIRKFELD: typ: %d - kennung: %d\n",
timeStr,
int(tele.aesType),
tele.aesDdsId
);
break;
}
case Constraints<PositionReport>::id():
{
const PositionReport tele(PositionReport::fromJson(objData));
if (!validEqId(tele))
break;
if (tele.opsPosition.opsId == 0)
break;
fprintf(stdout, "%s, IPS_POSITIONSDATEN: %d - OPS: %d\n",
timeStr,
tele.header.equipmentNumber,
tele.opsPosition.opsId
);
break;
}
case BESTAETIGUNG:
case UMGEBUNGS_MELDUNG2:
break;
default:
fprintf(stderr, "Printing telegram with id %d not implemented\n", telId);
break;
}
break;
}
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra:
{
N_CoPrtCnv::CoPrtCnvRadioTelegram radioTelegram(telegramData);
gef_telegramm_id_et telId = radioTelegram.getTelID();
if (telId == GEF_UMGEBUNGS_MELDUNG2)
{
const QByteArray tBA = formatTime(lh.m_Time);
const char *timeStr = tBA.constData();
static uint16_t bci = 0xFFFF;
if (bci != radioTelegram.getBroadcastIndex())
{
if (bci > radioTelegram.getBroadcastIndex() && bci != 0xFFFF)
{
fprintf(stdout, "BCI reset in %s at %s!\n",
qPrintable(telegramFile.fileName()),
timeStr);
}
fprintf(stdout, "BCI: %d\n", radioTelegram.getBroadcastIndex());
bci = radioTelegram.getBroadcastIndex();
}
}
break;
}
default:
break;
}
}
}
else
{
ERROR_LOG(logger) << "Wrong LogHeader version: " << lh.m_Version;
return 4;
}
}
else
break;
}
return 0;
}
+497
View File
@@ -0,0 +1,497 @@
#include "IntegerCalculator.hpp"
#include <sstream>
#include <iomanip>
namespace N_SST
{
IntegerCalculator::IntegerCalculator()
: m_OperationList({{"*", 6},{"/", 6},{"%", 6},{"+", 5},{"-", 5},{"<<", 4},{">>", 4}})
, m_AdditionalErrorText()
, m_ParanthesisCount(0)
, m_Error(IntegerCalculator::e_Ok)
{
}
int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText)
{
std::string calcText = a_calcText;
for (auto iter = m_OperationList.begin(); iter != m_OperationList.end(); ++iter)
replace(calcText, iter->first, " "+iter->first+" ");
replace(calcText, "(", " ( ");
replace(calcText, ")", " ) ");
m_ParanthesisCount = 0;
m_Error = e_Ok;
m_AdditionalErrorText = "";
size_t pos = 0;
bool dummy;
int64_t value = calc(calcText, pos, dummy, "", 0, "+");
if (m_Error == e_Ok)
{
if (m_ParanthesisCount > 0)
{
m_Error = e_MissingRightParanthesis;
}
else if (m_ParanthesisCount < 0)
{
m_Error = e_MissingLeftParanthesis;
}
else if (pos != calcText.length())
{
m_Error = e_UnknownError;
}
}
a_error = m_Error;
if (a_error != e_Ok)
{
value = 0;
if (a_addErrorText)
{
*a_addErrorText = m_AdditionalErrorText;
}
}
return value;
}
void IntegerCalculator::addVariable(const std::string& a_name, const int64_t a_value)
{
std::map<std::string, int64_t>::iterator iter = m_VariableList.find(a_name);
if (iter != m_VariableList.end())
removeVariable(a_name);
m_VariableList.insert(std::make_pair(a_name, a_value));
}
void IntegerCalculator::removeVariable(const std::string& a_name)
{
std::map<std::string, int64_t>::iterator iter = m_VariableList.find(a_name);
if (iter != m_VariableList.end())
m_VariableList.erase(iter);
}
int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis,
const std::string& a_prevOp, const int64_t a_prevValue,
const std::string& a_initOp)
{
std::string operation = a_initOp;
int64_t value1 = a_prevValue;
bool isNegative = false;
std::string calcText = a_calcText;
a_IsEndParanthesis = false;
while (a_pos < calcText.length())
{
if (' ' == calcText[a_pos])
{
a_pos++;
}
else if ('(' == calcText[a_pos])
{
m_ParanthesisCount++;
bool dummy;
int64_t value2 = calcSign(calc(calcText, ++a_pos, dummy), isNegative);
value1 = doOperation(value1, operation, value2);
size_t tmpPos = a_pos;
std::string nextOp = getToken(a_calcText, tmpPos);
if (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp))
{
return value1;
}
operation = "";
}
else if (')' == calcText[a_pos])
{
m_ParanthesisCount--;
a_pos++;
a_IsEndParanthesis = true;
return value1;
}
else if (isDigit(calcText[a_pos]))
{
int64_t value2 = calcSign(convertValue(calcText, a_pos), isNegative);
if (calcWithPriority(calcText, a_pos, value1, operation, value2, a_prevOp)) return value1;
}
else
{
std::string oldOperation = operation;
operation = getToken(calcText, a_pos);
if (!isOperation(operation))
{
int64_t value2 = 0;
if (getVariableValue(operation, value2))
{
value2 = calcSign(value2, isNegative);
if (calcWithPriority(calcText, a_pos, value1, oldOperation, value2, a_prevOp)) return value1;
operation = "";
}
else
{
m_Error = e_UnknownOperationOrVariable;
m_AdditionalErrorText = operation;
}
}
else
{
if (oldOperation != "")
{
if (operation == "+")
{
operation = oldOperation;
}
else if (operation == "-")
{
isNegative = !isNegative;
operation = oldOperation;
}
else
{
m_Error = e_NoOperandBetweenOperators;
m_AdditionalErrorText = oldOperation + " " + operation;
return 0;
}
}
}
}
}
return value1;
}
bool IntegerCalculator::calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1, std::string& a_operation, int64_t a_value2, const std::string& a_prevOp)
{
bool isParaEnd = false;
size_t tmpPos = a_pos;
std::string nextOp = getToken(a_calcText, tmpPos);
if (isOperation(a_operation) && isOperation(nextOp) && isOperationPriorityHigher(nextOp, a_operation))
{
a_value2 = calc(a_calcText, a_pos, isParaEnd, a_operation, a_value2);
}
a_value1 = doOperation(a_value1, a_operation, a_value2);
if (isParaEnd || (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp)))
{
return true;
}
a_operation = "";
return false;
}
int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative)
{
if (a_isNegative)
{
a_isNegative = false;
return -a_value;
}
return a_value;
}
int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& a_pos)
{
std::string valueText = a_valueText.substr(a_pos);
int base = 10;
size_t startpos = 0;
bool isHex = (0 == valueText.find("0X")) || (0 == valueText.find("0x"));
bool isBin = (0 == valueText.find("0B")) || (0 == valueText.find("0b"));
if (isHex)
{
base = 16;
startpos = 2;
}
else if (isBin)
{
base = 2;
startpos = 2;
}
size_t i;
for (i=startpos; i<valueText.length(); i++)
{
if (!isDigit(valueText[i], isHex, isBin))
{
break;
}
}
if (valueText.length() > i && valueText[i] != ' ')
{
m_Error = e_InvalidOperand;
int spacePos = valueText.find(' ');
m_AdditionalErrorText = valueText.substr(0, spacePos);
}
a_pos += i;
int64_t value = 0;
std::stringstream stream;
stream.str(valueText.substr(startpos, i-startpos));
if (2 == base)
{
const std::string binValueAsText = stream.str();
for (const char c : binValueAsText)
{
value = value << 1;
if (c == '1')
value += 1;
}
}
else
{
stream << std::setbase(base);
stream >> value;
}
return value;
}
std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a_pos)
{
while (a_pos < a_calcText.length())
{
if (a_calcText[a_pos] == ' ') a_pos++;
else break;
}
size_t startPos = a_pos;
while (a_pos < a_calcText.length())
{
if (' ' == a_calcText[a_pos]) break;
a_pos++;
}
return a_calcText.substr(startPos, a_pos-startPos);
}
bool IntegerCalculator::isOperation(const std::string& a_operation) const
{
std::map<std::string, int>::const_iterator iter = m_OperationList.find(a_operation);
return (iter != m_OperationList.end());
}
int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2)
{
if (("+" == a_operation) || a_operation.empty())
{
return a_value1 + a_value2;
}
else if ("-" == a_operation)
{
return a_value1 - a_value2;
}
else if ("*" == a_operation)
{
return a_value1 * a_value2;
}
else if ("/" == a_operation)
{
if (0 == a_value2)
{
m_Error = e_DivisionByZero;
}
else
{
return a_value1 / a_value2;
}
}
else if ("%" == a_operation)
{
if (0 == a_value2)
{
m_Error = e_DivisionByZero;
}
else
{
return a_value1 % a_value2;
}
}
else if ("<<" == a_operation)
{
return a_value1 << a_value2;
}
else if (">>" == a_operation)
{
return a_value1 >> a_value2;
}
else
{
m_Error = e_UnknownOperationOrVariable;
m_AdditionalErrorText = a_operation;
}
return 0;
}
bool IntegerCalculator::isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const
{
return (getPriority(a_operation1) > getPriority(a_operation2));
}
bool IntegerCalculator::getVariableValue(const std::string& a_variableName, int64_t& a_value) const
{
auto iter = m_VariableList.find(a_variableName);
if (iter != m_VariableList.end())
{
a_value = iter->second;
return true;
}
return false;
}
bool IntegerCalculator::isDigit(const char a_char, const bool a_isHex, const bool a_isBin)
{
if (a_isHex)
{
return (a_char >= '0' && a_char <= '9') || (a_char >= 'A' && a_char <= 'F') || (a_char >= 'a' && a_char <= 'f');
}
else if (a_isBin)
{
return (a_char >= '0' && a_char <= '1');
}
return (a_char >= '0' && a_char <= '9');
}
int16_t IntegerCalculator::getPriority(const std::string& a_operation) const
{
std::map<std::string, int>::const_iterator iter = m_OperationList.find(a_operation);
if (iter != m_OperationList.end())
return iter->second;
return -1;
}
void IntegerCalculator::replace(std::string& a_haystack, const std::string &a_searchText, const std::string &a_replaceText)
{
std::string::size_type searchSize = a_searchText.length();
std::string::size_type replaceSize = a_replaceText.length();
std::string::size_type pos = a_haystack.find(a_searchText, 0);
while (std::string::npos != pos)
{
a_haystack.replace(pos, searchSize, a_replaceText);
pos += replaceSize;
pos = a_haystack.find(a_searchText, pos);
}
}
}
+143
View File
@@ -0,0 +1,143 @@
#pragma once
#include <string>
#include <map>
namespace N_SST
{
class IntegerCalculator
{
public:
enum E_Error
{
e_Ok,
e_DivisionByZero,
e_UnknownOperationOrVariable,
e_NoOperandBetweenOperators,
e_InvalidOperand,
e_MissingLeftParanthesis,
e_MissingRightParanthesis,
e_UnknownError
};
IntegerCalculator();
virtual ~IntegerCalculator() = default;
int64_t calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText = nullptr);
void addVariable(const std::string& a_name, const int64_t a_value);
void removeVariable(const std::string& a_name);
protected:
const std::map<std::string, int> m_OperationList;
std::map<std::string, int64_t> m_VariableList;
std::string m_AdditionalErrorText;
int32_t m_ParanthesisCount;
E_Error m_Error;
int64_t calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis,
const std::string& a_prevOp = std::string(), const int64_t a_prevValue = 0,
const std::string& a_initOp = std::string());
bool calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1,
std::string& a_operation, int64_t a_value2, const std::string& a_prevOp);
static int64_t calcSign(const int64_t a_value, bool& a_isNegative);
int64_t convertValue(const std::string& a_valueText, size_t& a_pos);
static std::string getToken(const std::string& a_calcText, size_t& a_pos);
bool isOperation(const std::string& a_operation) const;
int64_t doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2);
bool isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const;
virtual bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const;
static bool isDigit(const char a_char, const bool a_isHex = false, const bool a_isBin = false);
int16_t getPriority(const std::string& a_operation) const;
static void replace(std::string& a_haystack, const std::string& a_searchText, const std::string& a_replaceText);
};
}
+36
View File
@@ -0,0 +1,36 @@
#include "LogViewBooleanEdit.hpp"
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
namespace N_LogView
{
LogViewBooleanEdit::LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QCheckBox (a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
{
const QString valueText = a_field->value(0);
setChecked(valueText.toInt() == 1);
setEnabled(!a_readonly);
}
bool LogViewBooleanEdit::saveContent(LogViewTelegram* a_telegram)
{
if (m_Valid)
{
if (a_telegram->isJsonTelegram())
a_telegram->setJsonValue(m_Field->jsonPath(), isChecked());
else
a_telegram->setUIntX(getSize(), isChecked());
return true;
}
return false;
}
}
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "LogViewWidget.hpp"
#include <QCheckBox>
namespace N_LogView
{
class LogViewBooleanEdit : public QCheckBox, public LogViewWidget
{
Q_OBJECT
public:
LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
bool saveContent(LogViewTelegram* a_telegram) override;
};
}
+86
View File
@@ -0,0 +1,86 @@
#include "LogViewDateTimeEdit.hpp"
#include <time.h>
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
namespace N_LogView
{
LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QDateTimeEdit(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
{
if (a_readonly)
{
setReadOnly(true);
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
}
qint64 unixTime = 0;
if (a_field->hasContent())
{
if (a_field->isMSecsField())
unixTime = a_field->value(0, true).toLongLong();
else
unixTime = a_field->value(0, true).toInt() * 1000LL;
}
if (0 == unixTime && !a_readonly)
unixTime = ::time(nullptr) * 1000LL;
setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime));
setDisplayFormat(QLatin1String("dd MMM yyyy hh:mm:ss"));
setCalendarPopup(true);
updateToolTip(QString::number(unixTime));
connect(this, &LogViewDateTimeEdit::editingFinished,
this, &LogViewDateTimeEdit::checkAndOvertakeContent);
}
void LogViewDateTimeEdit::checkAndOvertakeContent()
{
updateToolTip(QString::number(dateTime().toMSecsSinceEpoch() / 1000));
}
bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram)
{
if (a_telegram->isJsonTelegram())
{
a_telegram->setJsonValue(m_Field->jsonPath(), dateTime().toMSecsSinceEpoch());
}
else
{
a_telegram->setNextFieldAsGpsTimeField();
a_telegram->setUIntX(getSize(), dateTime().toMSecsSinceEpoch() / 1000);
}
return true;
}
}
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include "LogViewWidget.hpp"
#include <QDateTimeEdit>
namespace N_LogView
{
class LogViewDateTimeEdit : public QDateTimeEdit, public LogViewWidget
{
Q_OBJECT
public:
LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
bool saveContent(LogViewTelegram* a_telegram) override;
public slots:
void checkAndOvertakeContent();
};
}
+105
View File
@@ -0,0 +1,105 @@
#include "LogViewEnumEdit.hpp"
#include "LogViewXdrStruct.hpp"
#include "LogViewXdrValue.hpp"
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
namespace N_LogView
{
LogViewEnumEdit::LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index)
: QComboBox(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
{
QString value = a_field->value(a_index);
setToolTip(a_field->toolTipText());
bool bCurrentIndexSet = false;
int i = 0;
while (LogViewXdrValue* child = (static_cast<const LogViewXdrStruct*>(a_field->xdrElement()))->getChildAsValue(i++))
{
QString enumText = LogViewField::makeClean(child->getName());
if (!a_readonly || enumText == value)
{
addItem(QStringLiteral("%1 (%2)").arg(enumText).arg(child->getValue()), QVariant::fromValue(child->getValue()));
if (a_readonly)
bCurrentIndexSet = true;
}
if (enumText == value)
{
setCurrentIndex(a_readonly ? 0 : i - 1);
bCurrentIndexSet = true;
if (!a_readonly || (0 != a_index))
updateToolTip(itemData(currentIndex()).toString());
}
}
if (!bCurrentIndexSet)
{
addItem(value);
setCurrentIndex(findText(value));
}
connect(this, QOverload<int>::of(&LogViewEnumEdit::currentIndexChanged),
this, &LogViewEnumEdit::checkAndOvertakeContent);
}
uint16_t LogViewEnumEdit::getSize() const
{
const LogViewXdrStruct* xdrStruct = static_cast<const LogViewXdrStruct*>(m_Field->xdrElement());
return xdrStruct->getEnumSize();
}
void LogViewEnumEdit::checkAndOvertakeContent()
{
updateToolTip(itemData(currentIndex()).toString());
}
bool LogViewEnumEdit::saveContent(LogViewTelegram* a_telegram)
{
bool ok;
int value = itemData(currentIndex()).toInt(&ok);
if (ok)
{
if (a_telegram->isJsonTelegram())
a_telegram->setJsonValue(m_Field->jsonPath(), value);
else
a_telegram->setUIntX(getSize(), value);
return true;
}
return false;
}
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include "LogViewWidget.hpp"
#include <QComboBox>
namespace N_LogView
{
class LogViewEnumEdit : public QComboBox, public LogViewWidget
{
Q_OBJECT
public:
LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index);
uint16_t getSize() const override;
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void checkAndOvertakeContent();
};
}
+275
View File
@@ -0,0 +1,275 @@
#include "LogViewField.hpp"
#include <QtCore/QDateTime>
#include "LogViewXdrElement.hpp"
#include "LogViewXdrStandardType.hpp"
namespace N_LogView
{
LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, const LogViewXdrElement* a_xdrElement)
: m_Name(a_name),
m_IsRightAligned(false),
m_Offset(0),
m_Size(0),
m_MaxArraySize(0),
m_IsDynamicArray(false),
m_HasContent(true),
m_bDeleteXdr(false),
m_Kind(a_kind),
m_XdrElement(a_xdrElement),
m_logger(getLogger("LogViewField"))
{
}
LogViewField::~LogViewField()
{
for (LogViewField *f : qAsConst(m_Child))
delete f;
if (m_bDeleteXdr)
delete m_XdrElement;
}
LogViewField *LogViewField::clone(int arrayIdx) const
{
LogViewField *f = new LogViewField(*this);
f->m_Child.clear();
f->m_bDeleteXdr = false;
for (auto * c : m_Child)
{
auto *clonedChild = c->clone(-1);
if (arrayIdx >= 0)
{
QStringList sl = clonedChild->jsonPath();
if (sl.size() > 1 && sl.at(sl.size() - 2).startsWith(QStringLiteral("index: ")))
{
sl[sl.size() - 2] = QStringLiteral("index: %1").arg(arrayIdx);
clonedChild->setJsonPath(sl);
}
}
f->addChild(clonedChild);
}
for (auto &val : f->m_ValueList)
val.clear();
return f;
}
void LogViewField::addChild(LogViewField* a_child)
{
if (a_child)
m_Child.push_back(a_child);
}
void LogViewField::removeLastChild()
{
if (m_Child.empty())
return;
delete m_Child.takeLast();
}
LogViewField* LogViewField::child(int arrayIdx)
{
if (m_Child.size() > arrayIdx)
return m_Child.at(arrayIdx);
return nullptr;
}
void LogViewField::addValue(const QString &value)
{
m_ValueList.append(value);
}
void LogViewField::addValueBinaryHex(const QString &value)
{
const QByteArray ba = QByteArray::fromHex(value.toLatin1());
for (const char c : ba)
m_ValueList.append(QString::number(static_cast<unsigned char>(c)));
}
QString LogViewField::value(int arrayIdx, const bool a_doNotMakeSpecialConversions) const
{
if (m_ValueList.size() > arrayIdx)
{
const QString &ret = m_ValueList.at(arrayIdx);
if (!a_doNotMakeSpecialConversions)
{
if (isDateTimeField())
return QDateTime::fromMSecsSinceEpoch(ret.toLongLong() * 1000).toString(QStringLiteral("dd.mm.yy hh:mm:ss.zzz"));
if (isMSecsField())
return QDateTime::fromMSecsSinceEpoch(ret.toLongLong()).toString(QStringLiteral("dd.mm.yy hh:mm:ss.zzz"));
}
return ret;
}
return QString();
}
int64_t LogViewField::getHighestValue() const
{
switch (m_XdrElement->getKind())
{
case LogViewXdrElement::e_KindStandardType:
{
int64_t highest = 1;
uint16_t bitSize = 8*static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getEditSize();
if ((0 == m_Name.compare(QLatin1String("utm nordwert"), Qt::CaseInsensitive)) ||
(0 == m_Name.compare(QLatin1String("utm ostwert"), Qt::CaseInsensitive)))
bitSize -= 8;
switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) {
case LogViewXdrStandardType::e_Boolean:
return 1;
case LogViewXdrStandardType::e_Signed:
bitSize--;
Q_FALLTHROUGH();
case LogViewXdrStandardType::e_Unsigned:
case LogViewXdrStandardType::e_Data:
highest = highest << bitSize;
highest--;
break;
default:
highest = 0;
break;
}
return highest;
}
default:
ERROR_LOG(m_logger) << "Case not implemented";
}
return 0;
}
int64_t LogViewField::getLowestValue() const
{
switch (m_XdrElement->getKind())
{
case LogViewXdrElement::e_KindStandardType:
{
int64_t lowest = 0;
switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) {
case LogViewXdrStandardType::e_Boolean:
return 0;
case LogViewXdrStandardType::e_Signed:
lowest = getHighestValue() + 1;
lowest = -lowest;
break;
default:
break;
}
return lowest;
}
default:
ERROR_LOG(m_logger) << "Case not implemented";
break;
}
return 0;
}
void LogViewField::dump(const QString &a_indent) const
{
INFO_LOG(m_logger) << a_indent << "[";
INFO_LOG(m_logger) << a_indent << "Field[" << m_Name << "]: m_Kind=" << m_Kind << " m_Offset=" << m_Offset << " m_Size=" << m_Size << " m_MaxArraySize=" << m_MaxArraySize << " m_IsRightAligned=" << m_IsRightAligned << " m_IsDynamicArray=" << m_IsDynamicArray << " m_ToolTipText=" << m_ToolTipText;
for (int i=0; i<m_ValueList.size(); i++)
INFO_LOG(m_logger) << a_indent << "m_Value[" << i << "]=" << m_ValueList[i];
for (auto *c : m_Child)
c->dump(a_indent + QLatin1Char(' '));
INFO_LOG(m_logger) << a_indent << "]";
}
QString LogViewField::makeClean(const QString &text)
{
QString a_uncleanText = text;
if (a_uncleanText.endsWith(QLatin1String("_rt")))
a_uncleanText = a_uncleanText.left(a_uncleanText.length() - 3);
a_uncleanText = a_uncleanText.replace(QLatin1Char('_'), QLatin1Char(' '));
int pos = 0;
while (a_uncleanText.length() > pos)
{
a_uncleanText[pos] = a_uncleanText[pos].toUpper();
pos = a_uncleanText.indexOf(QLatin1Char(' '), pos + 1);
if (-1 == pos)
break;
pos++;
}
return a_uncleanText;
}
bool LogViewField::isDateTimeField() const
{
QString name = m_Name.toLower();
return name == QLatin1String("gps_zeit");
}
bool LogViewField::isMSecsField() const
{
QString name = m_Name.toLower();
return (name == QLatin1String("timestamp")) || (name == QLatin1String("effectstart"));
}
void LogViewField::setMaxArraySize(uint16_t newVal, const bool a_isDynamic)
{
m_MaxArraySize = newVal;
m_IsDynamicArray = a_isDynamic;
}
}
+142
View File
@@ -0,0 +1,142 @@
#pragma once
#include <QStringList>
#include <QVector>
#include "logger.h"
namespace N_LogView
{
class LogViewXdrElement;
class LogViewField
{
public:
enum E_FieldKind
{
e_FieldKindBorder,
e_FieldKindEdit,
e_FieldKindTab,
e_FieldKindTabChild,
e_FieldKindPodArray,
e_FieldKindPodArrayChild
};
LogViewField(const QString& a_name, const E_FieldKind a_kind, const LogViewXdrElement* a_xdrElement);
virtual ~LogViewField();
LogViewField *clone(int arrayIdx) const;
QString cleanName() const { return makeClean(m_Name); }
QString name() const { return m_Name; }
void setName(const QString &newVal) { m_Name = newVal; }
void addChild(LogViewField* a_child);
void removeLastChild();
LogViewField *child(int arrayIdx);
int childCount() const { return m_Child.size(); }
QString type() const { return m_type; }
void setType(const QString &type) { m_type = type; }
LogViewField::E_FieldKind kind() const { return m_Kind; }
void addValue(const QString &value);
void addValueBinaryHex(const QString &value);
QString value(int arrayIdx, const bool a_doNotMakeSpecialConversions = false) const;
int valueListSize() const { return m_ValueList.size(); }
bool isRightAligned() const { return m_IsRightAligned; }
void setIsRightAligned(bool newVal) { m_IsRightAligned = newVal; }
QString toolTipText() const { return m_ToolTipText; }
void setToolTipText(const QString &newVal) { m_ToolTipText = newVal; }
int64_t getHighestValue() const;
int64_t getLowestValue() const;
void dump(const QString &a_indent = QString()) const;
static QString makeClean(const QString &text);
int size() const { return m_Size; }
void setSize(int newVal) { m_Size = newVal; }
const LogViewXdrElement* xdrElement() const { return m_XdrElement; }
bool isDateTimeField() const;
bool isMSecsField() const;
uint16_t maxArraySize() const { return m_MaxArraySize; }
void setMaxArraySize(uint16_t newVal, const bool a_isDynamic);
bool isDynamicArray() const { return m_IsDynamicArray; }
bool hasContent() const { return m_HasContent; }
void setHasContent(bool newVal) { m_HasContent = newVal; }
void setDeleteXdr(bool bDelete) { m_bDeleteXdr = bDelete; }
void setJsonPath(const QStringList &path) { m_jsonPath = path; }
QStringList jsonPath() const { return m_jsonPath; }
protected:
QString m_Name;
QString m_type;
QStringList m_ValueList;
QStringList m_jsonPath;
bool m_IsRightAligned;
QString m_ToolTipText;
uint16_t m_Offset;
int m_Size;
uint16_t m_MaxArraySize;
bool m_IsDynamicArray;
bool m_HasContent;
bool m_bDeleteXdr;
QVector<LogViewField*> m_Child;
E_FieldKind m_Kind;
const LogViewXdrElement *m_XdrElement;
private:
NGL::INGLLogger &m_logger;
};
}
File diff suppressed because it is too large. Load diff
+189
View File
@@ -0,0 +1,189 @@
#pragma once
#include <QMainWindow>
#include <QtCore/QMap>
#include "LogViewModels.hpp"
#include "LogViewTelegramEditModel.hpp"
#include <set>
#include <QMenu>
#include "logger.h"
namespace N_LogView
{
class LogViewTelegram;
}
class QTableView;
class QGroupBox;
class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class QSplitter;
class QToolBox;
namespace N_LogView
{
class LogViewInjectionThread;
class TelegramEdit;
class LogViewGui : public QMainWindow
{
Q_OBJECT
public:
explicit LogViewGui(QWidget* a_parent);
static const QLatin1String WINDOW_GROUP;
static const QLatin1String SCREEN;
protected:
const QSize RADIO_BUTTON_ICON_SIZE;
static const QLatin1String SIZE;
static const QLatin1String POS;
static const QLatin1String SPLITTPOS;
static const QLatin1String TOOLBOXINDEX;
QGroupBox *m_CentralSelectionGroup;
std::set<int> m_CentralTelegramFilterList;
QCheckBox* m_SentCentralTelCheckBox;
QCheckBox* m_ReceivedCentralTelCheckBox;
QCheckBox* m_PosCentralTelCheckBox;
QCheckBox* m_ackCentralTelCheckBox;
QGroupBox *m_TetraSelectionGroup;
std::set<int> m_TetraTelegramFilterList;
QCheckBox* m_SentTetraTelCheckBox;
QCheckBox* m_ReceivedTetraTelCheckBox;
QCheckBox* m_PosTetraTelCheckBox;
QCheckBox* m_LoginTetraTelCheckBox;
QCheckBox* m_RegisterTetraTelCheckBox;
QCheckBox* m_ReportTetraTelCheckBox;
QCheckBox* m_FragmentedTetraTelCheckBox;
QCheckBox* m_AirInterfaceLoadTetraTelCheckBox;
QGroupBox *m_WlsSelectionGroup;
std::set<int> m_WlsTelegramFilterList;
QCheckBox* m_SentWlsTelCheckBox;
QCheckBox* m_ReceivedWlsTelCheckBox;
QCheckBox* m_PosWlsTelCheckBox;
QCheckBox* m_ackWlsTelCheckBox;
QString m_ActualLogfile;
qint64 m_LogfileSize;
bool m_DoReload;
QToolBox* m_ToolBox;
QTableView *m_ParticipantTableView;
ParticipantModel *m_participantModel;
QSortFilterProxyModel *m_participantProxyModel;
QTableView *m_logTelegramView;
TelegramModel *m_telegramModel;
TelegramProxyModel *m_telegramProxyModel;
QLabel *m_TelegramStatus;
QLabel *m_ParticipantStatus;
QGroupBox *m_ParticipantSelectionGroup;
TelegramEdit *m_EditTelegramController;
QTimer *m_TailTimer;
QSplitter *m_Splitter;
LogViewInjectionThread *m_InjectionThread;
QLabel *m_InjectionStatus;
QHash<int, int> m_participantListTelCount;
QHash<int, int> m_participantListIssi;
QAction *m_reloadAction;
QTimer *m_replayTimer;
int m_currentReplayRow;
NGL::INGLLogger &m_logger;
protected:
void readTelegramsFromLogFile(const QString& a_fileName, const qint64 a_filePos = 0);
void addToParticipantList(const QSharedPointer<LogViewTelegram> &a_telegram);
void syncParticipantList();
QCheckBox* createRadioButton(const QString& a_buttonName, const QString& a_iconName);
void startInjectionThread();
void closeEvent(QCloseEvent* a_closeEvent) override;
void createCentralSelectionWidget();
void createTetraSelectionWidget();
void createWlsSelectionWidget();
protected slots:
void addTelegramToEdit();
void showHexData();
void exportAsCsv();
void exportAsJson();
void onStartLogReplay();
void onReplayTimerTimeout();
void loadSpecificationFiles();
void newTelegramFile();
void loadTelegramFile();
void updateLogfile();
void selectedParticipantChanged();
void showTelegramTable();
void customMenuRequested(const QPoint &pos);
void changeSettings();
void reloadOnOff();
void updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText);
void onLogTelegramViewDoubleClicked(const QModelIndex &index);
private slots:
void onSettingsChanged(uint32_t changedFlags);
};
}
+143
View File
@@ -0,0 +1,143 @@
#include "LogViewInjectionThread.hpp"
#include "LogViewTelegram.hpp"
#include "LogViewOptionDialog.hpp"
#include <CoPrtCnv/CoPrtCnvInjectionHeader.hpp>
#include <QtNetwork/QTcpSocket>
#include <QtCore/QTimer>
#include <QtCore/QSettings>
namespace N_LogView
{
LogViewInjectionThread::LogViewInjectionThread()
: m_DoStartConnection(false)
, m_SendingPossible(false)
, m_Socket(nullptr)
, m_Timer(nullptr)
, m_logger(getLogger("LogViewInjectionThread"))
{
QSettings settings;
settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
m_Hostname = settings.value(LogViewOptionDialog::INJECTION_HOSTNAME).toString();
if (m_Hostname.isEmpty())
{
m_Hostname = QLatin1String("localhost");
settings.setValue(LogViewOptionDialog::INJECTION_HOSTNAME, m_Hostname);
}
m_Port = settings.value(LogViewOptionDialog::INJECTION_PORT).toInt();
if (0 == m_Port || m_Port > 65535)
{
m_Port = 46666;
settings.setValue(LogViewOptionDialog::INJECTION_PORT, m_Port);
}
}
void LogViewInjectionThread::run()
{
emit updateStatus(QLatin1String(":/image/RedLamp.png"),
tr("LogView ist nicht mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
QTimer::singleShot(100, this, &LogViewInjectionThread::tryToConnect);
exec();
}
void LogViewInjectionThread::setPort(uint16_t port)
{
m_Port = port;
QSettings settings;
settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
settings.setValue(LogViewOptionDialog::INJECTION_PORT, m_Port);
}
bool LogViewInjectionThread::isSendingPossible() const
{
return m_SendingPossible;
}
void LogViewInjectionThread::tryToConnect()
{
if (!m_Socket)
{
m_Socket = new QTcpSocket(this);
connect(m_Socket, &QTcpSocket::connected, this, &LogViewInjectionThread::doConnect);
connect(m_Socket, &QTcpSocket::disconnected, this, &LogViewInjectionThread::doDisconnect);
}
if (!m_Timer)
{
m_Timer = new QTimer(this);
connect(m_Timer, &QTimer::timeout, this, &LogViewInjectionThread::tryToConnect);
}
m_Timer->setInterval(3000);
m_Timer->start();
INFO_LOG(m_logger) << "Try to connect to injection-server of TETRA-If (" << m_Hostname << ":" << m_Port << ")";
m_Socket->connectToHost(m_Hostname, m_Port);
}
void LogViewInjectionThread::doConnect()
{
INFO_LOG(m_logger) << "LogView has successful connected to injection-server of TETRA-If";
m_SendingPossible = true;
m_Timer->stop();
emit updateStatus(QLatin1String(":/image/GreenLamp.png"),
tr("LogView ist mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
}
void LogViewInjectionThread::doDisconnect()
{
INFO_LOG(m_logger) << "LogView was disconnected from injection-server of TETRA-If";
m_SendingPossible = false;
emit updateStatus(QLatin1String(":/image/RedLamp.png"),
tr("LogView ist nicht mehr mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
tryToConnect();
}
void LogViewInjectionThread::sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram)
{
INFO_LOG(m_logger) << "inject " << (a_doSendAsCentralTelegram ? "central" : "Tetra") << " telegram";
if (!m_Socket || m_Socket->state() != QAbstractSocket::ConnectedState)
{
ERROR_LOG(m_logger) << "Try to write a telegramm but we are not connected";
return;
}
N_CoPrtCnv::CoPrtCnvInjectionHeader injectionHeader;
injectionHeader.m_Kind = a_doSendAsCentralTelegram ? N_CoPrtCnv::CoPrtCnvInjectionHeader::eCentral : N_CoPrtCnv::CoPrtCnvInjectionHeader::eRadio;
const QByteArray &data = a_telegram->getData();
injectionHeader.m_Size = data.size();
m_Socket->write((char*)(&injectionHeader), sizeof(injectionHeader));
m_Socket->write(data);
}
}
@@ -0,0 +1,79 @@
#pragma once
#include <QtCore/QThread>
#include "logger.h"
class QTcpSocket;
class QTimer;
namespace N_LogView
{
class LogViewTelegram;
class LogViewInjectionThread : public QThread
{
Q_OBJECT
public:
LogViewInjectionThread();
void run();
void setPort(uint16_t port);
bool isSendingPossible() const;
void sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram);
protected:
bool m_DoStartConnection;
bool m_SendingPossible;
QString m_Hostname;
int m_Port;
QTcpSocket *m_Socket;
QTimer *m_Timer;
private:
NGL::INGLLogger &m_logger;
protected:
protected slots:
void tryToConnect();
void doConnect();
void doDisconnect();
public:
signals:
void updateStatus(const QString& a_picName, const QString& a_toolTipText);
};
}
+57
View File
@@ -0,0 +1,57 @@
#include <nglapplication/nglapplication.h>
#include <QDesktopWidget>
#include <QtCore/QSettings>
#include <QNetworkProxy>
#ifndef WIN32
#include <unistd.h>
#endif
#include "LogViewGui.hpp"
#include "logger.h"
int main(int argc, char *argv[])
{
std::string logConfigFileName;
std::string dir;
#ifdef WIN32
dir = argv[0];
#else
std::stringstream s;
s << "/proc/" << getpid() << "/exe";
char buf[1024];
ssize_t len = readlink(s.str().c_str(), buf, 1024);
if(len > 0) {
buf[len] = '\0';
dir = buf;
} else {
dir = argv[0];
}
#endif
std::string::size_type pos = dir.find_last_of('/');
if (std::string::npos != pos)
logConfigFileName += dir.substr(0, pos + 1);;
logConfigFileName += "LogView_log4cxx.props";
qputenv("TDS_DEVEL", QByteArray::number(1));
NGLApplication app(argc, argv);
QNetworkProxy::setApplicationProxy(QNetworkProxy());
app.createLogger("LogView", logConfigFileName.c_str());
QCoreApplication::setOrganizationName(QLatin1String("RME"));
QCoreApplication::setApplicationName(QLatin1String("LogView"));
QSettings settings;
settings.beginGroup(N_LogView::LogViewGui::WINDOW_GROUP);
int screenNbr = settings.value(N_LogView::LogViewGui::SCREEN, 0).toInt();
settings.endGroup();
N_LogView::LogViewGui* logViewGui = new N_LogView::LogViewGui(QApplication::desktop()->screen(screenNbr));
logViewGui->show();
int ret = app.exec();
delete logViewGui;
return ret;
}
+548
View File
@@ -0,0 +1,548 @@
#include "LogViewModels.hpp"
#include <QtGui/QFont>
#include <QtGui/QPalette>
#include <QtGui/QGuiApplication>
namespace N_LogView
{
int ParticipantModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_particpants.size();
}
int ParticipantModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 3;
}
QVariant ParticipantModel::data(const QModelIndex &index, int role) const
{
if (index.isValid() && index.row() < m_particpants.size())
{
const auto &p = m_particpants.at(index.row());
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case 0:
return p.first;
case 1:
return p.second;
case 2:
return m_particpantMap.value(p.first);
default:
break;
}
}
if (role == Qt::ToolTipRole)
{
switch (index.column())
{
case 0:
return tr("hex: 0x%1").arg(p.first, 4, 16, QLatin1Char('0'));
case 1:
return tr("hex: 0x%1").arg(p.second, 4, 16, QLatin1Char('0'));
default:
break;
}
}
if (role == Qt::BackgroundColorRole)
{
if (p.first == 0)
return QVariant();
if (m_participantHeatmap.isEmpty())
updateHeatMap();
return m_participantHeatmap.value(p.first);
}
}
return QVariant();
}
QVariant ParticipantModel::headerData(int section,
Qt::Orientation orientation,
int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
switch (section)
{
case 0:
return tr("Equip. No.");
case 1:
return tr("ISSI");
case 2:
return tr("#");
default:
break;
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
void ParticipantModel::clearParticipants()
{
beginResetModel();
m_particpantMap.clear();
m_particpants.clear();
m_participantHeatmap.clear();
endResetModel();
}
bool ParticipantModel::addUpdateParticipants(const QVector<int> &eqIds,
const QVector<int> &issis,
const QVector<int> &numberOfTelegrams)
{
QVector<QPair<int, int> > newParticpants;
for (int i = 0; i < eqIds.size(); ++i)
{
const int eqId = eqIds.at(i);
const int issi = issis.at(i);
const int cntTelegrams = numberOfTelegrams.at(i);
auto it = m_particpantMap.find(eqId);
if (it != m_particpantMap.end())
{
it.value() = cntTelegrams;
continue;
}
newParticpants.push_back(qMakePair(eqId, issi));
m_particpantMap[eqId] = cntTelegrams;
}
if (!newParticpants.isEmpty())
{
beginInsertRows(QModelIndex(), m_particpants.size(), m_particpants.size() + newParticpants.size() - 1);
m_particpants.append(newParticpants);
endInsertRows();
}
m_participantHeatmap.clear();
return true;
}
void ParticipantModel::updateHeatMap() const
{
int maxNumberOfTelegrams = 0;
for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it)
{
if (it.key() == 0)
continue;
maxNumberOfTelegrams = std::max(it.value(), maxNumberOfTelegrams);
}
const QColor backgroundColor = QGuiApplication::palette().base().color();
const QColor redColor = Qt::red;
for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it)
{
const int eqId = it.key();
if (eqId == 0)
continue;
const int nbrTelegrams = it.value();
QColor curColor;
double percent = static_cast<double>(nbrTelegrams) / maxNumberOfTelegrams;
curColor.setRed(backgroundColor.red() - ((backgroundColor.red() - redColor.red()) * percent));
curColor.setGreen(backgroundColor.green() - ((backgroundColor.green() - redColor.green()) * percent));
curColor.setBlue(backgroundColor.blue() - ((backgroundColor.blue() - redColor.blue()) * percent));
m_participantHeatmap[eqId] = curColor;
}
}
int TelegramModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_telegrams.size();
}
int TelegramModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 6;
}
QVariant TelegramModel::data(const QModelIndex &index, int role) const
{
if (index.isValid() && index.row() < m_telegrams.size())
{
if (role == Qt::DisplayRole)
{
const QSharedPointer<LogViewTelegram> &telegram = m_telegrams.at(index.row());
switch (index.column())
{
case 0:
return telegram->getDestinationText();
case 1:
return telegram->getName();
case 2:
return telegram->getParticipantId();
case 3:
return telegram->getLogTimeText();
case 4:
return telegram->getGpsTimeText();
case 5:
return telegram->getDelay();
}
}
if (role == Qt::DecorationRole)
{
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
switch (index.column())
{
case 0:
return telegram->getIcon();
default:
break;
}
}
if (role == Qt::ToolTipRole)
{
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
switch (index.column())
{
case 1:
return telegram->getToolTipText(LogViewTelegram::e_ColName);
case 3:
return telegram->getToolTipText(LogViewTelegram::e_ColLogTime);
case 4:
return telegram->getToolTipText(LogViewTelegram::e_ColGpsTime);
default:
break;
}
}
}
return QVariant();
}
QVariant TelegramModel::headerData(int section,
Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal)
{
if (role == Qt::DisplayRole)
{
switch (section)
{
case 0:
return tr("Dest.");
case 1:
return tr("Description");
case 2:
return tr("Equip. No.");
case 3:
return tr("Send/Recieve time");
case 4:
return tr("GPS time");
case 5:
return tr("Delay");
default:
break;
}
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
void TelegramModel::clearTelegrams()
{
beginResetModel();
m_telegrams.clear();
endResetModel();
}
void TelegramModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams)
{
if (telegrams.isEmpty())
return;
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size() + telegrams.size() - 1);
m_telegrams += telegrams;
endInsertRows();
}
void TelegramModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
{
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size());
m_telegrams.push_back(telegram);
endInsertRows();
}
QSharedPointer<LogViewTelegram> TelegramModel::telegram(int row) const
{
if (row >= 0 && row < m_telegrams.size())
return m_telegrams.at(row);
return QSharedPointer<LogViewTelegram>();
}
void TelegramProxyModel::setFilterByEquipmentIds(bool bFilterByEquipmentIds)
{
if (m_bFilterByEquipmentIds == bFilterByEquipmentIds)
return;
m_bFilterByEquipmentIds = bFilterByEquipmentIds;
invalidateFilter();
}
void TelegramProxyModel::setAllowedEquipmentIds(const std::set<int> &allowedEquipmentIds)
{
if (m_allowedEquipmentIds == allowedEquipmentIds)
return;
m_allowedEquipmentIds = allowedEquipmentIds;
invalidateFilter();
}
void TelegramProxyModel::setFilteredCentralTelegramIds(const std::set<int> &filteredCentralTelegramIds)
{
if (m_filteredCentralTelegramIds == filteredCentralTelegramIds)
return;
m_filteredCentralTelegramIds = filteredCentralTelegramIds;
invalidateFilter();
}
void TelegramProxyModel::setFilteredTetraTelegramIds(const std::set<int> &filteredTetraTelegramIds)
{
if (m_filteredTetraTelegramIds == filteredTetraTelegramIds)
return;
m_filteredTetraTelegramIds = filteredTetraTelegramIds;
invalidateFilter();
}
void TelegramProxyModel::setFilteredWlsTelegramIds(const std::set<int> &filteredWlsTelegramIds)
{
if (m_filteredWlsTelegramIds == filteredWlsTelegramIds)
return;
m_filteredWlsTelegramIds = filteredWlsTelegramIds;
invalidateFilter();
}
void TelegramProxyModel::setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
bool bFilter)
{
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> curFilter = m_filterCentralTelegrams;
if (bFilter)
curFilter.insert(direction);
else
curFilter.erase(direction);
if (curFilter == m_filterCentralTelegrams)
return;
m_filterCentralTelegrams = curFilter;
invalidateFilter();
}
void TelegramProxyModel::setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
bool bFilter)
{
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> curFilter = m_filterTetraTelegrams;
if (bFilter)
curFilter.insert(direction);
else
curFilter.erase(direction);
if (curFilter == m_filterTetraTelegrams)
return;
m_filterTetraTelegrams = curFilter;
invalidateFilter();
}
void TelegramProxyModel::setFilterTetraPDU(N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType,
bool bFilter)
{
std::set<N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type> curFilter = m_filterTetraPDU;
if (bFilter)
curFilter.insert(pduType);
else
curFilter.erase(pduType);
if (curFilter == m_filterTetraPDU)
return;
m_filterTetraPDU = curFilter;
invalidateFilter();
}
void TelegramProxyModel::setFilterWlsTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
bool bFilter)
{
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> curFilter = m_filterWlsTelegrams;
if (bFilter)
curFilter.insert(direction);
else
curFilter.erase(direction);
if (curFilter == m_filterWlsTelegrams)
return;
m_filterWlsTelegrams = curFilter;
invalidateFilter();
}
void TelegramProxyModel::setFilterTetraLogin(bool bFilter)
{
if (m_bFilterLoginTelegrams == bFilter)
return;
m_bFilterLoginTelegrams = bFilter;
invalidateFilter();
}
void TelegramProxyModel::setFilterTetraFragmented(bool bFilter)
{
if (m_bFilterFragmentedTelegrams == bFilter)
return;
m_bFilterFragmentedTelegrams = bFilter;
invalidateFilter();
}
QSharedPointer<LogViewTelegram> TelegramProxyModel::telegram(int row) const
{
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
if (!tm)
return {};
const int srcRow = mapToSource(index(row, 0)).row();
return tm->telegram(srcRow);
}
bool TelegramProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
if (left.column() != right.column())
return QSortFilterProxyModel::lessThan(left, right);
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
if (!tm)
return QSortFilterProxyModel::lessThan(left, right);
QSharedPointer<LogViewTelegram> teleLeft = tm->telegram(left.row());
QSharedPointer<LogViewTelegram> teleRight = tm->telegram(right.row());
if (!teleLeft || !teleRight)
return QSortFilterProxyModel::lessThan(left, right);
switch (left.column())
{
case 0:
return teleLeft->getDestination() < teleRight->getDestination();
case 1:
return teleLeft->getName() < teleRight->getName();
case 2:
return teleLeft->getParticipantId() < teleRight->getParticipantId();
case 3:
return teleLeft->getLogTime() < teleRight->getLogTime();
case 4:
return teleLeft->getGpsTime() < teleRight->getGpsTime();
case 5:
return teleLeft->getDelay() < teleRight->getDelay();
}
return QSortFilterProxyModel::lessThan(left, right);
}
bool TelegramProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
if (!tm)
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
QSharedPointer<LogViewTelegram> tele = tm->telegram(source_row);
if (!tele)
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
if (m_bFilterByEquipmentIds)
{
int equipId = tele->getParticipantId();
if (m_allowedEquipmentIds.find(equipId) == m_allowedEquipmentIds.end())
return false;
}
switch (tele->getProtocol())
{
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral:
if (!m_filteredCentralTelegramIds.empty())
{
const int telegramId = tele->getTelId();
if (m_filteredCentralTelegramIds.find(telegramId) != m_filteredCentralTelegramIds.end())
return false;
}
if (!m_filterCentralTelegrams.empty())
{
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction = tele->getDirection();
if (m_filterCentralTelegrams.find(direction) != m_filterCentralTelegrams.end())
return false;
}
break;
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra:
{
if (!m_filteredTetraTelegramIds.empty())
{
const int telegramId = tele->getTelId();
if (m_filteredTetraTelegramIds.find(telegramId) != m_filteredTetraTelegramIds.end())
return false;
}
if (!m_filterTetraTelegrams.empty())
{
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction = tele->getDirection();
if (m_filterTetraTelegrams.find(direction) != m_filterTetraTelegrams.end())
return false;
}
const N_CoPrtCnv::CoPrtCnvRadioTelegram *tetraTelegram = tele->getTetraTelegram();
if (tetraTelegram)
{
if (!m_filterTetraPDU.empty())
{
N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType = tetraTelegram->getPDU_Type();
if (m_filterTetraPDU.find(pduType) != m_filterTetraPDU.end())
return false;
}
if (m_bFilterLoginTelegrams)
{
if (tetraTelegram->isLoginTelegram())
return false;
}
if (m_bFilterFragmentedTelegrams)
{
if (!tetraTelegram->isLoginTelegram() && !tetraTelegram->isNormalTelegram())
return false;
}
}
break;
}
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls:
if (!m_filteredWlsTelegramIds.empty())
{
const int telegramId = tele->getTelId();
if (m_filteredWlsTelegramIds.find(telegramId) != m_filteredWlsTelegramIds.end())
return false;
}
if (!m_filterWlsTelegrams.empty())
{
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction = tele->getDirection();
if (m_filterWlsTelegrams.find(direction) != m_filterWlsTelegrams.end())
return false;
}
break;
default:
break;
}
return true;
}
}
+109
View File
@@ -0,0 +1,109 @@
#pragma once
#include <QtCore/QAbstractTableModel>
#include <QtCore/QSharedPointer>
#include <QSortFilterProxyModel>
#include <set>
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include "LogViewTelegram.hpp"
namespace N_LogView
{
class ParticipantModel final : public QAbstractTableModel
{
Q_OBJECT
public:
using QAbstractTableModel::QAbstractTableModel;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
void clearParticipants();
bool addUpdateParticipants(const QVector<int> &eqIds,
const QVector<int> &issis,
const QVector<int> &numberOfTelegrams);
protected:
void updateHeatMap() const;
protected:
QVector<QPair<int, int> > m_particpants;
QHash<int, int> m_particpantMap;
mutable QHash<int, QColor> m_participantHeatmap;
};
class TelegramModel final : public QAbstractTableModel
{
Q_OBJECT
public:
using QAbstractTableModel::QAbstractTableModel;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
void clearTelegrams();
void appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams);
void appendTelegram(const QSharedPointer<LogViewTelegram> &telegram);
QSharedPointer<LogViewTelegram> telegram(int row) const;
protected:
QVector<QSharedPointer<LogViewTelegram> > m_telegrams;
};
class TelegramProxyModel final : public QSortFilterProxyModel
{
Q_OBJECT
public:
using QSortFilterProxyModel::QSortFilterProxyModel;
void setFilterByEquipmentIds(bool bFilterByEquipmentIds);
void setAllowedEquipmentIds(const std::set<int> &allowedEquipmentIds);
void setFilteredCentralTelegramIds(const std::set<int> &filteredCentralTelegramIds);
void setFilteredTetraTelegramIds(const std::set<int> &filteredTetraTelegramIds);
void setFilteredWlsTelegramIds(const std::set<int> &filteredWlsTelegramIds);
void setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter);
void setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter);
void setFilterTetraPDU(N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType, bool bFilter);
void setFilterWlsTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter);
void setFilterTetraLogin(bool bFilter);
void setFilterTetraFragmented(bool bFilter);
QSharedPointer<LogViewTelegram> telegram(int row) const;
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
protected:
std::set<int> m_allowedEquipmentIds;
std::set<int> m_filteredCentralTelegramIds;
std::set<int> m_filteredTetraTelegramIds;
std::set<int> m_filteredWlsTelegramIds;
bool m_bFilterByEquipmentIds = false;
bool m_bFilterLoginTelegrams = false;
bool m_bFilterFragmentedTelegrams = false;
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> m_filterCentralTelegrams;
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> m_filterTetraTelegrams;
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> m_filterWlsTelegrams;
std::set<N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type> m_filterTetraPDU;
};
}
+182
View File
@@ -0,0 +1,182 @@
#include "LogViewOptionDialog.hpp"
#include <QCoreApplication>
#include <QDialogButtonBox>
#include <QDir>
#include <QGridLayout>
#include <QGroupBox>
#include <QFileDialog>
#include <QIntValidator>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
namespace N_LogView
{
const QString LogViewOptionDialog::SPEC_FILES = tr("Spezifikations-Dateien (*.x)");
const QString LogViewOptionDialog::KRLOG_FILES = tr("Log-Dateien (*.krlog)");
const QLatin1String LogViewOptionDialog::SPEC_FILES_GROUP("SpecFiles");
const QLatin1String LogViewOptionDialog::DIR("Dir");
const QLatin1String LogViewOptionDialog::P0_FILENAME("Central2PrtCnv");
const QLatin1String LogViewOptionDialog::P5_FILENAME("PrtCnv2TETRA");
const QLatin1String LogViewOptionDialog::SERVER_GROUP("ServerPorts");
const QLatin1String LogViewOptionDialog::CENTRAL_PORT("Central");
const QLatin1String LogViewOptionDialog::TETRA_PORT("Tetra");
const QLatin1String LogViewOptionDialog::LOG_FILENAME("LogFilename");
const QLatin1String LogViewOptionDialog::INJECTION_GROUP("InjectionServer");
const QLatin1String LogViewOptionDialog::INJECTION_HOSTNAME("InjectionHostname");
const QLatin1String LogViewOptionDialog::INJECTION_PORT("InjectionPort");
LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
: QDialog(a_parent)
{
QVBoxLayout* layout = new QVBoxLayout(this);
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
QGroupBox* groupBox = new QGroupBox(tr("Telegramm-Spezifikations-Dateien"), this);
layout->addWidget(groupBox);
QGridLayout* groupLayout = new QGridLayout();
QLabel* p0Label = new QLabel(tr("&Zentrale - Protokollkonverter"), this);
groupLayout->addWidget(p0Label, 0, 0, 1, 2);
QString defString = QCoreApplication::applicationDirPath() + QLatin1String("/training_area_telegrams.h");
m_P0Edit = new QLineEdit(m_Settings.value(P0_FILENAME, defString).toString(), this);
m_P0Edit->setMinimumWidth(400);
groupLayout->addWidget(m_P0Edit);
QPushButton* p0Browse = new QPushButton(tr("Browse"), this);
p0Label->setBuddy(p0Browse);
connect(p0Browse, &QPushButton::clicked, this, &LogViewOptionDialog::browseP0File);
groupLayout->addWidget(p0Browse, 1, 1);
QLabel* p5Label = new QLabel(tr("Protokollkonverter - &TETRA"), this);
groupLayout->addWidget(p5Label, 2, 0, 1, 2);
defString = QCoreApplication::applicationDirPath() + QLatin1String("/zsksxd_tetraForLogView.x");
m_P5Edit = new QLineEdit(m_Settings.value(P5_FILENAME, defString).toString(), this);
groupLayout->addWidget(m_P5Edit);
QPushButton* p5Browse = new QPushButton(tr("Browse"), this);
p5Label->setBuddy(p5Browse);
connect(p5Browse, &QPushButton::clicked, this, &LogViewOptionDialog::browseP5File);
groupLayout->addWidget(p5Browse, 3, 1);
groupBox->setLayout(groupLayout);
m_Settings.endGroup();
m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
groupBox = new QGroupBox(tr("Telegram Injection Server"), this);
layout->addWidget(groupBox);
QGridLayout* injectLayout = new QGridLayout();
QLabel* injectPortLabel = new QLabel(tr("Port"), this);
injectLayout->addWidget(injectPortLabel, 1, 0);
m_InjectPortEdit = new QLineEdit(m_Settings.value(INJECTION_PORT).toString(), this);
QIntValidator* validator = new QIntValidator(1024, 65535, this);
m_InjectPortEdit->setValidator(validator);
injectLayout->addWidget(m_InjectPortEdit, 1, 1);
QLabel* injectHostnameLabel = new QLabel(tr("Hostname"), this);
injectLayout->addWidget(injectHostnameLabel, 0, 0);
m_InjectHostnameEdit = new QLineEdit(m_Settings.value(INJECTION_HOSTNAME).toString(), this);
injectLayout->addWidget(m_InjectHostnameEdit, 0, 1);
groupBox->setLayout(injectLayout);
m_Settings.endGroup();
layout->addStretch();
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &LogViewOptionDialog::save);
connect(buttonBox, &QDialogButtonBox::rejected, this, &LogViewOptionDialog::reject);
layout->addWidget(buttonBox);
}
void LogViewOptionDialog::browseP0File()
{
QString newFilename = QFileDialog::getOpenFileName(this,
tr("Zentrale - Protokollkonverter Spezifikations-Datei"),
m_Settings.value(DIR).toString(),
tr("TrainingArea Telegram Headerdatei (training_area_telegrams.h)"));
if (!newFilename.isEmpty())
{
m_P0Edit->setText(newFilename);
QDir dir;
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
m_Settings.setValue(DIR, dir.filePath(newFilename));
m_Settings.endGroup();
}
}
void LogViewOptionDialog::browseP5File()
{
QString newFilename = QFileDialog::getOpenFileName(this, tr("Protokollkonverter - TETRA Spezifikations-Datei"), m_Settings.value(DIR).toString(), SPEC_FILES);
if (!newFilename.isEmpty())
{
m_P5Edit->setText(newFilename);
QDir dir;
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
m_Settings.setValue(DIR, dir.filePath(newFilename));
m_Settings.endGroup();
}
}
void LogViewOptionDialog::save()
{
uint32_t changedFlags = 0;
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
QString string = m_Settings.value(P0_FILENAME).toString();
if ((string != m_P0Edit->text()) ||
(m_Settings.value(P5_FILENAME).toString() != m_P5Edit->text()))
{
m_Settings.setValue(P0_FILENAME, m_P0Edit->text());
m_Settings.setValue(P5_FILENAME, m_P5Edit->text());
changedFlags |= SpecFilesGroup;
}
m_Settings.endGroup();
m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
if ((m_Settings.value(INJECTION_HOSTNAME).toString() != m_InjectHostnameEdit->text()) ||
(m_Settings.value(INJECTION_PORT).toString() != m_InjectPortEdit->text()))
{
m_Settings.setValue(INJECTION_HOSTNAME, m_InjectHostnameEdit->text());
m_Settings.setValue(INJECTION_PORT, m_InjectPortEdit->text());
changedFlags |= InjectionGroup;
}
m_Settings.endGroup();
emit settingsChanged(changedFlags);
accept();
}
}
+77
View File
@@ -0,0 +1,77 @@
#pragma once
#include <QDialog>
#include <QtCore/QSettings>
class QLineEdit;
namespace N_LogView
{
class LogViewOptionDialog : public QDialog
{
Q_OBJECT
public:
enum SettingsChangedFlag {
SpecFilesGroup = 0x01,
ServerGroup = 0x02,
InjectionGroup = 0x04
};
static const QString KRLOG_FILES;
static const QLatin1String SPEC_FILES_GROUP;
static const QLatin1String P0_FILENAME;
static const QLatin1String P5_FILENAME;
static const QLatin1String SERVER_GROUP;
static const QLatin1String CENTRAL_PORT;
static const QLatin1String TETRA_PORT;
static const QLatin1String SIZE;
static const QLatin1String POS;
static const QLatin1String CENTRAL_IS_SERVER;
static const QLatin1String CENTRAL_HOSTNAME;
static const QLatin1String LOG_FILENAME;
static const QLatin1String INJECTION_GROUP;
static const QLatin1String INJECTION_HOSTNAME;
static const QLatin1String INJECTION_PORT;
explicit LogViewOptionDialog(QWidget* a_parent);
signals:
void settingsChanged(uint32_t changed);
protected:
static const QString SPEC_FILES;
static const QLatin1String DIR;
bool m_IsServer;
QLineEdit *m_P0Edit;
QLineEdit *m_P5Edit;
QSettings m_Settings;
QLineEdit *m_InjectHostnameEdit;
QLineEdit *m_InjectPortEdit;
protected slots:
void browseP0File();
void browseP5File();
void save();
};
}
+18
View File
@@ -0,0 +1,18 @@
<RCC>
<qresource prefix="/" >
<file>image/P2C.png</file>
<file>image/C2P.png</file>
<file>image/P2W.png</file>
<file>image/W2P.png</file>
<file>image/P2T.png</file>
<file>image/T2P.png</file>
<file>image/Central.png</file>
<file>image/Tetra.png</file>
<file>image/TNE.png</file>
<file>image/GreenLamp.png</file>
<file>image/RedLamp.png</file>
<file>image/YellowLamp.png</file>
<file>image/ShowSend.png</file>
<file>image/Wls.png</file>
</qresource>
</RCC>
+59
View File
@@ -0,0 +1,59 @@
#include "LogViewSpinBox.hpp"
#include "LogViewField.hpp"
namespace N_LogView
{
LogViewSpinBox::LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value)
: QSpinBox(a_parent)
, LogViewWidget(a_field, this, a_parent, false)
{
uint16_t maxArraySize = a_field->maxArraySize();
setRange(0, maxArraySize);
setValue(a_value);
setToolTip(tr("<nobr>Wertebereich: 0..%1</nobr>").arg(maxArraySize));
connect(this, &LogViewSpinBox::editingFinished,
this, &LogViewSpinBox::finishEditing);
}
void LogViewSpinBox::finishEditing()
{
emit valueEditingFinished(text().toInt());
}
bool LogViewSpinBox::saveContent(LogViewTelegram* a_telegram)
{
Q_UNUSED(a_telegram);
return false;
}
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include <QSpinBox>
#include "LogViewWidget.hpp"
namespace N_LogView
{
class LogViewSpinBox : public QSpinBox, public LogViewWidget
{
Q_OBJECT
public:
LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value);
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void finishEditing();
signals:
void valueEditingFinished(int a_newValue);
};
}
+139
View File
@@ -0,0 +1,139 @@
#include "LogViewTabWidget.hpp"
#include <QFrame>
#include <QGridLayout>
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
#include "LogViewTelegramDialog.hpp"
#include "LogViewSpinBox.hpp"
#include "LogViewTelegram.hpp"
#include "LogViewTetraTelegramsParser.hpp"
namespace N_LogView
{
LogViewTabWidget::LogViewTabWidget(LogViewField* a_field, LogViewTelegramDialog* a_parent, LogViewSpinBox* a_spinBox)
: QTabWidget(a_parent)
, LogViewWidget(a_field, this, a_parent, false)
, m_TelegramDialog(a_parent)
, m_SpinBox(a_spinBox)
{
setVisible(false);
}
void LogViewTabWidget::changeSize(const int a_newSize)
{
for (int i = count(); i < a_newSize; i++)
addTab(m_Field, true, i);
while (count() > a_newSize)
{
QStringList path = m_Field->jsonPath();
path += QStringLiteral("index: %1").arg(count() - 1);
m_TelegramDialog->removeItemsFromEditInfoList(path);
removeTab(count() - 1);
}
while (m_Field->childCount() > a_newSize)
m_Field->removeLastChild();
setVisible(a_newSize > 0);
m_TelegramDialog->makePretty();
}
bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram)
{
if (a_telegram->isJsonTelegram())
return true;
if (m_SpinBox)
{
if (!isValid())
return false;
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, count());
}
return true;
}
void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx)
{
if (arrayIdx < 0)
{
WARNING_LOG(m_logger) << "Invalid array index given: " << arrayIdx;
return;
}
QFrame *frame = new QFrame;
QGridLayout *box = new QGridLayout(frame);
QTabWidget::addTab(frame, QStringLiteral("%1 %2").arg(a_field->cleanName()).arg(count()+1));
if (a_isEmpty)
a_field->setHasContent(false);
auto *childTree = a_field->child(arrayIdx);
while (!childTree)
{
const auto *first = a_field->child(0);
if (first)
{
LogViewField *fNew = first->clone(arrayIdx);
a_field->addChild(fNew);
childTree = a_field->child(arrayIdx);
}
else
{
LogViewTetraTelegramsParser *p = LogViewTelegram::jsonParser();
const StructInformation si = p->structFromType(a_field->type());
if (si.type != a_field->type())
{
WARNING_LOG(m_logger) << "Could not find type '" << a_field->type() << "' - can not add substructure";
return;
}
LogViewField *tc = new LogViewField(a_field->name() + QStringLiteral("TabChild"), LogViewField::e_FieldKindTabChild, a_field->xdrElement());
tc->setJsonPath(a_field->jsonPath());
a_field->addChild(tc);
const QString path(QStringLiteral("index: %1"));
LogViewTelegram::addFieldTreeStruct(QJsonObject(), tc, si, path.arg(arrayIdx), m_logger);
childTree = a_field->child(arrayIdx);
}
}
m_TelegramDialog->showTree(childTree, box);
if (m_SpinBox)
{
int spinValue = m_SpinBox->value();
if (spinValue < count())
m_SpinBox->setValue(count());
}
setVisible(true);
}
}
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include <QTabWidget>
#include "LogViewWidget.hpp"
namespace N_LogView
{
class LogViewTelegramDialog;
class LogViewSpinBox;
class LogViewTabWidget : public QTabWidget, public LogViewWidget
{
Q_OBJECT
public:
LogViewTabWidget(LogViewField* a_field, LogViewTelegramDialog* a_parent, LogViewSpinBox* a_spinBox);
bool saveContent(LogViewTelegram* a_telegram) override;
void addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx);
public slots:
void changeSize(const int a_newSize);
protected:
LogViewTelegramDialog* m_TelegramDialog;
LogViewSpinBox* m_SpinBox;
};
}
+311
View File
@@ -0,0 +1,311 @@
#include "LogViewTableWidget.hpp"
#include "LogViewField.hpp"
#include <QHeaderView>
#include <QJsonArray>
#include "LogViewXdrStandardType.hpp"
#include "LogViewTelegram.hpp"
#include "LogViewEnumEdit.hpp"
namespace N_LogView
{
LogViewTableWidget::LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QTableWidget(0, 2, a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
, m_IsFloat(false)
, m_IsEnum(false)
{
switch (m_Field->xdrElement()->getKind())
{
case LogViewXdrElement::e_KindEnum:
m_IsEnum = true;
break;
default:
m_IsFloat = LogViewXdrStandardType::e_Float == static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement())->getValueKind();
}
if (!m_IsFloat)
setColumnCount(3);
if (m_IsEnum)
setColumnCount(1);
setHorizontalHeaderItem(0, new QTableWidgetItem(m_IsEnum ? tr("Enum") : tr("Dez")));
if (!m_IsEnum)
{
setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Hex")));
if (!m_IsFloat)
{
setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Bin")));
}
}
setAlternatingRowColors(true);
updateToolTip();
int nbrOfRows = a_field->valueListSize();
setRowCount(nbrOfRows);
for (int i = 0; i < nbrOfRows; i++)
changeRow(i, a_field->value(i));
makePretty();
connect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
}
void LogViewTableWidget::changeSize(const int a_newSize)
{
setRowCount(a_newSize);
disconnect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
for (int i = 0; i < a_newSize; i++)
changeRow(i, QLatin1String("0"));
connect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
makePretty();
m_Valid = true;
}
void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
{
if (m_IsEnum)
{
QWidget* enumItem = cellWidget(a_rowIndex, 0);
if (!enumItem)
setCellWidget(a_rowIndex, 0, new LogViewEnumEdit(m_Field, this, m_Readonly, a_rowIndex));
}
else
{
QFont font;
font.setStyleHint(QFont::TypeWriter);
font.setFamily(QString());
QTableWidgetItem* decItem = item(a_rowIndex, 0);
if (!decItem)
{
decItem = new QTableWidgetItem();
decItem->setText(a_value);
decItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
if (!m_Readonly)
{
decItem->setFlags(decItem->flags() | Qt::ItemIsEditable);
}
decItem->setFont(font);
decItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
setItem(a_rowIndex, 0, decItem);
}
QTableWidgetItem* hexItem = item(a_rowIndex, 1);
if (!hexItem)
{
hexItem = new QTableWidgetItem();
hexItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
hexItem->setFont(font);
hexItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
setItem(a_rowIndex, 1, hexItem);
}
if (!m_IsFloat)
{
QTableWidgetItem* binItem = item(a_rowIndex, 2);
if (!binItem)
{
binItem = new QTableWidgetItem();
binItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
binItem->setFont(font);
binItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
setItem(a_rowIndex, 2, binItem);
}
}
checkAndOvertakeContent(decItem);
makePretty();
}
}
void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem)
{
if (a_changedItem->column() != 0) return;
int row = a_changedItem->row();
QString text = a_changedItem->text();
bool ok;
int64_t intValue = 0;
double floatValue = 0.0;
if (m_IsFloat)
floatValue = getFloat(text, (uint64_t&)intValue, ok, true);
else
intValue = getInteger(text, ok);
if (!ok)
{
setFocus();
setCurrentCell(row, 0);
return;
}
QTableWidgetItem* decField = item(row, 0);
if (decField) decField->setText(QString::number(m_IsFloat ? floatValue : intValue));
QTableWidgetItem* hexField = item(row, 1);
if (hexField) hexField->setText(toHex(intValue));
if (!m_IsFloat)
{
QTableWidgetItem* binField = item(row, 2);
if (binField) binField->setText(toBin(intValue));
}
}
void LogViewTableWidget::makePretty()
{
resizeColumnsToContents();
resizeRowsToContents();
}
bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram)
{
if (!isValid())
return false;
if (a_telegram->isJsonTelegram())
{
if (m_Field->kind() == LogViewField::e_FieldKindPodArray)
{
QJsonArray arr;
for (int i = 0; i < rowCount(); ++i)
arr += item(i, 0)->text().toInt();
a_telegram->setJsonValue(m_Field->jsonPath(), arr);
}
else
{
QString value;
value.reserve(rowCount() * 2);
for (int i = 0; i < rowCount(); ++i)
{
int val = item(i, 0)->text().toInt();
value += QStringLiteral("%1").arg(val, 2, 16, QLatin1Char('0'));
}
a_telegram->setJsonValue(m_Field->jsonPath(), value);
}
return true;
}
uint16_t arraySize;
if (m_Field->isDynamicArray())
{
arraySize = rowCount();
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize);
}
else
{
arraySize = m_Field->maxArraySize();
}
INFO_LOG(m_logger) << "arraySize=" << arraySize;
for (int i = 0; i < arraySize; i++)
{
if (m_IsEnum)
{
LogViewEnumEdit *enumEdit = dynamic_cast<LogViewEnumEdit*>(cellWidget(i,0));
enumEdit->saveContent(a_telegram);
}
else
{
uint16_t size = getSize();
QString text = item(i, 0)->text();
if (!m_IsFloat)
{
a_telegram->setUIntX(size, text.toULong());
}
else
{
const LogViewXdrStandardType *stdType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
LogViewXdrStandardType::E_ByteOrder byteOrder = stdType->getByteOrder();
uint64_t hex;
getFloat(text, hex, m_Valid);
a_telegram->setUIntX(size, hex, byteOrder);
}
}
}
return true;
}
}
+46
View File
@@ -0,0 +1,46 @@
#pragma once
#include <QTableWidget>
#include "LogViewWidget.hpp"
namespace N_LogView
{
class LogViewTableWidget : public QTableWidget, public LogViewWidget
{
Q_OBJECT
public:
LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
bool saveContent(LogViewTelegram* a_telegram) override;
public slots:
void changeSize(const int a_newSize);
protected:
void changeRow(const int a_rowIndex, const QString& a_value);
void makePretty();
protected slots:
void checkAndOvertakeContent(QTableWidgetItem* a_changedItem);
private:
bool m_IsFloat;
bool m_IsEnum;
};
}
File diff suppressed because it is too large. Load diff
+372
View File
@@ -0,0 +1,372 @@
#pragma once
#include "LogViewXdrStandardType.hpp"
#include "LogViewField.hpp"
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
#include <QIcon>
#include <QJsonObject>
#include <QJsonDocument>
namespace N_CoPrtCnv
{
class CoPrtCnvRadioTelegram;
}
namespace N_LogView
{
struct StructInformation;
struct MemberInformation;
class LogViewTetraTelegramsParser;
class LogViewXdrParser;
class LogViewXdrType;
class LogViewTelegram final
{
public:
enum E_Validity
{
e_NotYetEvaluated,
e_Valid,
e_Invalid
};
enum E_Column
{
e_ColName,
e_ColGpsTime,
e_ColLogTime,
e_ColJsonData,
e_ColMax
};
~LogViewTelegram();
static const uint16_t SIZE_CENTRAL_DYN_ARRAY_SIZE;
LogViewTelegram(const LogViewTelegram &o);
LogViewTelegram &operator=(const LogViewTelegram &o) = delete;
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
int telegramId);
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
const quint64 a_unixTime,
const QByteArray &a_telegramData);
void setUIntX(const uint8_t a_size,
quint64 a_value,
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
bool setData(const uint16_t a_offset, const uint8_t a_data);
quint64 getLogTime() const { return m_LogTime; }
quint64 getLogTimeMsec() const;
QString getLogTimeText() const;
QString getDestinationText() const;
quint64 getGpsTime() const { return m_GpsTime; }
QString getGpsTimeText() const;
uint32_t getISSI() const { return m_ISSI; }
int getParticipantId() const { return m_ParticipantId; }
int32_t getDelay() const;
QString getToolTipText(const E_Column a_col);
void resetOffset();
LogViewField* getFieldTree();
void dump() const;
QString getStructName() const;
bool isValid();
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol getDestination() const { return m_Destination; }
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol getDirection() const;
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol getProtocol() const { return m_Protocol; }
int getTelId() const { return m_TelId; }
QIcon getIcon() const;
bool isJsonTelegram() const { return N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Protocol; }
void clearJsonData() { m_json.remove(QStringLiteral("data")); }
void rebuildJsonString() { if (!m_json.isEmpty()) m_data.clear(); }
void setJsonValue(const QStringList &path, const QJsonValue &val);
QJsonObject jsonData() const { return m_json; }
void updateJsonValue(const QStringList &path, const QJsonValue &newVal, QJsonObject &obj);
void updateJsonValue(const QStringList &path, const QJsonValue &newVal, QJsonArray &arr);
const N_CoPrtCnv::CoPrtCnvRadioTelegram* getTetraTelegram() const;
static LogViewTetraTelegramsParser *jsonParser();
static LogViewXdrParser *tetraParser();
QByteArray getData(QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Compact) const;
uint32_t getWaitTime() const { return m_WaitTime; }
void setWaitTime(uint32_t newVal) { m_WaitTime = newVal; }
QString getName() const { return m_Name; }
void setName(const QString &newVal) { m_Name = newVal; }
void setNextFieldAsGpsTimeField();
QVector<uint16_t> getGpsTimeField() const { return m_GpsFieldOffset; }
void setGpsTimeField(const QVector<uint16_t> &gpsFieldOffset) { m_GpsFieldOffset = gpsFieldOffset; }
void actualizeGpsTime();
void createToolTipTextForColName();
static double xdrToDouble(quint64 in);
static float xdrToFloat(uint32_t in);
static quint64 doubleToXdr(double in);
static uint32_t floatToXdr(float in);
protected:
QString m_Name;
std::vector<QString> m_ToolTipText;
uint32_t m_WaitTime;
int m_ParticipantId;
uint32_t m_ISSI;
int m_AllocatedSize;
static const LogViewXdrParser* m_Parser;
uint16_t m_ActOffset;
QVector<uint16_t> m_GpsFieldOffset;
int m_TelId;
uint32_t m_LastUnsignedValue;
uint16_t m_MaxArraySize;
static const uint16_t START_OFFSET_CENTRAL;
static const uint16_t POS_CENTRAL_COUNTER;
static const uint16_t POS_CENTRAL_TELID;
static const uint16_t POS_CENTRAL_PARTICIPANTID;
static const uint16_t START_OFFSET_TETRA_REGISTER;
static const uint16_t START_OFFSET_TETRA_AIRLOAD;
static const uint16_t START_OFFSET_TETRA_DATA;
static const uint16_t START_OFFSET_TETRA_LOGIN;
static const uint16_t START_OFFSET_TETRA_FRAGMENT;
LogViewXdrStandardType::E_DynArraySizeMethod m_DynArraySizeMethod;
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol m_Destination;
E_Validity m_Validity;
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol m_Protocol;
quint64 m_LogTime;
mutable QString m_logTimeText;
quint64 m_GpsTime;
QByteArray m_data;
QJsonObject m_json;
N_CoPrtCnv::CoPrtCnvRadioTelegram *m_TetraTelegram;
LogViewField *getFieldTree(const QString& a_type, const QString& a_name,
uint16_t a_arraySize, const LogViewXdrType* a_parentElement = nullptr,
const bool a_hasContent = true);
LogViewField *getFieldTreeJson(const QJsonValue &data,
const QString &name,
const StructInformation &si,
const QStringList &objectPathBase);
static void addFieldTreeStruct(const QJsonObject &parentObject,
LogViewField *parent,
const StructInformation &si,
const QString &objectNameArrayHint,
NGL::INGLLogger &logger);
static void addFieldTreeJsonString(const QJsonValue &val,
LogViewField *parent,
const QString &name,
bool isBinary,
const QString &objectNameArrayHint,
LogViewField::E_FieldKind fieldKind,
NGL::INGLLogger &logger);
static void addFieldTreeJsonPod(const QJsonValue &val,
LogViewField *parent,
const QString &name,
const QString &type,
const QString &objectNameArrayHint,
LogViewField::E_FieldKind fieldKind,
NGL::INGLLogger &logger);
static void addFieldTreeJsonEnum(const QJsonValue &val,
LogViewField *parent,
const QString &name,
const QString &type,
const QString &objectNameArrayHint,
LogViewField::E_FieldKind fieldKind,
NGL::INGLLogger &logger);
static QString typeFromStructInformation(const StructInformation &si, const QString &name);
static MemberInformation memberFromStructInformation(const StructInformation &si, const QString &name);
uint16_t getUInt16(const uint16_t a_offset) const;
uint32_t getUInt32(const uint16_t a_offset) const;
int32_t getInt32(const uint16_t a_offset) const;
quint64 getUIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
int32_t getSIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
char getChar(const uint16_t a_offset, const uint8_t a_size) const;
LogViewField* getContent(const LogViewXdrStandardType* a_standardType, uint16_t& a_offset, const uint16_t a_arraySize);
bool isScalar(const LogViewXdrType* a_xdrType) const;
void showMessageBox(const QString& a_errorText, const QString& a_title = QObject::tr("Invalid telegram")) const;
uint16_t getDynArraySize(uint16_t& a_offset) const;
static QString formatToolTipLine(const QString& a_name, const uint32_t a_value)
{
return formatToolTipLine(a_name, QString::number(a_value), a_value);
}
static QString formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value);
static QString formatToolTipLine(const QString& a_name, const std::string& a_text, const uint32_t a_value)
{
return formatToolTipLine(a_name, QString::fromStdString(a_text), a_value);
}
uint8_t getData(const uint16_t a_offset) const;
private:
NGL::INGLLogger &m_logger;
friend class LogViewTabWidget;
};
}
+497
View File
@@ -0,0 +1,497 @@
#include "LogViewTelegramDialog.hpp"
#include "LogViewTelegram.hpp"
#include <QApplication>
#include <QDesktopWidget>
#include <QDir>
#include <QFileDialog>
#include <QGroupBox>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QSettings>
#include <QScrollArea>
#include <QTextEdit>
#include <QVBoxLayout>
#include "LogViewXdrElement.hpp"
#include "LogViewField.hpp"
#include "IntegerCalculator.hpp"
#include "LogViewBooleanEdit.hpp"
#include "LogViewTextEdit.hpp"
#include "LogViewValueEdit.hpp"
#include "LogViewEnumEdit.hpp"
#include "LogViewDateTimeEdit.hpp"
#include "LogViewSpinBox.hpp"
#include "LogViewTableWidget.hpp"
#include "LogViewTabWidget.hpp"
namespace N_LogView
{
LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_readonly)
: QDialog(a_parent)
, m_ReadOnly(a_readonly)
, m_logger(getLogger("LogViewTelegramDialog"))
{
setAttribute(Qt::WA_DeleteOnClose);
}
void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_telegram)
{
delete layout();
hide();
m_Telegram = a_telegram;
a_telegram->dump();
m_fieldTree.reset(a_telegram->getFieldTree());
if (m_fieldTree)
{
QGridLayout *dialogLayout = new QGridLayout;
if (!m_ReadOnly)
{
QLabel *waitTimeLabel = new QLabel(tr("Wartezeit [ms]"), this);
dialogLayout->addWidget(waitTimeLabel, dialogLayout->rowCount(), 0);
m_WaitTimeEdit = new QLineEdit(QString::number(a_telegram->getWaitTime()), this);
dialogLayout->addWidget(m_WaitTimeEdit, dialogLayout->rowCount() - 1, 1);
QLabel *nameLabel = new QLabel(tr("Name"), this);
dialogLayout->addWidget(nameLabel, dialogLayout->rowCount(), 0);
m_NameEdit = new QLineEdit(a_telegram->getName(), this);
dialogLayout->addWidget(m_NameEdit, dialogLayout->rowCount() - 1, 1);
QFrame *f = new QFrame(this);
f->setFrameShape(QFrame::HLine);
f->setFrameShadow(QFrame::Sunken);
dialogLayout->addWidget(f, dialogLayout->rowCount(), 0, 1, 2);
}
showTree(m_fieldTree.data(), dialogLayout);
if (this->findChild<LogViewTableWidget *>() == nullptr)
dialogLayout->setRowStretch(dialogLayout->rowCount(), 1);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
m_contentsWidget = new QWidget;
m_contentsWidget->setLayout(dialogLayout);
m_ScrollArea = new QScrollArea(this);
m_ScrollArea->setWidget(m_contentsWidget);
m_ScrollArea->setWidgetResizable(true);
mainLayout->addWidget(m_ScrollArea);
QHBoxLayout *btnLayout = new QHBoxLayout;
btnLayout->addStretch();
showButtons(btnLayout);
mainLayout->addLayout(btnLayout);
setWindowTitle(m_fieldTree->cleanName() + QStringLiteral(" (%1)").arg(a_telegram->getTelId()));
setModal(true);
show();
makePretty();
}
else
showDataDump(a_telegram, true);
}
void LogViewTelegramDialog::showDataDump(const QSharedPointer<LogViewTelegram> &a_telegram, bool showErrorMessage)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(new QLabel(tr("Telegramm-Dump")));
if (showErrorMessage)
layout->addWidget(new QLabel(tr("Konnte Dialog basierend auf Struktur \'%1\' nicht generieren!").arg(a_telegram->getStructName())));
else
layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName())));
QString theDump = QLatin1String("<code>");
const QByteArray &data = a_telegram->getData();
for (int i = 0; i < data.size(); i++)
{
if (0 == (i % 8))
theDump += QStringLiteral("%1:").arg(i, 4, 16, QLatin1Char('0'));
theDump += QStringLiteral(" %1").arg(static_cast<unsigned char>(data[i]), 2, 16, QLatin1Char('0'));
if (7 == (i % 8))
theDump += QLatin1String("<br>");
}
theDump += QLatin1String("</code>");
QTextEdit *telegramDump = new QTextEdit(theDump);
layout->addWidget(telegramDump);
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen"));
QHBoxLayout *btnLayout = new QHBoxLayout;
btnLayout->addStretch();
btnLayout->addWidget(btnClose);
layout->addLayout(btnLayout);
connect(btnClose, &QPushButton::clicked,
this, &LogViewTelegramDialog::reject);
setLayout(layout);
show();
}
void LogViewTelegramDialog::makePretty()
{
return;
int sbWidth = m_ScrollArea->width() - m_ScrollArea->viewport()->width();
int wDiff = m_contentsWidget->width() - m_ScrollArea->width();
int hDiff = m_contentsWidget->height() - m_ScrollArea->viewport()->height();
const QRect screenSize = QApplication::desktop()->screenGeometry(this);
int newWidth = std::min(width() + wDiff + sbWidth, screenSize.width() * 9 / 10);
int newHeight = std::min(height() + hDiff, screenSize.height() * 9 / 10);
resize(QSize(newWidth, newHeight));
}
void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_box)
{
int i = 0;
while (LogViewField *child = a_fieldTree->child(i++))
{
if (!a_fieldTree->hasContent())
child->setHasContent(false);
switch (child->kind())
{
case LogViewField::e_FieldKindBorder:
{
QGroupBox *groupBox = new QGroupBox(child->cleanName());
QGridLayout *actBox = new QGridLayout(groupBox);
a_box->addWidget(groupBox, a_box->rowCount(), 0, 1, 2);
showTree(child, actBox);
break;
}
case LogViewField::e_FieldKindTab:
showTab(child, a_box);
break;
case LogViewField::e_FieldKindTabChild:
{
QWidget *widget = new QWidget;
widget->setContentsMargins(QMargins());
QGridLayout *actBox = new QGridLayout(widget);
a_box->addWidget(widget, a_box->rowCount(), 0, 1, 2);
showTree(child, actBox);
break;
}
case LogViewField::e_FieldKindEdit:
case LogViewField::e_FieldKindPodArray:
case LogViewField::e_FieldKindPodArrayChild:
showEditField(child, a_box);
break;
}
}
}
void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram)
{
INFO_LOG(m_logger) << "******************************************";
for (const auto ptr : qAsConst(m_EditInfoList))
{
if (!ptr->isValid())
{
INFO_LOG(m_logger) << ptr->field()->name() << " is invalid";
return;
}
}
a_telegram->resetOffset();
a_telegram->clearJsonData();
for (auto ptr : qAsConst(m_EditInfoList))
{
if (!ptr->saveContent(a_telegram))
{
QMessageBox::warning(this, tr("Error while saving telegram"),
tr("Found an invalid value - the telegram may be not saved correctly"));
}
}
}
void LogViewTelegramDialog::saveTelegram()
{
fillTelegram(m_Telegram.data());
N_SST::IntegerCalculator calculator;
N_SST::IntegerCalculator::E_Error error;
m_Telegram->setWaitTime(calculator.calc(m_WaitTimeEdit->text().toStdString(), error));
m_Telegram->setName(m_NameEdit->text());
accept();
}
void LogViewTelegramDialog::sendCurrentTelegram()
{
emit sendTelegram(m_Telegram);
}
void LogViewTelegramDialog::showButtons(QLayout *a_layout)
{
if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol())
{
QPushButton *btnSend = new QPushButton(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("&Send"));
btnSend->setEnabled(true);
connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram);
a_layout->addWidget(btnSend);
}
if (m_ReadOnly)
{
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen"));
connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject);
a_layout->addWidget(btnClose);
}
else
{
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Abbrechen"));
connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject);
a_layout->addWidget(btnClose);
QPushButton *btnOk = new QPushButton(QIcon(QLatin1String(":icons/16x16/dialog-ok-apply.png")), tr("&OK"));
btnOk->setDefault(true);
connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram);
a_layout->addWidget(btnOk);
}
}
void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLayout *a_box)
{
switch (a_logViewField->valueListSize())
{
case 1:
if (m_ReadOnly || !a_logViewField->isDynamicArray() || (LogViewXdrStandardType::e_Character == static_cast<const LogViewXdrStandardType *>(a_logViewField->xdrElement())->getValueKind()))
{
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
LogViewWidget *valueWidget = nullptr;
{
if (LogViewXdrElement::e_KindEnum == a_logViewField->xdrElement()->getKind())
{
valueWidget = new LogViewEnumEdit(a_logViewField, this, m_ReadOnly, 0);
}
else
{
if (a_logViewField->isDateTimeField() || a_logViewField->isMSecsField())
{
valueWidget = new LogViewDateTimeEdit(a_logViewField, this, m_ReadOnly);
}
else
{
switch (static_cast<const LogViewXdrStandardType *>(a_logViewField->xdrElement())->getValueKind())
{
case LogViewXdrStandardType::e_Boolean:
valueWidget = new LogViewBooleanEdit(a_logViewField, this, m_ReadOnly);
break;
case LogViewXdrStandardType::e_Signed:
case LogViewXdrStandardType::e_Unsigned:
case LogViewXdrStandardType::e_Float:
case LogViewXdrStandardType::e_Data:
valueWidget = new LogViewValueEdit(a_logViewField, this, m_ReadOnly);
break;
case LogViewXdrStandardType::e_Character:
valueWidget = new LogViewTextEdit(a_logViewField, this, m_ReadOnly);
break;
}
}
}
if (valueWidget)
m_EditInfoList.push_back(valueWidget);
}
QWidget *w = dynamic_cast<QWidget *>(valueWidget);
if (w)
a_box->addWidget(w, a_box->rowCount() - 1, 1);
else
WARNING_LOG(m_logger) << "Internal error - LogViewWidget is not derived from QWidget... !?";
break;
}
Q_FALLTHROUGH();
case 0:
if (m_ReadOnly)
{
a_box->addWidget(new QLabel(tr("Keine %1").arg(a_logViewField->cleanName())));
break;
}
Q_FALLTHROUGH();
default:
{
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
LogViewSpinBox *spinBox = nullptr;
if (!m_ReadOnly && a_logViewField->isDynamicArray())
{
spinBox = new LogViewSpinBox(a_logViewField, this, a_logViewField->valueListSize());
a_box->addWidget(spinBox, a_box->rowCount() - 1, 1);
}
LogViewTableWidget *tableWidget = new LogViewTableWidget(a_logViewField, this, m_ReadOnly);
m_EditInfoList.push_back(tableWidget);
a_box->addWidget(tableWidget, a_box->rowCount(), 0, 1, 2);
if (spinBox)
{
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
tableWidget, &LogViewTableWidget::changeSize);
}
}
break;
}
}
void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a_box)
{
LogViewSpinBox *spinBox = nullptr;
if (!m_ReadOnly && a_logViewField->isDynamicArray())
{
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
spinBox = new LogViewSpinBox(a_logViewField, this, 0);
a_box->addWidget(spinBox, a_box->rowCount() - 1, 1);
}
LogViewTabWidget *a_tabWidget = new LogViewTabWidget(a_logViewField, this, spinBox);
m_EditInfoList.push_back(dynamic_cast<LogViewWidget *>(a_tabWidget));
a_box->addWidget(a_tabWidget, a_box->rowCount(), 0, 1, 2);
if (spinBox)
{
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
a_tabWidget, &LogViewTabWidget::changeSize);
}
if (a_logViewField->hasContent())
{
for (int i = 0; i < a_logViewField->childCount(); ++i)
a_tabWidget->addTab(a_logViewField, false, i);
}
}
bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonPath)
{
if (m_EditInfoList.empty())
return false;
for (int i = m_EditInfoList.size() - 1; i >= 0; --i)
{
LogViewWidget *lvw = m_EditInfoList.at(i);
const QStringList jsonPathChild = lvw->field()->jsonPath();
if (jsonPathChild.size() < jsonPath.size())
continue;
bool bIsChild = true;
for (int j = 0; j < jsonPath.size(); ++j)
{
if (jsonPath.at(j) != jsonPathChild.at(j))
{
bIsChild = false;
break;
}
}
if (!bIsChild)
continue;
delete m_EditInfoList.at(i);
m_EditInfoList.removeAt(i);
}
m_EditInfoList.resize(m_EditInfoList.size() - 1);
return true;
}
}
+77
View File
@@ -0,0 +1,77 @@
#pragma once
#include <QDialog>
#include "logger.h"
class QGridLayout;
class QTabWidget;
class QFrame;
class QScrollArea;
class QLineEdit;
namespace N_LogView
{
class LogViewWidget;
class LogViewTelegram;
class LogViewField;
class LogViewTelegramDialog : public QDialog
{
Q_OBJECT
public:
explicit LogViewTelegramDialog(QWidget *a_parent = nullptr, const bool a_readonly = true);
void showDialog(const QSharedPointer<LogViewTelegram> &a_telegram);
void showDataDump(const QSharedPointer<LogViewTelegram> &a_telegram, bool showErrorMessage);
void makePretty();
void showTree(LogViewField *a_fieldTree, QGridLayout *a_box);
bool removeItemsFromEditInfoList(const QStringList &jsonPath);
Q_SIGNALS:
void sendTelegram(const QSharedPointer<LogViewTelegram> &telegramToSend);
protected slots:
void saveTelegram();
void sendCurrentTelegram();
protected:
void fillTelegram(LogViewTelegram *a_telegram);
void showButtons(QLayout *a_layout);
void showEditField(LogViewField *a_logViewField, QGridLayout *a_box);
void showTab(LogViewField *a_logViewField, QGridLayout *a_box);
private:
QSharedPointer<LogViewTelegram> m_Telegram;
QVector<LogViewWidget *> m_EditInfoList;
QScopedPointer<LogViewField> m_fieldTree;
QWidget *m_contentsWidget = nullptr;
QScrollArea *m_ScrollArea = nullptr;
QLineEdit *m_NameEdit = nullptr;
QLineEdit *m_WaitTimeEdit = nullptr;
bool m_ReadOnly = false;
NGL::INGLLogger &m_logger;
};
}
+586
View File
@@ -0,0 +1,586 @@
#include "LogViewTelegramEdit.hpp"
#include "LogViewInjectionThread.hpp"
#include "LogViewTelegramDialog.hpp"
#include "LogViewTelegramEditModel.hpp"
#include "LogViewTelegramSelectionDialog.hpp"
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
#include <QAction>
#include <QDir>
#include <QFileDialog>
#include <QHeaderView>
#include <QIcon>
#include <QMenu>
#include <QMessageBox>
#include <QModelIndex>
#include <QSettings>
#include <QTableView>
#include <QTimer>
namespace N_LogView
{
QString TelegramEdit::s_DIR()
{
return QStringLiteral("Dir");
}
QString TelegramEdit::s_EDIT_TELEGRAM_GROUP()
{
return QStringLiteral("EditTelegrams");
}
QString TelegramEdit::s_TELEGRAMLIST_FILE_ID()
{
return QStringLiteral("RDETGL");
}
QString TelegramEdit::s_TELEGRAMLIST_FILES()
{
return tr("Telegrammliste-Dateien (*.tgl);;Alle Dateien (*)");
}
TelegramEdit::TelegramEdit(QWidget *parent)
: QObject(parent)
, m_addTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-add.png")), tr("Add Telegram"), this))
, m_editTeleAction(new QAction(QIcon(QLatin1String(":/image/Edit.png")), tr("Edit Telegram"), this))
, m_copyTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-copy.png")), tr("Copy Telegram"), this))
, m_pasteTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-paste.png")), tr("Paste Telegram"), this))
, m_deleteTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-remove.png")), tr("Delete Telegram"), this))
, m_moveTeleUpAction(new QAction(QIcon(QLatin1String(":icons/16x16/go-up.png")), tr("Move up"), this))
, m_moveTeleDownAction(new QAction(QIcon(QLatin1String(":icons/16x16/go-down.png")), tr("Move down"), this))
, m_teleListLoad(new QAction(QIcon(QLatin1String(":icons/16x16/document-open-data.png")), tr("Load Telegram list"), this))
, m_teleListAppend(new QAction(QIcon(), tr("Telegrammliste anhaengen"), this))
, m_teleListSave(new QAction(QIcon(QLatin1String(":icons/16x16/document-save.png")), tr("Save Telegram list"), this))
, m_tableView(new QTableView(parent))
, m_DoLoop(false)
, m_InjectionThread(nullptr)
, m_EditModel(new TelegramEditModel(this))
, m_logger(getLogger("LogViewTelegramEdit"))
{
m_addTeleAction->setShortcut(tr("Ctrl+A"));
m_editTeleAction->setShortcut(tr("Ctrl+E"));
m_copyTeleAction->setShortcut(tr("Ctrl+C"));
m_pasteTeleAction->setShortcut(tr("Ctrl+V"));
m_deleteTeleAction->setShortcut(Qt::Key_Delete);
m_moveTeleUpAction->setShortcut(tr("Ctrl+U"));
m_moveTeleDownAction->setShortcut(tr("Ctrl+D"));
m_teleListLoad->setShortcut(tr("Ctrl+L"));
m_teleListAppend->setShortcut(tr("Ctrl+K"));
m_teleListSave->setShortcut(tr("Ctrl+S"));
m_addTeleAction->setEnabled(true);
m_copyTeleAction->setEnabled(false);
m_pasteTeleAction->setEnabled(false);
m_deleteTeleAction->setEnabled(false);
m_moveTeleUpAction->setEnabled(false);
m_moveTeleDownAction->setEnabled(false);
m_teleListLoad->setEnabled(true);
m_teleListAppend->setEnabled(true);
m_teleListSave->setEnabled(false);
connect(m_addTeleAction, &QAction::triggered, this, &TelegramEdit::addTelegram);
connect(m_editTeleAction, &QAction::triggered, this, &TelegramEdit::editTelegram);
connect(m_copyTeleAction, &QAction::triggered, this, &TelegramEdit::copy);
connect(m_pasteTeleAction, &QAction::triggered, this, &TelegramEdit::paste);
connect(m_deleteTeleAction, &QAction::triggered, this, &TelegramEdit::deleteTelegram);
connect(m_moveTeleUpAction, &QAction::triggered, this, &TelegramEdit::moveUp);
connect(m_moveTeleDownAction, &QAction::triggered, this, &TelegramEdit::moveDown);
connect(m_teleListLoad, &QAction::triggered, this, &TelegramEdit::loadTelegramListReplace);
connect(m_teleListAppend, &QAction::triggered, this, &TelegramEdit::loadTelegramListAppend);
connect(m_teleListSave, &QAction::triggered, this, &TelegramEdit::saveTelegramList);
m_tableView->setModel(m_EditModel);
m_tableView->verticalHeader()->hide();
m_tableView->setContextMenuPolicy(Qt::CustomContextMenu);
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &TelegramEdit::onSelectionChanged);
connect(m_tableView, &QTableView::doubleClicked,
this, &TelegramEdit::editTelegram);
connect(m_tableView, &QTableView::customContextMenuRequested,
this, &TelegramEdit::tableViewCustomContextMenu);
m_tableView->addAction(m_addTeleAction);
m_tableView->addAction(m_editTeleAction);
m_tableView->addAction(m_copyTeleAction);
m_tableView->addAction(m_pasteTeleAction);
m_tableView->addAction(m_deleteTeleAction);
m_tableView->addAction(m_moveTeleUpAction);
m_tableView->addAction(m_moveTeleDownAction);
}
void TelegramEdit::setInjectionThread(LogViewInjectionThread *a_injectionThread)
{
m_InjectionThread = a_injectionThread;
}
void TelegramEdit::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
{
m_EditModel->appendTelegram(telegram);
m_teleListSave->setEnabled(true);
}
void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
{
QMenu menu;
menu.addAction(m_addTeleAction);
menu.addAction(m_editTeleAction);
menu.addAction(m_copyTeleAction);
menu.addAction(m_pasteTeleAction);
menu.addAction(m_deleteTeleAction);
menu.addSeparator();
menu.addAction(m_moveTeleUpAction);
menu.addAction(m_moveTeleDownAction);
menu.addSeparator();
const bool itemSelected = m_tableView->currentIndex().isValid();
bool isCentral = false;
QSharedPointer<LogViewTelegram> tele = m_EditModel->telegram(m_tableView->currentIndex().row());
if (tele)
isCentral = (tele->getProtocol() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral);
if (isInjectionPossible())
{
QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm"));
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram);
action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm"));
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram);
menu.addSeparator();
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm"));
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram);
if (m_DoLoop)
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-stop.png")), tr("Stop Loopen"));
else
{
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-start.png")), tr("Loop Telegramme"));
action->setEnabled(itemSelected);
}
connect(action, &QAction::triggered, this, &TelegramEdit::loopTelegrams);
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-play-normal.png")), tr("Sende Sequenz"));
action->setEnabled(itemSelected);
connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams);
menu.addSeparator();
}
menu.addAction(m_teleListLoad);
menu.addAction(m_teleListAppend);
menu.addAction(m_teleListSave);
menu.exec(m_tableView->viewport()->mapToGlobal(pos));
}
void TelegramEdit::addTelegram()
{
LogViewTelegramSelectionDialog telegramSelectionDialog(m_tableView);
if (QDialog::Accepted == telegramSelectionDialog.exec())
{
QSharedPointer<LogViewTelegram> newTelegram = QSharedPointer<LogViewTelegram>(new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral,
telegramSelectionDialog.getSelectedTelegramId()));
m_curEditTelegramRow = m_EditModel->appendTelegram(newTelegram);
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
connect(editTelegramDialog, &LogViewTelegramDialog::finished,
this, &TelegramEdit::editTelegramDialogFinished);
connect(editTelegramDialog, &LogViewTelegramDialog::sendTelegram,
this, &TelegramEdit::sendTelegram);
editTelegramDialog->showDialog(newTelegram);
m_teleListSave->setEnabled(true);
}
}
QSharedPointer<LogViewTelegram> TelegramEdit::currentSelectedTelegram() const
{
return m_EditModel->telegram(currentSelectedIndex().row());
}
QModelIndex TelegramEdit::currentSelectedIndex() const
{
return m_tableView->currentIndex();
}
void TelegramEdit::editTelegramDialogFinished()
{
m_EditModel->emitDataChanged(m_curEditTelegramRow);
}
void TelegramEdit::editTelegram()
{
m_curEditTelegramRow = currentSelectedIndex().row();
if (m_curEditTelegramRow < 0)
return;
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
connect(editTelegramDialog, &LogViewTelegramDialog::finished, this, &TelegramEdit::editTelegramDialogFinished);
editTelegramDialog->showDialog(currentSelectedTelegram());
}
void TelegramEdit::showTelegram()
{
LogViewTelegramDialog *showTelegramDialog = new LogViewTelegramDialog(m_tableView, true);
showTelegramDialog->showDialog(currentSelectedTelegram());
}
void TelegramEdit::deleteTelegram()
{
const QModelIndexList indexList = m_tableView->selectionModel()->selectedIndexes();
QSet<int> rows;
rows.reserve(indexList.size());
for (const QModelIndex &index : indexList)
rows += index.row();
m_EditModel->removeTelegrams(rows);
m_teleListSave->setEnabled(m_EditModel->rowCount() > 0);
}
void TelegramEdit::injectCentralTelegram()
{
injectTelegram(true);
}
void TelegramEdit::injectTetraTelegram()
{
injectTelegram(false);
}
void TelegramEdit::injectTelegram(bool a_bAsCentralTelegram)
{
injectTelegram(currentSelectedTelegram(), a_bAsCentralTelegram);
}
void TelegramEdit::injectTelegram(const QSharedPointer<LogViewTelegram> &a_telegram, bool a_bAsCentralTelegram)
{
if (!isInjectionPossible())
{
WARNING_LOG(m_logger) << "Try to inject a telegramm but the injection thread is not running";
return;
}
if (a_telegram.isNull())
{
WARNING_LOG(m_logger) << "Try to inject a telegramm but no telegramm selected";
return;
}
a_telegram->actualizeGpsTime();
m_InjectionThread->sendTelegram(a_telegram.data(), a_bAsCentralTelegram);
}
void TelegramEdit::sendCurrentTelegram()
{
sendTelegram(currentSelectedTelegram());
}
void TelegramEdit::sendTelegram(const QSharedPointer<LogViewTelegram> &a_telegram)
{
injectTelegram(a_telegram, true);
}
void TelegramEdit::loopTelegrams()
{
if (m_DoLoop)
{
m_DoLoop = false;
m_deleteTeleAction->setEnabled(m_tableView->currentIndex().isValid());
}
else
{
m_DoLoop = true;
m_deleteTeleAction->setEnabled(false);
m_currentRowToSend = currentSelectedIndex().row();
if (m_currentRowToSend < 0)
return;
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::loopNextTelegram);
}
}
void TelegramEdit::loopNextTelegram()
{
if (!m_DoLoop)
return;
++m_currentRowToSend;
if (m_currentRowToSend >= m_tableView->model()->rowCount())
m_currentRowToSend = 0;
QSharedPointer<LogViewTelegram> tele = telegramAtRow(m_currentRowToSend);
if (!tele)
return;
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::loopNextTelegram);
}
void TelegramEdit::sequenceTelegrams()
{
m_currentRowToSend = currentSelectedIndex().row();
if (m_currentRowToSend < 0)
return;
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::sequenceNextTelegram);
}
void TelegramEdit::sequenceNextTelegram()
{
++m_currentRowToSend;
if (m_currentRowToSend >= m_tableView->model()->rowCount())
return;
QSharedPointer<LogViewTelegram> tele = telegramAtRow(m_currentRowToSend);
if (!tele)
return;
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::sequenceNextTelegram);
}
QSharedPointer<LogViewTelegram> TelegramEdit::telegramAtRow(int row)
{
return m_EditModel->telegram(row);
}
void TelegramEdit::copy()
{
m_copyTelegram = currentSelectedTelegram();
m_pasteTeleAction->setEnabled(m_copyTelegram != nullptr);
if (!m_copyTelegram)
return;
m_copyTelegram = QSharedPointer<LogViewTelegram>(new LogViewTelegram(*m_copyTelegram.data()));
}
void TelegramEdit::paste()
{
if (!m_copyTelegram)
return;
int row = currentSelectedIndex().row() + 1;
m_EditModel->pasteRows(row, m_copyTelegram);
}
void TelegramEdit::moveUp()
{
const QModelIndex idx = currentSelectedIndex();
if (m_EditModel->moveUp(idx.row()))
{
m_tableView->clearSelection();
m_tableView->setCurrentIndex(m_EditModel->index(idx.row() - 1, idx.column(), idx.parent()));
m_moveTeleUpAction->setEnabled(idx.row() > 1);
m_moveTeleDownAction->setEnabled(true);
}
}
void TelegramEdit::moveDown()
{
const QModelIndex idx = currentSelectedIndex();
if (m_EditModel->moveDown(idx.row()))
{
m_tableView->clearSelection();
m_tableView->setCurrentIndex(m_EditModel->index(idx.row() + 1, idx.column(), idx.parent()));
m_moveTeleUpAction->setEnabled(true);
m_moveTeleDownAction->setEnabled(idx.row() < m_EditModel->rowCount() - 2);
}
}
void TelegramEdit::saveTelegramList()
{
QSettings settings;
QString newFilename = QFileDialog::getSaveFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
settings.value(s_DIR()).toString(),
s_TELEGRAMLIST_FILES());
if (!newFilename.isEmpty())
{
if (!newFilename.contains(QLatin1Char('.')))
newFilename += QLatin1String(".tgl");
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
QFile telegramFile(newFilename);
telegramFile.open(QIODevice::WriteOnly);
QDataStream stream(&telegramFile);
uint32_t version = 1;
stream << s_TELEGRAMLIST_FILE_ID() << version;
int rows = m_tableView->model()->rowCount();
stream << rows;
for (int i = 0; i < rows; i++)
{
QSharedPointer<LogViewTelegram> telegram = telegramAtRow(i);
if (!telegram)
continue;
const QByteArray &data = telegram->getData();
const QString name = telegram->getName();
const unsigned int waitTime = telegram->getWaitTime();
stream << waitTime
<< name
<< telegram->getGpsTimeField()
<< data.size();
stream.writeRawData(data.data(), data.size());
}
telegramFile.close();
}
}
void TelegramEdit::loadTelegramListAppend()
{
loadTelegramList(true);
}
void TelegramEdit::loadTelegramListReplace()
{
loadTelegramList(false);
}
void TelegramEdit::loadTelegramList(bool checkAppend)
{
QSettings settings;
QString newFilename = QFileDialog::getOpenFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
settings.value(s_DIR()).toString(),
s_TELEGRAMLIST_FILES());
if (!newFilename.isEmpty())
{
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
{
if (!checkAppend)
m_EditModel->clearTelegrams();
}
QFile telegramFile(newFilename);
telegramFile.open(QIODevice::ReadOnly);
QDataStream stream(&telegramFile);
QString id;
stream >> id;
if (id != s_TELEGRAMLIST_FILE_ID())
{
QMessageBox::critical(m_tableView, tr("Error"), tr("<b>%1</b> does not contain telegram data").arg(newFilename));
return;
}
uint32_t version = 0;
stream >> version;
if (version != 1)
{
QMessageBox::critical(m_tableView, tr("Error"), tr("Wrong telegram list file version"));
return;
}
int rows = 0;
QVector<uint16_t> gpsFieldOffset;
stream >> rows;
for (int i = 0; i < rows; i++)
{
uint32_t waitTime = 0;
QString name;
int telegramSize = 0;
stream >> waitTime >> name >> gpsFieldOffset >> telegramSize;
if (telegramSize > 0)
{
DEBUG_LOG(m_logger) << "telegramSize=" << telegramSize;
QByteArray buf(telegramSize, Qt::Uninitialized);
stream.readRawData(buf.data(), telegramSize);
NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Debug, buf);
LogViewTelegram *telegram = new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral,
0,
buf);
telegram->setWaitTime(waitTime);
telegram->setName(name);
telegram->setGpsTimeField(gpsFieldOffset);
m_EditModel->appendTelegram(QSharedPointer<LogViewTelegram>(telegram));
}
}
telegramFile.close();
m_teleListSave->setEnabled(m_EditModel->rowCount() > 0);
}
}
bool TelegramEdit::isInjectionPossible() const
{
return m_InjectionThread ? m_InjectionThread->isSendingPossible() : false;
}
void TelegramEdit::onSelectionChanged()
{
const QModelIndex idx = currentSelectedIndex();
m_editTeleAction->setEnabled(idx.isValid());
m_copyTeleAction->setEnabled(idx.isValid());
m_deleteTeleAction->setEnabled(idx.isValid());
m_moveTeleUpAction->setEnabled(idx.row() > 0);
m_moveTeleDownAction->setEnabled(idx.isValid() && idx.row() < m_EditModel->rowCount() - 1);
}
}
+121
View File
@@ -0,0 +1,121 @@
#pragma once
#include "LogViewTelegram.hpp"
#include <QModelIndex>
class QAction;
class QTableView;
namespace N_LogView
{
class LogViewInjectionThread;
class TelegramEditModel;
class TelegramEdit :public QObject
{
Q_OBJECT
public:
explicit TelegramEdit(QWidget *parent = nullptr);
QTableView *tableView() { return m_tableView; }
void appendTelegram(const QSharedPointer<LogViewTelegram> &telegram);
void setInjectionThread(LogViewInjectionThread* a_injectionThread);
bool isInjectionPossible() const;
protected:
QSharedPointer<LogViewTelegram> m_copyTelegram;
QSharedPointer<LogViewTelegram> currentSelectedTelegram() const;
QModelIndex currentSelectedIndex() const;
QSharedPointer<LogViewTelegram> telegramAtRow(int row);
void loadTelegramList(bool checkAppend);
protected:
QAction *m_addTeleAction;
QAction *m_editTeleAction;
QAction *m_copyTeleAction;
QAction *m_pasteTeleAction;
QAction *m_deleteTeleAction;
QAction *m_moveTeleUpAction;
QAction *m_moveTeleDownAction;
QAction *m_teleListLoad;
QAction *m_teleListAppend;
QAction *m_teleListSave;
QTableView *m_tableView;
bool m_DoLoop;
LogViewInjectionThread *m_InjectionThread;
int m_currentRowToSend;
int m_curEditTelegramRow;
TelegramEditModel *m_EditModel;
NGL::INGLLogger &m_logger;
static QString s_DIR();
static QString s_EDIT_TELEGRAM_GROUP();
static QString s_TELEGRAMLIST_FILE_ID();
static QString s_TELEGRAMLIST_FILES();
protected Q_SLOTS:
void addTelegram();
void injectTelegram(bool a_bAsCentralTelegram);
void injectTelegram(const QSharedPointer<LogViewTelegram> &a_telegram, bool a_bAsCentralTelegram);
void sendTelegram(const QSharedPointer<LogViewTelegram> &a_telegram);
void sendCurrentTelegram();
void tableViewCustomContextMenu(const QPoint &pos);
void editTelegram();
void showTelegram();
void deleteTelegram();
void injectCentralTelegram();
void injectTetraTelegram();
void loopTelegrams();
void loopNextTelegram();
void sequenceTelegrams();
void sequenceNextTelegram();
void copy();
void paste();
void moveUp();
void moveDown();
void saveTelegramList();
void loadTelegramListAppend();
void loadTelegramListReplace();
void editTelegramDialogFinished();
void onSelectionChanged();
};
}
@@ -0,0 +1,163 @@
#include "LogViewTelegramEditModel.hpp"
#include <algorithm>
namespace N_LogView
{
int TelegramEditModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_telegrams.size();
}
int TelegramEditModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 3;
}
QVariant TelegramEditModel::data(const QModelIndex &index, int role) const
{
if (index.isValid() && index.row() < m_telegrams.size())
{
if (role == Qt::DisplayRole)
{
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
switch (index.column())
{
case 0:
return telegram->getName();
case 1:
return telegram->getParticipantId();
case 2:
return telegram->getWaitTime();
}
}
else if (role == Qt::ToolTipRole)
{
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
if (telegram->isJsonTelegram())
return telegram->getData(QJsonDocument::JsonFormat::Indented);
}
}
return QVariant();
}
QVariant TelegramEditModel::headerData(int section,
Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
switch (section)
{
case 0:
return tr("Description");
case 1:
return tr("Equip. No.");
case 2:
return tr("Wait Time");
default:
break;
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
void TelegramEditModel::clearTelegrams()
{
beginResetModel();
m_telegrams.clear();
endResetModel();
}
void TelegramEditModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams)
{
if (telegrams.isEmpty())
return;
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size() + telegrams.size() - 1);
m_telegrams += telegrams;
endInsertRows();
}
int TelegramEditModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
{
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size());
m_telegrams.push_back(telegram);
telegram->rebuildJsonString();
endInsertRows();
return m_telegrams.size() - 1;
}
QSharedPointer<LogViewTelegram> TelegramEditModel::telegram(int row) const
{
if (row >= 0 && row < m_telegrams.size())
return m_telegrams.at(row);
return QSharedPointer<LogViewTelegram>();
}
bool TelegramEditModel::moveUp(int row)
{
if (row <= 0 || row >= m_telegrams.size())
return false;
beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1);
std::swap(m_telegrams[row], m_telegrams[row - 1]);
endMoveRows();
return true;
}
bool TelegramEditModel::moveDown(int row)
{
if (row >= (m_telegrams.size() - 1))
return false;
beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 1);
std::swap(m_telegrams[row], m_telegrams[row + 1]);
endMoveRows();
return true;
}
void TelegramEditModel::emitDataChanged(int row)
{
QModelIndex top = createIndex(row, 0);
QModelIndex bottom = createIndex(row, columnCount() - 1);
emit dataChanged(top, bottom, {Qt::DisplayRole, Qt::ToolTipRole});
}
void TelegramEditModel::removeTelegrams(const QSet<int> &rows)
{
QList<int> rowList = rows.values();
std::sort(rowList.begin(), rowList.end());
for (int i = rowList.size() - 1 ; i >= 0; --i)
{
int row = rowList.at(i);
beginRemoveRows(QModelIndex(), row, row);
m_telegrams.remove(row);
endRemoveRows();
}
}
void TelegramEditModel::pasteRows(int row, const QSharedPointer<LogViewTelegram> &tele)
{
if (row < 0 || row > m_telegrams.size())
return;
beginInsertRows(QModelIndex(), row, row);
m_telegrams.insert(row, QSharedPointer<LogViewTelegram>(new LogViewTelegram(*tele.data())));
endInsertRows();
}
}
@@ -0,0 +1,44 @@
#pragma once
#include <QtCore/QAbstractTableModel>
#include <QtCore/QSharedPointer>
#include <QtCore/QSet>
#include "LogViewTelegram.hpp"
namespace N_LogView
{
class TelegramEditModel final : public QAbstractTableModel
{
Q_OBJECT
public:
using QAbstractTableModel::QAbstractTableModel;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
void clearTelegrams();
void appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams);
int appendTelegram(const QSharedPointer<LogViewTelegram> &telegram);
QSharedPointer<LogViewTelegram> telegram(int row) const;
bool moveUp(int row);
bool moveDown(int row);
void emitDataChanged(int row);
void removeTelegrams(const QSet<int> &rows);
void pasteRows(int row, const QSharedPointer<LogViewTelegram> &tele);
protected:
QVector<QSharedPointer<LogViewTelegram> > m_telegrams;
};
}
@@ -0,0 +1,62 @@
#include "LogViewTelegramSelectionDialog.hpp"
#include <QLabel>
#include <QListWidget>
#include <QVBoxLayout>
#include "LogViewXdrType.hpp"
#include "LogViewXdrParser.hpp"
#include "LogViewTelegram.hpp"
#include "LogViewTetraTelegramsParser.hpp"
namespace N_LogView
{
static int s_currentRow = 0;
LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent)
: QDialog(a_parent)
{
setMinimumSize(QSize(600, 500));
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(new QLabel(tr("Select a telegram:")));
m_TelegramList = new QListWidget(this);
const auto telegramMap = LogViewTelegram::jsonParser()->telegramsToCreate();
for (auto it = telegramMap.cbegin(); it != telegramMap.cend(); ++it)
{
if (it.key() == 0)
continue;
auto lwi = new QListWidgetItem(it.value() + QStringLiteral(" (%1)").arg(it.key()));
lwi->setData(Qt::UserRole, it.key());
m_TelegramList->addItem(lwi);
}
m_TelegramList->sortItems();
m_TelegramList->setCurrentRow(s_currentRow);
connect(m_TelegramList, &QListWidget::itemActivated,
this, &LogViewTelegramSelectionDialog::selectTelegram);
layout->addWidget(m_TelegramList);
setLayout(layout);
}
void LogViewTelegramSelectionDialog::selectTelegram(QListWidgetItem* a_telegramItem)
{
s_currentRow = m_TelegramList->currentRow();
m_SelectedTelegramId = a_telegramItem->data(Qt::UserRole).toInt();
accept();
}
}
@@ -0,0 +1,46 @@
#pragma once
#include <QDialog>
class QListWidget;
class QListWidgetItem;
namespace N_LogView
{
class LogViewTelegramSelectionDialog : public QDialog
{
Q_OBJECT
public:
explicit LogViewTelegramSelectionDialog(QWidget* a_parent);
int getSelectedTelegramId() const { return m_SelectedTelegramId; }
protected slots:
void selectTelegram(QListWidgetItem* a_telegramItem);
protected:
QListWidget *m_TelegramList;
int m_SelectedTelegramId;
};
}
@@ -0,0 +1,516 @@
#include "LogViewTetraTelegramsParser.hpp"
#include <QFile>
#include <QVector>
namespace N_LogView
{
LogViewTetraTelegramsParser::LogViewTetraTelegramsParser()
: m_logger(getLogger("LogViewTetraTelegramsParser"))
{
insertPod(QStringLiteral("bool"), 1, true, true, true);
insertPod(QStringLiteral("int"), 4, true, true);
insertPod(QStringLiteral("int32_t"), 4, true, true);
insertPod(QStringLiteral("qint64"), 8, true, true);
insertPod(QStringLiteral("float"), 4, true, false);
insertPod(QStringLiteral("double"), 8, true, false);
}
EnumInformation LogViewTetraTelegramsParser::enumFromType(const QString &type) const
{
for (const auto &ei : m_enums)
{
const QString fqType = ei.ns.isEmpty() ? ei.type : (ei.ns + QStringLiteral("::") + ei.type);
if (fqType == type)
return ei;
}
return EnumInformation();
}
StructInformation LogViewTetraTelegramsParser::structFromType(const QString &type) const
{
return m_structs.value(type);
}
PodInformation LogViewTetraTelegramsParser::podFromType(const QString &type) const
{
return m_pods.value(type);
}
bool LogViewTetraTelegramsParser::isEnum(const QString &type) const
{
for (const auto &ei : m_enums)
if (ei.type == type)
return true;
return false;
}
bool LogViewTetraTelegramsParser::isStruct(const QString &type) const
{
return m_structs.contains(type);
}
bool LogViewTetraTelegramsParser::isPod(const QString &type) const
{
return m_pods.contains(type);
}
static void fillBasemembers(StructInformation &si, const QHash<QString, StructInformation> &structs)
{
if (si.baseStruct.isEmpty())
return;
StructInformation base = structs.value(si.baseStruct);
fillBasemembers(base, structs);
si.member = (base.member + si.member);
}
bool LogViewTetraTelegramsParser::parse(const QString &filename)
{
m_telegramIdEnum = EnumInformation();
m_enums.clear();
m_structs.clear();
m_visibleTelegrams.clear();
QFile f(filename);
if (!f.open(QIODevice::ReadOnly))
{
WARNING_LOG(m_logger) << "Can not open file " << filename << " for reading: " << f.errorString();
return false;
}
const QString content = QString::fromUtf8(f.readAll());
f.close();
const QVector<QStringRef> lines = content.splitRef(QLatin1Char('\n'));
QVector<QStringRef> linesTrimmed;
linesTrimmed.reserve(lines.size());
for (const QStringRef &line : lines)
linesTrimmed += line.trimmed();
int i = 0;
while (i < linesTrimmed.size())
{
const QStringRef &line = linesTrimmed.at(i);
if (line.startsWith(QLatin1String("struct")))
{
i = parseStruct(linesTrimmed, i);
if (i < 0)
return false;
}
else if (line.startsWith(QLatin1String("enum")))
{
i = parseEnum(linesTrimmed, i, QString());
if (i < 0)
return false;
}
else if (line.startsWith(QLatin1String("template <> struct Constraints")))
{
i = parseConstraint(linesTrimmed, i);
if (i < 0)
return false;
}
++i;
}
const auto completeStructs = m_structs;
for (StructInformation &si : m_structs)
fillBasemembers(si, completeStructs);
return true;
}
void LogViewTetraTelegramsParser::insertPod(const QString &type, int byteLen, bool isSigned, bool isIntegral, bool isBoolean)
{
PodInformation pod;
pod.type = type;
pod.byteLen = byteLen;
pod.isBoolean = isBoolean;
pod.isIntegral = isIntegral;
pod.isSigned = isSigned;
m_pods[type] = pod;
}
int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, int iStartPos)
{
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos));
if (tokens.size() < 2)
return -1;
const QStringRef &structType = tokens.at(1);
if (structType.endsWith(QLatin1Char(';')))
return iStartPos;
StructInformation si;
si.type = structType.toString();
if (tokens.size() > 2)
{
if (tokens.at(2) != QLatin1String(":"))
{
WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1;
return -1;
}
for (int i = 3; i < tokens.size(); ++i)
{
if (!si.baseStruct.isEmpty())
{
WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1;
return -1;
}
QStringRef base = tokens.at(i);
if (base == QLatin1String("public") ||
base == QLatin1String("protected") ||
base == QLatin1String("private"))
continue;
if (base.endsWith(QLatin1Char(',')))
base.chop(1);
if (base.endsWith(QLatin1Char('>')))
{
si.isVisible = true;
continue;
}
si.baseStruct = tokens.at(i).toString();
}
}
int i = iStartPos + 1;
while (i < lines.size())
{
const QVector<QStringRef> tokens = tokenize(lines.at(i));
if (!validStructTokens(tokens))
{
++i;
continue;
}
if (tokens.at(0) == QLatin1String("};"))
break;
if (tokens.at(0) == QLatin1String("enum"))
{
i = parseEnum(lines, i, si.type, &si);
if (i < 0)
return -1;
++i;
continue;
}
MemberInformation mi;
if (tokens.size() > 2)
{
const int parserCommentPos = tokens.at(2) == QLatin1String("=") ? 4 : 2;
if (tokens.size() > parserCommentPos)
{
const QStringRef &comment = tokens.at(parserCommentPos);
DEBUG_LOG(m_logger) << "comment: " << comment.toString();
if (comment.startsWith(QLatin1String("//@array: ")))
{
const QStringRef hint = comment.mid(QLatin1String("//@array: ").size());
QString structStr = QLatin1String("struct ") + si.type + QLatin1String("::") + tokens.at(0).toString() + QLatin1Char('\n') + hint.toString();
structStr.replace(QLatin1Char(';'), QLatin1String(";\n"));
DEBUG_LOG(m_logger) << "structStr: " << structStr;
parseStruct(structStr.splitRef(QLatin1Char('\n')), 0);
mi.type = si.type + QLatin1String("::") + tokens.at(0).toString();
mi.isArray = true;
}
if (comment == QLatin1String("//@invisible"))
mi.isVisible = false;
}
}
QStringRef name = tokens.at(1);
if (name.endsWith(QLatin1Char(';')))
name.chop(1);
if (mi.type.isEmpty())
mi.type += tokens.at(0).toString();
categorizeMember(mi);
mi.name = name.toString();
if (mi.isEnum && !mi.type.contains(QLatin1String("::")))
{
for (const auto &ei : qAsConst(m_enums))
{
if (ei.type == mi.type)
{
if (!ei.ns.isEmpty())
mi.type = ei.ns + QLatin1String("::") + mi.type;
break;
}
}
}
si.member.push_back(std::move(mi));
++i;
}
if (m_logger.isDebugEnabled())
{
if (si.baseStruct.isEmpty())
DEBUG_LOG(m_logger) << "Found Struct: " << si.type;
else
DEBUG_LOG(m_logger) << "Found Struct: " << si.type << ", base: " << si.baseStruct;
for (int j = 0; j < si.member.size(); ++j)
{
const MemberInformation &mi = si.member.at(j);
DEBUG_LOG(m_logger) << "Member[" << j << "]: " << mi.type << " - " << mi.name;
}
}
m_structs[si.type] = si;
return i;
}
int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int iStartPos, const QString &ns, StructInformation *si)
{
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos));
if (tokens.size() < 2)
return -1;
QStringRef enumName = tokens.at(1);
if (enumName == QLatin1String("class"))
{
if (tokens.size() < 3)
return -1;
enumName = tokens.at(2);
}
if (enumName.endsWith(QLatin1Char(';')))
return iStartPos;
EnumInformation ei;
ei.type = enumName.toString();
ei.ns = ns;
int i = iStartPos + 1;
while (i < lines.size())
{
const QVector<QStringRef> tokens = tokenize(lines.at(i).split(QStringLiteral("//")).first());
if (tokens.isEmpty() ||
(tokens.at(0) == QLatin1String("{")))
{
++i;
continue;
}
if (tokens.at(0) == QLatin1String("};"))
break;
if ((tokens.size() != 1 && tokens.size() != 3) ||
(tokens.size() == 3 && tokens.at(1) != QLatin1String("=")))
{
if (tokens.size() == 4 && tokens.at(0) == QLatin1String("}") && tokens.at(3).endsWith(QLatin1Char(';')) && si)
{
MemberInformation mi;
if (ns.isEmpty())
mi.type = ei.type;
else
mi.type = ns + QStringLiteral("::") + ei.type;
mi.isEnum = true;
mi.name = tokens.at(1).toString();
si->member.push_back(std::move(mi));
break;
}
WARNING_LOG(m_logger) << "Could not parse enum: '" << lines.at(i).toString() << "', line: " << i + 1;
return -1;
}
EnumValue ev;
ev.key = tokens.at(0).toString();
if (tokens.size() == 3)
{
QStringRef value = tokens.at(2);
if (value.endsWith(QLatin1Char(',')))
value.chop(1);
ev.value = value.toInt();
}
else
{
int val = ei.values.isEmpty() ? 0 : (ei.values.last().value + 1);
ev.value = val;
}
ei.values.push_back(std::move(ev));
++i;
}
DEBUG_LOG(m_logger) << "Found Enum: " << ei.type;
for (const EnumValue &ev : qAsConst(ei.values))
DEBUG_LOG(m_logger) << "Member[" << i << "]: " << ev.key << " = " << ev.value;
if (ei.type == QLatin1String("TelegramId"))
m_telegramIdEnum = ei;
m_enums.push_back(std::move(ei));
return i;
}
int LogViewTetraTelegramsParser::parseConstraint(const QVector<QStringRef> &lines, int iStartPos)
{
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos));
if (tokens.size() != 4)
{
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'";
return -1;
}
const QStringRef &cs = tokens.at(3);
if (!cs.startsWith(QLatin1String("Constraints<")) || !cs.endsWith(QLatin1Char('>')))
{
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'";
return -1;
}
QStringRef structName = cs.mid(QLatin1String("Constraints<").size());
structName.chop(1);
DEBUG_LOG(m_logger) << "Constraint: " << structName.toString();
int i = iStartPos + 1;
while (i < lines.size())
{
const QVector<QStringRef> tokens = tokenize(lines.at(i));
if (tokens.isEmpty() ||
(tokens.at(0) == QLatin1String("{")))
{
++i;
continue;
}
if (tokens.at(0) == QLatin1String("};"))
break;
if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId"))
{
++i;
continue;
}
const QVector<QStringRef> parts = tokens.at(6).split(QLatin1String("::"));
if (parts.size() != 2)
{
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(i).toString() << "'";
return -1;
}
QStringRef enumKey = parts.at(1);
if (enumKey.endsWith(QLatin1Char(';')))
enumKey.chop(1);
bool bFound = false;
for (const auto &v : qAsConst(m_telegramIdEnum.values))
{
if (v.key == enumKey)
{
m_visibleTelegrams.insert(v.value, structName.toString());
bFound = true;
break;
}
}
if (!bFound)
{
WARNING_LOG(m_logger) << "Could not find enum value '" << enumKey.toString() << "' in enum TelegramId";
return -1;
}
++i;
}
return i;
}
QString LogViewTetraTelegramsParser::getInnerType(const QString &type)
{
int idxLt = type.lastIndexOf(QLatin1Char('>'));
if (idxLt < 0)
return QString();
int idxGt = type.indexOf(QLatin1Char('<'));
if (idxGt < 0)
return QString();
return type.mid(idxGt + 1, idxLt - idxGt - 1);
}
void LogViewTetraTelegramsParser::categorizeMember(MemberInformation &mi) const
{
mi.isPod = isPod(mi.type);
mi.isEnum = mi.isPod ? false : isEnum(mi.type);
if (mi.type.startsWith(QLatin1String("std::vector<")))
mi.isArray = true;
mi.isStruct = mi.isArray ? false : isStruct(mi.type);
mi.isString = (mi.type == QLatin1String("std::string") || mi.type == QLatin1String("QString"));
mi.isBinary = (mi.type == QLatin1String("std::vector<unsigned char>") || mi.type == QLatin1String("QByteArray"));
}
static inline void bracketCount(const QStringRef &str, int &cntLt, int &cntGt)
{
cntLt = 0;
cntGt = 0;
for (int i = 0; i < str.size(); ++i)
{
if (str.at(i) == QLatin1Char('<'))
cntLt++;
else if (str.at(i) == QLatin1Char('>'))
cntGt++;
}
}
QVector<QStringRef> LogViewTetraTelegramsParser::tokenize(const QStringRef &line) const
{
QVector<QStringRef> ret = line.split(QLatin1Char(' '), QString::SkipEmptyParts);
int i = 0;
while (i < ret.size())
{
const QStringRef &token = ret.at(i);
if (token.startsWith(QLatin1String("//")))
{
if (i == ret.size() - 1)
break;
const QStringRef &lastToken = ret.last();
const QStringRef newToken = QStringRef(token.string(), token.position(), lastToken.position() - token.position() + lastToken.size());
DEBUG_LOG(m_logger) << "New Token: " << newToken.toString();
ret.resize(i + 1);
ret[i] = newToken;
break;
}
if (i == ret.size() - 1)
break;
int cntLt;
int cntGt;
bracketCount(token, cntLt, cntGt);
if (cntLt == cntGt)
{
++i;
continue;
}
const QStringRef &nextToken = ret.at(i + 1);
const QStringRef newToken = QStringRef(token.string(), token.position(), nextToken.position() - token.position() + nextToken.size());
DEBUG_LOG(m_logger) << "New Token: " << newToken.toString();
ret.removeAt(i + 1);
ret[i] = newToken;
}
return ret;
}
bool LogViewTetraTelegramsParser::validStructTokens(const QVector<QStringRef> &tokens)
{
if (tokens.isEmpty() ||
(tokens.at(0) == QLatin1String("{")) ||
(tokens.at(0) == QLatin1String("{}")) ||
(tokens.at(0) == QLatin1String("}")) ||
(tokens.at(0) == QLatin1String(":")) ||
(tokens.at(0) == QLatin1String(",")) ||
(tokens.at(0) == QLatin1String("virtual")))
return false;
if (tokens.at(0) == QLatin1String("};") || tokens.at(0) == QLatin1String("enum"))
return true;
const int len = tokens.last().startsWith(QLatin1String("//")) ? tokens.size() - 1 : tokens.size();
if (len == 2)
return true;
if (len < 4)
return false;
if (len >= 4 && tokens.at(2) == QLatin1String("="))
return true;
return false;
}
}
@@ -0,0 +1,89 @@
#pragma once
#include <QHash>
#include <QString>
#include <QVector>
#include "logger.h"
namespace N_LogView
{
struct MemberInformation
{
QString name;
QString type;
bool isArray = false;
bool isBinary = false;
bool isEnum = false;
bool isPod = false;
bool isString = false;
bool isStruct = false;
bool isVisible = true;
};
struct StructInformation
{
QString type;
QString baseStruct;
QVector<MemberInformation> member;
bool isVisible = false;
};
struct EnumValue
{
QString key;
int value = 0;
};
struct EnumInformation
{
QString ns;
QString type;
QVector<EnumValue> values;
};
struct PodInformation
{
QString type;
int byteLen = 0;
bool isBoolean = false;
bool isIntegral = false;
bool isSigned = false;
};
class LogViewTetraTelegramsParser
{
public:
LogViewTetraTelegramsParser();
bool parse(const QString &filename);
EnumInformation enumFromType(const QString &type) const;
StructInformation structFromType(const QString &type) const;
PodInformation podFromType(const QString &type) const;
bool isEnum(const QString &type) const;
bool isStruct(const QString &type) const;
bool isPod(const QString &type) const;
QHash<int, QString> telegramsToCreate() const { return m_visibleTelegrams; }
QString nameFromTelegramId(int telId) const { return m_visibleTelegrams.value(telId); }
static QString getInnerType(const QString &type);
private:
void insertPod(const QString &type, int byteLen, bool isSigned, bool isIntegral, bool isBoolean = false);
int parseStruct(const QVector<QStringRef> &lines, int iStartPos);
int parseEnum(const QVector<QStringRef> &lines, int iStartPos, const QString &ns, StructInformation *si = nullptr);
int parseConstraint(const QVector<QStringRef> &lines, int iStartPos);
void categorizeMember(MemberInformation &mi) const;
QVector<QStringRef> tokenize(const QStringRef &line) const;
static bool validStructTokens(const QVector<QStringRef> &tokens);
private:
EnumInformation m_telegramIdEnum;
QVector<EnumInformation> m_enums;
QHash<QString, StructInformation> m_structs;
QHash<QString, PodInformation> m_pods;
QHash<int, QString> m_visibleTelegrams;
NGL::INGLLogger &m_logger;
};
}
+96
View File
@@ -0,0 +1,96 @@
#include "LogViewTextEdit.hpp"
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
namespace N_LogView
{
LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QLineEdit(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
{
const QString value = a_field->value(0);
setText(value);
if (a_readonly)
{
setReadOnly(true);
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
}
uint16_t maxArraySize = a_field->maxArraySize();
setMaxLength(maxArraySize);
updateToolTip(value);
QFontMetrics fm(font());
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
setMinimumWidth(fm.width(QLatin1Char(' ') + value + QLatin1Char(' ')));
#else
setMinimumWidth(fm.horizontalAdvance(QLatin1Char(' ') + value + QLatin1Char(' ')));
#endif
connect(this, &LogViewTextEdit::editingFinished,
this, &LogViewTextEdit::checkAndOvertakeContent);
}
void LogViewTextEdit::checkAndOvertakeContent()
{
updateToolTip(text());
m_Valid = true;
}
bool LogViewTextEdit::saveContent(LogViewTelegram* a_telegram)
{
if (!isValid())
return false;
if (a_telegram->isJsonTelegram())
{
a_telegram->setJsonValue(m_Field->jsonPath(), text());
}
else
{
uint16_t size = getSize();
QString content = text();
uint16_t arraySize;
if (m_Field->isDynamicArray())
{
arraySize = content.length();
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize);
}
else
{
arraySize = m_Field->maxArraySize();
}
for (int i = 0; i < arraySize; i++)
a_telegram->setUIntX(size, i < content.length() ? content[i].toLatin1() : 0);
}
return true;
}
}
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include "LogViewWidget.hpp"
#include <QLineEdit>
namespace N_LogView
{
class LogViewTextEdit : public QLineEdit, public LogViewWidget
{
Q_OBJECT
public:
LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void checkAndOvertakeContent();
};
}
+135
View File
@@ -0,0 +1,135 @@
#include "LogViewValueEdit.hpp"
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
namespace N_LogView
{
LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
: QLineEdit(a_parent)
, LogViewWidget(a_field, this, a_parent, a_readonly)
, m_IsFloat(false)
{
const LogViewXdrStandardType *stdType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
m_IsFloat = (LogViewXdrStandardType::e_Float == stdType->getValueKind());
const QString valueText = a_field->value(0);
setText(valueText);
updateToolTip(valueText);
QFontMetrics fm(font());
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
setMinimumWidth(fm.width(QLatin1Char(' ') + valueText + QLatin1Char(' ')));
#else
setMinimumWidth(fm.horizontalAdvance(QLatin1Char(' ') + valueText + QLatin1Char(' ')));
#endif
if (a_readonly)
{
setReadOnly(true);
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
}
else
{
connect(this, &LogViewValueEdit::editingFinished,
this, &LogViewValueEdit::checkAndOvertakeContent);
}
}
void LogViewValueEdit::checkAndOvertakeContent()
{
bool ok;
int64_t intValue = 0;
double floatValue = 0.0;
if (m_IsFloat)
floatValue = getFloat(text(), (uint64_t&)intValue, ok);
else
intValue = getInteger(text(), ok);
if (!ok)
{
setFocus();
selectAll();
return;
}
if (m_IsFloat)
setText(QString::number(floatValue));
else
setText(QString::number(intValue));
updateToolTip(text());
}
bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
{
if (m_Valid)
{
bool ok;
if (m_IsFloat)
{
uint64_t valueAsUint64;
const double value = getFloat(text(), valueAsUint64, ok);
if (ok)
{
if (a_telegram->isJsonTelegram())
{
a_telegram->setJsonValue(m_Field->jsonPath(), value);
}
else
{
const LogViewXdrStandardType *stdType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
LogViewXdrStandardType::E_ByteOrder byteOrder = stdType->getByteOrder();
a_telegram->setUIntX(getSize(), valueAsUint64, byteOrder);
}
return true;
}
}
else
{
qint64 intValue = getInteger(text(), ok);
if (ok)
{
if (a_telegram->isJsonTelegram())
a_telegram->setJsonValue(m_Field->jsonPath(), intValue);
else
a_telegram->setUIntX(getSize(), intValue);
return true;
}
}
}
return false;
}
}
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "LogViewWidget.hpp"
#include <QLineEdit>
namespace N_LogView
{
class LogViewValueEdit : public QLineEdit, public LogViewWidget
{
Q_OBJECT
public:
LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
bool saveContent(LogViewTelegram* a_telegram) override;
protected:
bool m_IsFloat;
protected slots:
void checkAndOvertakeContent();
};
}
+230
View File
@@ -0,0 +1,230 @@
#include "LogViewWidget.hpp"
#include "LogViewField.hpp"
#include "LogViewTelegram.hpp"
#include "LogViewXdrStandardType.hpp"
#include "IntegerCalculator.hpp"
#include <QMessageBox>
namespace N_LogView
{
LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* a_parent, bool a_readonly)
: m_Readonly(a_readonly)
, m_Valid(true)
, m_Widget(a_widget)
, m_Field(a_field)
, m_Parent(a_parent)
, m_logger(getLogger("LogViewWidget"))
{
}
uint16_t LogViewWidget::getSize() const
{
const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
return xdrStandardType->getValueSize();
}
void LogViewWidget::showMessageBox(const QString &a_errorText) const
{
QMessageBox::warning(m_Parent, QObject::tr("Fehler"), a_errorText);
}
void LogViewWidget::updateToolTip(const QString &a_text)
{
bool isList = m_Field->valueListSize() > 1 || m_Field->isDynamicArray();
switch (m_Field->xdrElement()->getKind())
{
case LogViewXdrElement::e_KindStandardType:
switch (static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement())->getValueKind())
{
case LogViewXdrStandardType::e_Character:
m_Widget->setToolTip(QObject::tr("%1 Zeichen").arg(a_text.length()));
if (!m_Readonly)
m_Widget->setToolTip(QObject::tr("%1<br><nobr>Maximal %2 Zeichen erlaubt</nobr>").arg(m_Widget->toolTip()).arg(m_Field->maxArraySize()));
break;
case LogViewXdrStandardType::e_Data:
if (m_Readonly)
m_Widget->setToolTip(QObject::tr("%1 Bytes").arg(m_Field->valueListSize()));
break;
case LogViewXdrStandardType::e_Unsigned:
case LogViewXdrStandardType::e_Signed:
if (m_Readonly && isList)
{
m_Widget->setToolTip(QObject::tr("%1 Elemente").arg(m_Field->valueListSize()));
}
else
{
if (m_Field->isDateTimeField())
{
m_Widget->setToolTip(QObject::tr("Unixzeit: %1 ").arg(a_text));
}
else
{
m_Widget->setToolTip(QString());
}
if (!isList)
{
int64_t value = a_text.toLong();
m_Widget->setToolTip(QStringLiteral("%1<b>%2</b> %3").arg(m_Widget->toolTip(), toHex(value), toBin(value)));
}
if (!m_Field->isDateTimeField() && !m_Readonly)
{
const QString sep(isList ? QString() : QStringLiteral("<br>"));
m_Widget->setToolTip(QStringLiteral("%1%2<nobr>Wertebereich: %3..%4</nobr>").arg(m_Widget->toolTip(), sep).arg(m_Field->getLowestValue()).arg(m_Field->getHighestValue()));
}
}
break;
case LogViewXdrStandardType::e_Float:
if (4 == m_Field->size())
m_Widget->setToolTip(QStringLiteral("<nobr>Wertebereich: +/-3.4e+/-38</nobr>"));
else
m_Widget->setToolTip(QStringLiteral("<nobr>Wertebereich: +/-1.7e+/-308</nobr>"));
break;
case LogViewXdrStandardType::e_Boolean:
m_Widget->setToolTip(QStringLiteral("true/false"));
}
break;
case LogViewXdrElement::e_KindEnum:
{
uint64_t enumValue = a_text.toLong();
m_Widget->setToolTip(QStringLiteral("<b>%1 %2</b> %3").arg(enumValue).arg(toHex(enumValue), toBin(enumValue)));
break;
}
default:
ERROR_LOG(m_logger) << "Case not implemented";
}
}
double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse)
{
double value;
if (8 == getSize())
{
value = a_text.toDouble(&a_ok);
a_FloatAsData = LogViewTelegram::doubleToXdr(value);
} else {
value = a_text.toFloat(&a_ok);
a_FloatAsData = LogViewTelegram::floatToXdr(value);
}
if (!a_ok)
showMessageBox(QStringLiteral("Inalid real value: '%1'").arg(a_text));
m_Valid = a_ok;
if (a_reverse)
{
int j = getSize() - 1;
uint64_t* ptr = &a_FloatAsData;
for (int i = 0; i < getSize() / 2; i++)
{
uint8_t data = ((uint8_t*)ptr)[j];
((uint8_t*)&a_FloatAsData)[j] = ((uint8_t*)&a_FloatAsData)[i];
((uint8_t*)&a_FloatAsData)[i] = data;
j--;
}
}
if (4 == getSize())
{
((uint8_t*)&a_FloatAsData)[4] = 0;
((uint8_t*)&a_FloatAsData)[5] = 0;
((uint8_t*)&a_FloatAsData)[6] = 0;
((uint8_t*)&a_FloatAsData)[7] = 0;
}
return value;
}
int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
{
N_SST::IntegerCalculator calculator;
N_SST::IntegerCalculator::E_Error error;
int64_t value = calculator.calc(a_text.toStdString(), error);
m_Valid = false;
a_ok = true;
if (N_SST::IntegerCalculator::e_Ok != error)
{
if (a_text != m_LastErrorValueText)
{
showMessageBox(QString::fromUtf8("Die Berechnung '%1' ist falsch").arg(a_text));
m_LastErrorValueText = a_text;
}
a_ok = false;
}
else
{
int64_t highest = m_Field->getHighestValue();
if (value > highest)
{
a_ok = false;
if (a_text != m_LastErrorValueText)
{
showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu hoch. Maximalwert: %2").arg(a_text).arg(highest));
m_LastErrorValueText = a_text;
}
return value;
}
int64_t lowest = m_Field->getLowestValue();
if (value < lowest)
{
a_ok = false;
if (a_text != m_LastErrorValueText)
{
showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu tief. Minimalwert: %2").arg(a_text).arg(lowest));
m_LastErrorValueText = a_text;
}
return value;
}
m_Valid = true;
}
return value;
}
}
+84
View File
@@ -0,0 +1,84 @@
#pragma once
#include <QWidget>
#include "logger.h"
class QWidget;
class QFont;
namespace N_LogView
{
template <typename T>
inline QString toHex(T num)
{
return QStringLiteral("0x%1").arg(num, 2, 16, QLatin1Char('0'));
}
template <typename T>
inline QString toBin(T num)
{
return QStringLiteral("0b%1").arg(num, 8, 2, QLatin1Char('0'));
}
class LogViewField;
class LogViewTelegram;
class LogViewWidget
{
public:
LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* a_parent, bool a_readonly);
virtual ~LogViewWidget() = default;
virtual uint16_t getSize() const;
LogViewField* field() const { return m_Field; }
bool isValid() const { return m_Valid; }
QString getText() const { return m_Text; }
virtual bool saveContent(LogViewTelegram* a_telegram) = 0;
protected:
void showMessageBox(const QString &a_errorText) const;
void updateToolTip(const QString &a_text = QString());
double getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse = false);
int64_t getInteger(const QString& a_text, bool& a_ok);
protected:
bool m_Readonly;
bool m_Valid;
QString m_Text;
QString m_LastErrorValueText;
QWidget *m_Widget;
LogViewField *m_Field;
QWidget *m_Parent;
NGL::INGLLogger &m_logger;
};
}
+61
View File
@@ -0,0 +1,61 @@
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
LogViewXdrElement::LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName)
: m_Name(a_name)
, m_Kind(a_kind)
, m_logger(getLogger(loggerName))
{
if (a_name.indexOf(QLatin1Char('<')) >= 0 || a_name.indexOf(QLatin1Char('[')) >= 0)
ERROR_LOG(m_logger) << "Element \'" << a_name.toStdString() << "\' has a problem";
}
void LogViewXdrElement::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName();
}
QString LogViewXdrElement::getKindName() const
{
switch (getKind())
{
case e_KindDefine:
return QLatin1String("Define");
case e_KindEnum:
return QLatin1String("Enum");
case e_KindEnumElement:
return QLatin1String("EnumElement");
case e_KindStandardType:
return QLatin1String("StandardType");
case e_KindStruct:
return QLatin1String("Struct");
case e_KindStructElement:
return QLatin1String("StructElement");
case e_KindTypedef:
return QLatin1String("Typedef");
}
return QStringLiteral("Unknown (%1)").arg(getKind());
}
}
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <QString>
#include "logger.h"
namespace N_LogView
{
class LogViewXdrElement
{
public:
enum E_ElementKind
{
e_KindStandardType,
e_KindTypedef,
e_KindStruct,
e_KindStructElement,
e_KindEnum,
e_KindEnumElement,
e_KindDefine
};
virtual ~LogViewXdrElement() = default;
protected:
LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName);
public:
const QString& getName() const { return m_Name; }
LogViewXdrElement::E_ElementKind getKind() const { return m_Kind; }
virtual void dump() const;
protected:
QString m_Name;
E_ElementKind m_Kind;
QString getKindName() const;
NGL::INGLLogger &m_logger;
};
}
File diff suppressed because it is too large. Load diff
+183
View File
@@ -0,0 +1,183 @@
#pragma once
#include <QString>
#include <QStringList>
#include "IntegerCalculator.hpp"
#include "logger.h"
#include "LogViewXdrStandardType.hpp"
namespace N_LogView
{
class LogViewXdrElement;
class LogViewXdrStruct;
class LogViewField;
class LogViewXdrValue;
class LogViewXdrType;
class LogViewXdrParser : public N_SST::IntegerCalculator
{
public:
enum E_ParseState
{
e_ParseMain,
e_ParseStruct,
e_ParseEnum,
e_ParseUnion
};
LogViewXdrParser();
~LogViewXdrParser();
void parseX_File(const QString& a_fileName);
QString getTelegramName(int a_telegramId) const;
QString getStructName(int a_telegramId) const;
bool getDefine(const QString& a_name, int64_t& a_value) const;
const LogViewXdrElement* getElement(const QString& a_name) const;
protected:
QString m_MessageBoxTitle;
bool m_WithinComment;
QString m_Line;
uint32_t m_LineNbr;
QString m_Filename;
bool m_DoReadUntilSemicolon;
QStringList m_WordList;
int m_WordListIndex;
QString m_UnionType;
std::map<QString, LogViewXdrElement*> m_ElementMap;
LogViewXdrStruct *m_ActElement;
E_ParseState m_State;
std::map<QString, LogViewXdrValue> m_DefinesMap;
std::map<int, LogViewXdrType> m_TelegramMap;
void addStandardType(const QString& a_name,
const uint16_t a_dataSize,
const uint16_t a_realSize,
const LogViewXdrStandardType::E_ValueKind a_kind,
const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod = LogViewXdrStandardType::e_DynArrayMsgLength,
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
QString removeComments(const QString& a_line);
void parseTypedef(const QString &a_line);
void parseDefine(const QString &a_line);
void parseEnum(const QString &a_line, const uint16_t a_enumSize = 4);
void parseStruct(const QString &a_line);
void parseUnion(const QString& a_line);
bool parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const;
void showErrorMessage(const QString& a_errorText) const;
int64_t calcValue(const QString& a_calcText, bool& a_isOk);
bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const override;
uint16_t parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const;
bool isNextWord(const char *a_word, const bool a_doIncrement = true);
void fillWordList(const QString& a_line);
QString getNextWord(const char *a_errorText = nullptr);
QString getNextType(bool& a_ok);
QString getNextEnum(const LogViewXdrStruct*& a_enumStruct);
bool parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const;
bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element);
private:
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,84 @@
#include "LogViewXdrStandardType.hpp"
namespace N_LogView
{
LogViewXdrStandardType::LogViewXdrStandardType(const QString& a_name, const int a_valueSize,
const int a_editSize, const E_ValueKind a_valueKind,
const E_DynArraySizeMethod a_dynArraySizeMethod, E_ByteOrder a_byteOrder)
: LogViewXdrElement(a_name, e_KindStandardType, "LogViewXdrStandardType")
, m_ValueSize(a_valueSize)
, m_EditSize(a_editSize)
, m_ValueKind(a_valueKind)
, m_ByteOrder(a_byteOrder)
, m_DynArraySizeMethod(a_dynArraySizeMethod)
{}
uint16_t LogViewXdrStandardType::getValueSize() const
{
return m_ValueSize;
}
LogViewXdrStandardType::E_ValueKind LogViewXdrStandardType::getValueKind() const
{
return m_ValueKind;
}
void LogViewXdrStandardType::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName()
<< "]: kind=" << getKindName()
<< " valueKind=" << getValueKind()
<< " valueSize=" << getValueSize()
<< " editSize=" << getEditSize()
<< " dynArrSizeMethod=" << getDynArraySizeMethod()
<< " byteOrder=" << getByteOrder();
}
LogViewXdrStandardType::E_DynArraySizeMethod LogViewXdrStandardType::getDynArraySizeMethod() const
{
return m_DynArraySizeMethod;
}
LogViewXdrStandardType::E_ByteOrder LogViewXdrStandardType::getByteOrder() const
{
return m_ByteOrder;
}
uint16_t LogViewXdrStandardType::getEditSize() const
{
return m_EditSize;
}
}
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
class LogViewXdrStandardType final : public LogViewXdrElement
{
public:
enum E_ValueKind
{
e_Unsigned,
e_Signed,
e_Float,
e_Character,
e_Boolean,
e_Data
};
enum E_ByteOrder
{
e_ByteOrderBigEndian,
e_ByteOrderLittleEndian
};
enum E_DynArraySizeMethod
{
e_DynArrayMsgLength,
e_DynArrayIndex,
e_DynArrayIndexDiv8
};
LogViewXdrStandardType(const QString &a_name,
const int a_valueSize,
const int a_editSize,
const E_ValueKind a_valueKind,
const E_DynArraySizeMethod a_dynArraySizeMethod,
E_ByteOrder a_byteOrder);
uint16_t getValueSize() const;
LogViewXdrStandardType::E_ValueKind getValueKind() const;
void dump() const override;
LogViewXdrStandardType::E_DynArraySizeMethod getDynArraySizeMethod() const;
LogViewXdrStandardType::E_ByteOrder getByteOrder() const;
uint16_t getEditSize() const;
protected:
int m_ValueSize;
int m_EditSize;
E_ValueKind m_ValueKind;
E_ByteOrder m_ByteOrder;
E_DynArraySizeMethod m_DynArraySizeMethod;
};
}
+105
View File
@@ -0,0 +1,105 @@
#include "LogViewXdrStruct.hpp"
#include "LogViewXdrValue.hpp"
#include "LogViewXdrType.hpp"
namespace N_LogView
{
LogViewXdrStruct::LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrStruct")
, m_EnumSize(enumSize)
{
}
LogViewXdrStruct::~LogViewXdrStruct()
{
for (auto ptr : m_ChildList)
delete ptr;
}
void LogViewXdrStruct::addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast)
{
m_ChildList.push_back(new LogViewXdrType(a_name, a_type, a_arraySize, a_dynArrayOffset, a_kind, a_firstBit, a_lastBit, a_isLast));
}
void LogViewXdrStruct::addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind)
{
m_ChildList.push_back(new LogViewXdrValue(a_name, a_value, a_kind));
}
LogViewXdrElement* LogViewXdrStruct::getChild(const uint32_t a_childIndex) const
{
if (m_ChildList.size() > a_childIndex)
return m_ChildList[a_childIndex];
return nullptr;
}
LogViewXdrType* LogViewXdrStruct::getChildAsType(const uint32_t a_childIndex) const
{
return static_cast<LogViewXdrType*>(getChild(a_childIndex));
}
LogViewXdrValue* LogViewXdrStruct::getChildAsValue(const uint32_t a_childIndex) const
{
return static_cast<LogViewXdrValue*>(getChild(a_childIndex));
}
void LogViewXdrStruct::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName().toStdString() << "]: kind=" << getKindName().toStdString() << " enumSize=" << getEnumSize();
INFO_LOG(m_logger) << "-------------- childs start -----------------";
std::vector<LogViewXdrElement*>::const_iterator iter = m_ChildList.begin();
while (iter != m_ChildList.end())
{
(*iter)->dump();
++iter;
}
INFO_LOG(m_logger) << "-------------- childs end -----------------";
}
uint32_t LogViewXdrStruct::getChildValue(const QString& a_name, bool* a_error) const
{
if (a_error)
*a_error = false;
std::vector<LogViewXdrElement*>::const_iterator iter = m_ChildList.begin();
while (iter != m_ChildList.end())
{
if ((*iter)->getName() == a_name)
return static_cast<const LogViewXdrValue*>(*iter)->getValue();
++iter;
}
if (a_error)
*a_error = true;
return 0;
}
}
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include <QtCore/QString>
#include "LogViewXdrElement.hpp"
#include <vector>
namespace N_LogView
{
class LogViewXdrValue;
}
namespace N_LogView
{
class LogViewXdrType;
}
namespace N_LogView
{
class LogViewXdrStruct final : public LogViewXdrElement
{
public:
LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize = 0);
~LogViewXdrStruct();
void addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit = -1, const int16_t a_lastBit = -1, const bool a_isLast = true);
void addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind);
LogViewXdrElement* getChild(const uint32_t a_childIndex) const;
LogViewXdrType* getChildAsType(const uint32_t a_childIndex) const;
LogViewXdrValue* getChildAsValue(const uint32_t a_childIndex) const;
void dump() const override;
uint32_t getChildValue(const QString& a_name, bool* a_error = nullptr) const;
uint16_t getEnumSize() const { return m_EnumSize; }
protected:
uint16_t m_EnumSize;
std::vector<LogViewXdrElement*> m_ChildList;
};
}
+106
View File
@@ -0,0 +1,106 @@
#include "LogViewXdrType.hpp"
namespace N_LogView
{
LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrElement")
, m_Type(a_type)
, m_ArraySize(a_arraySize)
, m_MaxArraySize(a_dynArrayOffset)
, m_FirstBit(-1)
, m_LastBit(-1)
, m_IsLast(true)
{
}
LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrType")
, m_Type(a_type)
, m_ArraySize(a_arraySize)
, m_MaxArraySize(a_dynArrayOffset)
, m_FirstBit(a_firstBit)
, m_LastBit(a_lastBit)
, m_IsLast(a_isLast)
{
}
void LogViewXdrType::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName()
<< "]: kind=" << getKindName()
<< " type=" << getType()
<< " arraySize=" << getArraySize()
<< " maxArraySize=" << getMaxArraySize()
<< " firstBit=" << m_FirstBit
<< " lastBit=" << m_LastBit
<< " isLast=" << m_IsLast;
}
const QString& LogViewXdrType::getType() const
{
return m_Type;
}
uint16_t LogViewXdrType::getArraySize() const
{
return m_ArraySize;
}
bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const
{
if (m_FirstBit != -1 && m_LastBit != -1)
{
DEBUG_LOG(m_logger) << "MaskValue for Element " << m_Name
<< " type: " << m_Type
<< " size: " << m_ArraySize
<< " first:last " << m_FirstBit << ":" << m_LastBit
<< " isLast: " << m_IsLast;
uint16_t bitshift = (a_size*8)-m_LastBit-1;
uint32_t mask = (1<<(m_LastBit-m_FirstBit+1))-1;
a_value = (a_value >> bitshift) & mask;
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_FirstBit, QLatin1String("<b>"));
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_LastBit+1, QLatin1String("</b>"));
return m_IsLast;
}
return true;
}
uint16_t LogViewXdrType::getMaxArraySize() const
{
return m_MaxArraySize;
}
}
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
class LogViewXdrType final : public LogViewXdrElement
{
public:
LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind);
LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast);
void dump() const override;
const QString& getType() const;
uint16_t getArraySize() const;
bool maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const;
uint16_t getMaxArraySize() const;
protected:
QString m_Type;
uint16_t m_ArraySize;
uint16_t m_MaxArraySize;
int16_t m_FirstBit;
int16_t m_LastBit;
bool m_IsLast;
};
}
+40
View File
@@ -0,0 +1,40 @@
#include "LogViewXdrValue.hpp"
namespace N_LogView
{
LogViewXdrValue::LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind)
: LogViewXdrElement(a_name, a_kind, "LogViewXdrValue")
, m_Value(a_value)
{}
void LogViewXdrValue::dump() const
{
INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName() << " value=" << getValue();
}
int64_t LogViewXdrValue::getValue() const
{
return m_Value;
}
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
class LogViewXdrValue final : public LogViewXdrElement
{
public:
LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind);
void dump() const override;
int64_t getValue() const;
protected:
int64_t m_Value;
};
}
+17
View File
@@ -0,0 +1,17 @@
log4j.reset=true
log4j.rootLogger=INFO, C
log4j.rootLogger=INFO, F
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.F=org.apache.log4j.RollingFileAppender
log4j.appender.F.File=${LOG4QT_LOGDIR}/${LOG4QT_USER}_LogView.log
log4j.appender.F.MaxFileSize=10MB
# Keep one backup file
log4j.appender.F.MaxBackupIndex=5
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.F.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%-5p (%-20.20F:%04L) [%d{HH:mm:ss.SSS}] - %m%n
log4j.appender.F.layout.ConversionPattern=%-5p (%-20.20F:%04L) [%d{HH:mm:ss.SSS}] - %m%n
Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

+32
View File
@@ -0,0 +1,32 @@
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace N_LogView
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "LogView.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <NGLLogger/INGLLogger.h>
namespace N_LogView
{
typedef NGL::INGLLogger &LOGGER_T;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
}
+1
View File
@@ -0,0 +1 @@
zsksxd_tetraForLogView.x
File diff suppressed because it is too large. Load diff
+1
View File
@@ -0,0 +1 @@
zsksxd_tetraForLogView_guez.x
File diff suppressed because it is too large. Load diff
+88
View File
@@ -0,0 +1,88 @@
#include "AppComponent.hpp"
namespace N_AppComponent
{
int32_t AppComponent::create(NGL::Settings *settings)
{
for (IAppComponent *c : m_Childs)
c->create(settings);
return 0;
}
int32_t AppComponent::destroy()
{
for (IAppComponent *c : m_Childs)
c->destroy();
return 0;
}
int32_t AppComponent::init()
{
for (IAppComponent *c : m_Childs)
c->init();
return 0;
}
int32_t AppComponent::deinit()
{
for (IAppComponent *c : m_Childs)
c->deinit();
return 0;
}
int32_t AppComponent::start()
{
for (IAppComponent *c : m_Childs)
c->start();
return 0;
}
int32_t AppComponent::stop()
{
for (IAppComponent *c : m_Childs)
c->stop();
return 0;
}
void AppComponent::addChild(IAppComponent *a_child, const QString &a_name)
{
if (a_child)
{
a_child->setName(a_name);
m_Childs.push_back(a_child);
}
}
IAppComponent *AppComponent::getChild(const QString &a_name)
{
for (IAppComponent *c : m_Childs)
{
if (a_name == c->getName())
return c;
}
return nullptr;
}
}
+45
View File
@@ -0,0 +1,45 @@
#pragma once
#include <vector>
#include "IAppComponent.hpp"
#include <PrtCnv/prtcnvlib_export.h>
namespace NGL {
class Settings;
}
namespace N_AppComponent
{
class PRTCNVLIB_EXPORT AppComponent : public N_AppComponent::IAppComponent
{
public:
AppComponent() = default;
~AppComponent() = default;
int32_t create(NGL::Settings *settings) override;
int32_t deinit() override;
int32_t destroy() override;
int32_t init() override;
int32_t start() override;
int32_t stop() override;
protected:
void addChild(IAppComponent* a_child, const QString& a_name = QString());
IAppComponent* getChild(const QString& a_name);
private:
std::vector<IAppComponent*> m_Childs;
};
}
+78
View File
@@ -0,0 +1,78 @@
#
# $Id$
# $HeadURL$
# $Author$
#
#ADD_SUBDIRECTORY(TetraTestServer)
ADD_SUBDIRECTORY(LastTest)
ADD_SUBDIRECTORY(LastTestAuswertung)
SET(PrtCnv_SRCS
logger.h
logger.cpp
AppComponent.cpp
AppComponent.hpp
IAppComponent.hpp
PrtCnvApplication.cpp
PrtCnvApplication.hpp
PrtCnvBroadcastMgr.cpp
PrtCnvBroadcastMgr.hpp
PrtCnvCentralThread.cpp
PrtCnvCentralThread.hpp
PrtCnvDbThread.cpp
PrtCnvDbThread.hpp
PrtCnvInjectionSocket.cpp
PrtCnvInjectionSocket.hpp
PrtCnvInjectionThread.cpp
PrtCnvInjectionThread.hpp
PrtCnvMember.cpp
PrtCnvMember.hpp
PrtCnvRadioThread.cpp
PrtCnvRadioThread.hpp
PrtCnvRadioTrafficThread.cpp
PrtCnvRadioTrafficThread.hpp
PrtCnvSocketThread.cpp
PrtCnvSocketThread.hpp
PrtCnvStoredCentralTelegram.hpp
PrtCnvStoredRadioTelegram.hpp
PrtCnvStoredTelegram.hpp
PrtCnvTelegramLogThread.cpp
PrtCnvTelegramLogThread.hpp
PrtCnvThread.cpp
PrtCnvThread.hpp
PrtCnvThreadStarter.cpp
PrtCnvThreadStarter.hpp
)
NGL_ADD_LIBRARY2(AAR SV PrtCnvLib SHARED ${PrtCnv_SRCS})
NGL_TARGET_LINK_LIBRARIES(PrtCnvLib
PRIVATE
ngldb
nglsettings
LtsUtilsCoreHeaderOnly
Qt5::Sql
Qt5::WebSockets
PUBLIC
CoPrtCnv
Qt5::Core
Qt5::Network
NGLLogger
)
NGL_TARGET_INCLUDE_DIRECTORIES(PrtCnvLib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_ADD_EXECUTABLE(AAR SV PrtCnv PrtCnvMain.cpp)
NGL_TARGET_LINK_LIBRARIES(PrtCnv
PrtCnvLib
Qt5::Core
LtsCommandLineParser
nglcoreapplication
)
NGL_INSTALL_TARGET(PrtCnv)
NGL_INSTALL(AAR SV FILES log4cxx_prtcnv.props DESTINATION bin)
NGL_INSTALL(AAR SV FILES PrtCnv.dat.tts DESTINATION bin)
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include <QtCore/QString>
namespace NGL {
class Settings;
}
namespace N_AppComponent
{
class IAppComponent
{
public:
IAppComponent() = default;
virtual ~IAppComponent() = default;
virtual int32_t create(NGL::Settings *settings) = 0;
virtual int32_t deinit() = 0;
virtual int32_t destroy() = 0;
virtual int32_t init() = 0;
virtual int32_t start() = 0;
virtual int32_t stop() = 0;
inline const QString& getName() const
{
return m_Name;
}
inline void setName(const QString& newVal)
{
m_Name = newVal;
}
protected:
QString m_Name;
};
}
Loaded 100 of 991 files, more files were not shown because too many files have changed in this diff. Show more