Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+104
View File
@@ -0,0 +1,104 @@
#
# $Id$
# $HeadURL$
# $Author$
#
ADD_SUBDIRECTORY(Console)
SET(my_SRCS
IntegerCalculator.cpp
IntegerCalculator.hpp
logger.cpp
logger.h
LogViewBooleanEdit.cpp
LogViewBooleanEdit.hpp
LogViewDateTimeEdit.cpp
LogViewDateTimeEdit.hpp
LogViewEnumEdit.cpp
LogViewEnumEdit.hpp
LogViewField.cpp
LogViewField.hpp
LogViewGui.cpp
LogViewGui.hpp
LogViewInjectionThread.cpp
LogViewInjectionThread.hpp
LogViewMain.cpp
LogViewModels.cpp
LogViewModels.hpp
LogViewOptionDialog.cpp
LogViewOptionDialog.hpp
LogViewSpinBox.cpp
LogViewSpinBox.hpp
LogViewTableWidget.cpp
LogViewTableWidget.hpp
LogViewTabWidget.cpp
LogViewTabWidget.hpp
LogViewTelegram.cpp
LogViewTelegramDialog.cpp
LogViewTelegramDialog.hpp
LogViewTelegramEdit.cpp
LogViewTelegramEdit.hpp
LogViewTelegramEditModel.cpp
LogViewTelegramEditModel.hpp
LogViewTelegram.hpp
LogViewTelegramSelectionDialog.cpp
LogViewTelegramSelectionDialog.hpp
LogViewTetraTelegramsParser.cpp
LogViewTetraTelegramsParser.hpp
LogViewTextEdit.cpp
LogViewTextEdit.hpp
LogViewValueEdit.cpp
LogViewValueEdit.hpp
LogViewWidget.cpp
LogViewWidget.hpp
LogViewXdrElement.cpp
LogViewXdrElement.hpp
LogViewXdrParser.cpp
LogViewXdrParser.hpp
LogViewXdrStandardType.cpp
LogViewXdrStandardType.hpp
LogViewXdrStruct.cpp
LogViewXdrStruct.hpp
LogViewXdrType.cpp
LogViewXdrType.hpp
LogViewXdrValue.cpp
LogViewXdrValue.hpp
zsksxd_tetraForLogView.x
)
QT5_ADD_RESOURCES(my_SRCS LogViewResources.qrc)
NGL_ADD_TOOL_ICON(my_SRCS)
NGL_ADD_EXECUTABLE(AAR SV NO_TRANSLATION LogView ${my_SRCS})
NGL_TARGET_LINK_LIBRARIES(LogView
Qt5::Core
Qt5::Gui
Qt5::Network
CoPrtCnv
nglwidgets
NGLLogger
nglapplication
ngltools
)
NGL_INSTALL_TARGET(LogView)
NGL_INSTALL(AAR SV FILES LogView_log4cxx.props DESTINATION bin)
# install on RPM build and copy for local builds so that LogView automatically finds the zsksxd_tetraForLogView.x file
if (BUILD_RPM)
add_custom_target(zsksxd_tetraForLogView.x_bin) # empty target so that LogView still builds on RPM build
NGL_INSTALL(AAR SV FILES zsksxd_tetraForLogView.x DESTINATION bin)
else()
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/zsksxd_tetraForLogView.x ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/zsksxd_tetraForLogView.x
COMMENT "[Local build] Copy zsksxd_tetraForLogView.x for LogView into bin/"
)
add_custom_target(zsksxd_tetraForLogView.x_bin DEPENDS ${CMAKE_BINARY_DIR}/bin/zsksxd_tetraForLogView.x)
endif()
if (TARGET LogView)
add_dependencies(LogView zsksxd_tetraForLogView.x_bin training_area_telegrams.h_bin)
endif()
+17
View File
@@ -0,0 +1,17 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET(console_SRCS
main.cpp
)
NGL_ADD_TOOL_ICON(console_SRCS)
NGL_ADD_EXECUTABLE(AAR SV LogView_console ${console_SRCS})
NGL_INSTALL_TARGET(LogView_console)
NGL_TARGET_LINK_LIBRARIES(LogView_console
CoPrtCnv
NGLLogger
)
+204
View File
@@ -0,0 +1,204 @@
/**
* $Id$
* $HeadURL$
* $Author$
*/
#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);
// Check alle 30 Sekunden
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;
}
//fprintf(stdout, "Counter;EqID;TelID;TelTime;LogTime;Diff\n");
while (true)
{
// read the header of telegram-entry
N_CoPrtCnv::CoPrtCnvLogHeader lh;
if (sizeof(lh) == telegramFile.read((char *)&lh, sizeof(lh)))
{
if (lh.m_Version == 3)
{
// read the telegram itself
qint64 telegramLength = lh.m_Length - sizeof(lh);
QByteArray telegramData(telegramLength, Qt::Uninitialized);
if (telegramLength == telegramFile.read(telegramData.data(), telegramLength))
{
// add the telegram to telegram-list
N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol dest = (N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol)
(lh.m_Protocol & N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolMask);
switch (dest)
{
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral:
{
const QJsonObject obj = QJsonDocument::fromJson(telegramData).object();
int telId = obj.value(QStringLiteral("typeId")).toInt();
if (telIdToSearch != telId)
continue;
const QJsonObject objData = obj.value(QStringLiteral("data")).toObject();
const QByteArray tBA = formatTime(lh.m_Time);
const char *timeStr = tBA.constData();
switch (telId)
{
case Constraints<CreateFunctionalArea>::id():
{
const CreateFunctionalArea tele(CreateFunctionalArea::fromJson(objData));
if (!validEqId(tele))
break;
fprintf(stdout, "%s, FUNKTIONSRAUM: '%s', %d, %d\n",
timeStr,
tele.name.c_str(),
tele.aesDdsId,
tele.header.equipmentNumber
);
break;
}
case Constraints<DeactivateEffectSimulation>::id():
{
const DeactivateEffectSimulation tele(DeactivateEffectSimulation::fromJson(objData));
fprintf(stdout, "%s, DEAKTIVIERUNG_WIRKFELD: typ: %d - kennung: %d\n",
timeStr,
int(tele.aesType),
tele.aesDdsId
);
break;
}
case Constraints<PositionReport>::id():
{
const PositionReport tele(PositionReport::fromJson(objData));
if (!validEqId(tele))
break;
if (tele.opsPosition.opsId == 0)
break;
fprintf(stdout, "%s, IPS_POSITIONSDATEN: %d - OPS: %d\n",
timeStr,
tele.header.equipmentNumber,
tele.opsPosition.opsId
);
break;
}
case BESTAETIGUNG:
case UMGEBUNGS_MELDUNG2:
break;
default:
fprintf(stderr, "Printing telegram with id %d not implemented\n", telId);
break;
}
break;
}
case N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolTetra:
{
N_CoPrtCnv::CoPrtCnvRadioTelegram radioTelegram(telegramData);
gef_telegramm_id_et telId = radioTelegram.getTelID();
if (telId == GEF_UMGEBUNGS_MELDUNG2)
{
const QByteArray tBA = formatTime(lh.m_Time);
const char *timeStr = tBA.constData();
static uint16_t bci = 0xFFFF;
if (bci != radioTelegram.getBroadcastIndex())
{
if (bci > radioTelegram.getBroadcastIndex() && bci != 0xFFFF)
{
fprintf(stdout, "BCI reset in %s at %s!\n",
qPrintable(telegramFile.fileName()),
timeStr);
}
fprintf(stdout, "BCI: %d\n", radioTelegram.getBroadcastIndex());
bci = radioTelegram.getBroadcastIndex();
}
}
break;
}
default:
break;
}
}
}
else
{
ERROR_LOG(logger) << "Wrong LogHeader version: " << lh.m_Version;
return 4;
}
}
else
break;
}
return 0;
}
+497
View File
@@ -0,0 +1,497 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#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)
{
}
// ---------------------------------------------------------------
// Converts the expressen in a_calcText into a signed value.
// Returns whether an error happend in the variable a_error.
// If an error happend, the variable a_addErrorText can
// contain more informaition about the error (see E_Error for
// more information about errors).
// ---------------------------------------------------------------
int64_t IntegerCalculator::calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText)
{
std::string calcText = a_calcText;
// separate operations from variables
for (auto iter = m_OperationList.begin(); iter != m_OperationList.end(); ++iter)
replace(calcText, iter->first, " "+iter->first+" ");
// separate paranthesis from variables
replace(calcText, "(", " ( ");
replace(calcText, ")", " ) ");
// now calculate the expression
m_ParanthesisCount = 0;
m_Error = e_Ok;
m_AdditionalErrorText = "";
size_t pos = 0;
bool dummy;
int64_t value = calc(calcText, pos, dummy, "", 0, "+"); // todo: use member-variable m_CalcText
//M_INFO("calc: " << calcText << " value: " << value);
// check the paranthesis
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;
}
}
// actions if a failure happens
a_error = m_Error;
if (a_error != e_Ok)
{
value = 0;
if (a_addErrorText)
{
*a_addErrorText = m_AdditionalErrorText;
}
}
return value;
}
// ---------------------------------------------------------------
// Adds or changes a case-sensitive variable to the calculator.
// ---------------------------------------------------------------
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));
}
// ---------------------------------------------------------------
// Removes a case-sensitive variable from the calculator.
// ---------------------------------------------------------------
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);
}
// ---------------------------------------------------------------
// Calculates the expression (recursive)
// ---------------------------------------------------------------
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);
// get next operation to check priority of operation
size_t tmpPos = a_pos; // do not change the position, we only pre-read
std::string nextOp = getToken(a_calcText, tmpPos);
if (isOperation(nextOp) && isOperation(a_prevOp) && !isOperationPriorityHigher(nextOp, a_prevOp))
{
// end of higher priority operation
return value1;
}
operation = "";
}
else if (')' == calcText[a_pos])
{
m_ParanthesisCount--;
a_pos++;
a_IsEndParanthesis = true;
return value1;
}
else if (isDigit(calcText[a_pos]))
{
// value
// -----
int64_t value2 = calcSign(convertValue(calcText, a_pos), isNegative);
if (calcWithPriority(calcText, a_pos, value1, operation, value2, a_prevOp)) return value1;
}
else
{
// operation or variable
// ---------------------
std::string oldOperation = operation;
operation = getToken(calcText, a_pos);
// is it a variable?
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
{
// error
m_Error = e_UnknownOperationOrVariable;
m_AdditionalErrorText = operation;
}
}
else
{
// do we have a sign?
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;
}
// ---------------------------------------------------------------
// Calculates an operation with respecting the priority of
// operations. This will be done with recursion.
// ---------------------------------------------------------------
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;
// get next operation to check priority of operation
size_t tmpPos = a_pos; // only pre-read
std::string nextOp = getToken(a_calcText, tmpPos);
if (isOperation(a_operation) && isOperation(nextOp) && isOperationPriorityHigher(nextOp, a_operation))
{
// next operation has higher priority => calc the next operation first
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)))
{
// end of higher priority operation
return true;
}
a_operation = "";
return false;
}
// ---------------------------------------------------------------
// Returns the inverted a_value if a_isNegative is true.
// a_isNegative will be false after calling this function.
// If a_isNegative is true, the NOT inverted a_value will be
// returned.
// ---------------------------------------------------------------
int64_t IntegerCalculator::calcSign(const int64_t a_value, bool& a_isNegative)
{
if (a_isNegative)
{
a_isNegative = false;
return -a_value;
}
return a_value;
}
// ---------------------------------------------------------------
// Converts the value in form of text to a number. The Text
// can be decimal, hex (0x) or binary (0b).
// ---------------------------------------------------------------
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;
// hex- and binary-stuff
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;
}
// search end of value
size_t i;
for (i=startpos; i<valueText.length(); i++)
{
if (!isDigit(valueText[i], isHex, isBin))
{
break;
}
}
// check the next char, it must be a space
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)
{
// our stl is not able to read in binary-values, therefore we have to implement it ourself
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;
}
// ---------------------------------------------------------------
// Returns the next token (with space as separator). Heading
// spaces will be ignored.
// ---------------------------------------------------------------
std::string IntegerCalculator::getToken(const std::string &a_calcText, size_t& a_pos)
{
// skip spaces at begin
while (a_pos < a_calcText.length())
{
if (a_calcText[a_pos] == ' ') a_pos++;
else break;
}
// search until next space (or end)
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);
}
// ---------------------------------------------------------------
// returns true if a_operation is a known operation.
// ---------------------------------------------------------------
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());
}
// ---------------------------------------------------------------
// Calculates the opeation a_operations with a_value1 as first
// and a_value2 as second operand.
// ---------------------------------------------------------------
int64_t IntegerCalculator::doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2)
{
// M_INFO("" << a_value1 << " " << a_operation << " " << 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;
}
// ---------------------------------------------------------------
// returns true if priority of a_opeation1 is higher than
// priority of a_operation2.
// ---------------------------------------------------------------
bool IntegerCalculator::isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const
{
return (getPriority(a_operation1) > getPriority(a_operation2));
}
// ---------------------------------------------------------------
// Returns true if the variable named a_variableName is known
// and a_value will be filled with its value. If the variable
// is not found false will be returned.
// Overload this virtual function if you want to implement
// your own variable-list.
// ---------------------------------------------------------------
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;
}
// error
return false;
}
// ---------------------------------------------------------------
// Returns true if a_char is a digit. When a_isHex is true,
// also the charactes a-f will be accepted as digits. When
// a_isBin is true, only 0 and 1 will be treated as digit.
// ---------------------------------------------------------------
bool IntegerCalculator::isDigit(const char a_char, const bool a_isHex, const bool a_isBin)
{
if (a_isHex)
{
// for hex-values also A..F are 'digits'
return (a_char >= '0' && a_char <= '9') || (a_char >= 'A' && a_char <= 'F') || (a_char >= 'a' && a_char <= 'f');
}
else if (a_isBin)
{
// for binary-values only 0 and 1 are allowed
return (a_char >= '0' && a_char <= '1');
}
// normal digits
return (a_char >= '0' && a_char <= '9');
}
// ---------------------------------------------------------------
// Returns the priority of the operation. A higher value means
// more priority.
// ---------------------------------------------------------------
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;
}
// ---------------------------------------------------------------
// replaces in a_haystack all a_searchText with a_replaceText
// (not greedy).
// ---------------------------------------------------------------
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);
}
}
} // namespace N_SST
+257
View File
@@ -0,0 +1,257 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <string>
#include <map>
namespace N_SST
{
/**
* This class calculates algebraic texts with integer values and returns its
* result as a signed value. It handles the operations - +, -, *, /, %, <<, >>. It
* understands the paranthesis and priorities of operations, like * before -. It
* also computes with variables, which names are case-sensitive. The values can be
* decimal, hexadecimal (0x) or binary (0b). The variable-system implemented
* virtual, so you can implement your own variable system (see getVariableValue()).
*
*
* @author alois.wismer
* @version 1.0
* @created 12-Mai-2010 16:26:43
*/
class IntegerCalculator
{
public:
/**
* Describes the error happend while calculation of an expression
*
* @author alois.wismer
* @version 1.0
* @created 17-Mai-2010 16:38:24
*/
enum E_Error
{
/**
* No error happend
*/
e_Ok,
/**
* The divisor is 0
*/
e_DivisionByZero,
/**
* The operation/variable is not known. a_addErrorText will contain the unknown
* operation/variable.
*/
e_UnknownOperationOrVariable,
/**
* Between to operators no variable/operand exists. a_addErrorText contains the 2
* operations.
*/
e_NoOperandBetweenOperators,
/**
* The operand contains invalid characters. a_addErrorText contains the invalid
* operand.
*/
e_InvalidOperand,
/**
* There are more ) than (
*/
e_MissingLeftParanthesis,
/**
* There are more ) than (
*/
e_MissingRightParanthesis,
/**
* Something else went wrong
*/
e_UnknownError
};
IntegerCalculator();
virtual ~IntegerCalculator() = default;
/**
* Converts the expressen in a_calcText into a signed value. Returns whether an
* error happend in the variable a_error. If an error happend, the variable
* a_addErrorText can contain more informaition about the error (see E_Error for
* more information about errors).
*
* @param a_calcText
* @param a_error
* @param a_addErrorText
*/
int64_t calc(const std::string& a_calcText, E_Error& a_error, std::string* a_addErrorText = nullptr);
/**
* Adds or changes a case-sensitive variable to the calculator.
*
* @param a_name
* @param a_value
*/
void addVariable(const std::string& a_name, const int64_t a_value);
/**
* Removes a case-sensitive variable from the calculator.
*
* @param a_name
*/
void removeVariable(const std::string& a_name);
protected:
/**
* Contains all supported operations
*/
const std::map<std::string, int> m_OperationList;
/**
* Contains all variables
*/
std::map<std::string, int64_t> m_VariableList;
/**
* The additional text for errors
*/
std::string m_AdditionalErrorText;
/**
* The number of open paranthesis
*/
int32_t m_ParanthesisCount;
E_Error m_Error;
/**
* Calculates the expression (recursive)
*
* @param a_calcText
* @param a_pos
* @param a_IsEndParanthesis
* @param a_prevOp
* @param a_prevValue
* @param a_initOp
*/
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());
/**
* Calculates an operation with respecting the priority of operations. This will
* be done with recursion.
*
* @param a_calcText
* @param a_pos
* @param a_value1
* @param a_operation
* @param a_value2
* @param a_prevOp
*/
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);
/**
* Returns the inverted a_value if a_isNegative is true. a_isNegative will be
* false after calling this function.
* If a_isNegative is true, the NOT inverted a_value will be returned.
*
* @param a_value
* @param a_isNegative
*/
static int64_t calcSign(const int64_t a_value, bool& a_isNegative);
/**
* Converts the value in form of text to a number. The Text can be decimal, hex
* (0x) or binary (0b).
*
* @param a_valueText
* @param a_pos
*/
int64_t convertValue(const std::string& a_valueText, size_t& a_pos);
/**
* Returns the next token (with space as separator). Heading spaces will be
* ignored.
*
* @param a_calcText
* @param a_pos
*/
static std::string getToken(const std::string& a_calcText, size_t& a_pos);
/**
* returns true if a_operation is a known operation.
*
* @param a_operation
*/
bool isOperation(const std::string& a_operation) const;
/**
* Calculates the opeation a_operations with a_value1 as first and a_value2 as
* second operand.
*
* @param a_value1
* @param a_operation
* @param a_value2
*/
int64_t doOperation(const int64_t a_value1, const std::string& a_operation, const int64_t a_value2);
/**
* returns true if priority of a_opeation1 is higher than priority of a_operation2.
*
*
* @param a_operation1
* @param a_operation2
*/
bool isOperationPriorityHigher(const std::string& a_operation1, const std::string& a_operation2) const;
/**
* Returns true if the variable named a_variableName is known and a_value will be
* filled with its value. If the variable is not found false will be returned.
* Overload this virtual function if you want to implement your own variable-list.
*
* @param a_variableName
* @param a_value
*/
virtual bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const;
/**
* Returns true if a_char is a digit. When a_isHex is true, also the charactes a-f
* will be accepted as digits. When a_isBin is true, only 0 and 1 will be treated
* as digit.
*
* @param a_char
* @param a_isHex
* @param a_isBin
*/
static bool isDigit(const char a_char, const bool a_isHex = false, const bool a_isBin = false);
/**
* Returns the priority of the operation. A higher value means more priority.
*
* @param a_operation
*/
int16_t getPriority(const std::string& a_operation) const;
/**
* replaces in a_haystack all a_searchText with a_replaceText (not greedy).
*
* @param a_haystack
* @param a_searchText
* @param a_replaceText
*/
static void replace(std::string& a_haystack, const std::string& a_searchText, const std::string& a_replaceText);
};
}
+41
View File
@@ -0,0 +1,41 @@
/**
* @RDE_HEADER@
* Edit boolean values
* $Id$
* $HeadURL$
* $Author$
*/
#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;
}
} // namespace N_LogView
+24
View File
@@ -0,0 +1,24 @@
/**
* @RDE_HEADER@
* Edit boolean values
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include "LogViewWidget.hpp"
#include <QCheckBox>
namespace N_LogView
{
class LogViewBooleanEdit : public QCheckBox, public LogViewWidget
{
Q_OBJECT
public:
LogViewBooleanEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
bool saveContent(LogViewTelegram* a_telegram) override;
};
}
+86
View File
@@ -0,0 +1,86 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#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);
}
// date-time-field
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;
}
// take actual date and time if time is 0
if (0 == unixTime && !a_readonly)
unixTime = ::time(nullptr) * 1000LL;
//valueWidget = new QDateTimeEdit(dateTime);
setDateTime(QDateTime::fromMSecsSinceEpoch(unixTime));
setDisplayFormat(QLatin1String("dd MMM yyyy hh:mm:ss"));
setCalendarPopup(true);
updateToolTip(QString::number(unixTime));
//setToolTip(a_field->getToolTipText());
// checkAndOvertakeContent();
connect(this, &LogViewDateTimeEdit::editingFinished,
this, &LogViewDateTimeEdit::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
void LogViewDateTimeEdit::checkAndOvertakeContent()
{
updateToolTip(QString::number(dateTime().toMSecsSinceEpoch() / 1000));
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewDateTimeEdit::saveContent(LogViewTelegram* a_telegram)
{
if (a_telegram->isJsonTelegram())
{
a_telegram->setJsonValue(m_Field->jsonPath(), dateTime().toMSecsSinceEpoch());
}
else
{
a_telegram->setNextFieldAsGpsTimeField(); // fixme: muss noch der feldname auf GPS Zeit geprüft werden?
a_telegram->setUIntX(getSize(), dateTime().toMSecsSinceEpoch() / 1000);
}
return true;
}
} // namespace N_LogView
+53
View File
@@ -0,0 +1,53 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewWidget.hpp"
#include <QDateTimeEdit>
namespace N_LogView
{
/**
* Used for date & time
*
* @author alois.wismer
* @version 1.0
* @created 20-Mai-2010 17:41:28
*/
class LogViewDateTimeEdit : public QDateTimeEdit, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
*/
LogViewDateTimeEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
public slots:
void checkAndOvertakeContent();
};
}
+105
View File
@@ -0,0 +1,105 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#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);
// show the tool-tip with special-case for TETRA bitfields
setToolTip(a_field->toolTipText());
// fill combobox
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 signals
connect(this, QOverload<int>::of(&LogViewEnumEdit::currentIndexChanged),
this, &LogViewEnumEdit::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
uint16_t LogViewEnumEdit::getSize() const
{
// todo: check ob wirklich ein struct
const LogViewXdrStruct* xdrStruct = static_cast<const LogViewXdrStruct*>(m_Field->xdrElement());
return xdrStruct->getEnumSize();
}
// ---------------------------------------------------------------
void LogViewEnumEdit::checkAndOvertakeContent()
{
updateToolTip(itemData(currentIndex()).toString());
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
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; // failure while conversion
}
} // namespace N_LogView
+57
View File
@@ -0,0 +1,57 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewWidget.hpp"
#include <QComboBox>
namespace N_LogView
{
/**
* Used for enums
*
* @author alois.wismer
* @version 1.0
* @created 21-Mai-2010 09:31:16
*/
class LogViewEnumEdit : public QComboBox, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
* @param a_index the array-index
*/
LogViewEnumEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly, const int a_index);
uint16_t getSize() const override;
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void checkAndOvertakeContent();
};
}
+275
View File
@@ -0,0 +1,275 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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)));
}
// ---------------------------------------------------------------
// Returns the value at position a_index converted to a string.
// If the field is a date-time-field, the returned value is
// converted to a string containing date and time, execpt when
// a_doNotMakeSpecialConversions is set to true, the unix-time
// will be returned as value.
// ---------------------------------------------------------------
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;
//const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(m_XdrElement);
uint16_t bitSize = 8*static_cast<const LogViewXdrStandardType*>(m_XdrElement)->getEditSize();
// fixme: mache configurierbar
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;
//const LogViewXdrStandardType* xdrStandardType = static_cast<const LogViewXdrStandardType*>(a_field->getXdrElement());
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;
// m_XdrElement->dump();
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 << "]";
}
// ---------------------------------------------------------------
// Makes the text <a_uncleanText> pretty for human readable.
// It does following:
// - generates umlaute (ä, ö, ü)
// - removes _rt at end
// - replaces _ with space
// - uppercase of every word
// ---------------------------------------------------------------
QString LogViewField::makeClean(const QString &text)
{
QString a_uncleanText = text;
// remove _rt at end
if (a_uncleanText.endsWith(QLatin1String("_rt")))
a_uncleanText = a_uncleanText.left(a_uncleanText.length() - 3);
// replace _ with space
a_uncleanText = a_uncleanText.replace(QLatin1Char('_'), QLatin1Char(' '));
// first character of every word must be uppercase
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;
}
// ---------------------------------------------------------------
// returns true if the field is a date-time
// ---------------------------------------------------------------
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;
}
} // namespace N_LogView
+162
View File
@@ -0,0 +1,162 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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);
/**
* Returns the value at position a_index converted to a string. If the field is a
* date-time-field, the returned value is converted to a string containing date
* and time, execpt when a_doNotMakeSpecialConversions is set to true, the unix-
* time will be returned as value.
*
* @param a_index
* @param a_doNotMakeSpecialConversions
*/
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;
/**
*
* @param a_indent
*/
void dump(const QString &a_indent = QString()) const;
/**
* Makes the text <a_uncleanText> pretty for human readable. It does following:
* - generates umlaute (ä, ö, ü)
* - removes _rt at end
* - replaces _ with space
* - uppercase of every word
*
* @param a_uncleanText
*/
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; }
/**
* returns true if the field is a date-time
*/
bool isDateTimeField() const;
bool isMSecsField() const;
uint16_t maxArraySize() const { return m_MaxArraySize; }
void setMaxArraySize(uint16_t newVal, const bool a_isDynamic);
/**
* True if the array is dynamic.
*/
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;
/**
* True if the array is dynamic.
*/
bool m_IsDynamicArray;
bool m_HasContent;
bool m_bDeleteXdr;
QVector<LogViewField*> m_Child;
E_FieldKind m_Kind;
const LogViewXdrElement *m_XdrElement;
private:
/**
* The logger object
*/
NGL::INGLLogger &m_logger;
};
}
File diff suppressed because it is too large. Load diff
+200
View File
@@ -0,0 +1,200 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
/**
* @author alois.wismer
* @version 1.0
* @created 03-Feb-2010 16:44:53
*/
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;
// Central
QGroupBox *m_CentralSelectionGroup;
std::set<int> m_CentralTelegramFilterList;
QCheckBox* m_SentCentralTelCheckBox;
QCheckBox* m_ReceivedCentralTelCheckBox;
QCheckBox* m_PosCentralTelCheckBox;
QCheckBox* m_ackCentralTelCheckBox;
// Tetra
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;
// Wls
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;
// ausstg, telcount
QHash<int, int> m_participantListTelCount;
// ausstg, issi
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);
/**
* returns true if the participant was added to the list
*/
void addToParticipantList(const QSharedPointer<LogViewTelegram> &a_telegram);
void syncParticipantList();
QCheckBox* createRadioButton(const QString& a_buttonName, const QString& a_iconName);
/**
* starts the thread, which trys to connect to the injection-server of PrtCnv
*/
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();
/**
* Checks whether the size of actual logfile has changed. If yes, the new log-
* entries will be read and shown within table.
*/
void updateLogfile();
void selectedParticipantChanged();
void showTelegramTable();
//SLOT for creating the ContextMenu
void customMenuRequested(const QPoint &pos);
void changeSettings();
/**
* Toggles whether the logfile must be periodically checked for changes
*/
void reloadOnOff();
/**
*
* @param a_picName
* @param a_toopTipText
*/
void updateInjectionStatus(const QString& a_picName, const QString& a_toopTipText);
void onLogTelegramViewDoubleClicked(const QModelIndex &index);
private slots:
void onSettingsChanged(uint32_t changedFlags);
};
}
+143
View File
@@ -0,0 +1,143 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#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"))
{
// load the settings (and write default-values if not defined)
QSettings settings;
settings.beginGroup(LogViewOptionDialog::INJECTION_GROUP);
m_Hostname = settings.value(LogViewOptionDialog::INJECTION_HOSTNAME).toString();
if (m_Hostname.isEmpty())
{
// set default-hostname if nothing was set
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()
{
//m_Timer->setInterval(3000);
if (!m_Socket)
{
m_Socket = new QTcpSocket(this);
connect(m_Socket, &QTcpSocket::connected, this, &LogViewInjectionThread::doConnect);
connect(m_Socket, &QTcpSocket::disconnected, this, &LogViewInjectionThread::doDisconnect);
}
// we need a timer for retrying connection
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);
}
} // namespace N_LogView
@@ -0,0 +1,89 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QtCore/QThread>
#include "logger.h"
class QTcpSocket;
class QTimer;
namespace N_LogView
{
class LogViewTelegram;
/**
* @author alois.wismer
* @version 1.0
* @created 05-Aug-2010 16:02:15
*/
class LogViewInjectionThread : public QThread
{
Q_OBJECT
public:
LogViewInjectionThread();
void run();
void setPort(uint16_t port);
bool isSendingPossible() const;
/**
*
* @param a_telegram
* @param a_doSendAsCentralTelegram
*/
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:
/**
* The logger object
*/
NGL::INGLLogger &m_logger;
protected:
protected slots:
void tryToConnect();
void doConnect();
void doDisconnect();
public:
signals:
/**
*
* @param a_picName
* @param a_toolTipText
*/
void updateStatus(const QString& a_picName, const QString& a_toolTipText);
};
}
+57
View File
@@ -0,0 +1,57 @@
#include <nglapplication/nglapplication.h>
#include <QDesktopWidget>
#include <QtCore/QSettings>
#include <QNetworkProxy>
#ifndef WIN32
#include <unistd.h>
#endif
#include "LogViewGui.hpp"
#include "logger.h"
int main(int argc, char *argv[])
{
std::string logConfigFileName;
std::string dir;
#ifdef WIN32
dir = argv[0];
#else
std::stringstream s;
s << "/proc/" << getpid() << "/exe";
char buf[1024];
ssize_t len = readlink(s.str().c_str(), buf, 1024);
if(len > 0) {
buf[len] = '\0';
dir = buf;
} else {
// fallback
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;
}
+553
View File
@@ -0,0 +1,553 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#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(); // 0 aussen vor lassen
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) // EqId 0 aussen vor lassen
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) // EqId 0 aussen vor lassen
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
{
// TODO: optimize
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;
}
} // namespace N_LogView;
+114
View File
@@ -0,0 +1,114 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#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:
// eqId , issi
QVector<QPair<int, int> > m_particpants;
// eqid, count telegrams
QHash<int, int> m_particpantMap;
// eqId, QColor for heatmap
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;
};
} // namespace N_LogView
+182
View File
@@ -0,0 +1,182 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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
{
// static member initialization
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);
// telegram specification files
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();
// injection
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();
// buttons
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);
//setLayout(layout);
}
// ---------------------------------------------------------------
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;
// check group wise for changes
// specification files
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();
// injection settings
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();
}
} // namespace N_LogView
+84
View File
@@ -0,0 +1,84 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QDialog>
#include <QtCore/QSettings>
class QLineEdit;
namespace N_LogView
{
/**
* This class lets the user view and change the settings of the application
*
* @author alois.wismer
* @version 1.0
* @created 09-Mrz-2010 14:49:40
*/
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;
/**
*
* @param a_parent a_parent
*/
explicit LogViewOptionDialog(QWidget* a_parent);
signals:
void settingsChanged(uint32_t changed); // bitfield of SettingsChangedFlag enum
protected:
static const QString SPEC_FILES;
static const QLatin1String DIR;
bool m_IsServer;
QLineEdit *m_P0Edit;
QLineEdit *m_P5Edit;
QSettings m_Settings;
QLineEdit *m_InjectHostnameEdit;
QLineEdit *m_InjectPortEdit;
protected slots:
void browseP0File();
void browseP5File();
void save();
};
}
+18
View File
@@ -0,0 +1,18 @@
<RCC>
<qresource prefix="/" >
<file>image/P2C.png</file>
<file>image/C2P.png</file>
<file>image/P2W.png</file>
<file>image/W2P.png</file>
<file>image/P2T.png</file>
<file>image/T2P.png</file>
<file>image/Central.png</file>
<file>image/Tetra.png</file>
<file>image/TNE.png</file>
<file>image/GreenLamp.png</file>
<file>image/RedLamp.png</file>
<file>image/YellowLamp.png</file>
<file>image/ShowSend.png</file>
<file>image/Wls.png</file>
</qresource>
</RCC>
+59
View File
@@ -0,0 +1,59 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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)
{
// set range
uint16_t maxArraySize = a_field->maxArraySize();
setRange(0, maxArraySize);
// set the actual value
setValue(a_value);
// set tooltip-text
setToolTip(tr("<nobr>Wertebereich: 0..%1</nobr>").arg(maxArraySize));
// connect
connect(this, &LogViewSpinBox::editingFinished,
this, &LogViewSpinBox::finishEditing);
}
// ---------------------------------------------------------------
void LogViewSpinBox::finishEditing()
{
emit valueEditingFinished(text().toInt());
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewSpinBox::saveContent(LogViewTelegram* a_telegram)
{
Q_UNUSED(a_telegram);
// not yet implemented
return false;
}
} // namespace N_LogView
+60
View File
@@ -0,0 +1,60 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QSpinBox>
#include "LogViewWidget.hpp"
namespace N_LogView
{
/**
* Used for changing size of dyn. arrays.
*
* @author alois.wismer
* @version 1.0
* @created 25-Mai-2010 10:39:45
*/
class LogViewSpinBox : public QSpinBox, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_value
*/
LogViewSpinBox(LogViewField* a_field, QWidget* a_parent, const int a_value);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void finishEditing();
signals:
/**
*
* @param a_newValue
*/
void valueEditingFinished(int a_newValue);
};
}
+139
View File
@@ -0,0 +1,139 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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)
{
// add new tabs
for (int i = count(); i < a_newSize; i++)
addTab(m_Field, true, i);
// remove old tabs
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(); // fixme: funktioniert so nicht, muss als signal realisiert werden
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewTabWidget::saveContent(LogViewTelegram* a_telegram)
{
if (a_telegram->isJsonTelegram())
return true;
// if m_SpinBox is NULL, we have a static array => no size has to be stored
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);
// todo: sind nach dem dyn. array noch weitere Felder, so wird addTab nicht richtig funktionieren, weil die
// neuen Felder des Tabs am Ende von m_EditInfoList hinzugefügt werden => diese müssen mittendrin (an der richtigen
// position) eingefügt werden.
// update spinbox
if (m_SpinBox)
{
int spinValue = m_SpinBox->value();
if (spinValue < count())
m_SpinBox->setValue(count());
}
setVisible(true);
}
} // namespace N_LogView
+56
View File
@@ -0,0 +1,56 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QTabWidget>
#include "LogViewWidget.hpp"
namespace N_LogView
{
class LogViewTelegramDialog;
class LogViewSpinBox;
/**
* Used for arrays of structures
*
* @author alois.wismer
* @version 1.0
* @created 26-Mai-2010 17:12:30
*/
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:
/**
*
* @param a_newSize
*/
void changeSize(const int a_newSize);
protected:
LogViewTelegramDialog* m_TelegramDialog;
LogViewSpinBox* m_SpinBox;
};
}
+311
View File
@@ -0,0 +1,311 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#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);
// make pretty
// horizontalHeader()->setResizeMode(2, QHeaderView::Stretch);
updateToolTip();
// for debugging only
// INFO_LOG(m_logger) << "type=" << static_cast<const LogViewXdrStandardType*>(a_field->getXdrElement())->getValueKind();
// INFO_LOG(m_logger) << "name=" << static_cast<const LogViewXdrStandardType*>(a_field->getXdrElement())->getName().toStdString();
// a_field->getXdrElement()->dump();
// fill in the values
// fixme: implementiere den Fall isHasContent() false
int nbrOfRows = a_field->valueListSize();
setRowCount(nbrOfRows);
for (int i = 0; i < nbrOfRows; i++)
changeRow(i, a_field->value(i));
makePretty();
// connect signals
connect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
void LogViewTableWidget::changeSize(const int a_newSize)
{
setRowCount(a_newSize);
disconnect(this, &LogViewTableWidget::itemChanged,
this, &LogViewTableWidget::checkAndOvertakeContent);
// check and set the new fields
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)
{
// INFO_LOG(m_logger) << "a_rowIndex=" << a_rowIndex << " a_value=" << a_value.toStdString();
if (m_IsEnum)
{
// enum
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());
// decimal
QTableWidgetItem* decItem = item(a_rowIndex, 0);
if (!decItem)
{
decItem = new QTableWidgetItem();
//decItem->setData(Qt::DisplayRole, 0);
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);
}
// hexadecimal
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);
}
// binary
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);
}
}
// set the values
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;
// get the calculated and checked value
if (m_IsFloat)
floatValue = getFloat(text, (uint64_t&)intValue, ok, true);
else
intValue = getInteger(text, ok);
// handle errors
if (!ok)
{
setFocus();
// selectAll();
setCurrentCell(row, 0); // todo: funktioniert nicht
return;
}
// set the decimal value
QTableWidgetItem* decField = item(row, 0);
if (decField) decField->setText(QString::number(m_IsFloat ? floatValue : intValue));
// set the hex value
QTableWidgetItem* hexField = item(row, 1);
if (hexField) hexField->setText(toHex(intValue));
// set the binary value
if (!m_IsFloat)
{
QTableWidgetItem* binField = item(row, 2);
if (binField) binField->setText(toBin(intValue));
}
}
// ---------------------------------------------------------------
void LogViewTableWidget::makePretty()
{
//horizontalHeader()->setResizeMode(2, QHeaderView::Stretch);
resizeColumnsToContents();
resizeRowsToContents();
// set the height of table-widget
//// QWidget* cellWdg = tableWidget->cellWidget(0, 0);
// int showRows = 7;
// if (m_Field->getValueListSize() < (showRows-1))
// {
// showRows = m_Field->getValueListSize()+1;
// setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// }
// else
// {
// setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// }
// setFixedHeight(showRows*tableWidget->rowHeight(0));
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
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);
// fixme: bei vielen Telegrammen muss Länge auf die Länge des Textes gesetzt werden. Dies kann nicht automatisch gemacht werden. Aber vielleicht kann man schauen, ob vor dem dyn. Array ein Feld Länge vorkommt, oder hartcodieren, oder konfigurierbaren
}
else
{
// todo: teste mit opaque[]
arraySize = m_Field->maxArraySize();
}
// copy the data
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;
}
} // namespace N_LogView
+55
View File
@@ -0,0 +1,55 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QTableWidget>
#include "LogViewWidget.hpp"
namespace N_LogView
{
/**
* Used for arrays of data (opaque)
*
* @author alois.wismer
* @version 1.0
* @created 25-Mai-2010 09:34:24
*/
class LogViewTableWidget : public QTableWidget, public LogViewWidget
{
Q_OBJECT
public:
LogViewTableWidget(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
public slots:
void changeSize(const int a_newSize);
protected:
void changeRow(const int a_rowIndex, const QString& a_value);
void makePretty();
protected slots:
void checkAndOvertakeContent(QTableWidgetItem* a_changedItem);
private:
bool m_IsFloat;
bool m_IsEnum;
};
}
File diff suppressed because it is too large. Load diff
+487
View File
@@ -0,0 +1,487 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
/**
* The header and the data of a logged or a edited telegram.
*
* Writing telegrams:
* 1. allocate a telegram with the constructor LogViewTelegram(N_CoPrtCnv::
* CoPrtCnvLogHeader::e_DestProtocolCentral, telegramId)
* 2. prepare with resetOffset()
* 3. write data with setUIntX()
* 4. finish with setNewSize();
*
* @author alois.wismer
* @version 1.0
* @created 04-Feb-2010 13:15:43
*/
class LogViewTelegram final
{
public:
/**
* @author alois.wismer
* @version 1.0
* @created 12-Mrz-2010 11:04:14
*/
enum E_Validity
{
e_NotYetEvaluated,
e_Valid,
e_Invalid
};
/**
* @author alois.wismer
* @version 1.0
* @created 05-Mai-2010 09:07:22
*/
enum E_Column
{
e_ColName,
e_ColGpsTime,
e_ColLogTime,
e_ColJsonData,
e_ColMax
};
~LogViewTelegram();
/**
* The size of the field which defines the size of the dyn. array for central-
* telegrams
*/
static const uint16_t SIZE_CENTRAL_DYN_ARRAY_SIZE;
/**
* Copy ctor
*/
LogViewTelegram(const LogViewTelegram &o);
// no assignment (needed)
LogViewTelegram &operator=(const LogViewTelegram &o) = delete;
/**
* Constructor for new telegrams (only receive central-telegrams are allowd),
* which will be edited
*
* @param a_destination
* @param a_telId
*/
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
int telegramId);
/**
* Constructor for existing telegrams
*
* @param a_destination
* @param a_unixTime
* @param a_telegramData
* @param a_telegramSize
*/
LogViewTelegram(const N_CoPrtCnv::CoPrtCnvLogHeader::E_CoPrtCnvProtocol a_destination,
const quint64 a_unixTime,
const QByteArray &a_telegramData);
/**
* Writes a_value with size a_size at actual position of m_Data (given with
* m_ActOffset). m_ActOffset will be updated after writing data.
* If the size of m_Data is not big enough, it will be made bigger.
*
* @param a_size
* @param a_value
* @param a_byteOrder
*/
void setUIntX(const uint8_t a_size,
quint64 a_value,
const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian);
/**
* Returns true if a_data could be written.
* Returns false if a_offset is outside of range and therefore a_data could not be
* written.
*
* @param a_offset
* @param a_data
*/
bool setData(const uint16_t a_offset, const uint8_t a_data);
/**
* Returns the log-time of the telegram
*/
quint64 getLogTime() const { return m_LogTime; }
quint64 getLogTimeMsec() const;
/**
* Returns the log-time of the telegram as pretty formatted text
*/
QString getLogTimeText() const;
QString getDestinationText() const;
/**
* Returns the gps-time of the telegram
*/
quint64 getGpsTime() const { return m_GpsTime; }
/**
* Returns the GPS-time of the telegram as pretty formatted text. Only telegrams
* from TETRA to central have a GPS-time, for all other telegrams an empty string
* will be returned.
*/
QString getGpsTimeText() const;
uint32_t getISSI() const { return m_ISSI; }
int getParticipantId() const { return m_ParticipantId; }
/**
* Returns the difference between GPS-time and log-time in seconds. Only telegrams
* from TETRA to central have a GPS-time (and therefore only for this telegrams a
* time-difference can be calculated), for all other telegrams 0 will be returned.
*/
int32_t getDelay() const;
/**
* Returns the tool-tip text for the with a_col defined column for this telegram.
* Its content depends on the type and subtype of telegram.
*
* @param a_col
*/
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;
/**
* The time to wait after sending this telegram in milliseconds.
*/
uint32_t getWaitTime() const { return m_WaitTime; }
/**
* The time to wait after sending this telegram in milliseconds.
*
* @param newVal
*/
void setWaitTime(uint32_t newVal) { m_WaitTime = newVal; }
/**
* The name of the telegram, shown in edit-list
*/
QString getName() const { return m_Name; }
/**
* The name of the telegram, shown in edit-list
*
* @param newVal
*/
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();
/**
* Create the tooltip text for the column 'Name'
*/
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:
/**
* The name of the telegram, shown in edit-list
*/
QString m_Name;
/**
* The tooltip text for caching purposes
*/
std::vector<QString> m_ToolTipText;
/**
* The time to wait after sending this telegram in milliseconds.
*/
uint32_t m_WaitTime;
int m_ParticipantId;
/**
* The ISSI of TETRA-Protocol
*/
uint32_t m_ISSI;
/**
* The allocated size of m_Data. (Used for optimizing of speed)
*/
int m_AllocatedSize;
static const LogViewXdrParser* m_Parser;
uint16_t m_ActOffset;
QVector<uint16_t> m_GpsFieldOffset;
int m_TelId;
/**
* used for dyn. array in TETRA-Protocol
*/
uint32_t m_LastUnsignedValue;
/**
* This value will be used for the dyn-array-method e_DynArrayMsgLength. This
* value will be subtracted from the message-length to get the size of the dynamic
* array.
*/
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);
/**
*
* @param a_offset
*/
uint16_t getUInt16(const uint16_t a_offset) const;
/**
*
* @param a_offset
*/
uint32_t getUInt32(const uint16_t a_offset) const;
/**
*
* @param a_offset
*/
int32_t getInt32(const uint16_t a_offset) const;
/**
*
* @param a_offset
* @param a_size
* @param a_byteOrder
*/
quint64 getUIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
/**
*
* @param a_offset
* @param a_size
* @param a_byteOrder
*/
int32_t getSIntX(const uint16_t a_offset, const uint8_t a_size, const LogViewXdrStandardType::E_ByteOrder a_byteOrder = LogViewXdrStandardType::e_ByteOrderBigEndian) const;
/**
*
* @param a_offset
* @param a_size
*/
char getChar(const uint16_t a_offset, const uint8_t a_size) const;
/**
*
* @param a_standardType
* @param a_offset
* @param a_arraySize
*/
LogViewField* getContent(const LogViewXdrStandardType* a_standardType, uint16_t& a_offset, const uint16_t a_arraySize);
/**
*
* @param a_xdrType
*/
bool isScalar(const LogViewXdrType* a_xdrType) const;
/**
*
* @param a_errorText
* @param a_title
*/
void showMessageBox(const QString& a_errorText, const QString& a_title = QObject::tr("Invalid telegram")) const;
/**
*
* @param a_offset
*/
uint16_t getDynArraySize(uint16_t& a_offset) const;
/**
*
* @param a_name
* @param a_value
*/
static QString formatToolTipLine(const QString& a_name, const uint32_t a_value)
{
return formatToolTipLine(a_name, QString::number(a_value), a_value);
}
/**
*
* @param a_name
* @param a_text
* @param 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);
}
/**
* returns the data-byte at a_offset. Returns 0 if a_offset is outside of range.
*
* @param a_offset
*/
uint8_t getData(const uint16_t a_offset) const;
private:
/**
* The logger object
*/
NGL::INGLLogger &m_logger;
friend class LogViewTabWidget;
};
}
+497
View File
@@ -0,0 +1,497 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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
{
// todo:
// - feld einfärben wenn geändert, wenn falsch
// - mache hartcodierte oder konfigurierbare ranges für spezielle Werte wie GPS-Position: signed 24-bit
// ---------------------------------------------------------------
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)
{
// edit wait-time
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);
// edit name
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);
}
//INFO_LOG(m_logger) << "--------------- create dialog " << fieldTree->getName().toStdString() << "--------------";
//m_fieldTree->dump();
showTree(m_fieldTree.data(), dialogLayout);
if (this->findChild<LogViewTableWidget *>() == nullptr)
dialogLayout->setRowStretch(dialogLayout->rowCount(), 1);
// build the dialog
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// make dialog scrollable
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);
// buttons
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)
// show error-message in dialog
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())));
// generate the telegram-dump
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;
// set the size and position of dialog
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);
//QRect winGeo = geometry();
int newWidth = std::min(width() + wDiff + sbWidth, screenSize.width() * 9 / 10);
int newHeight = std::min(height() + hDiff, screenSize.height() * 9 / 10);
//setGeometry(winGeo);
//QSize size = settings.value(SIZE, sizeHint()).toSize();
resize(QSize(newWidth, newHeight));
//move(settings.value(POS, QPoint(0, 0)).toPoint());
// --------------------------------------------------------------------
}
// ---------------------------------------------------------------
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) << "******************************************";
// check whether all changed values are valid
// ------------------------------------------
for (const auto ptr : qAsConst(m_EditInfoList))
{
if (!ptr->isValid())
{
INFO_LOG(m_logger) << ptr->field()->name() << " is invalid";
return; // abort when a value is not vaild
}
}
// now save the values
// -------------------
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());
// save wait-time and name
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); // TODO: Status ob wirklich möglich ggf. überprüfen
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);
// fixme: absturz, wenn feld ungültiger wert enthält und ok gedrückt wird
connect(btnOk, &QPushButton::clicked, this, &LogViewTelegramDialog::saveTelegram);
a_layout->addWidget(btnOk);
}
}
// ---------------------------------------------------------------
void LogViewTelegramDialog::showEditField(LogViewField *a_logViewField, QGridLayout *a_box)
{
// INFO_LOG(m_logger) << a_logViewField->getName() <<
// << " a_logViewField->getValueListSize()=" << a_logViewField->getValueListSize()
// << " a_logViewField->isIsDynamicArray()=" << a_logViewField->isIsDynamicArray()
// << " a_logViewField->getValue(0)=" << a_logViewField->getValue(0).toStdString()
// << " a_logViewField->getXdrElement())->getValueKind()=" << (int)(static_cast<const LogViewXdrStandardType*>(a_logViewField->getXdrElement())->getValueKind())
// ;
switch (a_logViewField->valueListSize())
{
case 1:
// 1 field (single or multi-line)
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;
//QString value = a_logViewField->getValue(0);
// if (-1 == value.indexOf("<br>") && value.length() < 80)
{
// single line
// -----------
if (LogViewXdrElement::e_KindEnum == a_logViewField->xdrElement()->getKind())
{
// enum => combobox
// ----------------
valueWidget = new LogViewEnumEdit(a_logViewField, this, m_ReadOnly, 0);
}
else
{
if (a_logViewField->isDateTimeField() || a_logViewField->isMSecsField())
{
// date-time-field
// ---------------
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: // Text
valueWidget = new LogViewTextEdit(a_logViewField, this, m_ReadOnly);
break;
}
}
}
if (valueWidget)
m_EditInfoList.push_back(valueWidget);
}
// else
// {
// // ----------------------------------------------------------------
// // fixme: not used => take away
// // multi-line
// valueWidget = new QTextEdit(value);
// static_cast<QTextEdit*>(valueWidget)->setReadOnly(true);
// // make proper width of widget
// QFontMetrics fm(valueWidget->font());
// // the 0 (at end) are here, because QFontMetrics does not understand the <code> and <b> tags.
// // So not the correct font will be used for calculating the width.
// // The solution here is suboptimal, but will hopefully work with a lot of fonts...
// valueWidget->setMinimumWidth(fm.width("0000: 00 00 00 00 00 00 00")*1.7);
// // ----------------------------------------------------------------
// }
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;
}
// fall through for not read-only and dyn. array
Q_FALLTHROUGH();
case 0:
if (m_ReadOnly)
{
// no field
a_box->addWidget(new QLabel(tr("Keine %1").arg(a_logViewField->cleanName())));
break;
}
// fall through for not read-only
Q_FALLTHROUGH();
default:
{
// show the title of table
QLabel *label = new QLabel(a_logViewField->cleanName());
a_box->addWidget(label, a_box->rowCount(), 0);
// show the spin-box for changing the dyn. array-size
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);
}
// show the table for changing the array-values
LogViewTableWidget *tableWidget = new LogViewTableWidget(a_logViewField, this, m_ReadOnly);
m_EditInfoList.push_back(tableWidget);
a_box->addWidget(tableWidget, a_box->rowCount(), 0, 1, 2);
// connect signals
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())
{
// show the spin-box for changing the dyn. array-size
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);
// connect signals
if (spinBox)
{
connect(spinBox, &LogViewSpinBox::valueEditingFinished,
a_tabWidget, &LogViewTabWidget::changeSize);
}
// add the tab
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;
}
} // namespace N_LogView
+81
View File
@@ -0,0 +1,81 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
/**
* @author alois.wismer
* @version 1.0
* @created 09-Feb-2010 15:05:05
*/
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);
/**
* Removes the elements from m_EditInfoList matching the path
*/
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;
};
}
+591
View File
@@ -0,0 +1,591 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#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;
// add, edit and remove telegrams
// ------------------------------
menu.addAction(m_addTeleAction);
menu.addAction(m_editTeleAction);
menu.addAction(m_copyTeleAction);
menu.addAction(m_pasteTeleAction);
menu.addAction(m_deleteTeleAction);
// move telegram up/down
// ---------------------
menu.addSeparator();
menu.addAction(m_moveTeleUpAction);
menu.addAction(m_moveTeleDownAction);
menu.addSeparator();
const bool itemSelected = m_tableView->currentIndex().isValid();
// is it a central-telegram?
bool isCentral = false;
QSharedPointer<LogViewTelegram> tele = m_EditModel->telegram(m_tableView->currentIndex().row());
if (tele)
isCentral = (tele->getProtocol() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral);
// inject telegram
// ---------------
if (isInjectionPossible())
{
QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm"));
// only central-telegrams can be injected
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram);
action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm"));
// only central-telegrams can be injected
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram);
menu.addSeparator();
// send and loop telegrams
// -----------------------
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm"));
// only central-telegrams can be sent
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);
// load/save telegram-list
// -----------------------
menu.addSeparator();
}
menu.addAction(m_teleListLoad);
menu.addAction(m_teleListAppend);
menu.addAction(m_teleListSave);
menu.exec(m_tableView->viewport()->mapToGlobal(pos));
}
// ---------------------------------------------------------------
// Adds a_telegram at a_row in table. If there is already a
// telegram it will be overwritten.
// If a_row is -1, the telegram will be added at end.
// If false is false, a_telegram will be ignored, a
// dialog for selecting an empty telegram will be shown
// instead.
// ---------------------------------------------------------------
void TelegramEdit::addTelegram()
{
// add telegram for editing
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);
// show the edit-telegram-dialog
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()
{
//model über geänderte Daten informieren
m_EditModel->emitDataChanged(m_curEditTelegramRow);
}
// ---------------------------------------------------------------
// shows a telegram-dialog, where the telegram can be changed.
// ---------------------------------------------------------------
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());
}
// ---------------------------------------------------------------
// shows a non-editable telegram-dialog
// ---------------------------------------------------------------
void TelegramEdit::showTelegram()
{
LogViewTelegramDialog *showTelegramDialog = new LogViewTelegramDialog(m_tableView, true);
showTelegramDialog->showDialog(currentSelectedTelegram());
//
// qulonglong dataPtr = m_TelegramTableWidget->item(a_tableWidget->row(), 0)->data(Qt::UserRole).toULongLong();
// LogViewTelegram* telegram = (LogViewTelegram*)dataPtr;
// LogViewTelegramDialog* telegramDialog = new LogViewTelegramDialog(this);
// telegramDialog->showDialog(telegram);
}
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()
{
//gucken ob loop schon gestartet oder nicht
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;
// am Ende ?
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) // invalid index
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()
{
// get the filename
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");
// save the actual directory
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
// save the telegram-list
QFile telegramFile(newFilename);
telegramFile.open(QIODevice::WriteOnly);
QDataStream stream(&telegramFile);
// write the header
uint32_t version = 1;
stream << s_TELEGRAMLIST_FILE_ID() << version;
// write the telegrams
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)
{
// get the filename
QSettings settings;
QString newFilename = QFileDialog::getOpenFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
settings.value(s_DIR()).toString(),
s_TELEGRAMLIST_FILES());
if (!newFilename.isEmpty())
{
// save the actual directory
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
// delete the actual telegram-list
{
if (!checkAppend)
m_EditModel->clearTelegrams();
}
// load the telegram-list
QFile telegramFile(newFilename);
telegramFile.open(QIODevice::ReadOnly);
QDataStream stream(&telegramFile);
// read the header
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;
}
// read the telegrams
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);
}
} // namespace N_LogView
+126
View File
@@ -0,0 +1,126 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#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,168 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#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; // row
}
// ---------------------------------------------------------------
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());
// von oben her löschen um ein Verschieben der Indizes zu vermeiden
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();
}
} // namespace N_LogView
@@ -0,0 +1,49 @@
/**
* @RDE_HEADER@
* some models for LogViewGui
* $Id$
* $HeadURL$
* $Author$
*/
#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 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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) // ACK
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();
}
} // namespace N_LogView
@@ -0,0 +1,53 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QDialog>
class QListWidget;
class QListWidgetItem;
namespace N_LogView
{
/**
* @author alois.wismer
* @version 1.0
* @created 05-Mai-2010 17:24:14
*/
class LogViewTelegramSelectionDialog : public QDialog
{
Q_OBJECT
public:
/**
*
* @param a_parent
*/
explicit LogViewTelegramSelectionDialog(QWidget* a_parent);
int getSelectedTelegramId() const { return m_SelectedTelegramId; }
protected slots:
/**
*
* @param a_telegramItem
*/
void selectTelegram(QListWidgetItem* a_telegramItem);
protected:
QListWidget *m_TelegramList;
int m_SelectedTelegramId;
};
}
@@ -0,0 +1,521 @@
/**
* Parses training_area_telegrams.h
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#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); // base first
}
bool LogViewTetraTelegramsParser::parse(const QString &filename)
{
m_telegramIdEnum = EnumInformation();
m_enums.clear();
m_structs.clear();
//m_pods.clear(); // only set once
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(';'))) // forward decl
return iStartPos; // move to next line
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('>'))) // helper template - ignore
{
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("::")))
{
// fixup ns
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(';'))) // forward decl
return iStartPos; // move to next line
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)
{
// enum in struct with direct decl of member
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")) // static constexpr TelegramId id() { return TelegramId::INIT; }
{
++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("//")))
{
// all comment after this - merge into one
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;
}
} // namespace N_LogView
@@ -0,0 +1,94 @@
/**
* Parses training_area_telegrams.h
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-04-14
*/
#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; // we only allow one base...
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;
};
} // namespace LogView
+96
View File
@@ -0,0 +1,96 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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);
}
// set a validator for number of chars
uint16_t maxArraySize = a_field->maxArraySize();
setMaxLength(maxArraySize);
updateToolTip(value);
// make proper width of widget
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 signals
connect(this, &LogViewTextEdit::editingFinished,
this, &LogViewTextEdit::checkAndOvertakeContent);
}
// ---------------------------------------------------------------
void LogViewTextEdit::checkAndOvertakeContent()
{
updateToolTip(text()); // fixme nach jedem zeichen updaten
m_Valid = true;
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
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);
// fixme: bei vielen Telegrammen muss Länge auf die Länge des Textes gesetzt werden. Dies kann nicht automatisch gemacht werden. Aber vielleicht kann man schauen, ob vor dem dyn. Array ein Feld Länge vorkommt, oder hartcodieren, oder konfigurierbaren
}
else
{
arraySize = m_Field->maxArraySize();
}
// copy the text
for (int i = 0; i < arraySize; i++)
a_telegram->setUIntX(size, i < content.length() ? content[i].toLatin1() : 0);
}
return true;
}
} // namespace N_LogView
+53
View File
@@ -0,0 +1,53 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewWidget.hpp"
#include <QLineEdit>
namespace N_LogView
{
/**
* Used for arrays of char and string.
*
* @author alois.wismer
* @version 1.0
* @created 21-Mai-2010 10:28:05
*/
class LogViewTextEdit : public QLineEdit, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
*/
LogViewTextEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected slots:
void checkAndOvertakeContent();
};
}
+135
View File
@@ -0,0 +1,135 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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);
// checkAndOvertakeContent();
updateToolTip(valueText);
// make proper width of widget
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;
// get the calculated and checked value
if (m_IsFloat)
floatValue = getFloat(text(), (uint64_t&)intValue, ok);
else
intValue = getInteger(text(), ok);
// handle errors
if (!ok)
{
setFocus();
selectAll();
return; // abort
}
// update
if (m_IsFloat)
setText(QString::number(floatValue));
else
setText(QString::number(intValue));
updateToolTip(text());
}
// ---------------------------------------------------------------
// Writes the content into telegram.
// Returns true if successful.
// ---------------------------------------------------------------
bool LogViewValueEdit::saveContent(LogViewTelegram* a_telegram)
{
if (m_Valid)
{
bool ok;
if (m_IsFloat)
{
// save the float or double-value
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
{
// save the integer-value
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;
}
} // namespace N_LogView
+57
View File
@@ -0,0 +1,57 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewWidget.hpp"
#include <QLineEdit>
namespace N_LogView
{
/**
* Used for scalar signed or unsigned values
*
* @author alois.wismer
* @version 1.0
* @created 20-Mai-2010 14:47:50
*/
class LogViewValueEdit : public QLineEdit, public LogViewWidget
{
Q_OBJECT
public:
/**
*
* @param a_field
* @param a_parent
* @param a_readonly
*/
LogViewValueEdit(LogViewField* a_field, QWidget* a_parent, const bool a_readonly);
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
bool saveContent(LogViewTelegram* a_telegram) override;
protected:
bool m_IsFloat;
protected slots:
void checkAndOvertakeContent();
};
}
+230
View File
@@ -0,0 +1,230 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#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
{
// todo: check whether really a standardtype
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
{
// fixme: bei 3-byte werten werden fälschlicherweise 4 Bytes angezeigt
if (m_Field->isDateTimeField())
{
m_Widget->setToolTip(QObject::tr("Unixzeit: %1 ").arg(a_text));
}
else
{
m_Widget->setToolTip(QString());
}
// actual value in hex and binary
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)));
}
// range
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)
{
// INFO_LOG(m_logger) << "a_text=" << a_text.toStdString();
//LogViewXdrStandardType::E_ByteOrder byteOrder = ((LogViewXdrStandardType*)m_Field->xdrElement())->getByteOrder();
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);
}
// show error-message
// fixme zeige fehler genauer
if (!a_ok)
showMessageBox(QStringLiteral("Inalid real value: '%1'").arg(a_text));
m_Valid = a_ok;
// swap for display data on table
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--;
}
}
// set the upper 4 bytes to 0 for float
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;
}
// ---------------------------------------------------------------
// Converts a_text into a signed integer and returns it. The
// parameter a_ok will be true if all was successful. The
// attribute m_Valid will be set to a_ok.
// The range will be checked, if the value is out of range, an
// error will be shown as messge-box and a_ok will be false.
// The input a_text can be a calculation.
// ---------------------------------------------------------------
int64_t LogViewWidget::getInteger(const QString& a_text, bool& a_ok)
{
// calculate the expression into a number
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)
{
// todo: show exact error-message
if (a_text != m_LastErrorValueText)
{
showMessageBox(QString::fromUtf8("Die Berechnung '%1' ist falsch").arg(a_text));
m_LastErrorValueText = a_text;
}
a_ok = false;
}
else
{
// check the range
int64_t highest = m_Field->getHighestValue();
if (value > highest)
{
a_ok = false;
// fixme: dieser Trick mit m_LastErrorValueText ist für den Benutzer etwas verwirrend, da
// plötzlich keine Reaktion mehr auf Tab, Ok oder wählen eines anderen Feldes passiert...
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; // abort
}
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; // abort
}
m_Valid = true;
}
return value;
}
} // namespace N_LogView
+101
View File
@@ -0,0 +1,101 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
/**
* @author alois.wismer
* @version 1.0
* @created 20-Mai-2010 14:51:17
*/
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; }
/**
* The content if the field is a text-field
*/
QString getText() const { return m_Text; }
/**
* Writes the content into telegram.
* Returns true if successful.
*
* @param a_telegram
*/
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);
/**
* Converts a_text into a signed integer and returns it. The parameter a_ok will
* be true if all was successful. The attribute m_Valid will be set to a_ok.
* The range will be checked, if the value is out of range, an error will be shown
* as messge-box and a_ok will be false.
* The input a_text can be a calculation.
*
* @param a_text
* @param a_ok
*/
int64_t getInteger(const QString& a_text, bool& a_ok);
protected:
bool m_Readonly;
bool m_Valid;
/**
* The content if the field is a text-field
*/
QString m_Text;
QString m_LastErrorValueText;
QWidget *m_Widget;
LogViewField *m_Field;
QWidget *m_Parent;
NGL::INGLLogger &m_logger;
};
}
+61
View File
@@ -0,0 +1,61 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
// ---------------------------------------------------------------
// Constructor of a struct or enum
// ---------------------------------------------------------------
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());
}
} // namespace N_LogView
+72
View File
@@ -0,0 +1,72 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QString>
#include "logger.h"
namespace N_LogView
{
/**
* @author alois.wismer
* @version 1.0
* @created 05-Feb-2010 11:24:56
*/
class LogViewXdrElement
{
public:
/**
* @author alois.wismer
* @version 1.0
* @created 10-Feb-2010 11:34:47
*/
enum E_ElementKind
{
e_KindStandardType,
e_KindTypedef,
e_KindStruct,
e_KindStructElement,
e_KindEnum,
e_KindEnumElement,
e_KindDefine
};
virtual ~LogViewXdrElement() = default;
protected:
/**
* Constructor of a struct or enum
*
* @param a_name
* @param a_kind
*/
LogViewXdrElement(const QString& a_name, const E_ElementKind a_kind, const char *loggerName);
public:
const QString& getName() const { return m_Name; }
LogViewXdrElement::E_ElementKind getKind() const { return m_Kind; }
virtual void dump() const;
protected:
QString m_Name;
E_ElementKind m_Kind;
QString getKindName() const;
NGL::INGLLogger &m_logger;
};
}
File diff suppressed because it is too large. Load diff
+274
View File
@@ -0,0 +1,274 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
/**
* @author alois.wismer
* @version 1.0
* @created 05-Feb-2010 10:46:58
*/
class LogViewXdrParser : public N_SST::IntegerCalculator
{
public:
/**
* Defines in which structure the parser is parsing now
*
* @author alois.wismer
* @version 1.0
* @created 08-Feb-2010 17:44:52
*/
enum E_ParseState
{
e_ParseMain,
e_ParseStruct,
e_ParseEnum,
e_ParseUnion
};
LogViewXdrParser();
~LogViewXdrParser();
/**
*
* @param a_fileName
*/
void parseX_File(const QString& a_fileName);
/**
* This function delivers the name of the telegram.
* The telegram will be defined with a_telegramId.
* The name will be delivered as return-parameter.
* If the telegram was not found, error-texts instead names will be returned.
*
* @param a_telegramId
*/
QString getTelegramName(int a_telegramId) const;
/**
* This function delivers the structure name of the telegram.
* The telegram will be defined with a_telegramId.
* The structure name will be delivered as return-parameter
* If the telegram was not found, error-texts instead names will be returned.
*
* @param a_telegramId
*/
QString getStructName(int a_telegramId) const;
/**
*
* @param a_name
* @param a_value
*/
bool getDefine(const QString& a_name, int64_t& a_value) const;
/**
*
* @param a_name
*/
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;
/**
* This will be used to suppress an error-message when parsing the overall
* telegram structure.
*/
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;
/**
*
* @param a_name
* @param a_dataSize
* @param a_realSize
* @param a_kind
* @param a_dynArraySizeMethod
* @param a_byteOrder
*/
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);
/**
*
* @param a_line
*/
QString removeComments(const QString& a_line);
/**
*
* @param a_line
*/
void parseTypedef(const QString &a_line);
/**
*
* @param a_line
*/
void parseDefine(const QString &a_line);
/**
*
* @param a_line
* @param a_enumSize The size in bytes of an enum-value
*/
void parseEnum(const QString &a_line, const uint16_t a_enumSize = 4);
/**
*
* @param a_line
*/
void parseStruct(const QString &a_line);
/**
*
* @param a_line
*/
void parseUnion(const QString& a_line);
/**
*
* @param a_line
* @param a_name
* @param a_value
*/
bool parseEnumLine(const QString& a_line, QString& a_name, QString& a_value) const;
/**
* Shows an error-message containing the line-nbr, the line itself and an
* additional error-text
*
* @param a_errorText
*/
void showErrorMessage(const QString& a_errorText) const;
/**
*
* @param a_calcText
* @param a_isOk
*/
int64_t calcValue(const QString& a_calcText, bool& a_isOk);
/**
*
* @param a_variableName
* @param a_value
*/
bool getVariableValue(const std::string& a_variableName, int64_t& a_value) const override;
/**
*
* @param a_name
* @param a_dynArrayMsgOffset This offset will be used for the dyn-array-method
* e_DynArrayMsgLength. Here the value in <x> will be subtracted from the message-
* length to get the size of the dynamic array.
*/
uint16_t parseArray(QString& a_name, uint16_t& a_dynArrayMsgOffset) const;
/**
*
* @param a_word
* @param a_doIncrement
*/
bool isNextWord(const char *a_word, const bool a_doIncrement = true);
/**
*
* @param a_line
*/
void fillWordList(const QString& a_line);
/**
*
* @param a_errorText
*/
QString getNextWord(const char *a_errorText = nullptr);
/**
*
* @param a_ok
*/
QString getNextType(bool& a_ok);
/**
*
* @param a_enumStruct
*/
QString getNextEnum(const LogViewXdrStruct*& a_enumStruct);
/**
*
* @param a_fieldText
* @param a_firstBit
* @param a_lastBit
*/
bool parseBitfield(const QString& a_fieldText, int16_t& a_firstBit, int16_t& a_lastBit) const;
/**
* adds an element to the element-map if it does not already exist within this map.
*
* If it exists, an error-message will be raised instead and false will be
* returned.
*
* @param a_name
* @param a_element
*/
bool addToElementMap(const QString& a_name, LogViewXdrElement* a_element);
private:
/**
* The logger object
*/
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,84 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
// manual class headers
#include "LogViewXdrStandardType.hpp"
namespace N_LogView
{
// ---------------------------------------------------------------
// (a_valueKind must be Unsigned, if a_dynArraySizeMethod is
// e_DynArray...)
// ---------------------------------------------------------------
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;
}
// ---------------------------------------------------------------
// The 'real' size of the value, which will be allowd when
// editing this value
// ---------------------------------------------------------------
uint16_t LogViewXdrStandardType::getEditSize() const
{
return m_EditSize;
}
} // namespace N_LogView
+150
View File
@@ -0,0 +1,150 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
/**
* This class represents the standardtypes like int, char, ...
* It holds the the size of this type and its representation to user
* (signed/unsigned value or character)
*
* @author alois.wismer
* @version 1.0
* @created 16-Feb-2010 14:22:20
*/
class LogViewXdrStandardType final : public LogViewXdrElement
{
public:
/**
* @author alois.wismer
* @version 1.0
* @created 16-Feb-2010 14:34:38
*/
enum E_ValueKind
{
/**
* An unsigned 32-bit integer
*/
e_Unsigned,
/**
* An signed 32-bit integer
*/
e_Signed,
/**
* A floating-point number
*/
e_Float,
/**
* A character or string
*/
e_Character,
/**
* A boolean value
*/
e_Boolean,
/**
* Hex-Data "0000: F7 A5 07 ..."
*/
e_Data
};
/**
* @author alois.wismer
* @version 1.0
* @created 31-Mrz-2010 10:27:31
*/
enum E_ByteOrder
{
e_ByteOrderBigEndian,
e_ByteOrderLittleEndian
};
/**
* @author alois.wismer
* @version 1.0
* @created 29-Mrz-2010 13:58:44
*/
enum E_DynArraySizeMethod
{
/**
* Size of dyn array depends on message-size (size - m_DynArrayOffset) (or no dyn
* array)
* The value within <> in struct-element will be used for m_DynArrayOffset.
*/
e_DynArrayMsgLength,
/**
* Size of dyn array is defined by a field (StandardType must be Unsigned)
*/
e_DynArrayIndex,
/**
* Size of dyn array is defined by a field, which will be divided by 8 (used for
* bitfields) (StandardType must be Unsigned)
*/
e_DynArrayIndexDiv8
};
/**
* (a_valueKind must be Unsigned, if a_dynArraySizeMethod is e_DynArray...)
*
*/
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;
/**
* The 'real' size of the value, which will be allowd when editing this value
*/
uint16_t getEditSize() const;
protected:
/**
* The size of this value as stored data. It may be bigger as the real (edit) size.
*/
int m_ValueSize;
/**
* The 'real' size of the value, which will be allowd when editing this value
*/
int m_EditSize;
E_ValueKind m_ValueKind;
E_ByteOrder m_ByteOrder;
E_DynArraySizeMethod m_DynArraySizeMethod;
};
}
+105
View File
@@ -0,0 +1,105 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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)); // fixme: check ob es wirklich ein XdrType ist
}
// ---------------------------------------------------------------
LogViewXdrValue* LogViewXdrStruct::getChildAsValue(const uint32_t a_childIndex) const
{
return static_cast<LogViewXdrValue*>(getChild(a_childIndex)); // fixme: check ob es wirklich ein XdrValue ist
}
// ---------------------------------------------------------------
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;
}
} // namespace N_LogView
+65
View File
@@ -0,0 +1,65 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include <QtCore/QString>
#include "LogViewXdrElement.hpp"
#include <vector>
// forward declarations from stereotyped includes
namespace N_LogView
{
class LogViewXdrValue;
}
namespace N_LogView
{
class LogViewXdrType;
}
namespace N_LogView
{
/**
* This class represents elements which have childs.
* This are enum and struct.
* @author alois.wismer
* @version 1.0
* @created 31-Mrz-2010 11:59:19
*/
class LogViewXdrStruct final : public LogViewXdrElement
{
public:
LogViewXdrStruct(const QString& a_name, const LogViewXdrElement::E_ElementKind a_kind, uint16_t enumSize = 0);
~LogViewXdrStruct();
void addElement(const QString& a_name, const QString& a_type, const uint16_t a_arraySize, const uint16_t a_dynArrayOffset, const E_ElementKind a_kind, const int16_t a_firstBit = -1, const int16_t a_lastBit = -1, const bool a_isLast = true);
void addElement(const QString& a_name, const uint32_t a_value, const E_ElementKind a_kind);
LogViewXdrElement* getChild(const uint32_t a_childIndex) const;
LogViewXdrType* getChildAsType(const uint32_t a_childIndex) const;
LogViewXdrValue* getChildAsValue(const uint32_t a_childIndex) const;
void dump() const override;
uint32_t getChildValue(const QString& a_name, bool* a_error = nullptr) const;
uint16_t getEnumSize() const { return m_EnumSize; }
protected:
uint16_t m_EnumSize;
std::vector<LogViewXdrElement*> m_ChildList;
};
}
+106
View File
@@ -0,0 +1,106 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
}
// ---------------------------------------------------------------
// 0 => opaque
// 1 => normal (scalar) element
// >1 => array
// ---------------------------------------------------------------
uint16_t LogViewXdrType::getArraySize() const
{
return m_ArraySize;
}
// ---------------------------------------------------------------
bool LogViewXdrType::maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const
{
// INFO_LOG(m_logger) << "firstBit=" << m_FirstBit << " lastBit=" << m_LastBit << " isLast=" << m_IsLast;
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;
// INFO_LOG(m_logger) << "value=" << a_value << " bitshift=" << bitshift << " mask=" << mask;
a_value = (a_value >> bitshift) & mask;
// make bold the corresponding bits in the bitfield
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;
}
} // namespace N_LogView
+111
View File
@@ -0,0 +1,111 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
/**
* This class represents XDR-elements which have a type and an arraySize. This are
* typedefs and struct-elements.
* The arraySize has following possibilities:
* 0 => opaque
* 1 => scalar
* >1 => array
*
* @author alois.wismer
* @version 1.0
* @created 16-Feb-2010 15:48:24
*/
class LogViewXdrType final : public LogViewXdrElement
{
public:
/**
*
* @param a_name
* @param a_type
* @param a_arraySize
* @param a_dynArrayOffset
* @param 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);
/**
*
* @param a_name
* @param a_type
* @param a_arraySize
* @param a_dynArrayOffset
* @param a_kind
* @param a_firstBit
* @param a_lastBit
* @param a_isLast
*/
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;
/**
* 0 => opaque
* 1 => normal (scalar) element
* >1 => array
*/
uint16_t getArraySize() const;
/**
*
* @param a_value
* @param a_size
* @param a_tooltip
*/
bool maskValue(uint32_t& a_value, const uint16_t a_size, QString& a_tooltip) const;
uint16_t getMaxArraySize() const;
protected:
QString m_Type;
/**
* 0 => opaque
* 1 => normal (scalar) element
* >1 => array
*/
uint16_t m_ArraySize;
/**
* The maximum size of the array. Interesting for dynamic arrays.
*/
uint16_t m_MaxArraySize;
/**
* The first relevant bit, if we have bitfield-enum
*/
int16_t m_FirstBit;
/**
* The last relevant bit, if we have bitfield-enum
*/
int16_t m_LastBit;
/**
* used to step to next values when reading out content-data of bit-fields
*/
bool m_IsLast;
};
}
+40
View File
@@ -0,0 +1,40 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#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;
}
} // namespace N_LogView
+40
View File
@@ -0,0 +1,40 @@
// **************************************************************************
//
// (C) Copyright 2009 Swiss SIMTEC AG
//
// **************************************************************************
//
// $HeadURL$
// $LastChangedBy$
// $LastChangedDate$
// $LastChangedRevision$
//
// **************************************************************************
#pragma once
#include "LogViewXdrElement.hpp"
namespace N_LogView
{
/**
* This class represents XDR-elements which have a value. This are #defines and
* enum-elements.
*
* @author alois.wismer
* @version 1.0
* @created 17-Feb-2010 11:17:53
*/
class LogViewXdrValue final : public LogViewXdrElement
{
public:
LogViewXdrValue(const QString& a_name, const int64_t a_value, const LogViewXdrElement::E_ElementKind a_kind);
void dump() const override;
int64_t getValue() const;
protected:
int64_t m_Value;
};
}
+17
View File
@@ -0,0 +1,17 @@
log4j.reset=true
log4j.rootLogger=INFO, C
log4j.rootLogger=INFO, F
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.F=org.apache.log4j.RollingFileAppender
log4j.appender.F.File=${LOG4QT_LOGDIR}/${LOG4QT_USER}_LogView.log
log4j.appender.F.MaxFileSize=10MB
# Keep one backup file
log4j.appender.F.MaxBackupIndex=5
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.F.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%-5p (%-20.20F:%04L) [%d{HH:mm:ss.SSS}] - %m%n
log4j.appender.F.layout.ConversionPattern=%-5p (%-20.20F:%04L) [%d{HH:mm:ss.SSS}] - %m%n
Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
*/
#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();
}
}
} // namespace LogView
+22
View File
@@ -0,0 +1,22 @@
/**
* @RDE_HEADER@
* Logging for AudioVideoManagement
* $Id$
* $HeadURL$
* $Author$
*/
#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());
}
} // namespace LogView
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff