/** * @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" #ifdef BUILD_RTI #include "lts_session_manager.h" #endif #include #include #include #include #include #include #include #include #include #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); #ifdef BUILD_RTI explicit LtsSession(LtsSessionManager* sessionManager); #else explicit LtsSession(); #endif ~LtsSession(); QString toString() const; #ifdef BUILD_RTI LtsSessionManager* getSessionManager(); #endif bool init(const DdsConnectionParams& connParams, const QVector& dataPluginList, const QVector& guiPluginList, bool hidden); #ifdef BUILD_RTI bool init(const dds::domain::DomainParticipant& dp, const DdsConnectionParams& connParams, const QVector& dataPluginList, const QVector& guiPluginList); #endif #ifdef BUILD_RTI void makeVisible(); #else void makeVisible(); // no-op when BUILD_RTI=OFF #endif 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); #ifdef BUILD_RTI bool removeMenuAction(LtsWidgets::LtsDragIcon* icon); #endif 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 */ #ifdef BUILD_RTI void setExerciseData(const LtsWidgets::ExerciseData& exerciseData); const LtsWidgets::ExerciseData* exerciseData() const; void setProfilePicture(const QPixmap& pixmap); #else void setExerciseData(const LtsWidgets::ExerciseData& exerciseData) { Q_UNUSED(exerciseData) } const LtsWidgets::ExerciseData* exerciseData() const { return nullptr; } void setProfilePicture(const QPixmap& pixmap) { Q_UNUSED(pixmap) } #endif 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); #ifdef BUILD_RTI LtsWidgets::LtsBaseLayoutWidget* baseLayout() { return m_baseLayout; } #else void* baseLayout() const { return nullptr; } #endif 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); #ifdef BUILD_RTI LtsWidgets::ExcState exerciseState() const; #else LtsWidgets::ExcState exerciseState() const { return LtsWidgets::ExerciseState::eUnknown; } #endif // BUILD_RTI void setLoadedFromSavegame() { m_loadedFromSavegame = true; } bool isLoadedFromSavegame() const { return m_loadedFromSavegame; } void addDeveloperActions(); #ifdef BUILD_RTI void refetchActions(); // Do not use. #else void refetchActions(); // Do not use. (no-op when BUILD_RTI=OFF) #endif void setDependency(LtsSession* session) { #ifdef BUILD_RTI if (m_dependency) { ERROR_LOG(m_logger) << "Tried to set session dependency on self"; return; } m_dependency = session; #else Q_UNUSED(session) #endif } 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: #ifdef BUILD_RTI void slotExecuteNextPayload(); // NEVER call this directly, queue a signal to this slot ! void slotPluginInitDone(); // NEVER call this directly, queue a signal to this slot ! #endif void slotShowOnlineHelp(const QString& fileName); // void takeOverBdv(); private slots: #ifdef BUILD_RTI void slotShowOperatorSettings(); #endif void slotSwap(); void slotStapleTopicLockHandler(LtsWidgets::LtsDialog* widget); void slotStopWaitDialog(); #ifdef BUILD_RTI void slotStartPluginInit(); void slotMonitorSelected(); void delayScriptEditorStart(); #endif 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; #ifdef BUILD_RTI friend class LtsSessionManager; #endif #ifdef BUILD_RTI bool event(QEvent* e) override; #endif void createBaseLayout(); #ifdef BUILD_RTI 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(); #endif 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); #ifdef BUILD_RTI QPointer m_sessionManager; #endif #ifdef BUILD_RTI 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) #endif LtsWidgets::LtsBackgroundWidget* m_mainBackground; bool m_hasBaseLayout; #ifdef BUILD_RTI LtsWidgets::LtsBaseLayoutWidget* m_baseLayout; #else void* m_baseLayout{nullptr}; // stub for non-RTI build #endif bool m_markedForDeletion; bool m_payloads; QVector m_notiCtlList; bool m_initDone; // set by doneInitializingSession / signalDoneInitializingSession #ifdef BUILD_RTI bool m_payloadsDone{false}; // for debug #endif bool m_menuVisible; // bool m_ignoreSignalInLoop = false; bool m_firstActionsFetch; #ifdef BUILD_RTI LtsWidgets::ExerciseData* m_exerciseData; #else void* m_exerciseData{nullptr}; // stub for non-RTI build #endif QVector m_missingRightActions; std::shared_ptr m_coreFtc; #ifdef BUILD_RTI GuiPluginBase::Interface* m_currentInitIfc; // not owning bool m_slotPluginInitDoneMutex; bool m_pluginInitDone; // set by slotPluginInitDone #endif 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 #ifdef BUILD_RTI QStringList m_failedFetches; #endif 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