Files
qt6-migration-pipeline/TetraIF/LogView/LogViewTelegramEdit.cpp
T
2026-07-14 12:07:36 +02:00

587 lines
18 KiB
C++

#include "LogViewTelegramEdit.hpp"
#include "LogViewInjectionThread.hpp"
#include "LogViewTelegramDialog.hpp"
#include "LogViewTelegramEditModel.hpp"
#include "LogViewTelegramSelectionDialog.hpp"
#include <CoPrtCnv/CoPrtCnvHexDumpHelper.hpp>
#include <QAction>
#include <QDir>
#include <QFileDialog>
#include <QHeaderView>
#include <QIcon>
#include <QMenu>
#include <QMessageBox>
#include <QModelIndex>
#include <QSettings>
#include <QTableView>
#include <QTimer>
namespace N_LogView
{
QString TelegramEdit::s_DIR()
{
return QStringLiteral("Dir");
}
QString TelegramEdit::s_EDIT_TELEGRAM_GROUP()
{
return QStringLiteral("EditTelegrams");
}
QString TelegramEdit::s_TELEGRAMLIST_FILE_ID()
{
return QStringLiteral("RDETGL");
}
QString TelegramEdit::s_TELEGRAMLIST_FILES()
{
return tr("Telegrammliste-Dateien (*.tgl);;Alle Dateien (*)");
}
TelegramEdit::TelegramEdit(QWidget *parent)
: QObject(parent)
, m_addTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-add.png")), tr("Add Telegram"), this))
, m_editTeleAction(new QAction(QIcon(QLatin1String(":/image/Edit.png")), tr("Edit Telegram"), this))
, m_copyTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-copy.png")), tr("Copy Telegram"), this))
, m_pasteTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/edit-paste.png")), tr("Paste Telegram"), this))
, m_deleteTeleAction(new QAction(QIcon(QLatin1String(":icons/16x16/list-remove.png")), tr("Delete Telegram"), this))
, m_moveTeleUpAction(new QAction(QIcon(QLatin1String(":icons/16x16/go-up.png")), tr("Move up"), this))
, m_moveTeleDownAction(new QAction(QIcon(QLatin1String(":icons/16x16/go-down.png")), tr("Move down"), this))
, m_teleListLoad(new QAction(QIcon(QLatin1String(":icons/16x16/document-open-data.png")), tr("Load Telegram list"), this))
, m_teleListAppend(new QAction(QIcon(), tr("Telegrammliste anhaengen"), this))
, m_teleListSave(new QAction(QIcon(QLatin1String(":icons/16x16/document-save.png")), tr("Save Telegram list"), this))
, m_tableView(new QTableView(parent))
, m_DoLoop(false)
, m_InjectionThread(nullptr)
, m_EditModel(new TelegramEditModel(this))
, m_logger(getLogger("LogViewTelegramEdit"))
{
m_addTeleAction->setShortcut(tr("Ctrl+A"));
m_editTeleAction->setShortcut(tr("Ctrl+E"));
m_copyTeleAction->setShortcut(tr("Ctrl+C"));
m_pasteTeleAction->setShortcut(tr("Ctrl+V"));
m_deleteTeleAction->setShortcut(Qt::Key_Delete);
m_moveTeleUpAction->setShortcut(tr("Ctrl+U"));
m_moveTeleDownAction->setShortcut(tr("Ctrl+D"));
m_teleListLoad->setShortcut(tr("Ctrl+L"));
m_teleListAppend->setShortcut(tr("Ctrl+K"));
m_teleListSave->setShortcut(tr("Ctrl+S"));
m_addTeleAction->setEnabled(true);
m_copyTeleAction->setEnabled(false);
m_pasteTeleAction->setEnabled(false);
m_deleteTeleAction->setEnabled(false);
m_moveTeleUpAction->setEnabled(false);
m_moveTeleDownAction->setEnabled(false);
m_teleListLoad->setEnabled(true);
m_teleListAppend->setEnabled(true);
m_teleListSave->setEnabled(false);
connect(m_addTeleAction, &QAction::triggered, this, &TelegramEdit::addTelegram);
connect(m_editTeleAction, &QAction::triggered, this, &TelegramEdit::editTelegram);
connect(m_copyTeleAction, &QAction::triggered, this, &TelegramEdit::copy);
connect(m_pasteTeleAction, &QAction::triggered, this, &TelegramEdit::paste);
connect(m_deleteTeleAction, &QAction::triggered, this, &TelegramEdit::deleteTelegram);
connect(m_moveTeleUpAction, &QAction::triggered, this, &TelegramEdit::moveUp);
connect(m_moveTeleDownAction, &QAction::triggered, this, &TelegramEdit::moveDown);
connect(m_teleListLoad, &QAction::triggered, this, &TelegramEdit::loadTelegramListReplace);
connect(m_teleListAppend, &QAction::triggered, this, &TelegramEdit::loadTelegramListAppend);
connect(m_teleListSave, &QAction::triggered, this, &TelegramEdit::saveTelegramList);
m_tableView->setModel(m_EditModel);
m_tableView->verticalHeader()->hide();
m_tableView->setContextMenuPolicy(Qt::CustomContextMenu);
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &TelegramEdit::onSelectionChanged);
connect(m_tableView, &QTableView::doubleClicked,
this, &TelegramEdit::editTelegram);
connect(m_tableView, &QTableView::customContextMenuRequested,
this, &TelegramEdit::tableViewCustomContextMenu);
m_tableView->addAction(m_addTeleAction);
m_tableView->addAction(m_editTeleAction);
m_tableView->addAction(m_copyTeleAction);
m_tableView->addAction(m_pasteTeleAction);
m_tableView->addAction(m_deleteTeleAction);
m_tableView->addAction(m_moveTeleUpAction);
m_tableView->addAction(m_moveTeleDownAction);
}
void TelegramEdit::setInjectionThread(LogViewInjectionThread *a_injectionThread)
{
m_InjectionThread = a_injectionThread;
}
void TelegramEdit::appendTelegram(const QSharedPointer<LogViewTelegram> &telegram)
{
m_EditModel->appendTelegram(telegram);
m_teleListSave->setEnabled(true);
}
void TelegramEdit::tableViewCustomContextMenu(const QPoint &pos)
{
QMenu menu;
menu.addAction(m_addTeleAction);
menu.addAction(m_editTeleAction);
menu.addAction(m_copyTeleAction);
menu.addAction(m_pasteTeleAction);
menu.addAction(m_deleteTeleAction);
menu.addSeparator();
menu.addAction(m_moveTeleUpAction);
menu.addAction(m_moveTeleDownAction);
menu.addSeparator();
const bool itemSelected = m_tableView->currentIndex().isValid();
bool isCentral = false;
QSharedPointer<LogViewTelegram> tele = m_EditModel->telegram(m_tableView->currentIndex().row());
if (tele)
isCentral = (tele->getProtocol() == N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral);
if (isInjectionPossible())
{
QAction *action = menu.addAction(QIcon(QLatin1String(":/image/InjectCentral.png")), tr("Injektiere Zentral-Telegramm"));
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectCentralTelegram);
action = menu.addAction(QIcon(QLatin1String(":/image/InjectTetra.png")), tr("Injektiere Tetra-Telegramm"));
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::injectTetraTelegram);
menu.addSeparator();
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/mail-send.png")), tr("Sende Telegramm"));
action->setEnabled(itemSelected && isCentral);
connect(action, &QAction::triggered, this, &TelegramEdit::sendCurrentTelegram);
if (m_DoLoop)
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-stop.png")), tr("Stop Loopen"));
else
{
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-playback-start.png")), tr("Loop Telegramme"));
action->setEnabled(itemSelected);
}
connect(action, &QAction::triggered, this, &TelegramEdit::loopTelegrams);
action = menu.addAction(QIcon(QLatin1String(":icons/16x16/media-play-normal.png")), tr("Sende Sequenz"));
action->setEnabled(itemSelected);
connect(action, &QAction::triggered, this, &TelegramEdit::sequenceTelegrams);
menu.addSeparator();
}
menu.addAction(m_teleListLoad);
menu.addAction(m_teleListAppend);
menu.addAction(m_teleListSave);
menu.exec(m_tableView->viewport()->mapToGlobal(pos));
}
void TelegramEdit::addTelegram()
{
LogViewTelegramSelectionDialog telegramSelectionDialog(m_tableView);
if (QDialog::Accepted == telegramSelectionDialog.exec())
{
QSharedPointer<LogViewTelegram> newTelegram = QSharedPointer<LogViewTelegram>(new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral,
telegramSelectionDialog.getSelectedTelegramId()));
m_curEditTelegramRow = m_EditModel->appendTelegram(newTelegram);
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
connect(editTelegramDialog, &LogViewTelegramDialog::finished,
this, &TelegramEdit::editTelegramDialogFinished);
connect(editTelegramDialog, &LogViewTelegramDialog::sendTelegram,
this, &TelegramEdit::sendTelegram);
editTelegramDialog->showDialog(newTelegram);
m_teleListSave->setEnabled(true);
}
}
QSharedPointer<LogViewTelegram> TelegramEdit::currentSelectedTelegram() const
{
return m_EditModel->telegram(currentSelectedIndex().row());
}
QModelIndex TelegramEdit::currentSelectedIndex() const
{
return m_tableView->currentIndex();
}
void TelegramEdit::editTelegramDialogFinished()
{
m_EditModel->emitDataChanged(m_curEditTelegramRow);
}
void TelegramEdit::editTelegram()
{
m_curEditTelegramRow = currentSelectedIndex().row();
if (m_curEditTelegramRow < 0)
return;
LogViewTelegramDialog *editTelegramDialog = new LogViewTelegramDialog(m_tableView, false);
connect(editTelegramDialog, &LogViewTelegramDialog::finished, this, &TelegramEdit::editTelegramDialogFinished);
editTelegramDialog->showDialog(currentSelectedTelegram());
}
void TelegramEdit::showTelegram()
{
LogViewTelegramDialog *showTelegramDialog = new LogViewTelegramDialog(m_tableView, true);
showTelegramDialog->showDialog(currentSelectedTelegram());
}
void TelegramEdit::deleteTelegram()
{
const QModelIndexList indexList = m_tableView->selectionModel()->selectedIndexes();
QSet<int> rows;
rows.reserve(indexList.size());
for (const QModelIndex &index : indexList)
rows += index.row();
m_EditModel->removeTelegrams(rows);
m_teleListSave->setEnabled(m_EditModel->rowCount() > 0);
}
void TelegramEdit::injectCentralTelegram()
{
injectTelegram(true);
}
void TelegramEdit::injectTetraTelegram()
{
injectTelegram(false);
}
void TelegramEdit::injectTelegram(bool a_bAsCentralTelegram)
{
injectTelegram(currentSelectedTelegram(), a_bAsCentralTelegram);
}
void TelegramEdit::injectTelegram(const QSharedPointer<LogViewTelegram> &a_telegram, bool a_bAsCentralTelegram)
{
if (!isInjectionPossible())
{
WARNING_LOG(m_logger) << "Try to inject a telegramm but the injection thread is not running";
return;
}
if (a_telegram.isNull())
{
WARNING_LOG(m_logger) << "Try to inject a telegramm but no telegramm selected";
return;
}
a_telegram->actualizeGpsTime();
m_InjectionThread->sendTelegram(a_telegram.data(), a_bAsCentralTelegram);
}
void TelegramEdit::sendCurrentTelegram()
{
sendTelegram(currentSelectedTelegram());
}
void TelegramEdit::sendTelegram(const QSharedPointer<LogViewTelegram> &a_telegram)
{
injectTelegram(a_telegram, true);
}
void TelegramEdit::loopTelegrams()
{
if (m_DoLoop)
{
m_DoLoop = false;
m_deleteTeleAction->setEnabled(m_tableView->currentIndex().isValid());
}
else
{
m_DoLoop = true;
m_deleteTeleAction->setEnabled(false);
m_currentRowToSend = currentSelectedIndex().row();
if (m_currentRowToSend < 0)
return;
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::loopNextTelegram);
}
}
void TelegramEdit::loopNextTelegram()
{
if (!m_DoLoop)
return;
++m_currentRowToSend;
if (m_currentRowToSend >= m_tableView->model()->rowCount())
m_currentRowToSend = 0;
QSharedPointer<LogViewTelegram> tele = telegramAtRow(m_currentRowToSend);
if (!tele)
return;
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::loopNextTelegram);
}
void TelegramEdit::sequenceTelegrams()
{
m_currentRowToSend = currentSelectedIndex().row();
if (m_currentRowToSend < 0)
return;
QSharedPointer<LogViewTelegram> tele = currentSelectedTelegram();
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::sequenceNextTelegram);
}
void TelegramEdit::sequenceNextTelegram()
{
++m_currentRowToSend;
if (m_currentRowToSend >= m_tableView->model()->rowCount())
return;
QSharedPointer<LogViewTelegram> tele = telegramAtRow(m_currentRowToSend);
if (!tele)
return;
sendTelegram(tele);
QTimer::singleShot(tele->getWaitTime(), this, &TelegramEdit::sequenceNextTelegram);
}
QSharedPointer<LogViewTelegram> TelegramEdit::telegramAtRow(int row)
{
return m_EditModel->telegram(row);
}
void TelegramEdit::copy()
{
m_copyTelegram = currentSelectedTelegram();
m_pasteTeleAction->setEnabled(m_copyTelegram != nullptr);
if (!m_copyTelegram)
return;
m_copyTelegram = QSharedPointer<LogViewTelegram>(new LogViewTelegram(*m_copyTelegram.data()));
}
void TelegramEdit::paste()
{
if (!m_copyTelegram)
return;
int row = currentSelectedIndex().row() + 1;
m_EditModel->pasteRows(row, m_copyTelegram);
}
void TelegramEdit::moveUp()
{
const QModelIndex idx = currentSelectedIndex();
if (m_EditModel->moveUp(idx.row()))
{
m_tableView->clearSelection();
m_tableView->setCurrentIndex(m_EditModel->index(idx.row() - 1, idx.column(), idx.parent()));
m_moveTeleUpAction->setEnabled(idx.row() > 1);
m_moveTeleDownAction->setEnabled(true);
}
}
void TelegramEdit::moveDown()
{
const QModelIndex idx = currentSelectedIndex();
if (m_EditModel->moveDown(idx.row()))
{
m_tableView->clearSelection();
m_tableView->setCurrentIndex(m_EditModel->index(idx.row() + 1, idx.column(), idx.parent()));
m_moveTeleUpAction->setEnabled(true);
m_moveTeleDownAction->setEnabled(idx.row() < m_EditModel->rowCount() - 2);
}
}
void TelegramEdit::saveTelegramList()
{
QSettings settings;
QString newFilename = QFileDialog::getSaveFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
settings.value(s_DIR()).toString(),
s_TELEGRAMLIST_FILES());
if (!newFilename.isEmpty())
{
if (!newFilename.contains(QLatin1Char('.')))
newFilename += QLatin1String(".tgl");
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
QFile telegramFile(newFilename);
telegramFile.open(QIODevice::WriteOnly);
QDataStream stream(&telegramFile);
uint32_t version = 1;
stream << s_TELEGRAMLIST_FILE_ID() << version;
int rows = m_tableView->model()->rowCount();
stream << rows;
for (int i = 0; i < rows; i++)
{
QSharedPointer<LogViewTelegram> telegram = telegramAtRow(i);
if (!telegram)
continue;
const QByteArray &data = telegram->getData();
const QString name = telegram->getName();
const unsigned int waitTime = telegram->getWaitTime();
stream << waitTime
<< name
<< telegram->getGpsTimeField()
<< data.size();
stream.writeRawData(data.data(), data.size());
}
telegramFile.close();
}
}
void TelegramEdit::loadTelegramListAppend()
{
loadTelegramList(true);
}
void TelegramEdit::loadTelegramListReplace()
{
loadTelegramList(false);
}
void TelegramEdit::loadTelegramList(bool checkAppend)
{
QSettings settings;
QString newFilename = QFileDialog::getOpenFileName(m_tableView,
tr("Dateiname der Telegrammliste"),
settings.value(s_DIR()).toString(),
s_TELEGRAMLIST_FILES());
if (!newFilename.isEmpty())
{
QDir dir;
settings.beginGroup(s_EDIT_TELEGRAM_GROUP());
settings.setValue(s_DIR(), dir.filePath(newFilename));
settings.endGroup();
{
if (!checkAppend)
m_EditModel->clearTelegrams();
}
QFile telegramFile(newFilename);
telegramFile.open(QIODevice::ReadOnly);
QDataStream stream(&telegramFile);
QString id;
stream >> id;
if (id != s_TELEGRAMLIST_FILE_ID())
{
QMessageBox::critical(m_tableView, tr("Error"), tr("<b>%1</b> does not contain telegram data").arg(newFilename));
return;
}
uint32_t version = 0;
stream >> version;
if (version != 1)
{
QMessageBox::critical(m_tableView, tr("Error"), tr("Wrong telegram list file version"));
return;
}
int rows = 0;
QVector<uint16_t> gpsFieldOffset;
stream >> rows;
for (int i = 0; i < rows; i++)
{
uint32_t waitTime = 0;
QString name;
int telegramSize = 0;
stream >> waitTime >> name >> gpsFieldOffset >> telegramSize;
if (telegramSize > 0)
{
DEBUG_LOG(m_logger) << "telegramSize=" << telegramSize;
QByteArray buf(telegramSize, Qt::Uninitialized);
stream.readRawData(buf.data(), telegramSize);
NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Debug, buf);
LogViewTelegram *telegram = new LogViewTelegram(N_CoPrtCnv::CoPrtCnvLogHeader::e_DestProtocolCentral,
0,
buf);
telegram->setWaitTime(waitTime);
telegram->setName(name);
telegram->setGpsTimeField(gpsFieldOffset);
m_EditModel->appendTelegram(QSharedPointer<LogViewTelegram>(telegram));
}
}
telegramFile.close();
m_teleListSave->setEnabled(m_EditModel->rowCount() > 0);
}
}
bool TelegramEdit::isInjectionPossible() const
{
return m_InjectionThread ? m_InjectionThread->isSendingPossible() : false;
}
void TelegramEdit::onSelectionChanged()
{
const QModelIndex idx = currentSelectedIndex();
m_editTeleAction->setEnabled(idx.isValid());
m_copyTeleAction->setEnabled(idx.isValid());
m_deleteTeleAction->setEnabled(idx.isValid());
m_moveTeleUpAction->setEnabled(idx.row() > 0);
m_moveTeleDownAction->setEnabled(idx.isValid() && idx.row() < m_EditModel->rowCount() - 1);
}
}