TetraIF migration and Unittest Implementation for it

Entire-Checkpoint: 14d1fef0cf36
This commit is contained in:
berrux-dev committed 2026-09-12 13:54:34 +02:00
1 parent a86f9b5bac
commit ba212f9dce
78 files changed
+1611 -640

No files matched your search

Vendored
+25 -9
View File
@@ -1,9 +1,13 @@
pipeline { pipeline {
agent { agent {
docker { docker {
image 'lifemaps/ci-cpp:latest' // Unified build image, built from ci/Dockerfile.ci:
// docker build -f ci/Dockerfile.ci -t legatus-build:26.04 ci
// Push it to the registry the Jenkins agents pull from before enabling this.
image 'legatus-build:26.04'
reuseNode true reuseNode true
args '-u root:root' // RTI Connext is not part of the image and has to be mounted read-only.
args '-u root:root -v /opt/rti_connext_dds-7.7.0:/opt/rti_connext_dds-7.7.0:ro'
} }
} }
@@ -13,12 +17,18 @@ pipeline {
} }
environment { environment {
PROJECT_DIR = "qt6-after/qt6-migrated-benchmark" PROJECT_DIR = "qt6-after/qt6-migrated-legatus"
BUILD_DIR = "build" BUILD_DIR = "qt6-after/qt6-migrated-legatus/build-ci"
CHANGE_TARGET = "${env.CHANGE_TARGET ?: 'origin/main'}" CHANGE_TARGET = "${env.CHANGE_TARGET ?: 'origin/main'}"
QT_QPA_PLATFORM = "offscreen" QT_QPA_PLATFORM = "offscreen"
LANG = "C.UTF-8" LANG = "C.UTF-8"
LC_ALL = "C.UTF-8" LC_ALL = "C.UTF-8"
// Targets known to build and test green today. A full `cmake --build` still
// fails outside TetraIF: Z/src/nglwidgets has an unfinished Poppler port, and
// several targets compile the RTI headers without -DRTI_UNIX. Widen this list
// as those modules get migrated.
BUILD_TARGETS = "CoPrtCnv PrtCnvLib PrtCnv LogView_console CoPrtCnvTests PrtCnvTests LogViewTests"
TEST_REGEX = "CoPrtCnvRadioTelegramTest|PrtCnvMemberTest|PrtCnvStoredTelegramTest|LogViewFieldTest|LogViewTetraTelegramsParserTest"
} }
stages { stages {
@@ -47,8 +57,8 @@ pipeline {
echo "QT_QPA_PLATFORM=$QT_QPA_PLATFORM" echo "QT_QPA_PLATFORM=$QT_QPA_PLATFORM"
echo "LANG=$LANG" echo "LANG=$LANG"
echo "LC_ALL=$LC_ALL" echo "LC_ALL=$LC_ALL"
dpkg -l | grep -E "qt6-base-dev|qtbase5-dev|qt6-tools" || true dpkg -l | grep -E "qt6-base-dev|qt6-tools|qt6-websockets-dev" || true
pkg-config --list-all | grep -i qt || true ls /opt/rti_connext_dds-7.7.0 >/dev/null && echo "RTI Connext mounted" || echo "RTI Connext MISSING"
''' '''
} }
} }
@@ -61,19 +71,25 @@ pipeline {
stage('Configure') { stage('Configure') {
steps { steps {
sh 'cmake -S ${PROJECT_DIR} -B ${BUILD_DIR} -G Ninja -DCMAKE_BUILD_TYPE=Debug' // The project pins CMAKE_CXX_STANDARD to 17; do not override it here.
sh '''
cmake -S ${PROJECT_DIR} -B ${BUILD_DIR} \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_RTI=ON \
-DBUILD_ARCGIS=OFF
'''
} }
} }
stage('Build') { stage('Build') {
steps { steps {
sh 'cmake --build ${BUILD_DIR} --parallel' sh 'cmake --build ${BUILD_DIR} --parallel --target ${BUILD_TARGETS}'
} }
} }
stage('Test') { stage('Test') {
steps { steps {
sh 'QT_QPA_PLATFORM=offscreen LANG=C.UTF-8 LC_ALL=C.UTF-8 ctest --test-dir ${BUILD_DIR} --output-on-failure' sh 'ctest --test-dir ${BUILD_DIR} -R "${TEST_REGEX}" --output-on-failure'
} }
} }
} }
+70 -67
View File
@@ -1,88 +1,91 @@
# Unified build/CI image for the Legatus Qt6 migration.
#
# Build (context is ci/, which holds the RTI licence file):
# docker build -f ci/Dockerfile.ci -t legatus-build:26.04 ci
#
# RTI Connext is not baked into the image, it is mounted at run time:
# -v /path/to/rti_connext_dds-7.7.0:/opt/rti_connext_dds-7.7.0:ro
#
# Qt comes from the Ubuntu 26.04 packages (6.10.2). It is deliberately not
# installed through aqtinstall: libkf6texttemplate-dev, which Lts/Common/CodeGen
# requires, is linked against the distribution Qt6, and loading a second Qt6
# from /opt/Qt beside it would put two copies of QtCore in the same process.
FROM ubuntu:26.04 FROM ubuntu:26.04
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
ENV QT_VERSION=6.10.2
ENV QT_ARCH=linux_gcc_64
ENV QT_BASE_DIR=/opt/Qt
ENV QT_ROOT=/opt/Qt/6.10.2/gcc_64
ENV Qt6_ROOT=/opt/Qt/6.10.2/gcc_64
ENV CMAKE_PREFIX_PATH=/usr/local:/opt/Qt/6.10.2/gcc_64
ENV PATH=/opt/Qt/6.10.2/gcc_64/bin:$PATH
ENV LD_LIBRARY_PATH=/opt/Qt/6.10.2/gcc_64/lib:${LD_LIBRARY_PATH:-}
RUN apt-get update && \ # Toolchain, CI tooling (policy checks and formatting), Qt 6.10.2 with every
apt-get install -y --no-install-recommends \ # module the project's find_package() calls ask for, KDE text templating for
# Lts/Common/CodeGen, GoogleTest, and the third-party libraries the services link.
RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \
build-essential \
g++ \
make \
cmake \
ninja-build \
pkg-config \
binutils \
gdb \
file \
less \
git \
ca-certificates \
openssh-client \
python3 \ python3 \
python3-pip \ python3-pip \
python3-venv \ python3-venv \
clang-format \ clang-format \
cmake \ qt6-base-dev \
ninja-build \ qt6-tools-dev \
git \ qt6-tools-dev-tools \
g++ \ qt6-l10n-tools \
make \ qt6-declarative-dev \
ca-certificates \ qt6-multimedia-dev \
openssh-client \ qt6-positioning-dev \
pkg-config \ qt6-serialport-dev \
libpq-dev \ qt6-svg-dev \
libbz2-dev \ qt6-webengine-dev \
qt6-websockets-dev \
qt6-5compat-dev \
libgl-dev \
libkf6texttemplate-dev \
libgtest-dev \
libboost-all-dev \ libboost-all-dev \
libxml2-dev \ libbz2-dev \
libcurl4-openssl-dev \
libpq-dev \
libssl-dev \ libssl-dev \
libcurl4-openssl-dev && \ libxml2-dev \
rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Install Qt 6.10.2 via aqtinstall # Headless Qt, for tests that instantiate widgets.
RUN python3 -m venv /opt/venv && \ ENV QT_QPA_PLATFORM=offscreen
/opt/venv/bin/pip install --upgrade pip setuptools wheel && \
/opt/venv/bin/pip install aqtinstall && \
mkdir -p "${QT_BASE_DIR}" && \
/opt/venv/bin/python -m aqt install-qt linux desktop "${QT_VERSION}" "${QT_ARCH}" -m qtmultimedia qtserialport qtimageformats qtwebsockets qtwebengine qtpdf qtwebview --outputdir "${QT_BASE_DIR}" && \
test -f "${QT_ROOT}/lib/cmake/Qt6/Qt6Config.cmake"
# Install Log4Qt for Qt6 # Log4Qt is deliberately NOT installed. Its public header log4qt/level.h declares
RUN git clone --depth 1 https://github.com/MEONMedical/Log4Qt.git /tmp/log4qt && \ # a defaulted C++20 operator<=>, so every consumer must be compiled with
cd /tmp/log4qt && \ # -std=c++20 or later. This project targets C++17, and pulling Log4Qt in makes
mkdir -p build && cd build && \ # Z/src/NGLLogger fail to compile. NGLLogger falls back to its own log4qt_stub.h
cmake -DCMAKE_BUILD_TYPE=Release \ # when the package is absent. Re-enabling Log4Qt would require moving the whole
-DCMAKE_CXX_STANDARD=23 \ # project to C++20 first.
-DCMAKE_CXX_EXTENSIONS=OFF \
-DCMAKE_PREFIX_PATH="${QT_ROOT}" \
-DCMAKE_INSTALL_PREFIX="/usr/local" \
-DBUILD_SHARED_LIBS=ON .. && \
cmake --build . -- -j$(nproc) && \
cmake --install . && \
rm -rf /tmp/log4qt
# Create minimal CMake config for Log4Qt # RTI Connext DDS - mounted at run time, see the header comment.
RUN mkdir -p /usr/local/lib/cmake/Log4Qt && \ ENV RTI_CONNEXT_HOME=/opt/rti_connext_dds-7.7.0 \
cat > /usr/local/lib/cmake/Log4Qt/Log4QtConfig.cmake << 'EOF' NDDSHOME=/opt/rti_connext_dds-7.7.0 \
if (NOT TARGET Log4Qt::log4qt) DDS_PATH=/opt/rti_connext_dds-7.7.0 \
add_library(Log4Qt::log4qt UNKNOWN IMPORTED) PATH=/opt/rti_connext_dds-7.7.0/bin:$PATH \
set_target_properties(Log4Qt::log4qt PROPERTIES LD_LIBRARY_PATH=/opt/rti_connext_dds-7.7.0/lib/x64Linux4gcc8.5.0
IMPORTED_LOCATION "/usr/local/lib/liblog4qt.so"
INTERFACE_INCLUDE_DIRECTORIES "/usr/local/include"
)
endif()
set(Log4Qt_FOUND TRUE CACHE INTERNAL "Log4Qt found by package config")
set(Log4Qt_INCLUDE_DIRS "/usr/local/include" CACHE INTERNAL "Log4Qt include dir")
set(Log4Qt_LIBRARIES "/usr/local/lib/liblog4qt.so" CACHE INTERNAL "Log4Qt library")
EOF
# Set Qt platform for headless testing # Developer licence file. Override RTI_LICENSE_FILE to point at another one.
# ArcGIS SDK configuration COPY rti_license.dat /root/rti_license.dat
ENV RTI_LICENSE_FILE=/root/rti_license.dat
# ArcGIS SDK - only needed with -DBUILD_ARCGIS=ON, mounted at run time.
ENV ARCGIS_ROOT=/repo/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk ENV ARCGIS_ROOT=/repo/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk
ENV ARCGIS_INC_DIR=${ARCGIS_ROOT}/include ENV ARCGIS_INC_DIR=${ARCGIS_ROOT}/include
ENV ARCGIS_LIB_DIR=${ARCGIS_ROOT}/linux/x64/lib ENV ARCGIS_LIB_DIR=${ARCGIS_ROOT}/linux/x64/lib
# Set Qt platform for headless testing # Containerised checkouts are owned by a different uid than the build user.
ENV QT_QPA_PLATFORM=offscreen
# Configure git for containerized environments
RUN git config --global --add safe.directory "*" RUN git config --global --add safe.directory "*"
# Setup RTI Connext license (developer license file)
COPY rti_license.dat /root/rti_license.dat
ENV RTI_LICENSE_FILE=/root/rti_license.dat
WORKDIR /workspace WORKDIR /workspace
CMD ["bash"]
-13
View File
@@ -1,13 +0,0 @@
FROM lifemaps/ci-cpp:latest
# Qt6Multimedia ist bereits im Basis-Image installiert (libqt6multimedia6)
# RTI Connext wird zur Laufzeit gemounted (nicht im Image kopieren)
# Erwartet: -v /pfad/zu/rti_connext_dds-7.7.0:/opt/rti_connext_dds-7.7.0
ENV RTI_LICENSE_FILE=/root/rti_license.dat
ENV RTI_CONNEXT_HOME=/opt/rti_connext_dds-7.7.0
ENV NDDSHOME=/opt/rti_connext_dds-7.7.0
ENV PATH=/opt/rti_connext_dds-7.7.0/bin:$PATH
ENV LD_LIBRARY_PATH=/opt/rti_connext_dds-7.7.0/lib/x64Linux4gcc7.3.0:$LD_LIBRARY_PATH
ENV CMAKE_PREFIX_PATH=/opt/rti_connext_dds-7.7.0/lib/cmake:$CMAKE_PREFIX_PATH
WORKDIR /workspace
-36
View File
@@ -1,36 +0,0 @@
#!/bin/bash
# Install RTI Connext into existing Docker image
set -e
RTI_SOURCE="/home/torsten/swy/sandbox/external/rti_connext_dds-7.7.0"
BASE_IMAGE="lifemaps/ci-cpp:latest"
TARGET_IMAGE="lifemaps/ci-cpp:rti"
echo "Step 1: Create container from base image..."
CONTAINER_ID=$(docker create --name rti-install-temp $BASE_IMAGE /bin/bash)
echo "Step 2: Copy RTI Connext into container..."
docker cp "$RTI_SOURCE" "$CONTAINER_ID:/opt/rti_connext_dds-7.7.0"
echo "Step 3: Commit container as new image..."
docker commit $CONTAINER_ID $TARGET_IMAGE
echo "Step 4: Remove temporary container..."
docker rm $CONTAINER_ID
echo "Step 5: Set environment variables in image..."
docker run --rm $TARGET_IMAGE /bin/bash -c '
echo "RTI Connext installed successfully"
ls -la /opt/rti_connext_dds-7.7.0 | head -10
'
echo ""
echo "RTI Connext installed in image: $TARGET_IMAGE"
echo "To use this image, set environment variables:"
echo " docker run -e RTI_CONNEXT_HOME=/opt/rti_connext_dds-7.7.0 \\"
echo " -e NDDSHOME=/opt/rti_connext_dds-7.7.0 \\"
echo " -e PATH=/opt/rti_connext_dds-7.7.0/bin:\$PATH \\"
echo " -e LD_LIBRARY_PATH=/opt/rti_connext_dds-7.7.0/lib/x64Linux4gcc7.3.0:\$LD_LIBRARY_PATH \\"
echo " -e CMAKE_PREFIX_PATH=/opt/rti_connext_dds-7.7.0/lib/cmake:\$CMAKE_PREFIX_PATH \\"
echo " $TARGET_IMAGE"
+41 -1
View File
@@ -96,7 +96,12 @@ include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsCore)
include_directories(${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap) include_directories(${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap)
include_directories(${CMAKE_SOURCE_DIR}/include/OperatorManagement) include_directories(${CMAKE_SOURCE_DIR}/include/OperatorManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/FileManagement) include_directories(${CMAKE_SOURCE_DIR}/include/FileManagement)
SET(CMAKE_CXX_STANDARD 17) # The project targets C++17. This was a plain SET() before, which silently
# shadowed any -DCMAKE_CXX_STANDARD= passed on the command line; the IF guard
# makes that override work again without changing the default.
IF(NOT CMAKE_CXX_STANDARD)
SET(CMAKE_CXX_STANDARD 17)
ENDIF()
SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON) SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
SET(CMAKE_CXX_VISIBILITY_PRESET hidden) SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
@@ -180,6 +185,34 @@ ENDIF()
ENABLE_TESTING() ENABLE_TESTING()
INCLUDE(CTest) INCLUDE(CTest)
# GoogleTest is resolved once here so that every unittest/ subdirectory can just
# link GTest::gtest_main. Set LTS_FETCH_GOOGLETEST=OFF on an offline build machine
# that has no system-wide GTest; the unit tests are then skipped instead of
# failing the configure step.
OPTION(LTS_FETCH_GOOGLETEST "Download GoogleTest when no system-wide GTest is found" ON)
IF(BUILD_TESTING)
FIND_PACKAGE(GTest QUIET)
IF(NOT TARGET GTest::gtest_main AND LTS_FETCH_GOOGLETEST)
INCLUDE(FetchContent)
FETCHCONTENT_DECLARE(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0
)
SET(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
SET(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
FETCHCONTENT_MAKEAVAILABLE(googletest)
ENDIF()
IF(TARGET GTest::gtest_main)
SET(LTS_HAVE_GTEST TRUE)
ELSE()
SET(LTS_HAVE_GTEST FALSE)
MESSAGE(STATUS "GoogleTest not available - unit tests will not be built")
ENDIF()
ELSE()
SET(LTS_HAVE_GTEST FALSE)
ENDIF()
CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY) CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY)
CONFIGURE_FILE(lts-cc.conf ${CMAKE_BINARY_DIR}/lts-cc.conf.distrib COPYONLY) CONFIGURE_FILE(lts-cc.conf ${CMAKE_BINARY_DIR}/lts-cc.conf.distrib COPYONLY)
@@ -418,6 +451,13 @@ if(NOT TARGET Qt6::OpenGL)
message(STATUS "Created stub target for Qt6::OpenGL (library not available)") message(STATUS "Created stub target for Qt6::OpenGL (library not available)")
endif() endif()
# WebSockets is not part of the component list of the first find_package() above,
# and that call succeeds, so the fallback block that does request it never runs.
# Look the module up on its own before deciding whether a stub is needed.
if(NOT TARGET Qt6::WebSockets)
find_package(Qt6 6.2 COMPONENTS WebSockets QUIET)
endif()
# Stub Qt6::WebSockets target if not available (needed by LtsWebSocket, httq, etc.) # Stub Qt6::WebSockets target if not available (needed by LtsWebSocket, httq, etc.)
if(NOT TARGET Qt6::WebSockets) if(NOT TARGET Qt6::WebSockets)
add_library(Qt6::WebSockets INTERFACE IMPORTED) add_library(Qt6::WebSockets INTERFACE IMPORTED)
@@ -1,34 +0,0 @@
# docker build -f Dockerfile.build -t legatus-build:26.04 .
FROM ubuntu:26.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \
build-essential \
cmake \
libkf6texttemplate-dev \
libqt6core6 \
libqt6gui6 \
libqt6widgets6 \
qt6-base-dev \
qt6-tools-dev-tools \
qt6-tools-dev \
qt6-l10n-tools \
libgtest-dev \
git \
file \
binutils \
gdb \
less \
&& rm -rf /var/lib/apt/lists/*
ENV QT_QPA_PLATFORM=offscreen
ENV RTI_LICENSE_FILE=/workspace/rti_license.dat \
DDS_PATH=/opt/rti_connext_dds-7.7.0 \
NDDSHOME=/opt/rti_connext_dds-7.7.0 \
CMAKE_PREFIX_PATH=/opt/Qt/6.10.2/gcc_64 \
LD_LIBRARY_PATH=/workspace/qt6-after/qt6-migrated-legatus/build4/lib:/opt/rti_connext_dds-7.7.0/lib/x64Linux4gcc8.5.0
WORKDIR /workspace/qt6-after/qt6-migrated-legatus
CMD ["bash"]
@@ -44,6 +44,11 @@ SET(SRCS_telegrams
training_area_telegrams.h training_area_telegrams.h
) )
NGL_ADD_LIBRARY(AAR SV WS HLA tabTelegrams STATIC ${SRCS_telegrams}) NGL_ADD_LIBRARY(AAR SV WS HLA tabTelegrams STATIC ${SRCS_telegrams})
# This static library is linked into shared libraries (CoPrtCnv among others),
# so its objects have to be position independent.
IF(TARGET tabTelegrams)
SET_TARGET_PROPERTIES(tabTelegrams PROPERTIES POSITION_INDEPENDENT_CODE ON)
ENDIF()
NGL_TARGET_INCLUDE_DIRECTORIES(tabTelegrams NGL_TARGET_INCLUDE_DIRECTORIES(tabTelegrams
PUBLIC PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/..
@@ -37,3 +37,8 @@ NGL_TARGET_INCLUDE_DIRECTORIES(CoPrtCnv
${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
) )
# Unit tests (LTS_HAVE_GTEST is set by the top-level CMakeLists.txt)
if(BUILD_TESTING AND LTS_HAVE_GTEST)
add_subdirectory(unittest)
endif()
@@ -16,6 +16,7 @@
#include "CoPrtCnvRadioTelegram.hpp" #include "CoPrtCnvRadioTelegram.hpp"
#include <QtCore/QByteArray> #include <QtCore/QByteArray>
#include <QtCore/QString>
#include <NGLLogger/NGLLoggerBootstrap.h> #include <NGLLogger/NGLLoggerBootstrap.h>
static std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegram* sammelTelegram) static std::string dumpSammeldeaktivierung(const N_CoPrtCnv::CoPrtCnvRadioTelegram* sammelTelegram)
@@ -129,7 +130,7 @@ QByteArray telegramId2String(gef_telegramm_id_et telId)
Q_ASSERT(str); Q_ASSERT(str);
if (!str) if (!str)
str = "Unknown"; str = "Unknown";
return str + QByteArray(" (") + QByteArray::number(int(telId)) + ")"; return QByteArray(str) + QByteArray(" (") + QByteArray::number(static_cast<int>(telId)) + ")";
} }
QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wirkfeldTyp) QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wirkfeldTyp)
@@ -137,29 +138,29 @@ QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wir
switch(wirkfeldTyp) switch(wirkfeldTyp)
{ {
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::MineArea: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::MineArea:
return QLatin1String("MINENSPERRE"); return QStringLiteral("MINENSPERRE");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionArea: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionArea:
return QLatin1String("FLAECHENFEUER"); return QStringLiteral("FLAECHENFEUER");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionSingle: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::ExplosionSingle:
return QLatin1String("EINZELFEUER"); return QStringLiteral("EINZELFEUER");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::NContamination: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::NContamination:
return QLatin1String("A_KAMPF"); return QStringLiteral("A_KAMPF");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::CContamination: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::CContamination:
return QLatin1String("C_KAMPF"); return QStringLiteral("C_KAMPF");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::FunctionalArea: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::FunctionalArea:
return QLatin1String("FUNKTIONS_RAUM"); return QStringLiteral("FUNKTIONS_RAUM");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::TechnicalArea: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::TechnicalArea:
return QLatin1String("FUNKTIONS_RAUM_TECHNIK"); return QStringLiteral("FUNKTIONS_RAUM_TECHNIK");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::GasPipeDetonation: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::GasPipeDetonation:
return QLatin1String("GAS_PIPE_DETONATION"); return QStringLiteral("GAS_PIPE_DETONATION");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::SpecialArea: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::SpecialArea:
return QLatin1String("SPECIAL_AREA"); return QStringLiteral("SPECIAL_AREA");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::Unknown: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::Unknown:
return QLatin1String("DUS"); return QStringLiteral("DUS");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DusSingleMineSimulator: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::DusSingleMineSimulator:
return QLatin1String("DUS_SINGLE_MINE_SIMULATOR"); return QStringLiteral("DUS_SINGLE_MINE_SIMULATOR");
case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::BeStillWarning: case TrainingAreaBase::TetraIcd::AreaEffectSimulationType::BeStillWarning:
return QLatin1String("BE_STILL_WARNING"); return QStringLiteral("BE_STILL_WARNING");
} }
return QStringLiteral("Unknown Wirkfeldtyp <%1>").arg(static_cast<int>(wirkfeldTyp)); return QStringLiteral("Unknown Wirkfeldtyp <%1>").arg(static_cast<int>(wirkfeldTyp));
} }
@@ -14,6 +14,7 @@
#pragma once #pragma once
#include <QtCore/QString> #include <QtCore/QString>
#include <QtCore/QByteArray>
#include <NGLLogger/INGLLogger.h> #include <NGLLogger/INGLLogger.h>
#include <TrainingAreaBase/training_area_telegrams.h> #include <TrainingAreaBase/training_area_telegrams.h>
#include "coprtcnv_export.h" #include "coprtcnv_export.h"
@@ -24,9 +25,10 @@ namespace N_CoPrtCnv
class CoPrtCnvRadioTelegram; class CoPrtCnvRadioTelegram;
} }
COPRTCNV_EXPORT QByteArray telegramId2String(gef_telegramm_id_et telId); // Qt6/C++17: [[nodiscard]] indicates return value should not be ignored
[[nodiscard]] COPRTCNV_EXPORT QByteArray telegramId2String(gef_telegramm_id_et telId);
COPRTCNV_EXPORT void dumpTelegram(NGL::INGLLogger &m_logger, COPRTCNV_EXPORT void dumpTelegram(NGL::INGLLogger &m_logger,
int id, int id,
N_CoPrtCnv::CoPrtCnvRadioTelegram *a_radioTelegram, N_CoPrtCnv::CoPrtCnvRadioTelegram *a_radioTelegram,
const char *prefix = nullptr); const char *prefix = nullptr);
COPRTCNV_EXPORT QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wirkfeldTyp); [[nodiscard]] COPRTCNV_EXPORT QString wirkfeldTyp2Str(TrainingAreaBase::TetraIcd::AreaEffectSimulationType wirkfeldTyp);
@@ -296,13 +296,13 @@ uint32_t CoPrtCnvRadioTelegram::getPayloadDataUInt32(size_t a_offset, uint16_t a
{ {
case 4: case 4:
ptrValue[3] = ptr[a_offset++]; ptrValue[3] = ptr[a_offset++];
Q_FALLTHROUGH(); [[fallthrough]];
case 3: case 3:
ptrValue[2] = ptr[a_offset++]; ptrValue[2] = ptr[a_offset++];
Q_FALLTHROUGH(); [[fallthrough]];
case 2: case 2:
ptrValue[1] = ptr[a_offset++]; ptrValue[1] = ptr[a_offset++];
Q_FALLTHROUGH(); [[fallthrough]];
case 1: case 1:
ptrValue[0] = ptr[a_offset++]; ptrValue[0] = ptr[a_offset++];
break; break;
@@ -949,7 +949,7 @@ bool CoPrtCnvRadioTelegram::isContentValid()
case GEF_WIRKFELD_EINZELMINENSIMULATOR: case GEF_WIRKFELD_EINZELMINENSIMULATOR:
wirkfeldkennung = getPayloadDataUInt32(5, 2); wirkfeldkennung = getPayloadDataUInt32(5, 2);
wirkfeldtyp = 3; wirkfeldtyp = 3;
Q_FALLTHROUGH(); [[fallthrough]];
case GEF_DEAKTIVIERUNG_WIRKFELD: case GEF_DEAKTIVIERUNG_WIRKFELD:
case GEF_WIRKFELD_AENDERUNG_BEZEICHNER: case GEF_WIRKFELD_AENDERUNG_BEZEICHNER:
if (GEF_DEAKTIVIERUNG_WIRKFELD == getTelID() || GEF_WIRKFELD_AENDERUNG_BEZEICHNER == getTelID()) if (GEF_DEAKTIVIERUNG_WIRKFELD == getTelID() || GEF_WIRKFELD_AENDERUNG_BEZEICHNER == getTelID())
@@ -1239,7 +1239,7 @@ bool CoPrtCnvRadioTelegram::mustBeSentAsBroadcast(time_t a_currentTime, bool& a_
break; break;
} }
++m_BroadcastCounter; ++m_BroadcastCounter;
Q_FALLTHROUGH(); [[fallthrough]];
case 1: case 1:
if (s_3rdDelay >= 0) if (s_3rdDelay >= 0)
{ {
@@ -1249,7 +1249,7 @@ bool CoPrtCnvRadioTelegram::mustBeSentAsBroadcast(time_t a_currentTime, bool& a_
break; break;
} }
++m_BroadcastCounter; ++m_BroadcastCounter;
Q_FALLTHROUGH(); [[fallthrough]];
default: default:
INFO_LOG(m_logger) << "3rd Broadcast-Telegram telId=" << getTelID() INFO_LOG(m_logger) << "3rd Broadcast-Telegram telId=" << getTelID()
<< " BC=" << getBroadcastIndex(); << " BC=" << getBroadcastIndex();
@@ -0,0 +1,20 @@
# Unit tests for the CoPrtCnv library.
# GoogleTest is resolved once in the top-level CMakeLists.txt.
add_executable(CoPrtCnvTests
${CMAKE_CURRENT_SOURCE_DIR}/../../unittest_main.cpp
CoPrtCnvRadioTelegramTest.cpp
)
target_include_directories(CoPrtCnvTests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/..
)
target_link_libraries(CoPrtCnvTests PRIVATE
CoPrtCnv
Qt6::Core
GTest::gtest
)
include(GoogleTest)
gtest_discover_tests(CoPrtCnvTests)
@@ -0,0 +1,167 @@
/**
* @file CoPrtCnvRadioTelegramTest.cpp
* @brief Unit tests for N_CoPrtCnv::CoPrtCnvRadioTelegram.
*
* Covers the constructors that build a telegram from scratch, the header
* accessors (ISSIs, telegram id, PDU type, identity) and the payload helpers.
* Payload words are stored MSB first, which several of these tests pin down.
*/
#include <gtest/gtest.h>
#include <QtCore/QByteArray>
#include "CoPrtCnvRadioTelegram.hpp"
#include "tetra_telegram_ids.h"
using N_CoPrtCnv::CoPrtCnvRadioTelegram;
TEST(CoPrtCnvRadioTelegramTest, RegisterIndCarriesSourceIssi)
{
const uint32_t sourceISSI = 0x123456;
const CoPrtCnvRadioTelegram telegram(sourceISSI);
EXPECT_EQ(telegram.getSrcISSI(), sourceISSI);
EXPECT_EQ(telegram.getPDU_Type(), CoPrtCnvRadioTelegram::e_RegisterInd);
EXPECT_EQ(telegram.getSize(), 9);
}
TEST(CoPrtCnvRadioTelegramTest, HeaderStartsWithMagicNumber)
{
const CoPrtCnvRadioTelegram telegram(1234);
ASSERT_GT(telegram.getSize(), 0);
EXPECT_EQ(static_cast<uint8_t>(telegram.data().at(0)), CoPrtCnvRadioTelegram::MAGIC_NUMBER);
}
TEST(CoPrtCnvRadioTelegramTest, SetSrcIssiOverwritesPreviousValue)
{
CoPrtCnvRadioTelegram telegram(1);
telegram.setSrcISSI(0xABCDEF);
EXPECT_EQ(telegram.getSrcISSI(), 0xABCDEFu);
telegram.setSrcISSI(0);
EXPECT_EQ(telegram.getSrcISSI(), 0u);
}
TEST(CoPrtCnvRadioTelegramTest, TelegramIdConstructorSetsIdAndIdentity)
{
const uint16_t payloadSize = 8;
const uint16_t identity = 0x0042;
const CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, payloadSize, identity);
EXPECT_EQ(telegram.getTelID(), GEF_POSITIONS_MELDUNG);
EXPECT_EQ(telegram.getIdentity(), identity);
EXPECT_EQ(telegram.getPDU_Type(), CoPrtCnvRadioTelegram::e_DataIndReq);
EXPECT_EQ(telegram.getSize(),
payloadSize + CoPrtCnvRadioTelegram::DATA_IND_REQ_HEADER_LENGTH);
}
TEST(CoPrtCnvRadioTelegramTest, TelegramIdConstructorProducesANormalTelegram)
{
const CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
EXPECT_TRUE(telegram.isNormalTelegram());
EXPECT_FALSE(telegram.isLoginTelegram());
}
TEST(CoPrtCnvRadioTelegramTest, SetIdentityIsReadBack)
{
CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
telegram.setIdentity(0x1234);
EXPECT_EQ(telegram.getIdentity(), 0x1234);
// The identity lives behind the telegram id, which must survive the write.
EXPECT_EQ(telegram.getTelID(), GEF_POSITIONS_MELDUNG);
}
TEST(CoPrtCnvRadioTelegramTest, TelegramIdIsTruncatedToASingleByte)
{
// The telegram id is written into one payload byte, so ids of 256 and above
// are stored truncated. GEF_GEFECHTSFELDTELEGRAMM (300) reads back as 44.
const CoPrtCnvRadioTelegram telegram(GEF_GEFECHTSFELDTELEGRAMM, 8, 0);
EXPECT_EQ(static_cast<int>(telegram.getTelID()), GEF_GEFECHTSFELDTELEGRAMM & 0xFF);
EXPECT_NE(static_cast<int>(telegram.getTelID()), int(GEF_GEFECHTSFELDTELEGRAMM));
}
TEST(CoPrtCnvRadioTelegramTest, PayloadWordsAreStoredMostSignificantByteFirst)
{
CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
telegram.setPayloadDataWithIndex(4, 0x00112233, 4);
EXPECT_EQ(telegram.getPayloadDataUInt32(4, 4), 0x00112233u);
EXPECT_EQ(telegram.getPayloadDataUInt8(4), 0x00);
EXPECT_EQ(telegram.getPayloadDataUInt8(5), 0x11);
EXPECT_EQ(telegram.getPayloadDataUInt8(6), 0x22);
EXPECT_EQ(telegram.getPayloadDataUInt8(7), 0x33);
}
TEST(CoPrtCnvRadioTelegramTest, PayloadDataUInt32HonoursRequestedWidth)
{
CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
telegram.setPayloadDataWithIndex(4, 0x00112233, 4);
EXPECT_EQ(telegram.getPayloadDataUInt32(4, 1), 0x00u);
EXPECT_EQ(telegram.getPayloadDataUInt32(5, 2), 0x1122u);
EXPECT_EQ(telegram.getPayloadDataUInt32(5, 3), 0x112233u);
}
TEST(CoPrtCnvRadioTelegramTest, ConstructingFromRawDataPreservesBytes)
{
const CoPrtCnvRadioTelegram source(0x00ABCD);
const QByteArray raw = source.data();
const CoPrtCnvRadioTelegram restored(raw);
EXPECT_EQ(restored.data(), raw);
EXPECT_EQ(restored.getSrcISSI(), source.getSrcISSI());
EXPECT_EQ(restored.getPDU_Type(), source.getPDU_Type());
}
TEST(CoPrtCnvRadioTelegramTest, TelegramLengthLimits)
{
EXPECT_TRUE(CoPrtCnvRadioTelegram::isTelegramLengthOk(1));
EXPECT_TRUE(CoPrtCnvRadioTelegram::isTelegramLengthOk(
CoPrtCnvRadioTelegram::MAX_RADIO_TELEGRAM_PAYLOAD_LENGTH));
EXPECT_FALSE(CoPrtCnvRadioTelegram::isTelegramLengthOk(0xFFFF));
}
TEST(CoPrtCnvRadioTelegramTest, LoginTelegramIsRecognised)
{
const CoPrtCnvRadioTelegram login(CoPrtCnvRadioTelegram::e_LoginRequest, 0x0001, 0x001234);
EXPECT_TRUE(login.isLoginTelegram());
EXPECT_FALSE(login.isNormalTelegram());
EXPECT_EQ(login.getIdentity(), 0x0001);
EXPECT_EQ(login.getDestISSI(), 0x001234u);
}
TEST(CoPrtCnvRadioTelegramTest, BroadcastIndexRoundTrips)
{
// getBroadcastIndex() only reports an index when the payload extends past
// offset 4, so the telegram needs more than five payload bytes.
CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
telegram.setBroadcastIndex(0x0107);
EXPECT_EQ(telegram.getBroadcastIndex(), 0x0107);
}
TEST(CoPrtCnvRadioTelegramTest, CounterRoundTrips)
{
CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
telegram.setZaehler(0x2A);
EXPECT_EQ(telegram.zaehler(), 0x2A);
}
TEST(CoPrtCnvRadioTelegramTest, DestIssiRoundTrips)
{
CoPrtCnvRadioTelegram telegram(GEF_POSITIONS_MELDUNG, 8, 0);
telegram.setDestISSI(0x00FEDC);
EXPECT_EQ(telegram.getDestISSI(), 0x00FEDCu);
}
@@ -65,7 +65,10 @@ SET(my_SRCS
zsksxd_tetraForLogView.x zsksxd_tetraForLogView.x
) )
QT5_ADD_RESOURCES(my_SRCS LogViewResources.qrc) # Qt6 replaces the QT5_ADD_RESOURCES macro with qt6_add_resources.
if(QT6_GUI_AVAILABLE)
qt6_add_resources(my_SRCS LogViewResources.qrc)
endif()
NGL_ADD_TOOL_ICON(my_SRCS) NGL_ADD_TOOL_ICON(my_SRCS)
NGL_ADD_EXECUTABLE(AAR SV NO_TRANSLATION LogView ${my_SRCS}) NGL_ADD_EXECUTABLE(AAR SV NO_TRANSLATION LogView ${my_SRCS})
@@ -114,3 +117,7 @@ if (TARGET LogView)
endif() endif()
endif() endif()
# Unit tests (LTS_HAVE_GTEST is set by the top-level CMakeLists.txt)
if(BUILD_TESTING AND LTS_HAVE_GTEST)
add_subdirectory(unittest)
endif()
@@ -30,7 +30,7 @@ QByteArray formatTime(quint64 t)
const quint64 secs = t >> 32; const quint64 secs = t >> 32;
const quint64 usecs = t & 0xFFFFFFFF; const quint64 usecs = t & 0xFFFFFFFF;
const quint64 msecs = usecs / 1000; const quint64 msecs = usecs / 1000;
return QDateTime::fromMSecsSinceEpoch(secs * 1000 + msecs).toString(QLatin1String("yy-MM-dd hh:mm:ss.zzz")).toUtf8(); return QDateTime::fromMSecsSinceEpoch(secs * 1000 + msecs).toString(QStringLiteral("yy-MM-dd hh:mm:ss.zzz")).toUtf8();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@@ -46,7 +46,7 @@ LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_paren
setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime)); setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime));
setDisplayFormat(QLatin1String("dd MMM yyyy hh:mm:ss")); setDisplayFormat(QStringLiteral("dd MMM yyyy hh:mm:ss"));
setCalendarPopup(true); setCalendarPopup(true);
updateToolTip(QString::number(unixTime)); updateToolTip(QString::number(unixTime));
@@ -31,7 +31,8 @@ LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, cons
m_HasContent(true), m_HasContent(true),
m_bDeleteXdr(false), m_bDeleteXdr(false),
m_Kind(a_kind), m_Kind(a_kind),
m_XdrElement(a_xdrElement) m_XdrElement(a_xdrElement),
m_logger(getLogger("LogViewField"))
{ {
} }
@@ -143,8 +144,8 @@ int64_t LogViewField::getHighestValue() const
uint16_t bitSize = 8*static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getEditSize(); uint16_t bitSize = 8*static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getEditSize();
if ((0 == m_Name.compare(QLatin1String("utm nordwert"), Qt::CaseInsensitive)) || if ((0 == m_Name.compare(QStringLiteral("utm nordwert"), Qt::CaseInsensitive)) ||
(0 == m_Name.compare(QLatin1String("utm ostwert"), Qt::CaseInsensitive))) (0 == m_Name.compare(QStringLiteral("utm ostwert"), Qt::CaseInsensitive)))
bitSize -= 8; bitSize -= 8;
switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) { switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) {
@@ -152,7 +153,7 @@ int64_t LogViewField::getHighestValue() const
return 1; return 1;
case LogViewXdrStandardType::e_Signed: case LogViewXdrStandardType::e_Signed:
bitSize--; bitSize--;
Q_FALLTHROUGH(); [[fallthrough]];
case LogViewXdrStandardType::e_Unsigned: case LogViewXdrStandardType::e_Unsigned:
case LogViewXdrStandardType::e_Data: case LogViewXdrStandardType::e_Data:
highest = highest << bitSize; highest = highest << bitSize;
@@ -228,7 +229,7 @@ QString LogViewField::makeClean(const QString &text)
{ {
QString a_uncleanText = text; QString a_uncleanText = text;
if (a_uncleanText.endsWith(QLatin1String("_rt"))) if (a_uncleanText.endsWith(QStringLiteral("_rt")))
a_uncleanText = a_uncleanText.left(a_uncleanText.length() - 3); a_uncleanText = a_uncleanText.left(a_uncleanText.length() - 3);
@@ -255,13 +256,13 @@ QString LogViewField::makeClean(const QString &text)
bool LogViewField::isDateTimeField() const bool LogViewField::isDateTimeField() const
{ {
QString name = m_Name.toLower(); QString name = m_Name.toLower();
return name == QLatin1String("gps_zeit"); return name == QStringLiteral("gps_zeit");
} }
bool LogViewField::isMSecsField() const bool LogViewField::isMSecsField() const
{ {
QString name = m_Name.toLower(); QString name = m_Name.toLower();
return (name == QLatin1String("timestamp")) || (name == QLatin1String("effectstart")); return (name == QStringLiteral("timestamp")) || (name == QStringLiteral("effectstart"));
} }
@@ -133,6 +133,8 @@ namespace N_LogView
const LogViewXdrElement *m_XdrElement; const LogViewXdrElement *m_XdrElement;
LOGGER_T m_logger;
private: private:
}; };
} }
@@ -72,8 +72,9 @@ LogViewGui::LogViewGui(QWidget* a_parent)
, m_InjectionThread(nullptr) , m_InjectionThread(nullptr)
, m_replayTimer(new QTimer(this)) , m_replayTimer(new QTimer(this))
, m_currentReplayRow(-1) , m_currentReplayRow(-1)
, m_logger(getLogger("LogViewGui"))
{ {
setWindowIcon(QIcon(QLatin1String(":icons/16x16/rde_16x16.png"))); setWindowIcon(QIcon(QStringLiteral(":icons/16x16/rde_16x16.png")));
QSettings settings; QSettings settings;
settings.beginGroup(WINDOW_GROUP); settings.beginGroup(WINDOW_GROUP);
@@ -96,7 +97,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
QString tipText; QString tipText;
QAction* action = new QAction(tr("Neue Log-Datei"), this); QAction* action = new QAction(tr("Neue Log-Datei"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/document-new.png"))); action->setIcon(QIcon(QStringLiteral(":icons/16x16/document-new.png")));
action->setShortcut(tr("Ctrl+N")); action->setShortcut(tr("Ctrl+N"));
tipText = tr("Eine neue Telegram-Log-Datei anzeigen (Ctrl-N)"); tipText = tr("Eine neue Telegram-Log-Datei anzeigen (Ctrl-N)");
action->setStatusTip(tipText); action->setStatusTip(tipText);
@@ -105,7 +106,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
toolBar->addAction(action); toolBar->addAction(action);
action = new QAction(tr("Log-Datei hinzu"), this); action = new QAction(tr("Log-Datei hinzu"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/document-import.png"))); action->setIcon(QIcon(QStringLiteral(":icons/16x16/document-import.png")));
action->setShortcut(tr("Ctrl+O")); action->setShortcut(tr("Ctrl+O"));
tipText = tr("Eine weitere Telegramm-Log-Datei anzeigen (Ctrl-O)"); tipText = tr("Eine weitere Telegramm-Log-Datei anzeigen (Ctrl-O)");
action->setStatusTip(tipText); action->setStatusTip(tipText);
@@ -116,7 +117,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_reloadAction = new QAction(tr("&Reload"), this); m_reloadAction = new QAction(tr("&Reload"), this);
m_reloadAction->setCheckable(true); m_reloadAction->setCheckable(true);
m_reloadAction->setChecked(m_DoReload); m_reloadAction->setChecked(m_DoReload);
m_reloadAction->setIcon(QIcon(QLatin1String(":icons/16x16/edit-redo.png"))); m_reloadAction->setIcon(QIcon(QStringLiteral(":icons/16x16/edit-redo.png")));
m_reloadAction->setShortcut(tr("Ctrl+R")); m_reloadAction->setShortcut(tr("Ctrl+R"));
tipText = tr("Reload des Logfiles ein-/ausschalten (Ctrl-R)"); tipText = tr("Reload des Logfiles ein-/ausschalten (Ctrl-R)");
m_reloadAction->setStatusTip(tipText); m_reloadAction->setStatusTip(tipText);
@@ -125,7 +126,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
toolBar->addAction(m_reloadAction); toolBar->addAction(m_reloadAction);
action = new QAction(tr("&Einstellungen"), this); action = new QAction(tr("&Einstellungen"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/configure.png"))); action->setIcon(QIcon(QStringLiteral(":icons/16x16/configure.png")));
action->setShortcut(tr("Ctrl+E")); action->setShortcut(tr("Ctrl+E"));
tipText = tr("Verhalten des Programmes einstellen (Ctrl-E)"); tipText = tr("Verhalten des Programmes einstellen (Ctrl-E)");
action->setStatusTip(tipText); action->setStatusTip(tipText);
@@ -135,7 +136,7 @@ LogViewGui::LogViewGui(QWidget* a_parent)
toolBar->addSeparator(); toolBar->addSeparator();
action = new QAction(tr("&Beenden"), this); action = new QAction(tr("&Beenden"), this);
action->setIcon(QIcon(QLatin1String(":icons/16x16/edit-delete.png"))); action->setIcon(QIcon(QStringLiteral(":icons/16x16/edit-delete.png")));
action->setShortcut(tr("Alt-F4")); action->setShortcut(tr("Alt-F4"));
tipText = tr("LogView beenden (Alt-F4)"); tipText = tr("LogView beenden (Alt-F4)");
action->setStatusTip(tipText); action->setStatusTip(tipText);
@@ -176,11 +177,11 @@ LogViewGui::LogViewGui(QWidget* a_parent)
m_ToolBox = new QToolBox(this); m_ToolBox = new QToolBox(this);
m_ToolBox->addItem(m_CentralSelectionGroup, QIcon(QLatin1String(":/image/Central.png")), tr("&Zentral-Telegramm-Filter")); m_ToolBox->addItem(m_CentralSelectionGroup, QIcon(QStringLiteral(":/image/Central.png")), tr("&Zentral-Telegramm-Filter"));
m_ToolBox->addItem(m_TetraSelectionGroup, QIcon(QLatin1String(":/image/Tetra.png")), tr("TET&RA-Telegramm-Filter")); m_ToolBox->addItem(m_TetraSelectionGroup, QIcon(QStringLiteral(":/image/Tetra.png")), tr("TET&RA-Telegramm-Filter"));
m_ToolBox->addItem(m_WlsSelectionGroup, QIcon(QLatin1String(":/image/Wls.png")), tr("&WLS-Telegramm-Filter")); m_ToolBox->addItem(m_WlsSelectionGroup, QIcon(QStringLiteral(":/image/Wls.png")), tr("&WLS-Telegramm-Filter"));
m_ToolBox->addItem(m_ParticipantSelectionGroup, QIcon(QLatin1String(":/image/TNE.png")), tr("Teilnehmer-&Filter")); m_ToolBox->addItem(m_ParticipantSelectionGroup, QIcon(QStringLiteral(":/image/TNE.png")), tr("Teilnehmer-&Filter"));
m_ToolBox->addItem(m_EditTelegramController->tableView(), QIcon(QLatin1String(":icons/16x16/document-edit.png")), tr("&Edit && Sende Telegramme")); m_ToolBox->addItem(m_EditTelegramController->tableView(), QIcon(QStringLiteral(":icons/16x16/document-edit.png")), tr("&Edit && Sende Telegramme"));
m_ToolBox->setCurrentIndex(settings.value(TOOLBOXINDEX).toInt()); m_ToolBox->setCurrentIndex(settings.value(TOOLBOXINDEX).toInt());
@@ -273,13 +274,13 @@ LogViewGui::LogViewGui(QWidget* a_parent)
void LogViewGui::createCentralSelectionWidget() void LogViewGui::createCentralSelectionWidget()
{ {
m_SentCentralTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/P2C.png")); m_SentCentralTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QStringLiteral(":/image/P2C.png"));
m_ReceivedCentralTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/C2P.png")); m_ReceivedCentralTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QStringLiteral(":/image/C2P.png"));
m_PosCentralTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/CentralPos.png")); m_PosCentralTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QStringLiteral(":/image/CentralPos.png"));
m_ackCentralTelCheckBox = createRadioButton(tr("&Bestaetigungstelegramme"), QLatin1String(":/image/CentralAck.png")); m_ackCentralTelCheckBox = createRadioButton(tr("&Bestaetigungstelegramme"), QStringLiteral(":/image/CentralAck.png"));
QVBoxLayout* centralFilterBox = new QVBoxLayout; QVBoxLayout* centralFilterBox = new QVBoxLayout;
centralFilterBox->addWidget(m_SentCentralTelCheckBox); centralFilterBox->addWidget(m_SentCentralTelCheckBox);
@@ -298,21 +299,21 @@ void LogViewGui::createCentralSelectionWidget()
void LogViewGui::createTetraSelectionWidget() void LogViewGui::createTetraSelectionWidget()
{ {
m_SentTetraTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/T2P.png")); m_SentTetraTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QStringLiteral(":/image/T2P.png"));
m_ReceivedTetraTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/P2T.png")); m_ReceivedTetraTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QStringLiteral(":/image/P2T.png"));
m_PosTetraTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/TetraPos.png")); m_PosTetraTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QStringLiteral(":/image/TetraPos.png"));
m_FragmentedTetraTelCheckBox = createRadioButton(tr("&Fragmentierte Meldungen"), QLatin1String(":/image/TetraFragmented.png")); m_FragmentedTetraTelCheckBox = createRadioButton(tr("&Fragmentierte Meldungen"), QStringLiteral(":/image/TetraFragmented.png"));
m_LoginTetraTelCheckBox = createRadioButton(tr("&Loginmeldungen"), QLatin1String(":/image/TetraLogin.png")); m_LoginTetraTelCheckBox = createRadioButton(tr("&Loginmeldungen"), QStringLiteral(":/image/TetraLogin.png"));
m_RegisterTetraTelCheckBox = createRadioButton(tr("&Registermeldungen"), QLatin1String(":/image/TetraRegister.png")); m_RegisterTetraTelCheckBox = createRadioButton(tr("&Registermeldungen"), QStringLiteral(":/image/TetraRegister.png"));
m_ReportTetraTelCheckBox = createRadioButton(tr("&Reportmeldungen"), QLatin1String(":/image/TetraReport.png")); m_ReportTetraTelCheckBox = createRadioButton(tr("&Reportmeldungen"), QStringLiteral(":/image/TetraReport.png"));
m_AirInterfaceLoadTetraTelCheckBox = createRadioButton(tr("&Air-Load Meldungen"), QLatin1String(":/image/TetraAirInterface.png")); m_AirInterfaceLoadTetraTelCheckBox = createRadioButton(tr("&Air-Load Meldungen"), QStringLiteral(":/image/TetraAirInterface.png"));
QVBoxLayout* tetraFilterBox = new QVBoxLayout; QVBoxLayout* tetraFilterBox = new QVBoxLayout;
tetraFilterBox->addWidget(m_SentTetraTelCheckBox); tetraFilterBox->addWidget(m_SentTetraTelCheckBox);
@@ -335,11 +336,11 @@ void LogViewGui::createTetraSelectionWidget()
void LogViewGui::createWlsSelectionWidget() void LogViewGui::createWlsSelectionWidget()
{ {
m_SentWlsTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QLatin1String(":/image/P2W.png")); m_SentWlsTelCheckBox = createRadioButton(tr("&gesendete Telegramme"), QStringLiteral(":/image/P2W.png"));
m_ReceivedWlsTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QLatin1String(":/image/W2P.png")); m_ReceivedWlsTelCheckBox = createRadioButton(tr("&empfangene Telegramme"), QStringLiteral(":/image/W2P.png"));
m_PosWlsTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QLatin1String(":/image/WlsPos.png")); m_PosWlsTelCheckBox = createRadioButton(tr("&Positionsmeldungen"), QStringLiteral(":/image/WlsPos.png"));
QVBoxLayout* wlsFilterBox = new QVBoxLayout; QVBoxLayout* wlsFilterBox = new QVBoxLayout;
wlsFilterBox->addWidget(m_SentWlsTelCheckBox); wlsFilterBox->addWidget(m_SentWlsTelCheckBox);
@@ -405,7 +406,7 @@ void LogViewGui::showHexData()
void LogViewGui::exportAsCsv() void LogViewGui::exportAsCsv()
{ {
const int idx = m_ActualLogfile.lastIndexOf(QLatin1Char('.')); const int idx = m_ActualLogfile.lastIndexOf(QLatin1Char('.'));
const QString suggestion = m_ActualLogfile.left(idx) + QLatin1String(".csv"); const QString suggestion = m_ActualLogfile.left(idx) + QStringLiteral(".csv");
const QString fn = QFileDialog::getSaveFileName(this, tr("Export logdata as CSV"), suggestion, tr("CSV file (*.csv)")); const QString fn = QFileDialog::getSaveFileName(this, tr("Export logdata as CSV"), suggestion, tr("CSV file (*.csv)"));
if (fn.isEmpty()) if (fn.isEmpty())
return; return;
@@ -445,7 +446,7 @@ void LogViewGui::exportAsCsv()
void LogViewGui::exportAsJson() void LogViewGui::exportAsJson()
{ {
const int idx = m_ActualLogfile.lastIndexOf(QLatin1Char('.')); const int idx = m_ActualLogfile.lastIndexOf(QLatin1Char('.'));
const QString suggestion = m_ActualLogfile.left(idx) + QLatin1String(".csv"); const QString suggestion = m_ActualLogfile.left(idx) + QStringLiteral(".csv");
const QString fn = QFileDialog::getSaveFileName(this, tr("Export logdata as Json"), suggestion, tr("JSon file (*.json)")); const QString fn = QFileDialog::getSaveFileName(this, tr("Export logdata as Json"), suggestion, tr("JSon file (*.json)"));
if (fn.isEmpty()) if (fn.isEmpty())
return; return;
@@ -542,7 +543,7 @@ void LogViewGui::loadSpecificationFiles()
settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP); settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
QString defString = QCoreApplication::applicationDirPath() + QLatin1String("/training_area_telegrams.h"); QString defString = QCoreApplication::applicationDirPath() + QStringLiteral("/training_area_telegrams.h");
QString filename = settings.value(LogViewOptionDialog::P0_FILENAME, defString).toString(); QString filename = settings.value(LogViewOptionDialog::P0_FILENAME, defString).toString();
INFO_LOG(m_logger) << "Load central-protocol spezification-file: " << filename.toStdString(); INFO_LOG(m_logger) << "Load central-protocol spezification-file: " << filename.toStdString();
if (!QFile::exists(filename)) if (!QFile::exists(filename))
@@ -553,7 +554,7 @@ void LogViewGui::loadSpecificationFiles()
LogViewTelegram::jsonParser()->parse(filename); LogViewTelegram::jsonParser()->parse(filename);
defString = QCoreApplication::applicationDirPath() + QLatin1String("/zsksxd_tetraForLogView.x"); defString = QCoreApplication::applicationDirPath() + QStringLiteral("/zsksxd_tetraForLogView.x");
filename = settings.value(LogViewOptionDialog::P5_FILENAME, defString).toString(); filename = settings.value(LogViewOptionDialog::P5_FILENAME, defString).toString();
INFO_LOG(m_logger) << "Load tetra-protocol spezification-file: " << filename.toStdString(); INFO_LOG(m_logger) << "Load tetra-protocol spezification-file: " << filename.toStdString();
if (!QFile::exists(filename)) if (!QFile::exists(filename))
@@ -589,7 +590,7 @@ void LogViewGui::loadTelegramFile()
{ {
const QLatin1String DIR("Dir"); const QLatin1String DIR("Dir");
QSettings settings; QSettings settings;
settings.beginGroup(QLatin1String("LogFiles")); settings.beginGroup(QStringLiteral("LogFiles"));
QString filename = QFileDialog::getOpenFileName(this, tr("Bitte eine Log-Datei auswaehlen"), settings.value(DIR).toString(), LogViewOptionDialog::KRLOG_FILES); QString filename = QFileDialog::getOpenFileName(this, tr("Bitte eine Log-Datei auswaehlen"), settings.value(DIR).toString(), LogViewOptionDialog::KRLOG_FILES);
if (filename.isEmpty()) if (filename.isEmpty())
@@ -655,7 +656,7 @@ void LogViewGui::updateLogfile()
QString filePath(fileInfo.absolutePath() + QLatin1Char('/')); QString filePath(fileInfo.absolutePath() + QLatin1Char('/'));
const QString baseName = fileInfo.baseName(); const QString baseName = fileInfo.baseName();
const QVector<QStringRef> parts = baseName.splitRef(QLatin1Char('_')); const QList<QStringView> parts = QStringView(baseName).split(QLatin1Char('_'));
for (int iterator = 0; iterator < parts.size() - 2; ++iterator) for (int iterator = 0; iterator < parts.size() - 2; ++iterator)
filePath += parts.at(iterator).toString() + QLatin1Char('_'); filePath += parts.at(iterator).toString() + QLatin1Char('_');
@@ -909,19 +910,19 @@ void LogViewGui::startInjectionThread()
m_InjectionThread = new LogViewInjectionThread(); m_InjectionThread = new LogViewInjectionThread();
QSettings settings; QSettings settings;
settings.beginGroup(QLatin1String("LogFiles")); settings.beginGroup(QStringLiteral("LogFiles"));
QString filePath = settings.value(QLatin1String("Dir")).toString(); QString filePath = settings.value(QStringLiteral("Dir")).toString();
QString exerciseName; QString exerciseName;
QVector<QStringRef> parts = filePath.splitRef(QLatin1Char('/')); const QList<QStringView> parts = QStringView(filePath).split(QLatin1Char('/'));
if (parts.size() >= 2) if (parts.size() >= 2)
exerciseName = QLatin1Char('_') + parts.at(parts.size() - 2).toString(); exerciseName = QLatin1Char('_') + parts.at(parts.size() - 2).toString();
QString portFilePath = QCoreApplication::applicationDirPath() + QDir::separator() + QLatin1String("PrtCnv") + exerciseName + QLatin1String(".dat"); QString portFilePath = QCoreApplication::applicationDirPath() + QDir::separator() + QStringLiteral("PrtCnv") + exerciseName + QStringLiteral(".dat");
QFileInfo checkPortFile(portFilePath); QFileInfo checkPortFile(portFilePath);
if(checkPortFile.exists() && checkPortFile.isFile()) if(checkPortFile.exists() && checkPortFile.isFile())
{ {
QSettings portSetting(portFilePath, QSettings::IniFormat); QSettings portSetting(portFilePath, QSettings::IniFormat);
m_InjectionThread->setPort(portSetting.value(QLatin1String("Injection/Port")).toInt()); m_InjectionThread->setPort(portSetting.value(QStringLiteral("Injection/Port")).toInt());
} }
m_EditTelegramController->setInjectionThread(m_InjectionThread); m_EditTelegramController->setInjectionThread(m_InjectionThread);
@@ -182,6 +182,9 @@ protected slots:
private slots: private slots:
void onSettingsChanged(uint32_t changedFlags); void onSettingsChanged(uint32_t changedFlags);
private:
LOGGER_T m_logger;
}; };
} }
@@ -28,6 +28,7 @@ LogViewInjectionThread::LogViewInjectionThread()
, m_SendingPossible(false) , m_SendingPossible(false)
, m_Socket(nullptr) , m_Socket(nullptr)
, m_Timer(nullptr) , m_Timer(nullptr)
, m_logger(getLogger("LogViewInjectionThread"))
{ {
QSettings settings; QSettings settings;
@@ -36,7 +37,7 @@ LogViewInjectionThread::LogViewInjectionThread()
if (m_Hostname.isEmpty()) if (m_Hostname.isEmpty())
{ {
m_Hostname = QLatin1String("localhost"); m_Hostname = QStringLiteral("localhost");
settings.setValue(LogViewOptionDialog::INJECTION_HOSTNAME, m_Hostname); settings.setValue(LogViewOptionDialog::INJECTION_HOSTNAME, m_Hostname);
} }
m_Port = settings.value(LogViewOptionDialog::INJECTION_PORT).toInt(); m_Port = settings.value(LogViewOptionDialog::INJECTION_PORT).toInt();
@@ -50,7 +51,7 @@ LogViewInjectionThread::LogViewInjectionThread()
void LogViewInjectionThread::run() void LogViewInjectionThread::run()
{ {
emit updateStatus(QLatin1String(":/image/RedLamp.png"), emit updateStatus(QStringLiteral(":/image/RedLamp.png"),
tr("LogView ist nicht mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port)); tr("LogView ist nicht mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
QTimer::singleShot(100, this, &LogViewInjectionThread::tryToConnect); QTimer::singleShot(100, this, &LogViewInjectionThread::tryToConnect);
@@ -106,7 +107,7 @@ void LogViewInjectionThread::doConnect()
INFO_LOG(m_logger) << "LogView has successful connected to injection-server of TETRA-If"; INFO_LOG(m_logger) << "LogView has successful connected to injection-server of TETRA-If";
m_SendingPossible = true; m_SendingPossible = true;
m_Timer->stop(); m_Timer->stop();
emit updateStatus(QLatin1String(":/image/GreenLamp.png"), emit updateStatus(QStringLiteral(":/image/GreenLamp.png"),
tr("LogView ist mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port)); tr("LogView ist mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
} }
@@ -116,7 +117,7 @@ void LogViewInjectionThread::doDisconnect()
{ {
INFO_LOG(m_logger) << "LogView was disconnected from injection-server of TETRA-If"; INFO_LOG(m_logger) << "LogView was disconnected from injection-server of TETRA-If";
m_SendingPossible = false; m_SendingPossible = false;
emit updateStatus(QLatin1String(":/image/RedLamp.png"), emit updateStatus(QStringLiteral(":/image/RedLamp.png"),
tr("LogView ist nicht mehr mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port)); tr("LogView ist nicht mehr mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
tryToConnect(); tryToConnect();
} }
@@ -70,6 +70,8 @@ namespace N_LogView
void updateStatus(const QString& a_picName, const QString& a_toolTipText); void updateStatus(const QString& a_picName, const QString& a_toolTipText);
protected:
LOGGER_T m_logger;
}; };
} }
@@ -1,5 +1,6 @@
#include <nglapplication/nglapplication.h> #include <nglapplication/nglapplication.h>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtCore/QSettings> #include <QtCore/QSettings>
#include <QNetworkProxy> #include <QNetworkProxy>
#ifndef WIN32 #ifndef WIN32
@@ -39,8 +40,8 @@ int main(int argc, char *argv[])
QNetworkProxy::setApplicationProxy(QNetworkProxy()); QNetworkProxy::setApplicationProxy(QNetworkProxy());
app.createLogger("LogView", logConfigFileName.c_str()); app.createLogger("LogView", logConfigFileName.c_str());
QCoreApplication::setOrganizationName(QLatin1String("RME")); QCoreApplication::setOrganizationName(QStringLiteral("RME"));
QCoreApplication::setApplicationName(QLatin1String("LogView")); QCoreApplication::setApplicationName(QStringLiteral("LogView"));
QSettings settings; QSettings settings;
settings.beginGroup(N_LogView::LogViewGui::WINDOW_GROUP); settings.beginGroup(N_LogView::LogViewGui::WINDOW_GROUP);
@@ -48,7 +49,12 @@ int main(int argc, char *argv[])
settings.endGroup(); settings.endGroup();
QScreen *screen = QGuiApplication::screens().value(screenNbr, QGuiApplication::primaryScreen()); QScreen *screen = QGuiApplication::screens().value(screenNbr, QGuiApplication::primaryScreen());
N_LogView::LogViewGui* logViewGui = new N_LogView::LogViewGui(screen); N_LogView::LogViewGui* logViewGui = new N_LogView::LogViewGui(nullptr);
// A QScreen is not a QWidget in Qt6, so the target screen can no longer be passed as the
// parent widget. Create the native window first, then assign it to the requested screen.
logViewGui->winId();
if (screen && logViewGui->windowHandle())
logViewGui->windowHandle()->setScreen(screen);
logViewGui->show(); logViewGui->show();
int ret = app.exec(); int ret = app.exec();
@@ -55,7 +55,7 @@ QVariant ParticipantModel::data(const QModelIndex &index, int role) const
break; break;
} }
} }
if (role == Qt::BackgroundColorRole) if (role == Qt::BackgroundRole)
{ {
if (p.first == 0) if (p.first == 0)
return QVariant(); return QVariant();
@@ -3,7 +3,7 @@
#pragma once #pragma once
#include <QtGui/QAbstractTableModel> #include <QtCore/QAbstractTableModel>
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#include <QtCore/QSortFilterProxyModel> #include <QtCore/QSortFilterProxyModel>
#include <set> #include <set>
@@ -59,7 +59,7 @@ LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
QLabel* p0Label = new QLabel(tr("&Zentrale - Protokollkonverter"), this); QLabel* p0Label = new QLabel(tr("&Zentrale - Protokollkonverter"), this);
groupLayout->addWidget(p0Label, 0, 0, 1, 2); groupLayout->addWidget(p0Label, 0, 0, 1, 2);
QString defString = QCoreApplication::applicationDirPath() + QLatin1String("/training_area_telegrams.h"); QString defString = QCoreApplication::applicationDirPath() + QStringLiteral("/training_area_telegrams.h");
m_P0Edit = new QLineEdit(m_Settings.value(P0_FILENAME, defString).toString(), this); m_P0Edit = new QLineEdit(m_Settings.value(P0_FILENAME, defString).toString(), this);
m_P0Edit->setMinimumWidth(400); m_P0Edit->setMinimumWidth(400);
groupLayout->addWidget(m_P0Edit); groupLayout->addWidget(m_P0Edit);
@@ -70,7 +70,7 @@ LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
QLabel* p5Label = new QLabel(tr("Protokollkonverter - &TETRA"), this); QLabel* p5Label = new QLabel(tr("Protokollkonverter - &TETRA"), this);
groupLayout->addWidget(p5Label, 2, 0, 1, 2); groupLayout->addWidget(p5Label, 2, 0, 1, 2);
defString = QCoreApplication::applicationDirPath() + QLatin1String("/zsksxd_tetraForLogView.x"); defString = QCoreApplication::applicationDirPath() + QStringLiteral("/zsksxd_tetraForLogView.x");
m_P5Edit = new QLineEdit(m_Settings.value(P5_FILENAME, defString).toString(), this); m_P5Edit = new QLineEdit(m_Settings.value(P5_FILENAME, defString).toString(), this);
groupLayout->addWidget(m_P5Edit); groupLayout->addWidget(m_P5Edit);
QPushButton* p5Browse = new QPushButton(tr("Browse"), this); QPushButton* p5Browse = new QPushButton(tr("Browse"), this);
@@ -88,7 +88,7 @@ void LogViewTableWidget::changeSize(const int a_newSize)
this, &LogViewTableWidget::checkAndOvertakeContent); this, &LogViewTableWidget::checkAndOvertakeContent);
for (int i = 0; i < a_newSize; i++) for (int i = 0; i < a_newSize; i++)
changeRow(i, QLatin1String("0")); changeRow(i, QStringLiteral("0"));
connect(this, &LogViewTableWidget::itemChanged, connect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent); this, &LogViewTableWidget::checkAndOvertakeContent);
@@ -73,6 +73,7 @@ LogViewTelegram::LogViewTelegram(const LogViewTelegram &o)
, m_data(o.m_data) , m_data(o.m_data)
, m_json(o.m_json) , m_json(o.m_json)
, m_TetraTelegram(nullptr) , m_TetraTelegram(nullptr)
, m_logger(getLogger("LogViewTelegram"))
{ {
if (!m_data.isEmpty()) if (!m_data.isEmpty())
m_TetraTelegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(m_data); m_TetraTelegram = new N_CoPrtCnv::CoPrtCnvRadioTelegram(m_data);
@@ -100,6 +101,7 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv
, m_LogTime(0) , m_LogTime(0)
, m_GpsTime(0) , m_GpsTime(0)
, m_TetraTelegram(nullptr) , m_TetraTelegram(nullptr)
, m_logger(getLogger("LogViewTelegram"))
{ {
const uint32_t &waitTime = qgetenv("LogViewWaitTime").toUInt(); const uint32_t &waitTime = qgetenv("LogViewWaitTime").toUInt();
if (waitTime > 0) if (waitTime > 0)
@@ -143,6 +145,7 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv
, m_GpsTime(0) , m_GpsTime(0)
, m_data(a_telegramData) , m_data(a_telegramData)
, m_TetraTelegram(nullptr) , m_TetraTelegram(nullptr)
, m_logger(getLogger("LogViewTelegram"))
{ {
const uint32_t &waitTime = qgetenv("LogViewWaitTime").toUInt(); const uint32_t &waitTime = qgetenv("LogViewWaitTime").toUInt();
if (waitTime > 0) if (waitTime > 0)
@@ -155,10 +158,10 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls:
{ {
m_json = QJsonDocument::fromJson(a_telegramData).object(); m_json = QJsonDocument::fromJson(a_telegramData).object();
m_TelId = m_json.value(QLatin1String("typeId")).toInt(); m_TelId = m_json.value(QStringLiteral("typeId")).toInt();
m_Name = m_json.value(QLatin1String("type")).toString(); m_Name = m_json.value(QStringLiteral("type")).toString();
switch (getTelId()) switch (getTelId())
{ {
case TrainingAreaBase::TetraIcd::BESTAETIGUNG: case TrainingAreaBase::TetraIcd::BESTAETIGUNG:
@@ -167,9 +170,9 @@ LogViewTelegram::LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnv
m_ParticipantId = m_json.value(QLatin1String("data")) m_ParticipantId = m_json.value(QStringLiteral("data"))
.toObject().value(QLatin1String("header")) .toObject().value(QStringLiteral("header"))
.toObject().value(QLatin1String("equipmentNumber")).toInt(); .toObject().value(QStringLiteral("equipmentNumber")).toInt();
break; break;
} }
break; break;
@@ -356,7 +359,7 @@ QString LogViewTelegram::getLogTimeText() const
if (m_logTimeText.isEmpty()) if (m_logTimeText.isEmpty())
{ {
const QDateTime dt(QDateTime::fromMSecsSinceEpoch(getLogTimeMsec())); const QDateTime dt(QDateTime::fromMSecsSinceEpoch(getLogTimeMsec()));
m_logTimeText = dt.toString(QLatin1String("ddd, MMM dd, yyyy hh:mm:ss.zzz")); m_logTimeText = dt.toString(QStringLiteral("ddd, MMM dd, yyyy hh:mm:ss.zzz"));
} }
return m_logTimeText; return m_logTimeText;
} }
@@ -373,9 +376,9 @@ QString LogViewTelegram::getDestinationText() const
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral: { case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral: {
switch (dest) { switch (dest) {
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive:
return QLatin1String("C > P"); return QStringLiteral("C > P");
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend:
return QLatin1String("P > C"); return QStringLiteral("P > C");
default: default:
break; break;
} }
@@ -384,9 +387,9 @@ QString LogViewTelegram::getDestinationText() const
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls: { case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls: {
switch (dest) { switch (dest) {
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive:
return QLatin1String("W > C"); return QStringLiteral("W > C");
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend:
return QLatin1String("C > W"); return QStringLiteral("C > W");
default: default:
break; break;
} }
@@ -395,9 +398,9 @@ QString LogViewTelegram::getDestinationText() const
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra: { case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra: {
switch (dest) { switch (dest) {
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestReceive:
return QLatin1String("P > T"); return QStringLiteral("P > T");
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend: case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend:
return QLatin1String("T > P"); return QStringLiteral("T > P");
default: default:
break; break;
} }
@@ -418,7 +421,7 @@ QString LogViewTelegram::getDestinationText() const
QString LogViewTelegram::getGpsTimeText() const QString LogViewTelegram::getGpsTimeText() const
{ {
if (m_GpsTime != 0) if (m_GpsTime != 0)
return QDateTime::fromMSecsSinceEpoch(m_GpsTime * 1000LL).toString(QLatin1String("hh:mm:ss")); return QDateTime::fromMSecsSinceEpoch(m_GpsTime * 1000LL).toString(QStringLiteral("hh:mm:ss"));
return QString(); return QString();
} }
@@ -462,11 +465,11 @@ QString LogViewTelegram::getToolTipText(const E_Column a_col)
} }
if(a_col == e_ColGpsTime && m_ToolTipText[e_ColGpsTime].isNull()) { if(a_col == e_ColGpsTime && m_ToolTipText[e_ColGpsTime].isNull()) {
if(m_GpsTime == 0) { if(m_GpsTime == 0) {
m_ToolTipText[e_ColGpsTime] = QLatin1String(""); m_ToolTipText[e_ColGpsTime] = QStringLiteral("");
} else { } else {
const QDateTime dtGpsTime(QDateTime::fromMSecsSinceEpoch(m_GpsTime * 1000LL)); const QDateTime dtGpsTime(QDateTime::fromMSecsSinceEpoch(m_GpsTime * 1000LL));
m_ToolTipText[e_ColGpsTime] = QStringLiteral("%1<br><nobr>Unixzeit: %2 <b>0x%3</b></nobr>") m_ToolTipText[e_ColGpsTime] = QStringLiteral("%1<br><nobr>Unixzeit: %2 <b>0x%3</b></nobr>")
.arg(dtGpsTime.toString(QLatin1String("ddd, MMM dd, yyyy hh:mm:ss"))) .arg(dtGpsTime.toString(QStringLiteral("ddd, MMM dd, yyyy hh:mm:ss")))
.arg(m_GpsTime) .arg(m_GpsTime)
.arg(m_GpsTime, 8, 16, QLatin1Char('0')); .arg(m_GpsTime, 8, 16, QLatin1Char('0'));
} }
@@ -487,12 +490,12 @@ void LogViewTelegram::createToolTipTextForColName()
{ {
const QString jsonStr = QString::fromUtf8(QJsonDocument(m_json).toJson(QJsonDocument::JsonFormat::Indented)); const QString jsonStr = QString::fromUtf8(QJsonDocument(m_json).toJson(QJsonDocument::JsonFormat::Indented));
m_ToolTipText[e_ColName] = QLatin1String("<table>") m_ToolTipText[e_ColName] = QStringLiteral("<table>")
+ formatToolTipLine(QObject::tr("Telegram Id"), getTelId()) + formatToolTipLine(QObject::tr("Telegram Id"), getTelId())
+ formatToolTipLine(QObject::tr("Counter"), getUInt32(POS_CENTRAL_COUNTER)) + formatToolTipLine(QObject::tr("Counter"), getUInt32(POS_CENTRAL_COUNTER))
+ formatToolTipLine(QObject::tr("Size"), m_data.size()) + formatToolTipLine(QObject::tr("Size"), m_data.size())
+ formatToolTipLine(QObject::tr("Json Data"), jsonStr, jsonStr.size()) + formatToolTipLine(QObject::tr("Json Data"), jsonStr, jsonStr.size())
+ QLatin1String("</table>"); + QStringLiteral("</table>");
break; break;
} }
@@ -502,26 +505,26 @@ void LogViewTelegram::createToolTipTextForColName()
{ {
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd:
m_ToolTipText[e_ColName] = QLatin1String("<table>") m_ToolTipText[e_ColName] = QStringLiteral("<table>")
+ formatToolTipLine(QObject::tr("Host ISSI"), m_TetraTelegram->getSrcISSI()) + formatToolTipLine(QObject::tr("Host ISSI"), m_TetraTelegram->getSrcISSI())
+ formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler()) + formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler())
+ formatToolTipLine(QObject::tr("Size"), m_data.size()) + formatToolTipLine(QObject::tr("Size"), m_data.size())
+ QLatin1String("</table>"); + QStringLiteral("</table>");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp:
m_ToolTipText[e_ColName] = QLatin1String("<table>") m_ToolTipText[e_ColName] = QStringLiteral("<table>")
+ formatToolTipLine(QObject::tr("Registration Status"), m_TetraTelegram->getRegistrationStatusAsText(), m_TetraTelegram->getRegistrationStatus()) + formatToolTipLine(QObject::tr("Registration Status"), m_TetraTelegram->getRegistrationStatusAsText(), m_TetraTelegram->getRegistrationStatus())
+ formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler()) + formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler())
+ formatToolTipLine(QObject::tr("Size"), m_data.size()) + formatToolTipLine(QObject::tr("Size"), m_data.size())
+ QLatin1String("</table>"); + QStringLiteral("</table>");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq: { case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq: {
int frameSize = 1; int frameSize = 1;
if(m_TetraTelegram->getWithCrc()) if(m_TetraTelegram->getWithCrc())
frameSize += 2; frameSize += 2;
m_ToolTipText[e_ColName] = QLatin1String("<table>") m_ToolTipText[e_ColName] = QStringLiteral("<table>")
+ formatToolTipLine(QObject::tr("Source ISSI"), m_TetraTelegram->getSrcISSI()) + formatToolTipLine(QObject::tr("Source ISSI"), m_TetraTelegram->getSrcISSI())
+ formatToolTipLine(QObject::tr("Destination ISSI"), m_TetraTelegram->getDestISSI()) + formatToolTipLine(QObject::tr("Destination ISSI"), m_TetraTelegram->getDestISSI())
+ formatToolTipLine(QObject::tr("Protocol Identifier"), m_TetraTelegram->getProtocolIdentifierAsText(), m_TetraTelegram->getProtocolIdentifier()) + formatToolTipLine(QObject::tr("Protocol Identifier"), m_TetraTelegram->getProtocolIdentifierAsText(), m_TetraTelegram->getProtocolIdentifier())
@@ -534,12 +537,12 @@ void LogViewTelegram::createToolTipTextForColName()
+ formatToolTipLine(QObject::tr("Real Payload in Bytes"), m_TetraTelegram->getLengthInBytes() - frameSize) + formatToolTipLine(QObject::tr("Real Payload in Bytes"), m_TetraTelegram->getLengthInBytes() - frameSize)
+ formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler()) + formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler())
+ formatToolTipLine(QObject::tr("Size"), m_data.size()) + formatToolTipLine(QObject::tr("Size"), m_data.size())
+ QLatin1String("</table>"); + QStringLiteral("</table>");
break; break;
} }
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_ReportIndReq: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_ReportIndReq:
m_ToolTipText[e_ColName] = QLatin1String("<table>") m_ToolTipText[e_ColName] = QStringLiteral("<table>")
+ formatToolTipLine(QObject::tr("Source ISSI"), m_TetraTelegram->getSrcISSI()) + formatToolTipLine(QObject::tr("Source ISSI"), m_TetraTelegram->getSrcISSI())
+ formatToolTipLine(QObject::tr("Destination ISSI"), m_TetraTelegram->getDestISSI()) + formatToolTipLine(QObject::tr("Destination ISSI"), m_TetraTelegram->getDestISSI())
+ formatToolTipLine(QObject::tr("Protocol Identifier"), m_TetraTelegram->getProtocolIdentifierAsText(), m_TetraTelegram->getProtocolIdentifier()) + formatToolTipLine(QObject::tr("Protocol Identifier"), m_TetraTelegram->getProtocolIdentifierAsText(), m_TetraTelegram->getProtocolIdentifier())
@@ -548,15 +551,15 @@ void LogViewTelegram::createToolTipTextForColName()
+ formatToolTipLine(QObject::tr("Delivery"), m_TetraTelegram->getDeliveryAsText(), m_TetraTelegram->getDelivery()) + formatToolTipLine(QObject::tr("Delivery"), m_TetraTelegram->getDeliveryAsText(), m_TetraTelegram->getDelivery())
+ formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler()) + formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler())
+ formatToolTipLine(QObject::tr("Size"), m_data.size()) + formatToolTipLine(QObject::tr("Size"), m_data.size())
+ QLatin1String("</table>"); + QStringLiteral("</table>");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq:
default: default:
m_ToolTipText[e_ColName] = QLatin1String("<table>") m_ToolTipText[e_ColName] = QStringLiteral("<table>")
+ formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler()) + formatToolTipLine(QObject::tr("Counter"), m_TetraTelegram->zaehler())
+ formatToolTipLine(QObject::tr("Size"), m_data.size()) + formatToolTipLine(QObject::tr("Size"), m_data.size())
+ QLatin1String("</table>"); + QStringLiteral("</table>");
break; break;
} }
break; break;
@@ -645,24 +648,24 @@ LogViewField* LogViewTelegram::getFieldTree()
{ {
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterInd:
m_ActOffset = START_OFFSET_TETRA_REGISTER; m_ActOffset = START_OFFSET_TETRA_REGISTER;
structName = QLatin1String("TETRA_register_indication_rt"); structName = QStringLiteral("TETRA_register_indication_rt");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_RegisterRsp:
m_ActOffset = START_OFFSET_TETRA_REGISTER; m_ActOffset = START_OFFSET_TETRA_REGISTER;
structName = QLatin1String("TETRA_register_response_rt"); structName = QStringLiteral("TETRA_register_response_rt");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_DataIndReq:
if (m_TetraTelegram->isLoginTelegram()) if (m_TetraTelegram->isLoginTelegram())
{ {
m_ActOffset = START_OFFSET_TETRA_LOGIN; m_ActOffset = START_OFFSET_TETRA_LOGIN;
structName = QLatin1String("TETRA_login_telegram_rt"); structName = QStringLiteral("TETRA_login_telegram_rt");
} }
else if (m_TetraTelegram->isNormalTelegram()) else if (m_TetraTelegram->isNormalTelegram())
{ {
structName = getStructName(); structName = getStructName();
if (structName == QLatin1String("gef_automatic_conversion_rt")) if (structName == QStringLiteral("gef_automatic_conversion_rt"))
{ {
auto centralTelegram = N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(m_TetraTelegram); auto centralTelegram = N_CoPrtCnv::CoPrtCnvTelegramConverter::convertToCentral(m_TetraTelegram);
@@ -692,15 +695,15 @@ LogViewField* LogViewTelegram::getFieldTree()
{ {
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_FirstFragment:
m_ActOffset = START_OFFSET_TETRA_FRAGMENT; m_ActOffset = START_OFFSET_TETRA_FRAGMENT;
structName = QLatin1String("TETRA_first_fragment_rt"); structName = QStringLiteral("TETRA_first_fragment_rt");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_MiddleFragment: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_MiddleFragment:
m_ActOffset = START_OFFSET_TETRA_FRAGMENT; m_ActOffset = START_OFFSET_TETRA_FRAGMENT;
structName = QLatin1String("TETRA_middle_fragment_rt"); structName = QStringLiteral("TETRA_middle_fragment_rt");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_LastFragment:
m_ActOffset = START_OFFSET_TETRA_FRAGMENT; m_ActOffset = START_OFFSET_TETRA_FRAGMENT;
structName = QLatin1String("TETRA_last_fragment_rt"); structName = QStringLiteral("TETRA_last_fragment_rt");
break; break;
default: default:
break; break;
@@ -710,22 +713,22 @@ LogViewField* LogViewTelegram::getFieldTree()
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_GroupMonitorReq: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_GroupMonitorReq:
m_ActOffset = START_OFFSET_TETRA_REGISTER; m_ActOffset = START_OFFSET_TETRA_REGISTER;
structName = QLatin1String("TETRA_group_monitoring_ind_rt"); structName = QStringLiteral("TETRA_group_monitoring_ind_rt");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_StatusIndReq: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_StatusIndReq:
m_ActOffset = START_OFFSET_TETRA_REGISTER; m_ActOffset = START_OFFSET_TETRA_REGISTER;
structName = QLatin1String("TETRA_status_ind_req_rt"); structName = QStringLiteral("TETRA_status_ind_req_rt");
break; break;
case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq: case N_CoPrtCnv::CoPrtCnvRadioTelegram::e_AirInterfaceLoadReq:
m_ActOffset = START_OFFSET_TETRA_AIRLOAD; m_ActOffset = START_OFFSET_TETRA_AIRLOAD;
structName = QLatin1String("TETRA_air_interface_load_req_rt"); structName = QStringLiteral("TETRA_air_interface_load_req_rt");
break; break;
default: default:
m_ActOffset = 0; m_ActOffset = 0;
structName = QLatin1String("TETRA_unknown_PDU_rt"); structName = QStringLiteral("TETRA_unknown_PDU_rt");
break; break;
} }
return getFieldTree(structName, structName, 1); return getFieldTree(structName, structName, 1);
@@ -1095,7 +1098,7 @@ LogViewField* LogViewTelegram::getFieldTree(const QString& a_type, const QString
return getFieldTree(xdrElement->getName(), a_name, a_arraySize); return getFieldTree(xdrElement->getName(), a_name, a_arraySize);
} }
} }
Q_FALLTHROUGH(); [[fallthrough]];
case LogViewXdrElement::e_KindStandardType: case LogViewXdrElement::e_KindStandardType:
{ {
@@ -1471,10 +1474,10 @@ void LogViewTelegram::setJsonValue(const QStringList &path, const QJsonValue &va
{ {
m_data.clear(); m_data.clear();
updateJsonValue(path, val, m_json); updateJsonValue(path, val, m_json);
if (path.size() && path.last() == QLatin1String("equipmentNumber")) if (path.size() && path.last() == QStringLiteral("equipmentNumber"))
m_ParticipantId = m_json.value(QLatin1String("data")) m_ParticipantId = m_json.value(QStringLiteral("data"))
.toObject().value(QLatin1String("header")) .toObject().value(QStringLiteral("header"))
.toObject().value(QLatin1String("equipmentNumber")).toInt(); .toObject().value(QStringLiteral("equipmentNumber")).toInt();
} }
@@ -1485,7 +1488,7 @@ void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue
if (path.size() > 1) if (path.size() > 1)
{ {
QString key = path.first(); QString key = path.first();
static const QLatin1String arrayMarker(QLatin1String("array: ")); static const QString arrayMarker = QStringLiteral("array: ");
const bool isArray = key.startsWith(arrayMarker); const bool isArray = key.startsWith(arrayMarker);
if (isArray) if (isArray)
{ {
@@ -1518,11 +1521,11 @@ void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue
return; return;
const QString &key = path.first(); const QString &key = path.first();
static const QLatin1String indexMarker(QLatin1String("index: ")); static const QString indexMarker = QStringLiteral("index: ");
if (!key.startsWith(indexMarker)) if (!key.startsWith(indexMarker))
return; return;
const int arrayIdx = key.midRef(indexMarker.size()).toInt(); const int arrayIdx = QStringView(key).mid(indexMarker.size()).toInt();
while (arr.size() <= arrayIdx) while (arr.size() <= arrayIdx)
arr.append(QJsonValue()); arr.append(QJsonValue());
@@ -1543,13 +1546,13 @@ void LogViewTelegram::updateJsonValue(const QStringList &path, const QJsonValue
QIcon LogViewTelegram::getIcon() const QIcon LogViewTelegram::getIcon() const
{ {
static const QIcon c2p(QLatin1String(":/image/C2P.png")); static const QIcon c2p(QStringLiteral(":/image/C2P.png"));
static const QIcon p2c(QLatin1String(":/image/P2C.png")); static const QIcon p2c(QStringLiteral(":/image/P2C.png"));
static const QIcon w2p(QLatin1String(":/image/W2P.png")); static const QIcon w2p(QStringLiteral(":/image/W2P.png"));
static const QIcon p2w(QLatin1String(":/image/P2W.png")); static const QIcon p2w(QStringLiteral(":/image/P2W.png"));
static const QIcon t2p(QLatin1String(":/image/T2P.png")); static const QIcon t2p(QStringLiteral(":/image/T2P.png"));
static const QIcon p2t(QLatin1String(":/image/P2T.png")); static const QIcon p2t(QStringLiteral(":/image/P2T.png"));
static const QIcon unk(QLatin1String(":/image/Unknown.png")); static const QIcon unk(QStringLiteral(":/image/Unknown.png"));
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol protocol, dest; N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol protocol, dest;
protocol =(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)(m_Destination & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask); protocol =(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)(m_Destination & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask);
dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)(m_Destination & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestDirectionMask); dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)(m_Destination & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestDirectionMask);
@@ -1627,10 +1630,10 @@ void LogViewTelegram::showMessageBox(const QString& a_errorText, const QString&
quint64 logTimeMicroSec = m_LogTime & 0x00FFFFFFFFULL; quint64 logTimeMicroSec = m_LogTime & 0x00FFFFFFFFULL;
const QDateTime dt(QDateTime::fromMSecsSinceEpoch(logTimeSec * 1000 + logTimeMicroSec/1000)); const QDateTime dt(QDateTime::fromMSecsSinceEpoch(logTimeSec * 1000 + logTimeMicroSec/1000));
const QString destStr((m_Destination&N_CoPrtCnv::CoPrtCnvLogHeader::e_DestDirectionMask)==N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend ? const QString destStr((m_Destination&N_CoPrtCnv::CoPrtCnvLogHeader::e_DestDirectionMask)==N_CoPrtCnv::CoPrtCnvLogHeader::e_DestSend ?
QLatin1String("gesendete") : QLatin1String("gelesene")); QStringLiteral("gesendete") : QStringLiteral("gelesene"));
QMessageBox::warning(QApplication::topLevelWidgets()[0], a_title, QMessageBox::warning(QApplication::topLevelWidgets()[0], a_title,
QString::fromUtf8("Das %5 Telegramm mit Protokoll %6 von %1 (Unix-Zeit: %2) und Länge %3 ist fehlerhaft:<br><br><b>%4</b>") QString::fromUtf8("Das %5 Telegramm mit Protokoll %6 von %1 (Unix-Zeit: %2) und Länge %3 ist fehlerhaft:<br><br><b>%4</b>")
.arg(dt.toString(Qt::SystemLocaleLongDate)).arg(logTimeSec).arg(m_data.size()).arg(a_errorText, destStr).arg(m_Protocol)); .arg(QLocale().toString(dt, QLocale::LongFormat)).arg(logTimeSec).arg(m_data.size()).arg(a_errorText, destStr).arg(m_Protocol));
} }
@@ -1667,12 +1670,12 @@ uint16_t LogViewTelegram::getDynArraySize(uint16_t& a_offset) const
QString LogViewTelegram::formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value) QString LogViewTelegram::formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value)
{ {
static const QString s1(QLatin1String("<tr><td><nobr>%1: </nobr></td><td align=right><b><nobr>%2</nobr></b></td><td align=right><nobr>0x%3</nobr></td><td align=right><nobr>0b%4</nobr></td></tr>")); static const QString s1(QStringLiteral("<tr><td><nobr>%1: </nobr></td><td align=right><b><nobr>%2</nobr></b></td><td align=right><nobr>0x%3</nobr></td><td align=right><nobr>0b%4</nobr></td></tr>"));
static const QString s2(QLatin1String("%1")); static const QString s2(QStringLiteral("%1"));
QString num16 = s2.arg(a_value, 2, 16, QLatin1Char('0')); QString num16 = s2.arg(a_value, 2, 16, QLatin1Char('0'));
QString num2 = s2.arg(a_value, 8, 2, QLatin1Char('0')); QString num2 = s2.arg(a_value, 8, 2, QLatin1Char('0'));
QString ret = s1.arg(a_name, a_text, num16, num2); QString ret = s1.arg(a_name, a_text, num16, num2);
ret = ret.replace(QLatin1Char('\n'), QLatin1String("<br/>")); ret = ret.replace(QLatin1Char('\n'), QStringLiteral("<br/>"));
return ret; return ret;
} }
@@ -15,6 +15,7 @@
#include "LogViewXdrStandardType.hpp" #include "LogViewXdrStandardType.hpp"
#include "LogViewField.hpp" #include "LogViewField.hpp"
#include "logger.h"
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp> #include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
#include <QtGui/QIcon> #include <QtGui/QIcon>
#include <QJsonObject> #include <QJsonObject>
@@ -364,5 +365,6 @@ namespace N_LogView
private: private:
friend class LogViewTabWidget; friend class LogViewTabWidget;
LOGGER_T m_logger;
}; };
} }
@@ -50,6 +50,7 @@ namespace N_LogView
LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_readonly) LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_readonly)
: QDialog(a_parent) : QDialog(a_parent)
, m_ReadOnly(a_readonly) , m_ReadOnly(a_readonly)
, m_logger(getLogger("LogViewTelegramDialog"))
{ {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
} }
@@ -139,7 +140,7 @@ void LogViewTelegramDialog::showDataDump(const QSharedPointer<LogViewTelegram> &
layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName()))); layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName())));
QString theDump = QLatin1String("<code>"); QString theDump = QStringLiteral("<code>");
const QByteArray &data = a_telegram->getData(); const QByteArray &data = a_telegram->getData();
for (int i = 0; i < data.size(); i++) for (int i = 0; i < data.size(); i++)
{ {
@@ -148,13 +149,13 @@ void LogViewTelegramDialog::showDataDump(const QSharedPointer<LogViewTelegram> &
theDump += QStringLiteral(" %1").arg(static_cast<unsigned char>(data[i]), 2, 16, QLatin1Char('0')); theDump += QStringLiteral(" %1").arg(static_cast<unsigned char>(data[i]), 2, 16, QLatin1Char('0'));
if (7 == (i % 8)) if (7 == (i % 8))
theDump += QLatin1String("<br>"); theDump += QStringLiteral("<br>");
} }
theDump += QLatin1String("</code>"); theDump += QStringLiteral("</code>");
QTextEdit *telegramDump = new QTextEdit(theDump); QTextEdit *telegramDump = new QTextEdit(theDump);
layout->addWidget(telegramDump); layout->addWidget(telegramDump);
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen")); QPushButton *btnClose = new QPushButton(QIcon(QStringLiteral(":icons/16x16/edit-delete.png")), tr("&Schliessen"));
QHBoxLayout *btnLayout = new QHBoxLayout; QHBoxLayout *btnLayout = new QHBoxLayout;
btnLayout->addStretch(); btnLayout->addStretch();
btnLayout->addWidget(btnClose); btnLayout->addWidget(btnClose);
@@ -282,7 +283,7 @@ void LogViewTelegramDialog::showButtons(QLayout *a_layout)
{ {
if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol()) if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol())
{ {
QPushButton *btnSend = new QPushButton(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("&Send")); QPushButton *btnSend = new QPushButton(QIcon(QStringLiteral(":icons/16x16/mail-send.png")), tr("&Send"));
btnSend->setEnabled(true); btnSend->setEnabled(true);
connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram); connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram);
a_layout->addWidget(btnSend); a_layout->addWidget(btnSend);
@@ -290,18 +291,18 @@ void LogViewTelegramDialog::showButtons(QLayout *a_layout)
if (m_ReadOnly) if (m_ReadOnly)
{ {
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen")); QPushButton *btnClose = new QPushButton(QIcon(QStringLiteral(":icons/16x16/edit-delete.png")), tr("&Schliessen"));
connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject); connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject);
a_layout->addWidget(btnClose); a_layout->addWidget(btnClose);
} }
else else
{ {
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Abbrechen")); QPushButton *btnClose = new QPushButton(QIcon(QStringLiteral(":icons/16x16/edit-delete.png")), tr("&Abbrechen"));
connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject); connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject);
a_layout->addWidget(btnClose); a_layout->addWidget(btnClose);
QPushButton *btnOk = new QPushButton(QIcon(QLatin1String(":icons/16x16/dialog-ok-apply.png")), tr("&OK")); QPushButton *btnOk = new QPushButton(QIcon(QStringLiteral(":icons/16x16/dialog-ok-apply.png")), tr("&OK"));
btnOk->setDefault(true); btnOk->setDefault(true);
connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram); connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram);
@@ -392,7 +393,7 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
break; break;
} }
Q_FALLTHROUGH(); [[fallthrough]];
case 0: case 0:
if (m_ReadOnly) if (m_ReadOnly)
{ {
@@ -401,7 +402,7 @@ void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLay
break; break;
} }
Q_FALLTHROUGH(); [[fallthrough]];
default: default:
{ {
@@ -69,6 +69,7 @@ private:
QLineEdit *m_NameEdit = nullptr; QLineEdit *m_NameEdit = nullptr;
QLineEdit *m_WaitTimeEdit = nullptr; QLineEdit *m_WaitTimeEdit = nullptr;
bool m_ReadOnly = false; bool m_ReadOnly = false;
LOGGER_T m_logger;
}; };
} }
@@ -43,20 +43,21 @@ QString TelegramEdit::s_TELEGRAMLIST_FILES()
TelegramEdit::TelegramEdit(QWidget *parent) TelegramEdit::TelegramEdit(QWidget *parent)
: QObject(parent) : QObject(parent)
, m_addTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-add.png")), tr("Add Telegram"), this)) , m_addTeleAction(new QAction(QIcon(QStringLiteral(":icons/16x16/list-add.png")), tr("Add Telegram"), this))
, m_editTeleAction(new QAction(QIcon(QLatin1String(":/image/Edit.png")), tr("Edit Telegram"), this)) , m_editTeleAction(new QAction(QIcon(QStringLiteral(":/image/Edit.png")), tr("Edit Telegram"), this))
, m_copyTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-copy.png")), tr("Copy Telegram"), this)) , m_copyTeleAction(new QAction(QIcon(QStringLiteral(":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_pasteTeleAction(new QAction(QIcon(QStringLiteral(":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_deleteTeleAction(new QAction(QIcon(QStringLiteral(":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_moveTeleUpAction(new QAction(QIcon(QStringLiteral(":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_moveTeleDownAction(new QAction(QIcon(QStringLiteral(":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_teleListLoad(new QAction(QIcon(QStringLiteral(":icons/16x16/document-open-data.png")), tr("Load Telegram list"), this))
, m_teleListAppend(new QAction(QIcon(), tr("Telegrammliste anhaengen"), 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_teleListSave(new QAction(QIcon(QStringLiteral(":icons/16x16/document-save.png")), tr("Save Telegram list"), this))
, m_tableView(new QTableView(parent)) , m_tableView(new QTableView(parent))
, m_DoLoop(false) , m_DoLoop(false)
, m_InjectionThread(nullptr) , m_InjectionThread(nullptr)
, m_EditModel(new TelegramEditModel(this)) , m_EditModel(new TelegramEditModel(this))
, m_logger(getLogger("TelegramEdit"))
{ {
m_addTeleAction->setShortcut(tr("Ctrl+A")); m_addTeleAction->setShortcut(tr("Ctrl+A"));
m_editTeleAction->setShortcut(tr("Ctrl+E")); m_editTeleAction->setShortcut(tr("Ctrl+E"));
@@ -151,12 +152,12 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
if (isInjectionPossible()) if (isInjectionPossible())
{ {
QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm")); QAction *action = menu.addAction(QIcon(QStringLiteral(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm"));
action->setEnabled(itemSelected && isCentral); action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram); connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram);
action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm")); action = menu.addAction(QIcon(QStringLiteral(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm"));
action->setEnabled(itemSelected && isCentral); action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram); connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram);
@@ -165,21 +166,21 @@ void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm")); action = menu.addAction(QIcon(QStringLiteral(":icons/16x16/mail-send.png")), tr("Sende Telegramm"));
action->setEnabled(itemSelected && isCentral); action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram); connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram);
if (m_DoLoop) if (m_DoLoop)
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-stop.png")), tr("Stop Loopen")); action = menu.addAction(QIcon(QStringLiteral(":icons/16x16/media-playback-stop.png")), tr("Stop Loopen"));
else else
{ {
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-start.png")), tr("Loop Telegramme")); action = menu.addAction(QIcon(QStringLiteral(":icons/16x16/media-playback-start.png")), tr("Loop Telegramme"));
action->setEnabled(itemSelected); action->setEnabled(itemSelected);
} }
connect(action, &QAction::triggered, this, &TelegramEdit::loopTelegrams); connect(action, &QAction::triggered, this, &TelegramEdit::loopTelegrams);
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-play-normal.png")), tr("Sende Sequenz")); action = menu.addAction(QIcon(QStringLiteral(":icons/16x16/media-play-normal.png")), tr("Sende Sequenz"));
action->setEnabled(itemSelected); action->setEnabled(itemSelected);
connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams); connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams);
@@ -440,7 +441,7 @@ void TelegramEdit::saveTelegramList()
if (!newFilename.isEmpty()) if (!newFilename.isEmpty())
{ {
if (!newFilename.contains(QLatin1Char('.'))) if (!newFilename.contains(QLatin1Char('.')))
newFilename += QLatin1String(".tgl"); newFilename += QStringLiteral(".tgl");
QDir dir; QDir dir;
@@ -4,7 +4,8 @@
#pragma once #pragma once
#include "LogViewTelegram.hpp" #include "LogViewTelegram.hpp"
#include <QtGui/QModelIndex> #include <QtCore/QModelIndex>
#include "logger.h"
class QAction; class QAction;
class QTableView; class QTableView;
@@ -114,5 +115,8 @@ protected Q_SLOTS:
void editTelegramDialogFinished(); void editTelegramDialogFinished();
void onSelectionChanged(); void onSelectionChanged();
protected:
LOGGER_T m_logger;
}; };
} }
@@ -3,7 +3,7 @@
#pragma once #pragma once
#include <QtGui/QAbstractTableModel> #include <QtCore/QAbstractTableModel>
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#include <QtCore/QSet> #include <QtCore/QSet>
#include "LogViewTelegram.hpp" #include "LogViewTelegram.hpp"
@@ -6,6 +6,7 @@
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QVector> #include <QtCore/QVector>
#include <QtCore/QStringView>
namespace N_LogView namespace N_LogView
{ {
@@ -87,29 +88,29 @@ bool LogViewTetraTelegramsParser::parse(const QString &filename)
const QString content = QString::fromUtf8(f.readAll()); const QString content = QString::fromUtf8(f.readAll());
f.close(); f.close();
const QVector<QStringRef> lines = content.splitRef(QLatin1Char('\n')); const QList<QStringView> lines = QStringView(content).split(QLatin1Char('\n'));
QVector<QStringRef> linesTrimmed; QList<QStringView> linesTrimmed;
linesTrimmed.reserve(lines.size()); linesTrimmed.reserve(lines.size());
for (const QStringRef &line : lines) for (QStringView line : lines)
linesTrimmed += line.trimmed(); linesTrimmed += line.trimmed();
int i = 0; int i = 0;
while (i < linesTrimmed.size()) while (i < linesTrimmed.size())
{ {
const QStringRef &line = linesTrimmed.at(i); const QStringView line = linesTrimmed.at(i);
if (line.startsWith(QLatin1String("struct"))) if (line.startsWith(QStringLiteral("struct")))
{ {
i = parseStruct(linesTrimmed, i); i = parseStruct(linesTrimmed, i);
if (i < 0) if (i < 0)
return false; return false;
} }
else if (line.startsWith(QLatin1String("enum"))) else if (line.startsWith(QStringLiteral("enum")))
{ {
i = parseEnum(linesTrimmed, i, QString()); i = parseEnum(linesTrimmed, i, QString());
if (i < 0) if (i < 0)
return false; return false;
} }
else if (line.startsWith(QLatin1String("template <> struct Constraints"))) else if (line.startsWith(QStringLiteral("template <> struct Constraints")))
{ {
i = parseConstraint(linesTrimmed, i); i = parseConstraint(linesTrimmed, i);
if (i < 0) if (i < 0)
@@ -136,12 +137,12 @@ void LogViewTetraTelegramsParser::insertPod(const QString &type, int byteLen, bo
} }
int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, int iStartPos) int LogViewTetraTelegramsParser::parseStruct(const QList<QStringView> &lines, int iStartPos)
{ {
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos)); const QList<QStringView> tokens = tokenize(lines.at(iStartPos));
if (tokens.size() < 2) if (tokens.size() < 2)
return -1; return -1;
const QStringRef &structType = tokens.at(1); const QStringView structType = tokens.at(1);
if (structType.endsWith(QLatin1Char(';'))) if (structType.endsWith(QLatin1Char(';')))
return iStartPos; return iStartPos;
@@ -149,7 +150,7 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, i
si.type = structType.toString(); si.type = structType.toString();
if (tokens.size() > 2) if (tokens.size() > 2)
{ {
if (tokens.at(2) != QLatin1String(":")) if (tokens.at(2) != QStringLiteral(":"))
{ {
WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1; WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1;
return -1; return -1;
@@ -162,10 +163,10 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, i
WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1; WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1;
return -1; return -1;
} }
QStringRef base = tokens.at(i); QStringView base = tokens.at(i);
if (base == QLatin1String("public") || if (base == QStringLiteral("public") ||
base == QLatin1String("protected") || base == QStringLiteral("protected") ||
base == QLatin1String("private")) base == QStringLiteral("private"))
continue; continue;
if (base.endsWith(QLatin1Char(','))) if (base.endsWith(QLatin1Char(',')))
base.chop(1); base.chop(1);
@@ -181,15 +182,15 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, i
int i = iStartPos + 1; int i = iStartPos + 1;
while (i < lines.size()) while (i < lines.size())
{ {
const QVector<QStringRef> tokens = tokenize(lines.at(i)); const QList<QStringView> tokens = tokenize(lines.at(i));
if (!validStructTokens(tokens)) if (!validStructTokens(tokens))
{ {
++i; ++i;
continue; continue;
} }
if (tokens.at(0) == QLatin1String("};")) if (tokens.at(0) == QStringLiteral("};"))
break; break;
if (tokens.at(0) == QLatin1String("enum")) if (tokens.at(0) == QStringLiteral("enum"))
{ {
i = parseEnum(lines, i, si.type, &si); i = parseEnum(lines, i, si.type, &si);
if (i < 0) if (i < 0)
@@ -201,35 +202,35 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, i
MemberInformation mi; MemberInformation mi;
if (tokens.size() > 2) if (tokens.size() > 2)
{ {
const int parserCommentPos = tokens.at(2) == QLatin1String("=") ? 4 : 2; const int parserCommentPos = tokens.at(2) == QStringLiteral("=") ? 4 : 2;
if (tokens.size() > parserCommentPos) if (tokens.size() > parserCommentPos)
{ {
const QStringRef &comment = tokens.at(parserCommentPos); const QStringView comment = tokens.at(parserCommentPos);
DEBUG_LOG(m_logger) << "comment: " << comment.toString(); DEBUG_LOG(m_logger) << "comment: " << comment.toString();
if (comment.startsWith(QLatin1String("//@array: "))) if (comment.startsWith(QStringLiteral("//@array: ")))
{ {
const QStringRef hint = comment.mid(QLatin1String("//@array: ").size()); const QStringView hint = comment.mid(QStringLiteral("//@array: ").size());
QString structStr = QLatin1String("struct ") + si.type + QLatin1String("::") + tokens.at(0).toString() + QLatin1Char('\n') + hint.toString(); QString structStr = QStringLiteral("struct ") + si.type + QStringLiteral("::") + tokens.at(0).toString() + QLatin1Char('\n') + hint.toString();
structStr.replace(QLatin1Char(';'), QLatin1String(";\n")); structStr.replace(QLatin1Char(';'), QStringLiteral(";\n"));
DEBUG_LOG(m_logger) << "structStr: " << structStr; DEBUG_LOG(m_logger) << "structStr: " << structStr;
parseStruct(structStr.splitRef(QLatin1Char('\n')), 0); parseStruct(QStringView(structStr).split(QLatin1Char('\n')), 0);
mi.type = si.type + QLatin1String("::") + tokens.at(0).toString(); mi.type = si.type + QStringLiteral("::") + tokens.at(0).toString();
mi.isArray = true; mi.isArray = true;
} }
if (comment == QLatin1String("//@invisible")) if (comment == QStringLiteral("//@invisible"))
mi.isVisible = false; mi.isVisible = false;
} }
} }
QStringRef name = tokens.at(1); QStringView name = tokens.at(1);
if (name.endsWith(QLatin1Char(';'))) if (name.endsWith(QLatin1Char(';')))
name.chop(1); name.chop(1);
if (mi.type.isEmpty()) if (mi.type.isEmpty())
mi.type += tokens.at(0).toString(); mi.type += tokens.at(0).toString();
categorizeMember(mi); categorizeMember(mi);
mi.name = name.toString(); mi.name = name.toString();
if (mi.isEnum && !mi.type.contains(QLatin1String("::"))) if (mi.isEnum && !mi.type.contains(QStringLiteral("::")))
{ {
for (const auto &ei : std::as_const(m_enums)) for (const auto &ei : std::as_const(m_enums))
@@ -237,7 +238,7 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, i
if (ei.type == mi.type) if (ei.type == mi.type)
{ {
if (!ei.ns.isEmpty()) if (!ei.ns.isEmpty())
mi.type = ei.ns + QLatin1String("::") + mi.type; mi.type = ei.ns + QStringLiteral("::") + mi.type;
break; break;
} }
} }
@@ -265,13 +266,13 @@ int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, i
return i; return i;
} }
int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int iStartPos, const QString &ns, StructInformation *si) int LogViewTetraTelegramsParser::parseEnum(const QList<QStringView> &lines, int iStartPos, const QString &ns, StructInformation *si)
{ {
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos)); const QList<QStringView> tokens = tokenize(lines.at(iStartPos));
if (tokens.size() < 2) if (tokens.size() < 2)
return -1; return -1;
QStringRef enumName = tokens.at(1); QStringView enumName = tokens.at(1);
if (enumName == QLatin1String("class")) if (enumName == QStringLiteral("class"))
{ {
if (tokens.size() < 3) if (tokens.size() < 3)
return -1; return -1;
@@ -287,19 +288,19 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int
int i = iStartPos + 1; int i = iStartPos + 1;
while (i < lines.size()) while (i < lines.size())
{ {
const QVector<QStringRef> tokens = tokenize(lines.at(i).split(QStringLiteral("//")).first()); const QList<QStringView> tokens = tokenize(lines.at(i).split(QStringLiteral("//")).first());
if (tokens.isEmpty() || if (tokens.isEmpty() ||
(tokens.at(0) == QLatin1String("{"))) (tokens.at(0) == QStringLiteral("{")))
{ {
++i; ++i;
continue; continue;
} }
if (tokens.at(0) == QLatin1String("};")) if (tokens.at(0) == QStringLiteral("};"))
break; break;
if ((tokens.size() != 1 && tokens.size() != 3) || if ((tokens.size() != 1 && tokens.size() != 3) ||
(tokens.size() == 3 && tokens.at(1) != QLatin1String("="))) (tokens.size() == 3 && tokens.at(1) != QStringLiteral("=")))
{ {
if (tokens.size() == 4 && tokens.at(0) == QLatin1String("}") && tokens.at(3).endsWith(QLatin1Char(';')) && si) if (tokens.size() == 4 && tokens.at(0) == QStringLiteral("}") && tokens.at(3).endsWith(QLatin1Char(';')) && si)
{ {
MemberInformation mi; MemberInformation mi;
@@ -320,7 +321,7 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int
ev.key = tokens.at(0).toString(); ev.key = tokens.at(0).toString();
if (tokens.size() == 3) if (tokens.size() == 3)
{ {
QStringRef value = tokens.at(2); QStringView value = tokens.at(2);
if (value.endsWith(QLatin1Char(','))) if (value.endsWith(QLatin1Char(',')))
value.chop(1); value.chop(1);
ev.value = value.toInt(); ev.value = value.toInt();
@@ -338,7 +339,7 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int
for (const EnumValue &ev : std::as_const(ei.values)) for (const EnumValue &ev : std::as_const(ei.values))
DEBUG_LOG(m_logger) << "Member[" << i << "]: " << ev.key << " = " << ev.value; DEBUG_LOG(m_logger) << "Member[" << i << "]: " << ev.key << " = " << ev.value;
if (ei.type == QLatin1String("TelegramId")) if (ei.type == QStringLiteral("TelegramId"))
m_telegramIdEnum = ei; m_telegramIdEnum = ei;
m_enums.push_back(std::move(ei)); m_enums.push_back(std::move(ei));
@@ -346,49 +347,49 @@ int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int
return i; return i;
} }
int LogViewTetraTelegramsParser::parseConstraint(const QVector<QStringRef> &lines, int iStartPos) int LogViewTetraTelegramsParser::parseConstraint(const QList<QStringView> &lines, int iStartPos)
{ {
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos)); const QList<QStringView> tokens = tokenize(lines.at(iStartPos));
if (tokens.size() != 4) if (tokens.size() != 4)
{ {
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'"; WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'";
return -1; return -1;
} }
const QStringRef &cs = tokens.at(3); const QStringView cs = tokens.at(3);
if (!cs.startsWith(QLatin1String("Constraints<")) || !cs.endsWith(QLatin1Char('>'))) if (!cs.startsWith(QStringLiteral("Constraints<")) || !cs.endsWith(QLatin1Char('>')))
{ {
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'"; WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'";
return -1; return -1;
} }
QStringRef structName = cs.mid(QLatin1String("Constraints<").size()); QStringView structName = cs.mid(QStringLiteral("Constraints<").size());
structName.chop(1); structName.chop(1);
DEBUG_LOG(m_logger) << "Constraint: " << structName.toString(); DEBUG_LOG(m_logger) << "Constraint: " << structName.toString();
int i = iStartPos + 1; int i = iStartPos + 1;
while (i < lines.size()) while (i < lines.size())
{ {
const QVector<QStringRef> tokens = tokenize(lines.at(i)); const QList<QStringView> tokens = tokenize(lines.at(i));
if (tokens.isEmpty() || if (tokens.isEmpty() ||
(tokens.at(0) == QLatin1String("{"))) (tokens.at(0) == QStringLiteral("{")))
{ {
++i; ++i;
continue; continue;
} }
if (tokens.at(0) == QLatin1String("};")) if (tokens.at(0) == QStringLiteral("};"))
break; break;
if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId")) if (tokens.size() != 8 || tokens.at(2) != QStringLiteral("TelegramId"))
{ {
++i; ++i;
continue; continue;
} }
const QVector<QStringRef> parts = tokens.at(6).split(QLatin1String("::")); const QList<QStringView> parts = tokens.at(6).split(QStringLiteral("::"));
if (parts.size() != 2) if (parts.size() != 2)
{ {
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(i).toString() << "'"; WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(i).toString() << "'";
return -1; return -1;
} }
QStringRef enumKey = parts.at(1); QStringView enumKey = parts.at(1);
if (enumKey.endsWith(QLatin1Char(';'))) if (enumKey.endsWith(QLatin1Char(';')))
enumKey.chop(1); enumKey.chop(1);
bool bFound = false; bool bFound = false;
@@ -427,14 +428,14 @@ void LogViewTetraTelegramsParser::categorizeMember(MemberInformation &mi) const
{ {
mi.isPod = isPod(mi.type); mi.isPod = isPod(mi.type);
mi.isEnum = mi.isPod ? false : isEnum(mi.type); mi.isEnum = mi.isPod ? false : isEnum(mi.type);
if (mi.type.startsWith(QLatin1String("std::vector<"))) if (mi.type.startsWith(QStringLiteral("std::vector<")))
mi.isArray = true; mi.isArray = true;
mi.isStruct = mi.isArray ? false : isStruct(mi.type); mi.isStruct = mi.isArray ? false : isStruct(mi.type);
mi.isString = (mi.type == QLatin1String("std::string") || mi.type == QLatin1String("QString")); mi.isString = (mi.type == QStringLiteral("std::string") || mi.type == QStringLiteral("QString"));
mi.isBinary = (mi.type == QLatin1String("std::vector<unsigned char>") || mi.type == QLatin1String("QByteArray")); mi.isBinary = (mi.type == QStringLiteral("std::vector<unsigned char>") || mi.type == QStringLiteral("QByteArray"));
} }
static inline void bracketCount(const QStringRef &str, int &cntLt, int &cntGt) static inline void bracketCount(QStringView str, int &cntLt, int &cntGt)
{ {
cntLt = 0; cntLt = 0;
cntGt = 0; cntGt = 0;
@@ -447,20 +448,20 @@ static inline void bracketCount(const QStringRef &str, int &cntLt, int &cntGt)
} }
} }
QVector<QStringRef> LogViewTetraTelegramsParser::tokenize(const QStringRef &line) const QList<QStringView> LogViewTetraTelegramsParser::tokenize(QStringView line) const
{ {
QVector<QStringRef> ret = line.split(QLatin1Char(' '), QString::SkipEmptyParts); QList<QStringView> ret = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);
int i = 0; int i = 0;
while (i < ret.size()) while (i < ret.size())
{ {
const QStringRef &token = ret.at(i); const QStringView token = ret.at(i);
if (token.startsWith(QLatin1String("//"))) if (token.startsWith(QStringLiteral("//")))
{ {
if (i == ret.size() - 1) if (i == ret.size() - 1)
break; break;
const QStringRef &lastToken = ret.last(); const QStringView lastToken = ret.last();
const QStringRef newToken = QStringRef(token.string(), token.position(), lastToken.position() - token.position() + lastToken.size()); const QStringView newToken(token.data(), lastToken.data() - token.data() + lastToken.size());
DEBUG_LOG(m_logger) << "New Token: " << newToken.toString(); DEBUG_LOG(m_logger) << "New Token: " << newToken.toString();
ret.resize(i + 1); ret.resize(i + 1);
ret[i] = newToken; ret[i] = newToken;
@@ -476,8 +477,8 @@ QVector<QStringRef> LogViewTetraTelegramsParser::tokenize(const QStringRef &line
++i; ++i;
continue; continue;
} }
const QStringRef &nextToken = ret.at(i + 1); const QStringView nextToken = ret.at(i + 1);
const QStringRef newToken = QStringRef(token.string(), token.position(), nextToken.position() - token.position() + nextToken.size()); const QStringView newToken(token.data(), nextToken.data() - token.data() + nextToken.size());
DEBUG_LOG(m_logger) << "New Token: " << newToken.toString(); DEBUG_LOG(m_logger) << "New Token: " << newToken.toString();
ret.removeAt(i + 1); ret.removeAt(i + 1);
ret[i] = newToken; ret[i] = newToken;
@@ -486,21 +487,21 @@ QVector<QStringRef> LogViewTetraTelegramsParser::tokenize(const QStringRef &line
return ret; return ret;
} }
bool LogViewTetraTelegramsParser::validStructTokens(const QVector<QStringRef> &tokens) bool LogViewTetraTelegramsParser::validStructTokens(const QList<QStringView> &tokens)
{ {
if (tokens.isEmpty() || if (tokens.isEmpty() ||
(tokens.at(0) == QLatin1String("{")) || (tokens.at(0) == QStringLiteral("{")) ||
(tokens.at(0) == QLatin1String("{}")) || (tokens.at(0) == QStringLiteral("{}")) ||
(tokens.at(0) == QLatin1String("}")) || (tokens.at(0) == QStringLiteral("}")) ||
(tokens.at(0) == QLatin1String(":")) || (tokens.at(0) == QStringLiteral(":")) ||
(tokens.at(0) == QLatin1String(",")) || (tokens.at(0) == QStringLiteral(",")) ||
(tokens.at(0) == QLatin1String("virtual"))) (tokens.at(0) == QStringLiteral("virtual")))
return false; return false;
if (tokens.at(0) == QLatin1String("};") || tokens.at(0) == QLatin1String("enum")) if (tokens.at(0) == QStringLiteral("};") || tokens.at(0) == QStringLiteral("enum"))
return true; return true;
const int len = tokens.last().startsWith(QLatin1String("//")) ? tokens.size() - 1 : tokens.size(); const int len = tokens.last().startsWith(QStringLiteral("//")) ? tokens.size() - 1 : tokens.size();
if (len == 2) if (len == 2)
return true; return true;
@@ -508,7 +509,7 @@ bool LogViewTetraTelegramsParser::validStructTokens(const QVector<QStringRef> &t
if (len < 4) if (len < 4)
return false; return false;
if (len >= 4 && tokens.at(2) == QLatin1String("=")) if (len >= 4 && tokens.at(2) == QStringLiteral("="))
return true; return true;
return false; return false;
@@ -6,6 +6,7 @@
#include <QtCore/QHash> #include <QtCore/QHash>
#include <QtCore/QString> #include <QtCore/QString>
#include <QtCore/QVector> #include <QtCore/QVector>
#include <QtCore/QStringView>
#include "logger.h" #include "logger.h"
namespace N_LogView namespace N_LogView
@@ -72,13 +73,14 @@ public:
static QString getInnerType(const QString &type); static QString getInnerType(const QString &type);
private: private:
void insertPod(const QString &type, int byteLen, bool isSigned, bool isIntegral, bool isBoolean = false); void insertPod(const QString &type, int byteLen, bool isSigned, bool isIntegral, bool isBoolean = false);
int parseStruct(const QVector<QStringRef> &lines, int iStartPos); int parseStruct(const QList<QStringView> &lines, int iStartPos);
int parseEnum(const QVector<QStringRef> &lines, int iStartPos, const QString &ns, StructInformation *si = nullptr); int parseEnum(const QList<QStringView> &lines, int iStartPos, const QString &ns, StructInformation *si = nullptr);
int parseConstraint(const QVector<QStringRef> &lines, int iStartPos); int parseConstraint(const QList<QStringView> &lines, int iStartPos);
void categorizeMember(MemberInformation &mi) const; void categorizeMember(MemberInformation &mi) const;
QVector<QStringRef> tokenize(const QStringRef &line) const; QList<QStringView> tokenize(QStringView line) const;
static bool validStructTokens(const QVector<QStringRef> &tokens); static bool validStructTokens(const QList<QStringView> &tokens);
private: private:
LOGGER_T m_logger;
EnumInformation m_telegramIdEnum; EnumInformation m_telegramIdEnum;
QVector<EnumInformation> m_enums; QVector<EnumInformation> m_enums;
QHash<QString, StructInformation> m_structs; QHash<QString, StructInformation> m_structs;
@@ -30,6 +30,7 @@ LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget*
, m_Widget(a_widget) , m_Widget(a_widget)
, m_Field(a_field) , m_Field(a_field)
, m_Parent(a_parent) , m_Parent(a_parent)
, m_logger(getLogger("LogViewWidget"))
{ {
} }
@@ -77,6 +77,8 @@ protected:
LogViewField *m_Field; LogViewField *m_Field;
QWidget *m_Parent; QWidget *m_Parent;
LOGGER_T m_logger;
}; };
} }
@@ -41,19 +41,19 @@ QString LogViewXdrElement::getKindName() const
switch (getKind()) switch (getKind())
{ {
case e_KindDefine: case e_KindDefine:
return QLatin1String("Define"); return QStringLiteral("Define");
case e_KindEnum: case e_KindEnum:
return QLatin1String("Enum"); return QStringLiteral("Enum");
case e_KindEnumElement: case e_KindEnumElement:
return QLatin1String("EnumElement"); return QStringLiteral("EnumElement");
case e_KindStandardType: case e_KindStandardType:
return QLatin1String("StandardType"); return QStringLiteral("StandardType");
case e_KindStruct: case e_KindStruct:
return QLatin1String("Struct"); return QStringLiteral("Struct");
case e_KindStructElement: case e_KindStructElement:
return QLatin1String("StructElement"); return QStringLiteral("StructElement");
case e_KindTypedef: case e_KindTypedef:
return QLatin1String("Typedef"); return QStringLiteral("Typedef");
} }
return QStringLiteral("Unknown (%1)").arg(getKind()); return QStringLiteral("Unknown (%1)").arg(getKind());
} }
@@ -53,6 +53,7 @@ namespace N_LogView
protected: protected:
QString m_Name; QString m_Name;
E_ElementKind m_Kind; E_ElementKind m_Kind;
LOGGER_T m_logger;
QString getKindName() const; QString getKindName() const;
}; };
@@ -37,6 +37,7 @@ LogViewXdrParser::LogViewXdrParser()
, m_WordListIndex(0) , m_WordListIndex(0)
, m_ActElement(nullptr) , m_ActElement(nullptr)
, m_State(e_ParseMain) , m_State(e_ParseMain)
, m_logger(getLogger("LogViewXdrParser"))
{} {}
LogViewXdrParser::~LogViewXdrParser() LogViewXdrParser::~LogViewXdrParser()
@@ -73,41 +74,41 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
m_State = e_ParseMain; m_State = e_ParseMain;
addStandardType(QLatin1String("unsigned short"), 4, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("unsigned short"), 4, 2, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("unsigned int"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("unsigned int"), 4, 4, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("short"), 4, 2, LogViewXdrStandardType::e_Signed); addStandardType(QStringLiteral("short"), 4, 2, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("int"), 4, 4, LogViewXdrStandardType::e_Signed); addStandardType(QStringLiteral("int"), 4, 4, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("u_int"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("u_int"), 4, 4, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("char"), 4, 2, LogViewXdrStandardType::e_Character); addStandardType(QStringLiteral("char"), 4, 2, LogViewXdrStandardType::e_Character);
addStandardType(QLatin1String("unsigned char"), 4, 1, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("unsigned char"), 4, 1, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("unsigned long"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("unsigned long"), 4, 4, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("u_long"), 4, 4, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("u_long"), 4, 4, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("u_short"), 4, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("u_short"), 4, 2, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("float"), 4, 4, LogViewXdrStandardType::e_Float, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderBigEndian); addStandardType(QStringLiteral("float"), 4, 4, LogViewXdrStandardType::e_Float, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderBigEndian);
addStandardType(QLatin1String("double"), 8, 8, LogViewXdrStandardType::e_Float, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderBigEndian); addStandardType(QStringLiteral("double"), 8, 8, LogViewXdrStandardType::e_Float, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderBigEndian);
addStandardType(QLatin1String("opaque"), 1, 1, LogViewXdrStandardType::e_Data); addStandardType(QStringLiteral("opaque"), 1, 1, LogViewXdrStandardType::e_Data);
addStandardType(QLatin1String("string"), 1, 1, LogViewXdrStandardType::e_Character); addStandardType(QStringLiteral("string"), 1, 1, LogViewXdrStandardType::e_Character);
addStandardType(QLatin1String("alpha"), 1, 1, LogViewXdrStandardType::e_Character); addStandardType(QStringLiteral("alpha"), 1, 1, LogViewXdrStandardType::e_Character);
addStandardType(QLatin1String("UInt8"), 1, 1, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("UInt8"), 1, 1, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("UInt16"), 2, 2, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("UInt16"), 2, 2, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("UInt24"), 3, 3, LogViewXdrStandardType::e_Unsigned); addStandardType(QStringLiteral("UInt24"), 3, 3, LogViewXdrStandardType::e_Unsigned);
addStandardType(QLatin1String("SInt8"), 1, 1, LogViewXdrStandardType::e_Signed); addStandardType(QStringLiteral("SInt8"), 1, 1, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("SInt16"), 2, 2, LogViewXdrStandardType::e_Signed); addStandardType(QStringLiteral("SInt16"), 2, 2, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("SInt24"), 3, 3, LogViewXdrStandardType::e_Signed); addStandardType(QStringLiteral("SInt24"), 3, 3, LogViewXdrStandardType::e_Signed);
addStandardType(QLatin1String("UInt16LE"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian); addStandardType(QStringLiteral("UInt16LE"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian);
addStandardType(QLatin1String("UInt32LE"), 4, 4, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian); addStandardType(QStringLiteral("UInt32LE"), 4, 4, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayMsgLength, LogViewXdrStandardType::e_ByteOrderLittleEndian);
addStandardType(QLatin1String("UInt8Idx"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex); addStandardType(QStringLiteral("UInt8Idx"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex);
addStandardType(QLatin1String("UInt16Idx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex); addStandardType(QStringLiteral("UInt16Idx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex);
addStandardType(QLatin1String("UInt16LEIdx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex, LogViewXdrStandardType::e_ByteOrderLittleEndian); addStandardType(QStringLiteral("UInt16LEIdx"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndex, LogViewXdrStandardType::e_ByteOrderLittleEndian);
addStandardType(QLatin1String("UInt8IdxDiv8"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8); addStandardType(QStringLiteral("UInt8IdxDiv8"), 1, 1, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8);
addStandardType(QLatin1String("UInt16IdxDiv8"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8); addStandardType(QStringLiteral("UInt16IdxDiv8"), 2, 2, LogViewXdrStandardType::e_Unsigned, LogViewXdrStandardType::e_DynArrayIndexDiv8);
const auto DEFINE_NAME = QLatin1String("%#define"); const auto DEFINE_NAME = QStringLiteral("%#define");
m_Filename = a_fileName; m_Filename = a_fileName;
@@ -155,11 +156,11 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
if (e_ParseMain == m_State) if (e_ParseMain == m_State)
{ {
if (cleanLine.startsWith(QLatin1String("union "))) if (cleanLine.startsWith(QStringLiteral("union ")))
{ {
m_State = e_ParseUnion; m_State = e_ParseUnion;
} }
else if (cleanLine.startsWith(QLatin1String("struct "))) else if (cleanLine.startsWith(QStringLiteral("struct ")))
{ {
m_State = e_ParseStruct; m_State = e_ParseStruct;
} }
@@ -182,19 +183,19 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
{ {
parseDefine(m_Line.mid(DEFINE_NAME.size())); parseDefine(m_Line.mid(DEFINE_NAME.size()));
} }
else if (cleanLine.startsWith(QLatin1String("typedef "))) else if (cleanLine.startsWith(QStringLiteral("typedef ")))
{ {
parseTypedef(cleanLine); parseTypedef(cleanLine);
} }
else if (cleanLine.startsWith(QLatin1String("enum "))) else if (cleanLine.startsWith(QStringLiteral("enum ")))
{ {
parseEnum(cleanLine.mid(5)); parseEnum(cleanLine.mid(5));
} }
else if (cleanLine.startsWith(QLatin1String("enum8 "))) else if (cleanLine.startsWith(QStringLiteral("enum8 ")))
{ {
parseEnum(cleanLine.mid(6), 1); parseEnum(cleanLine.mid(6), 1);
} }
else if (cleanLine.startsWith(QLatin1String("enum16 "))) else if (cleanLine.startsWith(QStringLiteral("enum16 ")))
{ {
parseEnum(cleanLine.mid(7), 2); parseEnum(cleanLine.mid(7), 2);
} }
@@ -213,7 +214,7 @@ void LogViewXdrParser::parseX_File(const QString& a_fileName)
} }
else else
{ {
QMessageBox::warning(nullptr, QLatin1String("Dateifehler"), QStringLiteral("Konnte die Datei <b>%1</b> nicht öffnen").arg(a_fileName)); QMessageBox::warning(nullptr, QStringLiteral("Dateifehler"), QStringLiteral("Konnte die Datei <b>%1</b> nicht öffnen").arg(a_fileName));
} }
} }
@@ -317,8 +318,8 @@ void LogViewXdrParser::parseDefine(const QString &a_line)
int sepPos = line.indexOf(QLatin1Char(' ')); int sepPos = line.indexOf(QLatin1Char(' '));
if (sepPos >= 0) if (sepPos >= 0)
{ {
const QString name = line.leftRef(sepPos).trimmed().toString(); const QString name = QStringView(line).left(sepPos).trimmed().toString();
QStringRef substitution = line.midRef(sepPos).trimmed(); QStringView substitution = QStringView(line).mid(sepPos).trimmed();
sepPos = substitution.indexOf(QLatin1Char(' ')); sepPos = substitution.indexOf(QLatin1Char(' '));
if (sepPos >= 0) if (sepPos >= 0)
substitution = substitution.left(sepPos).trimmed(); substitution = substitution.left(sepPos).trimmed();
@@ -342,17 +343,17 @@ void LogViewXdrParser::parseDefine(const QString &a_line)
void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSize) void LogViewXdrParser::parseEnum(const QString &a_line, const uint16_t a_enumSize)
{ {
if (QLatin1String("};") != a_line) if (QStringLiteral("};") != a_line)
{ {
switch(m_State) switch(m_State)
{ {
default: default:
if (a_line.endsWith(QLatin1String(" {"))) if (a_line.endsWith(QStringLiteral(" {")))
{ {
m_State = e_ParseEnum; m_State = e_ParseEnum;
const QString name = a_line.leftRef(a_line.length()-2).trimmed().toString(); const QString name = QStringView(a_line).left(a_line.length()-2).trimmed().toString();
m_ActElement = new LogViewXdrStruct(name, LogViewXdrElement::e_KindEnum, a_enumSize); m_ActElement = new LogViewXdrStruct(name, LogViewXdrElement::e_KindEnum, a_enumSize);
if (!addToElementMap(name, m_ActElement)) if (!addToElementMap(name, m_ActElement))
{ {
@@ -524,7 +525,7 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
if (!isNextWord("}", false)) if (!isNextWord("}", false))
{ {
QString keyword = getNextWord(); QString keyword = getNextWord();
if (keyword == QLatin1String("case")) if (keyword == QStringLiteral("case"))
{ {
@@ -542,7 +543,7 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
type = getNextWord("Typ"); type = getNextWord("Typ");
if (type.isEmpty()) return; if (type.isEmpty()) return;
} }
while (type == QLatin1String("case")); while (type == QStringLiteral("case"));
getElement(type); getElement(type);
@@ -565,13 +566,13 @@ void LogViewXdrParser::parseUnion(const QString& a_line)
} }
} }
} }
else if (keyword == QLatin1String("default")) else if (keyword == QStringLiteral("default"))
{ {
if (isNextWord(":")) if (isNextWord(":"))
{ {
QString defaultDefinition = getNextWord(); QString defaultDefinition = getNextWord();
if (defaultDefinition == QLatin1String("void")) if (defaultDefinition == QStringLiteral("void"))
{ {
isNextWord(";"); isNextWord(";");
@@ -617,8 +618,8 @@ bool LogViewXdrParser::parseEnumLine(const QString& a_line, QString& a_name, QSt
int sepPos = line.lastIndexOf(QLatin1Char('=')); int sepPos = line.lastIndexOf(QLatin1Char('='));
if (-1 != sepPos) if (-1 != sepPos)
{ {
a_name = line.leftRef(sepPos).trimmed().toString(); a_name = QStringView(line).left(sepPos).trimmed().toString();
a_value = line.midRef(sepPos+1).trimmed().toString(); a_value = QStringView(line).mid(sepPos+1).trimmed().toString();
return true; return true;
} }
else else
@@ -864,13 +865,13 @@ bool LogViewXdrParser::isNextWord(const char *a_word, const bool a_doIncrement)
void LogViewXdrParser::fillWordList(const QString& a_line) void LogViewXdrParser::fillWordList(const QString& a_line)
{ {
QString line = a_line; QString line = a_line;
line.replace(QLatin1Char('('), QLatin1String(" ( ")); line.replace(QLatin1Char('('), QStringLiteral(" ( "));
line.replace(QLatin1Char(')'), QLatin1String(" ) ")); line.replace(QLatin1Char(')'), QStringLiteral(" ) "));
line.replace(QLatin1Char('{'), QLatin1String(" { ")); line.replace(QLatin1Char('{'), QStringLiteral(" { "));
line.replace(QLatin1Char('}'), QLatin1String(" } ")); line.replace(QLatin1Char('}'), QStringLiteral(" } "));
line.replace(QLatin1Char(':'), QLatin1String(" : ")); line.replace(QLatin1Char(':'), QStringLiteral(" : "));
line.replace(QLatin1Char(';'), QLatin1String(" ; ")); line.replace(QLatin1Char(';'), QStringLiteral(" ; "));
m_WordList = line.split(QLatin1Char(' '), QString::SkipEmptyParts); m_WordList = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);
m_WordListIndex = 0; m_WordListIndex = 0;
@@ -906,8 +907,8 @@ QString LogViewXdrParser::getNextType(bool& a_ok)
a_ok = true; a_ok = true;
QString type = getNextWord("Typ"); QString type = getNextWord("Typ");
if (type.isEmpty()) a_ok = false; if (type.isEmpty()) a_ok = false;
if (type == QLatin1String("unsigned") || if (type == QStringLiteral("unsigned") ||
type == QLatin1String("signed")) type == QStringLiteral("signed"))
{ {
QString type2 = getNextWord("Typ"); QString type2 = getNextWord("Typ");
if (type2.isEmpty()) a_ok = false; if (type2.isEmpty()) a_ok = false;
@@ -951,7 +952,7 @@ bool LogViewXdrParser::parseBitfield(const QString& a_fieldText, int16_t& a_firs
a_lastBit = -1; a_lastBit = -1;
bool isLast = true; bool isLast = true;
int doublePointPos = a_fieldText.indexOf(QLatin1String("..")); int doublePointPos = a_fieldText.indexOf(QStringLiteral(".."));
if (doublePointPos != -1) if (doublePointPos != -1)
{ {
QString bitText = a_fieldText.left(doublePointPos); QString bitText = a_fieldText.left(doublePointPos);
@@ -174,6 +174,7 @@ namespace N_LogView
bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element); bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element);
private: private:
LOGGER_T m_logger;
}; };
} }
@@ -89,8 +89,8 @@ bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString
a_value = (a_value >> bitshift) & mask; 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_FirstBit, QStringLiteral("<b>"));
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_LastBit+1, QLatin1String("</b>")); a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_LastBit+1, QStringLiteral("</b>"));
return m_IsLast; return m_IsLast;
} }
return true; return true;
@@ -0,0 +1,32 @@
# Unit tests for LogView.
# LogView itself is an executable, so it cannot be linked into a test binary.
# The non-GUI sources under test are compiled directly into the test executable
# instead. GoogleTest is resolved once in the top-level CMakeLists.txt.
set(logview_under_test
${CMAKE_CURRENT_SOURCE_DIR}/../logger.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../LogViewField.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../LogViewXdrElement.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../LogViewXdrStandardType.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../LogViewTetraTelegramsParser.cpp
)
add_executable(LogViewTests
${CMAKE_CURRENT_SOURCE_DIR}/../../unittest_main.cpp
LogViewFieldTest.cpp
LogViewTetraTelegramsParserTest.cpp
${logview_under_test}
)
target_include_directories(LogViewTests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/..
)
target_link_libraries(LogViewTests PRIVATE
NGLLogger
Qt6::Core
GTest::gtest
)
include(GoogleTest)
gtest_discover_tests(LogViewTests)
@@ -0,0 +1,195 @@
/**
* @file LogViewFieldTest.cpp
* @brief Unit tests for N_LogView::LogViewField.
*
* LogViewField is the tree node LogView builds from a telegram specification.
* These tests cover the name/label handling, the value list, the child tree and
* the timestamp-field detection. They deliberately avoid the accessors that
* dereference the XDR element, which needs a parsed specification file.
*/
#include <gtest/gtest.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include "LogViewField.hpp"
using N_LogView::LogViewField;
namespace
{
LogViewField makeField(const QString &name,
LogViewField::E_FieldKind kind = LogViewField::e_FieldKindEdit)
{
return LogViewField(name, kind, nullptr);
}
} // namespace
TEST(LogViewFieldTest, ConstructorStoresNameAndKind)
{
const LogViewField field = makeField(QStringLiteral("issi"), LogViewField::e_FieldKindBorder);
EXPECT_EQ(field.name(), QStringLiteral("issi"));
EXPECT_EQ(field.kind(), LogViewField::e_FieldKindBorder);
EXPECT_EQ(field.xdrElement(), nullptr);
}
TEST(LogViewFieldTest, SetNameReplacesTheName)
{
LogViewField field = makeField(QStringLiteral("old"));
field.setName(QStringLiteral("new"));
EXPECT_EQ(field.name(), QStringLiteral("new"));
}
TEST(LogViewFieldTest, MakeCleanCapitalisesWordsAndDropsUnderscores)
{
EXPECT_EQ(LogViewField::makeClean(QStringLiteral("utm_nordwert")),
QStringLiteral("Utm Nordwert"));
EXPECT_EQ(LogViewField::makeClean(QStringLiteral("issi")), QStringLiteral("Issi"));
}
TEST(LogViewFieldTest, MakeCleanStripsTheRecordTypeSuffix)
{
EXPECT_EQ(LogViewField::makeClean(QStringLiteral("gef_header_rt")),
QStringLiteral("Gef Header"));
}
TEST(LogViewFieldTest, MakeCleanHandlesTheEmptyString)
{
EXPECT_EQ(LogViewField::makeClean(QString()), QString());
}
TEST(LogViewFieldTest, CleanNameUsesMakeClean)
{
const LogViewField field = makeField(QStringLiteral("gps_zeit"));
EXPECT_EQ(field.cleanName(), LogViewField::makeClean(QStringLiteral("gps_zeit")));
}
TEST(LogViewFieldTest, ValueListStartsEmpty)
{
const LogViewField field = makeField(QStringLiteral("issi"));
EXPECT_EQ(field.valueListSize(), 0);
EXPECT_TRUE(field.value(0).isEmpty());
}
TEST(LogViewFieldTest, AddValueAppendsInOrder)
{
LogViewField field = makeField(QStringLiteral("issi"));
field.addValue(QStringLiteral("11"));
field.addValue(QStringLiteral("22"));
EXPECT_EQ(field.valueListSize(), 2);
EXPECT_EQ(field.value(0), QStringLiteral("11"));
EXPECT_EQ(field.value(1), QStringLiteral("22"));
}
TEST(LogViewFieldTest, ValueReturnsEmptyForAnOutOfRangeIndex)
{
LogViewField field = makeField(QStringLiteral("issi"));
field.addValue(QStringLiteral("11"));
EXPECT_TRUE(field.value(1).isEmpty());
EXPECT_TRUE(field.value(99).isEmpty());
}
TEST(LogViewFieldTest, AddValueBinaryHexExpandsToDecimalBytes)
{
LogViewField field = makeField(QStringLiteral("payload"));
field.addValueBinaryHex(QStringLiteral("00ff10"));
ASSERT_EQ(field.valueListSize(), 3);
EXPECT_EQ(field.value(0), QStringLiteral("0"));
EXPECT_EQ(field.value(1), QStringLiteral("255"));
EXPECT_EQ(field.value(2), QStringLiteral("16"));
}
TEST(LogViewFieldTest, DateTimeFieldIsDetectedCaseInsensitively)
{
EXPECT_TRUE(makeField(QStringLiteral("gps_zeit")).isDateTimeField());
EXPECT_TRUE(makeField(QStringLiteral("GPS_ZEIT")).isDateTimeField());
EXPECT_FALSE(makeField(QStringLiteral("issi")).isDateTimeField());
}
TEST(LogViewFieldTest, MSecsFieldIsDetectedCaseInsensitively)
{
EXPECT_TRUE(makeField(QStringLiteral("timestamp")).isMSecsField());
EXPECT_TRUE(makeField(QStringLiteral("EffectStart")).isMSecsField());
EXPECT_FALSE(makeField(QStringLiteral("gps_zeit")).isMSecsField());
}
TEST(LogViewFieldTest, RawValueSkipsTheTimestampConversion)
{
LogViewField field = makeField(QStringLiteral("timestamp"));
field.addValue(QStringLiteral("1500000000000"));
EXPECT_EQ(field.value(0, true), QStringLiteral("1500000000000"));
EXPECT_NE(field.value(0), QStringLiteral("1500000000000"));
}
TEST(LogViewFieldTest, ScalarPropertiesRoundTrip)
{
LogViewField field = makeField(QStringLiteral("issi"));
field.setType(QStringLiteral("uint32_t"));
field.setSize(4);
field.setIsRightAligned(true);
field.setToolTipText(QStringLiteral("individual subscriber identity"));
field.setHasContent(false);
EXPECT_EQ(field.type(), QStringLiteral("uint32_t"));
EXPECT_EQ(field.size(), 4);
EXPECT_TRUE(field.isRightAligned());
EXPECT_EQ(field.toolTipText(), QStringLiteral("individual subscriber identity"));
EXPECT_FALSE(field.hasContent());
}
TEST(LogViewFieldTest, MaxArraySizeCarriesTheDynamicFlag)
{
LogViewField field = makeField(QStringLiteral("players"));
field.setMaxArraySize(8, false);
EXPECT_EQ(field.maxArraySize(), 8);
EXPECT_FALSE(field.isDynamicArray());
field.setMaxArraySize(16, true);
EXPECT_EQ(field.maxArraySize(), 16);
EXPECT_TRUE(field.isDynamicArray());
}
TEST(LogViewFieldTest, JsonPathRoundTrips)
{
LogViewField field = makeField(QStringLiteral("issi"));
const QStringList path{QStringLiteral("header"), QStringLiteral("issi")};
field.setJsonPath(path);
EXPECT_EQ(field.jsonPath(), path);
}
TEST(LogViewFieldTest, ChildrenAreOwnedAndOrdered)
{
LogViewField parent(QStringLiteral("header"), LogViewField::e_FieldKindBorder, nullptr);
EXPECT_EQ(parent.childCount(), 0);
auto *first = new LogViewField(QStringLiteral("a"), LogViewField::e_FieldKindEdit, nullptr);
auto *second = new LogViewField(QStringLiteral("b"), LogViewField::e_FieldKindEdit, nullptr);
parent.addChild(first);
parent.addChild(second);
ASSERT_EQ(parent.childCount(), 2);
EXPECT_EQ(parent.child(0), first);
EXPECT_EQ(parent.child(1), second);
parent.removeLastChild();
EXPECT_EQ(parent.childCount(), 1);
EXPECT_EQ(parent.child(0), first);
}
@@ -0,0 +1,244 @@
/**
* @file LogViewTetraTelegramsParserTest.cpp
* @brief Unit tests for N_LogView::LogViewTetraTelegramsParser.
*
* The parser reads the C++ telegram specification header and exposes the
* structs, enums and POD types it found. It is pure logic with no GUI
* dependency, so each test feeds it a small specification written to a
* temporary file and inspects the resulting model.
*/
#include <gtest/gtest.h>
#include <QtCore/QString>
#include <QtCore/QTemporaryDir>
#include "LogViewTetraTelegramsParser.hpp"
using N_LogView::EnumInformation;
using N_LogView::LogViewTetraTelegramsParser;
using N_LogView::MemberInformation;
using N_LogView::PodInformation;
using N_LogView::StructInformation;
namespace
{
// Writes a specification snippet to a file inside dir and parses it.
bool parseSpecification(LogViewTetraTelegramsParser &parser,
const QTemporaryDir &dir,
const QString &content)
{
const QString path = dir.filePath(QStringLiteral("spec.h"));
QFile f(path);
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate))
return false;
f.write(content.toUtf8());
f.close();
return parser.parse(path);
}
const MemberInformation *findMember(const StructInformation &si, const QString &name)
{
for (const MemberInformation &mi : si.member)
{
if (mi.name == name)
return &mi;
}
return nullptr;
}
} // namespace
TEST(LogViewTetraTelegramsParserTest, BuiltinPodTypesAreKnownUpFront)
{
const LogViewTetraTelegramsParser parser;
EXPECT_TRUE(parser.isPod(QStringLiteral("bool")));
EXPECT_TRUE(parser.isPod(QStringLiteral("int32_t")));
EXPECT_FALSE(parser.isPod(QStringLiteral("NotAType")));
const PodInformation pod = parser.podFromType(QStringLiteral("int32_t"));
EXPECT_EQ(pod.byteLen, 4);
EXPECT_TRUE(pod.isIntegral);
EXPECT_TRUE(pod.isSigned);
}
TEST(LogViewTetraTelegramsParserTest, ParsingAMissingFileFails)
{
LogViewTetraTelegramsParser parser;
EXPECT_FALSE(parser.parse(QStringLiteral("/does/not/exist/spec.h")));
}
TEST(LogViewTetraTelegramsParserTest, ASimpleStructIsCollected)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"struct Header\n"
"{\n"
" int32_t equipmentNumber;\n"
" double offset;\n"
"};\n")));
ASSERT_TRUE(parser.isStruct(QStringLiteral("Header")));
const StructInformation si = parser.structFromType(QStringLiteral("Header"));
EXPECT_EQ(si.type, QStringLiteral("Header"));
EXPECT_TRUE(si.baseStruct.isEmpty());
ASSERT_EQ(si.member.size(), 2);
const MemberInformation *eqNr = findMember(si, QStringLiteral("equipmentNumber"));
ASSERT_NE(eqNr, nullptr);
EXPECT_EQ(eqNr->type, QStringLiteral("int32_t"));
EXPECT_TRUE(eqNr->isPod);
EXPECT_FALSE(eqNr->isArray);
}
TEST(LogViewTetraTelegramsParserTest, UnsignedFixedWidthTypesAreNotBuiltinPods)
{
// The built-in POD table only holds bool, int, int32_t, qint64, float and
// double. Unsigned fixed-width types are therefore not recognised as PODs.
const LogViewTetraTelegramsParser parser;
EXPECT_FALSE(parser.isPod(QStringLiteral("uint32_t")));
EXPECT_FALSE(parser.isPod(QStringLiteral("uint8_t")));
}
TEST(LogViewTetraTelegramsParserTest, BaseStructIsRecorded)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"struct Header\n"
"{\n"
" uint32_t equipmentNumber;\n"
"};\n"
"struct Position : public Header\n"
"{\n"
" int32_t easting;\n"
"};\n")));
ASSERT_TRUE(parser.isStruct(QStringLiteral("Position")));
const StructInformation si = parser.structFromType(QStringLiteral("Position"));
EXPECT_EQ(si.baseStruct, QStringLiteral("Header"));
// Base members are merged in after parsing, so the derived struct sees both.
EXPECT_NE(findMember(si, QStringLiteral("easting")), nullptr);
EXPECT_NE(findMember(si, QStringLiteral("equipmentNumber")), nullptr);
}
TEST(LogViewTetraTelegramsParserTest, EnumValuesAreNumberedImplicitlyAndExplicitly)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"enum class State\n"
"{\n"
" Unknown = 0,\n"
" Alive = 1,\n"
" Dead = 7,\n"
"};\n")));
ASSERT_TRUE(parser.isEnum(QStringLiteral("State")));
const EnumInformation ei = parser.enumFromType(QStringLiteral("State"));
ASSERT_EQ(ei.values.size(), 3);
EXPECT_EQ(ei.values.at(0).key, QStringLiteral("Unknown"));
EXPECT_EQ(ei.values.at(0).value, 0);
EXPECT_EQ(ei.values.at(1).key, QStringLiteral("Alive"));
EXPECT_EQ(ei.values.at(1).value, 1);
EXPECT_EQ(ei.values.at(2).key, QStringLiteral("Dead"));
EXPECT_EQ(ei.values.at(2).value, 7);
}
TEST(LogViewTetraTelegramsParserTest, ImplicitEnumValuesKeepTheTrailingComma)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"enum class State\n"
"{\n"
" Unknown,\n"
" Alive,\n"
"};\n")));
const EnumInformation ei = parser.enumFromType(QStringLiteral("State"));
ASSERT_EQ(ei.values.size(), 2);
// Known parser limitation: the trailing comma is only stripped from the value
// of an "Key = value," entry, never from the key of an implicitly numbered
// one. The shipped specification files always use explicit values.
EXPECT_EQ(ei.values.at(0).key, QStringLiteral("Unknown,"));
EXPECT_EQ(ei.values.at(0).value, 0);
EXPECT_EQ(ei.values.at(1).key, QStringLiteral("Alive,"));
EXPECT_EQ(ei.values.at(1).value, 1);
}
TEST(LogViewTetraTelegramsParserTest, StringAndBinaryMembersAreCategorised)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"struct Payload\n"
"{\n"
" std::string name;\n"
" std::vector<unsigned char> raw;\n"
"};\n")));
const StructInformation si = parser.structFromType(QStringLiteral("Payload"));
const MemberInformation *name = findMember(si, QStringLiteral("name"));
const MemberInformation *raw = findMember(si, QStringLiteral("raw"));
ASSERT_NE(name, nullptr);
ASSERT_NE(raw, nullptr);
EXPECT_TRUE(name->isString);
EXPECT_TRUE(raw->isBinary);
}
TEST(LogViewTetraTelegramsParserTest, VectorMembersAreMarkedAsArrays)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"struct Group\n"
"{\n"
" std::vector<uint32_t> issis;\n"
"};\n")));
const StructInformation si = parser.structFromType(QStringLiteral("Group"));
const MemberInformation *issis = findMember(si, QStringLiteral("issis"));
ASSERT_NE(issis, nullptr);
EXPECT_TRUE(issis->isArray);
}
TEST(LogViewTetraTelegramsParserTest, GetInnerTypeUnwrapsTemplateArguments)
{
EXPECT_EQ(LogViewTetraTelegramsParser::getInnerType(QStringLiteral("std::vector<uint32_t>")),
QStringLiteral("uint32_t"));
EXPECT_TRUE(LogViewTetraTelegramsParser::getInnerType(QStringLiteral("uint32_t")).isEmpty());
}
TEST(LogViewTetraTelegramsParserTest, NoTelegramsAreVisibleWithoutConstraints)
{
QTemporaryDir dir;
ASSERT_TRUE(dir.isValid());
LogViewTetraTelegramsParser parser;
ASSERT_TRUE(parseSpecification(parser, dir, QStringLiteral(
"struct Header\n"
"{\n"
" uint32_t equipmentNumber;\n"
"};\n")));
EXPECT_TRUE(parser.telegramsToCreate().isEmpty());
EXPECT_TRUE(parser.nameFromTelegramId(1).isEmpty());
}
@@ -76,3 +76,8 @@ NGL_TARGET_LINK_LIBRARIES(PrtCnv
NGL_INSTALL_TARGET(PrtCnv) NGL_INSTALL_TARGET(PrtCnv)
NGL_INSTALL(AAR SV FILES log4cxx_prtcnv.props DESTINATION bin) NGL_INSTALL(AAR SV FILES log4cxx_prtcnv.props DESTINATION bin)
NGL_INSTALL(AAR SV FILES PrtCnv.dat.tts DESTINATION bin) NGL_INSTALL(AAR SV FILES PrtCnv.dat.tts DESTINATION bin)
# Unit tests (LTS_HAVE_GTEST is set by the top-level CMakeLists.txt)
if(BUILD_TESTING AND LTS_HAVE_GTEST)
add_subdirectory(unittest)
endif()
@@ -41,19 +41,19 @@ int main(int argc, char **argv)
TetraIF::usage(); TetraIF::usage();
} }
const QString mode = args[3].toLower(); const QString mode = args[3].toLower();
if (mode != QLatin1String("listen") && if (mode != QStringLiteral("listen") &&
mode != QLatin1String("send_random") && mode != QStringLiteral("send_random") &&
mode != QLatin1String("send_file")) mode != QStringLiteral("send_file"))
{ {
ERROR_LOG(logger) << "Invalid mode " << args[3]; ERROR_LOG(logger) << "Invalid mode " << args[3];
TetraIF::usage(); TetraIF::usage();
} }
TetraIF t(tetra, port, issi); TetraIF t(tetra, port, issi);
if (mode == QLatin1String("listen")) if (mode == QStringLiteral("listen"))
t.listenMode(args.mid(4)); t.listenMode(args.mid(4));
else if (mode == QLatin1String("send_random")) else if (mode == QStringLiteral("send_random"))
t.randomMode(args.mid(4)); t.randomMode(args.mid(4));
else if (mode == QLatin1String("send_file")) else if (mode == QStringLiteral("send_file"))
t.fileMode(args.mid(4)); t.fileMode(args.mid(4));
t.start(); t.start();
@@ -19,7 +19,9 @@
#include <PrtCnv/PrtCnvRadioThread.hpp> #include <PrtCnv/PrtCnvRadioThread.hpp>
#include <PrtCnv/PrtCnvThreadStarter.hpp> #include <PrtCnv/PrtCnvThreadStarter.hpp>
TetraIF::TetraIF(const QHostAddress &addr, unsigned short port, unsigned short issi) : QObject() TetraIF::TetraIF(const QHostAddress &addr, unsigned short port, unsigned short issi)
: QObject()
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger())
, m_addr(addr) , m_addr(addr)
, m_port(port) , m_port(port)
, m_issi(issi) , m_issi(issi)
@@ -30,12 +32,11 @@ TetraIF::TetraIF(const QHostAddress &addr, unsigned short port, unsigned short i
, m_secondFragment(0) , m_secondFragment(0)
, m_timer(nullptr) , m_timer(nullptr)
, m_SendCounter(0) , m_SendCounter(0)
), {
m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()) {
connect(m_socket, &QTcpSocket::connected, this, &TetraIF::onConnected); connect(m_socket, &QTcpSocket::connected, this, &TetraIF::onConnected);
connect(m_socket, &QTcpSocket::disconnected, this, &TetraIF::onDisconnected); connect(m_socket, &QTcpSocket::disconnected, this, &TetraIF::onDisconnected);
connect(m_socket, &QTcpSocket::readyRead, this, &TetraIF::onReadyRead); connect(m_socket, &QTcpSocket::readyRead, this, &TetraIF::onReadyRead);
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &TetraIF::onError); connect(m_socket, &QTcpSocket::errorOccurred, this, &TetraIF::onError);
m_outputDir = QCoreApplication::applicationDirPath(); m_outputDir = QCoreApplication::applicationDirPath();
m_outputDir += QLatin1Char('/') + QString::number(m_issi) + QLatin1Char('-'); m_outputDir += QLatin1Char('/') + QString::number(m_issi) + QLatin1Char('-');
@@ -303,7 +304,7 @@ void TetraIF::dumpData(const QByteArray &data)
const qint64 msecs = QDateTime::currentMSecsSinceEpoch(); const qint64 msecs = QDateTime::currentMSecsSinceEpoch();
const QString timeStr = QStringLiteral("%1.%2").arg(msecs / 1000).arg(msecs % 1000); const QString timeStr = QStringLiteral("%1.%2").arg(msecs / 1000).arg(msecs % 1000);
{ {
QFile f(m_outputDir + timeStr + QLatin1String(".dat")); QFile f(m_outputDir + timeStr + QStringLiteral(".dat"));
if (!f.open(QIODevice::WriteOnly)) if (!f.open(QIODevice::WriteOnly))
{ {
ERROR_LOG(m_logger) << "Error opening file " ERROR_LOG(m_logger) << "Error opening file "
@@ -406,7 +407,7 @@ QString TetraIF::getIssisAsString() const
{ {
QString ret; QString ret;
for (unsigned short issi : std::as_const(m_issiList)) for (unsigned short issi : std::as_const(m_issiList))
ret += QString::number(issi) + QLatin1String(", "); ret += QString::number(issi) + QStringLiteral(", ");
return ret.left(ret.size() - 2); return ret.left(ret.size() - 2);
} }
@@ -71,7 +71,7 @@ void MainWindow::slot_analysieren()
ui->labelResult->setText(QString()); ui->labelResult->setText(QString());
QString ISSI = ui->lineEditISSI->text(); QString ISSI = ui->lineEditISSI->text();
if (ISSI.isEmpty()) if (ISSI.isEmpty())
ISSI = QLatin1String("1"); ISSI = QStringLiteral("1");
m_logfileList.clear(); m_logfileList.clear();
@@ -79,8 +79,8 @@ void MainWindow::slot_analysieren()
m_files = folder.entryList(); m_files = folder.entryList();
folder.~QDir(); folder.~QDir();
ui->progressBar->setValue(1); ui->progressBar->setValue(1);
const QString paytext = ISSI + QLatin1String("-payload"); const QString paytext = ISSI + QStringLiteral("-payload");
const QString issitext = ISSI + QLatin1String("-1"); const QString issitext = ISSI + QStringLiteral("-1");
for (int i = 0; i < m_files.count(); i++) for (int i = 0; i < m_files.count(); i++)
{ {
@@ -92,7 +92,7 @@ void MainWindow::slot_analysieren()
} }
else else
{ {
if (!name.contains(QLatin1String(".dat"))) if (!name.contains(QStringLiteral(".dat")))
{ {
m_files.removeAt(i); m_files.removeAt(i);
i--; i--;
@@ -119,7 +119,7 @@ void MainWindow::slot_analysieren()
readFiles(); readFiles();
ui->progressBar->setValue(90); ui->progressBar->setValue(90);
ui->progressBar->repaint(); ui->progressBar->repaint();
QString ausgabetext = QLatin1String("\tANALYSIS COMPLETED - ") + QString::number(auswerten()) + QLatin1String(" missing messages"); QString ausgabetext = QStringLiteral("\tANALYSIS COMPLETED - ") + QString::number(auswerten()) + QStringLiteral(" missing messages");
ui->labelResult->setText(ausgabetext); ui->labelResult->setText(ausgabetext);
} }
ui->progressBar->setValue(100); ui->progressBar->setValue(100);
@@ -181,7 +181,7 @@ void MainWindow::openLogfile(const QString &folder, int count)
{ {
m_logfile = folder; m_logfile = folder;
m_logZeiten = folder; m_logZeiten = folder;
m_logfile += QLatin1String("/logfile_analysis.txt"); m_logfile += QStringLiteral("/logfile_analysis.txt");
QFile file(m_logfile); QFile file(m_logfile);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) if (file.open(QIODevice::WriteOnly | QIODevice::Text))
{ {
@@ -189,7 +189,7 @@ void MainWindow::openLogfile(const QString &folder, int count)
file.write(msg.toUtf8()); file.write(msg.toUtf8());
file.close(); file.close();
} }
m_logZeiten += QLatin1String("/transmission_times.csv"); m_logZeiten += QStringLiteral("/transmission_times.csv");
file.setFileName(m_logZeiten); file.setFileName(m_logZeiten);
if (file.open(QIODevice::WriteOnly)) if (file.open(QIODevice::WriteOnly))
{ {
@@ -206,13 +206,13 @@ void MainWindow::writeToLogfile(const QString &issi,
const QString &bytes) const QString &bytes)
{ {
QString text = issi; QString text = issi;
text += QLatin1String(": "); text += QStringLiteral(": ");
text += timestamp.toString(QLatin1String("dd.MM.yyyy hh:mm:ss")); text += timestamp.toString(QStringLiteral("dd.MM.yyyy hh:mm:ss"));
text += QLatin1String(" - "); text += QStringLiteral(" - ");
text += filename; text += filename;
text += QLatin1String(" -> "); text += QStringLiteral(" -> ");
text += bytes; text += bytes;
text += QLatin1String(" --> "); text += QStringLiteral(" --> ");
text += QString::number(lfdNr, 10); text += QString::number(lfdNr, 10);
text += QLatin1Char('\n'); text += QLatin1Char('\n');
QFile file(m_logfile); QFile file(m_logfile);
@@ -235,13 +235,13 @@ void MainWindow::writeToLogfile(const QString &issi,
uint lfdNr) uint lfdNr)
{ {
QString text = issi; QString text = issi;
text += QLatin1String(": "); text += QStringLiteral(": ");
text += sendeZeit.toString(QLatin1String("hh:mm:ss")); text += sendeZeit.toString(QStringLiteral("hh:mm:ss"));
text += QLatin1String(" --> "); text += QStringLiteral(" --> ");
text += timestamp.toString(QLatin1String("dd.MM.yyyy hh:mm:ss")); text += timestamp.toString(QStringLiteral("dd.MM.yyyy hh:mm:ss"));
text += QLatin1String(" - "); text += QStringLiteral(" - ");
text += filename; text += filename;
text += QLatin1String(" --> "); text += QStringLiteral(" --> ");
text += QString::number(lfdNr, 10); text += QString::number(lfdNr, 10);
text += QLatin1Char('\n'); text += QLatin1Char('\n');
QFile file(m_logfile); QFile file(m_logfile);
@@ -416,9 +416,9 @@ void MainWindow::writeLogZeiten(const QDateTime &beginn, const QDateTime &end, c
{ {
QString msg = issi; QString msg = issi;
msg += QLatin1Char(';'); msg += QLatin1Char(';');
msg += beginn.toString(QLatin1String("hh:mm:ss")); msg += beginn.toString(QStringLiteral("hh:mm:ss"));
msg += QLatin1Char(';'); msg += QLatin1Char(';');
msg += end.toString(QLatin1String("hh:mm:ss")); msg += end.toString(QStringLiteral("hh:mm:ss"));
msg += QLatin1Char('\n'); msg += QLatin1Char('\n');
QFile file(m_logZeiten); QFile file(m_logZeiten);
file.open(QIODevice::Append | QIODevice::Text); file.open(QIODevice::Append | QIODevice::Text);
@@ -53,7 +53,7 @@ static std::string threadIdToString(PrtCnvApplication::E_ThreadId id)
PrtCnvApplication::PrtCnvApplication() PrtCnvApplication::PrtCnvApplication()
: m_Config(nullptr) : m_Config(nullptr)
, m_exerciseId(0) , m_exerciseId(0)
, m_accessMutex(QMutex::Recursive) , m_logger(getLogger("PrtCnvApplication"))
{} {}
@@ -165,7 +165,7 @@ protected:
mutable QMutex m_accessMutex; mutable QRecursiveMutex m_accessMutex;
QString m_dbDriver; QString m_dbDriver;
QString m_dbHostName; QString m_dbHostName;
@@ -173,6 +173,8 @@ protected:
QString m_dbSchemaName; QString m_dbSchemaName;
QString m_dbUserName; QString m_dbUserName;
QString m_dbPassword; QString m_dbPassword;
LOGGER_T m_logger;
}; };
} }
@@ -12,6 +12,8 @@
#include "PrtCnvBroadcastMgr.hpp" #include "PrtCnvBroadcastMgr.hpp"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <utility> #include <utility>
#include "PrtCnvDbThread.hpp" #include "PrtCnvDbThread.hpp"
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp> #include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
@@ -351,6 +351,7 @@ Q_SIGNALS:
private: private:
NGL::INGLLogger &m_loggerBcRequest; NGL::INGLLogger &m_loggerBcRequest;
NGL::INGLLogger &m_logger;
}; };
} }
@@ -23,7 +23,7 @@
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp> #include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp> #include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
#include <LtsUtils/dds_bitarray.h> #include <LtsUtilsCore/dds_bitarray.h>
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
@@ -798,7 +798,7 @@ bool PrtCnvCentralThread::handleSpecialTelegram(N_CoPrtCnv::CoPrtCnvCentralTeleg
void PrtCnvCentralThread::connectSocket() void PrtCnvCentralThread::connectSocket()
{ {
const QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("EXCTDS01")); const QString host = m_Config->getString(getName(), QStringLiteral("HostName"), QStringLiteral("EXCTDS01"));
if (host == QLatin1String("directConnection")) if (host == QStringLiteral("directConnection"))
{ {
m_bDirectConnection = true; m_bDirectConnection = true;
connected(); connected();
@@ -43,13 +43,7 @@ PrtCnvDbThread::PrtCnvDbThread(const QString &dbDriver,
const QString &dbPassword, const QString &dbPassword,
PrtCnv::PrtCnvThreadStarter *a_parent) PrtCnv::PrtCnvThreadStarter *a_parent)
: PrtCnvThread(a_parent, "PrtCnvDbThread") : PrtCnvThread(a_parent, "PrtCnvDbThread")
, m_BattleFieldOpStateMutex(QMutex::Recursive)
, m_MemberListByIdMutex(QMutex::Recursive)
, m_CentralListMutex(QMutex::Recursive)
, m_OldCentralAckCounter(0) , m_OldCentralAckCounter(0)
, m_RadioListMutex(QMutex::Recursive)
, m_SqlCmdListMutex(QMutex::Recursive)
, m_BroadcastMapMutex(QMutex::Recursive)
, m_DoClean(false) , m_DoClean(false)
, m_DoWaitUntilSqlWritten(false) , m_DoWaitUntilSqlWritten(false)
, m_DoStorePermanent(false) , m_DoStorePermanent(false)
@@ -156,12 +150,12 @@ bool PrtCnvDbThread::createDatabase()
closeDb(); closeDb();
m_db = QSqlDatabase::addDatabase(m_dbDriver, QStringLiteral("PrtCnv")); m_db = QSqlDatabase::addDatabase(m_dbDriver, QStringLiteral("PrtCnv"));
if (m_dbDriver == QLatin1String("QSQLITE")) if (m_dbDriver == QStringLiteral("QSQLITE"))
{ {
QString path = m_Config->getString(getName(), QStringLiteral("DatabaseFileName"), QStringLiteral("telegrams.db")); QString path = m_Config->getString(getName(), QStringLiteral("DatabaseFileName"), QStringLiteral("telegrams.db"));
if (!QDir::isAbsolutePath(path)) if (!QDir::isAbsolutePath(path))
{ {
path = QCoreApplication::applicationDirPath() + QLatin1String("/../") + path; path = QCoreApplication::applicationDirPath() + QStringLiteral("/../") + path;
QFileInfo fi(path); QFileInfo fi(path);
QDir().mkpath(fi.absolutePath()); QDir().mkpath(fi.absolutePath());
} }
@@ -408,7 +402,7 @@ bool PrtCnvDbThread::createDatabase()
ERROR_LOG(m_logger) << "Internal error: conversion of telegram with telId=" << radioTelegram.getTelID() << " from radio to central failed"; ERROR_LOG(m_logger) << "Internal error: conversion of telegram with telId=" << radioTelegram.getTelID() << " from radio to central failed";
} }
if (m_db.driverName() == QLatin1String("QSQLITE")) if (m_db.driverName() == QStringLiteral("QSQLITE"))
{ {
q.exec(QStringLiteral("VACUUM;")); q.exec(QStringLiteral("VACUUM;"));
q.exec(QStringLiteral("PRAGMA journal_mode=WAL;")); q.exec(QStringLiteral("PRAGMA journal_mode=WAL;"));
@@ -213,15 +213,15 @@ namespace PrtCnv
mutable QMutex m_BattleFieldOpStateMutex; mutable QRecursiveMutex m_BattleFieldOpStateMutex;
mutable QMutex m_MemberListByIdMutex; mutable QRecursiveMutex m_MemberListByIdMutex;
mutable QMutex m_CentralListMutex; mutable QRecursiveMutex m_CentralListMutex;
@@ -238,16 +238,16 @@ namespace PrtCnv
std::list<PrtCnvStoredRadioTelegram*> m_RadioList; std::list<PrtCnvStoredRadioTelegram*> m_RadioList;
mutable QMutex m_RadioListMutex; mutable QRecursiveMutex m_RadioListMutex;
std::vector<QString> m_SqlCommandList; std::vector<QString> m_SqlCommandList;
mutable QMutex m_SqlCmdListMutex; mutable QRecursiveMutex m_SqlCmdListMutex;
mutable QMutex m_BroadcastMapMutex; mutable QRecursiveMutex m_BroadcastMapMutex;
std::list<PrtCnvStoredRadioTelegram*> m_BroadcastList; std::list<PrtCnvStoredRadioTelegram*> m_BroadcastList;
@@ -25,6 +25,7 @@ namespace PrtCnv
PrtCnvInjectionSocket::PrtCnvInjectionSocket() PrtCnvInjectionSocket::PrtCnvInjectionSocket()
: m_Socket(nullptr) : m_Socket(nullptr)
, m_Server(nullptr) , m_Server(nullptr)
, m_logger(getLogger("PrtCnvInjectionSocket"))
{} {}
PrtCnvInjectionSocket::~PrtCnvInjectionSocket() PrtCnvInjectionSocket::~PrtCnvInjectionSocket()
@@ -55,7 +55,8 @@ namespace PrtCnv
void disconnected(PrtCnvInjectionSocket* a_injectSocket); void disconnected(PrtCnvInjectionSocket* a_injectSocket);
protected:
LOGGER_T m_logger;
}; };
} }
@@ -88,9 +88,7 @@ PrtCnvRadioThread::PrtCnvRadioThread(int exerciseId, PrtCnvThreadStarter *a_pare
m_ReceivedTelegrams(0), m_ReceivedTelegrams(0),
m_ReceivedBytes(0), m_ReceivedBytes(0),
m_bUseScrambling(false), m_bUseScrambling(false),
m_loggerStats(getLogger("PrtCnvRadioThread.statistic")), m_loggerStats(getLogger("PrtCnvRadioThread.statistic")) {
m_exerciseEquipmentAssignmentMutex(QMutex::Recursive),
m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()) {
m_Name = QStringLiteral("Radio"); m_Name = QStringLiteral("Radio");
for (int i = 0; i < AVERAGE_COUNT; ++i) for (int i = 0; i < AVERAGE_COUNT; ++i)
{ {
@@ -176,7 +174,7 @@ int32_t PrtCnvRadioThread::init()
m_DbThread->licenseMember(m_DbThread->addMember(0, m_BroadcastISSI)); m_DbThread->licenseMember(m_DbThread->addMember(0, m_BroadcastISSI));
QString groupString = m_Config->getString(getName(), QStringLiteral("ListenGroups"), QString()); QString groupString = m_Config->getString(getName(), QStringLiteral("ListenGroups"), QString());
const QVector<QStringView> groups = groupString.splitView(QLatin1Char(','), Qt::SkipEmptyParts); const QList<QStringView> groups = QStringView(groupString).split(QLatin1Char(','), Qt::SkipEmptyParts);
for (const QStringView &sr : groups) for (const QStringView &sr : groups)
{ {
uint32_t group = sr.toUInt(); uint32_t group = sr.toUInt();
@@ -192,7 +190,7 @@ int32_t PrtCnvRadioThread::init()
m_LoginPathWithPrefix = m_Config->getString(QStringLiteral("Login"), QStringLiteral("LoginFilePathWithPrefix"), QStringLiteral("login")); m_LoginPathWithPrefix = m_Config->getString(QStringLiteral("Login"), QStringLiteral("LoginFilePathWithPrefix"), QStringLiteral("login"));
if (!QDir::isAbsolutePath(m_LoginPathWithPrefix)) if (!QDir::isAbsolutePath(m_LoginPathWithPrefix))
m_LoginPathWithPrefix = QCoreApplication::applicationDirPath() + QLatin1String("/../") + m_LoginPathWithPrefix; m_LoginPathWithPrefix = QCoreApplication::applicationDirPath() + QStringLiteral("/../") + m_LoginPathWithPrefix;
m_LoginPathWithPrefix = QDir::cleanPath(QDir::fromNativeSeparators(m_LoginPathWithPrefix)); m_LoginPathWithPrefix = QDir::cleanPath(QDir::fromNativeSeparators(m_LoginPathWithPrefix));
QString path = m_LoginPathWithPrefix.left(m_LoginPathWithPrefix.lastIndexOf(QLatin1Char('/'))); QString path = m_LoginPathWithPrefix.left(m_LoginPathWithPrefix.lastIndexOf(QLatin1Char('/')));
@@ -1524,8 +1522,8 @@ void PrtCnvRadioThread::writeLoginLog(const N_CoPrtCnv::CoPrtCnvRadioTelegram *a
INFO_LOG(m_logger) << logData; INFO_LOG(m_logger) << logData;
QString date = QDate::currentDate().toString(QLatin1String("yyyyMMdd")); QString date = QDate::currentDate().toString(QStringLiteral("yyyyMMdd"));
QString fileName = m_LoginPathWithPrefix + date + QLatin1Char('_') + QString::number(m_ExerciseId) + QLatin1String(".log"); QString fileName = m_LoginPathWithPrefix + date + QLatin1Char('_') + QString::number(m_ExerciseId) + QStringLiteral(".log");
QFile file(fileName); QFile file(fileName);
@@ -263,7 +263,7 @@ public:
std::unordered_map<int, std::unordered_set<int>> m_exerciseEquipmentAssignments; std::unordered_map<int, std::unordered_set<int>> m_exerciseEquipmentAssignments;
std::unordered_map<int, TrainingAreaBase::TetraIcd::GroupIssiInformation> m_groupIssiInformation; std::unordered_map<int, TrainingAreaBase::TetraIcd::GroupIssiInformation> m_groupIssiInformation;
mutable QMutex m_exerciseEquipmentAssignmentMutex; mutable QRecursiveMutex m_exerciseEquipmentAssignmentMutex;
private: private:
@@ -31,7 +31,6 @@ PrtCnvRadioTrafficThread::PrtCnvRadioTrafficThread(PrtCnvThreadStarter* a_parent
, m_hystLoad(5) , m_hystLoad(5)
, m_calcTimeout(1000) , m_calcTimeout(1000)
, m_cleanupTimeout(5000) , m_cleanupTimeout(5000)
, m_mutex(QMutex::Recursive)
{} {}
void PrtCnvRadioTrafficThread::newTelegramArrived(unsigned int size) void PrtCnvRadioTrafficThread::newTelegramArrived(unsigned int size)
@@ -72,7 +72,7 @@ protected:
QMutex m_mutex; QRecursiveMutex m_mutex;
@@ -100,7 +100,7 @@ void PrtCnvSocketThread::createNewSocket()
connect(m_Socket, &QTcpSocket::connected, this, &PrtCnvSocketThread::connected, Qt::QueuedConnection); connect(m_Socket, &QTcpSocket::connected, this, &PrtCnvSocketThread::connected, Qt::QueuedConnection);
connect(m_Socket, &QTcpSocket::disconnected, this, &PrtCnvSocketThread::disconnected, Qt::QueuedConnection); connect(m_Socket, &QTcpSocket::disconnected, this, &PrtCnvSocketThread::disconnected, Qt::QueuedConnection);
connect(m_Socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &PrtCnvSocketThread::error, Qt::QueuedConnection); connect(m_Socket, &QTcpSocket::errorOccurred, this, &PrtCnvSocketThread::error, Qt::QueuedConnection);
connect(m_Socket, &QTcpSocket::hostFound, this, &PrtCnvSocketThread::hostFound, Qt::QueuedConnection); connect(m_Socket, &QTcpSocket::hostFound, this, &PrtCnvSocketThread::hostFound, Qt::QueuedConnection);
connect(m_Socket, &QTcpSocket::stateChanged, this, &PrtCnvSocketThread::stateChanged); connect(m_Socket, &QTcpSocket::stateChanged, this, &PrtCnvSocketThread::stateChanged);
connect(m_Socket, &QTcpSocket::readyRead, this, &PrtCnvSocketThread::readyRead, Qt::QueuedConnection); connect(m_Socket, &QTcpSocket::readyRead, this, &PrtCnvSocketThread::readyRead, Qt::QueuedConnection);
@@ -364,8 +364,8 @@ void PrtCnvSocketThread::readHostAdresses()
uint16_t port = m_Config->getInteger(getName(), QStringLiteral("Port"), 4934); uint16_t port = m_Config->getInteger(getName(), QStringLiteral("Port"), 4934);
m_hostAdresses.push_back(qMakePair(host, port)); m_hostAdresses.push_back(qMakePair(host, port));
for (int i = 1; i < 10; ++i) { for (int i = 1; i < 10; ++i) {
const QString hostName = QLatin1String("HostName") + QString::number(i); const QString hostName = QStringLiteral("HostName") + QString::number(i);
const QString portName = QLatin1String("Port") + QString::number(i); const QString portName = QStringLiteral("Port") + QString::number(i);
host = m_Config->getString(getName(), hostName, QString()); host = m_Config->getString(getName(), hostName, QString());
port = m_Config->getInteger(getName(), portName, 0); port = m_Config->getInteger(getName(), portName, 0);
if (host.isEmpty() || port == 0) if (host.isEmpty() || port == 0)
@@ -36,6 +36,8 @@ protected:
Qt::HANDLE m_currentThreadId; Qt::HANDLE m_currentThreadId;
LOGGER_T m_logger;
public: public:
@@ -33,6 +33,7 @@ PrtCnvThreadStarter::PrtCnvThreadStarter(const PrtCnv::PrtCnvApplication::E_Thre
, m_Application(a_mainApp) , m_Application(a_mainApp)
, m_Id(a_id) , m_Id(a_id)
, m_settings(new NGL::Settings(configFileName)) , m_settings(new NGL::Settings(configFileName))
, m_logger(getLogger("PrtCnvThreadStarter"))
{ {
DEBUG_LOG(m_logger) << "Using Config file '" << configFileName << "'"; DEBUG_LOG(m_logger) << "Using Config file '" << configFileName << "'";
} }
@@ -59,6 +59,8 @@ protected:
void run() override; void run() override;
LOGGER_T m_logger;
}; };
} }
@@ -14,8 +14,8 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
QCoreApplication::setApplicationName(QLatin1String("TTS")); QCoreApplication::setApplicationName(QStringLiteral("TTS"));
QCoreApplication::setOrganizationName(QLatin1String("RME")); QCoreApplication::setOrganizationName(QStringLiteral("RME"));
NGLCoreApplication app(argc, argv); NGLCoreApplication app(argc, argv);
app.createLogger("tts", "log4cxx_tetratestserver.props"); app.createLogger("tts", "log4cxx_tetratestserver.props");
@@ -26,96 +26,96 @@ int main(int argc, char **argv)
LtsCommandLineParser::LtsCommandLineParser options(LtsCommandLineParser::LtsCommandLineParser::CustomConfigFile); LtsCommandLineParser::LtsCommandLineParser options(LtsCommandLineParser::LtsCommandLineParser::CustomConfigFile);
options.addOption({ QStringList() << QLatin1String("p") << QLatin1String("player") options.addOption({ QStringList() << QStringLiteral("p") << QStringLiteral("player")
, QLatin1String("number of players to be simulated.") , QStringLiteral("number of players to be simulated.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("5") , QStringLiteral("5")
}); });
options.addOption({ QStringList() << QLatin1String("n") << QLatin1String("northing") options.addOption({ QStringList() << QStringLiteral("n") << QStringLiteral("northing")
, QLatin1String("initial position UTM north.") , QStringLiteral("initial position UTM north.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("77777") , QStringLiteral("77777")
}); });
options.addOption({ QStringList() << QLatin1String("e") << QLatin1String("easting") options.addOption({ QStringList() << QStringLiteral("e") << QStringLiteral("easting")
, QLatin1String("initial position UTM east.") , QStringLiteral("initial position UTM east.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("99999") , QStringLiteral("99999")
}); });
options.addOption({ QStringList() << QLatin1String("f") << QLatin1String("first-id") options.addOption({ QStringList() << QStringLiteral("f") << QStringLiteral("first-id")
, QLatin1String("first equipment ID to use.") , QStringLiteral("first equipment ID to use.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("1101") , QStringLiteral("1101")
}); });
options.addOption({ QStringList() << QLatin1String("r") << QLatin1String("pprow") options.addOption({ QStringList() << QStringLiteral("r") << QStringLiteral("pprow")
, QLatin1String("players per row.") , QStringLiteral("players per row.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("25") , QStringLiteral("25")
}); });
options.addOption({ QStringList() << QLatin1String("s") << QLatin1String("pspacing") options.addOption({ QStringList() << QStringLiteral("s") << QStringLiteral("pspacing")
, QLatin1String("utm based spacing between the players.") , QStringLiteral("utm based spacing between the players.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("100") , QStringLiteral("100")
}); });
options.addOption({ QStringList() << QLatin1String("z") << QLatin1String("issi") options.addOption({ QStringList() << QStringLiteral("z") << QStringLiteral("issi")
, QLatin1String("DestinationIssi / HostISSI") , QStringLiteral("DestinationIssi / HostISSI")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("2") , QStringLiteral("2")
}); });
options.addOption({ QStringList() << QLatin1String("m") << QLatin1String("movements") options.addOption({ QStringList() << QStringLiteral("m") << QStringLiteral("movements")
, QLatin1String("how many movements per milliseconds to make.") , QStringLiteral("how many movements per milliseconds to make.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("2000") , QStringLiteral("2000")
}); });
options.addOption({ QStringList() << QLatin1String("d") << QLatin1String("death") options.addOption({ QStringList() << QStringLiteral("d") << QStringLiteral("death")
, QLatin1String("minimum times, after the movements timer is triggered, a dead player can revive.") , QStringLiteral("minimum times, after the movements timer is triggered, a dead player can revive.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("100") , QStringLiteral("100")
}); });
options.addOption({ QStringList() << QLatin1String("o") << QLatin1String("death-offset") options.addOption({ QStringList() << QStringLiteral("o") << QStringLiteral("death-offset")
, QLatin1String("maximum times, after the movements timer is triggered, a dead player can revive.") , QStringLiteral("maximum times, after the movements timer is triggered, a dead player can revive.")
, QLatin1String("(0 -> identical to min)") , QStringLiteral("(0 -> identical to min)")
, QLatin1String("0") , QStringLiteral("0")
}); });
options.addOption({ QStringList() << QLatin1String("t") << QLatin1String("pattern") options.addOption({ QStringList() << QStringLiteral("t") << QStringLiteral("pattern")
, QLatin1String("pattern the player has to walk [enter pattern by hand or pattern alias-name from settings file]\r\nfor more info, enter '--pattern-help'.") , QStringLiteral("pattern the player has to walk [enter pattern by hand or pattern alias-name from settings file]\r\nfor more info, enter '--pattern-help'.")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("3,30,20#3,30,-20#3,-30,-20#3,-30,20") , QStringLiteral("3,30,20#3,30,-20#3,-30,-20#3,-30,20")
}); });
options.addOption({ QStringList() << QLatin1String("demand-old-broadcast-telegrams") options.addOption({ QStringList() << QStringLiteral("demand-old-broadcast-telegrams")
, QLatin1String("player demand old broadcast telegrams starting at BCI <default value>") , QStringLiteral("player demand old broadcast telegrams starting at BCI <default value>")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("0") , QStringLiteral("0")
}); });
options.addOption({ QStringList() << QLatin1String("deactivate-single-mines") options.addOption({ QStringList() << QStringLiteral("deactivate-single-mines")
, QLatin1String("the first player deactivates single mines with ids from minimum-mine-id to maximum-mine-id") , QStringLiteral("the first player deactivates single mines with ids from minimum-mine-id to maximum-mine-id")
}); });
options.addOption({ QStringList() << QLatin1String("minimum-mine-id") options.addOption({ QStringList() << QStringLiteral("minimum-mine-id")
, QLatin1String("sets the value for minimum-mine-id used within deactivate-single-mines command") , QStringLiteral("sets the value for minimum-mine-id used within deactivate-single-mines command")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("minimum-mine-id 2048") , QStringLiteral("minimum-mine-id 2048")
}); });
options.addOption({ QStringList() << QLatin1String("maximum-mine-id") options.addOption({ QStringList() << QStringLiteral("maximum-mine-id")
, QLatin1String("sets the value for maximum-mine-Id used within deactivate-single-mines command") , QStringLiteral("sets the value for maximum-mine-Id used within deactivate-single-mines command")
, QLatin1String("Default value") , QStringLiteral("Default value")
, QLatin1String("maximum-mine-id 2100") , QStringLiteral("maximum-mine-id 2100")
}); });
options.addOption({ QStringList() << QLatin1String("pattern-help") options.addOption({ QStringList() << QStringLiteral("pattern-help")
, QLatin1String("help for the pattern interpreter.") , QStringLiteral("help for the pattern interpreter.")
}); });
@@ -124,30 +124,30 @@ int main(int argc, char **argv)
options.showHelp(); options.showHelp();
return -1; return -1;
} }
QSettings serverSettings(app.applicationDirPath() + QLatin1String("/") + options.iniFile(), QSettings::IniFormat); QSettings serverSettings(app.applicationDirPath() + QStringLiteral("/") + options.iniFile(), QSettings::IniFormat);
TTSArgs ttsArgs; TTSArgs ttsArgs;
ttsArgs.destIssi = options.isSet(QLatin1String("issi")) ? options.value(QLatin1String("issi")).toInt() : 2; ttsArgs.destIssi = options.isSet(QStringLiteral("issi")) ? options.value(QStringLiteral("issi")).toInt() : 2;
ttsArgs.cntPlayer = options.isSet(QLatin1String("player")) ? options.value(QLatin1String("player")).toInt() : 0; ttsArgs.cntPlayer = options.isSet(QStringLiteral("player")) ? options.value(QStringLiteral("player")).toInt() : 0;
int northPos_arg = options.isSet(QLatin1String("northing")) ? options.value(QLatin1String("northing")).toInt() : 77777; int northPos_arg = options.isSet(QStringLiteral("northing")) ? options.value(QStringLiteral("northing")).toInt() : 77777;
int eastPos_arg = options.isSet(QLatin1String("easting")) ? options.value(QLatin1String("easting")).toInt() : 90000; int eastPos_arg = options.isSet(QStringLiteral("easting")) ? options.value(QStringLiteral("easting")).toInt() : 90000;
ttsArgs.position = QPointF(eastPos_arg, northPos_arg); ttsArgs.position = QPointF(eastPos_arg, northPos_arg);
ttsArgs.eqIdStart = options.isSet(QLatin1String("first-id")) ? options.value(QLatin1String("first-id")).toInt() : 1101; ttsArgs.eqIdStart = options.isSet(QStringLiteral("first-id")) ? options.value(QStringLiteral("first-id")).toInt() : 1101;
ttsArgs.pprow = options.isSet(QLatin1String("pprow")) ? options.value(QLatin1String("pprow")).toInt() : 25; ttsArgs.pprow = options.isSet(QStringLiteral("pprow")) ? options.value(QStringLiteral("pprow")).toInt() : 25;
ttsArgs.pspacing = options.isSet(QLatin1String("pspacing")) ? options.value(QLatin1String("pspacing")).toInt() : 100; ttsArgs.pspacing = options.isSet(QStringLiteral("pspacing")) ? options.value(QStringLiteral("pspacing")).toInt() : 100;
ttsArgs.movs_per_msec = options.isSet(QLatin1String("movements")) ? options.value(QLatin1String("movements")).toInt() : 2000; ttsArgs.movs_per_msec = options.isSet(QStringLiteral("movements")) ? options.value(QStringLiteral("movements")).toInt() : 2000;
ttsArgs.minimumDeathTicks = options.isSet(QLatin1String("death")) ? options.value(QLatin1String("death")).toInt() : 10; ttsArgs.minimumDeathTicks = options.isSet(QStringLiteral("death")) ? options.value(QStringLiteral("death")).toInt() : 10;
ttsArgs.maximumDeathTicks = options.isSet(QLatin1String("death-offset")) ? options.value(QLatin1String("death-offset")).toInt() : 20; ttsArgs.maximumDeathTicks = options.isSet(QStringLiteral("death-offset")) ? options.value(QStringLiteral("death-offset")).toInt() : 20;
ttsArgs.demandOldBraodcastTelegrams = options.isSet(QLatin1String("demand-old-broadcast-telegrams")) ? true : false; ttsArgs.demandOldBraodcastTelegrams = options.isSet(QStringLiteral("demand-old-broadcast-telegrams")) ? true : false;
if (ttsArgs.demandOldBraodcastTelegrams) if (ttsArgs.demandOldBraodcastTelegrams)
ttsArgs.demandOldBraodcastTelegramsCounter = options.value(QLatin1String("demand-old-broadcast-telegrams")).toInt(); ttsArgs.demandOldBraodcastTelegramsCounter = options.value(QStringLiteral("demand-old-broadcast-telegrams")).toInt();
ttsArgs.deactivationSingleMines = options.isSet(QLatin1String("deactivate-single-mines")) ? true : false; ttsArgs.deactivationSingleMines = options.isSet(QStringLiteral("deactivate-single-mines")) ? true : false;
ttsArgs.minimumMineId = options.isSet(QLatin1String("minimum-mine-id")) ? options.value(QLatin1String("minimum-mine-id")).toInt() : 2048; ttsArgs.minimumMineId = options.isSet(QStringLiteral("minimum-mine-id")) ? options.value(QStringLiteral("minimum-mine-id")).toInt() : 2048;
ttsArgs.maximumMineId = options.isSet(QLatin1String("maximum-mine-id")) ? options.value(QLatin1String("maximum-mine-id")).toInt() : 2100; ttsArgs.maximumMineId = options.isSet(QStringLiteral("maximum-mine-id")) ? options.value(QStringLiteral("maximum-mine-id")).toInt() : 2100;
ttsArgs.pattern = options.isSet(QLatin1String("pattern")) ? options.value(QLatin1String("pattern")) : QLatin1String("3,30,20#3,30,-20#3,-30,-20#3,-30,20"); ttsArgs.pattern = options.isSet(QStringLiteral("pattern")) ? options.value(QStringLiteral("pattern")) : QStringLiteral("3,30,20#3,30,-20#3,-30,-20#3,-30,20");
if (options.isSet(QLatin1String("pattern-help"))) if (options.isSet(QStringLiteral("pattern-help")))
{ {
options.showHelp(); options.showHelp();
return -1; return -1;
@@ -170,9 +170,9 @@ int main(int argc, char **argv)
TTServer *s = new TTServer(ttsArgs); TTServer *s = new TTServer(ttsArgs);
if (!s->listen(QHostAddress::Any, serverSettings.value(QLatin1String("Radio/Port"), 4200).toInt())) if (!s->listen(QHostAddress::Any, serverSettings.value(QStringLiteral("Radio/Port"), 4200).toInt()))
{ {
ERROR_LOG(logger) << "Error listening on localhost:" << serverSettings.value(QLatin1String("Radio/Port"), 52010).toInt() << ": " ERROR_LOG(logger) << "Error listening on localhost:" << serverSettings.value(QStringLiteral("Radio/Port"), 52010).toInt() << ": "
<< s->errorString(); << s->errorString();
delete s; delete s;
return -1; return -1;
@@ -7,9 +7,10 @@
#include "worker.h" #include "worker.h"
TTServer::TTServer(const TTSArgs &ttsArgs) : m_ttsArgs(ttsArgs) TTServer::TTServer(const TTSArgs &ttsArgs)
.getNGLLogger("TTServer")), : m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger())
m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger()) { , m_ttsArgs(ttsArgs)
{
connect(this, &TTServer::newConnection, connect(this, &TTServer::newConnection,
this, &TTServer::onNewConnection); this, &TTServer::onNewConnection);
} }
@@ -21,16 +21,15 @@ TTWorker::TTWorker(QTcpSocket *socket, const TTSArgs &ttsArgs)
, m_ttsArgs(ttsArgs) , m_ttsArgs(ttsArgs)
, m_patternList(interpretPattern(ttsArgs.pattern)) , m_patternList(interpretPattern(ttsArgs.pattern))
, m_generalPosition(ttsArgs.position) , m_generalPosition(ttsArgs.position)
.getNGLLogger("TTWorker")) , m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger())
{ {
qsrand(time(nullptr));
} }
bool TTWorker::init() bool TTWorker::init()
{ {
connect(m_socket, &QTcpSocket::disconnected, connect(m_socket, &QTcpSocket::disconnected,
this, &TTWorker::deleteLater); this, &TTWorker::deleteLater);
connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), connect(m_socket, &QTcpSocket::errorOccurred,
this, &TTWorker::onSocketError); this, &TTWorker::onSocketError);
connect(m_socket, &QTcpSocket::readyRead, connect(m_socket, &QTcpSocket::readyRead,
this, &TTWorker::onReadyRead); this, &TTWorker::onReadyRead);
@@ -87,7 +86,7 @@ QVector<runningPattern> TTWorker::interpretPattern(QString pattern) const
QString patternAlias = pattern; QString patternAlias = pattern;
pattern = m_ttsArgs.settings->value(QLatin1String("pattern/") + patternAlias).toString(); pattern = m_ttsArgs.settings->value(QStringLiteral("pattern/") + patternAlias).toString();
if (pattern.isEmpty()) if (pattern.isEmpty())
{ {
@@ -7,6 +7,7 @@
#include <QtCore/QMap> #include <QtCore/QMap>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QPointF> #include <QtCore/QPointF>
#include <QtCore/QRandomGenerator>
#include <QtCore/QMap> #include <QtCore/QMap>
#include <NGLLogger/INGLLogger.h> #include <NGLLogger/INGLLogger.h>
#include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp> #include <CoPrtCnv/CoPrtCnvCentralTelegram.hpp>
@@ -22,10 +23,9 @@ class QTimer;
class Player class Player
{ {
private: private:
NGL::INGLLogger &m_logger;
void randomizeDeathTicks() void randomizeDeathTicks()
{ {
deathTicks = ((qrand() % (maximumDeathTicks - minimumDeathTicks + 1)) + minimumDeathTicks); deathTicks = QRandomGenerator::global()->bounded(minimumDeathTicks, maximumDeathTicks + 1);
} }
public: public:
@@ -125,4 +125,6 @@ private:
QVector<Player *> m_playerList; QVector<Player *> m_playerList;
QVector<runningPattern> m_patternList; QVector<runningPattern> m_patternList;
QPointF m_generalPosition; QPointF m_generalPosition;
NGL::INGLLogger &m_logger;
}; };
@@ -0,0 +1,26 @@
# Unit tests for PrtCnv.
# PrtCnvLib is built with hidden visibility and PrtCnvMember carries no export
# macro, so the classes under test are compiled into the test executable rather
# than widening the library's public ABI for the tests' sake.
# GoogleTest is resolved once in the top-level CMakeLists.txt.
add_executable(PrtCnvTests
${CMAKE_CURRENT_SOURCE_DIR}/../../unittest_main.cpp
PrtCnvMemberTest.cpp
PrtCnvStoredTelegramTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../PrtCnvMember.cpp
)
target_include_directories(PrtCnvTests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR}/../..
)
target_link_libraries(PrtCnvTests PRIVATE
CoPrtCnv
Qt6::Core
GTest::gtest
)
include(GoogleTest)
gtest_discover_tests(PrtCnvTests)
@@ -0,0 +1,94 @@
/**
* @file PrtCnvMemberTest.cpp
* @brief Unit tests for PrtCnv::PrtCnvMember.
*
* Covers the public state carried per member and the fragmented-telegram
* bookkeeping (collecting fragments, reporting the telegram id, clearing).
*/
#include <gtest/gtest.h>
#include <QtCore/QByteArray>
#include "PrtCnvMember.hpp"
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include <CoPrtCnv/tetra_telegram_ids.h>
using PrtCnv::PrtCnvMember;
using N_CoPrtCnv::CoPrtCnvRadioTelegram;
TEST(PrtCnvMemberTest, ConstructorStoresIdAndIssi)
{
const PrtCnvMember member(17, 4711);
EXPECT_EQ(member.m_Id, 17);
EXPECT_EQ(member.m_ISSI, 4711);
EXPECT_EQ(member.m_ClaimCount, 0);
EXPECT_EQ(member.m_loggedInExerciseId, 0);
EXPECT_FALSE(member.m_Licensed);
}
TEST(PrtCnvMemberTest, PublicStateIsWritable)
{
PrtCnvMember member(1, 2);
member.m_ClaimCount = 3;
member.m_loggedInExerciseId = 42;
member.m_Licensed = true;
EXPECT_EQ(member.m_ClaimCount, 3);
EXPECT_EQ(member.m_loggedInExerciseId, 42);
EXPECT_TRUE(member.m_Licensed);
}
TEST(PrtCnvMemberTest, FragmentedListStartsEmpty)
{
const PrtCnvMember member(1, 2);
EXPECT_TRUE(member.isFragmentedListEmpty());
EXPECT_TRUE(member.getUnfragmentedTelegramData().isEmpty());
}
TEST(PrtCnvMemberTest, AddingAFragmentFillsTheList)
{
PrtCnvMember member(1, 2);
const CoPrtCnvRadioTelegram fragment(GEF_GEFECHTSFELDTELEGRAMM, 8, 0);
member.addFragmentedTelegram(fragment);
EXPECT_FALSE(member.isFragmentedListEmpty());
}
TEST(PrtCnvMemberTest, ClearFragmentedListEmptiesTheList)
{
PrtCnvMember member(1, 2);
const CoPrtCnvRadioTelegram fragment(GEF_GEFECHTSFELDTELEGRAMM, 8, 0);
member.addFragmentedTelegram(fragment);
ASSERT_FALSE(member.isFragmentedListEmpty());
member.clearFragmentedList();
EXPECT_TRUE(member.isFragmentedListEmpty());
}
TEST(PrtCnvMemberTest, ClearFragmentedListIsIdempotent)
{
PrtCnvMember member(1, 2);
member.clearFragmentedList();
member.clearFragmentedList();
EXPECT_TRUE(member.isFragmentedListEmpty());
}
TEST(PrtCnvMemberTest, TelegramIdFallsBackWhenNoFirstFragmentIsPresent)
{
PrtCnvMember member(1, 2);
// A telegram built from the plain telegram-id constructor is not fragmented,
// so no entry qualifies as the first fragment of a fragmented telegram.
const CoPrtCnvRadioTelegram fragment(GEF_GEFECHTSFELDTELEGRAMM, 8, 0);
member.addFragmentedTelegram(fragment);
EXPECT_EQ(member.getFragmentedTelegramId(), GEF_BESTAETIGUNG);
}
@@ -0,0 +1,100 @@
/**
* @file PrtCnvStoredTelegramTest.cpp
* @brief Unit tests for PrtCnv::PrtCnvStoredTelegram.
*
* PrtCnvStoredTelegram is a small value holder pairing a radio telegram with
* the database bookkeeping the DB thread needs. These tests pin down its
* defaults and its copy behaviour (the telegram is shared, not cloned).
*/
#include <gtest/gtest.h>
#include <memory>
#include "PrtCnvStoredTelegram.hpp"
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
#include <CoPrtCnv/tetra_telegram_ids.h>
using PrtCnv::PrtCnvStoredTelegram;
using N_CoPrtCnv::CoPrtCnvRadioTelegram;
namespace
{
// CoPrtCnvRadioTelegram has no default constructor; the telegram-id constructor
// is the cheapest way to obtain a well-formed instance.
std::shared_ptr<CoPrtCnvRadioTelegram> makeTelegram()
{
return std::make_shared<CoPrtCnvRadioTelegram>(GEF_GEFECHTSFELDTELEGRAMM, uint16_t(8), uint16_t(0));
}
} // namespace
TEST(PrtCnvStoredTelegramTest, ConstructorStoresTelegramAndDefaults)
{
const std::shared_ptr<CoPrtCnvRadioTelegram> telegram = makeTelegram();
const PrtCnvStoredTelegram stored(telegram);
EXPECT_EQ(stored.m_RadioTelegram, telegram);
EXPECT_EQ(stored.m_Id, 0);
EXPECT_FALSE(stored.m_WriteCounterChanged);
}
TEST(PrtCnvStoredTelegramTest, CopyKeepsTheSameTelegramInstance)
{
const std::shared_ptr<CoPrtCnvRadioTelegram> telegram = makeTelegram();
PrtCnvStoredTelegram original(telegram);
original.m_Id = 123;
original.m_WriteCounterChanged = true;
const PrtCnvStoredTelegram copy(original);
EXPECT_EQ(copy.m_RadioTelegram, original.m_RadioTelegram);
EXPECT_EQ(copy.m_Id, 123);
EXPECT_TRUE(copy.m_WriteCounterChanged);
}
TEST(PrtCnvStoredTelegramTest, AssignmentCopiesEveryField)
{
const std::shared_ptr<CoPrtCnvRadioTelegram> telegram = makeTelegram();
PrtCnvStoredTelegram source(telegram);
source.m_Id = 789;
source.m_WriteCounterChanged = true;
PrtCnvStoredTelegram target(makeTelegram());
target = source;
EXPECT_EQ(target.m_RadioTelegram, telegram);
EXPECT_EQ(target.m_Id, 789);
EXPECT_TRUE(target.m_WriteCounterChanged);
}
TEST(PrtCnvStoredTelegramTest, MovingLeavesTheTargetHoldingTheTelegram)
{
const std::shared_ptr<CoPrtCnvRadioTelegram> telegram = makeTelegram();
PrtCnvStoredTelegram original(telegram);
original.m_Id = 456;
original.m_WriteCounterChanged = true;
const PrtCnvStoredTelegram moved(std::move(original));
EXPECT_EQ(moved.m_RadioTelegram, telegram);
EXPECT_EQ(moved.m_Id, 456);
EXPECT_TRUE(moved.m_WriteCounterChanged);
}
TEST(PrtCnvStoredTelegramTest, StoredTelegramKeepsTheTelegramAlive)
{
std::weak_ptr<CoPrtCnvRadioTelegram> observer;
{
PrtCnvStoredTelegram stored(makeTelegram());
observer = stored.m_RadioTelegram;
EXPECT_FALSE(observer.expired());
}
EXPECT_TRUE(observer.expired());
}
@@ -0,0 +1,27 @@
/**
* @file unittest_main.cpp
* @brief Shared entry point for the TetraIF unit test executables.
*
* GTest::gtest_main provides a main() that neither creates a QCoreApplication
* nor bootstraps the NGL root logger. The classes under test do both: they take
* a logger reference in their constructor, and NGL::NGLLoggerBootstrap throws
* NotCreatedError when the root logger has not been created yet.
*
* This mirrors tests/gtest_qt_main.cpp, minus the QApplication - none of the
* TetraIF unit tests touch widgets.
*/
#include <gtest/gtest.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <QtCore/QCoreApplication>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
NGL::NGLLoggerBootstrap::createNGLRootLogger(QString(), true, QString(), /*quiet=*/true);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
@@ -1,21 +1,14 @@
#!/bin/bash #!/bin/bash
set -e
# Run CMake configuration and build inside Docker. # docker build -f ci/Dockerfile.ci -t legatus-build:26.04 ci
# Utilise l'image legatus-build:26.04 (dependances pre-installees).
# Pour la (re)construire :
# docker build -f Dockerfile.build -t legatus-build:26.04 .
docker run --rm \ docker run --rm \
-v /home/nkana/repo/qt-migration-legatus:/workspace \ -v /home/nkana/repo/qt-migration-legatus:/workspace \
-v /home/nkana/repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/rti_license.dat:/workspace/rti_license.dat \ -v /home/nkana/repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/rti_license.dat:/workspace/rti_license.dat \
-v /home/nkana/repo/external/rti_connext_dds-7.7.0:/opt/rti_connext_dds-7.7.0:ro \ -v /home/nkana/repo/external/rti_connext_dds-7.7.0:/opt/rti_connext_dds-7.7.0:ro \
-w /workspace/qt6-after/qt6-migrated-legatus \ -w /workspace/qt6-after/qt6-migrated-legatus \
legatus-build:26.04 bash -c " legatus-build:26.04 bash -c "
# Set RTI license, DDS path, and Qt6 path
# (deja definis dans l'image, repris ici pour rester explicite)
export RTI_LICENSE_FILE=/workspace/rti_license.dat export RTI_LICENSE_FILE=/workspace/rti_license.dat
export DDS_PATH=/opt/rti_connext_dds-7.7.0 export DDS_PATH=/opt/rti_connext_dds-7.7.0
export CMAKE_PREFIX_PATH=/opt/Qt/6.10.2/gcc_64
# Clean and configure # Clean and configure
rm -rf build4 rm -rf build4
@@ -1,9 +1,5 @@
#!/bin/bash #!/bin/bash
# Shell interactif dans l'image de build (dependances deja installees). # docker build -f ci/Dockerfile.ci -t legatus-build:26.04 ci
# Ne supprime PAS build4 : les artefacts deja construits restent utilisables.
#
# Si l'image n'existe pas encore :
# docker build -f Dockerfile.build -t legatus-build:26.04 .
exec docker run --rm -it \ exec docker run --rm -it \
-v /home/nkana/repo/qt-migration-legatus:/workspace \ -v /home/nkana/repo/qt-migration-legatus:/workspace \
-v /home/nkana/repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/rti_license.dat:/workspace/rti_license.dat \ -v /home/nkana/repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/rti_license.dat:/workspace/rti_license.dat \
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
# Compile et lance les tests unitaires TetraIF dans l'image de build.
#
# ./docker_tetraif_tests.sh -> compile puis lance les trois suites
# ./docker_tetraif_tests.sh build -> compile seulement
# ./docker_tetraif_tests.sh run -> lance seulement (binaires deja compiles)
# ./docker_tetraif_tests.sh ctest -> lance via ctest (55 cas enregistres)
# ./docker_tetraif_tests.sh run 'PrtCnvMemberTest.*' -> sous-ensemble (filtre gtest)
#
# Prerequis : build4/ configure avec -DBUILD_RTI=ON (run ./docker_build.sh before).
MODE="${1:-all}"
FILTER="${2:-*}"
TARGETS="CoPrtCnvTests LogViewTests PrtCnvTests"
BUILD_CMD="make -j8 $TARGETS"
RUN_CMD="for t in $TARGETS; do echo \"== \$t ==\"; ./bin/\$t --gtest_filter='$FILTER'; done"
CTEST_CMD="ctest -R 'CoPrtCnv|LogView|PrtCnv' --output-on-failure"
case "$MODE" in
build) CMD="$BUILD_CMD" ;;
run) CMD="$RUN_CMD" ;;
ctest) CMD="$BUILD_CMD && $CTEST_CMD" ;;
all) CMD="$BUILD_CMD && $RUN_CMD" ;;
*) echo "usage: $0 [build|run|ctest|all] [filtre_gtest]"; exit 2 ;;
esac
docker run --rm \
-v /home/nkana/repo/qt-migration-legatus:/workspace \
-v /home/nkana/repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/rti_license.dat:/workspace/rti_license.dat \
-v /home/nkana/repo/external/rti_connext_dds-7.7.0:/opt/rti_connext_dds-7.7.0:ro \
-w /workspace/qt6-after/qt6-migrated-legatus/build4 \
legatus-build:26.04 bash -c "export QT_QPA_PLATFORM=offscreen && $CMD"