/** * @RDE_HEADER@ * Keeps the DDS Connector and common data about the session * $Id$ * $HeadURL$ * $Author$ * * Created by Mike Wille, SLSE, 2016-05-15 */ #pragma once #include "lts_session_data_dds.h" #include "lts_session_manager.h" #include #include #include // for connections #include #include #include #include #include #include namespace LtsWidgets { class LtsBackgroundWidget; class LtsTabWidget; class LtsBaseLayoutWidget; struct ExerciseData; class LtsDialog; class LtsDragIcon; } namespace LtsNotification { class LtsNotification; class LtsNotificationController; } namespace LtsPluginManager { struct PluginInstance; struct AppPluginInstance; } namespace DeveloperTools { class DevDialog; class AppWidget; } namespace Core { namespace Interface { class Ftc; } } namespace OnlineHelp { class ForeignOnlineHelpViewerGuiInterface; } namespace LtsSession { class LTSSESSION_EXPORT LtsSession : public LtsSessionDataDds { Q_OBJECT public: static bool s_valgrind; static int s_nextSessionId; enum class PluginInstanceStatus { UNKNOWN = 0, LOADED, FAILED, // e.g. fetchInterfaces gone wrong }; static QString appToString(LtsAppDescriptor::App app); static QString appIconFilename(LtsAppDescriptor::App app); static QIcon appToIcon(LtsAppDescriptor::App app); explicit LtsSession(LtsSessionManager *sessionManager); ~LtsSession(); QString toString() const; LtsSessionManager *getSessionManager(); bool init(const DdsConnectionParams &connParams, const QVector &dataPluginList, const QVector &guiPluginList, bool hidden); bool init(const dds::domain::DomainParticipant &dp, const DdsConnectionParams &connParams, const QVector &dataPluginList, const QVector &guiPluginList); void makeVisible(); void setPayloadsEnabled() { m_payloads = true; } // cannot be reverted void aboutToClose(); bool isInitializationDone() const { return m_initDone; } void presetBaseLayoutAsSecondaryWidget() { m_presetBaseLayoutAsSecondaryWidget = true; } /** * @brief addAction - IMPORTANT: Actions have to be translated on retranslate by adding the same action (with same identifier) * but with translated text & menu group! This replaces the text & menu group only. The pointer to the action stays the same. * @param plData * @param isFirstRun * @return */ LtsWidgets::LtsDragIcon *addAction(const LtsWidgets::PluginData &plData, bool isFirstRun = false); void setMenuVisible(bool visible = true); bool removeMenuAction(LtsWidgets::LtsDragIcon *icon); int screenId() const; int screenContainerId() const; int screenTypeId() const; LtsAppDescriptor::App app() const; void setScreenIdPreset(int screenId) { m_screenIdPreset = screenId; } void setScreenContainerIdPreset(int screenPart) { m_screenContainerIdPreset = screenPart; } bool isForeverInvisible() const { return m_foreverInvisible; } LtsNotification::LtsNotification *createNotification(const QString &identifier); /** * @brief setExerciseData is called by the ExerciseManagement plugin and sets the human reabale name of the exercise and puts the text into all base layouts of this session * @param exerciseData the human reable exercise name of the current exercise */ void setExerciseData(const LtsWidgets::ExerciseData &exerciseData); const LtsWidgets::ExerciseData *exerciseData() const; void setProfilePicture(const QPixmap &pixmap); void setBaseLayoutVisible() { m_hasBaseLayout = true; } // cannot be reverted after base layout was created (creation begins after all payloads have been executed OR if makeVisible was called)! bool isVisible() const { return (m_baseLayout != nullptr); } const QString &name() const { return m_name; } void setName(const QString &name) { m_name = name; } /** * @brief isChildOfSession can be used to check if a fiven QWidget is part of the current Session's application * * @param child widget to check against. * @return true if widget is child of session baselayout */ bool isChildOfSession(QWidget* child); LtsWidgets::LtsBaseLayoutWidget* baseLayout() { return m_baseLayout; } QWidget *baseLayoutWidget(); // prevents some classes to include LtsBaseLayoutWidget.h just to specify the blw as a parent widget void setMarkForDeletion() { m_markedForDeletion = true; } // session not needed anymore after payloads? then mark for deletion and after payloads, this session will be deleted(Later) void doneInitializingSession(); // TODO: private bool notifyUnsavedChanges(); // true if NO unsaved changes const QVector &bgWidgets() const { return m_bgWidgets; } // checks if a widget with the given data already exists bool widgetExists(const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area) const; /** * @brief addWidget * keep identifier empty to prevent checking for existing tabs * @return (see addWidget in LtsBaseLayoutWidget) */ bool addWidget(LtsWidgets::LtsDialog *widget, const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area = LtsWidgets::LayoutArea::eUnknown, bool setClosable = true); LtsWidgets::LtsDialog *getWidget(const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area); bool focusTab(const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area); /** WARNING: do not save the returned value, as baseLayouts can die (which kills LtsTabWidget also), so reuse this method instead of saving the pointer to the LtsTabWidget * @brief locateWidget locates the given widget 'widget' and returning the TabWidget on which it is on - widgets can be available in one of many LayoutAreas (TabWidgets) of many LtsBaseLayoutWidgets * @param widgetToLocate the widget to look for in the given layoutArea which is located in one of many LtsBaseLayoutWidget * @param area the area the widget is located * @return LtsTabWidget on which the widget is located */ LtsWidgets::LtsTabWidget *locateWidget(QWidget *widgetToLocate, LtsWidgets::LayoutArea area); /** * @brief enable/disable baseLayout menu * @param on if true enable otherwise disable */ void enableBaseLayoutMenu(bool on = true); /** * @brief enable/disable LayoutArea * @param area the area to enable/disable * @param on if true enable otherwise disable */ void enableBaseLayoutArea(LtsWidgets::LayoutArea area, bool on = true); /** * @brief Return the workstation ip for this workstation (== full ipv4 adress) - workstation id comes later from Asm */ static int workstationIp(); // really in LtsSession? /** * @brief Return the workstation name */ static QString workstationName(); // really in LtsSession? /** * @brief missingRightActions Do not use. * @return */ /*const*/ QVector &missingRightActions() /*const*/ { return m_missingRightActions; } void setSavegame(const QJsonObject &sg) { m_savegame = sg; } const QJsonObject &getSavegame() const { return m_savegame; } void setHidden() { m_hidden = true; } const QString workspaceId() const; void setWorkspaceId(const QString &newWorkspaceId); LtsWidgets::ExcState exerciseState() const; void setLoadedFromSavegame() { m_loadedFromSavegame = true; } bool isLoadedFromSavegame() const { return m_loadedFromSavegame; } void addDeveloperActions(); void refetchActions(); // Do not use. void setDependency(LtsSession *session); bool hasDependency(LtsSession *session) { return (m_dependency.data() == session); } LtsSession *dependency() const { return m_dependency; } // bogus. void setNeedsToBeSuccessfullyPlaced(bool needed = true) { m_needsToBeSuccessfullyPlaced = needed; } // works even after session creation as 'slotStartPluginInit', which finalizes the session (creates blw, etc.) is called async! int id() const { return m_id; } public slots: void slotExecuteNextPayload(); // NEVER call this directly, queue a signal to this slot ! void slotPluginInitDone(); // NEVER call this directly, queue a signal to this slot ! void slotShowOnlineHelp(const QString &fileName); //void takeOverBdv(); private slots: void slotShowOperatorSettings(); void slotSwap(); void slotStapleTopicLockHandler(LtsWidgets::LtsDialog *widget); void slotStopWaitDialog(); void slotStartPluginInit(); void slotMonitorSelected(); void delayScriptEditorStart(); signals: void signalInitializationAborted(); void _signalDoneInitializingSession(); // internal void signalDoneInitializingSession(); // is called AFTER all payloads have been executed (on no payloads, called after session was created) FOR LTSLOGIN ! void signalClose(); // tells the session manager to close this session void signalLogout(); void signalQuit(); // for payloads, so that they can quit an app void signalStillAlive(); void signalExerciseDataChanged(); void signalScreenIdChanged(int screenId, int screenContainerId, int screenTypeId); void sessionAboutToBeDestroyed(LtsSession *session); void workspaceIdChanged(const QString &newWorkspaceId); void signalTakeOverBdv(); void hideAllOtherBLWs(QObject *caller); void taskSwitch(QObject *caller); private: friend class DeveloperTools::DevDialog; friend class DeveloperTools::AppWidget; friend class LtsSessionManager; bool event(QEvent *e) override; void createBaseLayout(); void initializePlugins(const QVector &dataPluginList, const QVector &guiPluginList); void initializeDataPlugins(const QVector &dataPluginList); void initializeGuiPlugins(const QVector &guiPluginList); bool tryInitGuiPlugin(const QString &guiPluginKey, std::shared_ptr &guiPlugin); void clearDataPluginInterfaces(); void clearGuiPluginInterfaces(); void executePayloads(); void connectOnlineHelpButton(LtsWidgets::LtsDialog *widget); // TODO: AFTER FAT !! void stapleWidget(LtsWidgets::LtsDialog *dialog); // FIXME: HACK: because an LtsDialog can directly add widgets to the base layout and misses the staples... void aboutToCloseTab(LtsWidgets::LayoutArea area); QPointer m_sessionManager; QMap > m_payloadPriorityMap; // QMap automatically sorts by key on iteration and overwrites multiple occurences with the latest) QList > m_payloadList; // for payloads that don't care when they are executed (prio '9999' plugins) LtsWidgets::LtsBackgroundWidget *m_mainBackground; bool m_hasBaseLayout; LtsWidgets::LtsBaseLayoutWidget *m_baseLayout; bool m_markedForDeletion; bool m_payloads; QVector m_notiCtlList; bool m_initDone; // set by doneInitializingSession / signalDoneInitializingSession bool m_payloadsDone { false }; // for debug bool m_menuVisible; //bool m_ignoreSignalInLoop = false; bool m_firstActionsFetch; LtsWidgets::ExerciseData *m_exerciseData; QVector m_missingRightActions; std::shared_ptr m_coreFtc; GuiPluginBase::Interface *m_currentInitIfc; // not owning bool m_slotPluginInitDoneMutex; bool m_pluginInitDone; // set by slotPluginInitDone QJsonObject m_savegame; bool m_hidden; // if true, does not create BLW int m_screenId { -1 }; int m_screenContainerId { -1 }; int m_screenIdPreset { -1 }; int m_screenContainerIdPreset { -1 }; bool m_loadedFromSavegame; std::shared_ptr m_ohvIfc; bool m_foreverInvisible; // if true, creates BLW but hides it and does not use MMM QStringList m_failedFetches; QVector m_bgWidgets; QString m_workspaceId; bool m_needsToBeSuccessfullyPlaced { true /* ALWAYS! */ /*false*/ }; // if set to true, 'signalDoneInitializingSession' will only be called after the blw was successfully placed by MMM (even works if MMM inavtive (off)) QString m_name; QTimer *m_blub { nullptr }; QTimer *m_scriptEditorTimer { nullptr }; int m_blub2; QPointer m_dependency; // when MMM iprovides the screen selection for this app, it isn't allowed to replace apps that are dependencies of this app (e.g. logout bug) bool m_presetBaseLayoutAsSecondaryWidget { false }; int m_id; }; } // namespace LtsSession