Files
qt5-legatus-legacy/Lts/Common/LtsSession/lts_session_manager.cpp
T
2026-08-13 18:33:10 +02:00

251 lines
7.8 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Manages all the Sessions
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2016-05-15
*/
#include "lts_session_manager.h"
#include "lts_session.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <LtsPluginManager/lts_plugin_loader.h>
#include <LtsPluginManager/lts_plugin_manager.h>
#include <LtsWidgets/lts_wait_dialog.h>
#include <LtsSession/lts_session_data.h>
#include <PluginInterfaces/data_plugin_interface.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <QDebug>
namespace LtsSession
{
LtsSessionManager::LtsSessionManager()
: QObject()
, m_appId(LtsAppDescriptor::App::Login)
, m_headless(false)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsSession.Manager"))
{}
LtsSessionManager::~LtsSessionManager()
{
// qCritical() << "~LtsSessionManager";
for (auto i = m_sessionMap.begin(); i != m_sessionMap.end(); ++i)
{
LtsSession *session = i.value();
session->setInactive();
session->deleteLater();
}
}
bool LtsSessionManager::init(const DdsConnectionParams &connParams,
const QVector<LtsPluginManager::AppPluginInstance> &dataPluginList,
const QVector<LtsPluginManager::AppPluginInstance> &guiPluginList,
LtsAppDescriptor::App appId,
const QString &workspaceId,
bool headless,
bool hidden) // TODO: what to return ?
{
// TODO: check if maps empty?
m_dataPluginList = dataPluginList;
m_guiPluginList = guiPluginList;
m_appId = appId;
m_headless = headless;
// shortcut: on first login etc. we go through ExerciseChooser to select an exercise
// but when we're already in the exercise and starting an app from within,
// we don't want to have the exercise chooser a second time -> directly go through app
// and show the base layout
// ????? Der Kommentar stimmt leider nicht. Loest leider nicht das Problem.
bool bHasBaseLayout = connParams.exerciseId > 0;
LtsSession *session = createSession(connParams, bHasBaseLayout, true, hidden); // start Admin Session (for login, etc.)
session->setWorkspaceId(workspaceId);
return session;
}
QVector<LtsSession *> LtsSessionManager::sessions()
{
return m_sessionMap.values().toVector();
// QVector<LtsSession *> result;
// for (auto i = m_sessionMap.begin(); i != m_sessionMap.end(); ++i)
// result.append(i.value());
// return result;
}
void LtsSessionManager::softQuit()
{
for (auto i = m_sessionMap.begin(); i != m_sessionMap.end(); ++i)
{
LtsSession *session = *i;
session->aboutToClose();
session->setInactive();
session->deleteLater();
}
m_sessionMap.clear();
emit hideAllOtherBLWs(nullptr); // for tablet mode! shows another hidden session from some other app or maybe the same app, after the visible one was hidden
QMetaObject::invokeMethod(this, &LtsSessionManager::signalQuit, Qt::QueuedConnection); // wait until all Session's deleteLater is done
}
LtsSession *LtsSessionManager::createSession(const DdsConnectionParams &connParams,
bool hasBaseLayout,
bool payloads,
bool hidden)
{
LtsSession *session = getSession(connParams.partitionType, connParams.partitionId);
if (session != nullptr)
{
WARNING_LOG(m_logger) << "Tried to create a Session that already exists";
return nullptr;
}
session = new LtsSession(this);
connect(session, &LtsSession::signalQuit,
this, &LtsSessionManager::signalQuit);
// QueuedConnection since Qt5.9.1 seems to send the buttonRelease event again when entering an
// eventloop within this slot. Not yet clear why this happens
connect(session, &LtsSession::signalClose,
this, &LtsSessionManager::slotCloseSession, Qt::QueuedConnection);
connect(session, &LtsSession::signalLogout,
this, &LtsSessionManager::signalLogout);
connect(session, &LtsSession::signalInitializationAborted,
this, &LtsSessionManager::signalInitializationAborted);
connect(session, &LtsSession::hideAllOtherBLWs,
this, &LtsSessionManager::hideAllOtherBLWs);
connect(session, &LtsSession::taskSwitch,
this, &LtsSessionManager::taskSwitch);
#ifdef LTS_DEBUG
connect(session, &LtsSession::signalStillAlive,
this, [this]()
{
LtsSession *session = qobject_cast<LtsSession *>(sender());
for (auto i = m_sessionMap.constBegin(); i != m_sessionMap.constEnd(); ++i)
{
if (i.value() == session)
return;
}
WARNING_LOG(m_logger) << "Previously deleted Session " << session->partitionId() << "/"
<< session->partitionType() << " is still alive!";
});
#endif
if (hasBaseLayout)
session->setBaseLayoutVisible(); // after payloads are done (if any), the base layout will be created
if (payloads)
session->setPayloadsEnabled();
m_sessionMap[SessionKey(connParams.partitionType, connParams.partitionId)] = session;
LtsSession *globSession = getSession(IDL::PartitionType::Global, 0);
if (globSession && globSession->ddsConnector() && globSession->domainId() == connParams.domainId)
{
dds::domain::DomainParticipant dp = globSession->ddsConnector()->getDomainParticipant();
if (!session->init(dp, connParams, m_dataPluginList, m_guiPluginList)) // init not successful? return invalid ptr
{
session->deleteLater();
return nullptr;
}
}
else
{
/*
* init SOLLTE asynchron ablaufen.
* init läuft aber synchron, da die Payloads der Plugins DIrectConnections benutzen.
* AUf QueuedCOnnections umbauen ist schwerer, da init mit einem SessionCount von 0 rechnet, da init blocking ist und es daher nicht zum aufruf m_sessionMap[...] = ...; kommt......
*/
if (!session->init(connParams, m_dataPluginList, m_guiPluginList, hidden)) // init not successful? return invalid ptr
{
session->deleteLater();
return nullptr;
}
}
if (session->isInitializationDone())
QMetaObject::invokeMethod(this, &LtsSessionManager::signalInitializationFinished,
Qt::QueuedConnection);
else
connect(session, &LtsSession::signalDoneInitializingSession,
this, &LtsSessionManager::signalInitializationFinished,
Qt::QueuedConnection);
return session;
}
void LtsSessionManager::slotCloseSession()
{
LtsSession *session = qobject_cast<LtsSession *>(QObject::sender());
if (!session)
{
FATAL_LOG(m_logger) << "LtsSessionManager: slot called without object - so it cannot be deleted from the session list!";
return;
}
bool found = false;
for (auto i = m_sessionMap.begin(); i != m_sessionMap.end(); ++i)
{
if (i.value() == session)
{
const auto key = i.key();
session->aboutToClose();
session->setInactive();
session->deleteLater();
m_sessionMap.remove(key); // when destruction takes a long time, a new session may have been added which invalidated the iterator
found = true;
break;
}
}
if (!found)
FATAL_LOG(m_logger) << "LtsSessionManager: Cannot find Session in map!";
emit hideAllOtherBLWs(nullptr); // for tablet mode! shows another hidden session from some other app or maybe the same app, after the visible one was hidden
if (m_sessionMap.isEmpty()) // quit app if all sessions closed
emit signalQuit();
}
LtsSession *LtsSessionManager::getSession(IDL::PartitionType partitionType, int partitionId)
{
auto it = m_sessionMap.find(SessionKey(partitionType, partitionId));
if (it != m_sessionMap.end()) // session found? return it!
return it.value();
return nullptr; // not found
}
} // namespace LtsSession