Adds q2 repos to migrate
No files matched your search
@@ -0,0 +1,104 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
ADD_SUBDIRECTORY(Console)
|
||||
SET(my_SRCS
|
||||
IntegerCalculator.cpp
|
||||
IntegerCalculator.hpp
|
||||
logger.cpp
|
||||
logger.h
|
||||
LogViewBooleanEdit.cpp
|
||||
LogViewBooleanEdit.hpp
|
||||
LogViewDateTimeEdit.cpp
|
||||
LogViewDateTimeEdit.hpp
|
||||
LogViewEnumEdit.cpp
|
||||
LogViewEnumEdit.hpp
|
||||
LogViewField.cpp
|
||||
LogViewField.hpp
|
||||
LogViewGui.cpp
|
||||
LogViewGui.hpp
|
||||
LogViewInjectionThread.cpp
|
||||
LogViewInjectionThread.hpp
|
||||
LogViewMain.cpp
|
||||
LogViewModels.cpp
|
||||
LogViewModels.hpp
|
||||
LogViewOptionDialog.cpp
|
||||
LogViewOptionDialog.hpp
|
||||
LogViewSpinBox.cpp
|
||||
LogViewSpinBox.hpp
|
||||
LogViewTableWidget.cpp
|
||||
LogViewTableWidget.hpp
|
||||
LogViewTabWidget.cpp
|
||||
LogViewTabWidget.hpp
|
||||
LogViewTelegram.cpp
|
||||
LogViewTelegramDialog.cpp
|
||||
LogViewTelegramDialog.hpp
|
||||
LogViewTelegramEdit.cpp
|
||||
LogViewTelegramEdit.hpp
|
||||
LogViewTelegramEditModel.cpp
|
||||
LogViewTelegramEditModel.hpp
|
||||
LogViewTelegram.hpp
|
||||
LogViewTelegramSelectionDialog.cpp
|
||||
LogViewTelegramSelectionDialog.hpp
|
||||
LogViewTetraTelegramsParser.cpp
|
||||
LogViewTetraTelegramsParser.hpp
|
||||
LogViewTextEdit.cpp
|
||||
LogViewTextEdit.hpp
|
||||
LogViewValueEdit.cpp
|
||||
LogViewValueEdit.hpp
|
||||
LogViewWidget.cpp
|
||||
LogViewWidget.hpp
|
||||
LogViewXdrElement.cpp
|
||||
LogViewXdrElement.hpp
|
||||
LogViewXdrParser.cpp
|
||||
LogViewXdrParser.hpp
|
||||
LogViewXdrStandardType.cpp
|
||||
LogViewXdrStandardType.hpp
|
||||
LogViewXdrStruct.cpp
|
||||
LogViewXdrStruct.hpp
|
||||
LogViewXdrType.cpp
|
||||
LogViewXdrType.hpp
|
||||
LogViewXdrValue.cpp
|
||||
LogViewXdrValue.hpp
|
||||
zsksxd_tetraForLogView.x
|
||||
)
|
||||
|
||||
QT5_ADD_RESOURCES(my_SRCS LogViewResources.qrc)
|
||||
NGL_ADD_TOOL_ICON(my_SRCS)
|
||||
NGL_ADD_EXECUTABLE(AAR SV NO_TRANSLATION LogView ${my_SRCS})
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(LogView
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Network
|
||||
CoPrtCnv
|
||||
nglwidgets
|
||||
NGLLogger
|
||||
nglapplication
|
||||
ngltools
|
||||
)
|
||||
NGL_INSTALL_TARGET(LogView)
|
||||
NGL_INSTALL(AAR SV FILES LogView_log4cxx.props DESTINATION bin)
|
||||
|
||||
|
||||
|
||||
# install on RPM build and copy for local builds so that LogView automatically finds the zsksxd_tetraForLogView.x file
|
||||
if (BUILD_RPM)
|
||||
add_custom_target(zsksxd_tetraForLogView.x_bin) # empty target so that LogView still builds on RPM build
|
||||
NGL_INSTALL(AAR SV FILES zsksxd_tetraForLogView.x DESTINATION bin)
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/zsksxd_tetraForLogView.x ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/zsksxd_tetraForLogView.x
|
||||
COMMENT "[Local build] Copy zsksxd_tetraForLogView.x for LogView into bin/"
|
||||
)
|
||||
add_custom_target(zsksxd_tetraForLogView.x_bin DEPENDS ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x)
|
||||
endif()
|
||||
|
||||
if (TARGET LogView)
|
||||
add_dependencies(LogView zsksxd_tetraForLogView.x_bin training_area_telegrams.h_bin)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(console_SRCS
|
||||
main.cpp
|
||||
)
|
||||
|
||||
NGL_ADD_TOOL_ICON(console_SRCS)
|
||||
NGL_ADD_EXECUTABLE(AAR SV LogView_console ${console_SRCS})
|
||||
NGL_INSTALL_TARGET(LogView_console)
|
||||
NGL_TARGET_LINK_LIBRARIES(LogView_console
|
||||
CoPrtCnv
|
||||
NGLLogger
|
||||
)
|
||||
@@ -0,0 +1,201 @@
|
||||
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QStringList>
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QBuffer>
|
||||
#include <QSet>
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvTelegramConverter.hpp>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <TrainingAreaBase/training_area_telegrams.h>
|
||||
|
||||
static QSet<int> s_eqIds;
|
||||
template <typename T>
|
||||
bool validEqId(const T &tele)
|
||||
{
|
||||
if (!s_eqIds.isEmpty() && !s_eqIds.contains(tele.header.equipmentNumber))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray formatTime(quint64 t)
|
||||
{
|
||||
const quint64 secs = t >> 32;
|
||||
const quint64 usecs = t & 0xFFFFFFFF;
|
||||
const quint64 msecs = usecs / 1000;
|
||||
return QDateTime::fromMSecsSinceEpoch(secs * 1000 + msecs).toString(QLatin1String("yy-MM-dd hh:mm:ss.zzz")).toUtf8();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
using namespace TrainingAreaBase::TetraIcd;
|
||||
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
|
||||
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_tetra.props", false);
|
||||
|
||||
NGL::INGLLogger &logger(NGL::NGLLoggerBootstrap::getNGLRootLogger());
|
||||
|
||||
if (app.arguments().count() < 3)
|
||||
{
|
||||
ERROR_LOG(logger) << "Usage: " << app.arguments().at(0)
|
||||
<< " <logfile> <telId> <equipId>";
|
||||
return 1;
|
||||
}
|
||||
|
||||
QFile telegramFile(app.arguments().at(1));
|
||||
if (!telegramFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
ERROR_LOG(logger) << "Error opening " << telegramFile.fileName()
|
||||
<< " for reading: " << telegramFile.errorString();
|
||||
return 2;
|
||||
}
|
||||
bool bOk;
|
||||
int telIdToSearch = app.arguments().at(2).toUShort(&bOk);
|
||||
if (!bOk)
|
||||
{
|
||||
ERROR_LOG(logger) << "Error reading telId - not a (valid) number: "
|
||||
<< app.arguments().at(2);
|
||||
return 3;
|
||||
}
|
||||
s_eqIds.clear();
|
||||
for (int i = 3; i < app.arguments().size(); ++i)
|
||||
{
|
||||
int eqId = app.arguments().at(i).toUShort(&bOk);
|
||||
if (!bOk)
|
||||
{
|
||||
ERROR_LOG(logger) << "Error reading equipId - not a (valid) number: "
|
||||
<< app.arguments().at(i);
|
||||
return 4;
|
||||
}
|
||||
s_eqIds += eqId;
|
||||
}
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader lh;
|
||||
if (sizeof(lh) == telegramFile.read((char *)&lh, sizeof(lh)))
|
||||
{
|
||||
if (lh.m_Version == 3)
|
||||
{
|
||||
|
||||
qint64 telegramLength = lh.m_Length - sizeof(lh);
|
||||
QByteArray telegramData(telegramLength, Qt::Uninitialized);
|
||||
if (telegramLength == telegramFile.read(telegramData.data(), telegramLength))
|
||||
{
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)
|
||||
(lh.m_Protocol & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask);
|
||||
|
||||
switch (dest)
|
||||
{
|
||||
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral:
|
||||
{
|
||||
const QJsonObject obj = QJsonDocument::fromJson(telegramData).object();
|
||||
int telId = obj.value(QStringLiteral("typeId")).toInt();
|
||||
if (telIdToSearch != telId)
|
||||
continue;
|
||||
|
||||
const QJsonObject objData = obj.value(QStringLiteral("data")).toObject();
|
||||
|
||||
const QByteArray tBA = formatTime(lh.m_Time);
|
||||
const char *timeStr = tBA.constData();
|
||||
|
||||
switch (telId)
|
||||
{
|
||||
case Constraints<CreateFunctionalArea>::id():
|
||||
{
|
||||
const CreateFunctionalArea tele(CreateFunctionalArea::fromJson(objData));
|
||||
if (!validEqId(tele))
|
||||
break;
|
||||
fprintf(stdout, "%s, FUNKTIONSRAUM: '%s', %d, %d\n",
|
||||
timeStr,
|
||||
tele.name.c_str(),
|
||||
tele.aesDdsId,
|
||||
tele.header.equipmentNumber
|
||||
);
|
||||
break;
|
||||
}
|
||||
case Constraints<DeactivateEffectSimulation>::id():
|
||||
{
|
||||
const DeactivateEffectSimulation tele(DeactivateEffectSimulation::fromJson(objData));
|
||||
fprintf(stdout, "%s, DEAKTIVIERUNG_WIRKFELD: typ: %d - kennung: %d\n",
|
||||
timeStr,
|
||||
int(tele.aesType),
|
||||
tele.aesDdsId
|
||||
);
|
||||
break;
|
||||
}
|
||||
case Constraints<PositionReport>::id():
|
||||
{
|
||||
const PositionReport tele(PositionReport::fromJson(objData));
|
||||
if (!validEqId(tele))
|
||||
break;
|
||||
if (tele.opsPosition.opsId == 0)
|
||||
break;
|
||||
fprintf(stdout, "%s, IPS_POSITIONSDATEN: %d - OPS: %d\n",
|
||||
timeStr,
|
||||
tele.header.equipmentNumber,
|
||||
tele.opsPosition.opsId
|
||||
);
|
||||
break;
|
||||
}
|
||||
case BESTAETIGUNG:
|
||||
case UMGEBUNGS_MELDUNG2:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Printing telegram with id %d not implemented\n", telId);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra:
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram radioTelegram(telegramData);
|
||||
gef_telegramm_id_et telId = radioTelegram.getTelID();
|
||||
if (telId == GEF_UMGEBUNGS_MELDUNG2)
|
||||
{
|
||||
const QByteArray tBA = formatTime(lh.m_Time);
|
||||
const char *timeStr = tBA.constData();
|
||||
static uint16_t bci = 0xFFFF;
|
||||
if (bci != radioTelegram.getBroadcastIndex())
|
||||
{
|
||||
if (bci > radioTelegram.getBroadcastIndex() && bci != 0xFFFF)
|
||||
{
|
||||
fprintf(stdout, "BCI reset in %s at %s!\n",
|
||||
qPrintable(telegramFile.fileName()),
|
||||
timeStr);
|
||||
}
|
||||
fprintf(stdout, "BCI: %d\n", radioTelegram.getBroadcastIndex());
|
||||
bci = radioTelegram.getBroadcastIndex();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(logger) << "Wrong LogHeader version: " << lh.m_Version;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,497 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "IntegerCalculator.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace N_SST
|
||||
{
|
||||
IntegerCalculator::IntegerCalculator()
|
||||
: m_OperationList({{"*", 6},{"/", 6},{"%", 6},{"+", 5},{"-", 5},{"<<", 4},{">>", 4}})
|
||||
, m_AdditionalErrorText()
|
||||
, m_ParanthesisCount(0)
|
||||
, m_Error(IntegerCalculator::e_Ok)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText)
|
||||
{
|
||||
std::string calcText = a_calcText;
|
||||
|
||||
for (auto iter = m_OperationList.begin(); iter != m_OperationList.end(); ++iter)
|
||||
replace(calcText, iter->first, " "+iter->first+" ");
|
||||
|
||||
|
||||
replace(calcText, "(", " ( ");
|
||||
replace(calcText, ")", " ) ");
|
||||
|
||||
|
||||
|
||||
m_ParanthesisCount = 0;
|
||||
m_Error = e_Ok;
|
||||
m_AdditionalErrorText = "";
|
||||
size_t pos = 0;
|
||||
bool dummy;
|
||||
int64_t value = calc(calcText, pos, dummy, "", 0, "+");
|
||||
|
||||
|
||||
|
||||
if (m_Error == e_Ok)
|
||||
{
|
||||
if (m_ParanthesisCount > 0)
|
||||
{
|
||||
m_Error = e_MissingRightParanthesis;
|
||||
}
|
||||
else if (m_ParanthesisCount < 0)
|
||||
{
|
||||
m_Error = e_MissingLeftParanthesis;
|
||||
}
|
||||
else if (pos != calcText.length())
|
||||
{
|
||||
m_Error = e_UnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
a_error = m_Error;
|
||||
if (a_error != e_Ok)
|
||||
{
|
||||
value = 0;
|
||||
if (a_addErrorText)
|
||||
{
|
||||
*a_addErrorText = m_AdditionalErrorText;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void IntegerCalculator::addVariable(const std::string& a_name, const int64_t a_value)
|
||||
{
|
||||
std::map<std::string, int64_t>::iterator iter = m_VariableList.find(a_name);
|
||||
if (iter != m_VariableList.end())
|
||||
removeVariable(a_name);
|
||||
m_VariableList.insert(std::make_pair(a_name, a_value));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void IntegerCalculator::removeVariable(const std::string& a_name)
|
||||
{
|
||||
std::map<std::string, int64_t>::iterator iter = m_VariableList.find(a_name);
|
||||
if (iter != m_VariableList.end())
|
||||
m_VariableList.erase(iter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t IntegerCalculator::calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis,
|
||||
const std::string& a_prevOp, const int64_t a_prevValue,
|
||||
const std::string& a_initOp)
|
||||
{
|
||||
std::string operation = a_initOp;
|
||||
int64_t value1 = a_prevValue;
|
||||
bool isNegative = false;
|
||||
std::string calcText = a_calcText;
|
||||
a_IsEndParanthesis = false;
|
||||
|
||||
while (a_pos < calcText.length())
|
||||
{
|
||||
if (' ' == calcText[a_pos])
|
||||
{
|
||||
a_pos++;
|
||||
}
|
||||
else if ('(' == calcText[a_pos])
|
||||
{
|
||||
m_ParanthesisCount++;
|
||||
bool dummy;
|
||||
int64_t value2 = calcSign(calc(calcText, ++a_pos, dummy), isNegative);
|
||||
value1 = doOperation(value1, operation, value2);
|
||||
|
||||
|
||||
size_t tmpPos = a_pos;
|
||||
std::string nextOp = getToken(a_calcText, tmpPos);
|
||||
if (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp))
|
||||
{
|
||||
|
||||
return value1;
|
||||
}
|
||||
|
||||
operation = "";
|
||||
}
|
||||
else if (')' == calcText[a_pos])
|
||||
{
|
||||
m_ParanthesisCount--;
|
||||
a_pos++;
|
||||
a_IsEndParanthesis = true;
|
||||
return value1;
|
||||
}
|
||||
else if (isDigit(calcText[a_pos]))
|
||||
{
|
||||
|
||||
|
||||
int64_t value2 = calcSign(convertValue(calcText, a_pos), isNegative);
|
||||
if (calcWithPriority(calcText, a_pos, value1, operation, value2, a_prevOp)) return value1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
std::string oldOperation = operation;
|
||||
operation = getToken(calcText, a_pos);
|
||||
|
||||
|
||||
if (!isOperation(operation))
|
||||
{
|
||||
int64_t value2 = 0;
|
||||
if (getVariableValue(operation, value2))
|
||||
{
|
||||
value2 = calcSign(value2, isNegative);
|
||||
if (calcWithPriority(calcText, a_pos, value1, oldOperation, value2, a_prevOp)) return value1;
|
||||
operation = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
m_Error = e_UnknownOperationOrVariable;
|
||||
m_AdditionalErrorText = operation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (oldOperation != "")
|
||||
{
|
||||
if (operation == "+")
|
||||
{
|
||||
operation = oldOperation;
|
||||
}
|
||||
else if (operation == "-")
|
||||
{
|
||||
isNegative = !isNegative;
|
||||
operation = oldOperation;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Error = e_NoOperandBetweenOperators;
|
||||
m_AdditionalErrorText = oldOperation + " " + operation;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return value1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IntegerCalculator::calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1, std::string& a_operation, int64_t a_value2, const std::string& a_prevOp)
|
||||
{
|
||||
bool isParaEnd = false;
|
||||
|
||||
size_t tmpPos = a_pos;
|
||||
std::string nextOp = getToken(a_calcText, tmpPos);
|
||||
if (isOperation(a_operation) && isOperation(nextOp) && isOperationPriorityHigher(nextOp, a_operation))
|
||||
{
|
||||
|
||||
a_value2 = calc(a_calcText, a_pos, isParaEnd, a_operation, a_value2);
|
||||
}
|
||||
a_value1 = doOperation(a_value1, a_operation, a_value2);
|
||||
if (isParaEnd || (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp)))
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
a_operation = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative)
|
||||
{
|
||||
if (a_isNegative)
|
||||
{
|
||||
a_isNegative = false;
|
||||
return -a_value;
|
||||
}
|
||||
return a_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t IntegerCalculator::convertValue(const std::string &a_valueText, size_t& a_pos)
|
||||
{
|
||||
std::string valueText = a_valueText.substr(a_pos);
|
||||
int base = 10;
|
||||
size_t startpos = 0;
|
||||
|
||||
bool isHex = (0 == valueText.find("0X")) || (0 == valueText.find("0x"));
|
||||
bool isBin = (0 == valueText.find("0B")) || (0 == valueText.find("0b"));
|
||||
if (isHex)
|
||||
{
|
||||
base = 16;
|
||||
startpos = 2;
|
||||
}
|
||||
else if (isBin)
|
||||
{
|
||||
base = 2;
|
||||
startpos = 2;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for (i=startpos; i<valueText.length(); i++)
|
||||
{
|
||||
if (!isDigit(valueText[i], isHex, isBin))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valueText.length() > i && valueText[i] != ' ')
|
||||
{
|
||||
m_Error = e_InvalidOperand;
|
||||
int spacePos = valueText.find(' ');
|
||||
m_AdditionalErrorText = valueText.substr(0, spacePos);
|
||||
}
|
||||
a_pos += i;
|
||||
|
||||
int64_t value = 0;
|
||||
std::stringstream stream;
|
||||
stream.str(valueText.substr(startpos, i-startpos));
|
||||
if (2 == base)
|
||||
{
|
||||
|
||||
const std::string binValueAsText = stream.str();
|
||||
for (const char c : binValueAsText)
|
||||
{
|
||||
value = value << 1;
|
||||
if (c == '1')
|
||||
value += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << std::setbase(base);
|
||||
stream >> value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a_pos)
|
||||
{
|
||||
|
||||
while (a_pos < a_calcText.length())
|
||||
{
|
||||
if (a_calcText[a_pos] == ' ') a_pos++;
|
||||
else break;
|
||||
}
|
||||
|
||||
|
||||
size_t startPos = a_pos;
|
||||
while (a_pos < a_calcText.length())
|
||||
{
|
||||
if (' ' == a_calcText[a_pos]) break;
|
||||
a_pos++;
|
||||
}
|
||||
return a_calcText.substr(startPos, a_pos-startPos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IntegerCalculator::isOperation(const std::string& a_operation) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator iter = m_OperationList.find(a_operation);
|
||||
return (iter != m_OperationList.end());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2)
|
||||
{
|
||||
|
||||
if (("+" == a_operation) || a_operation.empty())
|
||||
{
|
||||
return a_value1 + a_value2;
|
||||
}
|
||||
else if ("-" == a_operation)
|
||||
{
|
||||
return a_value1 - a_value2;
|
||||
}
|
||||
else if ("*" == a_operation)
|
||||
{
|
||||
return a_value1 * a_value2;
|
||||
}
|
||||
else if ("/" == a_operation)
|
||||
{
|
||||
if (0 == a_value2)
|
||||
{
|
||||
m_Error = e_DivisionByZero;
|
||||
}
|
||||
else
|
||||
{
|
||||
return a_value1 / a_value2;
|
||||
}
|
||||
}
|
||||
else if ("%" == a_operation)
|
||||
{
|
||||
if (0 == a_value2)
|
||||
{
|
||||
m_Error = e_DivisionByZero;
|
||||
}
|
||||
else
|
||||
{
|
||||
return a_value1 % a_value2;
|
||||
}
|
||||
}
|
||||
else if ("<<" == a_operation)
|
||||
{
|
||||
return a_value1 << a_value2;
|
||||
}
|
||||
else if (">>" == a_operation)
|
||||
{
|
||||
return a_value1 >> a_value2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Error = e_UnknownOperationOrVariable;
|
||||
m_AdditionalErrorText = a_operation;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IntegerCalculator::isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const
|
||||
{
|
||||
return (getPriority(a_operation1) > getPriority(a_operation2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IntegerCalculator::getVariableValue(const std::string& a_variableName, int64_t& a_value) const
|
||||
{
|
||||
auto iter = m_VariableList.find(a_variableName);
|
||||
if (iter != m_VariableList.end())
|
||||
{
|
||||
a_value = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IntegerCalculator::isDigit(const char a_char, const bool a_isHex, const bool a_isBin)
|
||||
{
|
||||
if (a_isHex)
|
||||
{
|
||||
|
||||
return (a_char >= '0' && a_char <= '9') || (a_char >= 'A' && a_char <= 'F') || (a_char >= 'a' && a_char <= 'f');
|
||||
}
|
||||
else if (a_isBin)
|
||||
{
|
||||
|
||||
return (a_char >= '0' && a_char <= '1');
|
||||
}
|
||||
|
||||
return (a_char >= '0' && a_char <= '9');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int16_t IntegerCalculator::getPriority(const std::string& a_operation) const
|
||||
{
|
||||
std::map<std::string, int>::const_iterator iter = m_OperationList.find(a_operation);
|
||||
if (iter != m_OperationList.end())
|
||||
return iter->second;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void IntegerCalculator::replace(std::string& a_haystack, const std::string &a_searchText, const std::string &a_replaceText)
|
||||
{
|
||||
std::string::size_type searchSize = a_searchText.length();
|
||||
std::string::size_type replaceSize = a_replaceText.length();
|
||||
|
||||
std::string::size_type pos = a_haystack.find(a_searchText, 0);
|
||||
while (std::string::npos != pos)
|
||||
{
|
||||
a_haystack.replace(pos, searchSize, a_replaceText);
|
||||
pos += replaceSize;
|
||||
pos = a_haystack.find(a_searchText, pos);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace N_SST
|
||||
{
|
||||
|
||||
|
||||
class IntegerCalculator
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
enum E_Error
|
||||
{
|
||||
|
||||
|
||||
e_Ok,
|
||||
|
||||
|
||||
e_DivisionByZero,
|
||||
|
||||
|
||||
e_UnknownOperationOrVariable,
|
||||
|
||||
|
||||
e_NoOperandBetweenOperators,
|
||||
|
||||
|
||||
e_InvalidOperand,
|
||||
|
||||
|
||||
e_MissingLeftParanthesis,
|
||||
|
||||
|
||||
e_MissingRightParanthesis,
|
||||
|
||||
|
||||
e_UnknownError
|
||||
};
|
||||
|
||||
|
||||
IntegerCalculator();
|
||||
virtual ~IntegerCalculator() = default;
|
||||
|
||||
|
||||
|
||||
int64_t calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText = nullptr);
|
||||
|
||||
|
||||
|
||||
void addVariable(const std::string& a_name, const int64_t a_value);
|
||||
|
||||
|
||||
|
||||
void removeVariable(const std::string& a_name);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
const std::map<std::string, int> m_OperationList;
|
||||
|
||||
|
||||
std::map<std::string, int64_t> m_VariableList;
|
||||
|
||||
|
||||
std::string m_AdditionalErrorText;
|
||||
|
||||
|
||||
int32_t m_ParanthesisCount;
|
||||
E_Error m_Error;
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t calc(const std::string& a_calcText, size_t& a_pos, bool& a_IsEndParanthesis,
|
||||
const std::string& a_prevOp = std::string(), const int64_t a_prevValue = 0,
|
||||
const std::string& a_initOp = std::string());
|
||||
|
||||
|
||||
|
||||
bool calcWithPriority(const std::string& a_calcText, size_t& a_pos, int64_t& a_value1,
|
||||
std::string& a_operation, int64_t a_value2, const std::string& a_prevOp);
|
||||
|
||||
|
||||
|
||||
static int64_t calcSign(const int64_t a_value, bool& a_isNegative);
|
||||
|
||||
|
||||
|
||||
int64_t convertValue(const std::string& a_valueText, size_t& a_pos);
|
||||
|
||||
|
||||
|
||||
static std::string getToken(const std::string& a_calcText, size_t& a_pos);
|
||||
|
||||
|
||||
|
||||
bool isOperation(const std::string& a_operation) const;
|
||||
|
||||
|
||||
|
||||
int64_t doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2);
|
||||
|
||||
|
||||
|
||||
bool isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const;
|
||||
|
||||
|
||||
|
||||
virtual bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const;
|
||||
|
||||
|
||||
|
||||
static bool isDigit(const char a_char, const bool a_isHex = false, const bool a_isBin = false);
|
||||
|
||||
|
||||
|
||||
int16_t getPriority(const std::string& a_operation) const;
|
||||
|
||||
|
||||
|
||||
static void replace(std::string& a_haystack, const std::string& a_searchText, const std::string& a_replaceText);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
|
||||
#include "LogViewBooleanEdit.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewBooleanEdit::LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
|
||||
: QCheckBox (a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, a_readonly)
|
||||
{
|
||||
const QString valueText = a_field->value(0);
|
||||
|
||||
setChecked(valueText.toInt() == 1);
|
||||
setEnabled(!a_readonly);
|
||||
}
|
||||
|
||||
|
||||
bool LogViewBooleanEdit::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
if (m_Valid)
|
||||
{
|
||||
if (a_telegram->isJsonTelegram())
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), isChecked());
|
||||
else
|
||||
a_telegram->setUIntX(getSize(), isChecked());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewWidget.hpp"
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewBooleanEdit : public QCheckBox, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewDateTimeEdit.hpp"
|
||||
#include <time.h>
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewDateTimeEdit::LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
|
||||
: QDateTimeEdit(a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, a_readonly)
|
||||
{
|
||||
if (a_readonly)
|
||||
{
|
||||
setReadOnly(true);
|
||||
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
|
||||
}
|
||||
|
||||
|
||||
qint64 unixTime = 0;
|
||||
if (a_field->hasContent())
|
||||
{
|
||||
if (a_field->isMSecsField())
|
||||
unixTime = a_field->value(0, true).toLongLong();
|
||||
else
|
||||
unixTime = a_field->value(0, true).toInt() * 1000LL;
|
||||
}
|
||||
|
||||
if (0 == unixTime && !a_readonly)
|
||||
unixTime = ::time(nullptr) * 1000LL;
|
||||
|
||||
|
||||
setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime));
|
||||
setDisplayFormat(QLatin1String("dd MMM yyyy hh:mm:ss"));
|
||||
setCalendarPopup(true);
|
||||
updateToolTip(QString::number(unixTime));
|
||||
|
||||
|
||||
|
||||
connect(this, &LogViewDateTimeEdit::editingFinished,
|
||||
this, &LogViewDateTimeEdit::checkAndOvertakeContent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewDateTimeEdit::checkAndOvertakeContent()
|
||||
{
|
||||
updateToolTip(QString::number(dateTime().toMSecsSinceEpoch() / 1000));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
if (a_telegram->isJsonTelegram())
|
||||
{
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), dateTime().toMSecsSinceEpoch());
|
||||
}
|
||||
else
|
||||
{
|
||||
a_telegram->setNextFieldAsGpsTimeField();
|
||||
a_telegram->setUIntX(getSize(), dateTime().toMSecsSinceEpoch() / 1000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewWidget.hpp"
|
||||
#include <QDateTimeEdit>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewDateTimeEdit : public QDateTimeEdit, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
|
||||
|
||||
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
|
||||
public slots:
|
||||
void checkAndOvertakeContent();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewEnumEdit.hpp"
|
||||
#include "LogViewXdrStruct.hpp"
|
||||
#include "LogViewXdrValue.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
|
||||
LogViewEnumEdit::LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index)
|
||||
: QComboBox(a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, a_readonly)
|
||||
{
|
||||
QString value = a_field->value(a_index);
|
||||
|
||||
|
||||
setToolTip(a_field->toolTipText());
|
||||
|
||||
|
||||
bool bCurrentIndexSet = false;
|
||||
int i = 0;
|
||||
while (LogViewXdrValue* child = (static_cast<const LogViewXdrStruct*>(a_field->xdrElement()))->getChildAsValue(i++))
|
||||
{
|
||||
QString enumText = LogViewField::makeClean(child->getName());
|
||||
if (!a_readonly || enumText == value)
|
||||
{
|
||||
addItem(QStringLiteral("%1 (%2)").arg(enumText).arg(child->getValue()), QVariant::fromValue(child->getValue()));
|
||||
if (a_readonly)
|
||||
bCurrentIndexSet = true;
|
||||
}
|
||||
|
||||
if (enumText == value)
|
||||
{
|
||||
setCurrentIndex(a_readonly ? 0 : i - 1);
|
||||
bCurrentIndexSet = true;
|
||||
if (!a_readonly || (0 != a_index))
|
||||
updateToolTip(itemData(currentIndex()).toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!bCurrentIndexSet)
|
||||
{
|
||||
addItem(value);
|
||||
setCurrentIndex(findText(value));
|
||||
}
|
||||
|
||||
|
||||
connect(this, QOverload<int>::of(&LogViewEnumEdit::currentIndexChanged),
|
||||
this, &LogViewEnumEdit::checkAndOvertakeContent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t LogViewEnumEdit::getSize() const
|
||||
{
|
||||
|
||||
const LogViewXdrStruct* xdrStruct = static_cast<const LogViewXdrStruct*>(m_Field->xdrElement());
|
||||
return xdrStruct->getEnumSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewEnumEdit::checkAndOvertakeContent()
|
||||
{
|
||||
updateToolTip(itemData(currentIndex()).toString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewEnumEdit::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
bool ok;
|
||||
int value = itemData(currentIndex()).toInt(&ok);
|
||||
if (ok)
|
||||
{
|
||||
if (a_telegram->isJsonTelegram())
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), value);
|
||||
else
|
||||
a_telegram->setUIntX(getSize(), value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewWidget.hpp"
|
||||
#include <QComboBox>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewEnumEdit : public QComboBox, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index);
|
||||
|
||||
|
||||
uint16_t getSize() const override;
|
||||
|
||||
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
|
||||
protected slots:
|
||||
void checkAndOvertakeContent();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewField.hpp"
|
||||
#include <QtCore/QDateTime>
|
||||
#include "LogViewXdrElement.hpp"
|
||||
#include "LogViewXdrStandardType.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewField::LogViewField(const QString& a_name, const E_FieldKind a_kind, const LogViewXdrElement* a_xdrElement)
|
||||
: m_Name(a_name),
|
||||
m_IsRightAligned(false),
|
||||
m_Offset(0),
|
||||
m_Size(0),
|
||||
m_MaxArraySize(0),
|
||||
m_IsDynamicArray(false),
|
||||
m_HasContent(true),
|
||||
m_bDeleteXdr(false),
|
||||
m_Kind(a_kind),
|
||||
m_XdrElement(a_xdrElement),
|
||||
m_logger(getLogger("LogViewField"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LogViewField::~LogViewField()
|
||||
{
|
||||
for (LogViewField *f : qAsConst(m_Child))
|
||||
delete f;
|
||||
if (m_bDeleteXdr)
|
||||
delete m_XdrElement;
|
||||
}
|
||||
|
||||
LogViewField *LogViewField::clone(int arrayIdx) const
|
||||
{
|
||||
LogViewField *f = new LogViewField(*this);
|
||||
f->m_Child.clear();
|
||||
f->m_bDeleteXdr = false;
|
||||
for (auto * c : m_Child)
|
||||
{
|
||||
auto *clonedChild = c->clone(-1);
|
||||
if (arrayIdx >= 0)
|
||||
{
|
||||
QStringList sl = clonedChild->jsonPath();
|
||||
if (sl.size() > 1 && sl.at(sl.size() - 2).startsWith(QStringLiteral("index: ")))
|
||||
{
|
||||
sl[sl.size() - 2] = QStringLiteral("index: %1").arg(arrayIdx);
|
||||
clonedChild->setJsonPath(sl);
|
||||
}
|
||||
}
|
||||
f->addChild(clonedChild);
|
||||
}
|
||||
for (auto &val : f->m_ValueList)
|
||||
val.clear();
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewField::addChild(LogViewField* a_child)
|
||||
{
|
||||
if (a_child)
|
||||
m_Child.push_back(a_child);
|
||||
}
|
||||
|
||||
|
||||
void LogViewField::removeLastChild()
|
||||
{
|
||||
if (m_Child.empty())
|
||||
return;
|
||||
delete m_Child.takeLast();
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogViewField* LogViewField::child(int arrayIdx)
|
||||
{
|
||||
if (m_Child.size() > arrayIdx)
|
||||
return m_Child.at(arrayIdx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void LogViewField::addValue(const QString &value)
|
||||
{
|
||||
m_ValueList.append(value);
|
||||
}
|
||||
|
||||
|
||||
void LogViewField::addValueBinaryHex(const QString &value)
|
||||
{
|
||||
const QByteArray ba = QByteArray::fromHex(value.toLatin1());
|
||||
for (const char c : ba)
|
||||
m_ValueList.append(QString::number(static_cast<unsigned char>(c)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QString LogViewField::value(int arrayIdx, const bool a_doNotMakeSpecialConversions) const
|
||||
{
|
||||
if (m_ValueList.size() > arrayIdx)
|
||||
{
|
||||
const QString &ret = m_ValueList.at(arrayIdx);
|
||||
if (!a_doNotMakeSpecialConversions)
|
||||
{
|
||||
if (isDateTimeField())
|
||||
return QDateTime::fromMSecsSinceEpoch(ret.toLongLong() * 1000).toString(QStringLiteral("dd.mm.yy hh:mm:ss.zzz"));
|
||||
if (isMSecsField())
|
||||
return QDateTime::fromMSecsSinceEpoch(ret.toLongLong()).toString(QStringLiteral("dd.mm.yy hh:mm:ss.zzz"));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
int64_t LogViewField::getHighestValue() const
|
||||
{
|
||||
switch (m_XdrElement->getKind())
|
||||
{
|
||||
case LogViewXdrElement::e_KindStandardType:
|
||||
{
|
||||
int64_t highest = 1;
|
||||
|
||||
uint16_t bitSize = 8*static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getEditSize();
|
||||
|
||||
if ((0 == m_Name.compare(QLatin1String("utm nordwert"), Qt::CaseInsensitive)) ||
|
||||
(0 == m_Name.compare(QLatin1String("utm ostwert"), Qt::CaseInsensitive)))
|
||||
bitSize -= 8;
|
||||
|
||||
switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) {
|
||||
case LogViewXdrStandardType::e_Boolean:
|
||||
return 1;
|
||||
case LogViewXdrStandardType::e_Signed:
|
||||
bitSize--;
|
||||
Q_FALLTHROUGH();
|
||||
case LogViewXdrStandardType::e_Unsigned:
|
||||
case LogViewXdrStandardType::e_Data:
|
||||
highest = highest << bitSize;
|
||||
highest--;
|
||||
break;
|
||||
default:
|
||||
highest = 0;
|
||||
break;
|
||||
}
|
||||
return highest;
|
||||
}
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Case not implemented";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int64_t LogViewField::getLowestValue() const
|
||||
{
|
||||
switch (m_XdrElement->getKind())
|
||||
{
|
||||
case LogViewXdrElement::e_KindStandardType:
|
||||
{
|
||||
int64_t lowest = 0;
|
||||
|
||||
switch (static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getValueKind()) {
|
||||
case LogViewXdrStandardType::e_Boolean:
|
||||
return 0;
|
||||
case LogViewXdrStandardType::e_Signed:
|
||||
lowest = getHighestValue() + 1;
|
||||
lowest = -lowest;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return lowest;
|
||||
}
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Case not implemented";
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewField::dump(const QString &a_indent) const
|
||||
{
|
||||
INFO_LOG(m_logger) << a_indent << "[";
|
||||
INFO_LOG(m_logger) << a_indent << "Field[" << m_Name << "]: m_Kind=" << m_Kind << " m_Offset=" << m_Offset << " m_Size=" << m_Size << " m_MaxArraySize=" << m_MaxArraySize << " m_IsRightAligned=" << m_IsRightAligned << " m_IsDynamicArray=" << m_IsDynamicArray << " m_ToolTipText=" << m_ToolTipText;
|
||||
|
||||
for (int i=0; i<m_ValueList.size(); i++)
|
||||
INFO_LOG(m_logger) << a_indent << "m_Value[" << i << "]=" << m_ValueList[i];
|
||||
|
||||
for (auto *c : m_Child)
|
||||
c->dump(a_indent + QLatin1Char(' '));
|
||||
|
||||
INFO_LOG(m_logger) << a_indent << "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QString LogViewField::makeClean(const QString &text)
|
||||
{
|
||||
QString a_uncleanText = text;
|
||||
|
||||
if (a_uncleanText.endsWith(QLatin1String("_rt")))
|
||||
a_uncleanText = a_uncleanText.left(a_uncleanText.length() - 3);
|
||||
|
||||
|
||||
a_uncleanText = a_uncleanText.replace(QLatin1Char('_'), QLatin1Char(' '));
|
||||
|
||||
|
||||
int pos = 0;
|
||||
while (a_uncleanText.length() > pos)
|
||||
{
|
||||
a_uncleanText[pos] = a_uncleanText[pos].toUpper();
|
||||
pos = a_uncleanText.indexOf(QLatin1Char(' '), pos + 1);
|
||||
if (-1 == pos)
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
|
||||
return a_uncleanText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewField::isDateTimeField() const
|
||||
{
|
||||
QString name = m_Name.toLower();
|
||||
return name == QLatin1String("gps_zeit");
|
||||
}
|
||||
|
||||
bool LogViewField::isMSecsField() const
|
||||
{
|
||||
QString name = m_Name.toLower();
|
||||
return (name == QLatin1String("timestamp")) || (name == QLatin1String("effectstart"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewField::setMaxArraySize(uint16_t newVal, const bool a_isDynamic)
|
||||
{
|
||||
m_MaxArraySize = newVal;
|
||||
m_IsDynamicArray = a_isDynamic;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include "logger.h"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewXdrElement;
|
||||
class LogViewField
|
||||
{
|
||||
public:
|
||||
enum E_FieldKind
|
||||
{
|
||||
e_FieldKindBorder,
|
||||
e_FieldKindEdit,
|
||||
e_FieldKindTab,
|
||||
e_FieldKindTabChild,
|
||||
e_FieldKindPodArray,
|
||||
e_FieldKindPodArrayChild
|
||||
};
|
||||
|
||||
|
||||
LogViewField(const QString& a_name, const E_FieldKind a_kind, const LogViewXdrElement* a_xdrElement);
|
||||
virtual ~LogViewField();
|
||||
|
||||
LogViewField *clone(int arrayIdx) const;
|
||||
|
||||
QString cleanName() const { return makeClean(m_Name); }
|
||||
QString name() const { return m_Name; }
|
||||
void setName(const QString &newVal) { m_Name = newVal; }
|
||||
|
||||
|
||||
void addChild(LogViewField* a_child);
|
||||
void removeLastChild();
|
||||
LogViewField *child(int arrayIdx);
|
||||
int childCount() const { return m_Child.size(); }
|
||||
|
||||
QString type() const { return m_type; }
|
||||
void setType(const QString &type) { m_type = type; }
|
||||
|
||||
LogViewField::E_FieldKind kind() const { return m_Kind; }
|
||||
|
||||
void addValue(const QString &value);
|
||||
void addValueBinaryHex(const QString &value);
|
||||
|
||||
|
||||
|
||||
QString value(int arrayIdx, const bool a_doNotMakeSpecialConversions = false) const;
|
||||
int valueListSize() const { return m_ValueList.size(); }
|
||||
|
||||
|
||||
bool isRightAligned() const { return m_IsRightAligned; }
|
||||
void setIsRightAligned(bool newVal) { m_IsRightAligned = newVal; }
|
||||
|
||||
|
||||
QString toolTipText() const { return m_ToolTipText; }
|
||||
void setToolTipText(const QString &newVal) { m_ToolTipText = newVal; }
|
||||
|
||||
|
||||
int64_t getHighestValue() const;
|
||||
int64_t getLowestValue() const;
|
||||
|
||||
|
||||
|
||||
void dump(const QString &a_indent = QString()) const;
|
||||
|
||||
|
||||
|
||||
static QString makeClean(const QString &text);
|
||||
|
||||
|
||||
int size() const { return m_Size; }
|
||||
void setSize(int newVal) { m_Size = newVal; }
|
||||
|
||||
|
||||
const LogViewXdrElement* xdrElement() const { return m_XdrElement; }
|
||||
|
||||
|
||||
|
||||
bool isDateTimeField() const;
|
||||
bool isMSecsField() const;
|
||||
|
||||
|
||||
uint16_t maxArraySize() const { return m_MaxArraySize; }
|
||||
void setMaxArraySize(uint16_t newVal, const bool a_isDynamic);
|
||||
|
||||
|
||||
|
||||
bool isDynamicArray() const { return m_IsDynamicArray; }
|
||||
|
||||
|
||||
bool hasContent() const { return m_HasContent; }
|
||||
void setHasContent(bool newVal) { m_HasContent = newVal; }
|
||||
|
||||
void setDeleteXdr(bool bDelete) { m_bDeleteXdr = bDelete; }
|
||||
|
||||
void setJsonPath(const QStringList &path) { m_jsonPath = path; }
|
||||
QStringList jsonPath() const { return m_jsonPath; }
|
||||
|
||||
protected:
|
||||
|
||||
QString m_Name;
|
||||
QString m_type;
|
||||
QStringList m_ValueList;
|
||||
QStringList m_jsonPath;
|
||||
bool m_IsRightAligned;
|
||||
QString m_ToolTipText;
|
||||
uint16_t m_Offset;
|
||||
int m_Size;
|
||||
uint16_t m_MaxArraySize;
|
||||
|
||||
|
||||
bool m_IsDynamicArray;
|
||||
bool m_HasContent;
|
||||
bool m_bDeleteXdr;
|
||||
QVector<LogViewField*> m_Child;
|
||||
|
||||
E_FieldKind m_Kind;
|
||||
|
||||
const LogViewXdrElement *m_XdrElement;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QtCore/QMap>
|
||||
#include "LogViewModels.hpp"
|
||||
#include "LogViewTelegramEditModel.hpp"
|
||||
#include <set>
|
||||
#include <QMenu>
|
||||
#include "logger.h"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewTelegram;
|
||||
}
|
||||
class QTableView;
|
||||
|
||||
class QGroupBox;
|
||||
class QCheckBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
class QSplitter;
|
||||
class QToolBox;
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewInjectionThread;
|
||||
class TelegramEdit;
|
||||
|
||||
|
||||
|
||||
class LogViewGui : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit LogViewGui(QWidget* a_parent);
|
||||
|
||||
static const QLatin1String WINDOW_GROUP;
|
||||
static const QLatin1String SCREEN;
|
||||
|
||||
protected:
|
||||
|
||||
const QSize RADIO_BUTTON_ICON_SIZE;
|
||||
static const QLatin1String SIZE;
|
||||
static const QLatin1String POS;
|
||||
static const QLatin1String SPLITTPOS;
|
||||
static const QLatin1String TOOLBOXINDEX;
|
||||
|
||||
QGroupBox *m_CentralSelectionGroup;
|
||||
std::set<int> m_CentralTelegramFilterList;
|
||||
QCheckBox* m_SentCentralTelCheckBox;
|
||||
QCheckBox* m_ReceivedCentralTelCheckBox;
|
||||
QCheckBox* m_PosCentralTelCheckBox;
|
||||
QCheckBox* m_ackCentralTelCheckBox;
|
||||
|
||||
QGroupBox *m_TetraSelectionGroup;
|
||||
std::set<int> m_TetraTelegramFilterList;
|
||||
QCheckBox* m_SentTetraTelCheckBox;
|
||||
QCheckBox* m_ReceivedTetraTelCheckBox;
|
||||
QCheckBox* m_PosTetraTelCheckBox;
|
||||
QCheckBox* m_LoginTetraTelCheckBox;
|
||||
QCheckBox* m_RegisterTetraTelCheckBox;
|
||||
QCheckBox* m_ReportTetraTelCheckBox;
|
||||
QCheckBox* m_FragmentedTetraTelCheckBox;
|
||||
QCheckBox* m_AirInterfaceLoadTetraTelCheckBox;
|
||||
|
||||
QGroupBox *m_WlsSelectionGroup;
|
||||
std::set<int> m_WlsTelegramFilterList;
|
||||
QCheckBox* m_SentWlsTelCheckBox;
|
||||
QCheckBox* m_ReceivedWlsTelCheckBox;
|
||||
QCheckBox* m_PosWlsTelCheckBox;
|
||||
QCheckBox* m_ackWlsTelCheckBox;
|
||||
|
||||
QString m_ActualLogfile;
|
||||
qint64 m_LogfileSize;
|
||||
bool m_DoReload;
|
||||
QToolBox* m_ToolBox;
|
||||
QTableView *m_ParticipantTableView;
|
||||
ParticipantModel *m_participantModel;
|
||||
QSortFilterProxyModel *m_participantProxyModel;
|
||||
|
||||
QTableView *m_logTelegramView;
|
||||
TelegramModel *m_telegramModel;
|
||||
TelegramProxyModel *m_telegramProxyModel;
|
||||
|
||||
QLabel *m_TelegramStatus;
|
||||
|
||||
QLabel *m_ParticipantStatus;
|
||||
|
||||
QGroupBox *m_ParticipantSelectionGroup;
|
||||
|
||||
TelegramEdit *m_EditTelegramController;
|
||||
|
||||
QTimer *m_TailTimer;
|
||||
|
||||
QSplitter *m_Splitter;
|
||||
|
||||
LogViewInjectionThread *m_InjectionThread;
|
||||
|
||||
QLabel *m_InjectionStatus;
|
||||
|
||||
|
||||
QHash<int, int> m_participantListTelCount;
|
||||
|
||||
QHash<int, int> m_participantListIssi;
|
||||
|
||||
QAction *m_reloadAction;
|
||||
QTimer *m_replayTimer;
|
||||
int m_currentReplayRow;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
protected:
|
||||
void readTelegramsFromLogFile(const QString& a_fileName, const qint64 a_filePos = 0);
|
||||
|
||||
|
||||
|
||||
void addToParticipantList(const QSharedPointer<LogViewTelegram> &a_telegram);
|
||||
void syncParticipantList();
|
||||
QCheckBox* createRadioButton(const QString& a_buttonName, const QString& a_iconName);
|
||||
|
||||
|
||||
|
||||
void startInjectionThread();
|
||||
|
||||
void closeEvent(QCloseEvent* a_closeEvent) override;
|
||||
|
||||
void createCentralSelectionWidget();
|
||||
void createTetraSelectionWidget();
|
||||
void createWlsSelectionWidget();
|
||||
|
||||
protected slots:
|
||||
void addTelegramToEdit();
|
||||
void showHexData();
|
||||
void exportAsCsv();
|
||||
void exportAsJson();
|
||||
void onStartLogReplay();
|
||||
void onReplayTimerTimeout();
|
||||
|
||||
void loadSpecificationFiles();
|
||||
|
||||
|
||||
void newTelegramFile();
|
||||
|
||||
|
||||
void loadTelegramFile();
|
||||
|
||||
|
||||
|
||||
void updateLogfile();
|
||||
|
||||
void selectedParticipantChanged();
|
||||
|
||||
void showTelegramTable();
|
||||
|
||||
|
||||
void customMenuRequested(const QPoint &pos);
|
||||
|
||||
void changeSettings();
|
||||
|
||||
|
||||
|
||||
void reloadOnOff();
|
||||
|
||||
|
||||
|
||||
void updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText);
|
||||
|
||||
void onLogTelegramViewDoubleClicked(const QModelIndex &index);
|
||||
|
||||
private slots:
|
||||
void onSettingsChanged(uint32_t changedFlags);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewInjectionThread.hpp"
|
||||
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include "LogViewOptionDialog.hpp"
|
||||
#include <CoPrtCnv/CoPrtCnvInjectionHeader.hpp>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
LogViewInjectionThread::LogViewInjectionThread()
|
||||
: m_DoStartConnection(false)
|
||||
, m_SendingPossible(false)
|
||||
, m_Socket(nullptr)
|
||||
, m_Timer(nullptr)
|
||||
, m_logger(getLogger("LogViewInjectionThread"))
|
||||
{
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
|
||||
m_Hostname = settings.value(LogViewOptionDialog::INJECTION_HOSTNAME).toString();
|
||||
if (m_Hostname.isEmpty())
|
||||
{
|
||||
|
||||
m_Hostname = QLatin1String("localhost");
|
||||
settings.setValue(LogViewOptionDialog::INJECTION_HOSTNAME, m_Hostname);
|
||||
}
|
||||
m_Port = settings.value(LogViewOptionDialog::INJECTION_PORT).toInt();
|
||||
if (0 == m_Port || m_Port > 65535)
|
||||
{
|
||||
m_Port = 46666;
|
||||
settings.setValue(LogViewOptionDialog::INJECTION_PORT, m_Port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LogViewInjectionThread::run()
|
||||
{
|
||||
emit updateStatus(QLatin1String(":/image/RedLamp.png"),
|
||||
tr("LogView ist nicht mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
|
||||
QTimer::singleShot(100, this, &LogViewInjectionThread::tryToConnect);
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewInjectionThread::setPort(uint16_t port)
|
||||
{
|
||||
m_Port = port;
|
||||
QSettings settings;
|
||||
settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
|
||||
settings.setValue(LogViewOptionDialog::INJECTION_PORT, m_Port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LogViewInjectionThread::isSendingPossible() const
|
||||
{
|
||||
return m_SendingPossible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewInjectionThread::tryToConnect()
|
||||
{
|
||||
|
||||
if (!m_Socket)
|
||||
{
|
||||
m_Socket = new QTcpSocket(this);
|
||||
connect(m_Socket, &QTcpSocket::connected, this, &LogViewInjectionThread::doConnect);
|
||||
connect(m_Socket, &QTcpSocket::disconnected, this, &LogViewInjectionThread::doDisconnect);
|
||||
}
|
||||
|
||||
|
||||
if (!m_Timer)
|
||||
{
|
||||
m_Timer = new QTimer(this);
|
||||
connect(m_Timer, &QTimer::timeout, this, &LogViewInjectionThread::tryToConnect);
|
||||
}
|
||||
m_Timer->setInterval(3000);
|
||||
m_Timer->start();
|
||||
|
||||
INFO_LOG(m_logger) << "Try to connect to injection-server of TETRA-If (" << m_Hostname << ":" << m_Port << ")";
|
||||
m_Socket->connectToHost(m_Hostname, m_Port);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewInjectionThread::doConnect()
|
||||
{
|
||||
INFO_LOG(m_logger) << "LogView has successful connected to injection-server of TETRA-If";
|
||||
m_SendingPossible = true;
|
||||
m_Timer->stop();
|
||||
emit updateStatus(QLatin1String(":/image/GreenLamp.png"),
|
||||
tr("LogView ist mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewInjectionThread::doDisconnect()
|
||||
{
|
||||
INFO_LOG(m_logger) << "LogView was disconnected from injection-server of TETRA-If";
|
||||
m_SendingPossible = false;
|
||||
emit updateStatus(QLatin1String(":/image/RedLamp.png"),
|
||||
tr("LogView ist nicht mehr mit TETRA-If-Injection-Server (%1:%2) verbunden").arg(m_Hostname).arg(m_Port));
|
||||
tryToConnect();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewInjectionThread::sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram)
|
||||
{
|
||||
INFO_LOG(m_logger) << "inject " << (a_doSendAsCentralTelegram ? "central" : "Tetra") << " telegram";
|
||||
if (!m_Socket || m_Socket->state() != QAbstractSocket::ConnectedState)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Try to write a telegramm but we are not connected";
|
||||
return;
|
||||
}
|
||||
N_CoPrtCnv::CoPrtCnvInjectionHeader injectionHeader;
|
||||
injectionHeader.m_Kind = a_doSendAsCentralTelegram ? N_CoPrtCnv::CoPrtCnvInjectionHeader::eCentral : N_CoPrtCnv::CoPrtCnvInjectionHeader::eRadio;
|
||||
const QByteArray &data = a_telegram->getData();
|
||||
injectionHeader.m_Size = data.size();
|
||||
m_Socket->write((char*)(&injectionHeader), sizeof(injectionHeader));
|
||||
m_Socket->write(data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include "logger.h"
|
||||
|
||||
class QTcpSocket;
|
||||
class QTimer;
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewTelegram;
|
||||
|
||||
|
||||
|
||||
class LogViewInjectionThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
LogViewInjectionThread();
|
||||
|
||||
void run();
|
||||
|
||||
void setPort(uint16_t port);
|
||||
|
||||
bool isSendingPossible() const;
|
||||
|
||||
|
||||
|
||||
void sendTelegram(LogViewTelegram* a_telegram, const bool a_doSendAsCentralTelegram);
|
||||
|
||||
protected:
|
||||
|
||||
bool m_DoStartConnection;
|
||||
bool m_SendingPossible;
|
||||
QString m_Hostname;
|
||||
int m_Port;
|
||||
QTcpSocket *m_Socket;
|
||||
|
||||
QTimer *m_Timer;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
protected:
|
||||
protected slots:
|
||||
void tryToConnect();
|
||||
|
||||
|
||||
void doConnect();
|
||||
|
||||
|
||||
void doDisconnect();
|
||||
|
||||
public:
|
||||
signals:
|
||||
|
||||
|
||||
void updateStatus(const QString& a_picName, const QString& a_toolTipText);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <nglapplication/nglapplication.h>
|
||||
#include <QDesktopWidget>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QNetworkProxy>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "LogViewGui.hpp"
|
||||
#include "logger.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::string logConfigFileName;
|
||||
std::string dir;
|
||||
|
||||
#ifdef WIN32
|
||||
dir = argv[0];
|
||||
#else
|
||||
std::stringstream s;
|
||||
s << "/proc/" << getpid() << "/exe";
|
||||
char buf[1024];
|
||||
ssize_t len = readlink(s.str().c_str(), buf, 1024);
|
||||
if(len > 0) {
|
||||
buf[len] = '\0';
|
||||
dir = buf;
|
||||
} else {
|
||||
|
||||
dir = argv[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string::size_type pos = dir.find_last_of('/');
|
||||
if (std::string::npos != pos)
|
||||
logConfigFileName += dir.substr(0, pos + 1);;
|
||||
logConfigFileName += "LogView_log4cxx.props";
|
||||
|
||||
qputenv("TDS_DEVEL", QByteArray::number(1));
|
||||
NGLApplication app(argc, argv);
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy());
|
||||
app.createLogger("LogView", logConfigFileName.c_str());
|
||||
|
||||
QCoreApplication::setOrganizationName(QLatin1String("RME"));
|
||||
QCoreApplication::setApplicationName(QLatin1String("LogView"));
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup(N_LogView::LogViewGui::WINDOW_GROUP);
|
||||
int screenNbr = settings.value(N_LogView::LogViewGui::SCREEN, 0).toInt();
|
||||
settings.endGroup();
|
||||
|
||||
N_LogView::LogViewGui* logViewGui = new N_LogView::LogViewGui(QApplication::desktop()->screen(screenNbr));
|
||||
logViewGui->show();
|
||||
int ret = app.exec();
|
||||
|
||||
delete logViewGui;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,548 @@
|
||||
|
||||
|
||||
|
||||
#include "LogViewModels.hpp"
|
||||
|
||||
#include <QtGui/QFont>
|
||||
#include <QtGui/QPalette>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
|
||||
int ParticipantModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_particpants.size();
|
||||
}
|
||||
|
||||
|
||||
int ParticipantModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 3;
|
||||
}
|
||||
|
||||
|
||||
QVariant ParticipantModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.isValid() && index.row() < m_particpants.size())
|
||||
{
|
||||
const auto &p = m_particpants.at(index.row());
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return p.first;
|
||||
case 1:
|
||||
return p.second;
|
||||
case 2:
|
||||
return m_particpantMap.value(p.first);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (role == Qt::ToolTipRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return tr("hex: 0x%1").arg(p.first, 4, 16, QLatin1Char('0'));
|
||||
case 1:
|
||||
return tr("hex: 0x%1").arg(p.second, 4, 16, QLatin1Char('0'));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (role == Qt::BackgroundColorRole)
|
||||
{
|
||||
if (p.first == 0)
|
||||
return QVariant();
|
||||
if (m_participantHeatmap.isEmpty())
|
||||
updateHeatMap();
|
||||
return m_participantHeatmap.value(p.first);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QVariant ParticipantModel::headerData(int section,
|
||||
Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return tr("Equip. No.");
|
||||
case 1:
|
||||
return tr("ISSI");
|
||||
case 2:
|
||||
return tr("#");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
|
||||
void ParticipantModel::clearParticipants()
|
||||
{
|
||||
beginResetModel();
|
||||
m_particpantMap.clear();
|
||||
m_particpants.clear();
|
||||
m_participantHeatmap.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
bool ParticipantModel::addUpdateParticipants(const QVector<int> &eqIds,
|
||||
const QVector<int> &issis,
|
||||
const QVector<int> &numberOfTelegrams)
|
||||
{
|
||||
QVector<QPair<int, int> > newParticpants;
|
||||
for (int i = 0; i < eqIds.size(); ++i)
|
||||
{
|
||||
const int eqId = eqIds.at(i);
|
||||
const int issi = issis.at(i);
|
||||
const int cntTelegrams = numberOfTelegrams.at(i);
|
||||
auto it = m_particpantMap.find(eqId);
|
||||
if (it != m_particpantMap.end())
|
||||
{
|
||||
it.value() = cntTelegrams;
|
||||
continue;
|
||||
}
|
||||
newParticpants.push_back(qMakePair(eqId, issi));
|
||||
m_particpantMap[eqId] = cntTelegrams;
|
||||
}
|
||||
|
||||
if (!newParticpants.isEmpty())
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_particpants.size(), m_particpants.size() + newParticpants.size() - 1);
|
||||
m_particpants.append(newParticpants);
|
||||
endInsertRows();
|
||||
}
|
||||
m_participantHeatmap.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ParticipantModel::updateHeatMap() const
|
||||
{
|
||||
int maxNumberOfTelegrams = 0;
|
||||
for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it)
|
||||
{
|
||||
if (it.key() == 0)
|
||||
continue;
|
||||
maxNumberOfTelegrams = std::max(it.value(), maxNumberOfTelegrams);
|
||||
}
|
||||
|
||||
const QColor backgroundColor = QGuiApplication::palette().base().color();
|
||||
const QColor redColor = Qt::red;
|
||||
for (auto it = m_particpantMap.begin(); it != m_particpantMap.end(); ++it)
|
||||
{
|
||||
const int eqId = it.key();
|
||||
if (eqId == 0)
|
||||
continue;
|
||||
|
||||
const int nbrTelegrams = it.value();
|
||||
QColor curColor;
|
||||
double percent = static_cast<double>(nbrTelegrams) / maxNumberOfTelegrams;
|
||||
curColor.setRed(backgroundColor.red() - ((backgroundColor.red() - redColor.red()) * percent));
|
||||
curColor.setGreen(backgroundColor.green() - ((backgroundColor.green() - redColor.green()) * percent));
|
||||
curColor.setBlue(backgroundColor.blue() - ((backgroundColor.blue() - redColor.blue()) * percent));
|
||||
m_participantHeatmap[eqId] = curColor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int TelegramModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_telegrams.size();
|
||||
}
|
||||
|
||||
|
||||
int TelegramModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 6;
|
||||
}
|
||||
|
||||
|
||||
QVariant TelegramModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.isValid() && index.row() < m_telegrams.size())
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
const QSharedPointer<LogViewTelegram> &telegram = m_telegrams.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return telegram->getDestinationText();
|
||||
case 1:
|
||||
return telegram->getName();
|
||||
case 2:
|
||||
return telegram->getParticipantId();
|
||||
case 3:
|
||||
return telegram->getLogTimeText();
|
||||
case 4:
|
||||
return telegram->getGpsTimeText();
|
||||
case 5:
|
||||
return telegram->getDelay();
|
||||
}
|
||||
}
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return telegram->getIcon();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (role == Qt::ToolTipRole)
|
||||
{
|
||||
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case 1:
|
||||
return telegram->getToolTipText(LogViewTelegram::e_ColName);
|
||||
case 3:
|
||||
return telegram->getToolTipText(LogViewTelegram::e_ColLogTime);
|
||||
case 4:
|
||||
return telegram->getToolTipText(LogViewTelegram::e_ColGpsTime);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QVariant TelegramModel::headerData(int section,
|
||||
Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return tr("Dest.");
|
||||
case 1:
|
||||
return tr("Description");
|
||||
case 2:
|
||||
return tr("Equip. No.");
|
||||
case 3:
|
||||
return tr("Send/Recieve time");
|
||||
case 4:
|
||||
return tr("GPS time");
|
||||
case 5:
|
||||
return tr("Delay");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
|
||||
void TelegramModel::clearTelegrams()
|
||||
{
|
||||
beginResetModel();
|
||||
m_telegrams.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
void TelegramModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams)
|
||||
{
|
||||
if (telegrams.isEmpty())
|
||||
return;
|
||||
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size() + telegrams.size() - 1);
|
||||
m_telegrams += telegrams;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
void TelegramModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size());
|
||||
m_telegrams.push_back(telegram);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
QSharedPointer<LogViewTelegram> TelegramModel::telegram(int row) const
|
||||
{
|
||||
if (row >= 0 && row < m_telegrams.size())
|
||||
return m_telegrams.at(row);
|
||||
return QSharedPointer<LogViewTelegram>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilterByEquipmentIds(bool bFilterByEquipmentIds)
|
||||
{
|
||||
if (m_bFilterByEquipmentIds == bFilterByEquipmentIds)
|
||||
return;
|
||||
m_bFilterByEquipmentIds = bFilterByEquipmentIds;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setAllowedEquipmentIds(const std::set<int> &allowedEquipmentIds)
|
||||
{
|
||||
if (m_allowedEquipmentIds == allowedEquipmentIds)
|
||||
return;
|
||||
m_allowedEquipmentIds = allowedEquipmentIds;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilteredCentralTelegramIds(const std::set<int> &filteredCentralTelegramIds)
|
||||
{
|
||||
if (m_filteredCentralTelegramIds == filteredCentralTelegramIds)
|
||||
return;
|
||||
m_filteredCentralTelegramIds = filteredCentralTelegramIds;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilteredTetraTelegramIds(const std::set<int> &filteredTetraTelegramIds)
|
||||
{
|
||||
if (m_filteredTetraTelegramIds == filteredTetraTelegramIds)
|
||||
return;
|
||||
m_filteredTetraTelegramIds = filteredTetraTelegramIds;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilteredWlsTelegramIds(const std::set<int> &filteredWlsTelegramIds)
|
||||
{
|
||||
if (m_filteredWlsTelegramIds == filteredWlsTelegramIds)
|
||||
return;
|
||||
m_filteredWlsTelegramIds = filteredWlsTelegramIds;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
|
||||
bool bFilter)
|
||||
{
|
||||
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> curFilter = m_filterCentralTelegrams;
|
||||
if (bFilter)
|
||||
curFilter.insert(direction);
|
||||
else
|
||||
curFilter.erase(direction);
|
||||
if (curFilter == m_filterCentralTelegrams)
|
||||
return;
|
||||
m_filterCentralTelegrams = curFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
|
||||
bool bFilter)
|
||||
{
|
||||
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> curFilter = m_filterTetraTelegrams;
|
||||
if (bFilter)
|
||||
curFilter.insert(direction);
|
||||
else
|
||||
curFilter.erase(direction);
|
||||
if (curFilter == m_filterTetraTelegrams)
|
||||
return;
|
||||
m_filterTetraTelegrams = curFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilterTetraPDU(N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType,
|
||||
bool bFilter)
|
||||
{
|
||||
std::set<N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type> curFilter = m_filterTetraPDU;
|
||||
if (bFilter)
|
||||
curFilter.insert(pduType);
|
||||
else
|
||||
curFilter.erase(pduType);
|
||||
if (curFilter == m_filterTetraPDU)
|
||||
return;
|
||||
m_filterTetraPDU = curFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void TelegramProxyModel::setFilterWlsTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction,
|
||||
bool bFilter)
|
||||
{
|
||||
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> curFilter = m_filterWlsTelegrams;
|
||||
if (bFilter)
|
||||
curFilter.insert(direction);
|
||||
else
|
||||
curFilter.erase(direction);
|
||||
if (curFilter == m_filterWlsTelegrams)
|
||||
return;
|
||||
m_filterWlsTelegrams = curFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilterTetraLogin(bool bFilter)
|
||||
{
|
||||
if (m_bFilterLoginTelegrams == bFilter)
|
||||
return;
|
||||
m_bFilterLoginTelegrams = bFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
void TelegramProxyModel::setFilterTetraFragmented(bool bFilter)
|
||||
{
|
||||
if (m_bFilterFragmentedTelegrams == bFilter)
|
||||
return;
|
||||
m_bFilterFragmentedTelegrams = bFilter;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
QSharedPointer<LogViewTelegram> TelegramProxyModel::telegram(int row) const
|
||||
{
|
||||
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
|
||||
if (!tm)
|
||||
return {};
|
||||
const int srcRow = mapToSource(index(row, 0)).row();
|
||||
return tm->telegram(srcRow);
|
||||
}
|
||||
|
||||
|
||||
bool TelegramProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
if (left.column() != right.column())
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
|
||||
if (!tm)
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
QSharedPointer<LogViewTelegram> teleLeft = tm->telegram(left.row());
|
||||
QSharedPointer<LogViewTelegram> teleRight = tm->telegram(right.row());
|
||||
if (!teleLeft || !teleRight)
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
|
||||
switch (left.column())
|
||||
{
|
||||
case 0:
|
||||
return teleLeft->getDestination() < teleRight->getDestination();
|
||||
case 1:
|
||||
return teleLeft->getName() < teleRight->getName();
|
||||
case 2:
|
||||
return teleLeft->getParticipantId() < teleRight->getParticipantId();
|
||||
case 3:
|
||||
return teleLeft->getLogTime() < teleRight->getLogTime();
|
||||
case 4:
|
||||
return teleLeft->getGpsTime() < teleRight->getGpsTime();
|
||||
case 5:
|
||||
return teleLeft->getDelay() < teleRight->getDelay();
|
||||
}
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
|
||||
bool TelegramProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
|
||||
const TelegramModel *tm = qobject_cast<TelegramModel *>(sourceModel());
|
||||
if (!tm)
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
|
||||
QSharedPointer<LogViewTelegram> tele = tm->telegram(source_row);
|
||||
if (!tele)
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
|
||||
if (m_bFilterByEquipmentIds)
|
||||
{
|
||||
int equipId = tele->getParticipantId();
|
||||
if (m_allowedEquipmentIds.find(equipId) == m_allowedEquipmentIds.end())
|
||||
return false;
|
||||
}
|
||||
switch (tele->getProtocol())
|
||||
{
|
||||
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral:
|
||||
if (!m_filteredCentralTelegramIds.empty())
|
||||
{
|
||||
const int telegramId = tele->getTelId();
|
||||
if (m_filteredCentralTelegramIds.find(telegramId) != m_filteredCentralTelegramIds.end())
|
||||
return false;
|
||||
}
|
||||
if (!m_filterCentralTelegrams.empty())
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction = tele->getDirection();
|
||||
if (m_filterCentralTelegrams.find(direction) != m_filterCentralTelegrams.end())
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra:
|
||||
{
|
||||
if (!m_filteredTetraTelegramIds.empty())
|
||||
{
|
||||
const int telegramId = tele->getTelId();
|
||||
if (m_filteredTetraTelegramIds.find(telegramId) != m_filteredTetraTelegramIds.end())
|
||||
return false;
|
||||
}
|
||||
if (!m_filterTetraTelegrams.empty())
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction = tele->getDirection();
|
||||
if (m_filterTetraTelegrams.find(direction) != m_filterTetraTelegrams.end())
|
||||
return false;
|
||||
}
|
||||
const N_CoPrtCnv::CoPrtCnvRadioTelegram *tetraTelegram = tele->getTetraTelegram();
|
||||
if (tetraTelegram)
|
||||
{
|
||||
if (!m_filterTetraPDU.empty())
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType = tetraTelegram->getPDU_Type();
|
||||
if (m_filterTetraPDU.find(pduType) != m_filterTetraPDU.end())
|
||||
return false;
|
||||
}
|
||||
if (m_bFilterLoginTelegrams)
|
||||
{
|
||||
if (tetraTelegram->isLoginTelegram())
|
||||
return false;
|
||||
}
|
||||
if (m_bFilterFragmentedTelegrams)
|
||||
{
|
||||
if (!tetraTelegram->isLoginTelegram() && !tetraTelegram->isNormalTelegram())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolWls:
|
||||
if (!m_filteredWlsTelegramIds.empty())
|
||||
{
|
||||
const int telegramId = tele->getTelId();
|
||||
if (m_filteredWlsTelegramIds.find(telegramId) != m_filteredWlsTelegramIds.end())
|
||||
return false;
|
||||
}
|
||||
if (!m_filterWlsTelegrams.empty())
|
||||
{
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction = tele->getDirection();
|
||||
if (m_filterWlsTelegrams.find(direction) != m_filterWlsTelegrams.end())
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <set>
|
||||
|
||||
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
|
||||
#include <CoPrtCnv/CoPrtCnvRadioTelegram.hpp>
|
||||
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
class ParticipantModel final : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
void clearParticipants();
|
||||
bool addUpdateParticipants(const QVector<int> &eqIds,
|
||||
const QVector<int> &issis,
|
||||
const QVector<int> &numberOfTelegrams);
|
||||
protected:
|
||||
void updateHeatMap() const;
|
||||
protected:
|
||||
|
||||
QVector<QPair<int, int> > m_particpants;
|
||||
|
||||
QHash<int, int> m_particpantMap;
|
||||
|
||||
mutable QHash<int, QColor> m_participantHeatmap;
|
||||
};
|
||||
|
||||
class TelegramModel final : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
void clearTelegrams();
|
||||
void appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams);
|
||||
void appendTelegram(const QSharedPointer<LogViewTelegram> &telegram);
|
||||
QSharedPointer<LogViewTelegram> telegram(int row) const;
|
||||
protected:
|
||||
QVector<QSharedPointer<LogViewTelegram> > m_telegrams;
|
||||
};
|
||||
|
||||
class TelegramProxyModel final : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QSortFilterProxyModel::QSortFilterProxyModel;
|
||||
|
||||
void setFilterByEquipmentIds(bool bFilterByEquipmentIds);
|
||||
void setAllowedEquipmentIds(const std::set<int> &allowedEquipmentIds);
|
||||
|
||||
void setFilteredCentralTelegramIds(const std::set<int> &filteredCentralTelegramIds);
|
||||
void setFilteredTetraTelegramIds(const std::set<int> &filteredTetraTelegramIds);
|
||||
void setFilteredWlsTelegramIds(const std::set<int> &filteredWlsTelegramIds);
|
||||
|
||||
void setFilterCentralTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter);
|
||||
void setFilterTetraTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter);
|
||||
void setFilterTetraPDU(N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type pduType, bool bFilter);
|
||||
void setFilterWlsTelegrams(N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol direction, bool bFilter);
|
||||
|
||||
void setFilterTetraLogin(bool bFilter);
|
||||
void setFilterTetraFragmented(bool bFilter);
|
||||
|
||||
QSharedPointer<LogViewTelegram> telegram(int row) const;
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
protected:
|
||||
std::set<int> m_allowedEquipmentIds;
|
||||
std::set<int> m_filteredCentralTelegramIds;
|
||||
std::set<int> m_filteredTetraTelegramIds;
|
||||
std::set<int> m_filteredWlsTelegramIds;
|
||||
bool m_bFilterByEquipmentIds = false;
|
||||
bool m_bFilterLoginTelegrams = false;
|
||||
bool m_bFilterFragmentedTelegrams = false;
|
||||
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> m_filterCentralTelegrams;
|
||||
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> m_filterTetraTelegrams;
|
||||
std::set<N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol> m_filterWlsTelegrams;
|
||||
std::set<N_CoPrtCnv::CoPrtCnvRadioTelegram::E_PDU_Type> m_filterTetraPDU;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewOptionDialog.hpp"
|
||||
#include <QCoreApplication>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDir>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QFileDialog>
|
||||
#include <QIntValidator>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
const QString LogViewOptionDialog::SPEC_FILES = tr("Spezifikations-Dateien (*.x)");
|
||||
const QString LogViewOptionDialog::KRLOG_FILES = tr("Log-Dateien (*.krlog)");
|
||||
const QLatin1String LogViewOptionDialog::SPEC_FILES_GROUP("SpecFiles");
|
||||
const QLatin1String LogViewOptionDialog::DIR("Dir");
|
||||
const QLatin1String LogViewOptionDialog::P0_FILENAME("Central2PrtCnv");
|
||||
const QLatin1String LogViewOptionDialog::P5_FILENAME("PrtCnv2TETRA");
|
||||
const QLatin1String LogViewOptionDialog::SERVER_GROUP("ServerPorts");
|
||||
const QLatin1String LogViewOptionDialog::CENTRAL_PORT("Central");
|
||||
const QLatin1String LogViewOptionDialog::TETRA_PORT("Tetra");
|
||||
const QLatin1String LogViewOptionDialog::LOG_FILENAME("LogFilename");
|
||||
const QLatin1String LogViewOptionDialog::INJECTION_GROUP("InjectionServer");
|
||||
const QLatin1String LogViewOptionDialog::INJECTION_HOSTNAME("InjectionHostname");
|
||||
const QLatin1String LogViewOptionDialog::INJECTION_PORT("InjectionPort");
|
||||
|
||||
|
||||
|
||||
LogViewOptionDialog::LogViewOptionDialog(QWidget* a_parent)
|
||||
: QDialog(a_parent)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
|
||||
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
|
||||
QGroupBox* groupBox = new QGroupBox(tr("Telegramm-Spezifikations-Dateien"), this);
|
||||
layout->addWidget(groupBox);
|
||||
|
||||
QGridLayout* groupLayout = new QGridLayout();
|
||||
|
||||
QLabel* p0Label = new QLabel(tr("&Zentrale - Protokollkonverter"), this);
|
||||
groupLayout->addWidget(p0Label, 0, 0, 1, 2);
|
||||
QString defString = QCoreApplication::applicationDirPath() + QLatin1String("/training_area_telegrams.h");
|
||||
m_P0Edit = new QLineEdit(m_Settings.value(P0_FILENAME, defString).toString(), this);
|
||||
m_P0Edit->setMinimumWidth(400);
|
||||
groupLayout->addWidget(m_P0Edit);
|
||||
QPushButton* p0Browse = new QPushButton(tr("Browse"), this);
|
||||
p0Label->setBuddy(p0Browse);
|
||||
connect(p0Browse, &QPushButton::clicked, this, &LogViewOptionDialog::browseP0File);
|
||||
groupLayout->addWidget(p0Browse, 1, 1);
|
||||
|
||||
QLabel* p5Label = new QLabel(tr("Protokollkonverter - &TETRA"), this);
|
||||
groupLayout->addWidget(p5Label, 2, 0, 1, 2);
|
||||
defString = QCoreApplication::applicationDirPath() + QLatin1String("/zsksxd_tetraForLogView.x");
|
||||
m_P5Edit = new QLineEdit(m_Settings.value(P5_FILENAME, defString).toString(), this);
|
||||
groupLayout->addWidget(m_P5Edit);
|
||||
QPushButton* p5Browse = new QPushButton(tr("Browse"), this);
|
||||
p5Label->setBuddy(p5Browse);
|
||||
connect(p5Browse, &QPushButton::clicked, this, &LogViewOptionDialog::browseP5File);
|
||||
groupLayout->addWidget(p5Browse, 3, 1);
|
||||
|
||||
groupBox->setLayout(groupLayout);
|
||||
m_Settings.endGroup();
|
||||
|
||||
|
||||
m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
|
||||
groupBox = new QGroupBox(tr("Telegram Injection Server"), this);
|
||||
layout->addWidget(groupBox);
|
||||
QGridLayout* injectLayout = new QGridLayout();
|
||||
|
||||
QLabel* injectPortLabel = new QLabel(tr("Port"), this);
|
||||
injectLayout->addWidget(injectPortLabel, 1, 0);
|
||||
m_InjectPortEdit = new QLineEdit(m_Settings.value(INJECTION_PORT).toString(), this);
|
||||
QIntValidator* validator = new QIntValidator(1024, 65535, this);
|
||||
m_InjectPortEdit->setValidator(validator);
|
||||
injectLayout->addWidget(m_InjectPortEdit, 1, 1);
|
||||
|
||||
QLabel* injectHostnameLabel = new QLabel(tr("Hostname"), this);
|
||||
injectLayout->addWidget(injectHostnameLabel, 0, 0);
|
||||
m_InjectHostnameEdit = new QLineEdit(m_Settings.value(INJECTION_HOSTNAME).toString(), this);
|
||||
injectLayout->addWidget(m_InjectHostnameEdit, 0, 1);
|
||||
|
||||
groupBox->setLayout(injectLayout);
|
||||
m_Settings.endGroup();
|
||||
|
||||
|
||||
layout->addStretch();
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &LogViewOptionDialog::save);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &LogViewOptionDialog::reject);
|
||||
layout->addWidget(buttonBox);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewOptionDialog::browseP0File()
|
||||
{
|
||||
QString newFilename = QFileDialog::getOpenFileName(this,
|
||||
tr("Zentrale - Protokollkonverter Spezifikations-Datei"),
|
||||
m_Settings.value(DIR).toString(),
|
||||
tr("TrainingArea Telegram Headerdatei (training_area_telegrams.h)"));
|
||||
if (!newFilename.isEmpty())
|
||||
{
|
||||
m_P0Edit->setText(newFilename);
|
||||
QDir dir;
|
||||
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
|
||||
m_Settings.setValue(DIR, dir.filePath(newFilename));
|
||||
m_Settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewOptionDialog::browseP5File()
|
||||
{
|
||||
QString newFilename = QFileDialog::getOpenFileName(this, tr("Protokollkonverter - TETRA Spezifikations-Datei"), m_Settings.value(DIR).toString(), SPEC_FILES);
|
||||
if (!newFilename.isEmpty())
|
||||
{
|
||||
m_P5Edit->setText(newFilename);
|
||||
QDir dir;
|
||||
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
|
||||
m_Settings.setValue(DIR, dir.filePath(newFilename));
|
||||
m_Settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LogViewOptionDialog::save()
|
||||
{
|
||||
uint32_t changedFlags = 0;
|
||||
|
||||
|
||||
|
||||
m_Settings.beginGroup(LogViewOptionDialog::SPEC_FILES_GROUP);
|
||||
QString string = m_Settings.value(P0_FILENAME).toString();
|
||||
if ((string != m_P0Edit->text()) ||
|
||||
(m_Settings.value(P5_FILENAME).toString() != m_P5Edit->text()))
|
||||
{
|
||||
m_Settings.setValue(P0_FILENAME, m_P0Edit->text());
|
||||
m_Settings.setValue(P5_FILENAME, m_P5Edit->text());
|
||||
changedFlags |= SpecFilesGroup;
|
||||
}
|
||||
m_Settings.endGroup();
|
||||
|
||||
|
||||
m_Settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
|
||||
if ((m_Settings.value(INJECTION_HOSTNAME).toString() != m_InjectHostnameEdit->text()) ||
|
||||
(m_Settings.value(INJECTION_PORT).toString() != m_InjectPortEdit->text()))
|
||||
{
|
||||
m_Settings.setValue(INJECTION_HOSTNAME, m_InjectHostnameEdit->text());
|
||||
m_Settings.setValue(INJECTION_PORT, m_InjectPortEdit->text());
|
||||
changedFlags |= InjectionGroup;
|
||||
}
|
||||
m_Settings.endGroup();
|
||||
|
||||
emit settingsChanged(changedFlags);
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewOptionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum SettingsChangedFlag {
|
||||
SpecFilesGroup = 0x01,
|
||||
ServerGroup = 0x02,
|
||||
InjectionGroup = 0x04
|
||||
};
|
||||
|
||||
static const QString KRLOG_FILES;
|
||||
static const QLatin1String SPEC_FILES_GROUP;
|
||||
static const QLatin1String P0_FILENAME;
|
||||
static const QLatin1String P5_FILENAME;
|
||||
static const QLatin1String SERVER_GROUP;
|
||||
static const QLatin1String CENTRAL_PORT;
|
||||
static const QLatin1String TETRA_PORT;
|
||||
static const QLatin1String SIZE;
|
||||
static const QLatin1String POS;
|
||||
static const QLatin1String CENTRAL_IS_SERVER;
|
||||
static const QLatin1String CENTRAL_HOSTNAME;
|
||||
static const QLatin1String LOG_FILENAME;
|
||||
static const QLatin1String INJECTION_GROUP;
|
||||
static const QLatin1String INJECTION_HOSTNAME;
|
||||
static const QLatin1String INJECTION_PORT;
|
||||
|
||||
|
||||
|
||||
|
||||
explicit LogViewOptionDialog(QWidget* a_parent);
|
||||
|
||||
signals:
|
||||
void settingsChanged(uint32_t changed);
|
||||
|
||||
protected:
|
||||
|
||||
static const QString SPEC_FILES;
|
||||
static const QLatin1String DIR;
|
||||
bool m_IsServer;
|
||||
QLineEdit *m_P0Edit;
|
||||
QLineEdit *m_P5Edit;
|
||||
QSettings m_Settings;
|
||||
QLineEdit *m_InjectHostnameEdit;
|
||||
QLineEdit *m_InjectPortEdit;
|
||||
|
||||
protected slots:
|
||||
void browseP0File();
|
||||
void browseP5File();
|
||||
void save();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>image/P2C.png</file>
|
||||
<file>image/C2P.png</file>
|
||||
<file>image/P2W.png</file>
|
||||
<file>image/W2P.png</file>
|
||||
<file>image/P2T.png</file>
|
||||
<file>image/T2P.png</file>
|
||||
<file>image/Central.png</file>
|
||||
<file>image/Tetra.png</file>
|
||||
<file>image/TNE.png</file>
|
||||
<file>image/GreenLamp.png</file>
|
||||
<file>image/RedLamp.png</file>
|
||||
<file>image/YellowLamp.png</file>
|
||||
<file>image/ShowSend.png</file>
|
||||
<file>image/Wls.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewSpinBox.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewSpinBox::LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value)
|
||||
: QSpinBox(a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, false)
|
||||
{
|
||||
|
||||
uint16_t maxArraySize = a_field->maxArraySize();
|
||||
setRange(0, maxArraySize);
|
||||
|
||||
|
||||
setValue(a_value);
|
||||
|
||||
|
||||
setToolTip(tr("<nobr>Wertebereich: 0..%1</nobr>").arg(maxArraySize));
|
||||
|
||||
|
||||
connect(this, &LogViewSpinBox::editingFinished,
|
||||
this, &LogViewSpinBox::finishEditing);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewSpinBox::finishEditing()
|
||||
{
|
||||
emit valueEditingFinished(text().toInt());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewSpinBox::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
Q_UNUSED(a_telegram);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QSpinBox>
|
||||
#include "LogViewWidget.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewSpinBox : public QSpinBox, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value);
|
||||
|
||||
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
|
||||
protected slots:
|
||||
void finishEditing();
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
void valueEditingFinished(int a_newValue);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewTabWidget.hpp"
|
||||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include "LogViewTelegramDialog.hpp"
|
||||
#include "LogViewSpinBox.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include "LogViewTetraTelegramsParser.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewTabWidget::LogViewTabWidget(LogViewField* a_field, LogViewTelegramDialog* a_parent, LogViewSpinBox* a_spinBox)
|
||||
: QTabWidget(a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, false)
|
||||
, m_TelegramDialog(a_parent)
|
||||
, m_SpinBox(a_spinBox)
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTabWidget::changeSize(const int a_newSize)
|
||||
{
|
||||
|
||||
for (int i = count(); i < a_newSize; i++)
|
||||
addTab(m_Field, true, i);
|
||||
|
||||
|
||||
while (count() > a_newSize)
|
||||
{
|
||||
QStringList path = m_Field->jsonPath();
|
||||
path += QStringLiteral("index: %1").arg(count() - 1);
|
||||
m_TelegramDialog->removeItemsFromEditInfoList(path);
|
||||
removeTab(count() - 1);
|
||||
}
|
||||
while (m_Field->childCount() > a_newSize)
|
||||
m_Field->removeLastChild();
|
||||
|
||||
|
||||
setVisible(a_newSize > 0);
|
||||
m_TelegramDialog->makePretty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
if (a_telegram->isJsonTelegram())
|
||||
return true;
|
||||
|
||||
if (m_SpinBox)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, count());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTabWidget::addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx)
|
||||
{
|
||||
if (arrayIdx < 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Invalid array index given: " << arrayIdx;
|
||||
return;
|
||||
}
|
||||
|
||||
QFrame *frame = new QFrame;
|
||||
QGridLayout *box = new QGridLayout(frame);
|
||||
QTabWidget::addTab(frame, QStringLiteral("%1 %2").arg(a_field->cleanName()).arg(count()+1));
|
||||
if (a_isEmpty)
|
||||
a_field->setHasContent(false);
|
||||
auto *childTree = a_field->child(arrayIdx);
|
||||
while (!childTree)
|
||||
{
|
||||
const auto *first = a_field->child(0);
|
||||
if (first)
|
||||
{
|
||||
LogViewField *fNew = first->clone(arrayIdx);
|
||||
a_field->addChild(fNew);
|
||||
childTree = a_field->child(arrayIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogViewTetraTelegramsParser *p = LogViewTelegram::jsonParser();
|
||||
const StructInformation si = p->structFromType(a_field->type());
|
||||
if (si.type != a_field->type())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find type '" << a_field->type() << "' - can not add substructure";
|
||||
return;
|
||||
}
|
||||
LogViewField *tc = new LogViewField(a_field->name() + QStringLiteral("TabChild"), LogViewField::e_FieldKindTabChild, a_field->xdrElement());
|
||||
tc->setJsonPath(a_field->jsonPath());
|
||||
a_field->addChild(tc);
|
||||
const QString path(QStringLiteral("index: %1"));
|
||||
LogViewTelegram::addFieldTreeStruct(QJsonObject(), tc, si, path.arg(arrayIdx), m_logger);
|
||||
childTree = a_field->child(arrayIdx);
|
||||
}
|
||||
}
|
||||
m_TelegramDialog->showTree(childTree, box);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (m_SpinBox)
|
||||
{
|
||||
int spinValue = m_SpinBox->value();
|
||||
if (spinValue < count())
|
||||
m_SpinBox->setValue(count());
|
||||
}
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTabWidget>
|
||||
#include "LogViewWidget.hpp"
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewTelegramDialog;
|
||||
class LogViewSpinBox;
|
||||
|
||||
|
||||
|
||||
class LogViewTabWidget : public QTabWidget, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
LogViewTabWidget(LogViewField* a_field, LogViewTelegramDialog* a_parent, LogViewSpinBox* a_spinBox);
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
void addTab(LogViewField* a_field, const bool a_isEmpty, int arrayIdx);
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
void changeSize(const int a_newSize);
|
||||
|
||||
protected:
|
||||
|
||||
LogViewTelegramDialog* m_TelegramDialog;
|
||||
LogViewSpinBox* m_SpinBox;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewTableWidget.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include <QHeaderView>
|
||||
#include <QJsonArray>
|
||||
#include "LogViewXdrStandardType.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include "LogViewEnumEdit.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewTableWidget::LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
|
||||
: QTableWidget(0, 2, a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, a_readonly)
|
||||
, m_IsFloat(false)
|
||||
, m_IsEnum(false)
|
||||
{
|
||||
switch (m_Field->xdrElement()->getKind())
|
||||
{
|
||||
case LogViewXdrElement::e_KindEnum:
|
||||
m_IsEnum = true;
|
||||
break;
|
||||
default:
|
||||
m_IsFloat = LogViewXdrStandardType::e_Float == static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement())->getValueKind();
|
||||
}
|
||||
if (!m_IsFloat)
|
||||
setColumnCount(3);
|
||||
if (m_IsEnum)
|
||||
setColumnCount(1);
|
||||
|
||||
setHorizontalHeaderItem(0, new QTableWidgetItem(m_IsEnum ? tr("Enum") : tr("Dez")));
|
||||
if (!m_IsEnum)
|
||||
{
|
||||
setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Hex")));
|
||||
if (!m_IsFloat)
|
||||
{
|
||||
setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Bin")));
|
||||
}
|
||||
}
|
||||
setAlternatingRowColors(true);
|
||||
|
||||
|
||||
|
||||
|
||||
updateToolTip();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int nbrOfRows = a_field->valueListSize();
|
||||
setRowCount(nbrOfRows);
|
||||
for (int i = 0; i < nbrOfRows; i++)
|
||||
changeRow(i, a_field->value(i));
|
||||
|
||||
makePretty();
|
||||
|
||||
|
||||
connect(this, &LogViewTableWidget::itemChanged,
|
||||
this, &LogViewTableWidget::checkAndOvertakeContent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTableWidget::changeSize(const int a_newSize)
|
||||
{
|
||||
setRowCount(a_newSize);
|
||||
|
||||
disconnect(this, &LogViewTableWidget::itemChanged,
|
||||
this, &LogViewTableWidget::checkAndOvertakeContent);
|
||||
|
||||
for (int i = 0; i < a_newSize; i++)
|
||||
changeRow(i, QLatin1String("0"));
|
||||
|
||||
connect(this, &LogViewTableWidget::itemChanged,
|
||||
this, &LogViewTableWidget::checkAndOvertakeContent);
|
||||
|
||||
makePretty();
|
||||
|
||||
m_Valid = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTableWidget::changeRow(const int a_rowIndex, const QString& a_value)
|
||||
{
|
||||
|
||||
|
||||
if (m_IsEnum)
|
||||
{
|
||||
|
||||
QWidget* enumItem = cellWidget(a_rowIndex, 0);
|
||||
if (!enumItem)
|
||||
setCellWidget(a_rowIndex, 0, new LogViewEnumEdit(m_Field, this, m_Readonly, a_rowIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
QFont font;
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
font.setFamily(QString());
|
||||
|
||||
QTableWidgetItem* decItem = item(a_rowIndex, 0);
|
||||
if (!decItem)
|
||||
{
|
||||
decItem = new QTableWidgetItem();
|
||||
|
||||
decItem->setText(a_value);
|
||||
decItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
if (!m_Readonly)
|
||||
{
|
||||
decItem->setFlags(decItem->flags() | Qt::ItemIsEditable);
|
||||
}
|
||||
decItem->setFont(font);
|
||||
decItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
setItem(a_rowIndex, 0, decItem);
|
||||
}
|
||||
|
||||
|
||||
QTableWidgetItem* hexItem = item(a_rowIndex, 1);
|
||||
if (!hexItem)
|
||||
{
|
||||
hexItem = new QTableWidgetItem();
|
||||
hexItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
hexItem->setFont(font);
|
||||
hexItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
setItem(a_rowIndex, 1, hexItem);
|
||||
}
|
||||
|
||||
|
||||
if (!m_IsFloat)
|
||||
{
|
||||
QTableWidgetItem* binItem = item(a_rowIndex, 2);
|
||||
if (!binItem)
|
||||
{
|
||||
binItem = new QTableWidgetItem();
|
||||
binItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
binItem->setFont(font);
|
||||
binItem->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
setItem(a_rowIndex, 2, binItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
checkAndOvertakeContent(decItem);
|
||||
makePretty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTableWidget::checkAndOvertakeContent(QTableWidgetItem* a_changedItem)
|
||||
{
|
||||
if (a_changedItem->column() != 0) return;
|
||||
|
||||
int row = a_changedItem->row();
|
||||
QString text = a_changedItem->text();
|
||||
|
||||
|
||||
bool ok;
|
||||
int64_t intValue = 0;
|
||||
double floatValue = 0.0;
|
||||
|
||||
|
||||
if (m_IsFloat)
|
||||
floatValue = getFloat(text, (uint64_t&)intValue, ok, true);
|
||||
else
|
||||
intValue = getInteger(text, ok);
|
||||
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
setFocus();
|
||||
|
||||
setCurrentCell(row, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QTableWidgetItem* decField = item(row, 0);
|
||||
if (decField) decField->setText(QString::number(m_IsFloat ? floatValue : intValue));
|
||||
|
||||
|
||||
QTableWidgetItem* hexField = item(row, 1);
|
||||
if (hexField) hexField->setText(toHex(intValue));
|
||||
|
||||
|
||||
if (!m_IsFloat)
|
||||
{
|
||||
QTableWidgetItem* binField = item(row, 2);
|
||||
if (binField) binField->setText(toBin(intValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTableWidget::makePretty()
|
||||
{
|
||||
|
||||
resizeColumnsToContents();
|
||||
resizeRowsToContents();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewTableWidget::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
|
||||
if (a_telegram->isJsonTelegram())
|
||||
{
|
||||
if (m_Field->kind() == LogViewField::e_FieldKindPodArray)
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (int i = 0; i < rowCount(); ++i)
|
||||
arr += item(i, 0)->text().toInt();
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), arr);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString value;
|
||||
value.reserve(rowCount() * 2);
|
||||
for (int i = 0; i < rowCount(); ++i)
|
||||
{
|
||||
int val = item(i, 0)->text().toInt();
|
||||
value += QStringLiteral("%1").arg(val, 2, 16, QLatin1Char('0'));
|
||||
}
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t arraySize;
|
||||
if (m_Field->isDynamicArray())
|
||||
{
|
||||
arraySize = rowCount();
|
||||
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
arraySize = m_Field->maxArraySize();
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << "arraySize=" << arraySize;
|
||||
for (int i = 0; i < arraySize; i++)
|
||||
{
|
||||
if (m_IsEnum)
|
||||
{
|
||||
LogViewEnumEdit *enumEdit = dynamic_cast<LogViewEnumEdit*>(cellWidget(i,0));
|
||||
enumEdit->saveContent(a_telegram);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t size = getSize();
|
||||
QString text = item(i, 0)->text();
|
||||
if (!m_IsFloat)
|
||||
{
|
||||
a_telegram->setUIntX(size, text.toULong());
|
||||
}
|
||||
else
|
||||
{
|
||||
const LogViewXdrStandardType *stdType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
|
||||
LogViewXdrStandardType::E_ByteOrder byteOrder = stdType->getByteOrder();
|
||||
uint64_t hex;
|
||||
getFloat(text, hex, m_Valid);
|
||||
a_telegram->setUIntX(size, hex, byteOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTableWidget>
|
||||
#include "LogViewWidget.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewTableWidget : public QTableWidget, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
|
||||
|
||||
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
|
||||
public slots:
|
||||
void changeSize(const int a_newSize);
|
||||
|
||||
protected:
|
||||
void changeRow(const int a_rowIndex, const QString& a_value);
|
||||
void makePretty();
|
||||
protected slots:
|
||||
void checkAndOvertakeContent(QTableWidgetItem* a_changedItem);
|
||||
|
||||
private:
|
||||
bool m_IsFloat;
|
||||
bool m_IsEnum;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewXdrStandardType.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include <CoPrtCnv/CoPrtCnvLogHeader.hpp>
|
||||
#include <QIcon>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace N_CoPrtCnv
|
||||
{
|
||||
class CoPrtCnvRadioTelegram;
|
||||
}
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
struct StructInformation;
|
||||
struct MemberInformation;
|
||||
class LogViewTetraTelegramsParser;
|
||||
class LogViewXdrParser;
|
||||
class LogViewXdrType;
|
||||
|
||||
|
||||
class LogViewTelegram final
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
enum E_Validity
|
||||
{
|
||||
e_NotYetEvaluated,
|
||||
e_Valid,
|
||||
e_Invalid
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum E_Column
|
||||
{
|
||||
e_ColName,
|
||||
e_ColGpsTime,
|
||||
e_ColLogTime,
|
||||
e_ColJsonData,
|
||||
e_ColMax
|
||||
};
|
||||
|
||||
|
||||
~LogViewTelegram();
|
||||
|
||||
|
||||
|
||||
static const uint16_t SIZE_CENTRAL_DYN_ARRAY_SIZE;
|
||||
|
||||
|
||||
|
||||
|
||||
LogViewTelegram(const LogViewTelegram &o);
|
||||
|
||||
LogViewTelegram &operator=(const LogViewTelegram &o) = delete;
|
||||
|
||||
|
||||
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
|
||||
int telegramId);
|
||||
|
||||
|
||||
|
||||
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
|
||||
const quint64 a_unixTime,
|
||||
const QByteArray &a_telegramData);
|
||||
|
||||
|
||||
|
||||
void setUIntX(const uint8_t a_size,
|
||||
quint64 a_value,
|
||||
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
|
||||
|
||||
|
||||
|
||||
bool setData(const uint16_t a_offset, const uint8_t a_data);
|
||||
|
||||
|
||||
|
||||
quint64 getLogTime() const { return m_LogTime; }
|
||||
quint64 getLogTimeMsec() const;
|
||||
|
||||
|
||||
|
||||
QString getLogTimeText() const;
|
||||
|
||||
|
||||
QString getDestinationText() const;
|
||||
|
||||
|
||||
|
||||
quint64 getGpsTime() const { return m_GpsTime; }
|
||||
|
||||
|
||||
|
||||
QString getGpsTimeText() const;
|
||||
|
||||
|
||||
uint32_t getISSI() const { return m_ISSI; }
|
||||
|
||||
|
||||
int getParticipantId() const { return m_ParticipantId; }
|
||||
|
||||
|
||||
|
||||
int32_t getDelay() const;
|
||||
|
||||
|
||||
|
||||
QString getToolTipText(const E_Column a_col);
|
||||
|
||||
|
||||
void resetOffset();
|
||||
|
||||
|
||||
LogViewField* getFieldTree();
|
||||
|
||||
|
||||
void dump() const;
|
||||
|
||||
|
||||
QString getStructName() const;
|
||||
|
||||
|
||||
bool isValid();
|
||||
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol getDestination() const { return m_Destination; }
|
||||
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol getDirection() const;
|
||||
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol getProtocol() const { return m_Protocol; }
|
||||
|
||||
|
||||
int getTelId() const { return m_TelId; }
|
||||
|
||||
|
||||
QIcon getIcon() const;
|
||||
|
||||
bool isJsonTelegram() const { return N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Protocol; }
|
||||
void clearJsonData() { m_json.remove(QStringLiteral("data")); }
|
||||
void rebuildJsonString() { if (!m_json.isEmpty()) m_data.clear(); }
|
||||
void setJsonValue(const QStringList &path, const QJsonValue &val);
|
||||
QJsonObject jsonData() const { return m_json; }
|
||||
void updateJsonValue(const QStringList &path, const QJsonValue &newVal, QJsonObject &obj);
|
||||
void updateJsonValue(const QStringList &path, const QJsonValue &newVal, QJsonArray &arr);
|
||||
|
||||
|
||||
const N_CoPrtCnv::CoPrtCnvRadioTelegram* getTetraTelegram() const;
|
||||
|
||||
static LogViewTetraTelegramsParser *jsonParser();
|
||||
static LogViewXdrParser *tetraParser();
|
||||
|
||||
QByteArray getData(QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Compact) const;
|
||||
|
||||
|
||||
|
||||
uint32_t getWaitTime() const { return m_WaitTime; }
|
||||
|
||||
|
||||
|
||||
void setWaitTime(uint32_t newVal) { m_WaitTime = newVal; }
|
||||
|
||||
|
||||
|
||||
QString getName() const { return m_Name; }
|
||||
|
||||
|
||||
|
||||
void setName(const QString &newVal) { m_Name = newVal; }
|
||||
|
||||
|
||||
void setNextFieldAsGpsTimeField();
|
||||
|
||||
QVector<uint16_t> getGpsTimeField() const { return m_GpsFieldOffset; }
|
||||
|
||||
void setGpsTimeField(const QVector<uint16_t> &gpsFieldOffset) { m_GpsFieldOffset = gpsFieldOffset; }
|
||||
|
||||
void actualizeGpsTime();
|
||||
|
||||
|
||||
|
||||
void createToolTipTextForColName();
|
||||
|
||||
|
||||
static double xdrToDouble(quint64 in);
|
||||
static float xdrToFloat(uint32_t in);
|
||||
static quint64 doubleToXdr(double in);
|
||||
static uint32_t floatToXdr(float in);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
QString m_Name;
|
||||
|
||||
|
||||
std::vector<QString> m_ToolTipText;
|
||||
|
||||
|
||||
uint32_t m_WaitTime;
|
||||
int m_ParticipantId;
|
||||
|
||||
|
||||
uint32_t m_ISSI;
|
||||
|
||||
|
||||
int m_AllocatedSize;
|
||||
static const LogViewXdrParser* m_Parser;
|
||||
uint16_t m_ActOffset;
|
||||
QVector<uint16_t> m_GpsFieldOffset;
|
||||
int m_TelId;
|
||||
|
||||
|
||||
uint32_t m_LastUnsignedValue;
|
||||
|
||||
|
||||
uint16_t m_MaxArraySize;
|
||||
static const uint16_t START_OFFSET_CENTRAL;
|
||||
static const uint16_t POS_CENTRAL_COUNTER;
|
||||
static const uint16_t POS_CENTRAL_TELID;
|
||||
static const uint16_t POS_CENTRAL_PARTICIPANTID;
|
||||
static const uint16_t START_OFFSET_TETRA_REGISTER;
|
||||
static const uint16_t START_OFFSET_TETRA_AIRLOAD;
|
||||
static const uint16_t START_OFFSET_TETRA_DATA;
|
||||
static const uint16_t START_OFFSET_TETRA_LOGIN;
|
||||
static const uint16_t START_OFFSET_TETRA_FRAGMENT;
|
||||
LogViewXdrStandardType::E_DynArraySizeMethod m_DynArraySizeMethod;
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol m_Destination;
|
||||
|
||||
E_Validity m_Validity;
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol m_Protocol;
|
||||
|
||||
quint64 m_LogTime;
|
||||
|
||||
mutable QString m_logTimeText;
|
||||
|
||||
quint64 m_GpsTime;
|
||||
|
||||
QByteArray m_data;
|
||||
QJsonObject m_json;
|
||||
|
||||
N_CoPrtCnv::CoPrtCnvRadioTelegram *m_TetraTelegram;
|
||||
|
||||
LogViewField *getFieldTree(const QString& a_type, const QString& a_name,
|
||||
uint16_t a_arraySize, const LogViewXdrType* a_parentElement = nullptr,
|
||||
const bool a_hasContent = true);
|
||||
LogViewField *getFieldTreeJson(const QJsonValue &data,
|
||||
const QString &name,
|
||||
const StructInformation &si,
|
||||
const QStringList &objectPathBase);
|
||||
|
||||
static void addFieldTreeStruct(const QJsonObject &parentObject,
|
||||
LogViewField *parent,
|
||||
const StructInformation &si,
|
||||
const QString &objectNameArrayHint,
|
||||
NGL::INGLLogger &logger);
|
||||
static void addFieldTreeJsonString(const QJsonValue &val,
|
||||
LogViewField *parent,
|
||||
const QString &name,
|
||||
bool isBinary,
|
||||
const QString &objectNameArrayHint,
|
||||
LogViewField::E_FieldKind fieldKind,
|
||||
NGL::INGLLogger &logger);
|
||||
static void addFieldTreeJsonPod(const QJsonValue &val,
|
||||
LogViewField *parent,
|
||||
const QString &name,
|
||||
const QString &type,
|
||||
const QString &objectNameArrayHint,
|
||||
LogViewField::E_FieldKind fieldKind,
|
||||
NGL::INGLLogger &logger);
|
||||
static void addFieldTreeJsonEnum(const QJsonValue &val,
|
||||
LogViewField *parent,
|
||||
const QString &name,
|
||||
const QString &type,
|
||||
const QString &objectNameArrayHint,
|
||||
LogViewField::E_FieldKind fieldKind,
|
||||
NGL::INGLLogger &logger);
|
||||
|
||||
static QString typeFromStructInformation(const StructInformation &si, const QString &name);
|
||||
static MemberInformation memberFromStructInformation(const StructInformation &si, const QString &name);
|
||||
|
||||
|
||||
|
||||
uint16_t getUInt16(const uint16_t a_offset) const;
|
||||
|
||||
|
||||
|
||||
uint32_t getUInt32(const uint16_t a_offset) const;
|
||||
|
||||
|
||||
|
||||
int32_t getInt32(const uint16_t a_offset) const;
|
||||
|
||||
|
||||
|
||||
quint64 getUIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
|
||||
|
||||
|
||||
|
||||
int32_t getSIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
|
||||
|
||||
|
||||
|
||||
char getChar(const uint16_t a_offset, const uint8_t a_size) const;
|
||||
|
||||
|
||||
|
||||
LogViewField* getContent(const LogViewXdrStandardType* a_standardType, uint16_t& a_offset, const uint16_t a_arraySize);
|
||||
|
||||
|
||||
|
||||
bool isScalar(const LogViewXdrType* a_xdrType) const;
|
||||
|
||||
|
||||
|
||||
void showMessageBox(const QString& a_errorText, const QString& a_title = QObject::tr("Invalid telegram")) const;
|
||||
|
||||
|
||||
|
||||
uint16_t getDynArraySize(uint16_t& a_offset) const;
|
||||
|
||||
|
||||
|
||||
static QString formatToolTipLine(const QString& a_name, const uint32_t a_value)
|
||||
{
|
||||
return formatToolTipLine(a_name, QString::number(a_value), a_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static QString formatToolTipLine(const QString& a_name, const QString& a_text, const uint32_t a_value);
|
||||
|
||||
static QString formatToolTipLine(const QString& a_name, const std::string& a_text, const uint32_t a_value)
|
||||
{
|
||||
return formatToolTipLine(a_name, QString::fromStdString(a_text), a_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t getData(const uint16_t a_offset) const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
friend class LogViewTabWidget;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,497 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewTelegramDialog.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
#include <QScrollArea>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include "LogViewXdrElement.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include "IntegerCalculator.hpp"
|
||||
#include "LogViewBooleanEdit.hpp"
|
||||
#include "LogViewTextEdit.hpp"
|
||||
#include "LogViewValueEdit.hpp"
|
||||
#include "LogViewEnumEdit.hpp"
|
||||
#include "LogViewDateTimeEdit.hpp"
|
||||
#include "LogViewSpinBox.hpp"
|
||||
#include "LogViewTableWidget.hpp"
|
||||
#include "LogViewTabWidget.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LogViewTelegramDialog::LogViewTelegramDialog(QWidget *a_parent, const bool a_readonly)
|
||||
: QDialog(a_parent)
|
||||
, m_ReadOnly(a_readonly)
|
||||
, m_logger(getLogger("LogViewTelegramDialog"))
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
|
||||
void LogViewTelegramDialog::showDialog(const QSharedPointer<LogViewTelegram> &a_telegram)
|
||||
{
|
||||
delete layout();
|
||||
hide();
|
||||
|
||||
m_Telegram = a_telegram;
|
||||
a_telegram->dump();
|
||||
|
||||
m_fieldTree.reset(a_telegram->getFieldTree());
|
||||
|
||||
if (m_fieldTree)
|
||||
{
|
||||
QGridLayout *dialogLayout = new QGridLayout;
|
||||
if (!m_ReadOnly)
|
||||
{
|
||||
|
||||
QLabel *waitTimeLabel = new QLabel(tr("Wartezeit [ms]"), this);
|
||||
dialogLayout->addWidget(waitTimeLabel, dialogLayout->rowCount(), 0);
|
||||
m_WaitTimeEdit = new QLineEdit(QString::number(a_telegram->getWaitTime()), this);
|
||||
dialogLayout->addWidget(m_WaitTimeEdit, dialogLayout->rowCount() - 1, 1);
|
||||
|
||||
|
||||
QLabel *nameLabel = new QLabel(tr("Name"), this);
|
||||
dialogLayout->addWidget(nameLabel, dialogLayout->rowCount(), 0);
|
||||
m_NameEdit = new QLineEdit(a_telegram->getName(), this);
|
||||
dialogLayout->addWidget(m_NameEdit, dialogLayout->rowCount() - 1, 1);
|
||||
|
||||
QFrame *f = new QFrame(this);
|
||||
f->setFrameShape(QFrame::HLine);
|
||||
f->setFrameShadow(QFrame::Sunken);
|
||||
dialogLayout->addWidget(f, dialogLayout->rowCount(), 0, 1, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
showTree(m_fieldTree.data(), dialogLayout);
|
||||
if (this->findChild<LogViewTableWidget *>() == nullptr)
|
||||
dialogLayout->setRowStretch(dialogLayout->rowCount(), 1);
|
||||
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
|
||||
|
||||
m_contentsWidget = new QWidget;
|
||||
m_contentsWidget->setLayout(dialogLayout);
|
||||
|
||||
m_ScrollArea = new QScrollArea(this);
|
||||
m_ScrollArea->setWidget(m_contentsWidget);
|
||||
m_ScrollArea->setWidgetResizable(true);
|
||||
|
||||
mainLayout->addWidget(m_ScrollArea);
|
||||
|
||||
|
||||
QHBoxLayout *btnLayout = new QHBoxLayout;
|
||||
btnLayout->addStretch();
|
||||
showButtons(btnLayout);
|
||||
|
||||
mainLayout->addLayout(btnLayout);
|
||||
|
||||
setWindowTitle(m_fieldTree->cleanName() + QStringLiteral(" (%1)").arg(a_telegram->getTelId()));
|
||||
|
||||
setModal(true);
|
||||
show();
|
||||
|
||||
makePretty();
|
||||
}
|
||||
else
|
||||
showDataDump(a_telegram, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::showDataDump(const QSharedPointer<LogViewTelegram> &a_telegram, bool showErrorMessage)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
layout->addWidget(new QLabel(tr("Telegramm-Dump")));
|
||||
|
||||
if (showErrorMessage)
|
||||
|
||||
layout->addWidget(new QLabel(tr("Konnte Dialog basierend auf Struktur \'%1\' nicht generieren!").arg(a_telegram->getStructName())));
|
||||
else
|
||||
layout->addWidget(new QLabel(tr("HexData from \'%1\' - telegram:").arg(a_telegram->getName())));
|
||||
|
||||
|
||||
QString theDump = QLatin1String("<code>");
|
||||
const QByteArray &data = a_telegram->getData();
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
if (0 == (i % 8))
|
||||
theDump += QStringLiteral("%1:").arg(i, 4, 16, QLatin1Char('0'));
|
||||
|
||||
theDump += QStringLiteral(" %1").arg(static_cast<unsigned char>(data[i]), 2, 16, QLatin1Char('0'));
|
||||
if (7 == (i % 8))
|
||||
theDump += QLatin1String("<br>");
|
||||
}
|
||||
theDump += QLatin1String("</code>");
|
||||
|
||||
QTextEdit *telegramDump = new QTextEdit(theDump);
|
||||
layout->addWidget(telegramDump);
|
||||
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen"));
|
||||
QHBoxLayout *btnLayout = new QHBoxLayout;
|
||||
btnLayout->addStretch();
|
||||
btnLayout->addWidget(btnClose);
|
||||
layout->addLayout(btnLayout);
|
||||
connect(btnClose, &QPushButton::clicked,
|
||||
this, &LogViewTelegramDialog::reject);
|
||||
setLayout(layout);
|
||||
show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::makePretty()
|
||||
{
|
||||
return;
|
||||
|
||||
int sbWidth = m_ScrollArea->width() - m_ScrollArea->viewport()->width();
|
||||
int wDiff = m_contentsWidget->width() - m_ScrollArea->width();
|
||||
int hDiff = m_contentsWidget->height() - m_ScrollArea->viewport()->height();
|
||||
const QRect screenSize = QApplication::desktop()->screenGeometry(this);
|
||||
|
||||
int newWidth = std::min(width() + wDiff + sbWidth, screenSize.width() * 9 / 10);
|
||||
int newHeight = std::min(height() + hDiff, screenSize.height() * 9 / 10);
|
||||
|
||||
|
||||
resize(QSize(newWidth, newHeight));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::showTree(LogViewField *a_fieldTree, QGridLayout *a_box)
|
||||
{
|
||||
int i = 0;
|
||||
while (LogViewField *child = a_fieldTree->child(i++))
|
||||
{
|
||||
if (!a_fieldTree->hasContent())
|
||||
child->setHasContent(false);
|
||||
switch (child->kind())
|
||||
{
|
||||
case LogViewField::e_FieldKindBorder:
|
||||
{
|
||||
QGroupBox *groupBox = new QGroupBox(child->cleanName());
|
||||
QGridLayout *actBox = new QGridLayout(groupBox);
|
||||
a_box->addWidget(groupBox, a_box->rowCount(), 0, 1, 2);
|
||||
showTree(child, actBox);
|
||||
break;
|
||||
}
|
||||
case LogViewField::e_FieldKindTab:
|
||||
showTab(child, a_box);
|
||||
break;
|
||||
case LogViewField::e_FieldKindTabChild:
|
||||
{
|
||||
QWidget *widget = new QWidget;
|
||||
widget->setContentsMargins(QMargins());
|
||||
QGridLayout *actBox = new QGridLayout(widget);
|
||||
a_box->addWidget(widget, a_box->rowCount(), 0, 1, 2);
|
||||
showTree(child, actBox);
|
||||
break;
|
||||
}
|
||||
case LogViewField::e_FieldKindEdit:
|
||||
case LogViewField::e_FieldKindPodArray:
|
||||
case LogViewField::e_FieldKindPodArrayChild:
|
||||
showEditField(child, a_box);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::fillTelegram(LogViewTelegram *a_telegram)
|
||||
{
|
||||
INFO_LOG(m_logger) << "******************************************";
|
||||
|
||||
|
||||
|
||||
for (const auto ptr : qAsConst(m_EditInfoList))
|
||||
{
|
||||
if (!ptr->isValid())
|
||||
{
|
||||
INFO_LOG(m_logger) << ptr->field()->name() << " is invalid";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
a_telegram->resetOffset();
|
||||
a_telegram->clearJsonData();
|
||||
for (auto ptr : qAsConst(m_EditInfoList))
|
||||
{
|
||||
if (!ptr->saveContent(a_telegram))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error while saving telegram"),
|
||||
tr("Found an invalid value - the telegram may be not saved correctly"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::saveTelegram()
|
||||
{
|
||||
fillTelegram(m_Telegram.data());
|
||||
|
||||
|
||||
N_SST::IntegerCalculator calculator;
|
||||
N_SST::IntegerCalculator::E_Error error;
|
||||
m_Telegram->setWaitTime(calculator.calc(m_WaitTimeEdit->text().toStdString(), error));
|
||||
m_Telegram->setName(m_NameEdit->text());
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
void LogViewTelegramDialog::sendCurrentTelegram()
|
||||
{
|
||||
emit sendTelegram(m_Telegram);
|
||||
}
|
||||
|
||||
|
||||
void LogViewTelegramDialog::showButtons(QLayout *a_layout)
|
||||
{
|
||||
if (N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral == m_Telegram->getProtocol())
|
||||
{
|
||||
QPushButton *btnSend = new QPushButton(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("&Send"));
|
||||
btnSend->setEnabled(true);
|
||||
connect(btnSend, &QPushButton::clicked, this, &LogViewTelegramDialog::sendCurrentTelegram);
|
||||
a_layout->addWidget(btnSend);
|
||||
}
|
||||
|
||||
if (m_ReadOnly)
|
||||
{
|
||||
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Schliessen"));
|
||||
connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject);
|
||||
a_layout->addWidget(btnClose);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
QPushButton *btnClose = new QPushButton(QIcon(QLatin1String(":icons/16x16/edit-delete.png")), tr("&Abbrechen"));
|
||||
connect(btnClose, &QPushButton::clicked, this, &LogViewTelegramDialog::reject);
|
||||
a_layout->addWidget(btnClose);
|
||||
|
||||
QPushButton *btnOk = new QPushButton(QIcon(QLatin1String(":icons/16x16/dialog-ok-apply.png")), tr("&OK"));
|
||||
btnOk->setDefault(true);
|
||||
|
||||
connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram);
|
||||
a_layout->addWidget(btnOk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLayout *a_box)
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
switch (a_logViewField->valueListSize())
|
||||
{
|
||||
case 1:
|
||||
|
||||
if (m_ReadOnly || !a_logViewField->isDynamicArray() || (LogViewXdrStandardType::e_Character == static_cast<const LogViewXdrStandardType *>(a_logViewField->xdrElement())->getValueKind()))
|
||||
{
|
||||
QLabel *label = new QLabel(a_logViewField->cleanName());
|
||||
a_box->addWidget(label, a_box->rowCount(), 0);
|
||||
LogViewWidget *valueWidget = nullptr;
|
||||
|
||||
|
||||
{
|
||||
|
||||
|
||||
if (LogViewXdrElement::e_KindEnum == a_logViewField->xdrElement()->getKind())
|
||||
{
|
||||
|
||||
|
||||
valueWidget = new LogViewEnumEdit(a_logViewField, this, m_ReadOnly, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a_logViewField->isDateTimeField() || a_logViewField->isMSecsField())
|
||||
{
|
||||
|
||||
|
||||
valueWidget = new LogViewDateTimeEdit(a_logViewField, this, m_ReadOnly);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (static_cast<const LogViewXdrStandardType *>(a_logViewField->xdrElement())->getValueKind())
|
||||
{
|
||||
case LogViewXdrStandardType::e_Boolean:
|
||||
valueWidget = new LogViewBooleanEdit(a_logViewField, this, m_ReadOnly);
|
||||
break;
|
||||
case LogViewXdrStandardType::e_Signed:
|
||||
case LogViewXdrStandardType::e_Unsigned:
|
||||
case LogViewXdrStandardType::e_Float:
|
||||
case LogViewXdrStandardType::e_Data:
|
||||
valueWidget = new LogViewValueEdit(a_logViewField, this, m_ReadOnly);
|
||||
break;
|
||||
case LogViewXdrStandardType::e_Character:
|
||||
valueWidget = new LogViewTextEdit(a_logViewField, this, m_ReadOnly);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valueWidget)
|
||||
m_EditInfoList.push_back(valueWidget);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QWidget *w = dynamic_cast<QWidget *>(valueWidget);
|
||||
if (w)
|
||||
a_box->addWidget(w, a_box->rowCount() - 1, 1);
|
||||
else
|
||||
WARNING_LOG(m_logger) << "Internal error - LogViewWidget is not derived from QWidget... !?";
|
||||
break;
|
||||
}
|
||||
|
||||
Q_FALLTHROUGH();
|
||||
case 0:
|
||||
if (m_ReadOnly)
|
||||
{
|
||||
|
||||
a_box->addWidget(new QLabel(tr("Keine %1").arg(a_logViewField->cleanName())));
|
||||
break;
|
||||
}
|
||||
|
||||
Q_FALLTHROUGH();
|
||||
default:
|
||||
{
|
||||
|
||||
QLabel *label = new QLabel(a_logViewField->cleanName());
|
||||
a_box->addWidget(label, a_box->rowCount(), 0);
|
||||
|
||||
|
||||
LogViewSpinBox *spinBox = nullptr;
|
||||
if (!m_ReadOnly && a_logViewField->isDynamicArray())
|
||||
{
|
||||
spinBox = new LogViewSpinBox(a_logViewField, this, a_logViewField->valueListSize());
|
||||
a_box->addWidget(spinBox, a_box->rowCount() - 1, 1);
|
||||
}
|
||||
|
||||
|
||||
LogViewTableWidget *tableWidget = new LogViewTableWidget(a_logViewField, this, m_ReadOnly);
|
||||
m_EditInfoList.push_back(tableWidget);
|
||||
a_box->addWidget(tableWidget, a_box->rowCount(), 0, 1, 2);
|
||||
|
||||
|
||||
if (spinBox)
|
||||
{
|
||||
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
|
||||
tableWidget, &LogViewTableWidget::changeSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramDialog::showTab(LogViewField *a_logViewField, QGridLayout *a_box)
|
||||
{
|
||||
LogViewSpinBox *spinBox = nullptr;
|
||||
if (!m_ReadOnly && a_logViewField->isDynamicArray())
|
||||
{
|
||||
|
||||
QLabel *label = new QLabel(a_logViewField->cleanName());
|
||||
a_box->addWidget(label, a_box->rowCount(), 0);
|
||||
spinBox = new LogViewSpinBox(a_logViewField, this, 0);
|
||||
a_box->addWidget(spinBox, a_box->rowCount() - 1, 1);
|
||||
}
|
||||
|
||||
LogViewTabWidget *a_tabWidget = new LogViewTabWidget(a_logViewField, this, spinBox);
|
||||
m_EditInfoList.push_back(dynamic_cast<LogViewWidget *>(a_tabWidget));
|
||||
a_box->addWidget(a_tabWidget, a_box->rowCount(), 0, 1, 2);
|
||||
|
||||
|
||||
if (spinBox)
|
||||
{
|
||||
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
|
||||
a_tabWidget, &LogViewTabWidget::changeSize);
|
||||
}
|
||||
|
||||
|
||||
if (a_logViewField->hasContent())
|
||||
{
|
||||
for (int i = 0; i < a_logViewField->childCount(); ++i)
|
||||
a_tabWidget->addTab(a_logViewField, false, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LogViewTelegramDialog::removeItemsFromEditInfoList(const QStringList &jsonPath)
|
||||
{
|
||||
if (m_EditInfoList.empty())
|
||||
return false;
|
||||
for (int i = m_EditInfoList.size() - 1; i >= 0; --i)
|
||||
{
|
||||
LogViewWidget *lvw = m_EditInfoList.at(i);
|
||||
const QStringList jsonPathChild = lvw->field()->jsonPath();
|
||||
if (jsonPathChild.size() < jsonPath.size())
|
||||
continue;
|
||||
bool bIsChild = true;
|
||||
for (int j = 0; j < jsonPath.size(); ++j)
|
||||
{
|
||||
if (jsonPath.at(j) != jsonPathChild.at(j))
|
||||
{
|
||||
bIsChild = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bIsChild)
|
||||
continue;
|
||||
delete m_EditInfoList.at(i);
|
||||
m_EditInfoList.removeAt(i);
|
||||
}
|
||||
m_EditInfoList.resize(m_EditInfoList.size() - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include "logger.h"
|
||||
|
||||
class QGridLayout;
|
||||
class QTabWidget;
|
||||
class QFrame;
|
||||
class QScrollArea;
|
||||
class QLineEdit;
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewWidget;
|
||||
class LogViewTelegram;
|
||||
class LogViewField;
|
||||
|
||||
|
||||
|
||||
class LogViewTelegramDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LogViewTelegramDialog(QWidget *a_parent = nullptr, const bool a_readonly = true);
|
||||
|
||||
void showDialog(const QSharedPointer<LogViewTelegram> &a_telegram);
|
||||
void showDataDump(const QSharedPointer<LogViewTelegram> &a_telegram, bool showErrorMessage);
|
||||
void makePretty();
|
||||
void showTree(LogViewField *a_fieldTree, QGridLayout *a_box);
|
||||
|
||||
|
||||
|
||||
bool removeItemsFromEditInfoList(const QStringList &jsonPath);
|
||||
|
||||
Q_SIGNALS:
|
||||
void sendTelegram(const QSharedPointer<LogViewTelegram> &telegramToSend);
|
||||
protected slots:
|
||||
void saveTelegram();
|
||||
|
||||
void sendCurrentTelegram();
|
||||
|
||||
protected:
|
||||
|
||||
void fillTelegram(LogViewTelegram *a_telegram);
|
||||
void showButtons(QLayout *a_layout);
|
||||
void showEditField(LogViewField *a_logViewField, QGridLayout *a_box);
|
||||
void showTab(LogViewField *a_logViewField, QGridLayout *a_box);
|
||||
|
||||
private:
|
||||
QSharedPointer<LogViewTelegram> m_Telegram;
|
||||
QVector<LogViewWidget *> m_EditInfoList;
|
||||
QScopedPointer<LogViewField> m_fieldTree;
|
||||
QWidget *m_contentsWidget = nullptr;
|
||||
QScrollArea *m_ScrollArea = nullptr;
|
||||
QLineEdit *m_NameEdit = nullptr;
|
||||
QLineEdit *m_WaitTimeEdit = nullptr;
|
||||
bool m_ReadOnly = false;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,586 @@
|
||||
|
||||
|
||||
|
||||
#include "LogViewTelegramEdit.hpp"
|
||||
|
||||
#include "LogViewInjectionThread.hpp"
|
||||
#include "LogViewTelegramDialog.hpp"
|
||||
#include "LogViewTelegramEditModel.hpp"
|
||||
#include "LogViewTelegramSelectionDialog.hpp"
|
||||
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
|
||||
|
||||
#include <QAction>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QIcon>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QModelIndex>
|
||||
#include <QSettings>
|
||||
#include <QTableView>
|
||||
#include <QTimer>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
QString TelegramEdit::s_DIR()
|
||||
{
|
||||
return QStringLiteral("Dir");
|
||||
}
|
||||
QString TelegramEdit::s_EDIT_TELEGRAM_GROUP()
|
||||
{
|
||||
return QStringLiteral("EditTelegrams");
|
||||
}
|
||||
QString TelegramEdit::s_TELEGRAMLIST_FILE_ID()
|
||||
{
|
||||
return QStringLiteral("RDETGL");
|
||||
}
|
||||
QString TelegramEdit::s_TELEGRAMLIST_FILES()
|
||||
{
|
||||
return tr("Telegrammliste-Dateien (*.tgl);;Alle Dateien (*)");
|
||||
}
|
||||
|
||||
TelegramEdit::TelegramEdit(QWidget *parent)
|
||||
: QObject(parent)
|
||||
, m_addTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-add.png")), tr("Add Telegram"), this))
|
||||
, m_editTeleAction(new QAction(QIcon(QLatin1String(":/image/Edit.png")), tr("Edit Telegram"), this))
|
||||
, m_copyTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-copy.png")), tr("Copy Telegram"), this))
|
||||
, m_pasteTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-paste.png")), tr("Paste Telegram"), this))
|
||||
, m_deleteTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-remove.png")), tr("Delete Telegram"), this))
|
||||
, m_moveTeleUpAction(new QAction(QIcon(QLatin1String(":icons/16x16/go-up.png")), tr("Move up"), this))
|
||||
, m_moveTeleDownAction(new QAction(QIcon(QLatin1String(":icons/16x16/go-down.png")), tr("Move down"), this))
|
||||
, m_teleListLoad(new QAction(QIcon(QLatin1String(":icons/16x16/document-open-data.png")), tr("Load Telegram list"), this))
|
||||
, m_teleListAppend(new QAction(QIcon(), tr("Telegrammliste anhaengen"), this))
|
||||
, m_teleListSave(new QAction(QIcon(QLatin1String(":icons/16x16/document-save.png")), tr("Save Telegram list"), this))
|
||||
, m_tableView(new QTableView(parent))
|
||||
, m_DoLoop(false)
|
||||
, m_InjectionThread(nullptr)
|
||||
, m_EditModel(new TelegramEditModel(this))
|
||||
, m_logger(getLogger("LogViewTelegramEdit"))
|
||||
{
|
||||
m_addTeleAction->setShortcut(tr("Ctrl+A"));
|
||||
m_editTeleAction->setShortcut(tr("Ctrl+E"));
|
||||
m_copyTeleAction->setShortcut(tr("Ctrl+C"));
|
||||
m_pasteTeleAction->setShortcut(tr("Ctrl+V"));
|
||||
m_deleteTeleAction->setShortcut(Qt::Key_Delete);
|
||||
m_moveTeleUpAction->setShortcut(tr("Ctrl+U"));
|
||||
m_moveTeleDownAction->setShortcut(tr("Ctrl+D"));
|
||||
m_teleListLoad->setShortcut(tr("Ctrl+L"));
|
||||
m_teleListAppend->setShortcut(tr("Ctrl+K"));
|
||||
m_teleListSave->setShortcut(tr("Ctrl+S"));
|
||||
m_addTeleAction->setEnabled(true);
|
||||
m_copyTeleAction->setEnabled(false);
|
||||
m_pasteTeleAction->setEnabled(false);
|
||||
m_deleteTeleAction->setEnabled(false);
|
||||
m_moveTeleUpAction->setEnabled(false);
|
||||
m_moveTeleDownAction->setEnabled(false);
|
||||
m_teleListLoad->setEnabled(true);
|
||||
m_teleListAppend->setEnabled(true);
|
||||
m_teleListSave->setEnabled(false);
|
||||
|
||||
connect(m_addTeleAction, &QAction::triggered, this, &TelegramEdit::addTelegram);
|
||||
connect(m_editTeleAction, &QAction::triggered, this, &TelegramEdit::editTelegram);
|
||||
connect(m_copyTeleAction, &QAction::triggered, this, &TelegramEdit::copy);
|
||||
connect(m_pasteTeleAction, &QAction::triggered, this, &TelegramEdit::paste);
|
||||
connect(m_deleteTeleAction, &QAction::triggered, this, &TelegramEdit::deleteTelegram);
|
||||
connect(m_moveTeleUpAction, &QAction::triggered, this, &TelegramEdit::moveUp);
|
||||
connect(m_moveTeleDownAction, &QAction::triggered, this, &TelegramEdit::moveDown);
|
||||
connect(m_teleListLoad, &QAction::triggered, this, &TelegramEdit::loadTelegramListReplace);
|
||||
connect(m_teleListAppend, &QAction::triggered, this, &TelegramEdit::loadTelegramListAppend);
|
||||
connect(m_teleListSave, &QAction::triggered, this, &TelegramEdit::saveTelegramList);
|
||||
|
||||
m_tableView->setModel(m_EditModel);
|
||||
m_tableView->verticalHeader()->hide();
|
||||
m_tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &TelegramEdit::onSelectionChanged);
|
||||
connect(m_tableView, &QTableView::doubleClicked,
|
||||
this, &TelegramEdit::editTelegram);
|
||||
connect(m_tableView, &QTableView::customContextMenuRequested,
|
||||
this, &TelegramEdit::tableViewCustomContextMenu);
|
||||
m_tableView->addAction(m_addTeleAction);
|
||||
m_tableView->addAction(m_editTeleAction);
|
||||
m_tableView->addAction(m_copyTeleAction);
|
||||
m_tableView->addAction(m_pasteTeleAction);
|
||||
m_tableView->addAction(m_deleteTeleAction);
|
||||
m_tableView->addAction(m_moveTeleUpAction);
|
||||
m_tableView->addAction(m_moveTeleDownAction);
|
||||
}
|
||||
|
||||
void TelegramEdit::setInjectionThread(LogViewInjectionThread *a_injectionThread)
|
||||
{
|
||||
m_InjectionThread = a_injectionThread;
|
||||
}
|
||||
|
||||
void TelegramEdit::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
|
||||
{
|
||||
m_EditModel->appendTelegram(telegram);
|
||||
m_teleListSave->setEnabled(true);
|
||||
}
|
||||
|
||||
void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
|
||||
{
|
||||
QMenu menu;
|
||||
|
||||
|
||||
|
||||
menu.addAction(m_addTeleAction);
|
||||
menu.addAction(m_editTeleAction);
|
||||
menu.addAction(m_copyTeleAction);
|
||||
menu.addAction(m_pasteTeleAction);
|
||||
menu.addAction(m_deleteTeleAction);
|
||||
|
||||
|
||||
|
||||
menu.addSeparator();
|
||||
menu.addAction(m_moveTeleUpAction);
|
||||
menu.addAction(m_moveTeleDownAction);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
const bool itemSelected = m_tableView->currentIndex().isValid();
|
||||
|
||||
bool isCentral = false;
|
||||
QSharedPointer<LogViewTelegram> tele = m_EditModel->telegram(m_tableView->currentIndex().row());
|
||||
if (tele)
|
||||
isCentral = (tele->getProtocol() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral);
|
||||
|
||||
|
||||
|
||||
if (isInjectionPossible())
|
||||
{
|
||||
QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm"));
|
||||
|
||||
action->setEnabled(itemSelected && isCentral);
|
||||
connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram);
|
||||
|
||||
action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm"));
|
||||
|
||||
action->setEnabled(itemSelected && isCentral);
|
||||
connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
|
||||
|
||||
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm"));
|
||||
|
||||
action->setEnabled(itemSelected && isCentral);
|
||||
connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram);
|
||||
|
||||
if (m_DoLoop)
|
||||
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-stop.png")), tr("Stop Loopen"));
|
||||
else
|
||||
{
|
||||
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-start.png")), tr("Loop Telegramme"));
|
||||
action->setEnabled(itemSelected);
|
||||
}
|
||||
connect(action, &QAction::triggered, this, &TelegramEdit::loopTelegrams);
|
||||
|
||||
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-play-normal.png")), tr("Sende Sequenz"));
|
||||
action->setEnabled(itemSelected);
|
||||
connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams);
|
||||
|
||||
|
||||
|
||||
menu.addSeparator();
|
||||
}
|
||||
|
||||
menu.addAction(m_teleListLoad);
|
||||
menu.addAction(m_teleListAppend);
|
||||
menu.addAction(m_teleListSave);
|
||||
|
||||
menu.exec(m_tableView->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void TelegramEdit::addTelegram()
|
||||
{
|
||||
|
||||
LogViewTelegramSelectionDialog telegramSelectionDialog(m_tableView);
|
||||
if (QDialog::Accepted == telegramSelectionDialog.exec())
|
||||
{
|
||||
QSharedPointer<LogViewTelegram> newTelegram = QSharedPointer<LogViewTelegram>(new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral,
|
||||
telegramSelectionDialog.getSelectedTelegramId()));
|
||||
m_curEditTelegramRow = m_EditModel->appendTelegram(newTelegram);
|
||||
|
||||
|
||||
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
|
||||
connect(editTelegramDialog, &LogViewTelegramDialog::finished,
|
||||
this, &TelegramEdit::editTelegramDialogFinished);
|
||||
connect(editTelegramDialog, &LogViewTelegramDialog::sendTelegram,
|
||||
this, &TelegramEdit::sendTelegram);
|
||||
editTelegramDialog->showDialog(newTelegram);
|
||||
|
||||
m_teleListSave->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<LogViewTelegram> TelegramEdit::currentSelectedTelegram() const
|
||||
{
|
||||
return m_EditModel->telegram(currentSelectedIndex().row());
|
||||
}
|
||||
|
||||
QModelIndex TelegramEdit::currentSelectedIndex() const
|
||||
{
|
||||
return m_tableView->currentIndex();
|
||||
}
|
||||
|
||||
void TelegramEdit::editTelegramDialogFinished()
|
||||
{
|
||||
|
||||
m_EditModel->emitDataChanged(m_curEditTelegramRow);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TelegramEdit::editTelegram()
|
||||
{
|
||||
m_curEditTelegramRow = currentSelectedIndex().row();
|
||||
if (m_curEditTelegramRow < 0)
|
||||
return;
|
||||
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
|
||||
connect(editTelegramDialog, &LogViewTelegramDialog::finished, this, &TelegramEdit::editTelegramDialogFinished);
|
||||
editTelegramDialog->showDialog(currentSelectedTelegram());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TelegramEdit::showTelegram()
|
||||
{
|
||||
LogViewTelegramDialog *showTelegramDialog = new LogViewTelegramDialog(m_tableView, true);
|
||||
showTelegramDialog->showDialog(currentSelectedTelegram());
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TelegramEdit::deleteTelegram()
|
||||
{
|
||||
const QModelIndexList indexList = m_tableView->selectionModel()->selectedIndexes();
|
||||
QSet<int> rows;
|
||||
rows.reserve(indexList.size());
|
||||
for (const QModelIndex &index : indexList)
|
||||
rows += index.row();
|
||||
|
||||
m_EditModel->removeTelegrams(rows);
|
||||
m_teleListSave->setEnabled(m_EditModel->rowCount() > 0);
|
||||
}
|
||||
|
||||
void TelegramEdit::injectCentralTelegram()
|
||||
{
|
||||
injectTelegram(true);
|
||||
}
|
||||
|
||||
void TelegramEdit::injectTetraTelegram()
|
||||
{
|
||||
injectTelegram(false);
|
||||
}
|
||||
|
||||
void TelegramEdit::injectTelegram(bool a_bAsCentralTelegram)
|
||||
{
|
||||
injectTelegram(currentSelectedTelegram(), a_bAsCentralTelegram);
|
||||
}
|
||||
|
||||
void TelegramEdit::injectTelegram(const QSharedPointer<LogViewTelegram> &a_telegram, bool a_bAsCentralTelegram)
|
||||
{
|
||||
if (!isInjectionPossible())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Try to inject a telegramm but the injection thread is not running";
|
||||
return;
|
||||
}
|
||||
if (a_telegram.isNull())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Try to inject a telegramm but no telegramm selected";
|
||||
return;
|
||||
}
|
||||
a_telegram->actualizeGpsTime();
|
||||
m_InjectionThread->sendTelegram(a_telegram.data(), a_bAsCentralTelegram);
|
||||
}
|
||||
|
||||
void TelegramEdit::sendCurrentTelegram()
|
||||
{
|
||||
sendTelegram(currentSelectedTelegram());
|
||||
}
|
||||
|
||||
void TelegramEdit::sendTelegram(const QSharedPointer<LogViewTelegram> &a_telegram)
|
||||
{
|
||||
injectTelegram(a_telegram, true);
|
||||
}
|
||||
|
||||
void TelegramEdit::loopTelegrams()
|
||||
{
|
||||
|
||||
if (m_DoLoop)
|
||||
{
|
||||
m_DoLoop = false;
|
||||
m_deleteTeleAction->setEnabled(m_tableView->currentIndex().isValid());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DoLoop = true;
|
||||
m_deleteTeleAction->setEnabled(false);
|
||||
m_currentRowToSend = currentSelectedIndex().row();
|
||||
if (m_currentRowToSend < 0)
|
||||
return;
|
||||
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
|
||||
sendTelegram(tele);
|
||||
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::loopNextTelegram);
|
||||
}
|
||||
}
|
||||
|
||||
void TelegramEdit::loopNextTelegram()
|
||||
{
|
||||
if (!m_DoLoop)
|
||||
return;
|
||||
++m_currentRowToSend;
|
||||
|
||||
if (m_currentRowToSend >= m_tableView->model()->rowCount())
|
||||
m_currentRowToSend = 0;
|
||||
|
||||
QSharedPointer<LogViewTelegram> tele = telegramAtRow(m_currentRowToSend);
|
||||
if (!tele)
|
||||
return;
|
||||
|
||||
sendTelegram(tele);
|
||||
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::loopNextTelegram);
|
||||
}
|
||||
|
||||
void TelegramEdit::sequenceTelegrams()
|
||||
{
|
||||
m_currentRowToSend = currentSelectedIndex().row();
|
||||
if (m_currentRowToSend < 0)
|
||||
return;
|
||||
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
|
||||
sendTelegram(tele);
|
||||
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::sequenceNextTelegram);
|
||||
}
|
||||
|
||||
void TelegramEdit::sequenceNextTelegram()
|
||||
{
|
||||
++m_currentRowToSend;
|
||||
if (m_currentRowToSend >= m_tableView->model()->rowCount())
|
||||
return;
|
||||
|
||||
QSharedPointer<LogViewTelegram> tele = telegramAtRow(m_currentRowToSend);
|
||||
if (!tele)
|
||||
return;
|
||||
|
||||
sendTelegram(tele);
|
||||
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::sequenceNextTelegram);
|
||||
}
|
||||
|
||||
QSharedPointer<LogViewTelegram> TelegramEdit::telegramAtRow(int row)
|
||||
{
|
||||
return m_EditModel->telegram(row);
|
||||
}
|
||||
|
||||
void TelegramEdit::copy()
|
||||
{
|
||||
m_copyTelegram = currentSelectedTelegram();
|
||||
m_pasteTeleAction->setEnabled(m_copyTelegram != nullptr);
|
||||
if (!m_copyTelegram)
|
||||
return;
|
||||
m_copyTelegram = QSharedPointer<LogViewTelegram>(new LogViewTelegram(*m_copyTelegram.data()));
|
||||
}
|
||||
|
||||
void TelegramEdit::paste()
|
||||
{
|
||||
if (!m_copyTelegram)
|
||||
return;
|
||||
int row = currentSelectedIndex().row() + 1;
|
||||
m_EditModel->pasteRows(row, m_copyTelegram);
|
||||
}
|
||||
|
||||
void TelegramEdit::moveUp()
|
||||
{
|
||||
const QModelIndex idx = currentSelectedIndex();
|
||||
if (m_EditModel->moveUp(idx.row()))
|
||||
{
|
||||
m_tableView->clearSelection();
|
||||
m_tableView->setCurrentIndex(m_EditModel->index(idx.row() - 1, idx.column(), idx.parent()));
|
||||
m_moveTeleUpAction->setEnabled(idx.row() > 1);
|
||||
m_moveTeleDownAction->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TelegramEdit::moveDown()
|
||||
{
|
||||
const QModelIndex idx = currentSelectedIndex();
|
||||
if (m_EditModel->moveDown(idx.row()))
|
||||
{
|
||||
m_tableView->clearSelection();
|
||||
m_tableView->setCurrentIndex(m_EditModel->index(idx.row() + 1, idx.column(), idx.parent()));
|
||||
m_moveTeleUpAction->setEnabled(true);
|
||||
m_moveTeleDownAction->setEnabled(idx.row() < m_EditModel->rowCount() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
void TelegramEdit::saveTelegramList()
|
||||
{
|
||||
|
||||
QSettings settings;
|
||||
QString newFilename = QFileDialog::getSaveFileName(m_tableView,
|
||||
tr("Dateiname der Telegrammliste"),
|
||||
settings.value(s_DIR()).toString(),
|
||||
s_TELEGRAMLIST_FILES());
|
||||
if (!newFilename.isEmpty())
|
||||
{
|
||||
if (!newFilename.contains(QLatin1Char('.')))
|
||||
newFilename += QLatin1String(".tgl");
|
||||
|
||||
|
||||
QDir dir;
|
||||
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
|
||||
settings.setValue(s_DIR(), dir.filePath(newFilename));
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
QFile telegramFile(newFilename);
|
||||
telegramFile.open(QIODevice::WriteOnly);
|
||||
QDataStream stream(&telegramFile);
|
||||
|
||||
|
||||
uint32_t version = 1;
|
||||
stream << s_TELEGRAMLIST_FILE_ID() << version;
|
||||
|
||||
|
||||
int rows = m_tableView->model()->rowCount();
|
||||
stream << rows;
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
QSharedPointer<LogViewTelegram> telegram = telegramAtRow(i);
|
||||
if (!telegram)
|
||||
continue;
|
||||
|
||||
const QByteArray &data = telegram->getData();
|
||||
const QString name = telegram->getName();
|
||||
const unsigned int waitTime = telegram->getWaitTime();
|
||||
|
||||
stream << waitTime
|
||||
<< name
|
||||
<< telegram->getGpsTimeField()
|
||||
<< data.size();
|
||||
stream.writeRawData(data.data(), data.size());
|
||||
}
|
||||
telegramFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void TelegramEdit::loadTelegramListAppend()
|
||||
{
|
||||
loadTelegramList(true);
|
||||
}
|
||||
|
||||
void TelegramEdit::loadTelegramListReplace()
|
||||
{
|
||||
loadTelegramList(false);
|
||||
}
|
||||
|
||||
void TelegramEdit::loadTelegramList(bool checkAppend)
|
||||
{
|
||||
|
||||
QSettings settings;
|
||||
QString newFilename = QFileDialog::getOpenFileName(m_tableView,
|
||||
tr("Dateiname der Telegrammliste"),
|
||||
settings.value(s_DIR()).toString(),
|
||||
s_TELEGRAMLIST_FILES());
|
||||
if (!newFilename.isEmpty())
|
||||
{
|
||||
|
||||
QDir dir;
|
||||
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
|
||||
settings.setValue(s_DIR(), dir.filePath(newFilename));
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
{
|
||||
if (!checkAppend)
|
||||
m_EditModel->clearTelegrams();
|
||||
}
|
||||
|
||||
|
||||
QFile telegramFile(newFilename);
|
||||
telegramFile.open(QIODevice::ReadOnly);
|
||||
QDataStream stream(&telegramFile);
|
||||
|
||||
|
||||
QString id;
|
||||
stream >> id;
|
||||
if (id != s_TELEGRAMLIST_FILE_ID())
|
||||
{
|
||||
QMessageBox::critical(m_tableView, tr("Error"), tr("<b>%1</b> does not contain telegram data").arg(newFilename));
|
||||
return;
|
||||
}
|
||||
uint32_t version = 0;
|
||||
stream >> version;
|
||||
if (version != 1)
|
||||
{
|
||||
QMessageBox::critical(m_tableView, tr("Error"), tr("Wrong telegram list file version"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int rows = 0;
|
||||
QVector<uint16_t> gpsFieldOffset;
|
||||
stream >> rows;
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
uint32_t waitTime = 0;
|
||||
QString name;
|
||||
int telegramSize = 0;
|
||||
stream >> waitTime >> name >> gpsFieldOffset >> telegramSize;
|
||||
if (telegramSize > 0)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "telegramSize=" << telegramSize;
|
||||
QByteArray buf(telegramSize, Qt::Uninitialized);
|
||||
stream.readRawData(buf.data(), telegramSize);
|
||||
NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Debug, buf);
|
||||
LogViewTelegram *telegram = new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral,
|
||||
0,
|
||||
buf);
|
||||
telegram->setWaitTime(waitTime);
|
||||
telegram->setName(name);
|
||||
telegram->setGpsTimeField(gpsFieldOffset);
|
||||
m_EditModel->appendTelegram(QSharedPointer<LogViewTelegram>(telegram));
|
||||
}
|
||||
}
|
||||
telegramFile.close();
|
||||
|
||||
m_teleListSave->setEnabled(m_EditModel->rowCount() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TelegramEdit::isInjectionPossible() const
|
||||
{
|
||||
return m_InjectionThread ? m_InjectionThread->isSendingPossible() : false;
|
||||
}
|
||||
|
||||
|
||||
void TelegramEdit::onSelectionChanged()
|
||||
{
|
||||
const QModelIndex idx = currentSelectedIndex();
|
||||
|
||||
m_editTeleAction->setEnabled(idx.isValid());
|
||||
m_copyTeleAction->setEnabled(idx.isValid());
|
||||
m_deleteTeleAction->setEnabled(idx.isValid());
|
||||
m_moveTeleUpAction->setEnabled(idx.row() > 0);
|
||||
m_moveTeleDownAction->setEnabled(idx.isValid() && idx.row() < m_EditModel->rowCount() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include <QModelIndex>
|
||||
|
||||
class QAction;
|
||||
class QTableView;
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewInjectionThread;
|
||||
class TelegramEditModel;
|
||||
|
||||
class TelegramEdit :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TelegramEdit(QWidget *parent = nullptr);
|
||||
|
||||
QTableView *tableView() { return m_tableView; }
|
||||
|
||||
void appendTelegram(const QSharedPointer<LogViewTelegram> &telegram);
|
||||
|
||||
void setInjectionThread(LogViewInjectionThread* a_injectionThread);
|
||||
|
||||
bool isInjectionPossible() const;
|
||||
|
||||
protected:
|
||||
QSharedPointer<LogViewTelegram> m_copyTelegram;
|
||||
|
||||
QSharedPointer<LogViewTelegram> currentSelectedTelegram() const;
|
||||
|
||||
QModelIndex currentSelectedIndex() const;
|
||||
|
||||
QSharedPointer<LogViewTelegram> telegramAtRow(int row);
|
||||
|
||||
void loadTelegramList(bool checkAppend);
|
||||
|
||||
protected:
|
||||
QAction *m_addTeleAction;
|
||||
QAction *m_editTeleAction;
|
||||
QAction *m_copyTeleAction;
|
||||
QAction *m_pasteTeleAction;
|
||||
QAction *m_deleteTeleAction;
|
||||
QAction *m_moveTeleUpAction;
|
||||
QAction *m_moveTeleDownAction;
|
||||
QAction *m_teleListLoad;
|
||||
QAction *m_teleListAppend;
|
||||
QAction *m_teleListSave;
|
||||
QTableView *m_tableView;
|
||||
bool m_DoLoop;
|
||||
|
||||
LogViewInjectionThread *m_InjectionThread;
|
||||
|
||||
int m_currentRowToSend;
|
||||
|
||||
int m_curEditTelegramRow;
|
||||
|
||||
TelegramEditModel *m_EditModel;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
static QString s_DIR();
|
||||
static QString s_EDIT_TELEGRAM_GROUP();
|
||||
static QString s_TELEGRAMLIST_FILE_ID();
|
||||
static QString s_TELEGRAMLIST_FILES();
|
||||
|
||||
protected Q_SLOTS:
|
||||
|
||||
void addTelegram();
|
||||
|
||||
void injectTelegram(bool a_bAsCentralTelegram);
|
||||
|
||||
void injectTelegram(const QSharedPointer<LogViewTelegram> &a_telegram, bool a_bAsCentralTelegram);
|
||||
|
||||
void sendTelegram(const QSharedPointer<LogViewTelegram> &a_telegram);
|
||||
|
||||
void sendCurrentTelegram();
|
||||
|
||||
void tableViewCustomContextMenu(const QPoint &pos);
|
||||
|
||||
void editTelegram();
|
||||
|
||||
void showTelegram();
|
||||
|
||||
void deleteTelegram();
|
||||
|
||||
void injectCentralTelegram();
|
||||
|
||||
void injectTetraTelegram();
|
||||
|
||||
void loopTelegrams();
|
||||
|
||||
void loopNextTelegram();
|
||||
|
||||
void sequenceTelegrams();
|
||||
|
||||
void sequenceNextTelegram();
|
||||
|
||||
void copy();
|
||||
|
||||
void paste();
|
||||
|
||||
void moveUp();
|
||||
|
||||
void moveDown();
|
||||
|
||||
void saveTelegramList();
|
||||
|
||||
void loadTelegramListAppend();
|
||||
|
||||
void loadTelegramListReplace();
|
||||
|
||||
void editTelegramDialogFinished();
|
||||
|
||||
void onSelectionChanged();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
|
||||
|
||||
|
||||
#include "LogViewTelegramEditModel.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
int TelegramEditModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_telegrams.size();
|
||||
}
|
||||
|
||||
|
||||
int TelegramEditModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 3;
|
||||
}
|
||||
|
||||
|
||||
QVariant TelegramEditModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.isValid() && index.row() < m_telegrams.size())
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case 0:
|
||||
return telegram->getName();
|
||||
case 1:
|
||||
return telegram->getParticipantId();
|
||||
case 2:
|
||||
return telegram->getWaitTime();
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
const QSharedPointer<LogViewTelegram> telegram = m_telegrams.at(index.row());
|
||||
if (telegram->isJsonTelegram())
|
||||
return telegram->getData(QJsonDocument::JsonFormat::Indented);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
QVariant TelegramEditModel::headerData(int section,
|
||||
Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0:
|
||||
return tr("Description");
|
||||
case 1:
|
||||
return tr("Equip. No.");
|
||||
case 2:
|
||||
return tr("Wait Time");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
|
||||
void TelegramEditModel::clearTelegrams()
|
||||
{
|
||||
beginResetModel();
|
||||
m_telegrams.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
void TelegramEditModel::appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams)
|
||||
{
|
||||
if (telegrams.isEmpty())
|
||||
return;
|
||||
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size() + telegrams.size() - 1);
|
||||
m_telegrams += telegrams;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
int TelegramEditModel::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_telegrams.size(), m_telegrams.size());
|
||||
m_telegrams.push_back(telegram);
|
||||
telegram->rebuildJsonString();
|
||||
endInsertRows();
|
||||
return m_telegrams.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
QSharedPointer<LogViewTelegram> TelegramEditModel::telegram(int row) const
|
||||
{
|
||||
if (row >= 0 && row < m_telegrams.size())
|
||||
return m_telegrams.at(row);
|
||||
return QSharedPointer<LogViewTelegram>();
|
||||
}
|
||||
|
||||
|
||||
bool TelegramEditModel::moveUp(int row)
|
||||
{
|
||||
if (row <= 0 || row >= m_telegrams.size())
|
||||
return false;
|
||||
beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1);
|
||||
std::swap(m_telegrams[row], m_telegrams[row - 1]);
|
||||
endMoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TelegramEditModel::moveDown(int row)
|
||||
{
|
||||
if (row >= (m_telegrams.size() - 1))
|
||||
return false;
|
||||
beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 1);
|
||||
std::swap(m_telegrams[row], m_telegrams[row + 1]);
|
||||
endMoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TelegramEditModel::emitDataChanged(int row)
|
||||
{
|
||||
QModelIndex top = createIndex(row, 0);
|
||||
QModelIndex bottom = createIndex(row, columnCount() - 1);
|
||||
emit dataChanged(top, bottom, {Qt::DisplayRole, Qt::ToolTipRole});
|
||||
}
|
||||
|
||||
|
||||
void TelegramEditModel::removeTelegrams(const QSet<int> &rows)
|
||||
{
|
||||
QList<int> rowList = rows.values();
|
||||
std::sort(rowList.begin(), rowList.end());
|
||||
|
||||
for (int i = rowList.size() - 1 ; i >= 0; --i)
|
||||
{
|
||||
int row = rowList.at(i);
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_telegrams.remove(row);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TelegramEditModel::pasteRows(int row, const QSharedPointer<LogViewTelegram> &tele)
|
||||
{
|
||||
if (row < 0 || row > m_telegrams.size())
|
||||
return;
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
m_telegrams.insert(row, QSharedPointer<LogViewTelegram>(new LogViewTelegram(*tele.data())));
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QSet>
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class TelegramEditModel final : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
void clearTelegrams();
|
||||
void appendTelegrams(const QVector<QSharedPointer<LogViewTelegram> > &telegrams);
|
||||
int appendTelegram(const QSharedPointer<LogViewTelegram> &telegram);
|
||||
QSharedPointer<LogViewTelegram> telegram(int row) const;
|
||||
|
||||
bool moveUp(int row);
|
||||
bool moveDown(int row);
|
||||
|
||||
void emitDataChanged(int row);
|
||||
|
||||
void removeTelegrams(const QSet<int> &rows);
|
||||
|
||||
void pasteRows(int row, const QSharedPointer<LogViewTelegram> &tele);
|
||||
protected:
|
||||
QVector<QSharedPointer<LogViewTelegram> > m_telegrams;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewTelegramSelectionDialog.hpp"
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include "LogViewXdrType.hpp"
|
||||
#include "LogViewXdrParser.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include "LogViewTetraTelegramsParser.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
static int s_currentRow = 0;
|
||||
|
||||
LogViewTelegramSelectionDialog::LogViewTelegramSelectionDialog(QWidget* a_parent)
|
||||
: QDialog(a_parent)
|
||||
{
|
||||
setMinimumSize(QSize(600, 500));
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
layout->addWidget(new QLabel(tr("Select a telegram:")));
|
||||
m_TelegramList = new QListWidget(this);
|
||||
const auto telegramMap = LogViewTelegram::jsonParser()->telegramsToCreate();
|
||||
for (auto it = telegramMap.cbegin(); it != telegramMap.cend(); ++it)
|
||||
{
|
||||
if (it.key() == 0)
|
||||
continue;
|
||||
auto lwi = new QListWidgetItem(it.value() + QStringLiteral(" (%1)").arg(it.key()));
|
||||
lwi->setData(Qt::UserRole, it.key());
|
||||
m_TelegramList->addItem(lwi);
|
||||
}
|
||||
|
||||
m_TelegramList->sortItems();
|
||||
m_TelegramList->setCurrentRow(s_currentRow);
|
||||
connect(m_TelegramList, &QListWidget::itemActivated,
|
||||
this, &LogViewTelegramSelectionDialog::selectTelegram);
|
||||
layout->addWidget(m_TelegramList);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTelegramSelectionDialog::selectTelegram(QListWidgetItem* a_telegramItem)
|
||||
{
|
||||
s_currentRow = m_TelegramList->currentRow();
|
||||
m_SelectedTelegramId = a_telegramItem->data(Qt::UserRole).toInt();
|
||||
accept();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewTelegramSelectionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
explicit LogViewTelegramSelectionDialog(QWidget* a_parent);
|
||||
|
||||
|
||||
int getSelectedTelegramId() const { return m_SelectedTelegramId; }
|
||||
|
||||
protected slots:
|
||||
|
||||
|
||||
void selectTelegram(QListWidgetItem* a_telegramItem);
|
||||
|
||||
protected:
|
||||
|
||||
QListWidget *m_TelegramList;
|
||||
int m_SelectedTelegramId;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
|
||||
|
||||
|
||||
#include "LogViewTetraTelegramsParser.hpp"
|
||||
|
||||
#include <QFile>
|
||||
#include <QVector>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
LogViewTetraTelegramsParser::LogViewTetraTelegramsParser()
|
||||
: m_logger(getLogger("LogViewTetraTelegramsParser"))
|
||||
{
|
||||
insertPod(QStringLiteral("bool"), 1, true, true, true);
|
||||
insertPod(QStringLiteral("int"), 4, true, true);
|
||||
insertPod(QStringLiteral("int32_t"), 4, true, true);
|
||||
insertPod(QStringLiteral("qint64"), 8, true, true);
|
||||
insertPod(QStringLiteral("float"), 4, true, false);
|
||||
insertPod(QStringLiteral("double"), 8, true, false);
|
||||
}
|
||||
|
||||
EnumInformation LogViewTetraTelegramsParser::enumFromType(const QString &type) const
|
||||
{
|
||||
for (const auto &ei : m_enums)
|
||||
{
|
||||
const QString fqType = ei.ns.isEmpty() ? ei.type : (ei.ns + QStringLiteral("::") + ei.type);
|
||||
if (fqType == type)
|
||||
return ei;
|
||||
}
|
||||
return EnumInformation();
|
||||
}
|
||||
|
||||
StructInformation LogViewTetraTelegramsParser::structFromType(const QString &type) const
|
||||
{
|
||||
return m_structs.value(type);
|
||||
}
|
||||
|
||||
PodInformation LogViewTetraTelegramsParser::podFromType(const QString &type) const
|
||||
{
|
||||
return m_pods.value(type);
|
||||
}
|
||||
|
||||
bool LogViewTetraTelegramsParser::isEnum(const QString &type) const
|
||||
{
|
||||
for (const auto &ei : m_enums)
|
||||
if (ei.type == type)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LogViewTetraTelegramsParser::isStruct(const QString &type) const
|
||||
{
|
||||
return m_structs.contains(type);
|
||||
}
|
||||
|
||||
bool LogViewTetraTelegramsParser::isPod(const QString &type) const
|
||||
{
|
||||
return m_pods.contains(type);
|
||||
}
|
||||
|
||||
static void fillBasemembers(StructInformation &si, const QHash<QString, StructInformation> &structs)
|
||||
{
|
||||
if (si.baseStruct.isEmpty())
|
||||
return;
|
||||
StructInformation base = structs.value(si.baseStruct);
|
||||
fillBasemembers(base, structs);
|
||||
si.member = (base.member + si.member);
|
||||
}
|
||||
|
||||
bool LogViewTetraTelegramsParser::parse(const QString &filename)
|
||||
{
|
||||
m_telegramIdEnum = EnumInformation();
|
||||
m_enums.clear();
|
||||
m_structs.clear();
|
||||
|
||||
m_visibleTelegrams.clear();
|
||||
|
||||
QFile f(filename);
|
||||
if (!f.open(QIODevice::ReadOnly))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Can not open file " << filename << " for reading: " << f.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString content = QString::fromUtf8(f.readAll());
|
||||
f.close();
|
||||
|
||||
const QVector<QStringRef> lines = content.splitRef(QLatin1Char('\n'));
|
||||
QVector<QStringRef> linesTrimmed;
|
||||
linesTrimmed.reserve(lines.size());
|
||||
for (const QStringRef &line : lines)
|
||||
linesTrimmed += line.trimmed();
|
||||
|
||||
int i = 0;
|
||||
while (i < linesTrimmed.size())
|
||||
{
|
||||
const QStringRef &line = linesTrimmed.at(i);
|
||||
if (line.startsWith(QLatin1String("struct")))
|
||||
{
|
||||
i = parseStruct(linesTrimmed, i);
|
||||
if (i < 0)
|
||||
return false;
|
||||
}
|
||||
else if (line.startsWith(QLatin1String("enum")))
|
||||
{
|
||||
i = parseEnum(linesTrimmed, i, QString());
|
||||
if (i < 0)
|
||||
return false;
|
||||
}
|
||||
else if (line.startsWith(QLatin1String("template <> struct Constraints")))
|
||||
{
|
||||
i = parseConstraint(linesTrimmed, i);
|
||||
if (i < 0)
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
const auto completeStructs = m_structs;
|
||||
for (StructInformation &si : m_structs)
|
||||
fillBasemembers(si, completeStructs);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogViewTetraTelegramsParser::insertPod(const QString &type, int byteLen, bool isSigned, bool isIntegral, bool isBoolean)
|
||||
{
|
||||
PodInformation pod;
|
||||
pod.type = type;
|
||||
pod.byteLen = byteLen;
|
||||
pod.isBoolean = isBoolean;
|
||||
pod.isIntegral = isIntegral;
|
||||
pod.isSigned = isSigned;
|
||||
m_pods[type] = pod;
|
||||
}
|
||||
|
||||
|
||||
int LogViewTetraTelegramsParser::parseStruct(const QVector<QStringRef> &lines, int iStartPos)
|
||||
{
|
||||
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos));
|
||||
if (tokens.size() < 2)
|
||||
return -1;
|
||||
const QStringRef &structType = tokens.at(1);
|
||||
if (structType.endsWith(QLatin1Char(';')))
|
||||
return iStartPos;
|
||||
|
||||
StructInformation si;
|
||||
si.type = structType.toString();
|
||||
if (tokens.size() > 2)
|
||||
{
|
||||
if (tokens.at(2) != QLatin1String(":"))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 3; i < tokens.size(); ++i)
|
||||
{
|
||||
if (!si.baseStruct.isEmpty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse struct: '" << lines.at(iStartPos).toString() << "', line: " << iStartPos + 1;
|
||||
return -1;
|
||||
}
|
||||
QStringRef base = tokens.at(i);
|
||||
if (base == QLatin1String("public") ||
|
||||
base == QLatin1String("protected") ||
|
||||
base == QLatin1String("private"))
|
||||
continue;
|
||||
if (base.endsWith(QLatin1Char(',')))
|
||||
base.chop(1);
|
||||
if (base.endsWith(QLatin1Char('>')))
|
||||
{
|
||||
si.isVisible = true;
|
||||
continue;
|
||||
}
|
||||
si.baseStruct = tokens.at(i).toString();
|
||||
}
|
||||
}
|
||||
|
||||
int i = iStartPos + 1;
|
||||
while (i < lines.size())
|
||||
{
|
||||
const QVector<QStringRef> tokens = tokenize(lines.at(i));
|
||||
if (!validStructTokens(tokens))
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (tokens.at(0) == QLatin1String("};"))
|
||||
break;
|
||||
if (tokens.at(0) == QLatin1String("enum"))
|
||||
{
|
||||
i = parseEnum(lines, i, si.type, &si);
|
||||
if (i < 0)
|
||||
return -1;
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
MemberInformation mi;
|
||||
if (tokens.size() > 2)
|
||||
{
|
||||
const int parserCommentPos = tokens.at(2) == QLatin1String("=") ? 4 : 2;
|
||||
if (tokens.size() > parserCommentPos)
|
||||
{
|
||||
const QStringRef &comment = tokens.at(parserCommentPos);
|
||||
DEBUG_LOG(m_logger) << "comment: " << comment.toString();
|
||||
if (comment.startsWith(QLatin1String("//@array: ")))
|
||||
{
|
||||
const QStringRef hint = comment.mid(QLatin1String("//@array: ").size());
|
||||
QString structStr = QLatin1String("struct ") + si.type + QLatin1String("::") + tokens.at(0).toString() + QLatin1Char('\n') + hint.toString();
|
||||
structStr.replace(QLatin1Char(';'), QLatin1String(";\n"));
|
||||
DEBUG_LOG(m_logger) << "structStr: " << structStr;
|
||||
parseStruct(structStr.splitRef(QLatin1Char('\n')), 0);
|
||||
|
||||
mi.type = si.type + QLatin1String("::") + tokens.at(0).toString();
|
||||
mi.isArray = true;
|
||||
}
|
||||
if (comment == QLatin1String("//@invisible"))
|
||||
mi.isVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
QStringRef name = tokens.at(1);
|
||||
if (name.endsWith(QLatin1Char(';')))
|
||||
name.chop(1);
|
||||
if (mi.type.isEmpty())
|
||||
mi.type += tokens.at(0).toString();
|
||||
categorizeMember(mi);
|
||||
mi.name = name.toString();
|
||||
if (mi.isEnum && !mi.type.contains(QLatin1String("::")))
|
||||
{
|
||||
|
||||
for (const auto &ei : qAsConst(m_enums))
|
||||
{
|
||||
if (ei.type == mi.type)
|
||||
{
|
||||
if (!ei.ns.isEmpty())
|
||||
mi.type = ei.ns + QLatin1String("::") + mi.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
si.member.push_back(std::move(mi));
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
if (si.baseStruct.isEmpty())
|
||||
DEBUG_LOG(m_logger) << "Found Struct: " << si.type;
|
||||
else
|
||||
DEBUG_LOG(m_logger) << "Found Struct: " << si.type << ", base: " << si.baseStruct;
|
||||
for (int j = 0; j < si.member.size(); ++j)
|
||||
{
|
||||
const MemberInformation &mi = si.member.at(j);
|
||||
DEBUG_LOG(m_logger) << "Member[" << j << "]: " << mi.type << " - " << mi.name;
|
||||
}
|
||||
}
|
||||
|
||||
m_structs[si.type] = si;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int LogViewTetraTelegramsParser::parseEnum(const QVector<QStringRef> &lines, int iStartPos, const QString &ns, StructInformation *si)
|
||||
{
|
||||
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos));
|
||||
if (tokens.size() < 2)
|
||||
return -1;
|
||||
QStringRef enumName = tokens.at(1);
|
||||
if (enumName == QLatin1String("class"))
|
||||
{
|
||||
if (tokens.size() < 3)
|
||||
return -1;
|
||||
enumName = tokens.at(2);
|
||||
}
|
||||
if (enumName.endsWith(QLatin1Char(';')))
|
||||
return iStartPos;
|
||||
|
||||
EnumInformation ei;
|
||||
ei.type = enumName.toString();
|
||||
ei.ns = ns;
|
||||
|
||||
int i = iStartPos + 1;
|
||||
while (i < lines.size())
|
||||
{
|
||||
const QVector<QStringRef> tokens = tokenize(lines.at(i).split(QStringLiteral("//")).first());
|
||||
if (tokens.isEmpty() ||
|
||||
(tokens.at(0) == QLatin1String("{")))
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (tokens.at(0) == QLatin1String("};"))
|
||||
break;
|
||||
if ((tokens.size() != 1 && tokens.size() != 3) ||
|
||||
(tokens.size() == 3 && tokens.at(1) != QLatin1String("=")))
|
||||
{
|
||||
if (tokens.size() == 4 && tokens.at(0) == QLatin1String("}") && tokens.at(3).endsWith(QLatin1Char(';')) && si)
|
||||
{
|
||||
|
||||
MemberInformation mi;
|
||||
if (ns.isEmpty())
|
||||
mi.type = ei.type;
|
||||
else
|
||||
mi.type = ns + QStringLiteral("::") + ei.type;
|
||||
mi.isEnum = true;
|
||||
mi.name = tokens.at(1).toString();
|
||||
si->member.push_back(std::move(mi));
|
||||
break;
|
||||
}
|
||||
WARNING_LOG(m_logger) << "Could not parse enum: '" << lines.at(i).toString() << "', line: " << i + 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
EnumValue ev;
|
||||
ev.key = tokens.at(0).toString();
|
||||
if (tokens.size() == 3)
|
||||
{
|
||||
QStringRef value = tokens.at(2);
|
||||
if (value.endsWith(QLatin1Char(',')))
|
||||
value.chop(1);
|
||||
ev.value = value.toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
int val = ei.values.isEmpty() ? 0 : (ei.values.last().value + 1);
|
||||
ev.value = val;
|
||||
}
|
||||
ei.values.push_back(std::move(ev));
|
||||
++i;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Found Enum: " << ei.type;
|
||||
for (const EnumValue &ev : qAsConst(ei.values))
|
||||
DEBUG_LOG(m_logger) << "Member[" << i << "]: " << ev.key << " = " << ev.value;
|
||||
|
||||
if (ei.type == QLatin1String("TelegramId"))
|
||||
m_telegramIdEnum = ei;
|
||||
|
||||
m_enums.push_back(std::move(ei));
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int LogViewTetraTelegramsParser::parseConstraint(const QVector<QStringRef> &lines, int iStartPos)
|
||||
{
|
||||
const QVector<QStringRef> tokens = tokenize(lines.at(iStartPos));
|
||||
if (tokens.size() != 4)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'";
|
||||
return -1;
|
||||
}
|
||||
const QStringRef &cs = tokens.at(3);
|
||||
if (!cs.startsWith(QLatin1String("Constraints<")) || !cs.endsWith(QLatin1Char('>')))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(iStartPos).toString() << "'";
|
||||
return -1;
|
||||
}
|
||||
QStringRef structName = cs.mid(QLatin1String("Constraints<").size());
|
||||
structName.chop(1);
|
||||
DEBUG_LOG(m_logger) << "Constraint: " << structName.toString();
|
||||
|
||||
int i = iStartPos + 1;
|
||||
while (i < lines.size())
|
||||
{
|
||||
const QVector<QStringRef> tokens = tokenize(lines.at(i));
|
||||
if (tokens.isEmpty() ||
|
||||
(tokens.at(0) == QLatin1String("{")))
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (tokens.at(0) == QLatin1String("};"))
|
||||
break;
|
||||
if (tokens.size() != 8 || tokens.at(2) != QLatin1String("TelegramId"))
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
const QVector<QStringRef> parts = tokens.at(6).split(QLatin1String("::"));
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not parse constraint: '" << lines.at(i).toString() << "'";
|
||||
return -1;
|
||||
}
|
||||
|
||||
QStringRef enumKey = parts.at(1);
|
||||
if (enumKey.endsWith(QLatin1Char(';')))
|
||||
enumKey.chop(1);
|
||||
bool bFound = false;
|
||||
for (const auto &v : qAsConst(m_telegramIdEnum.values))
|
||||
{
|
||||
if (v.key == enumKey)
|
||||
{
|
||||
m_visibleTelegrams.insert(v.value, structName.toString());
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find enum value '" << enumKey.toString() << "' in enum TelegramId";
|
||||
return -1;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
QString LogViewTetraTelegramsParser::getInnerType(const QString &type)
|
||||
{
|
||||
int idxLt = type.lastIndexOf(QLatin1Char('>'));
|
||||
if (idxLt < 0)
|
||||
return QString();
|
||||
int idxGt = type.indexOf(QLatin1Char('<'));
|
||||
if (idxGt < 0)
|
||||
return QString();
|
||||
return type.mid(idxGt + 1, idxLt - idxGt - 1);
|
||||
}
|
||||
|
||||
void LogViewTetraTelegramsParser::categorizeMember(MemberInformation &mi) const
|
||||
{
|
||||
mi.isPod = isPod(mi.type);
|
||||
mi.isEnum = mi.isPod ? false : isEnum(mi.type);
|
||||
if (mi.type.startsWith(QLatin1String("std::vector<")))
|
||||
mi.isArray = true;
|
||||
mi.isStruct = mi.isArray ? false : isStruct(mi.type);
|
||||
mi.isString = (mi.type == QLatin1String("std::string") || mi.type == QLatin1String("QString"));
|
||||
mi.isBinary = (mi.type == QLatin1String("std::vector<unsigned char>") || mi.type == QLatin1String("QByteArray"));
|
||||
}
|
||||
|
||||
static inline void bracketCount(const QStringRef &str, int &cntLt, int &cntGt)
|
||||
{
|
||||
cntLt = 0;
|
||||
cntGt = 0;
|
||||
for (int i = 0; i < str.size(); ++i)
|
||||
{
|
||||
if (str.at(i) == QLatin1Char('<'))
|
||||
cntLt++;
|
||||
else if (str.at(i) == QLatin1Char('>'))
|
||||
cntGt++;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QStringRef> LogViewTetraTelegramsParser::tokenize(const QStringRef &line) const
|
||||
{
|
||||
QVector<QStringRef> ret = line.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
int i = 0;
|
||||
while (i < ret.size())
|
||||
{
|
||||
const QStringRef &token = ret.at(i);
|
||||
if (token.startsWith(QLatin1String("//")))
|
||||
{
|
||||
|
||||
if (i == ret.size() - 1)
|
||||
break;
|
||||
const QStringRef &lastToken = ret.last();
|
||||
const QStringRef newToken = QStringRef(token.string(), token.position(), lastToken.position() - token.position() + lastToken.size());
|
||||
DEBUG_LOG(m_logger) << "New Token: " << newToken.toString();
|
||||
ret.resize(i + 1);
|
||||
ret[i] = newToken;
|
||||
break;
|
||||
}
|
||||
if (i == ret.size() - 1)
|
||||
break;
|
||||
int cntLt;
|
||||
int cntGt;
|
||||
bracketCount(token, cntLt, cntGt);
|
||||
if (cntLt == cntGt)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
const QStringRef &nextToken = ret.at(i + 1);
|
||||
const QStringRef newToken = QStringRef(token.string(), token.position(), nextToken.position() - token.position() + nextToken.size());
|
||||
DEBUG_LOG(m_logger) << "New Token: " << newToken.toString();
|
||||
ret.removeAt(i + 1);
|
||||
ret[i] = newToken;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LogViewTetraTelegramsParser::validStructTokens(const QVector<QStringRef> &tokens)
|
||||
{
|
||||
if (tokens.isEmpty() ||
|
||||
(tokens.at(0) == QLatin1String("{")) ||
|
||||
(tokens.at(0) == QLatin1String("{}")) ||
|
||||
(tokens.at(0) == QLatin1String("}")) ||
|
||||
(tokens.at(0) == QLatin1String(":")) ||
|
||||
(tokens.at(0) == QLatin1String(",")) ||
|
||||
(tokens.at(0) == QLatin1String("virtual")))
|
||||
return false;
|
||||
|
||||
if (tokens.at(0) == QLatin1String("};") || tokens.at(0) == QLatin1String("enum"))
|
||||
return true;
|
||||
|
||||
const int len = tokens.last().startsWith(QLatin1String("//")) ? tokens.size() - 1 : tokens.size();
|
||||
|
||||
if (len == 2)
|
||||
return true;
|
||||
|
||||
if (len < 4)
|
||||
return false;
|
||||
|
||||
if (len >= 4 && tokens.at(2) == QLatin1String("="))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include "logger.h"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
struct MemberInformation
|
||||
{
|
||||
QString name;
|
||||
QString type;
|
||||
bool isArray = false;
|
||||
bool isBinary = false;
|
||||
bool isEnum = false;
|
||||
bool isPod = false;
|
||||
bool isString = false;
|
||||
bool isStruct = false;
|
||||
bool isVisible = true;
|
||||
};
|
||||
|
||||
struct StructInformation
|
||||
{
|
||||
QString type;
|
||||
QString baseStruct;
|
||||
|
||||
QVector<MemberInformation> member;
|
||||
bool isVisible = false;
|
||||
};
|
||||
|
||||
struct EnumValue
|
||||
{
|
||||
QString key;
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
struct EnumInformation
|
||||
{
|
||||
QString ns;
|
||||
QString type;
|
||||
QVector<EnumValue> values;
|
||||
};
|
||||
|
||||
struct PodInformation
|
||||
{
|
||||
QString type;
|
||||
int byteLen = 0;
|
||||
bool isBoolean = false;
|
||||
bool isIntegral = false;
|
||||
bool isSigned = false;
|
||||
};
|
||||
|
||||
class LogViewTetraTelegramsParser
|
||||
{
|
||||
public:
|
||||
LogViewTetraTelegramsParser();
|
||||
|
||||
bool parse(const QString &filename);
|
||||
|
||||
EnumInformation enumFromType(const QString &type) const;
|
||||
StructInformation structFromType(const QString &type) const;
|
||||
PodInformation podFromType(const QString &type) const;
|
||||
bool isEnum(const QString &type) const;
|
||||
bool isStruct(const QString &type) const;
|
||||
bool isPod(const QString &type) const;
|
||||
QHash<int, QString> telegramsToCreate() const { return m_visibleTelegrams; }
|
||||
QString nameFromTelegramId(int telId) const { return m_visibleTelegrams.value(telId); }
|
||||
static QString getInnerType(const QString &type);
|
||||
private:
|
||||
void insertPod(const QString &type, int byteLen, bool isSigned, bool isIntegral, bool isBoolean = false);
|
||||
int parseStruct(const QVector<QStringRef> &lines, int iStartPos);
|
||||
int parseEnum(const QVector<QStringRef> &lines, int iStartPos, const QString &ns, StructInformation *si = nullptr);
|
||||
int parseConstraint(const QVector<QStringRef> &lines, int iStartPos);
|
||||
void categorizeMember(MemberInformation &mi) const;
|
||||
QVector<QStringRef> tokenize(const QStringRef &line) const;
|
||||
static bool validStructTokens(const QVector<QStringRef> &tokens);
|
||||
private:
|
||||
EnumInformation m_telegramIdEnum;
|
||||
QVector<EnumInformation> m_enums;
|
||||
QHash<QString, StructInformation> m_structs;
|
||||
QHash<QString, PodInformation> m_pods;
|
||||
QHash<int, QString> m_visibleTelegrams;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewTextEdit.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewTextEdit::LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
|
||||
: QLineEdit(a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, a_readonly)
|
||||
{
|
||||
const QString value = a_field->value(0);
|
||||
setText(value);
|
||||
|
||||
if (a_readonly)
|
||||
{
|
||||
setReadOnly(true);
|
||||
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
|
||||
}
|
||||
|
||||
|
||||
uint16_t maxArraySize = a_field->maxArraySize();
|
||||
setMaxLength(maxArraySize);
|
||||
updateToolTip(value);
|
||||
|
||||
|
||||
QFontMetrics fm(font());
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
setMinimumWidth(fm.width(QLatin1Char(' ') + value + QLatin1Char(' ')));
|
||||
#else
|
||||
setMinimumWidth(fm.horizontalAdvance(QLatin1Char(' ') + value + QLatin1Char(' ')));
|
||||
#endif
|
||||
|
||||
|
||||
connect(this, &LogViewTextEdit::editingFinished,
|
||||
this, &LogViewTextEdit::checkAndOvertakeContent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewTextEdit::checkAndOvertakeContent()
|
||||
{
|
||||
updateToolTip(text());
|
||||
m_Valid = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewTextEdit::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
if (!isValid())
|
||||
return false;
|
||||
if (a_telegram->isJsonTelegram())
|
||||
{
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), text());
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t size = getSize();
|
||||
QString content = text();
|
||||
uint16_t arraySize;
|
||||
if (m_Field->isDynamicArray())
|
||||
{
|
||||
arraySize = content.length();
|
||||
a_telegram->setUIntX(LogViewTelegram::SIZE_CENTRAL_DYN_ARRAY_SIZE, arraySize);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
arraySize = m_Field->maxArraySize();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < arraySize; i++)
|
||||
a_telegram->setUIntX(size, i < content.length() ? content[i].toLatin1() : 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewWidget.hpp"
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewTextEdit : public QLineEdit, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
|
||||
|
||||
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
|
||||
protected slots:
|
||||
void checkAndOvertakeContent();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewValueEdit.hpp"
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewValueEdit::LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly)
|
||||
: QLineEdit(a_parent)
|
||||
, LogViewWidget(a_field, this, a_parent, a_readonly)
|
||||
, m_IsFloat(false)
|
||||
{
|
||||
const LogViewXdrStandardType *stdType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
|
||||
m_IsFloat = (LogViewXdrStandardType::e_Float == stdType->getValueKind());
|
||||
|
||||
const QString valueText = a_field->value(0);
|
||||
|
||||
setText(valueText);
|
||||
|
||||
|
||||
updateToolTip(valueText);
|
||||
|
||||
|
||||
QFontMetrics fm(font());
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
setMinimumWidth(fm.width(QLatin1Char(' ') + valueText + QLatin1Char(' ')));
|
||||
#else
|
||||
setMinimumWidth(fm.horizontalAdvance(QLatin1Char(' ') + valueText + QLatin1Char(' ')));
|
||||
#endif
|
||||
|
||||
if (a_readonly)
|
||||
{
|
||||
setReadOnly(true);
|
||||
setAlignment(a_field->isRightAligned() ? Qt::AlignRight : Qt::AlignLeft);
|
||||
}
|
||||
else
|
||||
{
|
||||
connect(this, &LogViewValueEdit::editingFinished,
|
||||
this, &LogViewValueEdit::checkAndOvertakeContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewValueEdit::checkAndOvertakeContent()
|
||||
{
|
||||
bool ok;
|
||||
int64_t intValue = 0;
|
||||
double floatValue = 0.0;
|
||||
|
||||
|
||||
if (m_IsFloat)
|
||||
floatValue = getFloat(text(), (uint64_t&)intValue, ok);
|
||||
else
|
||||
intValue = getInteger(text(), ok);
|
||||
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
setFocus();
|
||||
selectAll();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m_IsFloat)
|
||||
setText(QString::number(floatValue));
|
||||
else
|
||||
setText(QString::number(intValue));
|
||||
|
||||
updateToolTip(text());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
|
||||
{
|
||||
if (m_Valid)
|
||||
{
|
||||
bool ok;
|
||||
if (m_IsFloat)
|
||||
{
|
||||
|
||||
uint64_t valueAsUint64;
|
||||
const double value = getFloat(text(), valueAsUint64, ok);
|
||||
if (ok)
|
||||
{
|
||||
if (a_telegram->isJsonTelegram())
|
||||
{
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), value);
|
||||
}
|
||||
else
|
||||
{
|
||||
const LogViewXdrStandardType *stdType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
|
||||
LogViewXdrStandardType::E_ByteOrder byteOrder = stdType->getByteOrder();
|
||||
a_telegram->setUIntX(getSize(), valueAsUint64, byteOrder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
qint64 intValue = getInteger(text(), ok);
|
||||
if (ok)
|
||||
{
|
||||
if (a_telegram->isJsonTelegram())
|
||||
a_telegram->setJsonValue(m_Field->jsonPath(), intValue);
|
||||
else
|
||||
a_telegram->setUIntX(getSize(), intValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewWidget.hpp"
|
||||
#include <QLineEdit>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewValueEdit : public QLineEdit, public LogViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
|
||||
|
||||
|
||||
|
||||
bool saveContent(LogViewTelegram* a_telegram) override;
|
||||
|
||||
protected:
|
||||
|
||||
bool m_IsFloat;
|
||||
|
||||
protected slots:
|
||||
void checkAndOvertakeContent();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewWidget.hpp"
|
||||
|
||||
#include "LogViewField.hpp"
|
||||
#include "LogViewTelegram.hpp"
|
||||
#include "LogViewXdrStandardType.hpp"
|
||||
#include "IntegerCalculator.hpp"
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewWidget::LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* a_parent, bool a_readonly)
|
||||
: m_Readonly(a_readonly)
|
||||
, m_Valid(true)
|
||||
, m_Widget(a_widget)
|
||||
, m_Field(a_field)
|
||||
, m_Parent(a_parent)
|
||||
, m_logger(getLogger("LogViewWidget"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
uint16_t LogViewWidget::getSize() const
|
||||
{
|
||||
|
||||
const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement());
|
||||
return xdrStandardType->getValueSize();
|
||||
}
|
||||
|
||||
|
||||
void LogViewWidget::showMessageBox(const QString &a_errorText) const
|
||||
{
|
||||
QMessageBox::warning(m_Parent, QObject::tr("Fehler"), a_errorText);
|
||||
}
|
||||
|
||||
|
||||
void LogViewWidget::updateToolTip(const QString &a_text)
|
||||
{
|
||||
bool isList = m_Field->valueListSize() > 1 || m_Field->isDynamicArray();
|
||||
switch (m_Field->xdrElement()->getKind())
|
||||
{
|
||||
case LogViewXdrElement::e_KindStandardType:
|
||||
switch (static_cast<const LogViewXdrStandardType*>(m_Field->xdrElement())->getValueKind())
|
||||
{
|
||||
case LogViewXdrStandardType::e_Character:
|
||||
m_Widget->setToolTip(QObject::tr("%1 Zeichen").arg(a_text.length()));
|
||||
if (!m_Readonly)
|
||||
m_Widget->setToolTip(QObject::tr("%1<br><nobr>Maximal %2 Zeichen erlaubt</nobr>").arg(m_Widget->toolTip()).arg(m_Field->maxArraySize()));
|
||||
break;
|
||||
case LogViewXdrStandardType::e_Data:
|
||||
if (m_Readonly)
|
||||
m_Widget->setToolTip(QObject::tr("%1 Bytes").arg(m_Field->valueListSize()));
|
||||
break;
|
||||
case LogViewXdrStandardType::e_Unsigned:
|
||||
case LogViewXdrStandardType::e_Signed:
|
||||
if (m_Readonly && isList)
|
||||
{
|
||||
m_Widget->setToolTip(QObject::tr("%1 Elemente").arg(m_Field->valueListSize()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (m_Field->isDateTimeField())
|
||||
{
|
||||
m_Widget->setToolTip(QObject::tr("Unixzeit: %1 ").arg(a_text));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Widget->setToolTip(QString());
|
||||
}
|
||||
|
||||
if (!isList)
|
||||
{
|
||||
int64_t value = a_text.toLong();
|
||||
m_Widget->setToolTip(QStringLiteral("%1<b>%2</b> %3").arg(m_Widget->toolTip(), toHex(value), toBin(value)));
|
||||
}
|
||||
|
||||
if (!m_Field->isDateTimeField() && !m_Readonly)
|
||||
{
|
||||
const QString sep(isList ? QString() : QStringLiteral("<br>"));
|
||||
m_Widget->setToolTip(QStringLiteral("%1%2<nobr>Wertebereich: %3..%4</nobr>").arg(m_Widget->toolTip(), sep).arg(m_Field->getLowestValue()).arg(m_Field->getHighestValue()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LogViewXdrStandardType::e_Float:
|
||||
if (4 == m_Field->size())
|
||||
m_Widget->setToolTip(QStringLiteral("<nobr>Wertebereich: +/-3.4e+/-38</nobr>"));
|
||||
else
|
||||
m_Widget->setToolTip(QStringLiteral("<nobr>Wertebereich: +/-1.7e+/-308</nobr>"));
|
||||
break;
|
||||
case LogViewXdrStandardType::e_Boolean:
|
||||
m_Widget->setToolTip(QStringLiteral("true/false"));
|
||||
|
||||
}
|
||||
break;
|
||||
case LogViewXdrElement::e_KindEnum:
|
||||
{
|
||||
uint64_t enumValue = a_text.toLong();
|
||||
m_Widget->setToolTip(QStringLiteral("<b>%1 %2</b> %3").arg(enumValue).arg(toHex(enumValue), toBin(enumValue)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERROR_LOG(m_logger) << "Case not implemented";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double LogViewWidget::getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse)
|
||||
{
|
||||
|
||||
|
||||
|
||||
double value;
|
||||
if (8 == getSize())
|
||||
{
|
||||
value = a_text.toDouble(&a_ok);
|
||||
a_FloatAsData = LogViewTelegram::doubleToXdr(value);
|
||||
} else {
|
||||
value = a_text.toFloat(&a_ok);
|
||||
a_FloatAsData = LogViewTelegram::floatToXdr(value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!a_ok)
|
||||
showMessageBox(QStringLiteral("Inalid real value: '%1'").arg(a_text));
|
||||
|
||||
m_Valid = a_ok;
|
||||
|
||||
|
||||
if (a_reverse)
|
||||
{
|
||||
int j = getSize() - 1;
|
||||
uint64_t* ptr = &a_FloatAsData;
|
||||
for (int i = 0; i < getSize() / 2; i++)
|
||||
{
|
||||
uint8_t data = ((uint8_t*)ptr)[j];
|
||||
((uint8_t*)&a_FloatAsData)[j] = ((uint8_t*)&a_FloatAsData)[i];
|
||||
((uint8_t*)&a_FloatAsData)[i] = data;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (4 == getSize())
|
||||
{
|
||||
((uint8_t*)&a_FloatAsData)[4] = 0;
|
||||
((uint8_t*)&a_FloatAsData)[5] = 0;
|
||||
((uint8_t*)&a_FloatAsData)[6] = 0;
|
||||
((uint8_t*)&a_FloatAsData)[7] = 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
|
||||
{
|
||||
|
||||
N_SST::IntegerCalculator calculator;
|
||||
N_SST::IntegerCalculator::E_Error error;
|
||||
int64_t value = calculator.calc(a_text.toStdString(), error);
|
||||
m_Valid = false;
|
||||
a_ok = true;
|
||||
if (N_SST::IntegerCalculator::e_Ok != error)
|
||||
{
|
||||
|
||||
if (a_text != m_LastErrorValueText)
|
||||
{
|
||||
showMessageBox(QString::fromUtf8("Die Berechnung '%1' ist falsch").arg(a_text));
|
||||
m_LastErrorValueText = a_text;
|
||||
}
|
||||
a_ok = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
int64_t highest = m_Field->getHighestValue();
|
||||
if (value > highest)
|
||||
{
|
||||
a_ok = false;
|
||||
|
||||
|
||||
if (a_text != m_LastErrorValueText)
|
||||
{
|
||||
showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu hoch. Maximalwert: %2").arg(a_text).arg(highest));
|
||||
m_LastErrorValueText = a_text;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
int64_t lowest = m_Field->getLowestValue();
|
||||
if (value < lowest)
|
||||
{
|
||||
a_ok = false;
|
||||
if (a_text != m_LastErrorValueText)
|
||||
{
|
||||
showMessageBox(QString::fromUtf8("Der Wert '%1' ist zu tief. Minimalwert: %2").arg(a_text).arg(lowest));
|
||||
m_LastErrorValueText = a_text;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
m_Valid = true;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "logger.h"
|
||||
|
||||
class QWidget;
|
||||
class QFont;
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
template <typename T>
|
||||
inline QString toHex(T num)
|
||||
{
|
||||
return QStringLiteral("0x%1").arg(num, 2, 16, QLatin1Char('0'));
|
||||
}
|
||||
template <typename T>
|
||||
inline QString toBin(T num)
|
||||
{
|
||||
return QStringLiteral("0b%1").arg(num, 8, 2, QLatin1Char('0'));
|
||||
}
|
||||
|
||||
class LogViewField;
|
||||
class LogViewTelegram;
|
||||
|
||||
|
||||
|
||||
class LogViewWidget
|
||||
{
|
||||
public:
|
||||
LogViewWidget(LogViewField* a_field, QWidget* a_widget, QWidget* a_parent, bool a_readonly);
|
||||
virtual ~LogViewWidget() = default;
|
||||
|
||||
virtual uint16_t getSize() const;
|
||||
LogViewField* field() const { return m_Field; }
|
||||
bool isValid() const { return m_Valid; }
|
||||
|
||||
|
||||
|
||||
QString getText() const { return m_Text; }
|
||||
|
||||
|
||||
|
||||
virtual bool saveContent(LogViewTelegram* a_telegram) = 0;
|
||||
|
||||
protected:
|
||||
void showMessageBox(const QString &a_errorText) const;
|
||||
void updateToolTip(const QString &a_text = QString());
|
||||
double getFloat(const QString& a_text, uint64_t& a_FloatAsData, bool& a_ok, const bool a_reverse = false);
|
||||
|
||||
|
||||
|
||||
int64_t getInteger(const QString& a_text, bool& a_ok);
|
||||
|
||||
|
||||
protected:
|
||||
bool m_Readonly;
|
||||
bool m_Valid;
|
||||
|
||||
|
||||
QString m_Text;
|
||||
QString m_LastErrorValueText;
|
||||
QWidget *m_Widget;
|
||||
|
||||
LogViewField *m_Field;
|
||||
|
||||
QWidget *m_Parent;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewXdrElement.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
LogViewXdrElement::LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName)
|
||||
: m_Name(a_name)
|
||||
, m_Kind(a_kind)
|
||||
, m_logger(getLogger(loggerName))
|
||||
{
|
||||
if (a_name.indexOf(QLatin1Char('<')) >= 0 || a_name.indexOf(QLatin1Char('[')) >= 0)
|
||||
ERROR_LOG(m_logger) << "Element \'" << a_name.toStdString() << "\' has a problem";
|
||||
}
|
||||
|
||||
|
||||
void LogViewXdrElement::dump() const
|
||||
{
|
||||
INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName();
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString LogViewXdrElement::getKindName() const
|
||||
{
|
||||
switch (getKind())
|
||||
{
|
||||
case e_KindDefine:
|
||||
return QLatin1String("Define");
|
||||
case e_KindEnum:
|
||||
return QLatin1String("Enum");
|
||||
case e_KindEnumElement:
|
||||
return QLatin1String("EnumElement");
|
||||
case e_KindStandardType:
|
||||
return QLatin1String("StandardType");
|
||||
case e_KindStruct:
|
||||
return QLatin1String("Struct");
|
||||
case e_KindStructElement:
|
||||
return QLatin1String("StructElement");
|
||||
case e_KindTypedef:
|
||||
return QLatin1String("Typedef");
|
||||
}
|
||||
return QStringLiteral("Unknown (%1)").arg(getKind());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include "logger.h"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewXdrElement
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
enum E_ElementKind
|
||||
{
|
||||
e_KindStandardType,
|
||||
e_KindTypedef,
|
||||
e_KindStruct,
|
||||
e_KindStructElement,
|
||||
e_KindEnum,
|
||||
e_KindEnumElement,
|
||||
e_KindDefine
|
||||
};
|
||||
|
||||
virtual ~LogViewXdrElement() = default;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName);
|
||||
|
||||
public:
|
||||
const QString& getName() const { return m_Name; }
|
||||
LogViewXdrElement::E_ElementKind getKind() const { return m_Kind; }
|
||||
|
||||
virtual void dump() const;
|
||||
|
||||
protected:
|
||||
QString m_Name;
|
||||
E_ElementKind m_Kind;
|
||||
QString getKindName() const;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include "IntegerCalculator.hpp"
|
||||
#include "logger.h"
|
||||
#include "LogViewXdrStandardType.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewXdrElement;
|
||||
class LogViewXdrStruct;
|
||||
class LogViewField;
|
||||
class LogViewXdrValue;
|
||||
class LogViewXdrType;
|
||||
|
||||
|
||||
|
||||
class LogViewXdrParser : public N_SST::IntegerCalculator
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
enum E_ParseState
|
||||
{
|
||||
e_ParseMain,
|
||||
e_ParseStruct,
|
||||
e_ParseEnum,
|
||||
e_ParseUnion
|
||||
};
|
||||
|
||||
|
||||
LogViewXdrParser();
|
||||
~LogViewXdrParser();
|
||||
|
||||
|
||||
|
||||
|
||||
void parseX_File(const QString& a_fileName);
|
||||
|
||||
|
||||
|
||||
QString getTelegramName(int a_telegramId) const;
|
||||
|
||||
|
||||
|
||||
QString getStructName(int a_telegramId) const;
|
||||
|
||||
|
||||
|
||||
bool getDefine(const QString& a_name, int64_t& a_value) const;
|
||||
|
||||
|
||||
|
||||
const LogViewXdrElement* getElement(const QString& a_name) const;
|
||||
|
||||
protected:
|
||||
|
||||
QString m_MessageBoxTitle;
|
||||
bool m_WithinComment;
|
||||
QString m_Line;
|
||||
uint32_t m_LineNbr;
|
||||
QString m_Filename;
|
||||
bool m_DoReadUntilSemicolon;
|
||||
QStringList m_WordList;
|
||||
int m_WordListIndex;
|
||||
|
||||
|
||||
QString m_UnionType;
|
||||
std::map<QString, LogViewXdrElement*> m_ElementMap;
|
||||
|
||||
LogViewXdrStruct *m_ActElement;
|
||||
|
||||
E_ParseState m_State;
|
||||
|
||||
std::map<QString, LogViewXdrValue> m_DefinesMap;
|
||||
|
||||
std::map<int, LogViewXdrType> m_TelegramMap;
|
||||
|
||||
|
||||
|
||||
void addStandardType(const QString& a_name,
|
||||
const uint16_t a_dataSize,
|
||||
const uint16_t a_realSize,
|
||||
const LogViewXdrStandardType::E_ValueKind a_kind,
|
||||
const LogViewXdrStandardType::E_DynArraySizeMethod a_dynArraySizeMethod = LogViewXdrStandardType::e_DynArrayMsgLength,
|
||||
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
|
||||
|
||||
|
||||
|
||||
QString removeComments(const QString& a_line);
|
||||
|
||||
|
||||
|
||||
void parseTypedef(const QString &a_line);
|
||||
|
||||
|
||||
|
||||
void parseDefine(const QString &a_line);
|
||||
|
||||
|
||||
|
||||
void parseEnum(const QString &a_line, const uint16_t a_enumSize = 4);
|
||||
|
||||
|
||||
|
||||
void parseStruct(const QString &a_line);
|
||||
|
||||
|
||||
|
||||
void parseUnion(const QString& a_line);
|
||||
|
||||
|
||||
|
||||
bool parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const;
|
||||
|
||||
|
||||
|
||||
void showErrorMessage(const QString& a_errorText) const;
|
||||
|
||||
|
||||
|
||||
int64_t calcValue(const QString& a_calcText, bool& a_isOk);
|
||||
|
||||
|
||||
|
||||
bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const override;
|
||||
|
||||
|
||||
|
||||
uint16_t parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const;
|
||||
|
||||
|
||||
|
||||
bool isNextWord(const char *a_word, const bool a_doIncrement = true);
|
||||
|
||||
|
||||
|
||||
void fillWordList(const QString& a_line);
|
||||
|
||||
|
||||
|
||||
QString getNextWord(const char *a_errorText = nullptr);
|
||||
|
||||
|
||||
|
||||
QString getNextType(bool& a_ok);
|
||||
|
||||
|
||||
|
||||
QString getNextEnum(const LogViewXdrStruct*& a_enumStruct);
|
||||
|
||||
|
||||
|
||||
bool parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const;
|
||||
|
||||
|
||||
|
||||
bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewXdrStandardType.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LogViewXdrStandardType::LogViewXdrStandardType(const QString& a_name, const int a_valueSize,
|
||||
const int a_editSize, const E_ValueKind a_valueKind,
|
||||
const E_DynArraySizeMethod a_dynArraySizeMethod, E_ByteOrder a_byteOrder)
|
||||
: LogViewXdrElement(a_name, e_KindStandardType, "LogViewXdrStandardType")
|
||||
, m_ValueSize(a_valueSize)
|
||||
, m_EditSize(a_editSize)
|
||||
, m_ValueKind(a_valueKind)
|
||||
, m_ByteOrder(a_byteOrder)
|
||||
, m_DynArraySizeMethod(a_dynArraySizeMethod)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
uint16_t LogViewXdrStandardType::getValueSize() const
|
||||
{
|
||||
return m_ValueSize;
|
||||
}
|
||||
|
||||
|
||||
LogViewXdrStandardType::E_ValueKind LogViewXdrStandardType::getValueKind() const
|
||||
{
|
||||
return m_ValueKind;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewXdrStandardType::dump() const
|
||||
{
|
||||
INFO_LOG(m_logger) << "Element[" << getName()
|
||||
<< "]: kind=" << getKindName()
|
||||
<< " valueKind=" << getValueKind()
|
||||
<< " valueSize=" << getValueSize()
|
||||
<< " editSize=" << getEditSize()
|
||||
<< " dynArrSizeMethod=" << getDynArraySizeMethod()
|
||||
<< " byteOrder=" << getByteOrder();
|
||||
}
|
||||
|
||||
|
||||
LogViewXdrStandardType::E_DynArraySizeMethod LogViewXdrStandardType::getDynArraySizeMethod() const
|
||||
{
|
||||
return m_DynArraySizeMethod;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogViewXdrStandardType::E_ByteOrder LogViewXdrStandardType::getByteOrder() const
|
||||
{
|
||||
return m_ByteOrder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint16_t LogViewXdrStandardType::getEditSize() const
|
||||
{
|
||||
return m_EditSize;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewXdrElement.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewXdrStandardType final : public LogViewXdrElement
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
enum E_ValueKind
|
||||
{
|
||||
|
||||
|
||||
e_Unsigned,
|
||||
|
||||
|
||||
e_Signed,
|
||||
|
||||
|
||||
e_Float,
|
||||
|
||||
|
||||
e_Character,
|
||||
|
||||
|
||||
e_Boolean,
|
||||
|
||||
|
||||
e_Data
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum E_ByteOrder
|
||||
{
|
||||
e_ByteOrderBigEndian,
|
||||
e_ByteOrderLittleEndian
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum E_DynArraySizeMethod
|
||||
{
|
||||
|
||||
|
||||
e_DynArrayMsgLength,
|
||||
|
||||
|
||||
e_DynArrayIndex,
|
||||
|
||||
|
||||
e_DynArrayIndexDiv8
|
||||
};
|
||||
|
||||
|
||||
|
||||
LogViewXdrStandardType(const QString &a_name,
|
||||
const int a_valueSize,
|
||||
const int a_editSize,
|
||||
const E_ValueKind a_valueKind,
|
||||
const E_DynArraySizeMethod a_dynArraySizeMethod,
|
||||
E_ByteOrder a_byteOrder);
|
||||
|
||||
|
||||
uint16_t getValueSize() const;
|
||||
|
||||
|
||||
LogViewXdrStandardType::E_ValueKind getValueKind() const;
|
||||
|
||||
|
||||
void dump() const override;
|
||||
|
||||
|
||||
LogViewXdrStandardType::E_DynArraySizeMethod getDynArraySizeMethod() const;
|
||||
|
||||
|
||||
LogViewXdrStandardType::E_ByteOrder getByteOrder() const;
|
||||
|
||||
|
||||
|
||||
uint16_t getEditSize() const;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
int m_ValueSize;
|
||||
|
||||
|
||||
int m_EditSize;
|
||||
E_ValueKind m_ValueKind;
|
||||
|
||||
E_ByteOrder m_ByteOrder;
|
||||
|
||||
E_DynArraySizeMethod m_DynArraySizeMethod;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewXdrStruct.hpp"
|
||||
#include "LogViewXdrValue.hpp"
|
||||
#include "LogViewXdrType.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewXdrStruct::LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize)
|
||||
: LogViewXdrElement(a_name, a_kind, "LogViewXdrStruct")
|
||||
, m_EnumSize(enumSize)
|
||||
{
|
||||
}
|
||||
|
||||
LogViewXdrStruct::~LogViewXdrStruct()
|
||||
{
|
||||
for (auto ptr : m_ChildList)
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewXdrStruct::addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast)
|
||||
{
|
||||
m_ChildList.push_back(new LogViewXdrType(a_name, a_type, a_arraySize, a_dynArrayOffset, a_kind, a_firstBit, a_lastBit, a_isLast));
|
||||
}
|
||||
|
||||
|
||||
void LogViewXdrStruct::addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind)
|
||||
{
|
||||
m_ChildList.push_back(new LogViewXdrValue(a_name, a_value, a_kind));
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogViewXdrElement* LogViewXdrStruct::getChild(const uint32_t a_childIndex) const
|
||||
{
|
||||
if (m_ChildList.size() > a_childIndex)
|
||||
return m_ChildList[a_childIndex];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogViewXdrType* LogViewXdrStruct::getChildAsType(const uint32_t a_childIndex) const
|
||||
{
|
||||
return static_cast<LogViewXdrType*>(getChild(a_childIndex));
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogViewXdrValue* LogViewXdrStruct::getChildAsValue(const uint32_t a_childIndex) const
|
||||
{
|
||||
return static_cast<LogViewXdrValue*>(getChild(a_childIndex));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewXdrStruct::dump() const
|
||||
{
|
||||
INFO_LOG(m_logger) << "Element[" << getName().toStdString() << "]: kind=" << getKindName().toStdString() << " enumSize=" << getEnumSize();
|
||||
INFO_LOG(m_logger) << "-------------- childs start -----------------";
|
||||
|
||||
std::vector<LogViewXdrElement*>::const_iterator iter = m_ChildList.begin();
|
||||
while (iter != m_ChildList.end())
|
||||
{
|
||||
(*iter)->dump();
|
||||
++iter;
|
||||
}
|
||||
INFO_LOG(m_logger) << "-------------- childs end -----------------";
|
||||
}
|
||||
|
||||
|
||||
uint32_t LogViewXdrStruct::getChildValue(const QString& a_name, bool* a_error) const
|
||||
{
|
||||
if (a_error)
|
||||
*a_error = false;
|
||||
std::vector<LogViewXdrElement*>::const_iterator iter = m_ChildList.begin();
|
||||
while (iter != m_ChildList.end())
|
||||
{
|
||||
if ((*iter)->getName() == a_name)
|
||||
return static_cast<const LogViewXdrValue*>(*iter)->getValue();
|
||||
++iter;
|
||||
}
|
||||
if (a_error)
|
||||
*a_error = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include "LogViewXdrElement.hpp"
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewXdrValue;
|
||||
}
|
||||
namespace N_LogView
|
||||
{
|
||||
class LogViewXdrType;
|
||||
}
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewXdrStruct final : public LogViewXdrElement
|
||||
{
|
||||
public:
|
||||
LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize = 0);
|
||||
~LogViewXdrStruct();
|
||||
|
||||
void addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit = -1, const int16_t a_lastBit = -1, const bool a_isLast = true);
|
||||
void addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind);
|
||||
|
||||
LogViewXdrElement* getChild(const uint32_t a_childIndex) const;
|
||||
LogViewXdrType* getChildAsType(const uint32_t a_childIndex) const;
|
||||
LogViewXdrValue* getChildAsValue(const uint32_t a_childIndex) const;
|
||||
|
||||
|
||||
void dump() const override;
|
||||
|
||||
uint32_t getChildValue(const QString& a_name, bool* a_error = nullptr) const;
|
||||
uint16_t getEnumSize() const { return m_EnumSize; }
|
||||
|
||||
protected:
|
||||
|
||||
uint16_t m_EnumSize;
|
||||
std::vector<LogViewXdrElement*> m_ChildList;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewXdrType.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind)
|
||||
: LogViewXdrElement(a_name, a_kind, "LogViewXdrElement")
|
||||
, m_Type(a_type)
|
||||
, m_ArraySize(a_arraySize)
|
||||
, m_MaxArraySize(a_dynArrayOffset)
|
||||
, m_FirstBit(-1)
|
||||
, m_LastBit(-1)
|
||||
, m_IsLast(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
LogViewXdrType::LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast)
|
||||
: LogViewXdrElement(a_name, a_kind, "LogViewXdrType")
|
||||
, m_Type(a_type)
|
||||
, m_ArraySize(a_arraySize)
|
||||
, m_MaxArraySize(a_dynArrayOffset)
|
||||
, m_FirstBit(a_firstBit)
|
||||
, m_LastBit(a_lastBit)
|
||||
, m_IsLast(a_isLast)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogViewXdrType::dump() const
|
||||
{
|
||||
INFO_LOG(m_logger) << "Element[" << getName()
|
||||
<< "]: kind=" << getKindName()
|
||||
<< " type=" << getType()
|
||||
<< " arraySize=" << getArraySize()
|
||||
<< " maxArraySize=" << getMaxArraySize()
|
||||
<< " firstBit=" << m_FirstBit
|
||||
<< " lastBit=" << m_LastBit
|
||||
<< " isLast=" << m_IsLast;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const QString& LogViewXdrType::getType() const
|
||||
{
|
||||
return m_Type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint16_t LogViewXdrType::getArraySize() const
|
||||
{
|
||||
return m_ArraySize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const
|
||||
{
|
||||
|
||||
if (m_FirstBit != -1 && m_LastBit != -1)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "MaskValue for Element " << m_Name
|
||||
<< " type: " << m_Type
|
||||
<< " size: " << m_ArraySize
|
||||
<< " first:last " << m_FirstBit << ":" << m_LastBit
|
||||
<< " isLast: " << m_IsLast;
|
||||
uint16_t bitshift = (a_size*8)-m_LastBit-1;
|
||||
uint32_t mask = (1<<(m_LastBit-m_FirstBit+1))-1;
|
||||
|
||||
a_value = (a_value >> bitshift) & mask;
|
||||
|
||||
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_FirstBit, QLatin1String("<b>"));
|
||||
a_tooltip.insert(a_tooltip.length()-(a_size*8)+m_LastBit+1, QLatin1String("</b>"));
|
||||
return m_IsLast;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t LogViewXdrType::getMaxArraySize() const
|
||||
{
|
||||
return m_MaxArraySize;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewXdrElement.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewXdrType final : public LogViewXdrElement
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind);
|
||||
|
||||
|
||||
|
||||
LogViewXdrType(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit, const int16_t a_lastBit, const bool a_isLast);
|
||||
|
||||
|
||||
void dump() const override;
|
||||
|
||||
|
||||
const QString& getType() const;
|
||||
|
||||
|
||||
|
||||
uint16_t getArraySize() const;
|
||||
|
||||
|
||||
|
||||
bool maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const;
|
||||
|
||||
|
||||
uint16_t getMaxArraySize() const;
|
||||
|
||||
protected:
|
||||
|
||||
QString m_Type;
|
||||
|
||||
|
||||
uint16_t m_ArraySize;
|
||||
|
||||
|
||||
uint16_t m_MaxArraySize;
|
||||
|
||||
|
||||
int16_t m_FirstBit;
|
||||
|
||||
|
||||
int16_t m_LastBit;
|
||||
|
||||
|
||||
bool m_IsLast;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "LogViewXdrValue.hpp"
|
||||
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
LogViewXdrValue::LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind)
|
||||
: LogViewXdrElement(a_name, a_kind, "LogViewXdrValue")
|
||||
, m_Value(a_value)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
void LogViewXdrValue::dump() const
|
||||
{
|
||||
INFO_LOG(m_logger) << "Element[" << getName() << "]: kind=" << getKindName() << " value=" << getValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int64_t LogViewXdrValue::getValue() const
|
||||
{
|
||||
return m_Value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogViewXdrElement.hpp"
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
|
||||
class LogViewXdrValue final : public LogViewXdrElement
|
||||
{
|
||||
public:
|
||||
LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind);
|
||||
|
||||
void dump() const override;
|
||||
int64_t getValue() const;
|
||||
|
||||
protected:
|
||||
|
||||
int64_t m_Value;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
log4j.reset=true
|
||||
log4j.rootLogger=INFO, C
|
||||
log4j.rootLogger=INFO, F
|
||||
|
||||
log4j.appender.C=org.apache.log4j.ConsoleAppender
|
||||
|
||||
log4j.appender.F=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.F.File=${LOG4QT_LOGDIR}/${LOG4QT_USER}_LogView.log
|
||||
|
||||
log4j.appender.F.MaxFileSize=10MB
|
||||
# Keep one backup file
|
||||
log4j.appender.F.MaxBackupIndex=5
|
||||
|
||||
log4j.appender.C.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.F.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.C.layout.ConversionPattern=%-5p (%-20.20F:%04L) [%d{HH:mm:ss.SSS}] - %m%n
|
||||
log4j.appender.F.layout.ConversionPattern=%-5p (%-20.20F:%04L) [%d{HH:mm:ss.SSS}] - %m%n
|
||||
|
After Width: | Height: | Size: 287 B |
|
After Width: | Height: | Size: 191 B |
|
After Width: | Height: | Size: 586 B |
|
After Width: | Height: | Size: 534 B |
|
After Width: | Height: | Size: 275 B |
|
After Width: | Height: | Size: 288 B |
|
After Width: | Height: | Size: 188 B |
|
After Width: | Height: | Size: 801 B |
|
After Width: | Height: | Size: 382 B |
|
After Width: | Height: | Size: 278 B |
|
After Width: | Height: | Size: 253 B |
|
After Width: | Height: | Size: 307 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 191 B |
|
After Width: | Height: | Size: 586 B |
|
After Width: | Height: | Size: 543 B |
@@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "LogView.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace N_LogView
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
zsksxd_tetraForLogView.x
|
||||
@@ -0,0 +1 @@
|
||||
zsksxd_tetraForLogView_guez.x
|
||||