diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/CMakeLists.txt
new file mode 100755
index 000000000..83a19ecab
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/CMakeLists.txt
@@ -0,0 +1,37 @@
+#
+# $Id$
+# $HeadURL$
+# $Author$
+# Created by Hanna Rathje, SLSE, 2017-12-14
+#
+
+SET(SRCS
+ aar_application.cpp
+ aar_application.h
+ databases_model.cpp
+ databases_model.h
+ logger.cpp
+ logger.h
+ main.cpp
+)
+
+NGL_WRAP_UI(SRCS aarApp.ui)
+
+NGL_ADD_EXECUTABLE(AAR aarApp ${SRCS})
+
+NGL_TARGET_LINK_LIBRARIES(aarApp
+ Qt6::Widgets
+ Qt6::Core
+ nglapplication
+ ngldb
+ nglcoreapplication
+ ngltools
+ ngltranslator
+ nglwidgets
+ NGLLogger
+ LtsCommandLineParser
+)
+
+NGL_INSTALL_TARGET(aarApp)
+NGL_INSTALL(AAR FILES log4cxx_aarApp.props DESTINATION bin)
+
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aarApp.ui b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aarApp.ui
new file mode 100755
index 000000000..185a56721
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aarApp.ui
@@ -0,0 +1,162 @@
+
+
+ AarApplication
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 846
+ 382
+
+
+
+ Database administration
+
+
+
+
+
+ Qt::ToolButtonIconOnly
+
+
+ QTabWidget::Rounded
+
+
+
+ -
+
+
-
+
+
+ Status:
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ No active database
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Databases:
+
+
+
+ -
+
+
+ true
+
+
+ QAbstractItemView::SingleSelection
+
+
+ QAbstractItemView::SelectRows
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Activate network database
+
+
+
+ -
+
+
+ Activate local database
+
+
+
+ -
+
+
+ Remove database
+
+
+
+ -
+
+
+ Close
+
+
+
+
+
+
+
+
+
+ &Show
+
+
+
+
+ &Start
+
+
+
+
+ St&op
+
+
+
+
+
+
+
+ oeffnenClicked()
+
+
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aar_application.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aar_application.cpp
new file mode 100755
index 000000000..ec846ca95
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aar_application.cpp
@@ -0,0 +1,501 @@
+/*
+ * @RDE_HEADER@
+ *
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Malte Schröder, SLSE, 2016-06-08
+ */
+
+#include "aar_application.h"
+#include "ui_aarApp.h"
+#include "databases_model.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DEFAULT_DB "lts_ets_pro"
+
+namespace AARApplication
+{
+
+AarApplication::AarApplication(QWidget *parent)
+ : QMainWindow(parent)
+ , m_ui(new Ui::AarApplication)
+ , m_stopping(false)
+ , m_proc(nullptr)
+ , m_progressDialog(nullptr)
+ , m_logger(getLogger("AarApplication"))
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ m_ui->setupUi(this);
+
+ const QList &screenList = QGuiApplication::screens();
+ m_widgets.reserve(screenList.size());
+ for (QScreen *s : qAsConst(screenList))
+ {
+ QWidget *w = new QWidget(); // no parent
+ w->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
+ w->setGeometry(s->geometry());
+ w->activateWindow();
+ w->show();
+ m_widgets.append(w);
+ }
+
+ m_databasesModel = new DatabasesModel(this);
+ m_proxyModel = new DatabasesProxyModel(this);
+ m_proxyModel->setSourceModel(m_databasesModel);
+ m_ui->tableViewDatabases->setModel(m_proxyModel);
+
+ connect(m_ui->pbClose, &QPushButton::clicked, this, &AarApplication::onClosedClicked);
+ connect(m_ui->pbRemove, &QPushButton::clicked, this, &AarApplication::onRemoveClicked);
+ connect(m_ui->pbActivate, &QPushButton::clicked, this, &AarApplication::onActivateClicked);
+ connect(m_ui->pbActivateNetwork, &QPushButton::clicked, this, &AarApplication::onActivateNetworkClicked);
+
+ connect(m_ui->tableViewDatabases->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AarApplication::enaDisa);
+
+ setWindowTitle(QLatin1String("AarApplication"));
+
+ enaDisa();
+
+ m_progressDialog = new QProgressDialog(this);
+
+ m_progressDialog->setLabelText(tr("Stopping server software ..."));
+ m_progressDialog->setMinimum(0);
+ m_progressDialog->setMaximum(0);
+ m_progressDialog->show();
+ onStopApp();
+
+}
+
+AarApplication::~AarApplication()
+{
+ delete m_ui;
+ delete m_databasesModel;
+ delete m_progressDialog;
+
+ for (QSqlDatabase db : qAsConst(m_dbMap))
+ db.close();
+
+ m_dbPostgres.close();
+
+ if (m_proc)
+ m_proc->deleteLater();
+
+ qDeleteAll(m_widgets);
+}
+
+bool AarApplication::init()
+{
+ m_ui->lblStatus->setText(tr("No active database"));
+
+ m_dbPostgres = DBConnection::open(m_logger,
+ QStringLiteral("postgres"),
+ QStringLiteral("postgres"),
+ QStringLiteral("QPSQL"),
+ QStringLiteral("localhost"),
+ QStringLiteral("postgres"),
+ QString(),
+ QStringLiteral("localhost_postgres"));
+
+ if (!m_dbPostgres.open())
+ {
+ ERROR_LOG(m_logger) << "Error opening postgres database" << m_dbPostgres.lastError().databaseText();
+ return false;
+ }
+
+ NSqlQuery q(m_dbPostgres);
+
+ QString stmt = QStringLiteral("SELECT datname FROM pg_database WHERE datname = '") + QStringLiteral(DEFAULT_DB) + QStringLiteral("'");
+
+ if (!q.execAndFetch(stmt))
+ {
+ NOTICE_LOG(m_logger) << "Database does not exist: " << DEFAULT_DB;
+ }
+ else
+ {
+ QSqlDatabase db_lts = DBConnection::open(m_logger,
+ QStringLiteral("ctc_sv"),
+ QStringLiteral("ctc11de"),
+ QStringLiteral("QPSQL"),
+ QStringLiteral("localhost"),
+ QStringLiteral(DEFAULT_DB),
+ QString(),
+ QStringLiteral("localhost_")+QStringLiteral(DEFAULT_DB));
+
+ if (!db_lts.open())
+ {
+ ERROR_LOG(m_logger) << "Error opening database " << DEFAULT_DB << " : "<< db_lts.lastError().databaseText();
+ m_dbPostgres.close();
+ return false;
+ }
+
+ NSqlQuery ql(db_lts);
+
+ stmt = QStringLiteral("SELECT id FROM exm.exercise");
+
+ if (!ql.execAndFetch(stmt))
+ {
+ ERROR_LOG(m_logger) << "No entry for exercise found in database " << DEFAULT_DB;
+ }
+ else
+ {
+ int dbId = ql.value(0).toInt();
+ db_lts.close();
+
+ QString dbName = QStringLiteral("lts_db_") + QString::number(dbId);
+ INFO_LOG(m_logger) << "New dbName for " << DEFAULT_DB << ": " << dbName;
+
+ stmt = QStringLiteral("ALTER DATABASE ") + QStringLiteral(DEFAULT_DB) + QStringLiteral(" RENAME TO ") + dbName;
+
+ if (!q.exec(stmt))
+ {
+ ERROR_LOG(m_logger) << "Error renaming database " << DEFAULT_DB << " : " << db_lts.lastError().databaseText();
+ m_dbPostgres.close();
+ return false;
+ }
+ }
+ }
+
+ stmt = QStringLiteral("SELECT datname FROM pg_database WHERE datname ilike 'lts_db_%';");
+
+ if (!q.exec(stmt))
+ {
+ ERROR_LOG(m_logger) << "Error while reading dbnames from database";
+ return false;
+ }
+
+ while (q.next())
+ {
+ QString dbName = q.value(0).toString();
+ QSqlDatabase db = DBConnection::open(m_logger,
+ QStringLiteral("ctc_sv"),
+ QStringLiteral("ctc11de"),
+ QStringLiteral("QPSQL"),
+ QStringLiteral("localhost"),
+ dbName,
+ QString(),
+ QStringLiteral("localhost_") + dbName);
+
+ if (!db.open())
+ {
+ ERROR_LOG(m_logger) << "Error while opening database " << dbName << ", error: " << db.lastError().databaseText();
+ continue;
+ }
+
+ m_databasesModel->initModel(db);
+ m_dbMap.insert(dbName, db);
+ }
+
+ m_ui->tableViewDatabases->resizeColumnsToContents();
+
+ return true;
+}
+
+void AarApplication::onClosedClicked()
+{
+ handleProcInit(QStringLiteral("/usr/bin/openbox"), {QStringLiteral("--exit")});
+ m_proc->start();
+ m_proc->waitForFinished();
+ QThread::sleep(2);
+ close();
+}
+
+void AarApplication::onRemoveClicked()
+{
+ disableButtons();
+
+ m_databaseToRemove = m_databasesModel->getRowData(m_ui->tableViewDatabases->currentIndex().row());
+
+ QString strMsg = QStringLiteral("Do you really want to remove the database '%1'?").arg (m_databaseToRemove.dbName);
+ int result = QMessageBox::question(this, tr("Remove Database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ if (result == QMessageBox::No)
+ {
+ enableButtons();
+ return;
+ }
+
+ DEBUG_LOG(m_logger) << "onRemoveClicked: dbName = " << m_databaseToRemove.dbName;
+ QSqlDatabase db = m_dbMap.value(m_databaseToRemove.dbName);
+ db.close();
+
+ const QStringList args({QStringLiteral("-U"),
+ QStringLiteral("postgres"),
+ QStringLiteral("-h"),
+ QStringLiteral("localhost"),
+ m_databaseToRemove.dbName
+ });
+
+ QString errStr;
+ const QString exePath = NGL::postgresExecutablePath(QStringLiteral("dropdb"), errStr);
+ if (!errStr.isEmpty())
+ WARNING_LOG(m_logger) << errStr;
+
+ handleProcInit(exePath, args);
+ connect(m_proc, QOverload::of(&QProcess::finished),
+ this, &AarApplication::onDropDbFinished);
+
+ // start process
+ m_proc->start();
+}
+
+void AarApplication::onActivateClicked()
+{
+ const QString fileName = QStringLiteral("/shd/CTC/WS/lts-cc.conf.org");
+
+ WARNING_LOG(m_logger) << "FileName: " << fileName;
+ QFile ltsConfig(fileName);
+
+ if (ltsConfig.exists())
+ ltsConfig.rename(QStringLiteral("/shd/CTC/WS/lts-cc.conf.org"), QStringLiteral("/shd/CTC/WS/lts-cc.conf"));
+
+ Exercise ex = m_databasesModel->getRowData(m_ui->tableViewDatabases->currentIndex().row());
+
+ QString strMsg = tr("Do you really want to activate database '%1'?").arg(ex.name);
+ int result = QMessageBox::question(this, tr("Activate local database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ if (result == QMessageBox::No)
+ return;
+
+ INFO_LOG(m_logger) << "onActivateClicked: dbName = " << ex.dbName;
+
+ QSqlDatabase db = m_dbMap.value(ex.dbName);
+ db.close();
+
+ NSqlQuery q(m_dbPostgres);
+
+ QString stmt = QStringLiteral("ALTER DATABASE ") + ex.dbName + QStringLiteral(" RENAME TO ") + QStringLiteral(DEFAULT_DB);
+
+ if (!q.exec(stmt))
+ ERROR_LOG(m_logger) << "Error renaming " << ex.dbName << " to " << DEFAULT_DB << " "<< m_dbPostgres.lastError().databaseText();
+ else
+ INFO_LOG(m_logger) << "Database " << ex.dbName << " renamed to " << DEFAULT_DB;
+
+ QString status = ex.name + QStringLiteral(" (") + ex.dbName + QStringLiteral(") ") + tr("active");
+ m_ui->lblStatus->setText(status);
+ onStartApp();
+}
+
+void AarApplication::onActivateNetworkClicked()
+{
+ onStopApp();
+ //const QString fileName = QDir::homePath()+ QStringLiteral("/lts-cc.conf");
+
+ const QString fileName = QStringLiteral("/shd/CTC/WS") + QStringLiteral("/lts-cc.conf");
+
+ WARNING_LOG(m_logger) << "FileName: " << fileName;
+ QFile ltsConfig(fileName);
+
+ if (!ltsConfig.exists())
+ {
+ QMessageBox::critical(this, tr ("Activate network database"), tr("Network database active"), QMessageBox::Ok);
+ m_ui->lblStatus->setText(tr("Network database active"));
+ return;
+ }
+
+ ltsConfig.rename(QStringLiteral("/shd/CTC/WS/lts-cc.conf"), QStringLiteral("/shd/CTC/WS/lts-cc.conf.org"));
+ m_ui->lblStatus->setText(tr("Network database active"));
+}
+
+void AarApplication::enaDisa()
+{
+ if (!m_ui)
+ return;
+ int selected = m_ui->tableViewDatabases->selectionModel()->selectedRows().size();
+
+ m_ui->pbRemove->setEnabled(selected > 0);
+ m_ui->pbActivate->setEnabled(selected > 0);
+}
+
+void AarApplication::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ INFO_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
+
+ static const QString s_title = tr("Remove Database");
+ static const QString s_msgFailure = tr("Removing database failed.");
+ static const QString s_msgSuccess = tr("Removing database successful.");
+
+ if (exitCode > 0)
+ {
+ const QString str = QString::fromLocal8Bit(m_proc->readAllStandardError()) + QLatin1Char('\n') +
+ QString::fromLocal8Bit(m_proc->readAllStandardOutput());
+ ERROR_LOG(m_logger) << "Cannot drop database: " << str;
+ QString msg = s_msgFailure;
+ QString db0 = QLatin1String("ERROR: database \"") + m_databaseToRemove.dbName + QLatin1String("\" does not exist");
+ if (!str.contains(db0))
+ msg += tr(" Database cannot be removed:\n%1.").arg(str);
+ QMessageBox::critical(this, s_title, msg, QMessageBox::Ok);
+ }
+ else
+ {
+ m_databasesModel->onDataChanged(m_databaseToRemove, DataModification::eRemoved);
+ QMessageBox::information(this, s_title, s_msgSuccess);
+ }
+
+ enableButtons();
+}
+
+void AarApplication::onErrorOccured(QProcess::ProcessError error)
+{
+ ERROR_LOG(m_logger) << "error: " << error;
+}
+
+void AarApplication::onStartApp()
+{
+ handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")});
+ connect(m_proc, QOverload::of(&QProcess::finished),
+ this, &AarApplication::onPsauxFinished);
+ m_proc->start();
+}
+
+
+void AarApplication::onPsauxFinished()
+{
+ enableButtons();
+ QByteArray output = m_proc->readAllStandardOutput();
+
+ if (output.contains("svcServiceManagement"))
+ {
+ ERROR_LOG(m_logger) << "ServiceManagement already started";
+ }
+ else
+ {
+ ERROR_LOG(m_logger) << "Start svcServiceManagement";
+ handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-z")});
+ connect(m_proc, QOverload::of(&QProcess::finished),
+ this, &AarApplication::onStartAppFinished);
+ m_proc->start();
+ m_proc->waitForFinished();
+ }
+}
+
+void AarApplication::onStartAppFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ handleProcFinished(exitCode, exitStatus);
+}
+
+void AarApplication::onStopApp()
+{
+ disableButtons();
+ handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")});
+ m_proc->start();
+ if (m_proc->waitForFinished())
+ onPsauxStopFinished();
+}
+
+void AarApplication::onPsauxStopFinished()
+{
+ DEBUG_LOG(m_logger) << "IN onPsauxStopFinished";
+ enableButtons();
+ QByteArray output = m_proc->readAllStandardOutput();
+
+ if (output.contains("svcServiceManagement"))
+ {
+ if (m_stopping)
+ {
+ QThread::sleep(3);
+ onStopApp();
+ }
+ else
+ {
+
+ ERROR_LOG(m_logger) << "ServiceManagement started - stopping";
+
+ handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-s")});
+ connect(m_proc, QOverload::of(&QProcess::finished),
+ this, &AarApplication::onStopAppFinished);
+ m_proc->start();
+ m_stopping = true;
+ }
+ }
+ else
+ {
+ INFO_LOG(m_logger) << "ServiceManagement already stopped";
+ m_stopping = false;
+ m_progressDialog->hide();
+ }
+
+ m_proc->waitForFinished();
+}
+
+void AarApplication::onStopAppFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ if (m_stopping)
+ onPsauxStopFinished();
+
+ handleProcFinished(exitCode, exitStatus);
+}
+
+void AarApplication::handleProcInit(const QString &program, const QStringList &args)
+{
+ if (m_proc)
+ {
+ m_proc->disconnect(this);
+ m_proc->deleteLater();
+ }
+ m_proc = new QProcess(this);
+ NOTICE_LOG(m_logger) << "Starting process '" << program << "' with args '"
+ << args.join(QLatin1Char(' ')) << "'";
+
+ m_proc->setProgram(program);
+ m_proc->setArguments(args);
+ connect(m_proc, &QProcess::errorOccurred, this, &AarApplication::onErrorOccured);
+ disableButtons();
+}
+
+void AarApplication::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ enableButtons();
+
+ if (!m_proc)
+ return;
+ if (exitCode != 0 || exitStatus != 0)
+ {
+ QByteArray out = m_proc->readAllStandardError();
+ if (!out.isEmpty())
+ out += '\n';
+ out += m_proc->readAllStandardOutput();
+ ERROR_LOG(m_logger) << "Process finished - exitCode: " << exitCode << ", exitStatus = " << exitStatus << ", " << out;
+
+ QMessageBox::critical(this,
+ tr ("Execute process"), tr("Error executing process, exitCode: %1, exitStatus: %2, output: %3")
+ .arg(exitCode).arg(exitStatus).arg(QString::fromLocal8Bit(out)),
+ QMessageBox::Ok);
+ }
+ m_proc->disconnect(this);
+ m_proc->deleteLater();
+ m_proc = nullptr;
+
+ if (m_progressDialog)
+ m_progressDialog->hide();
+}
+
+
+void AarApplication::enaDisaButtons(bool bEnable)
+{
+ {
+ const QList l = findChildren();
+ for (QPushButton *pb : l)
+ pb->setEnabled(bEnable);
+ }
+ {
+ const QList l = findChildren();
+ for (QAction *a : l)
+ a->setEnabled(bEnable);
+ }
+ if (bEnable)
+ enaDisa();
+}
+
+} // namespace AarApplication
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aar_application.h b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aar_application.h
new file mode 100755
index 000000000..e6f57af64
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/aar_application.h
@@ -0,0 +1,78 @@
+/*
+ * @RDE_HEADER@
+ *
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Malte Schröder, SLSE, 2016-06-08
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "logger.h"
+#include "databases_model.h"
+
+namespace Ui {
+class AarApplication;
+}
+
+namespace AARApplication
+{
+class AarApplication : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit AarApplication(QWidget *parent = nullptr);
+ ~AarApplication();
+
+ bool init();
+
+private slots:
+ void onClosedClicked();
+ void onRemoveClicked();
+ void onActivateClicked();
+ void onActivateNetworkClicked();
+ void onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void onPsauxFinished();
+ void onStartAppFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void onPsauxStopFinished();
+ void onStopAppFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void onErrorOccured(QProcess::ProcessError error);
+ void onStartApp();
+ void onStopApp();
+
+private:
+ void enaDisa();
+ void handleProcInit(const QString &program, const QStringList &args);
+ void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void disableButtons() { enaDisaButtons(false); }
+ void enableButtons() { enaDisaButtons(true); }
+ void enaDisaButtons(bool bEnable);
+
+
+private:
+ Ui::AarApplication *m_ui;
+ DatabasesModel *m_databasesModel;
+ DatabasesProxyModel *m_proxyModel;
+ QMap m_dbMap;
+ bool m_stopping;
+ Exercise m_databaseToRemove;
+ QProcess *m_proc;
+ QSqlDatabase m_dbPostgres;
+ QProgressDialog *m_progressDialog;
+ QVector m_widgets;
+
+ LOGGER_T m_logger;
+};
+} // namespace AARApplication
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/databases_model.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/databases_model.cpp
new file mode 100755
index 000000000..72aebf169
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/databases_model.cpp
@@ -0,0 +1,214 @@
+/**
+ * @RDE_HEADER@
+ * PresentationManangement - Script Overview Dialog Model
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ *
+ * Created by Mike Wille, SLSE, 2017-03-15
+ */
+
+#include "databases_model.h"
+
+#include
+#include
+
+#include
+#include
+
+namespace AARApplication
+{
+
+DatabasesModel::DatabasesModel(QObject *parent)
+ : QAbstractTableModel(parent)
+, m_logger(getLogger("DatabasesModel"))
+{
+ beginResetModel();
+ m_vecData.clear();
+ endResetModel();
+}
+
+bool DatabasesModel::initModel(const QSqlDatabase &db)
+{
+ NSqlQuery q(db);
+
+ QString stmt = QStringLiteral("SELECT id, name, begin_time, end_time, exercise_state_id FROM exm.exercise");
+
+ if (!q.prepare(stmt))
+ {
+ ERROR_LOG(m_logger) << "Preparing statement '" << stmt << "' failed.";
+ return false;
+ }
+
+ if (!q.exec(stmt))
+ {
+ ERROR_LOG(m_logger) << "Executing statement '" << stmt << "' failed.";
+ return false;
+ }
+
+ int count = 0;
+ while (q.next())
+ {
+ if (count > 0)
+ {
+ WARNING_LOG(m_logger) << "More than one exercise detected. There should be only one exercise per database.";
+ break;
+ }
+
+ Exercise exercise;
+ exercise.m_id = q.value(0).toInt();
+ exercise.name = q.value(1).toString();
+ exercise.startTime = q.value(2).toLongLong();
+ exercise.endTime = q.value(3).toLongLong();
+ exercise.dbName = QStringLiteral("lts_db_") + QString::number(exercise.m_id);
+ exercise.stateId = q.value(4).toInt();
+ TRACE_LOG(m_logger) << "Found exercise with id=" << exercise.m_id << ", name=" << exercise.name << ", startTime="
+ << exercise.startTime << ", endTime=" << exercise.endTime << ", dbName=" << exercise.dbName
+ << ", stateId=" << exercise.stateId;
+ if (exercise.stateId != 6)
+ onDataChanged(exercise, DataModification::eAdded);
+ ++count;
+ }
+
+ INFO_LOG(m_logger) << "initModel - #exercises: " << m_vecData.size();
+
+ return true;
+}
+
+
+QVariant DatabasesModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole || !index.isValid() || index.row() >= m_vecData.size())
+ return QVariant();
+
+ const Exercise &e = m_vecData.at(index.row());
+
+ switch (index.column())
+ {
+ case Id:
+ return e.m_id;
+ case Name:
+ return QString(e.name);
+ case StartTime:
+ return DTG::toStringMSec(e.startTime);
+ case EndTime:
+ return DTG::toStringMSec(e.endTime);
+ }
+
+ return QVariant();
+}
+
+int DatabasesModel::rowCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : m_vecData.size();
+}
+
+int DatabasesModel::columnCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : EndTime + 1;
+}
+
+QVariant DatabasesModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal
+ && role == Qt::DisplayRole)
+ {
+ Columns col = static_cast(section);
+ switch (col)
+ {
+ case Id:
+ return tr("Id");
+ case Name:
+ return tr("Name");
+ case StartTime:
+ return tr("Start Time");
+ case EndTime:
+ return tr("End Time");
+ }
+ }
+ return QAbstractTableModel::headerData(section, orientation, role);
+}
+
+Exercise DatabasesModel::getRowData(int row) const
+{
+ if (row < 0 || row >= m_vecData.size())
+ return Exercise();
+ return m_vecData.at(row);
+}
+
+bool DatabasesModel::insertRow(const Exercise &item)
+{
+ beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
+ m_vecData.append(item);
+ endInsertRows();
+ return true;
+}
+
+bool DatabasesModel::removeRow(const int &row)
+{
+ beginRemoveRows(QModelIndex(), row, row);
+ m_vecData.remove(row);
+ endRemoveRows();
+ return true;
+}
+
+void DatabasesModel::onDataChanged(const Exercise &data, DataModification modType)
+{
+ int row = -1;
+ switch (modType)
+ {
+ case DataModification::eAdded:
+ row = m_vecData.size();
+ if (insertRow(data))
+ emit dataChanged(index(row, Columns::Id), index(row, Columns::EndTime));
+ return;
+
+ case DataModification::eModified:
+ row = m_vecData.indexOf(data);
+ if (row != -1)
+ {
+ m_vecData[row] = data;
+ emit dataChanged(index(row, Columns::Id), index(row, Columns::EndTime));
+ }
+ return;
+
+ case DataModification::eRemoved:
+ row = m_vecData.indexOf(data);
+ if (row != -1)
+ if (removeRow(row))
+ emit dataChanged(index(std::min(row, m_vecData.size()-1), Columns::Id), index(m_vecData.size()-1, Columns::EndTime));
+ return;
+ } // switch
+}
+
+
+void DatabasesProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
+{
+ m_sourceModel = qobject_cast(sourceModel);
+ QSortFilterProxyModel::setSourceModel(sourceModel);
+}
+
+bool DatabasesProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
+{
+ if (!m_sourceModel ||
+ source_left.column() != source_right.column() ||
+ !source_left.isValid() ||
+ !source_right.isValid())
+ return QSortFilterProxyModel::lessThan(source_left, source_right);
+ const auto &dataLeft = m_sourceModel->m_vecData.at(source_left.row());
+ const auto dataRight = m_sourceModel->m_vecData.at(source_right.row());
+ switch (source_left.column())
+ {
+ case DatabasesModel::StartTime:
+ return dataLeft.startTime < dataRight.startTime;
+ case DatabasesModel::EndTime:
+ return dataLeft.endTime < dataRight.endTime;
+ case DatabasesModel::Id:
+ case DatabasesModel::Name:
+ break;
+ }
+ return QSortFilterProxyModel::lessThan(source_left, source_right);
+}
+
+
+} // namespace AARApplication
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/databases_model.h b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/databases_model.h
new file mode 100755
index 000000000..310e79aa5
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/databases_model.h
@@ -0,0 +1,100 @@
+/**
+ * @RDE_HEADER@
+ * PresentationManangement - Script Overview Dialog Model
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ *
+ * Created by Mike Wille, SLSE, 2017-03-15
+ */
+
+#pragma once
+
+#include "logger.h"
+
+#include
+
+#include
+#include
+
+
+class QSqlDatabase;
+
+namespace AARApplication
+{
+
+struct Exercise
+{
+ qint32 id = 0;
+ QString name;
+ QString dbName;
+ qint64 startTime = 0;
+ qint64 endTime = 0;
+ qint32 stateId = 0;
+
+ bool operator == (const Exercise &other) { return id == other.m_id; }
+ bool operator != (const Exercise &other) { return id != other.m_id; }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// DatabasesModel
+//
+class DatabasesModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ enum Columns
+ {
+ Id = 0,
+ Name,
+ StartTime,
+ EndTime
+ };
+
+ explicit DatabasesModel(QObject *parent = nullptr);
+ ~DatabasesModel() = default;
+
+ bool initModel(const QSqlDatabase &db);
+
+ QVariant data(const QModelIndex &, int) const override final;
+
+ int rowCount(const QModelIndex &parent) const override final;
+ int columnCount(const QModelIndex &parent) const override final;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
+ Exercise getRowData(int row) const;
+ bool insertRow(const Exercise &item);
+ bool removeRow(const int &row);
+
+ friend class DatabasesProxyModel;
+
+protected:
+
+public slots:
+ void onDataChanged(const Exercise &data, DataModification modType);
+
+private:
+ QVector m_vecData;
+ LOGGER_T m_logger;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// DatabasesProxyModel
+//
+class DatabasesProxyModel final : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ using QSortFilterProxyModel::QSortFilterProxyModel;
+ void setSourceModel(QAbstractItemModel *sourceModel) override;
+
+protected:
+ bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
+
+private:
+ DatabasesModel *m_sourceModel = nullptr;
+};
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/log4cxx_aarApp.props b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/log4cxx_aarApp.props
new file mode 100755
index 000000000..4121f7803
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/log4cxx_aarApp.props
@@ -0,0 +1,77 @@
+log4j.reset=true
+log4j.rootLogger=WARN, file
+
+# DbAdministration
+###########################################################
+
+#log4j.logger.DbAdministration=DEBUG
+
+# File
+###########################################################
+log4j.appender.file=Lts::RollingFileAppender
+log4j.appender.file.MaxFileSize=1MB
+log4j.appender.file.MaxBackupIndex=9
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
+
+
+# Appnd_Console
+###########################################################
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
+
+
+# Appnd_Syslog
+###########################################################
+log4j.appender.syslog=org.apache.log4j.SyslogAppender
+log4j.appender.syslog.Threshold=ERROR
+log4j.appender.syslog.SysLogHost=localhost
+log4j.appender.syslog.Facility=LOCAL7
+log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
+log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
+log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
+log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
+log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
+
+
+###########################################################
+###########################################################
+###########################################################
+# 1) Available Levels in LOG4CXX Version 0.10.0:
+# TRACE,
+# DEBUG,
+# INFO,
+# WARN,
+# ERROR
+# FATAL
+#
+# d = date/time
+# p = priority (Level)
+# c = category/channel
+# m = message
+# F = file
+# L = line
+# n = platform dependent line separator character or characters.
+# ....
+#
+# Examples for console:
+# a)
+# %d %p %c #%m# (%.50F:%L)%n
+# date/time
+# priority
+# category/channel
+# #message#
+# (Maximal 50Character des Filename von rechts:Line)
+# line separator
+#
+# b)
+# %d (%.15F:%L) %-5p %c |#| %m%n
+# date/time
+# (Maximal 15Character des Filename von rechts:Line)
+# priority, Right pad with spaces if the priority name is less than 5 characters long.
+# category/channel
+# message
+# line separator
+#
+# Examples for files:
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/logger.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/logger.cpp
new file mode 100755
index 000000000..8555f4448
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/logger.cpp
@@ -0,0 +1,37 @@
+/**
+ * @RDE_HEADER@
+ * Building Config - logging facility
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ */
+
+#include "logger.h"
+
+#include
+
+namespace AARApplication
+{
+
+LOGGER_T getLogger(const char *name)
+{
+ static const char ns[] = "DBA.";
+ 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 AARApplication
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/logger.h b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/logger.h
new file mode 100755
index 000000000..e09954e43
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/logger.h
@@ -0,0 +1,23 @@
+/**
+ * @RDE_HEADER@
+ * Logging for Evaluations
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ */
+
+#pragma once
+
+#include
+
+
+namespace AARApplication
+{
+typedef NGL::INGLLogger &LOGGER_T;
+
+ LOGGER_T getLogger(const char *name);
+inline LOGGER_T getLogger(const QString &loggerName)
+{
+ return getLogger(loggerName.toUtf8().constData());
+}
+} // namespace AARApplication
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/main.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/main.cpp
new file mode 100755
index 000000000..2db9648f4
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/AarApp/main.cpp
@@ -0,0 +1,80 @@
+/*
+ * @RDE_HEADER@
+ *
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Malte Schröder, SLSE, 2016-06-08
+ */
+
+#include "aar_application.h"
+#include
+#include
+#include
+#include
+#include
+
+class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
+{
+public:
+ CmdLineParser()
+ : LtsCommandLineParser(ProvideCommandLineParameterOptions::None)
+ {
+ addOption({{QStringLiteral("l"), QStringLiteral("lang")},
+ QStringLiteral("Language iso code to use (de_DE, en_GB, en_US)"),
+ QStringLiteral("")
+ });
+ }
+ QString langIsoCode() const { return value(QStringLiteral("l")); }
+};
+
+int main(int argc, char *argv[])
+{
+ int retval = -1;
+ bool bHeadless = false;
+ for (int i = 1; i < argc; ++i)
+ {
+ if (strcmp(argv[i], "-e") == 0)
+ {
+ bHeadless = true;
+ break;
+ }
+ }
+ QScopedPointer app;
+ app.reset(bHeadless ? dynamic_cast(new NGLCoreApplication(argc, argv))
+ : dynamic_cast(new NGLApplication(argc, argv)));
+ QCoreApplication::setApplicationName(QLatin1String("AarApplication"));
+ QCoreApplication::setOrganizationName(QLatin1String("RME"));
+
+ if (!bHeadless)
+ app->setAttribute(Qt::AA_UseHighDpiPixmaps);
+
+
+ NGL::LoggerHandler *lh = dynamic_cast(app.data());
+ lh->createLogger("AarApp", "log4cxx_aarApp.props");
+ NGL::INGLLogger &logger = lh->baseLogger();
+
+ // Parse Options
+ CmdLineParser options;
+ if (!options.init())
+ return retval;
+
+ // Set Translation
+ QString langIsoCode = options.langIsoCode();
+ if (langIsoCode.isEmpty())
+ langIsoCode = QLocale::system().name();
+ NGL::setTranslationLocale(langIsoCode.toLatin1());
+
+ AARApplication::AarApplication * w = new AARApplication::AarApplication;
+ if (!w->init())
+ return -2;
+
+ STARTUP_LOG(logger);
+ w->show();
+ QGuiApplication::setQuitOnLastWindowClosed(true);
+ retval = QCoreApplication::exec();
+
+ SHUTDOWN_LOG(logger);
+
+ return retval;
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/CMakeLists.txt
new file mode 100755
index 000000000..91294f50c
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/CMakeLists.txt
@@ -0,0 +1,9 @@
+#
+# $Id$
+# $HeadURL$
+# $Author$
+#
+
+ADD_SUBDIRECTORY(AarApp)
+ADD_SUBDIRECTORY(OpApp)
+ADD_SUBDIRECTORY(THP)
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/CMakeLists.txt
new file mode 100755
index 000000000..1fc717a67
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/CMakeLists.txt
@@ -0,0 +1,53 @@
+#
+# $Id$
+# $HeadURL$
+# $Author$
+#
+
+SET(LOG4CXX_PROPS_FILE log4cxx_opapp.props)
+
+SET(mwt_SRCS
+ main.cpp
+ ${LOG4CXX_PROPS_FILE}
+)
+
+IF(WIN32)
+ SET(JBN ${JENKINS_BUILD_NUMBER})
+ IF (NOT JENKINS_BUILD_NUMBER)
+ SET(JBN "0")
+ ENDIF()
+ SET(OPAPP_VERSION_INFO "${LTS_VERSION_MAJOR}, ${LTS_VERSION_MINOR}, ${JBN}, ${LTS_VERSION_PATCH}")
+ CONFIGURE_FILE(opapp.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/opapp.rc)
+ LIST(APPEND mwt_SRCS ${CMAKE_CURRENT_BINARY_DIR}/opapp.rc)
+ENDIF()
+NGL_ADD_APP_ICON(mwt_SRCS)
+
+IF(BUILD_RPM)
+ NGL_ADD_EXECUTABLE(WS OperatorApplication WIN32 ${mwt_SRCS})
+ELSE()
+ NGL_ADD_EXECUTABLE(WS OperatorApplication ${mwt_SRCS})
+ENDIF()
+
+NGL_TARGET_LINK_LIBRARIES(OperatorApplication
+ ArcGISQt5Hack # make sure it's loaded *before* libEsriCommonQt.so
+ Qt6::Widgets
+ Qt6::Network
+ nglapplication
+ LtsCommandLineParser
+ NGLLogger
+ LtsSession
+ LtsPluginLoader
+ LtsAppDescriptor
+ LtsAppManager
+ LtsSessionData
+ LtsUtilsSettings
+ ngltranslator
+ nglsettings
+ LtsProjectionWorkstation
+ LtsMultiMonitor # TODO: rm if -m is out
+ LtsUtilsGuiConnectDialog # to set timeout if -v is set
+ LtsUtilsGuiStyleManager
+)
+NGL_INSTALL_TARGET(OperatorApplication)
+
+NGL_INSTALL(FILES WS ${LOG4CXX_PROPS_FILE} DESTINATION "bin")
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/log4cxx_opapp.props b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/log4cxx_opapp.props
new file mode 100755
index 000000000..78aab386a
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/log4cxx_opapp.props
@@ -0,0 +1,537 @@
+# Created by Mike Wille, SLSE, 2016-08-08
+log4j.reset=true
+
+log4j.rootLogger=WARN, file
+
+# LtsSession
+###########################################################
+#log4j.logger.LtsSession.TopicLockHandler=INFO
+#log4j.logger.LtsWidget.LtsDialog=INFO
+
+
+# SituationReplayManagement SRM
+###########################################################
+#log4j.logger.SRM=DEBUG
+
+# Schnittstelle Adpter Adler SAA
+###########################################################
+#log4j.logger.SAA.SAAInterfaceGuiPlugin=DEBUG
+#log4j.logger.SAA.SaaDialogModel=DEBUG
+#log4j.logger.SAA.CustomViewSaa=DEBUG
+#log4j.logger.SAA.SaaChooser=DEBUG
+
+# FileManagement FLM
+###########################################################
+#log4j.logger.AVM=DEBUG
+#log4j.logger.FLM.Plugins.Data=INFO
+#log4j.logger.FLM.Plugins.Gui.Explorer=INFO
+#log4j.logger.FLM.Plugins.Gui.FlmCombobox=INFO
+#log4j.logger.FLM.FileManagementDialog=DEBUG
+#log4j.logger.FLM.DialogModelFolder=INFO
+#log4j.logger.FLM.DialogEditFolder=INFO
+#log4j.logger.FLM.DialogModelFile=INFO
+#log4j.logger.FLM.FileContentEditDialog=DEBUG
+#log4j.logger.FLM.FileContentPreviewDialog=DEBUG
+#log4j.logger.FLM.SetAttributesDialog=INFO
+#log4j.logger.FLM.HQReportModel=DEBUG
+
+
+# FilterManagement FLT
+###########################################################
+#log4j.logger.FLT.AesDisplayFilterImpl=DEBUG
+#log4j.logger.FLT.BuildingComponentSettingsImpl=TRACE
+#log4j.logger.FLT.BuildingComponentFilterDialog=TRACE
+#log4j.logger.FLT.BuildingComponentSettingsWidget=TRACE
+#log4j.logger.FLT.SymbolAppearanceSettings=DEBUG
+#log4j.logger.FLT.SymbolAppearanceDialog=INFO
+#log4j.logger.FLT.SymbolAppearanceWidget=DEBUG
+
+#log4j.logger.FLT.FilterChangeDialog=INFO
+
+# CodificationManagement COD
+###########################################################
+#log4j.logger.COD.Plugins.Gui.CodificationDataImpl=DEBUG
+#log4j.logger.COD.CodificationDataOverviewDialog=DEBUG
+#log4j.logger.COD.CodificationDataOverviewModel=DEBUG
+#log4j.logger.COD.CodificationDataTableView=DEBUG
+#log4j.logger.COD.CodificationDataTableEditView=DEBUG
+#log4j.logger.COD.CodificationDataTableView=DEBUG
+#log4j.logger.COD.CodificationCSVExport=DEBUG
+#log4j.logger.COD.CodificationCSVImport=DEBUG
+#log4j.logger.COD.NumeralCodeTableModel=DEBUG
+#log4j.logger.COD.AuthenticationCodeTableModel=DEBUG
+#log4j.logger.COD.LogisticalTermsModel=DEBUG
+#log4j.logger.COD.PhraseTableModel= DEBUG
+#log4j.logger.COD.CodeTableEditDelegate=DEBUG
+#log4j.logger.COD.AssignCodificationDataTable=DEBUG
+
+# AlarmManagement Info
+###########################################################
+#log4j.logger.ALM.Config=DEBUG
+#log4j.logger.ALM.Model=DEBUG
+#log4j.logger.ALM.Dialog=DEBUG
+
+# InfrastructureManagement ISM
+###########################################################
+#log4j.logger.ISM.ApproachingPointsDialog=DEBUG
+#log4j.logger.ISM.ApproachingPointsDialogModel=DEBUG
+#log4j.logger.ISM.AssetFilterDialog=DEBUG
+#log4j.logger.ISM.AssetListDialog=DEBUG
+#log4j.logger.ISM.AssetListDialogModel=DEBUG
+#log4j.logger.ISM.AudioVideoConfigPlugin=DEBUG
+#log4j.logger.ISM.BuildingMountPointDialog=DEBUG
+#log4j.logger.ISM.BuildingMountPointModel=DEBUG
+#log4j.logger.ISM.CustomViewSchedule=DEBUG
+#log4j.logger.ISM.DdsSelector=DEBUG
+#log4j.logger.ISM.EditApproachingPointDialog=DEBUG
+#log4j.logger.ISM.EditAssetDialog=DEBUG
+#log4j.logger.ISM.ExerciseAssignmentDialog=DEBUG
+#log4j.logger.ISM.ExerciseAssignmentDialogModel=DEBUG
+#log4j.logger.ISM.ForeignDataInterface=DEBUG
+#log4j.logger.ISM.InfrastructureManagement=DEBUG
+#log4j.logger.ISM.MountingPointInfoDialog=DEBUG
+#log4j.logger.ISM.MountingPointListDialog=DEBUG
+#log4j.logger.ISM.MountingPointListDialogModel=DEBUG
+#log4j.logger.ISM.NewPlanDialog=DEBUG
+#log4j.logger.ISM.OverviewDialog=DEBUG
+#log4j.logger.ISM.OverviewDialogModel=DEBUG
+
+#log4j.logger.ISM.OverviewMountingPointListDialog=DEBUG
+#log4j.logger.ISM.ViewMountingPointListModel=DEBUG
+
+#log4j.logger.ISM.PlanChooser=DEBUG
+#log4j.logger.ISM.PlanDialog=DEBUG
+#log4j.logger.ISM.PlanDialogModel=DEBUG
+#log4j.logger.ISM.PlanEditDialog=DEBUG
+#log4j.logger.ISM.PlanTimeLineDialog=DEBUG
+#log4j.logger.ISM.PlanTimeLineModel=DEBUG
+#log4j.logger.ISM.Plugins.Gui.IsmCombobox=DEBUG
+#log4j.logger.ISM.ResourceManagement=DEBUG
+#log4j.logger.ISM.SetPropertiesDialog=DEBUG
+#log4j.logger.ISM.SetRecordingDialog=DEBUG
+
+# AreaEffectSimulation Info
+###########################################################
+#log4j.logger.AES.AESInfo=DEBUG
+#log4j.logger.AES.AESInfoDialog=DEBUG
+
+# generated using ctc_find_getlogger.sh
+#log4j.logger.AES.AesGuiBase=DEBUG
+#log4j.logger.AES.AESInfo=DEBUG
+#log4j.logger.AES.AESInfoDialog=DEBUG
+#log4j.logger.AES.AesItemList=DEBUG
+#log4j.logger.AES.ChargeAdministration=DEBUG
+#log4j.logger.AES.ChargeAdministrationList=DEBUG
+#log4j.logger.AES.DangerArea.AesItemInfo=DEBUG
+#log4j.logger.AES.Plugins.Gui.Aes.Borderline=DEBUG
+#log4j.logger.AES.Plugins.Gui.AirSupport=DEBUG
+#log4j.logger.AES.Plugins.Gui.BcContamination=DEBUG
+#log4j.logger.AES.Plugins.Gui.BorderlineImpl=DEBUG
+#log4j.logger.AES.Plugins.Gui.ChargeAdministration=DEBUG
+#log4j.logger.AES.Plugins.Gui.DangerArea=DEBUG
+#log4j.logger.AES.Plugins.Gui.Explosion=DEBUG
+#log4j.logger.AES.Plugins.Gui.FunctionalArea=DEBUG
+#log4j.logger.AES.Plugins.Gui.GasPipe=DEBUG
+#log4j.logger.AES.Plugins.Gui.MineArea=DEBUG
+#log4j.logger.AES.Plugins.Gui.MineCorridor=DEBUG
+#log4j.logger.AES.Plugins.Gui.MineSingleVirtual=DEBUG
+#log4j.logger.AES.Plugins.Gui.NContamination=DEBUG
+#log4j.logger.AES.Plugins.Gui.TechnicalArea=DEBUG
+
+#log4j.logger.AES.BCContaminationEdit=DEBUG
+#log4j.logger.AES.BoobyTrapEdit=DEBUG
+#log4j.logger.AES.BorderlineEdit=DEBUG
+#log4j.logger.AES.DangerAreaEdit=DEBUG
+#log4j.logger.AES.ExplosionEdit=DEBUG
+### setExplosionsEdit to ERROR (WARN "zValue is very small, set to 100")
+log4j.logger.AES.ExplosionsEdit=ERROR
+#log4j.logger.AES.FunctionalAreaEdit=DEBUG
+#log4j.logger.AES.GasPipeEdit=DEBUG
+#log4j.logger.AES.MineAreaEdit=DEBUG
+#log4j.logger.AES.MineCorridorEdit=DEBUG
+#log4j.logger.AES.NContaminationEdit=DEBUG
+#log4j.logger.AES.OffRouteMineEdit=DEBUG
+#log4j.logger.AES.TechnicalAreaEdit=DEBUG
+
+# in context ExplosionCluster / Artillery suppress warnings of TrajectoryGenerator, TrajectoryGeneratorVulcano
+log4j.logger.AES.TrajectoryGenerator=ERROR
+log4j.logger.AES.TrajectoryGeneratorVulcano=ERROR
+
+
+
+# AdvancedSymbolgy
+###########################################################
+#log4j.logger.AdvSymbology=INFO
+#log4j.logger.AdvSymbology.FlmSubscriber=DEBUG
+# FlmSubscriber.ReFetch should be on INFO to be able check the occurance of ReFetching
+#log4j.logger.AdvSymbology.FlmSubscriber.ReFetch=INFO
+#log4j.logger.AdvSymbology.FlmSymbolProxy=DEBUG
+#log4j.logger.AdvSymbology.EsriDictionaryProcessor=INFO
+#log4j.logger.AdvSymbology.SidcBuilder=INFO
+#log4j.logger.AdvSymbology.PropertyResult=INFO
+#log4j.logger.AdvSymbology.PropertyResultWatcher=INFO
+#log4j.logger.AdvSymbology.SymbolResult=INFO
+#log4j.logger.AdvSymbology.SymbolResultWatcher=INFO
+#log4j.logger.AdvSymbology.SymbolDictionary=INFO
+#log4j.logger.AdvSymbology.SymbolDictionaryImpl=INFO
+
+# AdvancedSymbolgy - Plugin
+#log4j.logger.AdvSymbology.FlmSubscriber=INFO
+#log4j.logger.AdvSymbology.FlmSymbolProxy=INFO
+
+
+# Building-Viewer
+###########################################################
+#log4j.logger.BDV=DEBUG
+#Common
+#log4j.logger.BDV.BuildingManager=DEBUG
+#log4j.logger.BDV.BuildingViewerDdsController=DEBUG
+#log4j.logger.BDV.BgViewerControllerSingleton=DEBUG
+#log4j.logger.BDV.BuildingViewerDdsController=DEBUG
+#log4j.logger.BDV.CommunicationInterface=DEBUG
+#GUI
+#log4j.logger.BDV.BuildingViewer::BuildingEdit=DEBUG
+#log4j.logger.BDV.BgViewerDataView=DEBUG
+#log4j.logger.BDV.ThreadVideoExporter=DEBUG
+#log4j.logger.BDV.ReplayHandler=DEBUG
+#log4j.logger.BDV.BdvPluginProvider=DEBUG
+#log4j.logger.BDV.BgViewerDataViewDialog=DEBUG
+#log4j.logger.BDV.TopicReplayInterface=DEBUG
+#Plugin
+#log4j.logger.BDV.InterfaceImpl=DEBUG
+
+
+# Building
+###########################################################
+#log4j.logger.BLD.BldInfo=DEBUG
+#log4j.logger.BLD.BldInfoDialog=DEBUG
+#log4j.logger.BLD.BuildingConfigDialog=DEBUG
+
+# TakeHomePackageManager
+###########################################################
+#log4j.logger.TPM.ExportedScriptsModel=DEBUG
+
+# Script Editor
+###########################################################
+#log4j.logger.ScriptTimelineDialog.JournalDialog=DEBUG
+#log4j.logger.ScriptTimelineDialog.ScriptTimelineDialog=DEBUG
+#log4j.logger.ScriptTimelineDialog.ScriptModel=DEBUG
+#log4j.logger.ScriptTimelineDialog.Plugins.Gui.Pre.ScriptTimeline=DEBUG
+#log4j.logger.ScriptTimelineDialog.StoryboardDialog=DEBUG
+#log4j.logger.PRE.ScreenRecorder=DEBUG
+#log4j.logger.PRE.TopicRecorder=DEBUG
+
+# SituationMap
+###########################################################
+#log4j.logger.SituationMap=INFO
+
+### rethink SituationMap.Plugins.Gui.SitMap
+#log4j.logger.SituationMap.Plugins.Gui.SitMap=INFO
+#log4j.logger.SituationMap.SituationMapInit=INFO
+#log4j.logger.SituationMap.MapInitializer=INFO
+#log4j.logger.SituationMap.ThatPartyIdToColorFunctor=INFO
+#log4j.logger.SituationMap.RegisterAppHandler=INFO
+
+# SituationMap-AdapterDds:
+#log4j.logger.SituationMap.AdapterDds=INFO
+#log4j.logger.SituationMap.EmergencyCallToMap=INFO
+#log4j.logger.SituationMap.MovementTrack=INFO
+#log4j.logger.SituationMap.MovementTrackManager=INFO
+#log4j.logger.SituationMap.Building2SituationMap=INFO
+#log4j.logger.SituationMap.BuildingOwnership=INFO
+#log4j.logger.SituationMap.BCContamination2SituationMap=INFO
+#log4j.logger.SituationMap.ExplosionSingle2SituationMap=INFO
+#log4j.logger.SituationMap.ExplosionArea2SituationMap=INFO
+#log4j.logger.SituationMap.ExplosionCluster2SituationMap=INFO
+#log4j.logger.SituationMap.ExplosionCluster2SituationMap.update=INFO
+#log4j.logger.SituationMap.GuezIed2SituationMap=INFO
+#log4j.logger.SituationMap.Participant2SituationMap=INFO
+#log4j.logger.SituationMap.HitlineInfo2SituationMap=INFO
+#log4j.logger.SituationMap.MineArea2SituationMap=INFO
+#log4j.logger.SituationMap.MsePointToMap=INFO
+#log4j.logger.SituationMap.MseBridgeToMap=INFO
+#log4j.logger.SituationMap.MountingPointToMap=INFO
+#log4j.logger.SituationMap.SoundAreaToMap=INFO
+#log4j.logger.SituationMap.AerialOrdnance2SituationMap=INFO
+#log4j.logger.SituationMap.BoobyTrap2SituationMap=INFO
+#log4j.logger.SituationMap.OffRoute2SituationMap=INFO
+#log4j.logger.SituationMap.ChargeEffectToMap=INFO
+
+# SituationMap-Core
+#log4j.logger.SituationMap=INFO
+#log4j.logger.SituationMap.MapImpl=INFO
+#log4j.logger.SituationMap.MapSettings=INFO
+#log4j.logger.SituationMap.MapInitializer=INFO
+#log4j.logger.SituationMap.JumpPoints=INFO
+#log4j.logger.SituationMap.JumpPointWidget=TRACE
+#log4j.logger.SituationMap.LayerFactoryImpl=INFO
+#log4j.logger.SituationMap.LayerControl=INFO
+#log4j.logger.SituationMap.LogicalLayer=INFO
+#log4j.logger.SituationMap.CoordTranslationFunctorImpl=INFO
+#log4j.logger.SituationMap.CoordTranslationThread=INFO
+#log4j.logger.SituationMap.PositionsTranslated=INFO
+#log4j.logger.SituationMap.GridImpl=INFO
+#log4j.logger.SituationMap.ObjectFactory=INFO
+#log4j.logger.SituationMap.IdGenerator=INFO
+#log4j.logger.SituationMap.ObjectContainer=INFO
+#log4j.logger.SituationMap.ObjectContainerCTC=INFO
+#log4j.logger.SituationMap.OverlayHandlerImpl=INFO
+#log4j.logger.SituationMap.OverviewMapHandlerImpl=INFO
+#log4j.logger.SituationMap.OverviewMap=INFO
+#log4j.logger.SituationMap.PixelBasedTextBoxHandlerImpl=INFO
+#log4j.logger.SituationMap.ViewshedImpl=INFO
+#log4j.logger.SituationMap.ViewshedBase=INFO
+
+# SituationMap-AbstractMapObject's
+#log4j.logger.SituationMap.AbstractMapObjectImpl=INFO
+#log4j.logger.SituationMap.AbstractEffectSimulationImpl=INFO
+#log4j.logger.SituationMap.OriginTranslated=INFO
+#log4j.logger.SituationMap.PositionsTranslated=INFO
+#log4j.logger.SituationMap.AbstractMultiPointMapObjectImpl=INFO
+#log4j.logger.SituationMap.AbstractSinglePointMapObjectImpl=INFO
+#log4j.logger.SituationMap.BasicPathObjectImpl=INFO
+#log4j.logger.SituationMap.PathContainer=INFO
+#log4j.logger.SituationMap.IndicationContainer=INFO
+
+#log4j.logger.SituationMap.PolygonImpl=INFO
+#log4j.logger.SituationMap.PolylineImpl=INFO
+#log4j.logger.SituationMap.TextImpl=INFO
+
+#log4j.logger.SituationMap.AreaFireImpl=INFO
+#log4j.logger.SituationMap.BiologicalAgentImpl=INFO
+#log4j.logger.SituationMap.BuildingOutlineImpl=INFO
+#log4j.logger.SituationMap.ChemicalAgentImpl=INFO
+#log4j.logger.SituationMap.DangerAreaImpl=INFO
+#log4j.logger.SituationMap.FunctionalAreaImpl=INFO
+#log4j.logger.SituationMap.GeoImageImpl=INFO
+#log4j.logger.SituationMap.HitLineImpl=INFO
+#log4j.logger.SituationMap.ObjectIndicatorImpl=INFO
+#log4j.logger.SituationMap.MineImpl=INFO
+#log4j.logger.SituationMap.MineFieldImpl=INFO
+#log4j.logger.SituationMap.NineLinerImpl=TRACE
+#log4j.logger.SituationMap.NuclearAgentImpl=INFO
+#log4j.logger.SituationMap.ParticipantImpl=INFO
+#log4j.logger.SituationMap.SingleFireImpl=INFO
+#log4j.logger.SituationMap.CubeImpl=INFO
+#log4j.logger.SituationMap.VirtualMineImpl=INFO
+
+#log4j.logger.SituationMap.AbstractGraphicalObject=INFO
+#log4j.logger.SituationMap.GraphicalObjectAttributes=INFO
+#log4j.logger.SituationMap.GraphicalObjectEllipse=INFO
+#log4j.logger.SituationMap.GraphicalObjectPath=INFO
+#log4j.logger.SituationMap.GraphicalObjectMultiPath=INFO
+#log4j.logger.SituationMap.GraphicalObjectPictureMarker=INFO
+#log4j.logger.SituationMap.GraphicalObjectRange=INFO
+#log4j.logger.SituationMap.GraphicalObjectRendererAttributes=INFO
+#log4j.logger.SituationMap.GraphicalObjectSceneMarker=INFO
+#log4j.logger.SituationMap.GraphicalObjectText=INFO
+#log4j.logger.SituationMap.TacticalAppearance=INFO
+
+
+#log4j.logger.SituationMap.ElevationMapManager=DEBUG
+#log4j.logger.SituationMap.ElevationMap=DEBUG
+
+
+
+# SituationMap-Widgets
+#log4j.logger.SituationMap.MapWidgetControl=INFO
+#log4j.logger.SituationMap.LayerControlDialog=INFO
+#log4j.logger.SituationMap.ConfigureMapUrls=INFO
+
+# TargetManagement TGT
+###########################################################
+# SVC
+#log4j.logger.TGT.DdsHandler=INFO
+#log4j.logger.TGT.HandlerTargetConfig=INFO
+# SVC-L400
+#log4j.logger.TGT.HandlerShootbackArea=INFO
+#log4j.logger.TGT.HandlerShootbackTarget=INFO
+#log4j.logger.TGT.HandlerTargetAreaAssignment=INFO
+#log4j.logger.TGT.ObjectShootbackArea=INFO
+#log4j.logger.TGT.ObjectShootbackTarget=INFO
+#log4j.logger.TGT.ObjectTargetAreaAssignment=INFO
+#log4j.logger.TGT.ShootbackController=INFO
+# PLUGIN-L400
+#log4j.logger.Plugins.Gui.Tgt.Target=INFO
+#log4j.logger.TGT.ParticipantHandler=INFO
+#log4j.logger.TGT.AreaDialog=INFO
+#log4j.logger.TGT.AreaEdit=INFO
+#log4j.logger.TGT.AreaModel=INFO
+#log4j.logger.TGT.AssignmentParticipantModel=INFO
+#log4j.logger.TGT.AssignmentDialog=INFO
+#log4j.logger.TGT.AssignmentEditDialog=INFO
+#log4j.logger.TGT.ShootbackTargetEdit=INFO
+#log4j.logger.TGT.TargetPartDialog=INFO
+#log4j.logger.TGT.TargetParticipantModel=INFO
+
+
+# MeteoDataManagement MDM
+###########################################################
+#log4j.logger.MDM.MeteoDataManagementDialog=INFO
+#log4j.logger.MDM.MeteoDataManagementEdit=INFO
+#log4j.logger.MDM.MeteoDataModel=INFO
+#log4j.logger.MDM.InterfaceImpl.MeteoData=INFO
+
+# Messaging MSG
+###########################################################
+#log4j.logger.MSG.MessagingDialog=INFO
+#log4j.logger.MSG.MessagingModel=INFO
+
+# AudioVideoManagement AVM
+###########################################################
+# AVM AudioSettings
+#log4j.logger.AVM.AudioSettingsDialog=DEBUG
+#log4j.logger.AVM.AudioSettingsAvailStreamsModel=DEBUG
+#log4j.logger.AVM.AudioSettingsUsedStreamsModel=DEBUG
+
+# AVM TopicEditor
+#log4j.logger.AVM.AvmSequenceModel=DEBUG
+
+# AVM AVMenuEdit
+#log4j.logger.AVM.Plugins.Gui.Avm.MenuEdit=DEBUG
+#log4j.logger.AVM.AvailableStreamsModel=DEBUG
+#log4j.logger.AVM.UsedStreamsModel=DEBUG
+#log4j.logger.AVM.ChooseMenu=DEBUG
+#log4j.logger.AVM.AudioVideoManagementEdit=DEBUG
+#log4j.logger.AVM.AudioVideoManagementDialog=DEBUG
+#log4j.logger.AVM.MenuViewModel=DEBUG
+#log4j.logger.AVM.NewMenu=DEBUG
+
+# AVM CNR
+#log4j.logger.AVM.Plugins.Gui.Avm.CombatNetRadio=DEBUG
+#log4j.logger.AVM.CombatNetRadioDialog=DEBUG
+#log4j.logger.AVM.CombatNetRadioDialogModel=DEBUG
+#log4j.logger.AVM.EditCombatNetRadioDialog=DEBUG
+
+# AVM CNR FrequencyPlanning
+#log4j.logger.AVM.Plugins.Gui.Avm.CombatNetRadio=DEBUG
+#log4j.logger.AVM.FrequencyPlanningDialog=DEBUG
+#log4j.logger.AVM.FrequencyPlanningDialogModel=DEBUG
+#log4j.logger.AVM.InitFrequencyPlanningDialog=DEBUG
+#log4j.logger.AVM.EditFrequencyPlanningDialog=DEBUG
+#log4j.logger.AVM.EditFrequencyPlanningDataModel=DEBUG
+#log4j.logger.AVM.EditFrequencyPlanningResourceDialog=DEBUG
+#log4j.logger.AVM.EditFrequencyPlanningResourceDataModel=DEBUG
+
+
+# AVM Eloka
+#log4j.logger.AVM.Plugins.Gui.avm.Eloka=DEBUG
+#log4j.logger.AVM.ElokaDialog=DEBUG
+#log4j.logger.AVM.ElokaEditDialog=DEBUG
+#log4j.logger.AVM.ElokaModel=DEBUG
+
+# AVM MobileVideoSystem
+#log4j.logger.AVM.Plugins.Gui.Avm.MobileVideoSystem=DEBUG
+#log4j.logger.AVM.MvsDialog=DEBUG
+#log4j.logger.AVM.EditVideoTeamDialog=DEBUG
+#log4j.logger.AVM.MvsModel=DEBUG
+#log4j.logger.AVM.MvsVideoTeamDialog=DEBUG
+
+# AVM TVC
+#log4j.logger.AVM.Plugins.Gui.Avm.CombatNetRadio=DEBUG
+#log4j.logger.AVM.TrainingVoiceCommunicationDialog=DEBUG
+#log4j.logger.AVM.EditTrainingVoiceCommunicationDialog=DEBUG
+#log4j.logger.AVM.TrainingVoiceCommunicationDialogModel=DEBUG
+
+
+
+# OPM
+###########################################################
+#log4j.logger.OPM.Plugins.Gui.Opm=INFO
+#log4j.logger.OPM.Plugins.Gui.Opm.Edit=INFO
+#log4j.logger.OPM.Plugins.Gui.Opm.Overview=INFO
+#log4j.logger.OPM.Plugins.Gui.Opm.OpmCombobox=INFO
+#log4j.logger.OPM.Plugins.Gui.Opm.Settings=INFO
+#log4j.logger.OPM.Plugins.Gui.Opm.SettingsDialog=INFO
+#log4j.logger.OPM.LoginDialog=INFO
+#log4j.logger.OPM.SettingsGroup=DEBUG
+
+
+# PWS
+###########################################################
+#log4j.logger.PWS.LtsProjetionWorkstation=INFO
+#log4j.logger.PWS.ControlDialog=INFO
+
+# Online Help
+#log4j.logger.OLH.onlineHelp=INFO
+
+# ServiceMonitor
+###########################################################
+#log4j.logger.ServiceMonitorDialog=INFO
+#log4j.logger.ServiceMonitorBiteModel=INFO
+#log4j.logger.ServiceMonitorManipulationModel=INFO
+#log4j.logger.BasePlayerModel=DEBUG
+#log4j.logger.PartyEquipmentCheckDialog=DEBUG
+#log4j.logger.SingleServiceEquipmentCheckDialog=DEBUG
+
+# Appnd_File
+###########################################################
+log4j.appender.file=Lts::RollingFileAppender
+log4j.appender.file.MaxFileSize=100MB
+log4j.appender.file.MaxBackupIndex=9
+#log4j.appender.file.file=${LOG4QT_LOGDIR}/${LOG4QT_USER}_OpApp.log
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
+
+
+# Appnd_Console
+###########################################################
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern= %d %-5p %c{1} |#| %m (%-.30F:%L) %n
+
+#log4j.appender.stdout.layout.ConversionPattern= %d %-5p %-30c |#| %m (%-.30F:%L) %n
+
+
+# Appnd_Syslog
+###########################################################
+log4j.appender.syslog=org.apache.log4j.SyslogAppender
+log4j.appender.syslog.Threshold=ERROR
+log4j.appender.syslog.SysLogHost=localhost
+log4j.appender.syslog.Facility=LOCAL7
+log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
+log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
+log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
+log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
+log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
+
+
+###########################################################
+###########################################################
+###########################################################
+# 1) Available Levels in LOG4CXX Version 0.10.0:
+# TRACE,
+# DEBUG,
+# INFO,
+# WARN,
+# ERROR
+# FATAL
+#
+# d = date/time
+# p = priority (Level)
+# c = category/channel
+# m = message
+# F = file
+# L = line
+# n = platform dependent line separator character or characters.
+# ....
+#
+# Examples for console:
+# a)
+# %d %p %c #%m# (%.50F:%L)%n
+# date/time
+# priority
+# category/channel
+# #message#
+# (Maximal 50Character des Filename von rechts:Line)
+# line separator
+#
+# b)
+# %d (%.15F:%L) %-5p %c |#| %m%n
+# date/time
+# (Maximal 15Character des Filename von rechts:Line)
+# priority, Right pad with spaces if the priority name is less than 5 characters long.
+# category/channel
+# message
+# line separator
+#
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/main.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/main.cpp
new file mode 100755
index 000000000..15d1843a9
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/main.cpp
@@ -0,0 +1,523 @@
+/**
+ * @RDE_HEADER@
+ * main for OperatorApplication
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
+{
+public:
+ CmdLineParser()
+ : LtsCommandLineParser(ProvideCommandLineParameterOptions(CreateDomainIdFromIp | DomainId | ExerciseId | TcpConnectionUrl))
+ {
+ addOption({{QStringLiteral("a"), QStringLiteral("application")},
+ QStringLiteral("Specify the initial application to start (Default: Situation [Demo / Dev - otherwise NOT SPECIFIED => starts AppChooser]"), QStringLiteral("Application"),
+ QStringLiteral("Situation")
+ }); // TODO: remove default on release
+
+ addOption({{QStringLiteral("b"), QStringLiteral("basePlugin")},
+ QStringLiteral("Base Project Plugin Iid to start the application with (Default: )"), QStringLiteral("Base Project Plugin Iid"),
+ QString()
+ }); // TODO: remove default on release
+
+ addOption({{QStringLiteral("s"), QStringLiteral("stylePlugin")},
+ QStringLiteral("Style Plugin to start the application with (Default: rme.light)"), QStringLiteral("Style Plugin Iid"),
+ QStringLiteral("rme.light")
+ });
+
+ addOption({{QStringLiteral("u"), QStringLiteral("username")},
+ QStringLiteral("Preset Username to skip login (also specify -p !)"),
+ QStringLiteral("username")
+ });
+
+ addOption({{QStringLiteral("x"), QStringLiteral("tabletmode")},
+ QStringLiteral("Enforce Tablet Mode"),
+ QStringLiteral("false")
+ });
+
+ addOption({{QStringLiteral("w"), QStringLiteral("workstationmode")},
+ QStringLiteral("Enforce Workstation Mode"),
+ QStringLiteral("false")
+ });
+
+ addOption({{QStringLiteral("q"), QStringLiteral("qos_file")},
+ QStringLiteral("Define QoS Profile "),
+ QStringLiteral("qos_file")
+ });
+
+
+ addOption({{QStringLiteral("p"), QStringLiteral("password")},
+ QStringLiteral("Preset Password to skip login (also specify -u !)"),
+ QStringLiteral("password")
+ });
+
+ addOption({{QStringLiteral("k"), QStringLiteral("skipScreen")},
+ QStringLiteral("Tell the Multi Monitor mode to not put anything on the screen with id n (example: 1 (skips entire screen 1)) - or on sub screen 0 or 1 (left or right) for ultra wide screens (example: 1.1 (skips the right side of screen 1)) (Default: (none))"),
+ QStringLiteral("screen id"),
+ });
+
+ addOption({{QStringLiteral("m"), QStringLiteral("multi-monitor-mode")},
+ QStringLiteral("Use the Multi Monitor mode to place Base Layouts on Screens in Fullscreen")
+ });
+
+#ifdef LTS_DEBUG
+ addOption({QStringLiteral("dbgmmm"),
+ QStringLiteral("Start the multi-monitor-mode with reduced size for use on development maschines")
+ });
+#endif
+
+ addOption({{QStringLiteral("r"), QStringLiteral("replayId")},
+ QStringLiteral("Default: -1"),
+ QStringLiteral("Replay ID"),
+ QStringLiteral("-1")
+ });
+
+ addOption({{QStringLiteral("l"), QStringLiteral("lang")},
+ QStringLiteral("Language iso code to use (de_DE, en_GB, en_US)"),
+ QStringLiteral("")
+ });
+
+ addOption({QStringLiteral("ignore-plugins"),
+ QStringLiteral("Ignore these plugins, which otherwise would be loaded, "
+ "specified by apps.json of the selected Base Plugin. "
+ "Example: \"--ignore-plugins data:avm,data:bdv,gui:avm\""),
+ QStringLiteral("ignore-plugins") // <= value
+ });
+
+ addOption({QStringLiteral("projection"),
+ QStringLiteral("Application is started on an Projection Workstation."),
+ });
+
+ addOption({QStringLiteral("check-requirements"),
+ QStringLiteral("Lets the Plugin Loader check if every App's requirements are met before starting"),
+ });
+ addOption({QStringLiteral("enable-experimental-web-platform-features"),
+ QString(),
+ });
+
+ addOption({QStringLiteral("script"),
+ QStringLiteral("Id of a script. The script has to exist in the given exercise."),
+ QStringLiteral("ScriptId"),
+ QStringLiteral("0")
+ });
+
+ addOption({QStringLiteral("place-script-screens"),
+ QStringLiteral("Let the screen 1 and screen 2 of the script-editor be placed automatically on startup.")
+ });
+
+ m_additionalHelpStr =
+ QStringLiteral("\n\n\e[33m example OWS : %1 -m -a0 -d1 -b legatus -t EXCTDS01:7400 -l de_DE \n\n\e[0m").arg(QCoreApplication::arguments().at(0));
+
+ // fprintf(stdout, "\n\n\e[33m example OWS : %s -m -a0 -d1 -b legatus -t EXCTDS01:7400 -l de_DE \n\n\e[0m", QCoreApplication::arguments().at(0).toLatin1().data());
+
+ }
+
+ QString operatorName() const { return value(QStringLiteral("u")); }
+ QString password() const { return value(QStringLiteral("p")); }
+ int replayId() const { return value(QStringLiteral("r")).toInt(); }
+ QString projectPluginIid() const { return value(QStringLiteral("b")); }
+ QString stylePluginIid() const { return value(QStringLiteral("s")); }
+ int applicationId() const { bool idk = false; int id = value(QStringLiteral("a")).toInt(&idk); if (!idk) { return -1; } return id; }
+ bool multiMonitorMode() const { return isSet(QStringLiteral("m")); }
+ bool isProjectionWorkstation() const { return isSet(QStringLiteral("projection")); }
+ bool isForcedTabletMode() const { return isSet(QStringLiteral("x")); }
+ bool isForcedWSMode() const { return isSet(QStringLiteral("w")); }
+ QString langIsoCode() const { return value(QStringLiteral("l")); }
+ QStringList ignoredPlugins() const { return value(QStringLiteral("ignore-plugins")).split(QLatin1Char(','), QString::SkipEmptyParts); }
+ bool checkRequirements() const { return isSet(QStringLiteral("check-requirements")); }
+ QString skipScreen() const { return value(QStringLiteral("k")); }
+ QString qosFile() const { return value(QStringLiteral("q")).size() > 0 ? value(QStringLiteral("q")) : QString(); }
+ int scriptId() const { return value(QStringLiteral("script")).toInt(); }
+ bool placeScriptScreens() const { return isSet(QStringLiteral("place-script-screens")); }
+#ifdef LTS_DEBUG
+ bool debugMultiMonitorMode() const { return isSet(QStringLiteral("dbgmmm")); }
+#endif
+};
+
+
+// ------------------------------------------------------------------
+int main(int argc, char **argv) // TODO: json strings to lower
+{
+ qsrand(time(nullptr));
+
+ QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
+
+ QScrollerProperties props;
+ props.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
+ props.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
+
+ QScrollerProperties::setDefaultScrollerProperties(props);
+
+ QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
+ //LtsApp app(argc, argv);
+ NGLApplication app(argc, argv);
+ app.createLogger("opApp");
+ QApplication::setQuitOnLastWindowClosed(false); // we are cool enough to handle it ourselves 8)
+ QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+ QNetworkProxy::setApplicationProxy(QNetworkProxy()); // do NOT use proxies anywhere!
+
+ NGL::LoggerHandler *lh = NGL::LoggerHandler::getLoggerHandler();
+ if (lh)
+ {
+ const QByteArray postfix = lh->loggerNamePostfix().toLocal8Bit() + "_dds_";
+ const QByteArray prefix = lh->loggerNamePrefix().toLocal8Bit();
+
+ rti::config::Logger &ddsLogger = rti::config::Logger::instance();
+ //ddsLogger.output_file(fdopen(STDOUT_FILENO, "w"));
+ ddsLogger.output_file_set(postfix.data(), prefix.data(), 10 * 1024 * 1024, 10);
+ ddsLogger.verbosity(rti::config::Verbosity_def::WARNING);
+ //ddsLogger.verbosity_by_category(rti::config::LogCategory_def::COMMUNICATION, rti::config::Verbosity_def::STATUS_ALL);
+ }
+
+
+ // TODO: replace all exit(x) with qApp.quit() and an error msg
+
+ LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(false); // avoid wait screen, we have the splash for this reason!
+
+#ifdef __linux__
+ // svcSituationRep - pgrep/pkill length limitation
+ QProcess::startDetached(QLatin1String("pkill -9 svcSituationRep")); // kill it!
+ QProcess::startDetached(QLatin1String("pkill -9 ffmpeg")); // otherwise a stray ffmpeg may record until the the disk is full
+#elif _WIN32
+ QProcess::startDetached(QLatin1String("taskkill /im svcSituationReplay /f"));
+#endif
+
+ // Parse Options
+ CmdLineParser options;
+ if (!options.init())
+ return -1;
+
+ // Set Translation
+
+ QString langIsoCode = options.langIsoCode();
+ if (langIsoCode.isEmpty())
+ langIsoCode = QLocale::system().name();
+ NGL::setTranslationLocale(langIsoCode.toLatin1());
+
+
+ // Set Style
+ QString stylePluginName = options.stylePluginIid();
+ if (stylePluginName.isEmpty())
+ {
+ ERROR_LOG(app.baseLogger()) << "No Style Plugin Iid specified - abort.";
+ return -1;
+ }
+
+ // .. to keep some compatibility to old resource structure TODO: rm !
+ QDir::setSearchPaths(QLatin1String("icon"), QStringList(QLatin1String(":/style/icons/")));
+ QDir::setSearchPaths(QLatin1String("icon"), QStringList(QLatin1String(":/style/"))); // FIXME: does qt check for recursion ??
+
+
+ LtsUtils::StyleManager::getInstance()->loadStyle(stylePluginName);
+
+
+ // Load Plugins
+ LtsPluginManager::LtsPluginLoader *pluginLoader = LtsPluginManager::LtsPluginLoader::getInstance();
+
+ QString projectPluginName = options.projectPluginIid();
+
+ if (projectPluginName.isEmpty())
+ {
+ bool k;
+ projectPluginName = QInputDialog::getText(nullptr,
+ QCoreApplication::tr("No Project Plugin specified"),
+ QCoreApplication::tr("Please specify a Project Plugin:"), QLineEdit::Normal,
+ QString(), &k); // blocking, no event loop needed
+
+ if (!k || projectPluginName.isEmpty())
+ {
+ ERROR_LOG(app.baseLogger()) << "No Project Plugin Iid specified - abort.";
+ return -1;
+ }
+ }
+
+ // load project plugin
+ if (!pluginLoader->loadPlugins(LtsPluginManager::PluginType::PROJECT, nullptr, {projectPluginName}))
+ {
+ ERROR_LOG(app.baseLogger()) << "Error loading Project Plugin - abort.";
+ return -1;
+ }
+
+ LtsUtils::ProjectSettings::initFromFile(QStringLiteral(":project/project_settings.json"));
+
+ // Setup Application
+ if (options.multiMonitorMode())
+ LtsMultiMonitor::LtsMultiMonitor::getInstance()->setEnableMultiMonitorMode();
+#ifdef LTS_DEBUG
+ if (options.debugMultiMonitorMode())
+ LtsMultiMonitor::LtsMultiMonitor::getInstance()->setDebugMultiMonitorMode();
+#endif
+
+
+ // show splash
+ LtsWidgets::Splash::getInstance()->show();
+
+ LtsAppDescriptor::App applicationId = LtsAppDescriptor::LtsAppDescriptor::appFromInteger(options.applicationId());
+ int exerciseId = options.exerciseId(); // -1 = invalid, 0 = admin, >0 = exercise
+ int replayId = options.replayId(); // -1 = invalid, TODO: comment doku
+ int scriptId = options.scriptId(); // <0 = invalid, 0 = default = ignore, >0 script
+ QString operatorName = options.operatorName();
+ QString password = options.password();
+ QStringList qos_file = QStringList(options.qosFile());
+
+ // TODO: log4cxx/NGLLlogger does not flush here !! messages not seen !
+
+ if (scriptId < 0)
+ {
+ ERROR_LOG(app.baseLogger()) << "Given scriptId " << scriptId << " is invalid - abort.";
+ return -1;
+ }
+
+ if (scriptId > 0 && applicationId != LtsAppDescriptor::App::Scripts)
+ {
+ ERROR_LOG(app.baseLogger()) << "ScriptId set but given app is not Scripts - abort.";
+ return -1;
+ }
+
+ if (scriptId > 0 && exerciseId < 1)
+ {
+ ERROR_LOG(app.baseLogger()) << "ScriptId set but no exercise is given - abort.";
+ return -1;
+ }
+
+ if (scriptId > 0 && exerciseId > 0 && applicationId == LtsAppDescriptor::App::Scripts)
+ {
+ LtsSessionData::LtsSessionData::getInstance()->setScriptId(scriptId);
+ }
+
+ if (options.placeScriptScreens() && applicationId != LtsAppDescriptor::App::Scripts)
+ {
+ ERROR_LOG(app.baseLogger()) << "PlaceScriptScreensn is set but given app is not Scripts - abort.";
+ return -1;
+ }
+
+ LtsSessionData::LtsSessionData::getInstance()->setPlaceScriptScreens(options.placeScriptScreens());
+
+ if (operatorName.isEmpty() != password.isEmpty()) // check for xor and warn user
+ {
+ ERROR_LOG(app.baseLogger()) << "Specify -u if -p is specified & vise versa - abort.";
+ return 1;
+ }
+
+ if (options.domainId() < 0)
+ {
+ ERROR_LOG(app.baseLogger()) << "Invalid configuration for domainId (" << options.domainId() << ") from LtsConfig - abort.";
+ QMessageBox::critical(nullptr, QCoreApplication::tr("Invalid Domain Id"), QCoreApplication::tr("Domain #%1 is not valid - abort.").arg(options.domainId()));
+ return -1;
+ }
+ // }
+
+
+ LtsSessionData::LtsSessionData *sessionData = LtsSessionData::LtsSessionData::getInstance();
+
+ sessionData->setDomainIdPreset(options.domainId());
+ sessionData->setRequestedAppId(applicationId);
+
+ if (options.useTcpConnection())
+ sessionData->setTcpConnectionUrl(options.tcpConnectionUrl());
+
+ if (options.checkRequirements())
+ sessionData->setDebugFlagValue(QStringLiteral("PluginManager.CheckAppRequirements"), true);
+
+ // load JSON app description file
+ QFile appsFile(QStringLiteral(":project/apps.json")); // TODO: convert Json => Binary Json
+
+ if (!appsFile.open(QFile::ReadOnly))
+ {
+ ERROR_LOG(app.baseLogger()) << "Could not read App Description File";
+ return -1;
+ }
+
+ QStringList lastErrors;
+ QString loginPluginIid;
+
+ LtsAppDescriptor::AppDescriptionVector appDescs = LtsAppDescriptor::LtsAppDescriptor::getAppDescriptionVector(appsFile.readAll(),
+ lastErrors,
+ options.ignoredPlugins(),
+ loginPluginIid);
+
+ if (loginPluginIid.isEmpty())
+ loginPluginIid = QStringLiteral("opm.login");
+
+ QString skipScreen = options.skipScreen();
+
+ int skipScreenId = -1;
+ int skipSubScreenId = -1;
+
+ if (!skipScreen.isEmpty())
+ {
+ QStringList skipScreenList(skipScreen.split(QLatin1Char('.'), QString::SkipEmptyParts));
+
+ int skipScreenListCount = skipScreenList.count();
+
+ if (skipScreenListCount > 2)
+ {
+ qWarning() << "invalid skip screen syntax:" << skipScreen;
+ return -1;
+ }
+
+ if (skipScreenListCount > 0)
+ {
+ bool k = false;
+ skipScreenId = skipScreenList.at(0).toInt(&k);
+
+ if (!k)
+ {
+ qWarning() << "invalid skip screen syntax:" << skipScreen;
+ return -1;
+ }
+ }
+
+ if (skipScreenListCount > 1)
+ {
+ bool k = false;
+ skipSubScreenId = skipScreenList.at(1).toInt(&k);
+
+ if (!k)
+ {
+ qWarning() << "invalid skip screen syntax:" << skipScreen;
+ return -1;
+ }
+ }
+ }
+
+ LtsMultiMonitor::LtsMultiMonitor::getInstance()->setSkipScreen(skipScreenId, skipSubScreenId);
+
+ appsFile.close();
+
+ if (!lastErrors.isEmpty())
+ {
+ QMessageBox::critical(nullptr, QString(), lastErrors.join(QStringLiteral("\r\n\r\n")));
+ // TODO: log precise msg !!
+ return -1;
+ }
+
+
+ if(options.isForcedTabletMode())
+ sessionData->setAsTablet();
+ else if (options.isForcedWSMode())
+ sessionData->setAsTablet(false);
+ else if (!QTouchDevice::devices().isEmpty())
+ sessionData->setAsTablet();
+ LtsWidgets::LtsComboBox::setUseSelectionDialog(sessionData->isTablet());
+
+ LtsAppManager::LtsAppManager *appManager = LtsAppManager::LtsAppManager::getInstance();
+ appManager->setAvailableApps(appDescs);
+
+
+ // Projection Specific Setup
+ if (options.isProjectionWorkstation())
+ {
+ if (operatorName.isEmpty() && password.isEmpty())
+ {
+ ERROR_LOG(app.baseLogger()) << "Projection-User & Password has to be specified when --projection option is active!";
+ return 1;
+ }
+
+ applicationId = LtsAppDescriptor::App::Situation;
+
+ LtsProjectionWorkstation::LtsProjectionWorkstation::getInstance()->setProjectionOperatorPreset(operatorName, password);
+ }
+ // Normal Setup
+ else
+ {
+ if (applicationId == LtsAppDescriptor::App::Login)
+ INFO_LOG(app.baseLogger()) << "No Application specified - starting with App Chooser.";
+
+ // TODO: replayid can not life without exerciseId
+ if (exerciseId >= 0 && replayId >= 0) // do not set both!
+ {
+ ERROR_LOG(app.baseLogger()) << "Use either -e (exercise) or -r (replay) - abort.";
+ return 1;
+ }
+
+ if (!operatorName.isEmpty() && !password.isEmpty())
+ {
+ sessionData->setOperatorPreset(operatorName, password); // if -u and -p (no Login window !)
+ }
+
+ if (exerciseId == 0) // Admin Session was requested explicitly
+ {
+ //sessionManager->setGlobalSessionVisible();
+ sessionData->setPartitionPreset(exerciseId, IDL::PartitionType::Global);
+ }
+
+ if (!qos_file.isEmpty()) // use defined qos file
+ {
+ //sessionManager->setGlobalSessionVisible();
+ DEBUG_LOG(app.baseLogger()) << "QOS -> using new file" << qos_file.join(QStringLiteral(","));
+ sessionData->setQosFile(qos_file);
+ }
+
+ if (exerciseId > 0) // non Admin => Exercise
+ sessionData->setPartitionPreset(exerciseId, IDL::PartitionType::Exercise);
+
+ if (replayId >= 0) // Replay
+ sessionData->setPartitionPreset(replayId, IDL::PartitionType::Replay);
+ }
+
+ appManager->setLoginPluginIid(loginPluginIid);
+ appManager->setMainApp(applicationId);
+ if (applicationId == LtsAppDescriptor::App::ThpSituationReplay)
+ {
+ LtsSessionData::LtsSessionData::getInstance()->setVisibleParties({});
+ LtsSessionData::LtsSessionData::getInstance()->setOperatorRights({-1});
+ QTimer::singleShot(0, appManager, [qos_file, appManager]()
+ {
+ LtsSession::DdsConnectionParams params;
+ params.domainId = 1;
+ params.exerciseId = 2;
+ params.partitionId = 2;
+ if (!qos_file.isEmpty())
+ params.qos_file = qos_file;
+
+ params.partitionType = IDL::PartitionType::Replay;
+ appManager->createApp(LtsAppDescriptor::App::Situation, params, {}, false, true);
+ } );
+ }
+ else
+ {
+ appManager->showLogin();
+ }
+
+ // Startup Application
+ STARTUP_LOG(app.baseLogger());
+ int iRet = app.exec();
+ SHUTDOWN_LOG(app.baseLogger());
+
+ return iRet;
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/opapp.rc.cmake b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/opapp.rc.cmake
new file mode 100755
index 000000000..01c63c9cf
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/OpApp/opapp.rc.cmake
@@ -0,0 +1,30 @@
+#include
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @OPAPP_VERSION_INFO@
+ PRODUCTVERSION @OPAPP_VERSION_INFO@
+ FILEFLAGSMASK 0x0L
+ FILEFLAGS 0x0L
+ FILEOS VOS_NT_WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040704b0"
+ BEGIN
+ VALUE "CompanyName", "Rheinmetall Electronics GmbH"
+ VALUE "FileDescription", "Operator Application (64bit)"
+ VALUE "FileVersion", "@OPAPP_VERSION_INFO@"
+ VALUE "InternalName", "OpApp"
+ VALUE "LegalCopyright", "Copyright © 2018 Rheinmetall Electronics GmbH. Alle Rechte vorbehalten"
+ VALUE "OriginalFilename", "OperatorApplication.exe"
+ VALUE "ProductName", "Operator Application"
+ VALUE "ProductVersion", "@OPAPP_VERSION_INFO@"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x407, 1200
+ END
+END
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/CMakeLists.txt
new file mode 100755
index 000000000..a1fa02a8d
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/CMakeLists.txt
@@ -0,0 +1,127 @@
+#
+# THP-Viewer
+#
+ADD_SUBDIRECTORY(THP-Starter)
+FIND_PACKAGE(VLC REQUIRED)
+
+SET(thp_viewer_SRCS
+ main.cpp
+ thp_plugin_provider.cpp
+ thp_plugin_provider.h
+ thp_situation_filter_interface_impl.cpp
+ thp_situation_filter_interface_impl.h
+ thp_viewer.cpp
+ thp_viewer.h
+
+ thpwidgets/thp_audio_video_widget.cpp
+ thpwidgets/thp_audio_video_widget.h
+ thpwidgets/thp_audio_video_widget_p.h
+ thpwidgets/thp_building_settings.cpp
+ thpwidgets/thp_building_settings.h
+ thpwidgets/thp_building_widget.cpp
+ thpwidgets/thp_building_widget.h
+ thpwidgets/thp_html_widget.cpp
+ thpwidgets/thp_html_widget.h
+ thpwidgets/thp_pdf_widget.cpp
+ thpwidgets/thp_pdf_widget.h
+ thpwidgets/thp_situation_building_base.h
+ thpwidgets/thp_situation_building_base.cpp
+ thpwidgets/thp_situation_filter_aes.cpp
+ thpwidgets/thp_situation_filter_aes.h
+ thpwidgets/thp_situation_filter_building_components.cpp
+ thpwidgets/thp_situation_filter_building_components.h
+ thpwidgets/thp_situation_filter_collapse_expand.cpp
+ thpwidgets/thp_situation_filter_collapse_expand.h
+ thpwidgets/thp_situation_filter_symbol_appearance.cpp
+ thpwidgets/thp_situation_filter_symbol_appearance.h
+ thpwidgets/thp_situation_filter_types.cpp
+ thpwidgets/thp_situation_filter_types.h
+ thpwidgets/thp_situation_widget.cpp
+ thpwidgets/thp_situation_widget.h
+ thpwidgets/thp_zoom_slider.cpp
+ thpwidgets/thp_zoom_slider.h
+)
+
+NGL_WRAP_UI(thp_viewer_SRCS
+ thp_viewer.ui
+ thpwidgets/thp_audio_video_widget.ui
+ thpwidgets/thp_building_settings.ui
+ thpwidgets/thp_html_widget.ui
+ thpwidgets/thp_pdf_widget.ui
+ thpwidgets/thp_situation_building_base.ui
+)
+IF(WIN32)
+ SET(JBN ${JENKINS_BUILD_NUMBER})
+ IF (NOT JENKINS_BUILD_NUMBER)
+ SET(JBN "0")
+ ENDIF()
+ SET(THP_VERSION_INFO "${LTS_VERSION_MAJOR}, ${LTS_VERSION_MINOR}, ${JBN}, ${LTS_VERSION_PATCH}")
+ CONFIGURE_FILE(thp_viewer.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/thp_viewer.rc)
+ LIST(APPEND thp_viewer_SRCS ${CMAKE_CURRENT_BINARY_DIR}/thp_viewer.rc)
+ENDIF(WIN32)
+NGL_ADD_APP_ICON(thp_viewer_SRCS)
+
+NGL_ADD_EXECUTABLE(WS thp_viewer WIN32 ${thp_viewer_SRCS})
+NGL_INSTALL_TARGET(thp_viewer)
+NGL_TARGET_INCLUDE_DIRECTORIES(thp_viewer
+ PRIVATE
+ ${VLC_INCLUDE_DIR}
+)
+NGL_TARGET_COMPILE_DEFINITIONS(thp_viewer
+ PRIVATE
+ ${VLC_DEFINES}
+)
+NGL_TARGET_LINK_LIBRARIES(thp_viewer
+ ArcGISQt5Hack # make sure it's loaded *before* libEsriCommonQt.so
+
+ ${VLC_LIBRARIES}
+ Qt6::Core
+ Qt6::Gui
+ Qt6::PrintSupport
+ Qt6::Svg
+ Qt6::WebEngineCore
+ Qt6::WebEngineWidgets
+ Qt6::Widgets
+ Qt6::Xml
+
+ RmeLightStyleQrc
+
+ AsbData
+ AsbForeignDataPluginThp
+ BuildingViewerCommon
+ FltAesGuiCommon
+ FltAesWidget
+ FltBldgCmpntWidget
+ FltParticipantWidget
+ IsmDataPluginThp
+ LtsCoordTrans
+ LtsCommandLineParser
+ NGLLogger
+ nglsingleapplication
+ ngltools
+ ngltranslator
+ nglwidgets
+ PdmComboBoxGui
+ PpmComboBoxGui
+ SitmapDds
+ SituationReplaySqlite
+
+ svcFlmCommon
+
+ svcAesClient
+ svcBldClient
+ svcCesClient
+ svcGimClient
+ svcIsmClient
+ svcPpmClient
+ svcPdmClient
+ svcAlmClient
+)
+IF(WIN32)
+# NGL_INSTALL(WS FILES autorun.inf DESTINATION bin)
+# NGL_INSTALL(WS FILES readme.win32.en_US.txt DESTINATION bin)
+# NGL_INSTALL(WS FILES readme.win32.de_DE.txt DESTINATION bin)
+ENDIF()
+NGL_INSTALL(WS FILES log4cxx_thp_viewer.props DESTINATION bin)
+
+ADD_SUBDIRECTORY(SitMapReplayTest)
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/README.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/README.txt
new file mode 100755
index 000000000..56388c104
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/README.txt
@@ -0,0 +1,101 @@
+#
+# Hinweise für das THP
+#
+# $Id$
+# $HeadURL$
+# $Author$
+#
+
+N. Thoden, 12.03.2020
+
+Das TakeHomePackage (für Windows) besteht aus 3 Komponenten:
+============================================================
+
+1) den THP-Viewer / THP-Starter
+ (inkl. Qt ; ohne MSVCRuntime, z.B. msvcr120.dll, in C:\Windows\system32 !?)
+ http://jenkins-master.sl.defence-elec.de:8080/job/ahtc_OC-Tablet/
+ thp.tgz
+2) die Kartendaten
+ (evtl. für den Datenträger reduziert in Bezug auf die Speichergröße)
+3) die Topic-Daten (Video, Audio, DB-Abzug...)
+
+
+Woher kommt was?
+================
+1) Der THP-Viewer / THP-Starter
+ Kann aus der CI-Umgebung (Jenkins) heruntergeladen werden (thp.tgz)
+ Am besten mit 7Zip entpackt werden:
+ (tgz -> gepackt und anschliessend komprimiert)
+ - Per Kontext-Menue "entpacken nach hier"
+ - die resultierende Datei "thp' "entpacken nach thp~".
+ Dann sollte ein Verzeichnis "thp" MIT diversen Unterverzeichnissen entstehen.
+
+ Das THP-Verzeichnis wird auf jeder Workstation im Ordner /opt/THP als Quelle für den USB-Datentraeger bereitgestellt.
+
+2) Diese werden manuell für das THP bereitgestellt (meist als tpk-Datei).
+
+3) Die Topic-Daten werden in der OpApp mit "Präsentation exportieren" erzeugt.
+ Sie werden unter /tmp/THP-Export generiert.
+
+
+Woher kommt das Verzeichnis 'Maps'?
+===================================
+Der Verzeichnisname 'Maps' ist fest und darf nicht verändert werden.
+Es müssen die für das Medium (CD, DVD, Stick..) passenden Basiskarten/Kartendaten hinein.
+Das sind also z.B.
+ - 2020-03-03_UaeAerial_32639_Lvl6.tpk
+ - 2020-03-03_UaeAerial_WebMerc_Lvl15.tpk
+ - 2020-03-03_UaeTopo_32639_Lvl6.tpk
+ - 2020-03-03_UaeTopo_WebMerc_Lvl15.tpk
+ - AHTC_utm_dgm_surface_wgs84.tif
+
+Das layerMapping.json hat nun die Aufgabe, diese (für das Übungsgebiet) spezifischen
+Dateinamen zu abstrahieren.
+Die bei der Ausführung des THPs geforderten Basiskarten (Annahme: eine Topo und zwei Aerial)
+können mit Hilfe der layerMapping.json auf eine geringere Anzahl Dateien gemappt werden.
+
+Basiskarten: Mapping per layerMapping.json
+ in der WS-App: Dateien in Dir 'Maps'
+ -------------- ---------------------
+ - Aerial2 -> 2020-03-03_UaeAerial_32639_Lvl6.tpk
+ - Aerial1 -> 2020-03-03_UaeAerial_32639_Lvl6.tpk
+ - Topo -> 2020-03-03_UaeTopo_32639_Lvl6.tpk
+
+Best Practise:
+Daher ergibt es Sinn, eine layerMapping.json in dem Verzeichnis 'Maps' vorzubereiten
+und beim Zusammengefügen in die darüberliegende Dateiebene zu kopieren.
+
+
+Wie müssen die 3 Komponenten zusammengefügt werden?
+===================================================
+
+Device:
+ - Excersise_6
+ - 1 <- Übungsdaten (Komponenten 3)
+ - ...
+ - index.html <- Übungsdaten (Komponenten 3)
+ - ... <- Übungsdaten (Komponenten 3)
+
+ - Maps <- Kartendaten (Komponenten 2)
+ - *.tpk
+ - [layerMapping.json] <- Sonderfall AHTC 03/2020: Diese Datei in
+ die darüberliegende Ebenen verschieben.
+ - layerMapping.json <- Übungsdaten (Komponenten 2/3)
+ (generiert, Sonderfall AHTC 03/2020:
+ aus 'Maps' hierher transferieren)
+
+ - thp <- thp (Komponenten 1)
+ - resources <- thp (Komponenten 1), hat mal gefehlt)
+ - thv_viewer.exe <- thp (Komponenten 1)
+ - vc.redist.x64.exe <- thp (Komponenten 1), für MSVCRuntime
+ - thp_starter.exe <- thp (Komponenten 1)
+ - autorun.inf <- thp (Komponenten 1)
+ - [wappen.png] <- thp (Komponenten 1 oder 3) optional !?
+
+
+Logfiles zuir Fehlersuche
+=========================
+Ein Logfile befindet sich unter ~Benutzer\AppData\Local\Temp\.
+Bsp: C:\User\thoden\AppData\Local\Temp\thoden_thp.log
+ C:\User\thoden\AppData\Local\Temp\thoden_thp.log.1
+
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/CMakeLists.txt
new file mode 100755
index 000000000..4af2ca45a
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/CMakeLists.txt
@@ -0,0 +1,40 @@
+#
+# SitMapReplayTest
+#
+SET(SRPTEST_SRCS
+ srp_main.cpp
+ srp_main_window.cpp
+ srp_main_window.h
+ ../thp_plugin_provider.cpp
+ ../thp_plugin_provider.h
+ ../thp_situation_filter_interface_impl.cpp
+ ../thp_situation_filter_interface_impl.h
+)
+NGL_WRAP_UI(SRPTEST_SRCS
+ srp_main_window.ui
+)
+NGL_ADD_EXECUTABLE(WS SitMapReplayTest ${SRPTEST_SRCS})
+NGL_TARGET_LINK_LIBRARIES(SitMapReplayTest
+ SituationReplaySqlite
+
+ ddsconnector
+ Qt6::Core
+ nglapplication
+ SitmapDds
+
+ AsbForeignDataPluginThp
+ BuildingViewerCommon
+ FltAesGuiCommon
+ IsmDataPluginThp
+
+ svcFlmCommon
+
+ svcAesClient
+ svcBldClient
+ svcCesClient
+ svcGimClient
+ svcIsmClient
+ svcPpmClient
+ svcPdmClient
+)
+
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main.cpp
new file mode 100755
index 000000000..34268f7a8
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main.cpp
@@ -0,0 +1,64 @@
+/**
+ * @RDE_HEADER@
+ * Main for SitMapReplayTest
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "../thp_plugin_provider.h"
+#include "srp_main_window.h"
+#include "ui_srp_main_window.h"
+
+int main(int argc, char **argv)
+{
+ QNetworkProxy::setApplicationProxy(QNetworkProxy());
+ NGLApplication app(argc, argv);
+ app.createLogger("SRP");
+ app.setAttribute(Qt::AA_UseHighDpiPixmaps);
+
+ SituationReplay::ConnectionParams connParams;
+ connParams.domainId = 1;
+ connParams.partitionId = 1;
+ std::shared_ptr srpMainHandler(new SituationReplay::MainHandlerSqlite);
+ if (!srpMainHandler->initDds(connParams))
+ return 1;
+ // TODO: fixme or trash me
+ SituationReplay::ReplayInformation ri;
+ ri.databaseFilePath = QStringLiteral("dump.sqlite");
+ ri.replayConfigPath = QStringLiteral("dump.json");
+ if (!srpMainHandler->initDb(ri, {}, {}))
+ return 2;
+
+ std::shared_ptr ddsConn = srpMainHandler->ddsReplay();
+ THP::SitMapPluginProvider *pp = new THP::SitMapPluginProvider;
+ pp->init(ddsConn);
+
+ SituationMap::SituationMapInit *smi = new SituationMap::SituationMapInit(nullptr);
+ smi->initPluginProvider(pp);
+
+ QPointer movementTrackMgr =
+ QPointer(new SituationMap::MovementTrackManager(smi));
+
+ smi->initAdapter(movementTrackMgr, false);
+ smi->initMap(true, SituationMap::Mode::Mode_2D);
+
+ SituationReplay::MainWindow *mw = new SituationReplay::MainWindow(smi, srpMainHandler->handlerSrp());
+ mw->show();
+
+ int ret = app.exec();
+
+ delete mw;
+ delete smi;
+ delete pp;
+ ddsConn.reset();
+ return ret;
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.cpp
new file mode 100755
index 000000000..9b98756d3
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.cpp
@@ -0,0 +1,47 @@
+/**
+ * @RDE_HEADER@
+ * MainWindow for SitMapReplayTest
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+
+#include "srp_main_window.h"
+#include "ui_srp_main_window.h"
+#include
+#include
+
+namespace SituationReplay
+{
+MainWindow::MainWindow(SituationMap::SituationMapInit *sitMap,
+ const std::shared_ptr &srpHandler,
+ QWidget *parent)
+ : QMainWindow(parent)
+ , m_srpHandler(srpHandler)
+ , m_ui(new Ui::SrpMainWindow)
+{
+ m_ui->setupUi(this);
+ setCentralWidget(sitMap->getWidget());
+ connect(m_ui->actionStart_Replay, &QAction::triggered, this, &MainWindow::onStartReplay);
+ connect(m_ui->actionStop_Replay, &QAction::triggered, this, &MainWindow::onStopReplay);
+}
+
+MainWindow::~MainWindow()
+{
+ delete m_ui;
+}
+
+void MainWindow::onStartReplay()
+{
+ const qint64 begin = (time(nullptr) - 60 * 60 * 30) * 1000;
+ const qint64 end = 0;
+ const double pace = 1;
+ m_srpHandler->onStartReplayRequest(begin, end, pace);
+}
+
+void MainWindow::onStopReplay()
+{
+ m_srpHandler->onStopReplayRequest();
+}
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.h b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.h
new file mode 100755
index 000000000..b653e0b6a
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.h
@@ -0,0 +1,41 @@
+/**
+ * @RDE_HEADER@
+ * MainWindow for SitMapReplayTest
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+#pragma once
+
+#include
+#include
+
+namespace Ui
+{
+class SrpMainWindow;
+}
+namespace SituationMap
+{
+class SituationMapInit;
+}
+namespace SituationReplay
+{
+class HandlerSituationReplaySqlite;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow(SituationMap::SituationMapInit *sitMap,
+ const std::shared_ptr &srpHandler,
+ QWidget *parent = nullptr);
+ ~MainWindow();
+protected slots:
+ void onStartReplay();
+ void onStopReplay();
+private:
+ std::shared_ptr m_srpHandler;
+ Ui::SrpMainWindow *m_ui;
+};
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.ui b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.ui
new file mode 100755
index 000000000..aa92e573a
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/SitMapReplayTest/srp_main_window.ui
@@ -0,0 +1,49 @@
+
+
+ SrpMainWindow
+
+
+
+ 0
+ 0
+ 800
+ 600
+
+
+
+ MainWindow
+
+
+
+
+
+
+ Start Replay
+
+
+
+
+ Stop Replay
+
+
+
+
+
+
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/CMakeLists.txt
new file mode 100755
index 000000000..9d60bb14f
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/CMakeLists.txt
@@ -0,0 +1,22 @@
+#
+# $Id$
+# $HeadURL$
+# $Author$
+#
+
+IF(WIN32)
+ # static msvc runtime
+ FOREACH(flag_var
+ CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ IF(${flag_var} MATCHES "/MD")
+ STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+ ENDIF()
+ ENDFOREACH()
+ SET(THP_ICO "${CMAKE_SOURCE_DIR}/Lts/Common/LtsWidgets/resources/rde_icon_256.ico")
+ CONFIGURE_FILE(thp_starter.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/thp_starter.rc)
+
+ NGL_ADD_EXECUTABLE(WS thp_starter WIN32 thp_starter.cpp ${CMAKE_CURRENT_BINARY_DIR}/thp_starter.rc)
+ NGL_TARGET_LINK_LIBRARIES(thp_starter user32.lib opengl32.lib gdi32.lib)
+ NGL_INSTALL_TARGET(thp_starter)
+ENDIF(WIN32)
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/thp_starter.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/thp_starter.cpp
new file mode 100755
index 000000000..9f457ce41
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/thp_starter.cpp
@@ -0,0 +1,149 @@
+/**
+ * @RDE_HEADER@
+ * Small wrapper to automatically start thp_viewer
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+
+#include
+#include
+#include
+
+static void* getGLExtensionFuncPtr(const char *funcName, const char *fallbackFuncName)
+{
+ void* ptr = wglGetProcAddress(funcName);
+ if (ptr)
+ return ptr;
+ return wglGetProcAddress(fallbackFuncName);
+}
+
+static int checkOpenGL(HWND hWnd)
+{
+ HDC hDC = GetDC( hWnd );
+
+ PIXELFORMATDESCRIPTOR pfd;
+ ZeroMemory( &pfd, sizeof( pfd ) );
+ pfd.nSize = sizeof( pfd );
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER |
+ PFD_SWAP_EXCHANGE;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 32;
+ pfd.cRedBits = 8;
+ pfd.cGreenBits = 8;
+ pfd.cBlueBits = 8;
+ pfd.cAlphaBits = 8;
+ pfd.cDepthBits = 0;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ int iFormat = ChoosePixelFormat( hDC, &pfd );
+ if( !SetPixelFormat( hDC, iFormat, &pfd ) ) {
+ DWORD dw = GetLastError();
+ int ret = MessageBox(NULL,
+ L"Your system does not support some mandatory OpenGL Functions.\nThe THP-Viewer may not display all things correct!\nDo you really want to start the THP-viewer?",
+ L"THP-Viewer startup",
+ MB_ICONWARNING|MB_YESNO);
+ if(ret == IDNO) {
+ ReleaseDC( hWnd, hDC );
+ return 1;
+ }
+ }
+
+ HGLRC hRC = wglCreateContext( hDC );
+
+ DWORD dw = wglMakeCurrent( hDC, hRC );
+ void *_glCompressedTexImage2D = getGLExtensionFuncPtr( "glCompressedTexImage2D", "glCompressedTexImage2DARB" );
+ if(!_glCompressedTexImage2D) {
+ int ret = MessageBox(NULL,
+ L"Your system does not support the mandatory OpenGL Function glCompressedTexImage2D.\nThe THP-Viewer may not display all things correct!\nDo you really want to start the THP-viewer?",
+ L"THP-Viewer startup",
+ MB_ICONWARNING|MB_YESNO);
+ if(ret == IDNO) {
+ wglDeleteContext( hRC );
+ ReleaseDC( hWnd, hDC );
+ return 1;
+ }
+ }
+
+ wglDeleteContext( hRC );
+ ReleaseDC( hWnd, hDC );
+
+ return 0;
+}
+
+static int startThpViewer(HINSTANCE hInstance)
+{
+ TCHAR fn[MAX_PATH*10];
+ DWORD len = GetModuleFileName(hInstance, fn, sizeof(fn));
+
+ for(int i = len - 1; i >= 0; --i) {
+ if(fn[i] == '\\')
+ break;
+ fn[i] = '\0';
+ }
+ wcscat(fn, L"thp\\thp_viewer.exe");
+
+ STARTUPINFO si; ZeroMemory(&si, sizeof(si));
+ PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi));
+ si.cb = sizeof(si);
+
+ DWORD ret = CreateProcess(fn,
+ NULL, // lpCommandLine
+ NULL, // lpProcessAttributes
+ NULL, // lpThreadAttributes
+ NULL, // bInheritHandles
+ 0, // dwCreationFlags
+ NULL, // lpEnvironment
+ NULL, // lpCurrentDirectory
+ &si, // lpStartupInfo
+ &pi); // lpProcessInformation
+
+ if(ret == 0) {
+ MessageBox(NULL,
+ L"Error starting the THP-Viewer!",
+ L"THP-Viewer startup",
+ MB_ICONWARNING|MB_OK);
+ return 1;
+ }
+ // Wait until child process exits.
+ WaitForSingleObject( pi.hProcess, INFINITE );
+
+ // Close process and thread handles.
+ CloseHandle( pi.hProcess );
+ CloseHandle( pi.hThread );
+
+ return 0;
+}
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc( hWnd, message, wParam, lParam );
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow)
+{
+ WNDCLASS wc;
+ ZeroMemory( &wc, sizeof(wc) );
+ // register window class
+ wc.style = CS_OWNDC;
+ wc.lpfnWndProc = WndProc;
+ wc.hInstance = hInstance;
+ wc.lpszClassName = L"THP_Viewer_startup";
+ RegisterClass( &wc );
+
+ // create main window
+ HWND hWnd = CreateWindow(L"THP_Viewer_startup",
+ L"THP-Viewer startup",
+ WS_CAPTION | WS_POPUPWINDOW,
+ 0, 0, 256, 256,
+ NULL, NULL, hInstance, NULL );
+
+ int iRet = checkOpenGL(hWnd);
+ if(iRet != 0)
+ return iRet;
+ return startThpViewer(hInstance);
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/thp_starter.rc.cmake b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/thp_starter.rc.cmake
new file mode 100755
index 000000000..bd838c67a
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/THP-Starter/thp_starter.rc.cmake
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "@THP_ICO@"
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/autorun.inf b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/autorun.inf
new file mode 100755
index 000000000..a4a4ec31a
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/autorun.inf
@@ -0,0 +1,6 @@
+[autorun]
+OPEN=thp\bin\thp_viewer.exe
+ICON=thp\bin\thp_viewer.exe,0
+SHELL=readit
+SHELL\readit="THP-Viewer starten"
+SHELL\readit\command=thp\bin\thp_viewer.exe
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/log4cxx_thp_viewer.props b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/log4cxx_thp_viewer.props
new file mode 100755
index 000000000..f30520ea3
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/log4cxx_thp_viewer.props
@@ -0,0 +1,28 @@
+log4j.reset=true
+log4j.rootLogger=WARN, file
+
+#log4j.logger.GDW=WARN
+#log4j.logger.GDW_CTC=WARN
+#log4j.logger.KALA=WARN
+#
+# THP
+#
+#log4j.logger.THP=WARN
+#log4j.logger.THP.AudioVideoWidget=WARN
+#log4j.logger.THP.PlanFilter=WARN
+#log4j.logger.THP.SymbolLoaderThread=WARN
+#log4j.logger.THP.SHMFileHandler=WARN
+
+# Appender
+############
+log4j.appender.file=Lts::RollingFileAppender
+log4j.appender.file.MaxFileSize=1MB
+log4j.appender.file.MaxBackupIndex=9
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
+
+# Appnd_Console
+###########################################################
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/main.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/main.cpp
new file mode 100755
index 000000000..50cb9cfe9
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/main.cpp
@@ -0,0 +1,166 @@
+/**
+ * @RDE_HEADER@
+ * Main entry for thp viewer
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "thp_viewer.h"
+#include
+#include
+
+#ifdef Q_OS_WIN
+# include
+#endif
+
+class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
+{
+public:
+ CmdLineParser()
+ : LtsCommandLineParser(ProvideCommandLineParameterOptions::None)
+ {
+ addOption({{QStringLiteral("l"), QStringLiteral("lang")},
+ QStringLiteral("Language iso code to use (de_DE, en_GB, en_US)"),
+ QStringLiteral("")
+ });
+ addOption({{QStringLiteral("t"), QStringLiteral("alwaysontop")},
+ QStringLiteral("Set as always on top window")
+ });
+ }
+ bool useAsAlwaysOnTop() const
+ {
+ return isSet(QStringLiteral("t"));
+ }
+ QString langIsoCode() const { return value(QStringLiteral("l")); }
+};
+
+int main(int argc, char **argv)
+{
+ QNetworkProxy::setApplicationProxy(QNetworkProxy());
+
+ NGLSingleApplication app(argc, argv);
+ app.createLogger("THP", "log4cxx_thp_viewer.props");
+ app.setOrganizationName(QStringLiteral("RME"));
+ app.setApplicationName(QStringLiteral("thp_viewer"));
+ app.setAttribute(Qt::AA_UseHighDpiPixmaps);
+
+ QDir::setSearchPaths(QLatin1String("icon"), QStringList(QLatin1String(":/style/")));
+ Q_INIT_RESOURCE(rme_light_style);
+
+ // Parse Options
+ CmdLineParser options;
+ if (!options.init())
+ return -1;
+
+ // Set Translation
+ QString langIsoCode = options.langIsoCode();
+ if (langIsoCode.isEmpty())
+ langIsoCode = QLocale::system().name();
+ NGL::setTranslationLocale(langIsoCode.toLatin1());
+
+ //check for optional alyways on top flag
+ bool alwaysOnTop = options.useAsAlwaysOnTop();
+
+ QString index;
+ const QStringList args = options.positionalArguments();
+
+// QString searchDir = QCoreApplication::applicationDirPath();
+ QString searchDir(QDir::currentPath());
+
+ if (args.count() == 1)
+ {
+ QFileInfo fi(args.first());
+ if (fi.isDir())
+ searchDir = fi.absolutePath();
+ else
+ index = fi.absoluteFilePath();
+ }
+
+ if (index.isEmpty())
+ {
+ const auto indexFiles = { QStringLiteral("index_%1.html").arg(langIsoCode),
+ QStringLiteral("index.html") };
+ for (const QString &indexFile : indexFiles)
+ {
+ QDir d(searchDir);
+ index = d.absoluteFilePath(indexFile);
+ while (!d.exists(index))
+ {
+ if (!d.cdUp())
+ break;
+ index = d.absoluteFilePath(indexFile);
+ }
+ if (d.exists(index))
+ break;
+ }
+ }
+
+ QFileInfo fi(index);
+ QString basePath = fi.path() + QLatin1Char('/');
+ if (!fi.exists() || !fi.isFile())
+ {
+ fprintf(stderr, "%s basePath=%s\n", argv[0], basePath.toStdString().c_str());
+ QMessageBox::critical(nullptr,
+ QObject::tr("File missing"),
+ QObject::tr("Could not find a valid index.html - aborting"));
+ return -1;
+ }
+ index = fi.absoluteFilePath();
+
+ if (app.sendMessage(index))
+ return 0;
+
+ int ret = 1;
+ {
+ QString splashfile = basePath;
+ static const auto extension = {QStringLiteral("gif"),
+ QStringLiteral("jpg"),
+ QStringLiteral("png")};
+ for (const auto &ext : extension)
+ {
+ const QString fn = splashfile + QStringLiteral("/wappen.") + ext;
+ if (!QFile::exists(fn))
+ continue;
+ splashfile = fn;
+ break;
+ }
+
+ const QPixmap splashPixmap(splashfile);
+ QSplashScreen splash((splashPixmap));
+ if (!splashPixmap.isNull())
+ splash.show();
+
+#ifdef BUILD_STATIC_LIBRARIES
+ Q_INIT_RESOURCE(libsymbol);
+ Q_INIT_RESOURCE(nglresources);
+#endif
+
+ NGL::ThpViewer view(QUrl::fromLocalFile(index));
+ if (alwaysOnTop)
+ {
+ view.setWindowFlag(Qt::WindowStaysOnTopHint, true);
+ view.setWindowFlag(Qt::WindowMinimizeButtonHint, false);
+ }
+
+ if (!view.init())
+ return ret;
+ view.center();
+
+ QObject::connect(&app, &NGLSingleApplication::messageReceived,
+ &view, &NGL::ThpViewer::onNewThp);
+ view.show();
+ splash.finish(&view);
+
+ ret = app.exec();
+ }
+
+ return ret;
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_plugin_provider.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_plugin_provider.cpp
new file mode 100755
index 000000000..0d4b73d9c
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_plugin_provider.cpp
@@ -0,0 +1,105 @@
+/**
+ * @RDE_HEADER@
+ * Plugin Provider for standalone SRP / THP
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+
+#include "thp_plugin_provider.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "thp_situation_filter_interface_impl.h"
+
+namespace THP
+{
+
+QString SitMapPluginProvider::toString() const
+{
+ return QString();
+}
+
+bool SitMapPluginProvider::init(const std::shared_ptr &ddsConnector)
+{
+ m_ddsConnector = ddsConnector;
+
+ m_buildingPluginProvider = std::make_shared();
+
+ m_aesDtc = AreaEffectSimulation::Interface::Dtc::create(ddsConnector);
+ m_aesDtc->enableAll();
+ m_bldDtc = Buildings::Interface::Dtc::create(ddsConnector);
+ m_bldDtc->enableAll();
+ m_cesDtc = CentralEffectSimulation::Interface::Dtc::create(ddsConnector);
+ m_cesDtc->enableAll();
+ m_gimDtc = GuezIedManagement::Interface::Dtc::create(ddsConnector);
+ m_gimDtc->enableAll();
+// m_ismDtc = InfrastructureManagement::Interface::Dtc::create(ddsConnector);
+// m_ismDtc->enableAll();
+// m_ismForeign = std::make_shared(m_ismDtc);
+ m_ppmDtc = ParticipantManagement::Interface::Dtc::create(ddsConnector);
+ m_ppmDtc->enableAll();
+ m_pdmDtc = ProjectDataManagement::Interface::Dtc::create(ddsConnector);
+ m_pdmDtc->enableAll();
+
+ // needs m_ppmDtc
+ m_fltParticipantIfc = std::make_shared(m_ppmDtc);
+ m_fltAesIfc = std::make_shared(m_ppmDtc);
+ m_fltBuildingComponentIfc = std::make_shared(m_ppmDtc);
+ // m_fltParticipantIfc = m_fltAesIfc; // Not sure, lets try
+
+ return m_buildingPluginProvider->init(ddsConnector, this);
+}
+
+
+bool BuildingPluginProvider::init(const std::shared_ptr &ddsConnector,
+ SitMapPluginProvider *smPluginProvider)
+{
+ Q_ASSERT(smPluginProvider);
+ m_smPluginProvider = smPluginProvider;
+ connect(m_smPluginProvider, &SitMapPluginProvider::partitionTimeChanged,
+ this, &BuildingPluginProvider::partitionTimeChanged);
+
+ m_connectionParams.domainId = ddsConnector->getDomainId();
+ m_connectionParams.partitionId = ddsConnector->getPartitionId();
+ m_connectionParams.exerciseId = ddsConnector->getPartitionId();
+ m_connectionParams.tcpConnectionUrl = ddsConnector->getTcpConnectionUrl();
+
+ m_asbIfc = std::make_shared(m_smPluginProvider->ppmDtc(),
+ m_smPluginProvider->aesDtc(),
+ m_smPluginProvider->gimDtc());
+
+ return true;
+}
+
+
+std::shared_ptr SitMapPluginProvider::ismDataIfc() const
+{
+ if (!m_ismForeign)
+ m_ismForeign = std::make_shared(ismDtc());
+
+ return m_ismForeign;
+}
+
+
+std::shared_ptr SitMapPluginProvider::ismDtc() const
+{
+ if (!m_ismDtc)
+ {
+ m_ismDtc = InfrastructureManagement::Interface::Dtc::create(m_ddsConnector);
+ m_ismDtc->enableAll();
+ }
+
+ return m_ismDtc;
+}
+
+} // namespace THP
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_plugin_provider.h b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_plugin_provider.h
new file mode 100755
index 000000000..0226b29de
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_plugin_provider.h
@@ -0,0 +1,149 @@
+/**
+ * @RDE_HEADER@
+ * Plugin Provider for standalone SRP / THP
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace DDSConnector
+{
+class DdsConnector;
+}
+namespace THP
+{
+class BuildingPluginProvider;
+class SitMapPluginProvider final : public SituationMap::PluginProvider
+{
+ Q_OBJECT
+public:
+ using SituationMap::PluginProvider::PluginProvider;
+
+ QString toString() const override;
+
+ bool init(const std::shared_ptr &ddsConnector);
+
+ void emitPartitionTimeChanged(qint64 curTime) { m_curPartitionTime = curTime; emit partitionTimeChanged(curTime); }
+
+ void setExerciseId(int exerciseId) { m_exerciseId = exerciseId; }
+ int exerciseId() const override { return m_exerciseId; }
+ bool isSessionValid() const override { return true; }
+ qint64 partitionTime() const override { return m_curPartitionTime; }
+ int partitionId() const override { return -1; }
+ int operatorId() const override { return 42; }
+ LtsAppDescriptor::App appId() const override { return LtsAppDescriptor::App::ThpSituationReplay; }
+
+ bool isVisibleParty(int) const override { return true; }
+ QString workspaceId() const override { return {}; }
+ bool isReplayPartition() const override { return false; }
+
+ std::shared_ptr aesDtc() const override { return m_aesDtc; }
+ std::shared_ptr aesInfoIfc() const override { return {}; }
+ std::shared_ptr almDtc() const override { return {}; }
+ std::shared_ptr almFtc() const override { return {}; }
+ std::shared_ptr almInfoIfc() const override { return {}; }
+ std::shared_ptr asmDtc() const override { return {}; }
+ std::shared_ptr asmFtc() const override { return {}; }
+ std::shared_ptr bldDtc() const override { return m_bldDtc; }
+ std::shared_ptr bldFtc() const override { return {}; }
+ std::shared_ptr bldInfoIfc() const override { return {}; }
+ std::shared_ptr cesDtc() const override { return m_cesDtc; }
+ std::shared_ptr exmDtc() const override { return {}; }
+ std::shared_ptr exmFtc() const override { return {}; }
+ std::shared_ptr fltDtc() const override { return {}; }
+ std::shared_ptr fltFtc() const override { return {}; }
+ std::shared_ptr fltParticipantIfc() const override { return m_fltParticipantIfc; }
+ std::shared_ptr fltAesIfc() const override { return m_fltAesIfc; }
+ std::shared_ptr fltBuildingComponentIfc() const override { return m_fltBuildingComponentIfc; }
+ std::shared_ptr gimDtc() const override { return m_gimDtc; }
+ std::shared_ptr gimIfc() const override { return {}; }
+ std::shared_ptr gnaDtc() const override { return {}; }
+ std::shared_ptr gnaIfc() const override { return {}; }
+ std::shared_ptr ismDtc() const override;
+ std::shared_ptr ismDataIfc() const override;
+ std::shared_ptr ismGuiIfc() const override { return {}; }
+ std::shared_ptr opmDtc() const override { return {}; }
+ std::shared_ptr opmFtc() const override { return {}; }
+ std::shared_ptr ppmDtc() const override { return m_ppmDtc; }
+ std::shared_ptr ppmFtc() const override { return {}; }
+ std::shared_ptr ppmParticipantInfoIfc() const override { return {}; }
+ std::shared_ptr pdmDtc() const override { return m_pdmDtc; }
+ std::shared_ptr srpDtc() const override { return m_srpDtc; }
+ std::shared_ptr ocParticipantInfoIfc() const override { return {}; }
+ std::shared_ptr smoServiceMonitorIfc() const override { return {}; }
+ std::shared_ptr tgtDtc() const override { return {}; }
+ std::shared_ptr cmoDtc() const override { return {}; }
+
+ // for BuildingPluginProvider
+ BuildingPluginProvider *buildingPluginProvider() { return m_buildingPluginProvider.get(); }
+
+private:
+ std::shared_ptr m_aesDtc;
+ std::shared_ptr m_bldDtc;
+ std::shared_ptr m_cesDtc;
+ std::shared_ptr m_fltParticipantIfc;
+ std::shared_ptr m_fltAesIfc;
+ std::shared_ptr m_fltBuildingComponentIfc;
+ std::shared_ptr m_gimDtc;
+ mutable std::shared_ptr m_ismDtc;
+ mutable std::shared_ptr m_ismForeign;
+ std::shared_ptr m_ppmDtc;
+ std::shared_ptr m_srpDtc;
+ std::shared_ptr m_pdmDtc;
+
+ qint64 m_curPartitionTime = 0;
+ int m_exerciseId = 0;
+
+ std::shared_ptr m_buildingPluginProvider;
+ std::shared_ptr m_ddsConnector;
+};
+
+class BuildingPluginProvider final : public BuildingViewer::PluginProvider
+{
+ Q_OBJECT
+public:
+ using BuildingViewer::PluginProvider::PluginProvider;
+
+ BuildingPluginProvider() = default;
+
+ QString toString() const override { return m_smPluginProvider->toString(); }
+
+ bool init(const std::shared_ptr &ddsConnector,
+ SitMapPluginProvider *smPluginProvider);
+
+ void emitPartitionTimeChanged(qint64 curTime) { m_smPluginProvider->emitPartitionTimeChanged(curTime); }
+
+ int exerciseId() const override { return m_smPluginProvider->exerciseId(); }
+ qint64 partitionTime() const override { return m_smPluginProvider->partitionTime(); }
+ bool isReplayPartition() const override { return false; }
+ bool isVisibleParty(int partyId) const override { return m_smPluginProvider->isVisibleParty(partyId); }
+ LtsSession::DdsConnectionParams connParams() const override { return m_connectionParams; }
+
+ std::shared_ptr asbIfc() const override { return m_asbIfc; }
+ std::shared_ptr avmDataIfc() const override { return nullptr; } // optional
+ std::shared_ptr bldDtc() const override { return m_smPluginProvider->bldDtc(); }
+ std::shared_ptr bldInfoIfc() const override { return m_smPluginProvider->bldInfoIfc(); } // optional
+ std::shared_ptr ismDtc() const override { return m_smPluginProvider->ismDtc(); }
+ std::shared_ptr ismDataIfc() const override { return m_smPluginProvider->ismDataIfc(); }
+ std::shared_ptr aesDtc() const override { return m_smPluginProvider->aesDtc(); } // optional
+ std::shared_ptr ppmDtc() const override { return m_smPluginProvider->ppmDtc(); } // optional
+ std::shared_ptr pdmDtc() const override { return m_smPluginProvider->pdmDtc(); } // optional
+ std::shared_ptr srpDtc() const override { return m_smPluginProvider->srpDtc(); } // optional
+ std::shared_ptr ppmParticipantInfoIfc() const override { return m_smPluginProvider->ppmParticipantInfoIfc(); } // optional
+
+private:
+ SitMapPluginProvider *m_smPluginProvider{nullptr};
+ std::shared_ptr m_asbIfc;
+ LtsSession::DdsConnectionParams m_connectionParams;
+};
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_situation_filter_interface_impl.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_situation_filter_interface_impl.cpp
new file mode 100755
index 000000000..8154bbeb4
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_situation_filter_interface_impl.cpp
@@ -0,0 +1,47 @@
+/**
+ * @RDE_HEADER@
+ * Simple implmentation of FilterHandling for THP
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+
+#include "thp_situation_filter_interface_impl.h"
+#include
+#include
+#include
+
+namespace FilterManagement
+{
+ThpFilterInterfaceImpl::ThpFilterInterfaceImpl(const std::shared_ptr &dtcPpm)
+ : m_fltSymbols(std::make_shared(dtcPpm))
+ , m_fltAes(std::make_shared())
+ , m_fltBuildingComponentSettings(std::make_shared())
+{
+ m_fltAes->setVisiblePartiesCheck([](int) -> bool { return true; });
+}
+
+std::shared_ptr ThpFilterInterfaceImpl::symbolAppearanceForOperator(int operatorId, const QString &context)
+{
+ Q_UNUSED(operatorId);
+ Q_UNUSED(context);
+ return m_fltSymbols;
+}
+
+std::shared_ptr ThpFilterInterfaceImpl::aesFilterForOperator(int operatorId, const QString &context)
+{
+ Q_UNUSED(operatorId);
+ Q_UNUSED(context);
+ return m_fltAes;
+}
+
+std::shared_ptr ThpFilterInterfaceImpl::buildingComponentSettingsForOperator(int operatorId, const QString &context)
+{
+ Q_UNUSED(operatorId);
+ Q_UNUSED(context);
+ return m_fltBuildingComponentSettings;
+
+}
+
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_situation_filter_interface_impl.h b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_situation_filter_interface_impl.h
new file mode 100755
index 000000000..d82e6fda4
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_situation_filter_interface_impl.h
@@ -0,0 +1,40 @@
+/**
+ * @RDE_HEADER@
+ * Simple implmentation of FilterHandling for THP
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ * Created by Christian Ehrlicher, SLSE, 2016-02-29
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace FilterManagement
+{
+class ThpFilterInterfaceImpl : public ForeignFltParticipantGuiInterface,
+ public ForeignAesGuiInterface,
+ public ForeignFltBuildingComponentGuiInterface
+{
+public:
+ explicit ThpFilterInterfaceImpl(const std::shared_ptr &dtcPpm);
+
+ // from Participant
+ std::shared_ptr symbolAppearanceForOperator(int operatorId, const QString &context) override;
+
+ // from Aes
+ std::shared_ptr aesFilterForOperator(int operatorId, const QString &context) override;
+
+ // from BuildingComponent
+ std::shared_ptr buildingComponentSettingsForOperator(int operatorId, const QString &context) override;
+
+
+private:
+ std::shared_ptr m_fltSymbols;
+ std::shared_ptr m_fltAes;
+ std::shared_ptr m_fltBuildingComponentSettings;
+};
+}
diff --git a/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_viewer.cpp b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_viewer.cpp
new file mode 100755
index 000000000..6a90c528e
--- /dev/null
+++ b/qt6-after/qt6-migrated-legatus/Lts/Application/THP/thp_viewer.cpp
@@ -0,0 +1,686 @@
+/**
+ * @RDE_HEADER@
+ * Main thp viewer widget
+ * $Id$
+ * $HeadURL$
+ * $Author$
+ */
+#include "thp_viewer.h"
+#include "ui_thp_viewer.h"
+#include "thp_plugin_provider.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include