1152 lines
27 KiB
C++
Executable File
1152 lines
27 KiB
C++
Executable File
#include "lts_app_manager.h"
|
|
#include "AppChooser/app_chooser.h"
|
|
|
|
#include <LtsPluginManager/lts_plugin_manager.h>
|
|
#include <LtsLogin/lts_login.h>
|
|
#include <LtsSession/lts_session.h>
|
|
#include <LtsSession/lts_session_data.h>
|
|
#include <LtsSession/lts_session_manager.h>
|
|
#include <LtsMultiMonitor/lts_multi_monitor.h>
|
|
#include <LtsWidgets/lts_global_wait_dialog.h>
|
|
#include <LtsUtilsSettings/settings.h>
|
|
#include <LtsWidgets/lts_events.h>
|
|
#include <PluginInterfaces/gui_plugin_interface.h>
|
|
#include <OperatorManagement/opm_settings_gui_plugin_interface.h>
|
|
|
|
#include <QCoreApplication>
|
|
#include <QMessageBox>
|
|
#include <QTimer>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonArray>
|
|
#include <QJsonValue>
|
|
#include <QTcpServer>
|
|
#include <QTcpSocket>
|
|
#include <QUuid>
|
|
|
|
|
|
|
|
|
|
#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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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 : qAsConst(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;
|
|
}
|
|
|
|
}
|