451 lines
18 KiB
C++
Executable File
451 lines
18 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Base Layout Widget with all Areas (Info, Main, Detail, Menu)
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "lts_base.h"
|
|
#include "lts_widgets_export.h"
|
|
#include "lts_notification_box.h"
|
|
#include "qevent.h"
|
|
|
|
#include <memory>
|
|
#include <QMap>
|
|
#include <QPointer>
|
|
#include <QWidget>
|
|
|
|
|
|
class QButtonGroup;
|
|
class QPropertyAnimation;
|
|
class QPushButton;
|
|
class QTimer;
|
|
class QToolButton;
|
|
|
|
namespace Ui
|
|
{
|
|
class LtsBaseLayoutWidget;
|
|
}
|
|
|
|
namespace IDL
|
|
{
|
|
enum class PartitionType;
|
|
}
|
|
|
|
namespace LtsUtils { class Promise; }
|
|
|
|
namespace LtsWidgets
|
|
{
|
|
class LtsDragIcon;
|
|
class LtsProgressDialogHelper;
|
|
class LtsTabWidget;
|
|
class LtsToolBarArea;
|
|
class LtsToolBox;
|
|
|
|
struct ExerciseData
|
|
{
|
|
QString exName;
|
|
QString exDescription;
|
|
int phId = -1;
|
|
QString phName;
|
|
QString phDescription;
|
|
QString exStateString; // Already translated. Todo: Probably won't change, if Language is changed on the fly.
|
|
ExcState exState = ExerciseState::eUnknown;
|
|
QColor exStateCol;
|
|
QString partitionType;
|
|
|
|
bool operator==(const ExerciseData &o) const
|
|
{
|
|
return exName == o.exName &&
|
|
exDescription == o.exDescription &&
|
|
phId == o.phId &&
|
|
phName == o.phName &&
|
|
phDescription == o.phDescription &&
|
|
exStateString == o.exStateString &&
|
|
exState == o.exState &&
|
|
exStateCol == o.exStateCol &&
|
|
partitionType == o.partitionType;
|
|
}
|
|
bool operator!=(const ExerciseData &o) const
|
|
{
|
|
return !operator ==(o);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief The LtsBaseLayoutWidget class represents the Patric-Layout-System (all Areas: Info, Main, Detail, Menu), which is used as stand-alone widget per Screen.
|
|
* It is created per Session by the LtsSession, created by the LtsSessionManager whenever a new Session was created.
|
|
*/
|
|
class LTSWIDGETS_EXPORT LtsBaseLayoutWidget : public QWidget
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit LtsBaseLayoutWidget(QWidget *parent = nullptr, bool splitMenu = true);
|
|
~LtsBaseLayoutWidget();
|
|
|
|
/**
|
|
* @brief hideVisibleLayouts hides all layouts without interfering layout sizes and saves all layout's old states that can be restored by calling resetLayoutVisibility
|
|
*/
|
|
void hideVisibleLayouts();
|
|
|
|
/**
|
|
* @brief resetLayoutVisibility reverts the actions done by hideVisibleLayouts - reshows all hidden layouts
|
|
*/
|
|
void resetLayoutVisibility();
|
|
|
|
/**
|
|
* @brief setMenuVisible sets the visibility of the menu (and the special tab, too!)
|
|
* @param visible true to reshow the menu and special tab, false to completely hide them
|
|
*/
|
|
void setMenuVisible(bool visible);
|
|
|
|
/**
|
|
* @brief isMenuVisible returns the visibility state of the menu (and special tab, too!)
|
|
* @return true if both are visibly, false if not
|
|
*/
|
|
bool isMenuVisible() const;
|
|
|
|
bool isTopBarVisible() const;
|
|
void setTopBarVisible(bool visible);
|
|
|
|
/**
|
|
* @brief isMenuCollapsed returns if the menu was collapsed programmatically by calling clappseMenu.
|
|
* NOTE: does not consider the collapsed state if the user collapsed the menu himself by reducing the menu size to zero by moving the splitter.
|
|
* @return true is collapsed before, false if menu is not size zero.
|
|
*/
|
|
bool isMenuCollapsed() const;
|
|
|
|
/**
|
|
* @brief collapseMenu reduces the size of the menu to zero, but the visibility doesn't change, so that the user can still restore the menu with the splitter.
|
|
* NOTE: the special tab widget is collapsed, too.
|
|
* @param collapse true to collapse, false to restore to the state before the collapse.
|
|
*/
|
|
void collapseMenu(bool collapse = true);
|
|
|
|
/**
|
|
* @brief setSessionInfo sets the informations about the Session of this BaseLayout, so that the window can request a Session close (by logging out) when this window receives a close request.
|
|
*/
|
|
void setSessionInfo(const int domainId, const IDL::PartitionType &partitionType, const int partitionId, const QString &workspaceId);
|
|
|
|
/**
|
|
* @brief addMenuAction adds an action (aka. menu entry) to the menu layout. The Action will be added into the given group.
|
|
* @param plData Action data with information about where to put the menu entry and what to do when the menu entry is clicked
|
|
* @return the LtsDragIcon that was now created and put into the menu layout
|
|
*/
|
|
LtsDragIcon *addMenuAction(const PluginData &plData, bool isFirstRun = false);
|
|
|
|
/**
|
|
* @brief removeMenuAction removes an action (aka. menu entry) previously created by the addMenuAction method by identifying it by the information in the given plData
|
|
* @param plData Action data to identify the menu entry with (group name + captioin text of the menu entry)
|
|
* @return true when found & deleted, false when not found and also not deleted
|
|
*/
|
|
bool removeMenuAction(const PluginData &plData);
|
|
|
|
/**
|
|
* @brief removeMenuAction removes an action (aka. menu entry) previously created by the addMenuAction method by identifying it by the pointer value
|
|
* @param icon to identify the action (aka. menu entry) by the menu entry the LtsDragIcon that was created by the addMenuAction method and put into the menu layout
|
|
* @return true when found & deleted, false when not found and also not deleted (as it was deleted before)
|
|
*/
|
|
bool removeMenuAction(LtsDragIcon *icon);
|
|
|
|
bool removeMenuAction(const QString &byIdentifier);
|
|
|
|
/**
|
|
* @brief clearMenuActions deletes all actions (aka. menu entries) in the menu layout
|
|
*/
|
|
void clearMenuActions();
|
|
|
|
void setAppName(const QString &appName);
|
|
bool isDialogFocused(const LtsDialog *dialog) const;
|
|
|
|
/**
|
|
* @brief setCustomText shows a custom text to the top layout of the base layout, right after the partition type text.
|
|
* Also prepends a bullet before the text to clearly differenciate between the partition type text and the custom text.
|
|
* Call with an empty string to hide the custom text again.
|
|
* @param text to print on the label
|
|
*/
|
|
void setCustomText(const QString &text);
|
|
const QString customText() const;
|
|
|
|
/**
|
|
* @brief getTabFromLayoutArea returns the pointer to the LtsTabWidget that is of the type LayoutArea 'area'
|
|
* @param area the area of which the LtsTabWidget's type of
|
|
* @return the pointer to the LtsTabWidget
|
|
*/
|
|
LtsTabWidget *getTabFromLayoutArea(LayoutArea area) const;
|
|
|
|
/** TODO: rename to getDialog
|
|
* @brief getWidget returns the Dialog which is located in the given LayoutArea, identified by the group + identifier strings
|
|
* @param menuGroup the name of the main tab of the LayoutArea
|
|
* @param identifier the name of the sub tab (when sub-tabbed) of the LayoutArea, otherwise the identifier is added to the menuGroup string
|
|
* @param area the LayoutArea (/LtsTabWidget) the Dialog is located
|
|
* @return the LtsDialog when found, otherwise nullptr when not found
|
|
*/
|
|
LtsDialog *getWidget(const QString &menuGroup, const QString &identifier, LayoutArea area = LayoutArea::eUnknown);
|
|
|
|
/**
|
|
* @brief getMenu returns the Widget of the Menu Layout Area (as the Menu is not an actual LayoutArea (not an LtsTabWidget which could be returned by 'getTabFromLayoutArea')
|
|
* @return the pointer to the Widget of the Menu Layout
|
|
*/
|
|
QWidget *getMenu() const;
|
|
|
|
/**
|
|
* @brief getToolbar returns the LtsToolBarArea of the Menu Layout Area
|
|
* @return the pointer to the LtsToolBarArea of the Menu Layout
|
|
*/
|
|
LtsToolBarArea *getToolbar() const;
|
|
|
|
/**
|
|
* @brief setOperatorName sets the operator name of this session's operator and sets the operator name widget's text
|
|
* @param operatorName the human readable operator name of this session's operator
|
|
*/
|
|
void setOperatorName(const QString &operatorName, bool showTerminalButton);
|
|
|
|
/**
|
|
* @brief setProfilePicture sets the profile picture of this session's operator and sets the profile picture widget's picture
|
|
* @param profilePicture the profgile picture of this session's operator
|
|
*/
|
|
void setProfilePicture(const QPixmap &profilePicture);
|
|
|
|
/**
|
|
* @brief setExerciseData sets the name and phase of this Exercise (if it is an Exercise) of this session - only sets the text of a label (label is hidden of not set)
|
|
* @param exerciseData necessary data to show
|
|
*/
|
|
void setExerciseData(const ExerciseData &data);
|
|
|
|
/**
|
|
* @brief Call this function when the base layout was properly constructed so baselayout can do some internal stuff
|
|
*/
|
|
void initilizationFinished();
|
|
|
|
/**
|
|
* @brief addNotification [Do not use.] used by LtsSession to add a Notification to the Notification Bar, but as a QToolButton
|
|
* @param noti the noti to add to the Notification Bar
|
|
*/
|
|
void addNotification(QToolButton *noti);
|
|
|
|
/**
|
|
* @brief isWidgetsHidden returns the visibility state of the detail tab - the state changes with calling either of
|
|
* these methods: onReShowAnimated, onHideAnimated, showWidgets, hideWidgets
|
|
* @return detail tab visible (not to be confused with resizing the detail widget with the splitter, that only
|
|
* minized the tab, but the tab is still visible)
|
|
*/
|
|
bool isWidgetsHidden() const;
|
|
|
|
bool notificationExists(const QString &identifier) const;
|
|
const QMap<LtsDragIcon *, PluginData> &mapButtons() const { return m_mapButtons; }
|
|
void setToolBarActions(const QStringList &actions);
|
|
QStringList toolBarActions() const;
|
|
void setFunctionKeys(const QMap<int, QString> &actions);
|
|
QMap<int, QString> functionKeys() const;
|
|
void setWorkspaceId(const QString &workspaceId) { m_workspaceId = workspaceId; }
|
|
|
|
/**
|
|
* @brief showMessage adds a notification bubble to the bottom right of the blw. Text can be formatted with HTML.
|
|
* If a message is already visible, it will be replaced and will be shown after the new message was closed.
|
|
* A message with the same identifier will be replaced in the queue or if currently shown.
|
|
* @param title The title in bold which is show obove the text.
|
|
* @param text The text to show in the bubble - should be as short as possible as bubbles are small. Can be HTML.
|
|
* @param type The type which sets the color and icon the bubble should have. See LtsNotificationBox::MessageType.
|
|
* @param clickedLinkCallback The function to call if a link inside the bubble has been clicked (HTML 'a' tag)
|
|
* @param closeOnLinkClicked Closes the bubble if a link has been clicked. Note: queued messages (if any) will be shown next
|
|
* @param identifier An invisible identifier a message will be queued with. Can be left empty. If another message with the
|
|
* same identifier (if not empty) is shown, the other message with the same identifier will be removed from the queue or if
|
|
* it's the shown message, it will be closed.
|
|
*/
|
|
void showMessage(const QString &title, const QString &text, LtsNotificationBox::MessageType type = LtsNotificationBox::MessageType::Info, const std::function<void(const QString &link)> &clickedLinkCallback = nullptr, bool closeOnLinkClicked = true, const QString &identifier = {});
|
|
bool messageIdentifierExists(const QString &identifier) const;
|
|
|
|
void executeAction(const QString &actionIdentifier);
|
|
bool isSecondaryWidget() const { return m_isSecondaryWidget; } // for the LtsScreenContainer to determine if this is a 'Hilfsansicht' for GUEZ SWP 2023 (https://devhub.defence-elec.de/confluence/x/yLjeDg) (siehe 1.1.1)
|
|
void setSecondaryWidget() { m_isSecondaryWidget = true; }
|
|
|
|
/**
|
|
|
|
* @brief Remove Messages from Queue, as it's handled by someones else
|
|
* @param message identifier to remote from que or diplay.
|
|
*/
|
|
void removeQueuedMessage(const QString &messageIdentifier);
|
|
|
|
|
|
public slots:
|
|
bool slotClose(); // checks for unsaved changes first and aborts if there are any
|
|
void slotLogout(); // checks for unsaved changes first and aborts if there are any
|
|
|
|
void slotScreenCountChanged(int count);
|
|
|
|
/**
|
|
* @brief onMenuEntryClicked is triggered when an action (aka. menu entry) in the menu layout is clicked, executes the action's payload (or focuses the coherant dialog when already open)
|
|
*/
|
|
void onMenuEntryClicked();
|
|
|
|
void onHideAnimated();
|
|
void onReShowAnimated();
|
|
|
|
/**
|
|
* @brief addWidget adds a widget to the operator-specified base layout (either selection by cursor or by permanent selectioin) NOTE: deletes dialog if it already exists
|
|
* @param widget the Dialog to be added
|
|
* @param menuGroup the main tab identified by 'menuGroup' (tab is created when tab not existent) to add the Dialog into
|
|
* @param identifier the sub tab (when LtsTabWidget is sub-tabbed, otherwise only added to tab identified by menuGroup + identifier), identified by 'identifier' to add the Dialog into - keep empty to prevent checking for existing tabs
|
|
* @param area the LayoutArea to add the Dialog into
|
|
* @param setClosable true when closable by operator (shows a close-button in the tab), false when not closable by operator
|
|
* @return true when added, false when not (invalid widget or non-existant LayoutArea)
|
|
*/
|
|
bool addWidget(LtsWidgets::LtsDialog *dialog, const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area = LayoutArea::eUnknown, bool setClosable = true, bool focusNewTab = true);
|
|
|
|
/**
|
|
* @brief Like addWidget addOrReplaceWidget adds a dialog widget to base layout with the difference that an existing widget with same identifier is removed from layout before adding he new one.
|
|
* The new dialog will not be deleted (compare with adddWidget)
|
|
* @param widget the Dialog to be added
|
|
* @param menuGroup the main tab identified by 'menuGroup' (tab is created when tab not existent) to add the Dialog into
|
|
* @param identifier the sub tab (when LtsTabWidget is sub-tabbed, otherwise only added to tab identified by menuGroup + identifier), identified by 'identifier' to add the Dialog into - keep empty to prevent checking for existing tabs
|
|
* @param area the LayoutArea to add the Dialog into
|
|
* @param setClosable true when closable by operator (shows a close-button in the tab), false when not closable by operator
|
|
* @return true when added, false when not (invalid widget or non-existant LayoutArea)
|
|
* @see addWidget
|
|
*/
|
|
bool addOrReplaceWidget(LtsDialog *dialog, const QString &menuGroup, const QString &identifier, LayoutArea area = LayoutArea::eUnknown, bool setClosable = true, bool focusNewTab = true );
|
|
|
|
bool focusTab(const QString &menuGroup, const QString &identifier, LtsWidgets::LayoutArea area);
|
|
|
|
/**
|
|
* @brief executeCreateInstantFunctions executes both the createWidgetFunc and the directFunc (if available). (only used by LtsSession & this addMenuAction)
|
|
* @param plData
|
|
*/
|
|
void executeCreateInstantFunctions(const LtsWidgets::PluginData &plData);
|
|
|
|
void setExerciseTime(qint64 mSecsSinceEpoch);
|
|
bool haveUnsavedChanges();
|
|
|
|
|
|
|
|
/**
|
|
* @brief notifyUnsavedChanges
|
|
* @return true if there were NO unsaved changes (method 'failed') and vice versa
|
|
*
|
|
*/
|
|
bool notifyUnsavedChanges();
|
|
|
|
// LtsUtils::Promise *notifyUnsavedChangesAsync();
|
|
|
|
void setIrreplaceableOnce() { m_irreplaceableOnce = true; }
|
|
bool irreplaceableReset() { bool r = m_irreplaceableOnce; m_irreplaceableOnce = false; return r; }
|
|
bool isIrreplaceable() const { return m_irreplaceableOnce; }
|
|
|
|
/**
|
|
* @brief showWidgets shows the Dialog Layout again after it was previously hidden
|
|
*/
|
|
void showWidgets();
|
|
|
|
/**
|
|
* @brief hideWidgets hides the visible Dialog Layout (for example e.g. when more space is needed for selection on the map)
|
|
*/
|
|
void hideWidgets();
|
|
|
|
|
|
private slots:
|
|
/**
|
|
* @brief slotOperatorMenuClicked shows a menu to change things affecting the operator (logout, etc.)
|
|
*/
|
|
void slotOperatorMenuClicked();
|
|
|
|
void setCurrentTime();
|
|
|
|
|
|
signals:
|
|
/**
|
|
* @brief signalCloseRequest is emitted by the closeEvent and requests a logout / close of the current Session (if this is the last BaseLayout)
|
|
*/
|
|
//void signalCloseRequest(const int domainId, const IDL::PartitionType &partitionType, const int partitionId);
|
|
|
|
void signalClose();
|
|
void signalLogout();
|
|
void signalShowOperatorSettings();
|
|
void signalRetranslateActions();
|
|
void signalSwap();
|
|
void signalStapleTopicLockHandler(LtsWidgets::LtsDialog *widget);
|
|
void signalSuccessfullyPlaced(); // called by MMM if this widget was successfully placed (even works if MMM is inactive (off))
|
|
|
|
/**
|
|
* Notify about unsaved changes before popup message box.
|
|
*/
|
|
void signalNotifyUnsavedChanges(bool &reject);
|
|
|
|
protected:
|
|
/**
|
|
* @brief closeEvent requests to close a session. As a BaseLayout is linked to a Session, the Session must be closed before allowing
|
|
* the BaseLayout to close. So a logout is executed before closing the BaseLayout.
|
|
* TODO: One or more BaseLayouts can be linked to a Session - look if it's the last BaseLayout
|
|
* @param event
|
|
*/
|
|
void closeEvent(QCloseEvent *event) override;
|
|
|
|
void showEvent(QShowEvent *event) override;
|
|
void changeEvent(QEvent *e) override;
|
|
|
|
|
|
private:
|
|
void addDebugMenu();
|
|
void retranslate();
|
|
void addTouchScroll(QWidget *widget);
|
|
LtsDragIcon *createButton(const PluginData &plData);
|
|
int getIndexOfTab(LtsTabWidget *tab);
|
|
LtsToolBox *getToolBox(const ExercisePart &exercisePart) const;
|
|
QPushButton *getExercisePartButton(const ExercisePart &exercisePart) const;
|
|
void checkExercisePartButtonVisibility();
|
|
void checkMenuGroup(const QString &menuGroup, const ExercisePart &exercisePart);
|
|
bool isDialogFocused(const LtsDialog *dialog, const LayoutArea &layoutArea) const;
|
|
bool isDialogFocused(const LtsDialog *dialog, const LtsTabWidget *tab) const;
|
|
void applyExerciseStateRestricition();
|
|
void executePluginData(const PluginData &plData);
|
|
void showNextQueuedMessage();
|
|
//void removeQueuedMessage(const QString &messageIdentifier);
|
|
|
|
struct Message
|
|
{
|
|
public:
|
|
QString title;
|
|
QString text;
|
|
LtsNotificationBox::MessageType type;
|
|
std::function<void(const QString &link)> clickedLinkCallback;
|
|
bool closeOnLinkClicked;
|
|
QString identifier;
|
|
};
|
|
|
|
ExerciseData m_exerciseData;
|
|
QMap<LtsDragIcon *, PluginData> m_mapButtons;
|
|
QList<int> m_mainSplitterSizes;
|
|
QList<int> m_menuSplitterSizes;
|
|
bool m_isHidden;
|
|
QPropertyAnimation *m_currentAnimation{nullptr};
|
|
Ui::LtsBaseLayoutWidget *m_ui{nullptr};
|
|
IDL::PartitionType m_partitionType;
|
|
int m_domainId;
|
|
int m_partitionId;
|
|
QString m_operatorName;
|
|
bool m_firstShow;
|
|
bool m_showTerminalButton;
|
|
qint64 m_exerciseTime;
|
|
QTimer *m_setCurrentTimeTimer{nullptr};
|
|
bool m_irreplaceableOnce;
|
|
QButtonGroup *m_bg{nullptr};
|
|
QString m_workspaceId;
|
|
int m_screenCount;
|
|
bool m_menuCollapsed;
|
|
QMap<QPointer<LtsWidgets::LtsTabWidget>, bool> m_oldLayoutVisibilityStates;
|
|
LtsNotificationBox *m_notiBox{nullptr};
|
|
QStringList m_notFoundYet;
|
|
bool m_isSecondaryWidget { false };
|
|
QVector<Message> m_currentMessage; // optional
|
|
QVector<Message> m_messageQueue;
|
|
};
|
|
|
|
} // namespace LtsWidgets
|