/** * @RDE_HEADER@ * Keeps the DDS Connector and common data about the session * $Id$ * $HeadURL$ * $Author$ * * Created by Mike Wille, SLSE, 2016-05-15 */ #include "lts_session.h" #ifdef BUILD_RTI #include "lts_session_data_dds.h" #include "lts_session_lock_handler.h" #endif // Stub logging macros when BUILD_RTI=OFF #ifndef BUILD_RTI // Logging deaktivieren - qDebug() wird verwendet weil es operator<< für QString unterstützt #define DEBUG_LOG(logger) if (false) qDebug() #define WARNING_LOG(logger) if (false) qDebug() #define ERROR_LOG(logger) if (false) qDebug() #define INFO_LOG(logger) if (false) qDebug() #define TRACE_LOG(logger) if (false) qDebug() #define LOGFUNCTION "" #endif #include "lts_session_manager.h" #include #include #include #include #include #include #include // app icons #include // TODO: rm on release ! #include #include #include #include #include #include #ifdef BUILD_FILTERMANAGEMENT #include // XXX: grrr.. #endif #include #include #include #include #include #include #include #include #include #include #include // #include using namespace LtsWidgets; namespace LtsSession { bool LtsSession::s_valgrind = false; int LtsSession::s_nextSessionId = 0; #ifdef BUILD_RTI LtsSession::LtsSession(LtsSessionManager* sessionManager) : m_sessionManager(sessionManager), m_mainBackground(nullptr), m_hasBaseLayout(false), m_baseLayout(nullptr), m_markedForDeletion(false), m_payloads(false), m_initDone(false), m_menuVisible(true), m_firstActionsFetch(true), m_exerciseData(new LtsWidgets::ExerciseData), m_currentInitIfc(nullptr), m_slotPluginInitDoneMutex(false), m_pluginInitDone(false), m_hidden(false), m_loadedFromSavegame(false), m_foreverInvisible(false), m_id(s_nextSessionId++) #else LtsSession::LtsSession() : m_mainBackground(nullptr), m_hasBaseLayout(false), m_baseLayout(nullptr), m_markedForDeletion(false), m_payloads(false), m_initDone(false), m_menuVisible(true), m_firstActionsFetch(true), m_exerciseData(nullptr), m_hidden(false), m_loadedFromSavegame(false), m_foreverInvisible(false), m_id(s_nextSessionId++) #endif { LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(); connect(this, &LtsSession::signalDoneInitializingSession, this, &LtsSession::slotStopWaitDialog); connect(this, &LtsSession::signalInitializationAborted, this, &LtsSession::slotStopWaitDialog); // preparations for stack connect connect(this, &LtsSession::_signalDoneInitializingSession, this, [this]() { // if (m_initDone) // qWarning() << "blub"; disconnect(this, &LtsSession::_signalDoneInitializingSession, this, nullptr); // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); m_initDone = true; emit signalDoneInitializingSession(); }); QTimer* t = new QTimer(this); t->setInterval(1000); connect(t, &QTimer::timeout, this, &LtsSession::signalStillAlive); t->start(); m_scriptEditorTimer = new QTimer(this); // [Qatar MNQ-474] Crash open Script Editor application Hack if (strcmp(PROJECTBUILD, "qatarmout") == 0 || strcmp(PROJECTBUILD, "qatar") == 0) { #ifdef BUILD_RTI DEBUG_LOG(m_logger) << "qatarmout Timer = 4000"; #endif m_scriptEditorTimer->setInterval(4000); } else { #ifdef BUILD_RTI DEBUG_LOG(m_logger) << "qatarmout Timer = 0"; #endif m_scriptEditorTimer->setInterval(0); } m_scriptEditorTimer->setSingleShot(true); #ifdef BUILD_RTI connect(m_scriptEditorTimer, &QTimer::timeout, this, &LtsSession::delayScriptEditorStart); #endif } LtsSession::~LtsSession() { // qCritical() << "~LtsSession"; // delete m_mainBackground; parented on hiddenWidget! #ifdef BUILD_RTI delete m_baseLayout; // TODO: deleteLater? problem: clear interfaces! // qWarning() << this << "deleted" << m_baseLayout; #endif // Don't: qDeleteAll(m_notiCtlList); // make sure to unref the data plugins, as they carry this LtsSession, and the erase method would not delete the // Session (avoid circular dependencies) #ifdef BUILD_RTI clearGuiPluginInterfaces(); clearDataPluginInterfaces(); #endif #ifdef BUILD_RTI delete m_exerciseData; #endif } QString LtsSession::toString() const { QString str; str.append(QStringLiteral("LtsSession: this=%1").arg(QString::number(reinterpret_cast(this)))); #ifdef BUILD_RTI str.append(QStringLiteral(", domainId=%1, partitionId=%2").arg(domainId()).arg(partitionId())); #endif str.append(QStringLiteral(", workspaceId='%1'").arg(workspaceId())); #ifdef BUILD_RTI str.append(QStringLiteral(", appToString='%1'").arg(appToString(app()))); str.append(QStringLiteral(", partitionType=%1, exerciseId='%2'").arg(partitionType()).arg(exerciseId())); str.append(QStringLiteral(", LtsSessionDataDds=%1").arg(LtsSessionDataDds::toString())); #else str.append(QStringLiteral(", app=Login (stub)")); str.append(QStringLiteral(", partitionType=N/A, exerciseId=N/A")); #endif return str; } #ifdef BUILD_RTI QWidget* LtsSession::baseLayoutWidget() { // qWarning() << "baseLayoutWidget" << m_baseLayout; // qWarning() << "baseLayoutWidget (widget)" << static_cast(m_baseLayout); return static_cast(m_baseLayout); } #else QWidget* LtsSession::baseLayoutWidget() { return nullptr; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::aboutToCloseTab(LayoutArea area) { m_baseLayout->getTabFromLayoutArea(area)->aboutToClose(); } #else void LtsSession::aboutToCloseTab(LayoutArea /*area*/) { // no-op in non-RTI build } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::aboutToClose() { emit sessionAboutToBeDestroyed(this); if (m_baseLayout == nullptr) return; aboutToCloseTab(LayoutArea::eDialogTab); aboutToCloseTab(LayoutArea::eInfoTab); aboutToCloseTab(LayoutArea::eSpecialTab); aboutToCloseTab(LayoutArea::eMainTab); } #else void LtsSession::aboutToClose() { emit sessionAboutToBeDestroyed(this); // no-op in non-RTI build } #endif // BUILD_RTI void LtsSession::slotStopWaitDialog() { #ifdef BUILD_RTI disconnect(this, &LtsSession::signalDoneInitializingSession, this, &LtsSession::slotStopWaitDialog); disconnect(this, &LtsSession::signalInitializationAborted, this, &LtsSession::slotStopWaitDialog); #endif LtsWidgets::LtsGlobalWaitDialog::getInstance()->done(); } QString LtsSession::appToString(LtsAppDescriptor::App app) { using namespace LtsAppDescriptor; switch (app) { case App::Situation: return tr("Situation"); case App::ResourceManager: return tr("Resource Manager"); case App::PlanEditor: return tr("Plan Editor"); case App::BuildingViewer: return tr("Building Viewer"); case App::OC: return tr("O/C"); case App::OrgChart: return tr("Organisation Chart"); case App::Scripts: return tr("Scripts"); case App::Snapshot: return tr("Snapshot"); case App::SystemMonitor: return tr("System Monitor"); case App::Timeline: return tr("Timeline"); case App::SymbolEditor: return tr("Symbol Editor"); case App::ScriptEditorEssentialsView: return tr("Scripts Essentials View"); case App::BaseDownloader: return tr("Base Downloader"); case App::OnlineHelp: return tr("Online Help"); case App::ThpSituationReplay: return tr("THP Situation Replay"); case App::SituationTablet: return tr("Situation (Tablet)"); case App::SilhouetteEditor: return tr("Silhouette Editor"); case App::Shootback: return tr("Shootback"); case App::Login: return tr("Login"); break; case App::SAAs: return tr("SAAs"); break; } return tr("Unknown"); } QString LtsSession::appIconFilename(LtsAppDescriptor::App app) { using namespace LtsAppDescriptor; switch (app) { case App::Situation: return QStringLiteral("icon:situation.svg"); case App::ResourceManager: return QStringLiteral("icon:player_equipment.svg"); case App::PlanEditor: return QStringLiteral("icon:plan_editor.svg"); case App::BuildingViewer: return QStringLiteral("icon:3d_viewer.svg"); case App::OC: return QStringLiteral("icon:display_oc_evaluations.svg"); case App::OrgChart: return QStringLiteral("icon:org_chart.svg"); case App::Scripts: return QStringLiteral("icon:insert_script.svg"); case App::Snapshot: return QStringLiteral("icon:snapshots.svg"); case App::SystemMonitor: return QStringLiteral("icon:system_status.svg"); case App::Timeline: return QStringLiteral("icon:timeline.svg"); case App::SymbolEditor: return QStringLiteral("icon:define_tactical_symbols.svg"); case App::ScriptEditorEssentialsView: return QStringLiteral("icon:evaluation_elements.svg"); case App::BaseDownloader: return QStringLiteral("icon:download.svg"); case App::OnlineHelp: return QStringLiteral("icon:help.svg"); case App::ThpSituationReplay: return QStringLiteral("icon:restart.svg"); case App::SituationTablet: return QStringLiteral("icon:situation.svg"); case App::SilhouetteEditor: return QStringLiteral("icon:situation.svg"); case App::Shootback: return QStringLiteral("icon:target.svg"); case App::SAAs: return QStringLiteral("icon:saa_remote_desktop.svg"); case App::Login: break; } return {}; } QIcon LtsSession::appToIcon(LtsAppDescriptor::App app) { return LtsUtils::iconFromSvg(appIconFilename(app)); } #ifdef BUILD_RTI bool LtsSession::removeMenuAction(LtsWidgets::LtsDragIcon* icon) { if (!m_baseLayout) return false; return m_baseLayout->removeMenuAction(icon); } #endif #ifdef BUILD_RTI void LtsSession::setMenuVisible(bool visible) { m_menuVisible = visible; if (m_baseLayout == nullptr) return; m_baseLayout->getMenu()->setVisible(visible); } #else void LtsSession::setMenuVisible(bool /*visible*/) { // no-op in non-RTI build } #endif // BUILD_RTI #ifdef BUILD_RTI LtsDragIcon* LtsSession::addAction(const LtsWidgets::PluginData& plData, bool isFirstRun) { if (!m_baseLayout) { ERROR_LOG(m_logger) << "No BaseLayout available atm, cannot add action!"; return nullptr; } return m_baseLayout->addMenuAction(plData, isFirstRun); } LtsNotification::LtsNotification* LtsSession::createNotification(const QString& identifier) { LtsNotification::LtsNotificationController* c = new LtsNotification::LtsNotificationController(identifier); LtsNotification::LtsNotification* n = new LtsNotification::LtsNotification(c); if (m_baseLayout) m_baseLayout->addNotification(c->createWidget()); m_notiCtlList.append(c); // Wenn die notification getötet wird, auch wieder austragen... connect(c, &LtsNotification::LtsNotificationController::destroyed, this, [this, c]() { m_notiCtlList.removeAll(c); }); return n; } #else LtsDragIcon* LtsSession::addAction(const LtsWidgets::PluginData& /*plData*/, bool /*isFirstRun*/) { // no-op in non-RTI build return nullptr; } LtsNotification::LtsNotification* LtsSession::createNotification(const QString& /*identifier*/) { // no-op in non-RTI build return nullptr; } #endif // BUILD_RTI #ifdef BUILD_RTI bool LtsSession::init(const DdsConnectionParams& connParams, const QVector& dataPluginList, const QVector& guiPluginList, bool hidden) { m_foreverInvisible = hidden; if (!LtsSessionDataDds::init(connParams)) return false; initializePlugins(dataPluginList, guiPluginList); return true; } bool LtsSession::init(const dds::domain::DomainParticipant& dp, const DdsConnectionParams& connParams, const QVector& dataPluginList, const QVector& guiPluginList) { if (!LtsSessionDataDds::init(dp, connParams)) return false; initializePlugins(dataPluginList, guiPluginList); return true; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::initializePlugins(const QVector& dataPluginList, const QVector& guiPluginList) { initializeDataPlugins(dataPluginList); initializeGuiPlugins(guiPluginList); } void LtsSession::initializeDataPlugins(const QVector& dataPluginList) // TODO: DOC: no gui ifcs in data ifcs ! (as // fetchInterfaces() is done before gui ifcs are loaded) { QMap> newDataPluginInterfaces; for (const LtsPluginManager::AppPluginInstance& api : dataPluginList) { DataPluginBase::Plugin* plugin = qobject_cast(api.pluginInstance.plugin); if (!plugin) { WARNING_LOG(m_logger) << "Session: invalid data plugin (" << api.pluginInstance.plugin->metaObject()->className() << ")" << api.pluginInstance.fileName; continue; } // super heavy hardcore hack to speed up login -> we need to check what plugins are needed for an app! if (app() == LtsAppDescriptor::App::Login && (!plugin->pluginName().contains(QStringLiteral("AssetManagement")) && !plugin->pluginName().contains(QStringLiteral("OperatorManagement")) && !plugin->pluginName().contains(QStringLiteral("ExerciseManagement")))) continue; // check if plugin has to be loaded in this session type if (!plugin->availableInPartition(partitionType())) { DEBUG_LOG(m_logger) << "Data plugin " << api.pluginInstance.pluginName << " is not available in this partition type " << partitionType(); continue; } // super heavy hardcore hack to speed up login if ((!plugin->pluginName().contains(QStringLiteral("AssetManagement")) && !plugin->pluginName().contains(QStringLiteral("OperatorManagement")) && !plugin->pluginName().contains(QStringLiteral("ExerciseManagement"))) && app() == LtsAppDescriptor::App::Login) continue; std::shared_ptr ifc = plugin->createDataInterface(this); if (!ifc) { WARNING_LOG(m_logger) << "Create data interface failed for '" << api.pluginInstance.pluginName << "' !"; continue; } m_dataPluginInterfaces[plugin->pluginName()] = ifc; newDataPluginInterfaces[plugin->pluginName()] = ifc; DEBUG_LOG(m_logger) << "Adding data plugin " << plugin->pluginName() << " for " << partitionType() << " - " << this; } addAvailablaeDataPluginInterfaces(newDataPluginInterfaces); } #endif #ifdef BUILD_RTI void LtsSession::initializeGuiPlugins(const QVector& guiPluginList) { m_failedFetches.clear(); /* important to create gui interfaces even if they are not available in a session, * but foreign plugins can still use their ForeignGuiInterface to use * their windows */ for (auto i = guiPluginList.constBegin(); i != guiPluginList.constEnd(); ++i) { const LtsPluginManager::AppPluginInstance& api = *i; GuiPluginBase::Plugin* plugin = qobject_cast(api.pluginInstance.plugin); if (!plugin) { WARNING_LOG(m_logger) << "Session: invalid gui plugin (" << api.pluginInstance.plugin->metaObject()->className() << ")" << api.pluginInstance.fileName; continue; } // check if plugin has to be loaded in this session type if (!plugin->availableInPartition(partitionType())) { DEBUG_LOG(m_logger) << "Gui plugin " << api.pluginInstance.pluginName << " is not available in this partition type " << partitionType(); continue; } std::shared_ptr ifc = plugin->createGuiInterface(this); if (!ifc) { WARNING_LOG(m_logger) << "Create gui interface failed for '" << api.pluginInstance.pluginName << "' (" << api.pluginInstance.plugin->metaObject()->className() << ") !"; continue; } QFlags flags = api.m_flags; // copy flags if (api.pluginInstance.pluginName == QStringLiteral("dev")) flags |= LtsAppDescriptor::PluginInfo::Flag::ACTIONS; ifc->setFlags(flags); // durchreichen.. raw plugin => plugin instance ifc->setOptions(api.m_options); // s.a.a. ifc->setAppId(api.m_appId); // s.a.a. m_guiPluginInterfaces[plugin->pluginName()] = ifc; DEBUG_LOG(m_logger) << "Adding gui plugin " << plugin->pluginName() << " for " << partitionType() << " - " << this; } /*/ * there are all plugin instances in this list * if fetchInterface of a single plugin failes, that plugin instance will be removed (does not find his obligatory plugin(s) in this list) * a refetch has to be done, in case some other plugin(s) used that plugin which is now deleted /*/ QMutableMapIterator> it( m_guiPluginInterfaces); // modify a list while iterating through it while (it.hasNext()) { const auto val = it.next(); const QString& guiPluginKey = val.key(); std::shared_ptr guiPlugin = val.value(); if (!guiPlugin->fetchInterfaces()) { DEBUG_LOG(m_logger) << "Fetching interfaces failed for Gui Plugin '" << guiPluginKey << "' - removing and refetching !"; m_failedFetches.append(guiPluginKey); it.remove(); it.toFront(); // rewind! // remove from payloads list if failed, because payload might already be added before refetching, but we // don't want payloads of plugins that failed fetching interfaces.. for (auto i = m_payloadPriorityMap.begin(); i != m_payloadPriorityMap.end(); ++i) { std::shared_ptr payloadIfc = *i; if (payloadIfc == guiPlugin) break; } m_payloadList.removeAll(guiPlugin); } else { // ERROR_LOG(m_logger) << "GUI FETCH INTERFACE OKAY!"; int executionPriority = guiPlugin->executionPriority(); if (executionPriority > -1) { if (m_payloads && guiPlugin->getFlags().testFlag(LtsAppDescriptor::PluginInfo::Flag::PAYLOAD)) { if (executionPriority == 9999) { if (!m_payloadList.contains(guiPlugin)) m_payloadList.append(guiPlugin); } else m_payloadPriorityMap.insert(executionPriority, guiPlugin); // addPayload(executionPriority, guiPlugin); // DEBUG_LOG(m_logger) << " > has payloads, adding payload request to session"; } } // DEBUG_LOG(m_logger) << " > done"; } } QTimer::singleShot(100, this, &LtsSession::slotStartPluginInit); // executePayloads(); // does not execute when there are no payloads, but is needed to be called here ! } #endif // BUILD_RTI #ifdef BUILD_RTI LtsTabWidget* LtsSession::locateWidget(QWidget* widgetToLocate, LayoutArea area) { if (!m_baseLayout) return nullptr; LtsTabWidget* tabWidget = m_baseLayout->getTabFromLayoutArea(area); if (tabWidget->indexOf(widgetToLocate) >= 0) return tabWidget; return nullptr; // not found! } #else LtsTabWidget* LtsSession::locateWidget(QWidget* /*widgetToLocate*/, LayoutArea /*area*/) { return nullptr; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::enableBaseLayoutMenu(bool on) { if (m_baseLayout) { QWidget* ltsMenu = m_baseLayout->getMenu(); if (ltsMenu) ltsMenu->setEnabled(on); } } void LtsSession::enableBaseLayoutArea(LtsWidgets::LayoutArea area, bool on) { if (m_baseLayout) { QWidget* ltsWidget = m_baseLayout->getTabFromLayoutArea(area); if (ltsWidget) ltsWidget->setEnabled(on); } } #else void LtsSession::enableBaseLayoutMenu(bool /*on*/) { // no-op in non-RTI build } void LtsSession::enableBaseLayoutArea(LtsWidgets::LayoutArea /*area*/, bool /*on*/) { // no-op in non-RTI build } #endif // BUILD_RTI int LtsSession::workstationIp() { static int wsId = -1; if (wsId == -1) { #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) const QString hostname = workstationName(); const auto addreses = QHostInfo::fromName(hostname).addresses(); for (const QHostAddress& ha : addreses) { if (ha.isLoopback()) continue; if (ha.protocol() != QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) continue; wsId = static_cast(ha.toIPv4Address()); break; } #else const QList interfaces = QNetworkInterface::allInterfaces(); for (const QNetworkInterface& ninterface : interfaces) { if (ninterface.type() == QNetworkInterface::InterfaceType::Wifi) continue; const auto addreseEntry = ninterface.addressEntries(); for (const QNetworkAddressEntry& ent : addreseEntry) { const QHostAddress ha = ent.ip(); if (ha.isLoopback()) continue; if (ha.protocol() != QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) continue; wsId = static_cast(ha.toIPv4Address()); break; } if (wsId != -1) break; } #endif } return wsId; } QString LtsSession::workstationName() { return QHostInfo::localHostName().toUpper(); } const QString LtsSession::workspaceId() const { #ifdef BUILD_RTI if (isReplayPartition()) return QStringLiteral("replay_%1").arg(QString::number(partitionId())); #endif return m_workspaceId; // sessionManager->workspaceId(); } void LtsSession::setWorkspaceId(const QString &newWorkspaceId /* <= MW: that's why I like "get" in getter names (needed to prepend "new" because of already existing method with the name "workspaceId") */) { #ifdef BUILD_RTI DEBUG_LOG(m_logger) << LOGFUNCTION << " change workspaceId: cur = '" << m_workspaceId << "' for app '" << appToString(app()) << "'"; DEBUG_LOG(m_logger) << LOGFUNCTION << " change workspaceId: new = '" << newWorkspaceId << "' for app '" << appToString(app()) << "'"; #else Q_UNUSED(newWorkspaceId) #endif m_workspaceId = newWorkspaceId; // m_sessionManager->setWorkspaceId(workspaceId); #ifdef BUILD_RTI if (m_baseLayout) m_baseLayout->setWorkspaceId(workspaceId() /* use getter instead of member var, as replay partition strings can only be retrieved with the getter */); #endif // BUILD_RTI emit workspaceIdChanged(newWorkspaceId); } #ifdef BUILD_RTI ExcState LtsSession::exerciseState() const { return m_exerciseData ? m_exerciseData->exState : ExerciseState::eUnknown; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::connectOnlineHelpButton(LtsWidgets::LtsDialog* widget) { // FIXME: HACK: also connect show online help here !! connect(widget, &LtsDialog::signalShowOnlineHelp, this, &LtsSession::slotShowOnlineHelp, Qt::UniqueConnection); } void LtsSession::slotStapleTopicLockHandler(LtsWidgets::LtsDialog* widget) { if (widget->property("topicLockStapled").isValid()) { Q_ASSERT(false); return; } widget->setProperty("topicLockStapled", true); connectOnlineHelpButton(widget); if (m_coreFtc == nullptr) { DEBUG_LOG(m_logger) << "no core ftc, no TopicLockHandler for " << toString(); return; } auto* topicLockHandler = new TopicLockHandler(/* widget <= see comment below */); /*/ * Conceptional: widgets is closing, widget deletes lock handler, lock handler unlocks via ftc, * lock handler was deleted, ftc answers to already deleted lock handler => crash * This is a conceptional problem in all the ftc handlers /*/ if (!topicLockHandler->init(m_coreFtc, m_exerciseId)) { WARNING_LOG(m_logger) << "LtsSession::addWidget: init of TopicLockHandler failed!"; delete topicLockHandler; return; } connect(topicLockHandler, &TopicLockHandler::signalLockDialog, widget, &LtsDialog::slotLock, Qt::QueuedConnection); connect(topicLockHandler, &TopicLockHandler::signalUnlockDialog, widget, &LtsDialog::slotUnlock, Qt::QueuedConnection); connect(widget, &LtsDialog::signalLockTopic, topicLockHandler, &TopicLockHandler::slotTryLock, Qt::DirectConnection); // sync! // widget->setTopicLockHandler(topicLockHandler); connect(widget, &LtsDialog::destroyed, topicLockHandler, &TopicLockHandler::slotFinalize, Qt::QueuedConnection); // qWarning() << "added tlh to" << widget->windowTitle(); connectOnlineHelpButton(widget); } #else void LtsSession::connectOnlineHelpButton(LtsWidgets::LtsDialog* widget) { Q_UNUSED(widget) // no-op in non-RTI build } void LtsSession::slotStapleTopicLockHandler(LtsWidgets::LtsDialog* widget) { Q_UNUSED(widget) // no-op in non-RTI build } #endif // BUILD_RTI #ifdef BUILD_RTI bool LtsSession::focusTab(const QString& menuGroup, const QString& identifier, LtsWidgets::LayoutArea area) { if (!m_baseLayout) { ERROR_LOG(m_logger) << "no base layout to focus a tab on! menuGroup: " << menuGroup << "ident: " << identifier; return false; } return m_baseLayout->focusTab(menuGroup, identifier, area); } #else bool LtsSession::focusTab(const QString& menuGroup, const QString& identifier, LtsWidgets::LayoutArea area) { Q_UNUSED(menuGroup) Q_UNUSED(identifier) Q_UNUSED(area) return false; } #endif #ifdef BUILD_RTI LtsWidgets::LtsDialog* LtsSession::getWidget(const QString& menuGroup, const QString& identifier, LtsWidgets::LayoutArea area) { if (!m_baseLayout) { ERROR_LOG(m_logger) << "no base layout to get a widget from! menuGroup: " << menuGroup << "ident: " << identifier; return nullptr; } return m_baseLayout->getWidget(menuGroup, identifier, area); } #else LtsWidgets::LtsDialog* LtsSession::getWidget(const QString& menuGroup, const QString& identifier, LtsWidgets::LayoutArea area) { Q_UNUSED(menuGroup) Q_UNUSED(identifier) Q_UNUSED(area) return nullptr; } #endif #ifdef BUILD_RTI bool LtsSession::widgetExists(const QString& menuGroup, const QString& identifier, LayoutArea area) const { if (!m_baseLayout) return false; LtsTabWidget* tab = m_baseLayout->getTabFromLayoutArea(area); if (!tab) return false; QWidget* existingWidget = tab->getWidget(menuGroup, identifier); return existingWidget != nullptr; } #else bool LtsSession::widgetExists(const QString& /*menuGroup*/, const QString& /*identifier*/, LayoutArea /*area*/) const { return false; } #endif // BUILD_RTI #ifdef BUILD_RTI bool LtsSession::addWidget(LtsDialog* widget, const QString& menuGroup, const QString& identifier, LayoutArea area, bool setClosable) { // TODO: operator selection + possibility to permanent select base layout until its dissolving if (!m_baseLayout) { ERROR_LOG(m_logger) << "no base layout to put a widget on! menuGroup: " << menuGroup << "ident: " << identifier; return false; } // slotStapleTopicLockHandler(widget); => already done in blw's addWidget (below!) // FIXMe: connect(widget, &LtsDialog::signalShowOnlineHelp, // this, &LtsSession::slotShowOnlineHelp, // Qt::UniqueConnection) done in slotStaple.. because using LtsDialog::addDialog does NOT reach this // code here ! return m_baseLayout->addWidget(widget, menuGroup, identifier, area, setClosable); } #else bool LtsSession::addWidget(LtsDialog* widget, const QString& menuGroup, const QString& identifier, LayoutArea area, bool setClosable) { Q_UNUSED(widget) Q_UNUSED(menuGroup) Q_UNUSED(identifier) Q_UNUSED(area) Q_UNUSED(setClosable) return false; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::setExerciseData(const LtsWidgets::ExerciseData& exerciseData) { // avoid mutiple calls (and signal to emitted multiple times) if ((*m_exerciseData) == exerciseData) return; *m_exerciseData = exerciseData; // partitionType(); ?!? if (!m_baseLayout) return; m_baseLayout->setExerciseData(exerciseData); emit signalExerciseDataChanged(); } void LtsSession::setProfilePicture(const QPixmap& pixmap) { // partitionType(); ?!? if (!m_baseLayout) return; m_baseLayout->setProfilePicture(pixmap); } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::makeVisible() { Q_ASSERT(m_baseLayout == nullptr); if (m_baseLayout) // onyl create a new base layout when there was not one before ! { qCritical() << "base layout already visible"; return; } createBaseLayout(); } #else void LtsSession::makeVisible() { // BUILD_RTI=OFF: No base layout to create } #endif #ifdef BUILD_RTI void LtsSession::refetchActions() { // get actions for (auto i = m_guiPluginInterfaces.cbegin(); i != m_guiPluginInterfaces.cend(); ++i) { std::shared_ptr ifc = *i; if (!ifc->availableInPartition(partitionType())) { DEBUG_LOG(m_logger) << i.key() << " is not available in this partition type " << partitionType(); continue; } if (m_firstActionsFetch && ifc->getFlags().testFlag(LtsAppDescriptor::PluginInfo::Flag::MAIN) && !ifc->getFlags().testFlag( LtsAppDescriptor::PluginInfo::Flag::ACTIONS)) // respect the MAIN flag, even though ACTIONS is not set // (main, but NOT actions) [but only if this is NOT a // refetch] { ERROR_LOG(m_logger) << "Plugin '" << i.key() << "' has flag 'MAIN' but is missing the 'ACTIONS' flag - ingoring actions!"; continue; } if (ifc->getFlags().testFlag(LtsAppDescriptor::PluginInfo::Flag::ACTIONS)) { // get gui plugin's actions (only when init was successful) const QVector plData = ifc->getActions(); if (plData.isEmpty()) DEBUG_LOG(m_logger) << i.key() << " (" << ifc->menuGroup() << ") does not provide actions"; // WARNING_LOG(m_logger) << " > " << plData.count() << " Actions"; for (const LtsWidgets::PluginData& pd : plData) { if (!pd.menuGroup.isEmpty() && !pd.menuText.isEmpty() && pd.identifier.isEmpty()) // check if identifier is missing ERROR_LOG(m_logger) << "Identifier for Action " << pd.menuGroup << " - " << pd.menuText << " missing - not added!"; else { if (!LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(pd.operatorRight)) m_missingRightActions += pd; m_baseLayout->addMenuAction(pd, m_firstActionsFetch); } } } else { // WARNING_LOG(m_logger) << " > " << plData.count() << " Actions - but ignored by flag"; } } #ifdef LTS_DEBUG if (m_firstActionsFetch) { const QString& executeAction(qEnvironmentVariable("EXCON_EXECUTE_ACTION", {})); if (!executeAction.isEmpty()) { WARNING_LOG(m_logger) << "EXCON_EXECUTE_ACTION was set to: " << executeAction; m_baseLayout->executeAction(executeAction); } } #endif m_firstActionsFetch = false; } #else void LtsSession::refetchActions() { // BUILD_RTI=OFF: No actions to fetch m_firstActionsFetch = false; } #endif #ifdef BUILD_RTI void LtsSession::slotSwap() { LtsMultiMonitor::LtsMultiMonitor::getInstance()->selectAndSwap(m_baseLayout); } #else void LtsSession::slotSwap() { // BUILD_RTI=OFF: No base layout to swap } #endif // BUILD_RTI #ifdef BUILD_RTI int LtsSession::screenId() const { if (m_baseLayout == nullptr) return -1; LtsMultiMonitor::LtsScreenBase* screen = LtsMultiMonitor::LtsMultiMonitor::getInstance()->widgetsScreen(m_baseLayout); if (screen == nullptr) return -2; return screen->screenId(); } #else int LtsSession::screenId() const { return -1; } #endif // BUILD_RTI #ifdef BUILD_RTI int LtsSession::screenContainerId() const { if (m_baseLayout == nullptr) return -1; LtsMultiMonitor::LtsScreenBase* screen = LtsMultiMonitor::LtsMultiMonitor::getInstance()->widgetsScreen(m_baseLayout); if (screen == nullptr) return -2; try { return screen->containerIdOfWidget(m_baseLayout); } catch (...) { } return -3; } #else int LtsSession::screenContainerId() const { return -1; } #endif // BUILD_RTI #ifdef BUILD_RTI int LtsSession::screenTypeId() const { if (m_baseLayout == nullptr) return -1; LtsMultiMonitor::LtsScreenBase* screen = LtsMultiMonitor::LtsMultiMonitor::getInstance()->widgetsScreen(m_baseLayout); if (screen == nullptr) return -2; return screen->screenType(); } #else int LtsSession::screenTypeId() const { return -1; } #endif // BUILD_RTI #ifdef BUILD_RTI LtsAppDescriptor::App LtsSession::app() const { return m_sessionManager ? m_sessionManager->appId() : LtsAppDescriptor::App::Login; } #else LtsAppDescriptor::App LtsSession::app() const { return LtsAppDescriptor::App::Login; } #endif #ifdef BUILD_RTI bool LtsSession::event(QEvent* e) { if (e->type() == QEvent::LanguageChange) m_baseLayout->setAppName(appToString(app())); return LtsSessionDataDds::event(e); } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::addDeveloperActions() { // DEVELOPER / DEBUG MENU { LtsWidgets::PluginData p; p.menuGroup = QStringLiteral("[Dev]"); p.menuText = QStringLiteral("Open Admin Session"); p.identifier = QStringLiteral("OpenAdminSession"); p.directFunc = [&](const LtsWidgets::PluginData&) { LtsSession* adminSession = m_sessionManager->getSession(IDL::PartitionType::Global, 0); if (!adminSession) { // QMessageBox::information(nullptr, QString(), QStringLiteral("no admin session")); DdsConnectionParams connParams; connParams.domainId = domainId(); connParams.partitionId = 0; connParams.exerciseId = 0; connParams.partitionType = IDL::PartitionType::Global; connParams.tcpConnectionUrl = tcpConnectionUrl(); connParams.qos_file = m_qosFileList; adminSession = m_sessionManager->createSession( connParams, true, false); // no payloads !! TODO: is this a real domainId or a dead var ?? return; } else adminSession->makeVisible(); }; m_baseLayout->addMenuAction(p); } { LtsWidgets::PluginData p; p.menuGroup = QStringLiteral("[Dev]"); p.menuText = QStringLiteral("Slow down RequestHelper"); p.identifier = QStringLiteral("SlowDownRequestHelper"); p.directFunc = [&](const LtsWidgets::PluginData&) { LtsUtils::RequestHelper::s_debug = true; }; m_baseLayout->addMenuAction(p); } { LtsWidgets::PluginData p; p.menuGroup = QStringLiteral("[Dev]"); p.menuText = QStringLiteral("Reset RequestHelper"); p.identifier = QStringLiteral("ResetRequestHelper"); p.directFunc = [&](const LtsWidgets::PluginData&) { LtsUtils::RequestHelper::s_debug = false; }; m_baseLayout->addMenuAction(p); } { LtsWidgets::PluginData p; p.menuGroup = QStringLiteral("[Dev]"); p.menuText = QStringLiteral("fake DoneInitializingSession"); p.identifier = QStringLiteral("fakeDoneInitializingSession"); p.directFunc = [&](const LtsWidgets::PluginData&) { m_initDone = true; emit _signalDoneInitializingSession(); }; m_baseLayout->addMenuAction(p); } // END DEVELOPER / DEBUG MENU } #endif #ifdef BUILD_RTI bool LtsSession::notifyUnsavedChanges() { if (m_baseLayout == nullptr) return true; return m_baseLayout->notifyUnsavedChanges(); } #else bool LtsSession::notifyUnsavedChanges() { return true; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::createBaseLayout() { // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); using namespace LtsAppDescriptor; TRACE_LOG(m_logger) << LOGFUNCTION << " START, Creating Base Layout for Session " << partitionId(); Q_ASSERT(m_baseLayout == nullptr); if (m_baseLayout != nullptr) { WARNING_LOG(m_logger) << "Base Layout already exists for Session" << this; return; // already exists } m_baseLayout = new LtsBaseLayoutWidget; // main widget connect(m_baseLayout, &LtsBaseLayoutWidget::signalSuccessfullyPlaced, this, [this]() { DEBUG_LOG(m_logger) << "current APP " << appToString(this->app()); // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); if (this->app() == App::Scripts) { m_scriptEditorTimer->start(); } else { if (m_needsToBeSuccessfullyPlaced) { // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); emit _signalDoneInitializingSession(); // needs to be emitted here, as if 'm_needsToBeSuccessfullyPlaced' is // TRUE, it was not emitted before } } }); connect(m_baseLayout, &LtsBaseLayoutWidget::destroyed, this, [this]() { m_baseLayout = nullptr; // sec // qWarning() << "baseLayout deleted"; }); m_baseLayout->hide(); // hide m_baseLayout->setSessionInfo(domainId(), partitionType(), partitionId(), workspaceId()); // this shd ptr has a different counter .. m_baseLayout->setWindowIcon( appToIcon(app())); // for the magic corner to have an icon to show for switching to / from secondaries // auto *x = new QLabel; // x->setPixmap(m_baseLayout->windowIcon().pixmap(128, 128)); // x->show(); if (app() == App::ScriptEditorEssentialsView || // NOTE: timeline's replay app and snapshot's edit plan are // secondaries, too - setSecondaryWidget needs to be called from // timeline & snapshot app, too m_presetBaseLayoutAsSecondaryWidget) m_baseLayout->setSecondaryWidget(); connect(m_baseLayout, &LtsBaseLayoutWidget::signalRetranslateActions, this, &LtsSession::refetchActions); connect(m_baseLayout, &LtsBaseLayoutWidget::signalClose, this, &LtsSession::signalClose); connect(m_baseLayout, &LtsBaseLayoutWidget::signalLogout, this, &LtsSession::signalLogout); connect(m_baseLayout, &LtsBaseLayoutWidget::signalShowOperatorSettings, this, &LtsSession::slotShowOperatorSettings); connect(m_baseLayout, &LtsBaseLayoutWidget::signalSwap, this, &LtsSession::slotSwap); connect(this, &LtsSession::partitionTimeChanged, m_baseLayout, &LtsBaseLayoutWidget::setExerciseTime); connect(m_baseLayout, &LtsBaseLayoutWidget::signalStapleTopicLockHandler, this, &LtsSession::slotStapleTopicLockHandler, Qt::DirectConnection); const auto* sessionData = LtsSessionData::LtsSessionData::getInstance(); const QString& operatorName = sessionData->getOperatorName(); bool showTerminalWindow = sessionData->getShowTerminalWindow(); m_baseLayout->setOperatorName(operatorName, showTerminalWindow); m_baseLayout->setProfilePicture(sessionData->getProfilePicture()); m_baseLayout->setAppName(appToString(app())); refetchActions(); #ifdef LTS_DEBUG bool showDeveloperActions = true; #else bool showDeveloperActions = false; #endif if (sessionData->hasDebugFlag(QStringLiteral("DeveloperTools.Active"))) showDeveloperActions = true; if (showDeveloperActions) addDeveloperActions(); for (LtsNotification::LtsNotificationController* ctl : qAsConst(m_notiCtlList)) { if (!m_baseLayout->notificationExists(ctl->identifier())) // add if non-existent only m_baseLayout->addNotification(ctl->createWidget()); // FIXME: crash when no icons? } m_hasBaseLayout = true; // not needed anymore, but for its correctness..... m_baseLayout->getMenu()->setVisible(m_menuVisible); m_baseLayout->initilizationFinished(); // QMessageBox::warning(nullptr, QStringLiteral("attach!"), QString()); if (!m_foreverInvisible) { // build list of irreplacable widgets by the dependency tree of its dependencies and their dependencies' // dependencies QVector irreplacableWidgets{baseLayoutWidget()}; LtsSession* dependencySession = dependency(); int runaway = 100; while (dependencySession && runaway > 0) { irreplacableWidgets += dependencySession->baseLayoutWidget(); dependencySession = dependencySession->dependency(); runaway--; } // qWarning() << "#2 irreplacableWidgets count" << irreplacableWidgets.count() << "from" << this; // for (QWidget *w : irreplacableWidgets) // qWarning() << "irre" << w; LtsMultiMonitor::LtsMultiMonitor* multiMonitor = LtsMultiMonitor::LtsMultiMonitor::getInstance(); WARNING_LOG(m_logger) << "Presets: ScreenId: " << m_screenIdPreset << ", screenContainerId: " << m_screenContainerIdPreset; if (m_screenIdPreset >= 0) multiMonitor->putScreen(m_baseLayout, m_screenIdPreset, m_screenContainerIdPreset); else multiMonitor->selectScreen(m_baseLayout, nullptr, true, false, irreplacableWidgets); slotMonitorSelected(); connect(multiMonitor, &LtsMultiMonitor::LtsMultiMonitor::signalSelected, this, &LtsSession::slotMonitorSelected, Qt::UniqueConnection); connect(multiMonitor, &LtsMultiMonitor::LtsMultiMonitor::signalScreenCountChanged, m_baseLayout, &LtsBaseLayoutWidget::slotScreenCountChanged); m_baseLayout->slotScreenCountChanged(multiMonitor->screenCount()); } if (!sessionData->isTablet()) return; // done here if not a tablet LtsNotification::LtsNotification* noti = createNotification(QStringLiteral("TabletWindowSwitcher")); noti->setIcon(QIcon(QStringLiteral("icon:switch_display.svg"))); noti->setAction([this]() { emit taskSwitch(this /* tell it that we are the caller, don't hide US! */); }); emit hideAllOtherBLWs(this); } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::slotMonitorSelected() { auto mmm = LtsMultiMonitor::LtsMultiMonitor::getInstance(); LtsMultiMonitor::LtsScreenBase* screen = mmm->widgetsScreen(m_baseLayout); if (!screen) return; int newScreenContainerId; try { newScreenContainerId = screen->containerIdOfWidget(m_baseLayout); } catch (...) { WARNING_LOG(m_logger) << "cannot find container for base layout"; return; } const int newScreenId = screen->screenId(); if (m_screenId != newScreenId) { m_screenId = newScreenId; m_screenContainerId = newScreenContainerId; emit signalScreenIdChanged(m_screenId, m_screenContainerId, screen->screenType()); } } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::delayScriptEditorStart() { DEBUG_LOG(m_logger) << "LtsSession::delayScriptEditorStart "; if (m_needsToBeSuccessfullyPlaced) { // qWarning() << "delayScriptEditorStart mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); emit _signalDoneInitializingSession(); // needs to be emitted here, as if 'm_needsToBeSuccessfullyPlaced' is // TRUE, it was not emitted before } } #endif // BUILD_RTI #ifdef BUILD_RTI bool LtsSession::isChildOfSession(QWidget* child) { if (!child) { return false; } return baseLayout()->isAncestorOf(child); } #else bool LtsSession::isChildOfSession(QWidget* /*child*/) { return false; } #endif // BUILD_RTI void LtsSession::doneInitializingSession() { LtsGlobalWaitDialog::getInstance()->done(); // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); if (m_markedForDeletion) { emit signalInitializationAborted(); // to call done() on global wait dialog emit signalClose(); // session manager removes us from his list and then deletes us return; } #ifdef BUILD_RTI if (!m_sessionManager->isHeadless()) // disallow base layout creation if app is headless { int sessionCount = m_sessionManager->sessionCount(); if (!m_hidden && (m_hasBaseLayout || sessionCount < 1)) // show base layout if m_hasBaseLayout is true OR IF there is only // this session (e.g. Payloads have not started any sessions) makeVisible(); // if (!m_hasBaseLayout) // delete session if it's useless & empty // { // emit signalClose(); // return; // } } #endif #ifdef BUILD_RTI // qWarning() << "emit signalDoneInitializingSession();"; if (!createTopicClient(m_coreFtc)) WARNING_LOG(m_logger) << "could not create core ftc - no tlh"; m_coreFtc->enableAll(); if (!getForeignGuiInterface(m_ohvIfc)) WARNING_LOG(m_logger) << "no ovh ifc, no Help-Button !"; INFO_LOG(m_logger) << "emit signalDoneInitializingSession, session=" << this; // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); // qWarning() << !m_needsToBeSuccessfullyPlaced << m_sessionManager->isHeadless() << !m_hasBaseLayout; if (!m_needsToBeSuccessfullyPlaced || m_sessionManager->isHeadless() || !m_hasBaseLayout) // can't be placed if without something to show .. :) { // qWarning() << "mep" << // QStringLiteral("%1:%2").arg(QString::fromUtf8(__FILE__).split(QStringLiteral("/")).last()).arg(__LINE__); // qWarning() << "!! headless !"; emit _signalDoneInitializingSession(); } // qWarning() << "not headless !"; #else // Non-RTI build: always emit signal after initialization emit _signalDoneInitializingSession(); #endif // BUILD_RTI } void LtsSession::slotShowOnlineHelp(const QString& fileName) { #ifdef BUILD_RTI if (m_ohvIfc == nullptr) { LtsWidgets::LtsMessageDialog::showMessage(baseLayout() /* can be 0ptr */, tr("Online Help not available.")); return; } m_ohvIfc->showHelp(fileName); #else Q_UNUSED(fileName) // no-op in non-RTI build #endif } #ifdef BUILD_RTI void LtsSession::slotShowOperatorSettings() { const QMap& mapButtons = m_baseLayout->mapButtons(); for (auto i = mapButtons.constBegin(); i != mapButtons.constEnd(); ++i) { const PluginData& pd = *i; if (pd.identifier == QStringLiteral("_OpmShowOperatorSettings")) { LtsDialog* showOperatorSettingsDlg = pd.createWidgetFunc(nullptr); if (showOperatorSettingsDlg != nullptr) { addWidget(showOperatorSettingsDlg, pd.menuGroup, pd.identifier, pd.layoutArea, pd.closable); // qWarning() << "showing operator settings"; } else WARNING_LOG(m_logger) << "could not create operator settings dialog from action"; return; } } WARNING_LOG(m_logger) << "action for showing operator settings not found !!"; } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::slotStartPluginInit() { m_initializeThesePlugins = m_guiPluginInterfaces; // copy slotPluginInitDone(); } void LtsSession::slotPluginInitDone() // NEVER call this directly, queue a signal to this slot ! { // qWarning() << "LtsSession::slotPluginInitDone: sender" << sender(); if (m_pluginInitDone) return; if (m_slotPluginInitDoneMutex) { // qWarning() << "<< never call slotPluginInitDone directly or after all initialization was done! bad sender // was" << sender(); abort(); return; } m_slotPluginInitDoneMutex = true; // lock GuiPluginBase::Interface* theSender = dynamic_cast(sender()); if (theSender != m_currentInitIfc) { WARNING_LOG(m_logger) << this << " called slotPluginInitDone from plugin which was not currently active for initialization - ignoring"; #ifdef LTS_DEBUG WARNING_LOG(m_logger) << "current init ifc: " << m_currentInitIfc << ", sender: " << sender(); #endif m_slotPluginInitDoneMutex = false; // unlock return; } // qWarning() << "currently initializing ifc"< ifc = i.value(); if (ifc->availableInPartition(partitionType())) { m_currentInitIfc = ifc.get(); // qWarning() << "set m_currentInitIfc to" << m_currentInitIfc; // qWarning() << "initializing" << i.key() << (void *)ifc.get(); ifc->init(); if (!ifc->m_hasInit) // workaround for ifcs without init method (which needs quitting by signals) { // qWarning() << "resetting m_currentInitIfc to nullptr"; m_currentInitIfc = nullptr; QTimer::singleShot(0, this, &LtsSession::slotPluginInitDone); } } else // do not initialize plugins that are not available in partition x { m_currentInitIfc = nullptr; QTimer::singleShot(0, this, &LtsSession::slotPluginInitDone); } m_initializeThesePlugins.erase(i); m_slotPluginInitDoneMutex = false; // unlock } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::slotExecuteNextPayload() { LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(); // show wait dialog again /* there is currently a problem when executing a secondary event loop, * which leads to resending already sent signals, as they might not be * marked as executed by Qt itself. So this is a workaround.. */ // if (m_ignoreSignalInLoop) // return; // m_ignoreSignalInLoop = true; // execute in order auto it1 = m_payloadPriorityMap.begin(); // largest key (see qt doc) if (it1 != m_payloadPriorityMap.end()) { std::shared_ptr ifc = (*it1); m_payloadPriorityMap.erase( it1); // delete first, as executePayload can be stuck here when the connection is not queued ! DEBUG_LOG(m_logger) << "Executing priorized Payload in Partition " << partitionId() << ", Type " << partitionType(); LtsWidgets::LtsGlobalWaitDialog::getInstance()->done(); // don't interrupt payload uis with the wait dialog if (m_blub) { m_blub->stop(); m_blub->deleteLater(); // qWarning() << "killing blub"; } m_blub = new QTimer(this); m_blub2 = 0; QString name(QString::fromUtf8(typeid(ifc.get()).name())); connect(m_blub, &QObject::destroyed, this, [name]() { // qWarning() << "prio-payload for" << name << "DESTROYED!!!!"; }); connect(m_blub, &QTimer::timeout, this, [this, name]() { m_blub2++; // qWarning() << "prio-payload for" << name << "running since" << m_blub2 << "seconds"; }); m_blub->start(1000); ifc->executePayload(m_mainBackground); } else // no priority payloads left, check for unpriorized payloads { auto it2 = m_payloadList.begin(); if (it2 != m_payloadList.end()) { std::shared_ptr ifc = (*it2); m_payloadList.erase( it2); // delete first, as executePayload can be stuck here when the connection is not queued ! DEBUG_LOG(m_logger) << "Executing unpriorized Payload in Partition " << partitionId() << ", Type " << partitionType(); LtsWidgets::LtsGlobalWaitDialog::getInstance()->done(); // don't interrupt payload uis with the wait dialog if (m_blub) { m_blub->stop(); m_blub->deleteLater(); // qWarning() << "killing blub"; } m_blub = new QTimer(this); m_blub2 = 0; QString name(QString::fromUtf8(typeid(ifc.get()).name())); connect(m_blub, &QObject::destroyed, this, [name]() { // qWarning() << "prio-payload for" << name << "DESTROYED!!!!"; }); connect(m_blub, &QTimer::timeout, this, [this, name]() { m_blub2++; // qWarning() << "prio-payload for" << name << "running since" << m_blub2 << "seconds"; }); m_blub->start(1000); ifc->executePayload(m_mainBackground); } else // no payloads left, delete background widget(s) and say that all plugins have been loaded { Q_ASSERT(m_payloadsDone == false); m_payloadsDone = true; m_mainBackground = nullptr; // as it was parented to m_hiddenWidget if (m_blub) { m_blub->stop(); m_blub->deleteLater(); // qWarning() << "killing blub - no payloads left"; m_blub = nullptr; } // qWarning() << "no payloads left"; doneInitializingSession(); } } // m_ignoreSignalInLoop = false; // executing payload is done, clear the ignore-flag } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::executePayloads() { // look for gui plugins (needed to get execution priority and run payloads) if (!m_payloadPriorityMap.isEmpty() || !m_payloadList.isEmpty()) { // DEBUG_LOG(m_logger) << m_payloadPriorityMap.count() << " priorized payload(s), " << m_payloadList.count() << // " unpriorized payload(s) - " << m_payloadPriorityMap.count() + m_payloadList.count() << " total."; // QMetaObject::invokeMethod(this, &LtsSession::slotExecuteNextPayload); LtsWidgets::LtsGlobalWaitDialog::getInstance() ->done(); // ugly workaround: as the next method says wait even if we call it the first time (LtsSession // c_tor called wait already) slotExecuteNextPayload(); } else { // qWarning() << "this session has no payloads assigned!!"; DEBUG_LOG(m_logger) << "no payloads"; if (partitionType() == IDL::PartitionType::Global) { m_hasBaseLayout = true; // admin session has no payloads, so show base layout, otherwise there is nothing to show.. } doneInitializingSession(); } } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::clearDataPluginInterfaces() { QMap> weakDataPluginInterfaces; for (auto i = m_dataPluginInterfaces.cbegin(); i != m_dataPluginInterfaces.cend(); ++i) { // i.value()->clearInterfaces(); weakDataPluginInterfaces.insert(i.key(), i.value()); } DEBUG_LOG(m_logger) << "Clearing data plugin interfaces for " << partitionType() << " - " << this; m_dataPluginInterfaces.clear(); #ifdef LTS_DEBUG // in global plugins somehow are not unloaded if (partitionType() != IDL::PartitionType::Global) { for (auto i = weakDataPluginInterfaces.cbegin(); i != weakDataPluginInterfaces.cend(); ++i) { std::shared_ptr sp = i.value().lock(); if (!sp) continue; WARNING_LOG(m_logger) << "still referenced Data Plugin '" << i.key() << "' in partition type " << partitionType() << " (use_count=" << sp.use_count() << ")" << " - application may crash on exit! " << this; } } #endif } #endif // BUILD_RTI #ifdef BUILD_RTI void LtsSession::clearGuiPluginInterfaces() { bool bInClearPluginInterfaces = true; auto cbCheckEventLoop = [this, &bInClearPluginInterfaces]() { if (bInClearPluginInterfaces) { ERROR_LOG(m_logger) << "QEventLoop was called within clearGuiPluginInterfaces which is not allowed!"; Q_ASSERT(false); } }; QTimer::singleShot(0, this, cbCheckEventLoop); m_ohvIfc = nullptr; QMap> weakGuiPluginInterfaces; for (auto i = m_guiPluginInterfaces.cbegin(); i != m_guiPluginInterfaces.cend(); ++i) { i.value()->clearInterfaces(); weakGuiPluginInterfaces.insert(i.key(), i.value()); } bInClearPluginInterfaces = false; DEBUG_LOG(m_logger) << "Clearing gui plugin interfaces for " << partitionType() << " - " << this; m_guiPluginInterfaces.clear(); #ifdef LTS_DEBUG // in global plugins somehow are not unloaded if (partitionType() != IDL::PartitionType::Global) { for (auto i = weakGuiPluginInterfaces.cbegin(); i != weakGuiPluginInterfaces.cend(); ++i) { std::shared_ptr sp = i.value().lock(); if (!sp) continue; WARNING_LOG(m_logger) << "still referenced Gui Plugin '" << i.key() << "'in partition type " << partitionType() << " (use_count=" << sp.use_count() << ")" << " Gui Plugin '" << i.key() << "'" << " - application may crash on exit! " << this; } } #endif } #endif // BUILD_RTI #ifdef BUILD_RTI LtsSessionManager* LtsSession::getSessionManager() { return m_sessionManager; } #endif } // namespace LtsSession