// Copyright (C) 2020 Uwe Kindler // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-2.1-or-later OR GPL-3.0-or-later #pragma once #include "ads_globals.h" #include QT_BEGIN_NAMESPACE class QToolBar; class QXmlStreamWriter; QT_END_NAMESPACE namespace ADS { class DockWidgetPrivate; class DockWidgetTab; class DockManager; class DockContainerWidget; class DockAreaWidget; class DockContainerWidgetPrivate; class FloatingDockContainer; class AutoHideTab; class AutoHideDockContainer; class AutoHideSideBar; /** * The QDockWidget class provides a widget that can be docked inside a * DockManager or floated as a top-level window on the desktop. */ class ADS_EXPORT DockWidget : public QFrame { Q_OBJECT Q_PROPERTY(bool focused READ isFocused WRITE setFocused NOTIFY focusedChanged) private: DockWidgetPrivate *d; ///< private data (pimpl) friend class DockWidgetPrivate; /** * Adjusts the toolbar icon sizes according to the floating state */ void setToolbarFloatingStyle(bool topLevel); protected: friend class DockContainerWidget; friend class DockAreaWidget; friend class FloatingDockContainer; friend class DockManager; friend class DockManagerPrivate; friend class DockContainerWidgetPrivate; friend class DockAreaTabBar; friend class DockWidgetTab; friend class DockWidgetTabPrivate; friend class DockAreaTitleBarPrivate; friend class AutoHideDockContainer; friend AutoHideSideBar; /** * Assigns the dock manager that manages this dock widget */ void setDockManager(DockManager *dockManager); /** * If this dock widget is inserted into a dock area, the dock area will * be registered on this widget via this function. If a dock widget is * removed from a dock area, this function will be called with nullptr * value. */ void setDockArea(DockAreaWidget *dockArea); /** * This function changes the toggle view action without emitting any * signal */ void setToggleViewActionChecked(bool checked); /** * Saves the state into the given stream */ void saveState(QXmlStreamWriter &stream) const; /** * This is a helper function for the dock manager to flag this widget * as unassigned. * When calling the restore function, it may happen, that the saved state * contains less dock widgets then currently available. All widgets whose * data is not contained in the saved state, are flagged as unassigned * after the restore process. If the user shows an unassigned dock widget, * a floating widget will be created to take up the dock widget. */ void flagAsUnassigned(); /** * Call this function to emit a topLevelChanged() signal and to update * the dock area tool bar visibility */ static void emitTopLevelEventForWidget(DockWidget *topLevelDockWidget, bool floating); /** * Use this function to emit a top level changed event. * Do never use emit topLevelChanged(). Always use this function because * it only emits a signal if the floating state has really changed */ void emitTopLevelChanged(bool floating); /** * Internal function for modifying the closed state when restoring * a saved docking state */ void setClosedState(bool closed); /** * Internal toggle view function that does not check if the widget * already is in the given state */ void toggleViewInternal(bool open); /** * Internal close dock widget implementation. * The function returns true if the dock widget has been closed or hidden */ bool closeDockWidgetInternal(bool forceClose = false); public: using Super = QFrame; enum DockWidgetFeature { DockWidgetClosable = 0x001, ///< dock widget has a close button DockWidgetMovable = 0x002, ///< dock widget is movable and can be moved to a new position in the current dock container DockWidgetFloatable = 0x004, ///< dock widget can be dragged into a floating window DockWidgetDeleteOnClose = 0x008, ///< deletes the dock widget when it is closed CustomCloseHandling = 0x010, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead DockWidgetFocusable = 0x020, ///< if this is enabled, a dock widget can get focus highlighting DockWidgetForceCloseWithArea = 0x040, ///< dock widget will be closed when the dock area hosting it is closed NoTab = 0x080, ///< dock widget tab will never be shown if this flag is set DeleteContentOnClose = 0x100, ///< deletes only the contained widget on close, keeping the dock widget intact ///< and in place. Attempts to rebuild the contents widget on show if there is a widget factory set. DockWidgetPinnable = 0x200, ///< dock widget can be pinned and added to an auto hide dock container DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable | DockWidgetPinnable, AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling, DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose, NoDockWidgetFeatures = 0x000 }; Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) enum eState { StateHidden, StateDocked, StateFloating }; enum eToolBarStyleSource { ToolBarStyleFromDockManager, ToolBarStyleFromDockWidget }; /** * Sets the widget for the dock widget to widget. * The InsertMode defines how the widget is inserted into the dock widget. * The content of a dock widget should be resizable do a very small size to * prevent the dock widget from blocking the resizing. To ensure, that a * dock widget can be resized very well, it is better to insert the content+ * widget into a scroll area or to provide a widget that is already a scroll * area or that contains a scroll area. * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically * detect how to insert the given widget. If the widget is derived from * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted * directly. If the given widget is not a scroll area, the widget will be * inserted into a scroll area. * To force insertion into a scroll area, you can also provide the InsertMode * ForceScrollArea. To prevent insertion into a scroll area, you can * provide the InsertMode ForceNoScrollArea */ enum eInsertMode { AutoScrollArea, ForceScrollArea, ForceNoScrollArea }; /** * The mode of the minimumSizeHint() that is returned by the DockWidget * minimumSizeHint() function. * To ensure, that a dock widget does not block resizing, the dock widget * reimplements minimumSizeHint() function to return a very small minimum * size hint. If you would like to adhere the minimumSizeHint() from the * content widget, then set the minimumSizeHintMode() to * MinimumSizeHintFromContent. If you would like to use the minimumSize() * value of the content widget or the dock widget, then you can use the * MinimumSizeHintFromDockWidgetMinimumSize or * MinimumSizeHintFromContentMinimumSize modes. */ enum eMinimumSizeHintMode { MinimumSizeHintFromDockWidget, MinimumSizeHintFromContent, MinimumSizeHintFromDockWidgetMinimumSize, MinimumSizeHintFromContentMinimumSize, }; /** * This mode configures the behavior of the toggle view action. * If the mode if ActionModeToggle, then the toggle view action is * a checkable action to show / hide the dock widget. If the mode * is ActionModeShow, then the action is not checkable an it will * always show the dock widget if clicked. If the mode is ActionModeShow, * the user can only close the DockWidget with the close button. */ enum eToggleViewActionMode { ActionModeToggle, //!< ActionModeToggle ActionModeShow //!< ActionModeShow }; /** * This constructor creates a dock widget with the given title. * The title is the text that is shown in the window title when the dock * widget is floating and it is the title that is shown in the titlebar * or the tab of this dock widget if it is tabified. * The object name of the dock widget is also set to the title. The * object name is required by the dock manager to properly save and restore * the state of the dock widget. That means, the title needs to be unique. * If your title is not unique or if you would like to change the title * during runtime, you need to set a unique object name explicitly * by calling setObjectName() after construction. * Use the layoutFlags to configure the layout of the dock widget. */ DockWidget(const QString &uniqueId, QWidget *parent = nullptr); /** * Virtual Destructor */ ~DockWidget() override; /** * We return a fixed minimum size hint or the size hint of the content * widget if minimum size hint mode is MinimumSizeHintFromContent */ QSize minimumSizeHint() const override; /** * Sets the widget for the dock widget to widget. * The InsertMode defines how the widget is inserted into the dock widget. * The content of a dock widget should be resizable to a very small size to * prevent the dock widget from blocking the resizing. To ensure, that a * dock widget can be resized very well, it is better to insert the content+ * widget into a scroll area or to provide a widget that is already a scroll * area or that contains a scroll area. * If the InsertMode is AutoScrollArea, the DockWidget tries to automatically * detect how to insert the given widget. If the widget is derived from * QScrollArea (i.e. an QAbstractItemView), then the widget is inserted * directly. If the given widget is not a scroll area, the widget will be * inserted into a scroll area. * To force insertion into a scroll area, you can also provide the InsertMode * ForceScrollArea. To prevent insertion into a scroll area, you can * provide the InsertMode ForceNoScrollArea */ void setWidget(QWidget *widget, eInsertMode insertMode = AutoScrollArea); /** * Only used when the feature flag DeleteContentOnClose is set. * Using the flag and setting a widget factory allows to free the resources * of the widget of your application while retaining the position the next * time you want to show your widget, unlike the flag DockWidgetDeleteOnClose * which deletes the dock widget itself. Since we keep the dock widget, all * regular features of ADS should work as normal, including saving and * restoring the state of the docking system and using perspectives. */ using FactoryFunc = std::function; void setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode = AutoScrollArea); /** * Remove the widget from the dock and give ownership back to the caller */ QWidget *takeWidget(); /** * Returns the widget for the dock widget. This function returns zero if * the widget has not been set. */ QWidget *widget() const; /** * Returns the tab widget of this dock widget that is shown in the dock * area title bar */ DockWidgetTab *tabWidget() const; /** * Sets, whether the dock widget is movable, closable, and floatable. */ void setFeatures(DockWidgetFeatures features); /** * Sets the feature flag for this dock widget if on is true; otherwise * clears the flag. */ void setFeature(DockWidgetFeature flag, bool on); /** * This property holds whether the dock widget is movable, closable, and * floatable. * By default, this property is set to a combination of DockWidgetClosable, * DockWidgetMovable and DockWidgetFloatable. */ DockWidgetFeatures features() const; /** * Returns the dock manager that manages the dock widget or 0 if the widget * has not been assigned to any dock manager yet */ DockManager *dockManager() const; /** * Returns the dock container widget this dock area widget belongs to or 0 * if this dock widget has not been docked yet */ DockContainerWidget *dockContainer() const; /** * This function return the floating DockContainer if is isFloating() is true * and a nullptr if this dock widget is not floating. */ FloatingDockContainer *floatingDockContainer() const; /** * Returns the dock area widget this dock widget belongs to or 0 * if this dock widget has not been docked yet */ DockAreaWidget *dockAreaWidget() const; /** * Returns the side tab widget for this dock, if this dock widget is in * a auto hide container. If it is not in a auto hide container, then this * function returns a nullptr, */ AutoHideTab *sideTabWidget() const; /** * Assign a side tab widget if this dock widget is an auto hide container */ void setSideTabWidget(AutoHideTab *sideTab) const; /** * Returns true, if this dock widget is in an auto hide container */ bool isAutoHide() const; /** * Returns the auto hide dock container of this dock widget or 0 if there is none. */ AutoHideDockContainer *autoHideDockContainer() const; /** * Returns the auto hide side bar location or SideBarNone if, this is not an autohide dock widget. */ SideBarLocation autoHideLocation() const; /** * This property holds whether the dock widget is floating. * A dock widget is only floating, if it is the one and only widget inside of a floating * container. If there are more than one dock widget in a floating container, the all dock * widgets are docked and not floating. */ bool isFloating() const; /** * This function returns true, if this dock widget is in a floating. * The function returns true, if the dock widget is floating and it also * returns true if it is docked inside of a floating container. */ bool isInFloatingContainer() const; /** * Returns true, if this dock widget is closed. */ bool isClosed() const; /** * Sets the focus property for widget */ void setFocused(bool focused); /** * Returns true if this dock widget is focused. */ bool isFocused() const; /** * Returns a checkable action that can be used to show or close this dock widget. * The action's text is set to the dock widget's window title. */ QAction *toggleViewAction() const; /** * Use provided action to be the default toggle view action for this dock widget. * This dock widget now owns the action. */ void setToggleViewAction(QAction *action); /** * Configures the behavior of the toggle view action. * \see eToggleViewActionMode for a detailed description */ void setToggleViewActionMode(eToggleViewActionMode mode); /** * Configures the minimum size hint that is returned by the * minimumSizeHint() function. * \see eMinimumSizeHintMode for a detailed description */ void setMinimumSizeHintMode(eMinimumSizeHintMode mode); /** * Get the minimum size hint mode configured by setMinimumSizeHintMode */ eMinimumSizeHintMode minimumSizeHintMode() const; /** * Returns true if the dock widget is set as central widget of it's dock manager */ bool isCentralWidget() const; /** * Sets the dock widget icon that is shown in tabs and in toggle view * actions */ void setIcon(const QIcon &icon); /** * Returns the icon that has been assigned to the dock widget */ QIcon icon() const; /** * This function returns the dock widget top tool bar. * If no toolbar is assigned, this function returns nullptr. To get a valid * toolbar you either need to create a default empty toolbar via * createDefaultToolBar() function or you need to assign your custom * toolbar via setToolBar(). */ QToolBar *toolBar() const; /** * If you would like to use the default top tool bar, then call this * function to create the default tool bar. * After this function the toolBar() function will return a valid toolBar() * object. */ QToolBar *createDefaultToolBar(); /** * Assign a new tool bar that is shown above the content widget. * The dock widget will become the owner of the tool bar and deletes it * on destruction */ void setToolBar(QToolBar *toolBar); /** * Configures, if the dock widget uses the global tool bar styles from * dock manager or if it uses its own tool bar style */ void setToolBarStyleSource(eToolBarStyleSource source); /** * Returns the configured tool bar style source */ eToolBarStyleSource toolBarStyleSource() const; /** * This function sets the tool button style for the given dock widget state. * It is possible to switch the tool button style depending on the state. * If a dock widget is floating, then here are more space and it is * possible to select a style that requires more space like * Qt::ToolButtonTextUnderIcon. For the docked state Qt::ToolButtonIconOnly * might be better. */ void setToolBarStyle(Qt::ToolButtonStyle style, eState state); /** * Returns the tool button style for the given docking state. * \see setToolBarStyle() */ Qt::ToolButtonStyle toolBarStyle(eState state) const; /** * This function sets the tool button icon size for the given state. * If a dock widget is floating, there is more space an increasing the * icon size is possible. For docked widgets, small icon sizes, eg. 16 x 16 * might be better. */ void setToolBarIconSize(const QSize &iconSize, eState state); /** * Returns the icon size for a given docking state. * \see setToolBarIconSize() */ QSize toolBarIconSize(eState state) const; /** * Set the actions that will be shown in the dock area title bar * if this dock widget is the active tab. * You should not add to many actions to the title bar, because this * will remove the available space for the tabs. If you have a number * of actions, just add an action with a menu to show a popup menu * button in the title bar. */ void setTitleBarActions(QList actions); /** * Returns a list of actions that will be inserted into the dock area title * bar if this dock widget becomes the current widget */ virtual QList titleBarActions() const; #ifndef QT_NO_TOOLTIP /** * This is function sets text tooltip for title bar widget * and tooltip for toggle view action */ void setTabToolTip(const QString &text); #endif /** * Returns true if the dock widget is floating and if the floating dock * container is full screen */ bool isFullScreen() const; /** * Returns true if this dock widget is in a dock area, that contains at * least 2 opened dock widgets */ bool isTabbed() const; /** * Returns true if this dock widget is the current one in the dock * area widget that contains it. * If the dock widget is the only opened dock widget in a dock area, * the true is returned */ bool isCurrentTab() const; public: // reimplements QFrame /** * Emits titleChanged signal if title change event occurs */ bool event(QEvent *event) override; /** * This property controls whether the dock widget is open or closed. * The toggleViewAction triggers this slot */ void toggleView(bool open = true); /** * Makes this dock widget the current tab in its dock area. * The function only has an effect, if the dock widget is open. A call * to this function will not toggle the view, so if it is closed, * nothing will happen */ void setAsCurrentTab(); /** * Brings the dock widget to the front * This means: * - If the dock widget is tabbed with other dock widgets but its tab is not current, it's made current. * - If the dock widget is floating, QWindow::raise() is called. * This only applies if the dock widget is already open. If closed, does nothing. */ void raise(); /** * This function will make a docked widget floating */ void setFloating(); /** * This function will delete the dock widget and its content from the * docking system */ void deleteDockWidget(); /** * Closes the dock widget */ void closeDockWidget(); /** * Request closing of the dock widget. * For DockWidget with default close handling, the function does the same like clodeDockWidget() * but if the flag CustomCloseHandling is set, the function only emits the closeRequested() signal. */ void requestCloseDockWidget(); /** * Shows the widget in full-screen mode. * Normally this function only affects windows. To make the interface compatible to QDockWidget, * this function also maximizes a floating dock widget. * * \note Full-screen mode works fine under Windows, but has certain problems (doe not work) * under X (Linux). These problems are due to limitations of the ICCCM protocol that specifies * the communication between X11 clients and the window manager. ICCCM simply does not * understand the concept of non-decorated full-screen windows. */ void showFullScreen(); /** * This function complements showFullScreen() to restore the widget after it has been in full * screen mode. */ void showNormal(); /** * Sets the dock widget into auto hide mode if this feature is enabled * via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled) */ void setAutoHide(bool enable, SideBarLocation location = SideBarNone, int tabIndex = -1); /** * Switches the dock widget to auto hide mode or vice versa depending on its current state. */ void toggleAutoHide(SideBarLocation location = SideBarNone); signals: /** * This signal is emitted if the dock widget is opened or closed */ void viewToggled(bool open); /** * This signal is emitted if the dock widget is closed */ void closed(); /** * This signal is emitted if the window title of this dock widget * changed */ void titleChanged(const QString &title); /** * This signal is emitted when the floating property changes. * The topLevel parameter is true if the dock widget is now floating; * otherwise it is false. */ void topLevelChanged(bool topLevel); /** * This signal is emitted, if close is requested */ void closeRequested(); /** * This signal is emitted when the dock widget becomes visible (or invisible). * This happens when the widget is hidden or shown, as well as when it is * docked in a tabbed dock area and its tab becomes selected or unselected. */ void visibilityChanged(bool visible); /** * This signal is emitted when the features property changes. * The features parameter gives the new value of the property. */ void featuresChanged(DockWidgetFeatures features); void focusedChanged(); }; // class DockWidget } // namespace ADS