/** * @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 #include #include #include #include #include // for connections #include namespace LtsWidgets { class LtsBackgroundWidget; class LtsTabWidget; class LtsBaseLayoutWidget; struct ExerciseData; class LtsDialog; class LtsDragIcon; } // namespace LtsWidgets namespace LtsNotification { class LtsNotification; class LtsNotificationController; } // namespace LtsNotification namespace LtsPluginManager { struct PluginInstance; struct AppPluginInstance; } // namespace LtsPluginManager namespace DeveloperTools { class DevDialog; class AppWidget; } // namespace DeveloperTools namespace Core { namespace Interface { class Ftc; } } // namespace Core 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