- training_area_telegrams.cpp: Fixed QJsonObject initializer syntax (Qt6 requires {{}} not ({}))
- training_area_telegrams.cpp: Fixed fromJson() methods to access m_* members directly
- training_area_telegrams.cpp: Fixed brace mismatches in multiple toJson() methods
- training_area_telegrams.h: Changed Header struct to public members for consistency
- tx_mixin.cpp: Fixed getEquipmentNumber() template for direct member access
- lts_coordinate.cpp: Added missing #include <iomanip>
- MIGRATION_STATUS.md: Added migration progress tracking document
C++17 constraint enforced due to RTI Connext DDS 7.7.0 incompatibility with C++20+
Build status: BUILD_RTI=OFF successful (0 errors, warnings only)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
964 lines
31 KiB
C++
964 lines
31 KiB
C++
#include "lts_app_manager.h"
|
|
|
|
#include "AppChooser/app_chooser.h"
|
|
|
|
#include <LtsLogin/lts_login.h>
|
|
#include <LtsMultiMonitor/lts_multi_monitor.h>
|
|
#include <LtsPluginManager/lts_plugin_manager.h>
|
|
#include <LtsSession/lts_session.h>
|
|
#include <LtsSession/lts_session_data.h>
|
|
#include <LtsSession/lts_session_manager.h>
|
|
#include <LtsUtilsSettings/settings.h>
|
|
#include <LtsWidgets/lts_events.h>
|
|
#include <LtsWidgets/lts_global_wait_dialog.h>
|
|
#include <OperatorManagement/opm_settings_gui_plugin_interface.h>
|
|
#include <PluginInterfaces/gui_plugin_interface.h>
|
|
#include <QtCore/QCoreApplication>
|
|
#include <QtCore/QJsonArray>
|
|
#include <QtCore/QJsonDocument>
|
|
#include <QtCore/QJsonObject>
|
|
#include <QtCore/QJsonValue>
|
|
#include <QtWidgets/QMessageBox>
|
|
#include <QtNetwork/QTcpServer>
|
|
#include <QtNetwork/QTcpSocket>
|
|
#include <QtCore/QTimer>
|
|
#include <QtCore/QUuid>
|
|
#include <utility>
|
|
|
|
#ifndef LTS_VERSION_MAJOR
|
|
#define LTS_VERSION_MAJOR "undefined"
|
|
#endif
|
|
#ifndef LTS_VERSION_MINOR
|
|
#define LTS_VERSION_MINOR "undefined"
|
|
#endif
|
|
#ifndef LTS_VERSION_PATCH
|
|
#define LTS_VERSION_PATCH "undefined"
|
|
#endif
|
|
#ifndef JENKINS_BUILD_NUMBER
|
|
#define JENKINS_BUILD_NUMBER "unknown"
|
|
#endif
|
|
static const char ver_major[] = LTS_VERSION_MAJOR;
|
|
static const char ver_minor[] = LTS_VERSION_MINOR;
|
|
static const char ver_patch[] = LTS_VERSION_PATCH;
|
|
static const char ver_jenkins[] = JENKINS_BUILD_NUMBER;
|
|
|
|
namespace LtsAppManager
|
|
{
|
|
|
|
struct LtsAppManagerHandler
|
|
{
|
|
LtsAppManager ltsAppManager;
|
|
};
|
|
|
|
Q_GLOBAL_STATIC(LtsAppManagerHandler, s_ltsAppManager)
|
|
|
|
LtsAppManager* LtsAppManager::getInstance()
|
|
{
|
|
return &s_ltsAppManager->ltsAppManager;
|
|
}
|
|
|
|
LtsAppManager::LtsAppManager() : m_login(nullptr)
|
|
{
|
|
|
|
qRegisterMetaType<LtsAppDescriptor::App>("LtsAppDescriptor::App");
|
|
slotStartDebugServer();
|
|
connect(qApp, &QCoreApplication::aboutToQuit, this, [this] {
|
|
delete m_login;
|
|
m_login = nullptr;
|
|
});
|
|
}
|
|
|
|
LtsAppManager::~LtsAppManager()
|
|
{
|
|
|
|
delete m_login;
|
|
m_login = nullptr;
|
|
}
|
|
|
|
void LtsAppManager::setAvailableApps(const LtsAppDescriptor::AppDescriptionVector& availableApps)
|
|
{
|
|
m_availableApps = availableApps;
|
|
|
|
#ifndef LTS_DEBUG
|
|
if (LtsSessionData::LtsSessionData::getInstance()->debugFlagValue(
|
|
QStringLiteral("PluginManager.CheckAppRequirements")) == QVariant(true))
|
|
{
|
|
QMessageBox::information(nullptr, QStringLiteral("LtsAppManager"),
|
|
QStringLiteral("Checking App Requirements now"));
|
|
#else
|
|
{
|
|
#endif
|
|
QStringList errors;
|
|
LtsPluginManager::LtsPluginLoader::getInstance()->checkPlugins(availableApps, errors);
|
|
|
|
if (!errors.isEmpty())
|
|
QMessageBox::critical(
|
|
nullptr, QStringLiteral("LtsAppManager"),
|
|
QStringLiteral("App Requirements check failed!<br> - %1").arg(errors.join(QStringLiteral("<br> - "))));
|
|
}
|
|
|
|
if (m_availableApps.isEmpty())
|
|
{
|
|
QMessageBox::critical(nullptr, tr("App Manager"),
|
|
tr("There are no apps available for this project.\nPlease contact Support."));
|
|
abort();
|
|
}
|
|
}
|
|
|
|
void LtsAppManager::slotStartDebugServer()
|
|
{
|
|
QTcpServer* debugServer = new QTcpServer(this);
|
|
|
|
if (!debugServer->listen(QHostAddress::Any, 20000))
|
|
{
|
|
debugServer->deleteLater();
|
|
const int waitTryAgain = 5;
|
|
#ifdef LTS_DEBUG
|
|
|
|
#endif
|
|
QTimer::singleShot(waitTryAgain * 1000, this, &LtsAppManager::slotStartDebugServer);
|
|
return;
|
|
}
|
|
|
|
connect(debugServer, &QTcpServer::newConnection, this, [this]() {
|
|
QTcpServer* server = qobject_cast<QTcpServer*>(sender());
|
|
|
|
if (server == nullptr)
|
|
return;
|
|
|
|
QTcpSocket* client = server->nextPendingConnection();
|
|
|
|
if (client == nullptr)
|
|
return;
|
|
|
|
connect(client, &QTcpSocket::readyRead, this, [this]() {
|
|
QTcpSocket* client = qobject_cast<QTcpSocket*>(sender());
|
|
|
|
if (client == nullptr)
|
|
return;
|
|
|
|
QString commandStr(
|
|
QString::fromUtf8(client->readLine(100)).remove(QStringLiteral("\r")).remove(QStringLiteral("\n")));
|
|
|
|
QStringList argList = commandStr.split(QLatin1Char(' '), QString::SplitBehavior::SkipEmptyParts);
|
|
|
|
if (argList.count() < 1)
|
|
return;
|
|
|
|
const QString& command = argList.at(0);
|
|
|
|
LtsSessionData::LtsSessionData* sessionData = LtsSessionData::LtsSessionData::getInstance();
|
|
static QStringList commands;
|
|
commands << QStringLiteral("showSessions") << QStringLiteral("operator") << QStringLiteral("help")
|
|
<< QStringLiteral("logout") << QStringLiteral("flag") << QStringLiteral("setFlag")
|
|
<< QStringLiteral("start") << QStringLiteral("voiceCommand") << QStringLiteral("ftcmock");
|
|
|
|
switch (commands.indexOf(command))
|
|
{
|
|
case 0: {
|
|
sessionData->setDebugFlagValue(QStringLiteral("DeveloperTools.ShowSessionsOnce"), true);
|
|
client->write("K");
|
|
break;
|
|
}
|
|
|
|
case 1: {
|
|
QString operatorName(sessionData->getOperatorName());
|
|
|
|
if (operatorName.isEmpty())
|
|
operatorName = QStringLiteral("(none)");
|
|
|
|
QString result(QStringLiteral("%1").arg(operatorName));
|
|
client->write(result.toUtf8());
|
|
break;
|
|
}
|
|
|
|
case 2: {
|
|
QString result(QStringLiteral("Available Commands: %1").arg(commands.join(QStringLiteral(", "))));
|
|
client->write(result.toUtf8());
|
|
break;
|
|
}
|
|
|
|
case 3: {
|
|
client->write("...");
|
|
slotLogout();
|
|
client->write("\r\nK");
|
|
break;
|
|
}
|
|
|
|
case 4: {
|
|
if (argList.count() != 2)
|
|
{
|
|
client->write("Usage: flag <flag name>");
|
|
break;
|
|
}
|
|
|
|
const QString& debugFlagName = argList.at(1);
|
|
if (!sessionData->hasDebugFlag(debugFlagName))
|
|
{
|
|
client->write("(unknown)");
|
|
break;
|
|
}
|
|
|
|
client->write(sessionData->debugFlagValue(argList.at(1)).toString().toUtf8());
|
|
break;
|
|
}
|
|
|
|
case 5: {
|
|
if (argList.count() < 3)
|
|
{
|
|
client->write("Usage: setFlag <flag name> <flag type> <value>\r\nFlag types: int, string (no "
|
|
"spaces allowed yet), boolean, double");
|
|
break;
|
|
}
|
|
|
|
static QStringList flagTypes;
|
|
flagTypes << QStringLiteral("int") << QStringLiteral("string") << QStringLiteral("boolean")
|
|
<< QStringLiteral("double");
|
|
|
|
const QString& flagType = argList.at(2);
|
|
bool k = false;
|
|
|
|
const QString& flagName = argList.at(1);
|
|
|
|
switch (flagTypes.indexOf(flagType))
|
|
{
|
|
case 0: {
|
|
int value = argList.at(3).toInt(&k);
|
|
if (k)
|
|
sessionData->setDebugFlagValue(flagName, value);
|
|
else
|
|
client->write("cannot convert value to integer");
|
|
|
|
break;
|
|
}
|
|
|
|
case 1: {
|
|
sessionData->setDebugFlagValue(flagName, argList.at(3));
|
|
break;
|
|
}
|
|
|
|
case 2: {
|
|
QString value(argList.at(3).toLower().simplified());
|
|
if (value == QStringLiteral("true"))
|
|
sessionData->setDebugFlagValue(flagName, true);
|
|
else if (value == QStringLiteral("false"))
|
|
sessionData->setDebugFlagValue(flagName, false);
|
|
else
|
|
client->write("cannot convert value to boolean");
|
|
|
|
break;
|
|
}
|
|
|
|
case 3: {
|
|
double value = argList.at(3).toDouble(&k);
|
|
if (k)
|
|
sessionData->setDebugFlagValue(flagName, value);
|
|
else
|
|
client->write("cannot convert value to double");
|
|
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
client->write("unknown flag type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 6: {
|
|
if (argList.count() < 3)
|
|
{
|
|
client->write("Usage: start <app id> <domain id> ");
|
|
break;
|
|
}
|
|
|
|
client->write("not implemented yet");
|
|
break;
|
|
}
|
|
|
|
case 7: {
|
|
if (argList.count() < 2)
|
|
{
|
|
client->write("Usage: voiceCommand <keyword> <optional description>");
|
|
break;
|
|
}
|
|
|
|
static QStringList keywords;
|
|
keywords << QStringLiteral("AddMarker") << QStringLiteral("SetMarker")
|
|
<< QStringLiteral("AddSnapshot") << QStringLiteral("SaveSnapshot");
|
|
|
|
const QString& keyword = argList.at(1);
|
|
|
|
switch (keywords.indexOf(keyword))
|
|
{
|
|
case 0: {
|
|
auto ev = new LtsWidgets::AddMarkerEvent;
|
|
ev->setAccepted(false);
|
|
sessionData->setDebugFlagValue(command, keyword);
|
|
QCoreApplication::postEvent(qApp, ev);
|
|
break;
|
|
}
|
|
case 1: {
|
|
auto ev = new LtsWidgets::SetMarkerEvent(QString());
|
|
if (argList.size() > 2)
|
|
ev->setDescription(argList.at(2));
|
|
ev->setAccepted(false);
|
|
sessionData->setDebugFlagValue(command, keyword);
|
|
QCoreApplication::postEvent(qApp, ev);
|
|
break;
|
|
}
|
|
case 2: {
|
|
auto ev = new LtsWidgets::AddSnapshotEvent;
|
|
ev->setAccepted(false);
|
|
sessionData->setDebugFlagValue(command, keyword);
|
|
QCoreApplication::postEvent(qApp, ev);
|
|
break;
|
|
}
|
|
case 3: {
|
|
auto ev = new LtsWidgets::SaveSnapshotEvent(QString());
|
|
if (argList.size() > 2)
|
|
ev->setDescription(argList.at(2));
|
|
ev->setAccepted(false);
|
|
sessionData->setDebugFlagValue(command, keyword);
|
|
QCoreApplication::postEvent(qApp, ev);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!sessionData->hasDebugFlag(command))
|
|
{
|
|
client->write("(unknown)");
|
|
break;
|
|
}
|
|
|
|
client->write(sessionData->debugFlagValue(argList.at(1)).toString().toUtf8());
|
|
break;
|
|
}
|
|
case 8: {
|
|
auto usage = [client]() {
|
|
client->write("Usage: ftcmock start <sessionId> <min ms> <max ms> <timer count> - See 'Session "
|
|
"id' in DevDialog "
|
|
"\nftcmock stop <sessionId>");
|
|
};
|
|
|
|
if (argList.count() < 3)
|
|
{
|
|
usage();
|
|
break;
|
|
}
|
|
|
|
bool k = false;
|
|
switch (QStringList({QStringLiteral("start"), QStringLiteral("stop")}).indexOf(argList.at(1)))
|
|
{
|
|
case 0: {
|
|
if (argList.count() < 6)
|
|
{
|
|
usage();
|
|
return;
|
|
}
|
|
|
|
const int min = argList.at(3).toInt(&k);
|
|
if (!k || min < 0)
|
|
{
|
|
client->write("min must be a positive integer!");
|
|
return;
|
|
}
|
|
|
|
const int max = argList.at(4).toInt(&k);
|
|
if (!k || max < 0)
|
|
{
|
|
client->write("max must be a positive integer!");
|
|
return;
|
|
}
|
|
|
|
const int timers = argList.at(5).toInt(&k);
|
|
if (!k || timers < 1)
|
|
{
|
|
client->write("'timer count' must be a positive integer and greater than 0!");
|
|
return;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 1: {
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
usage();
|
|
return;
|
|
}
|
|
}
|
|
|
|
const int sessionId = argList.at(2).toInt(&k);
|
|
if (!k || sessionId < 0)
|
|
{
|
|
client->write("sessionId must be a positive integer!");
|
|
return;
|
|
}
|
|
|
|
emit signalCommand(client, argList);
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
QString result(QStringLiteral("Unknown command '%1'").arg(command));
|
|
client->write(result.toUtf8());
|
|
break;
|
|
}
|
|
}
|
|
|
|
client->write("\r\n> ");
|
|
});
|
|
|
|
QString versionString = QStringLiteral("%1.%2-%3 (rev: %4)")
|
|
.arg(QString::fromLatin1(ver_major), QString::fromLatin1(ver_minor),
|
|
QString::fromLatin1(ver_jenkins), QString::fromLatin1(ver_patch));
|
|
|
|
QString motd(QStringLiteral("\r\nOperatorApplication - Version %1").arg(versionString));
|
|
client->write(motd.toUtf8());
|
|
client->write("\r\n> ");
|
|
});
|
|
}
|
|
|
|
void LtsAppManager::showLogin()
|
|
{
|
|
|
|
QTimer::singleShot(0, this, &LtsAppManager::slotShowLogin);
|
|
}
|
|
|
|
void LtsAppManager::slotShowLogin()
|
|
{
|
|
|
|
if (m_login == nullptr)
|
|
{
|
|
m_login = new LtsLogin::LtsLogin;
|
|
connect(m_login, &LtsLogin::LtsLogin::signalLoginDone, this, [&] {
|
|
|
|
#ifdef LTS_DEBUG
|
|
|
|
#endif
|
|
if (m_appList.isEmpty())
|
|
if (!startAppOrLetUserChoose(m_app, {}))
|
|
QTimer::singleShot(100, this, &LtsAppManager::slotLogout);
|
|
});
|
|
|
|
connect(m_login, &LtsLogin::LtsLogin::signalLogoffDone, this, &LtsAppManager::signalLogoffDone);
|
|
|
|
connect(m_login, &LtsLogin::LtsLogin::signalLogoffDone, this, &LtsAppManager::slotShowLogin,
|
|
Qt::QueuedConnection);
|
|
|
|
connect(m_login, &LtsLogin::LtsLogin::signalLogout, this, &LtsAppManager::slotLogout);
|
|
|
|
m_login->setLoginPlugin(m_loginPluginIid);
|
|
}
|
|
|
|
m_login->login();
|
|
}
|
|
|
|
bool LtsAppManager::hasRightForApp(const LtsAppDescriptor::AppDescription& appDescription) const
|
|
{
|
|
const QSet<int>& acls = LtsSessionData::LtsSessionData::getInstance()->getOperatorRights();
|
|
for (int reqRight : appDescription.requiredAcls)
|
|
{
|
|
if (!acls.contains(reqRight))
|
|
{
|
|
QMessageBox::critical(
|
|
nullptr, tr("App Manager"),
|
|
tr("The minimal required operator rights are not met. Therefore, the app cannot be started."));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void LtsAppManager::taskSwitch(QObject* _caller)
|
|
{
|
|
LtsSession::LtsSession* caller = qobject_cast<LtsSession::LtsSession*>(_caller);
|
|
|
|
if (caller == nullptr)
|
|
{
|
|
Q_ASSERT(false);
|
|
return;
|
|
}
|
|
|
|
QVector<LtsSession::LtsSession*> sessions;
|
|
|
|
for (const LtsPluginManager::LtsPluginManager* app : m_appList)
|
|
sessions += app->sessions();
|
|
|
|
if (sessions.isEmpty())
|
|
return;
|
|
|
|
int sessionCount = sessions.count();
|
|
|
|
if (sessionCount < 2)
|
|
return;
|
|
|
|
auto sessionIt = std::find_if(sessions.begin(), sessions.end(),
|
|
[caller](const LtsSession::LtsSession* session) { return (session == caller); });
|
|
|
|
if (sessionIt == sessions.end())
|
|
{
|
|
|
|
return;
|
|
}
|
|
|
|
auto it = ++sessionIt;
|
|
|
|
int x = 0;
|
|
do
|
|
{
|
|
|
|
if (x > 100)
|
|
{
|
|
|
|
return;
|
|
}
|
|
x++;
|
|
|
|
if (it == sessions.end())
|
|
{
|
|
|
|
if (sessions.begin() == sessionIt)
|
|
{
|
|
|
|
return;
|
|
}
|
|
it = sessions.begin();
|
|
}
|
|
|
|
LtsSession::LtsSession* session = *it;
|
|
|
|
QWidget* blw = session->baseLayoutWidget();
|
|
|
|
if (blw == nullptr || session->isForeverInvisible() || session == caller)
|
|
{
|
|
|
|
continue;
|
|
}
|
|
|
|
caller->baseLayoutWidget()->hide();
|
|
blw->showFullScreen();
|
|
|
|
return;
|
|
}
|
|
|
|
while (++it != sessionIt);
|
|
}
|
|
|
|
void LtsAppManager::hideAllOtherBLWs(QObject* _caller)
|
|
{
|
|
|
|
if (!LtsSessionData::LtsSessionData::getInstance()->isTablet())
|
|
return;
|
|
|
|
LtsSession::LtsSession* caller = qobject_cast<LtsSession::LtsSession*>(_caller);
|
|
|
|
QVector<LtsSession::LtsSession*> sessions;
|
|
for (const LtsPluginManager::LtsPluginManager* app : m_appList)
|
|
sessions += app->sessions();
|
|
|
|
for (LtsSession::LtsSession* session : sessions)
|
|
{
|
|
|
|
QWidget* blw = session->baseLayoutWidget();
|
|
|
|
if (blw != nullptr && !session->isForeverInvisible() && session != caller)
|
|
{
|
|
|
|
blw->hide();
|
|
}
|
|
}
|
|
|
|
if (caller != nullptr)
|
|
return;
|
|
|
|
for (LtsSession::LtsSession* session : sessions)
|
|
{
|
|
|
|
QWidget* blw = session->baseLayoutWidget();
|
|
|
|
if (blw == nullptr || session->isForeverInvisible())
|
|
{
|
|
|
|
continue;
|
|
}
|
|
|
|
blw->showFullScreen();
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool LtsAppManager::startAppOrLetUserChoose(LtsAppDescriptor::App appId,
|
|
const LtsSession::DdsConnectionParams& connParams, bool force)
|
|
{
|
|
return startAppOrLetUserChoose(getApp(appId), connParams, force);
|
|
}
|
|
|
|
bool LtsAppManager::startAppOrLetUserChoose(const LtsAppDescriptor::AppDescription& appDescription,
|
|
const LtsSession::DdsConnectionParams& connParams, bool force)
|
|
{
|
|
if (!appDescription.active && !force)
|
|
{
|
|
|
|
AppChooser* appChooser = new AppChooser();
|
|
appChooser->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
connect(appChooser, &AppChooser::signalLogout, this, &LtsAppManager::slotLogout);
|
|
|
|
connect(
|
|
appChooser, &AppChooser::signalAppSelected, this,
|
|
[this, connParams](LtsAppDescriptor::App appId) {
|
|
if (createApp(appId, connParams) == nullptr)
|
|
QTimer::singleShot(100, this, &LtsAppManager::slotLogout);
|
|
},
|
|
Qt::QueuedConnection);
|
|
|
|
appChooser->show();
|
|
return true;
|
|
}
|
|
|
|
if (createApp(appDescription, connParams, {}, false, force) == nullptr)
|
|
{
|
|
QMessageBox::critical(nullptr, tr("App Manager"), tr("Could not create app.\nPlease contact support."));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
LtsPluginManager::LtsPluginManager* LtsAppManager::createApp(LtsAppDescriptor::App appId,
|
|
const LtsSession::DdsConnectionParams& connParams,
|
|
const QString& workspaceId, bool hidden, bool force)
|
|
{
|
|
return createApp(getApp(appId), connParams, workspaceId, hidden, force);
|
|
}
|
|
|
|
LtsPluginManager::LtsPluginManager* LtsAppManager::createApp(const LtsAppDescriptor::AppDescription& appDescription,
|
|
const LtsSession::DdsConnectionParams& connParams,
|
|
const QString& workspaceId, bool hidden, bool force)
|
|
{
|
|
if (!appDescription.isValid())
|
|
{
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
if (!hasRightForApp(appDescription) && !force)
|
|
return nullptr;
|
|
|
|
const bool bDesiredAppHasSituationMapInstance =
|
|
LtsPluginManager::LtsPluginManager::hasSituationMapInstance(appDescription, true);
|
|
if (bDesiredAppHasSituationMapInstance)
|
|
{
|
|
const int curInstances = getNumberOfSituationMapInstances();
|
|
|
|
if (curInstances >= 3 && !force)
|
|
{
|
|
if (QMessageBox::Yes !=
|
|
QMessageBox::question(nullptr, tr("App Manager"),
|
|
tr("Are you sure you want to launch another resource-intensive app? <br />"
|
|
"Please note that you are currently running three apps containing the "
|
|
"resource-intensive map componment. <br />"
|
|
"It may lead to potential performance issues.")))
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto* pluginManager = new LtsPluginManager::LtsPluginManager();
|
|
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::signalQuit, this, &LtsAppManager::slotQuit);
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::signalSoftQuit, this, &LtsAppManager::slotSoftQuit);
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::signalLogout, this, &LtsAppManager::slotLogout);
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::signalInitializationFinished, this,
|
|
&LtsAppManager::signalInitializationFinished);
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::destroyed, this, &LtsAppManager::slotAppDestroyed);
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::hideAllOtherBLWs, this,
|
|
&LtsAppManager::hideAllOtherBLWs);
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::taskSwitch, this, &LtsAppManager::taskSwitch);
|
|
#ifdef LTS_DEBUG
|
|
connect(pluginManager, &LtsPluginManager::LtsPluginManager::signalStillAlive, this, [this]() {
|
|
auto* app = qobject_cast<LtsPluginManager::LtsPluginManager*>(sender());
|
|
if (!app)
|
|
return;
|
|
|
|
for (auto i = m_appList.constBegin(); i != m_appList.constEnd(); ++i)
|
|
{
|
|
if (*i == app)
|
|
return;
|
|
}
|
|
});
|
|
#endif
|
|
|
|
if (!pluginManager->startApp(appDescription, false, connParams, workspaceId, hidden))
|
|
{
|
|
QMessageBox::critical(
|
|
nullptr, tr("App Manager"),
|
|
tr("The Plugin Manager failed to start the app due to plugin errors.\nPlease contact support."));
|
|
pluginManager->deleteLater();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
m_appList.append(pluginManager);
|
|
|
|
return pluginManager;
|
|
}
|
|
|
|
bool LtsAppManager::hasApp(LtsAppDescriptor::App appId) const
|
|
{
|
|
return (std::find_if(m_availableApps.constBegin(), m_availableApps.constEnd(),
|
|
[appId](const LtsAppDescriptor::AppDescription& app) {
|
|
bool ret = (app.id == appId);
|
|
|
|
return ret;
|
|
}) != m_availableApps.constEnd());
|
|
}
|
|
|
|
int LtsAppManager::getNumberOfSituationMapInstances() const
|
|
{
|
|
int numberOfSituationMapInstances = 0;
|
|
for (const LtsPluginManager::LtsPluginManager* app : std::as_const(m_appList))
|
|
{
|
|
if (!app)
|
|
continue;
|
|
|
|
if (app->hasSituationMapInstance())
|
|
++numberOfSituationMapInstances;
|
|
}
|
|
|
|
return numberOfSituationMapInstances;
|
|
}
|
|
|
|
LtsAppDescriptor::AppDescription LtsAppManager::getApp(LtsAppDescriptor::App appId) const
|
|
{
|
|
for (const LtsAppDescriptor::AppDescription& app : m_availableApps)
|
|
{
|
|
|
|
if (app.id == appId)
|
|
return app;
|
|
}
|
|
|
|
return LtsAppDescriptor::AppDescription();
|
|
}
|
|
|
|
void LtsAppManager::setMainApp(LtsAppDescriptor::App appId)
|
|
{
|
|
m_app = getApp(appId);
|
|
}
|
|
|
|
void LtsAppManager::saveState()
|
|
{
|
|
|
|
if (LtsSessionData::LtsSessionData::getInstance()->getOperatorId() == 0)
|
|
return;
|
|
|
|
QStringList unsavedWorkspaces =
|
|
LtsUtils::OperatorSettings::getInstance()->identifiers(QStringLiteral("UnsavedWorkspace"));
|
|
for (auto i = unsavedWorkspaces.constBegin(); i != unsavedWorkspaces.constEnd(); ++i)
|
|
LtsUtils::OperatorSettings::getInstance()->removeValue(QStringLiteral("UnsavedWorkspace"), *i);
|
|
|
|
QStringList unsavedFilterPreset =
|
|
LtsUtils::OperatorSettings::getInstance()->identifiers(QStringLiteral("UnsavedFilterPreset"));
|
|
for (auto i = unsavedFilterPreset.constBegin(); i != unsavedFilterPreset.constEnd(); ++i)
|
|
LtsUtils::OperatorSettings::getInstance()->removeValue(QStringLiteral("UnsavedFilterPreset"), *i);
|
|
|
|
QJsonArray root;
|
|
for (const LtsPluginManager::LtsPluginManager* app : std::as_const(m_appList))
|
|
{
|
|
const QVector<LtsSession::LtsSession*> sessions = app->sessions();
|
|
|
|
const auto appId = app->appDescription().id;
|
|
|
|
if (appId == LtsAppDescriptor::App::Login || sessions.count() < 1)
|
|
continue;
|
|
|
|
QJsonObject appState;
|
|
appState[QStringLiteral("id")] = static_cast<int>(appId);
|
|
|
|
QJsonArray sessionStates;
|
|
|
|
for (LtsSession::LtsSession* session : sessions)
|
|
{
|
|
if (session->baseLayout() != nullptr && session->baseLayout()->isSecondaryWidget())
|
|
continue;
|
|
|
|
QJsonObject sessionState;
|
|
|
|
int screenId = session->screenId();
|
|
|
|
int screenContainerId = session->screenContainerId();
|
|
|
|
sessionState[QStringLiteral("screenId")] = screenId;
|
|
sessionState[QStringLiteral("screenContainerId")] = screenContainerId;
|
|
sessionState[QStringLiteral("exerciseId")] = session->exerciseId();
|
|
sessionState[QStringLiteral("partitionId")] = session->partitionId();
|
|
sessionState[QStringLiteral("partitionType")] = int(session->partitionType());
|
|
sessionState[QStringLiteral("savegame")] = session->getSavegame();
|
|
|
|
const QString newId(QUuid::createUuid().toString());
|
|
sessionState[QStringLiteral("workspaceId")] = newId;
|
|
|
|
std::shared_ptr<OperatorManagement::ForeignSettingsGuiInterface> ifcOpm;
|
|
if (session->getForeignGuiInterface<OperatorManagement::ForeignSettingsGuiInterface>(ifcOpm))
|
|
{
|
|
|
|
ifcOpm->callWorkspaceSaveUnsaved(newId);
|
|
}
|
|
|
|
sessionStates.append(sessionState);
|
|
}
|
|
|
|
if (!sessionStates.isEmpty())
|
|
{
|
|
appState[QStringLiteral("sessions")] = sessionStates;
|
|
root.append(appState);
|
|
}
|
|
}
|
|
|
|
QJsonDocument doc(root);
|
|
|
|
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("app"), QStringLiteral("LastAppStates"),
|
|
doc.toJson(QJsonDocument::Compact));
|
|
}
|
|
|
|
void LtsAppManager::slotLogout()
|
|
{
|
|
for (LtsPluginManager::LtsPluginManager* app : std::as_const(m_appList))
|
|
{
|
|
const QVector<LtsSession::LtsSession*> sessions = app->sessions();
|
|
for (LtsSession::LtsSession* session : sessions)
|
|
{
|
|
if (session->notifyUnsavedChanges() == false)
|
|
return;
|
|
}
|
|
}
|
|
|
|
saveState();
|
|
|
|
const QVector<LtsPluginManager::LtsPluginManager*> apps = m_appList;
|
|
|
|
if (apps.isEmpty() && m_login != nullptr)
|
|
m_login->logoff();
|
|
|
|
for (LtsPluginManager::LtsPluginManager* app : apps)
|
|
app->deleteLater();
|
|
}
|
|
|
|
void LtsAppManager::slotAppDestroyed()
|
|
{
|
|
LtsPluginManager::LtsPluginManager* app = static_cast<LtsPluginManager::LtsPluginManager*>(sender());
|
|
|
|
m_appList.removeOne(app);
|
|
|
|
if (m_appList.isEmpty() && m_login != nullptr)
|
|
{
|
|
|
|
m_login->logoff();
|
|
}
|
|
}
|
|
|
|
void LtsAppManager::slotQuit()
|
|
{
|
|
|
|
QObject* object = sender();
|
|
|
|
if (!object)
|
|
qCritical()
|
|
<< "ERROR: LtsAppManager: slot called without object - so it cannot be deleted from the app assignments!";
|
|
|
|
LtsPluginManager::LtsPluginManager* app = qobject_cast<LtsPluginManager::LtsPluginManager*>(object);
|
|
|
|
if (app == nullptr)
|
|
{
|
|
qCritical() << "ERROR: LtsAppManager: quit requested for invalid app";
|
|
return;
|
|
}
|
|
|
|
if (m_appList.count() == 1)
|
|
{
|
|
m_appList.removeAll(app);
|
|
saveState();
|
|
}
|
|
|
|
app->deleteLater();
|
|
}
|
|
|
|
void LtsAppManager::slotSoftQuit()
|
|
{
|
|
|
|
QObject* object = sender();
|
|
|
|
LtsPluginManager::LtsPluginManager* app = qobject_cast<LtsPluginManager::LtsPluginManager*>(object);
|
|
|
|
if (app == nullptr)
|
|
{
|
|
qCritical() << "ERROR: LtsAppManager: quit requested for invalid app";
|
|
return;
|
|
}
|
|
|
|
app->_softQuit();
|
|
|
|
if (m_appList.count() == 1)
|
|
{
|
|
m_appList.removeAll(app);
|
|
saveState();
|
|
}
|
|
}
|
|
|
|
bool LtsAppManager::otherSessionsResponsibility(LtsSession::LtsSession* thisSession,
|
|
const QVector<LtsAppDescriptor::App>& requiredAppTypes,
|
|
const QVector<IDL::PartitionType>& requiredPartitionTypes,
|
|
const QString& menuGroup, const QString& identifier,
|
|
LtsWidgets::LayoutArea area)
|
|
{
|
|
const QVector<LtsPluginManager::LtsPluginManager*> apps = LtsAppManager::LtsAppManager::getInstance()->getAppList();
|
|
QVector<LtsPluginManager::LtsPluginManager*> worthyApps;
|
|
|
|
for (LtsPluginManager::LtsPluginManager* app : apps)
|
|
{
|
|
if (!requiredAppTypes.contains(static_cast<LtsAppDescriptor::App>(app->appDescription().id)))
|
|
continue;
|
|
|
|
worthyApps.append(app);
|
|
}
|
|
|
|
for (const LtsPluginManager::LtsPluginManager* app : std::as_const(worthyApps))
|
|
{
|
|
const QVector<LtsSession::LtsSession*> sessions = app->sessions();
|
|
for (const LtsSession::LtsSession* session : sessions)
|
|
{
|
|
if (session->widgetExists(menuGroup, identifier, area))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
LtsMultiMonitor::LtsMultiMonitor* mm = LtsMultiMonitor::LtsMultiMonitor::getInstance();
|
|
LtsMultiMonitor::LtsScreenBase* mainScreen = mm->mainScreen();
|
|
|
|
for (const LtsPluginManager::LtsPluginManager* app : std::as_const(worthyApps))
|
|
{
|
|
const QVector<LtsSession::LtsSession*> sessions = app->sessions();
|
|
for (LtsSession::LtsSession* session : sessions)
|
|
{
|
|
if (session != thisSession && mm->widgetsScreen(session->baseLayoutWidget()) == mainScreen &&
|
|
requiredPartitionTypes.contains(session->partitionType()))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace LtsAppManager
|