Add open auto-hide dock on hover from drag and drop (#663)

This commit is contained in:
TheBoje 2024-10-04 22:17:42 +02:00
parent 952131a1e9
commit 6ff39bccf8
7 changed files with 585 additions and 552 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

View File

@ -49,6 +49,7 @@
- [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock) - [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock)
- [`AutoHideHasCloseButton`](#autohidehasclosebutton) - [`AutoHideHasCloseButton`](#autohidehasclosebutton)
- [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton) - [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton)
- [`AutoHideOpenOnDragHover`](#autohideopenondraghover)
- [DockWidget Feature Flags](#dockwidget-feature-flags) - [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable) - [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable) - [`DockWidgetMovable`](#dockwidgetmovable)
@ -150,7 +151,7 @@ This ie enabled by default to minimize the size of the saved data.
### `TabCloseButtonIsToolButton` ### `TabCloseButtonIsToolButton`
If enabled the tab close buttons will be `QToolButtons` instead of `QPushButtons` - If enabled the tab close buttons will be `QToolButtons` instead of `QPushButtons` -
disabled by default. Normally the default configuration should be ok but if your disabled by default. Normally the default configuration should be ok but if your
application requires `QToolButtons` instead of `QPushButtons` for styling reasons application requires `QToolButtons` instead of `QPushButtons` for styling reasons
or for any other reasons, then you can enable this flag. or for any other reasons, then you can enable this flag.
@ -181,7 +182,7 @@ constant, that means, if enabled, the tabs need more space.
### `DragPreviewIsDynamic` ### `DragPreviewIsDynamic`
If non-opaque undocking is enabled, this flag defines the behavior of the drag If non-opaque undocking is enabled, this flag defines the behavior of the drag
preview window. If this flag is enabled, then it will give the user the preview window. If this flag is enabled, then it will give the user the
impression, that the floating drag preview is dynamically adjusted to the drop impression, that the floating drag preview is dynamically adjusted to the drop
area. In order to give the perfect impression, you should disable the flags area. In order to give the perfect impression, you should disable the flags
@ -197,7 +198,7 @@ CDockManager::setConfigFlag(CDockManager::DragPreviewHasWindowFrame, false);
### `DragPreviewShowsContentPixmap` ### `DragPreviewShowsContentPixmap`
If non-opaque undocking is enabled, the created drag preview window shows a If non-opaque undocking is enabled, the created drag preview window shows a
copy of the content of the dock widget / dock are that is dragged, if this copy of the content of the dock widget / dock are that is dragged, if this
flag is enabled (default). flag is enabled (default).
@ -210,7 +211,7 @@ like window without any content.
### `DragPreviewHasWindowFrame` ### `DragPreviewHasWindowFrame`
If non-opaque undocking is enabled, then this flag configures if the drag If non-opaque undocking is enabled, then this flag configures if the drag
preview is frameless (default) or looks like a real window. If it is enabled, preview is frameless (default) or looks like a real window. If it is enabled,
then the drag preview is a transparent window with a system window frame. then the drag preview is a transparent window with a system window frame.
@ -378,7 +379,7 @@ ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar
If you have a content widget that does not support focussing for some reason If you have a content widget that does not support focussing for some reason
(like `QVTKOpenGLStereoWidget` from the [VTK library](https://github.com/Kitware/VTK)), (like `QVTKOpenGLStereoWidget` from the [VTK library](https://github.com/Kitware/VTK)),
then you can manually switch the focus by reacting on mouse events. The then you can manually switch the focus by reacting on mouse events. The
following code shows, how to install en event filter on the `QVTKOpenGLStereoWidget` following code shows, how to install en event filter on the `QVTKOpenGLStereoWidget`
to properly switch the focus on `QEvent::MouseButtonPress`: to properly switch the focus on `QEvent::MouseButtonPress`:
@ -422,7 +423,7 @@ bool CMainWindow::eventFilter(QObject *watched, QEvent *event)
### `EqualSplitOnInsertion` ### `EqualSplitOnInsertion`
This flag configures how the space is distributed if a new dock widget is This flag configures how the space is distributed if a new dock widget is
inserted into an existing dock area. The flag is disabled by default. If 3 inserted into an existing dock area. The flag is disabled by default. If 3
dock widgets are inserted with the following code dock widgets are inserted with the following code
```c++ ```c++
@ -433,7 +434,7 @@ then this is the result, if the flag is disabled:
![EqualSplitOnInsertion false](cfg_flag_EqualSplitOnInsertion_false.png) ![EqualSplitOnInsertion false](cfg_flag_EqualSplitOnInsertion_false.png)
If the flag is enabled, then the space is equally distributed to all widgets If the flag is enabled, then the space is equally distributed to all widgets
in a splitter: in a splitter:
![EqualSplitOnInsertion true](cfg_flag_EqualSplitOnInsertion_true.png) ![EqualSplitOnInsertion true](cfg_flag_EqualSplitOnInsertion_true.png)
@ -501,7 +502,7 @@ for active tabs. Inactive tabs only show their icon:
The Advanced Docking System supports "Auto-Hide" functionality for **all** The Advanced Docking System supports "Auto-Hide" functionality for **all**
dock containers. The "Auto Hide" feature allows to display more information dock containers. The "Auto Hide" feature allows to display more information
using less screen space by hiding or showing windows pinned to one of the using less screen space by hiding or showing windows pinned to one of the
four dock container borders. four dock container borders.
Enabling this feature adds a button with a pin icon to each dock area. Enabling this feature adds a button with a pin icon to each dock area.
@ -563,7 +564,7 @@ That means, you can drag them to a different border or sidebar:
### Auto-Hide Tab Sorting ### Auto-Hide Tab Sorting
You can drag Auto-Hide tabs to a new position in the current sidebar You can drag Auto-Hide tabs to a new position in the current sidebar
to sort them: to sort them:
![Auo-Hide sort tabs](AutoHide_Sort_Tabs.gif) ![Auo-Hide sort tabs](AutoHide_Sort_Tabs.gif)
@ -632,7 +633,7 @@ the other Auto-Hide flags will be evaluated.
### `DockAreaHasAutoHideButton` ### `DockAreaHasAutoHideButton`
If this flag is set (default), then each dock area has a pin button in the title If this flag is set (default), then each dock area has a pin button in the title
bar to toggle Auto-Hide state. bar to toggle Auto-Hide state.
![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png) ![DockAreaHasAutoHideButton true](cfg_flag_DockAreaHasAutoHideButton.png)
@ -676,7 +677,7 @@ works if this feature is enabled.
Some users don't understand the distinction between closing an auto hide dock and Some users don't understand the distinction between closing an auto hide dock and
collapsing an auto hide dock. This may lead to situations where they press the collapsing an auto hide dock. This may lead to situations where they press the
close button (losing the side tab widget) instead of simply clicking outside close button (losing the side tab widget) instead of simply clicking outside
the auto hide dock (collapsing the dock). the auto hide dock (collapsing the dock).
![AutoHideCloseButtonCollapsesDock false](cfg_flag_AutoHideCloseButtonCollapsesDock_false.gif) ![AutoHideCloseButtonCollapsesDock false](cfg_flag_AutoHideCloseButtonCollapsesDock_false.gif)
@ -704,6 +705,15 @@ If this flag is set (disabled by default), then each auto hide widget has a mini
![AutoHideHasMinimizeButton](cfg_flag_AutoHideHasMinimizeButton.png) ![AutoHideHasMinimizeButton](cfg_flag_AutoHideHasMinimizeButton.png)
### `AutoHideOpenOnDragHover`
If this flag is set (disabled by default), then holding a dragging cursor hover an auto-hide collapsed dock's tab will open said dock:
![AutoHideOpenOnDragHover](cfg_flag_AutoHideOpenOnDragHover.gif)
Said dock must be set to accept drops to hide when cursor leaves its scope.
## DockWidget Feature Flags ## DockWidget Feature Flags
### `DockWidgetClosable` ### `DockWidgetClosable`

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,6 @@
** License along with this library; If not, see <http://www.gnu.org/licenses/>. ** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/ ******************************************************************************/
//============================================================================ //============================================================================
/// \file AutoHideDockContainer.h /// \file AutoHideDockContainer.h
/// \author Syarif Fakhri /// \author Syarif Fakhri
@ -29,10 +28,10 @@
//============================================================================ //============================================================================
// INCLUDES // INCLUDES
//============================================================================ //============================================================================
#include "ads_globals.h"
#include <QSplitter> #include <QSplitter>
#include "AutoHideTab.h" #include "AutoHideTab.h"
#include "ads_globals.h"
QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter) QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
@ -52,151 +51,153 @@ struct SideTabBarPrivate;
*/ */
class ADS_EXPORT CAutoHideDockContainer : public QFrame class ADS_EXPORT CAutoHideDockContainer : public QFrame
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(int sideBarLocation READ sideBarLocation) Q_PROPERTY(int sideBarLocation READ sideBarLocation)
private: private:
AutoHideDockContainerPrivate* d; ///< private data (pimpl) AutoHideDockContainerPrivate* d; ///< private data (pimpl)
friend struct AutoHideDockContainerPrivate; friend struct AutoHideDockContainerPrivate;
friend CAutoHideSideBar; friend CAutoHideSideBar;
friend SideTabBarPrivate; friend SideTabBarPrivate;
protected: protected:
virtual bool eventFilter(QObject* watched, QEvent* event) override; virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override; virtual void resizeEvent(QResizeEvent* event) override;
virtual void leaveEvent(QEvent *event) override; virtual void leaveEvent(QEvent* event) override;
virtual bool event(QEvent* event) override; virtual bool event(QEvent* event) override;
virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
/** /**
* Updates the size considering the size limits and the resize margins * Updates the size considering the size limits and the resize margins
*/ */
void updateSize(); void updateSize();
/* /*
* Saves the state and size * Saves the state and size
*/ */
void saveState(QXmlStreamWriter& Stream); void saveState(QXmlStreamWriter& Stream);
public: public:
using Super = QFrame; using Super = QFrame;
/** /**
* Create Auto Hide widget with the given dock widget * Create Auto Hide widget with the given dock widget
*/ */
CAutoHideDockContainer(CDockWidget* DockWidget, SideBarLocation area, CAutoHideDockContainer(CDockWidget* DockWidget, SideBarLocation area,
CDockContainerWidget* parent); CDockContainerWidget* parent);
/**
* Virtual Destructor
*/
virtual ~CAutoHideDockContainer();
/**
* Gets the side tab bar
*/
CAutoHideSideBar* autoHideSideBar() const;
/**
* Returns the side tab
*/
CAutoHideTab* autoHideTab() const;
/**
* Gets the dock widget in this dock container
*/
CDockWidget* dockWidget() const;
/**
* Returns the index of this container in the sidebar
*/
int tabIndex() const;
/**
* Adds a dock widget and removes the previous dock widget
*/
void addDockWidget(CDockWidget* DockWidget);
/** /**
* Returns the side tab bar area of this Auto Hide dock container * Virtual Destructor
*/ */
SideBarLocation sideBarLocation() const; virtual ~CAutoHideDockContainer();
/** /**
* Sets a new SideBarLocation. * Gets the side tab bar
* If a new side bar location is set, the auto hide dock container needs */
* to update its resize handle position CAutoHideSideBar* autoHideSideBar() const;
*/
void setSideBarLocation(SideBarLocation SideBarLocation);
/** /**
* Returns the dock area widget of this Auto Hide dock container * Returns the side tab
*/ */
CDockAreaWidget* dockAreaWidget() const; CAutoHideTab* autoHideTab() const;
/** /**
* Returns the parent container that hosts this auto hide container * Gets the dock widget in this dock container
*/ */
CDockContainerWidget* dockContainer() const; CDockWidget* dockWidget() const;
/** /**
* Moves the contents to the parent container widget * Returns the index of this container in the sidebar
* Used before removing this Auto Hide dock container */
*/ int tabIndex() const;
/**
* Adds a dock widget and removes the previous dock widget
*/
void addDockWidget(CDockWidget* DockWidget);
/**
* Returns the side tab bar area of this Auto Hide dock container
*/
SideBarLocation sideBarLocation() const;
/**
* Sets a new SideBarLocation.
* If a new side bar location is set, the auto hide dock container needs
* to update its resize handle position
*/
void setSideBarLocation(SideBarLocation SideBarLocation);
/**
* Returns the dock area widget of this Auto Hide dock container
*/
CDockAreaWidget* dockAreaWidget() const;
/**
* Returns the parent container that hosts this auto hide container
*/
CDockContainerWidget* dockContainer() const;
/**
* Moves the contents to the parent container widget
* Used before removing this Auto Hide dock container
*/
void moveContentsToParent(); void moveContentsToParent();
/** /**
* Cleanups up the side tab widget and then deletes itself * Cleanups up the side tab widget and then deletes itself
*/ */
void cleanupAndDelete(); void cleanupAndDelete();
/* /*
* Toggles the auto Hide dock container widget * Toggles the auto Hide dock container widget
* This will also hide the side tab widget * This will also hide the side tab widget
*/ */
void toggleView(bool Enable); void toggleView(bool Enable);
/* /*
* Collapses the auto hide dock container widget * Collapses the auto hide dock container widget
* Does not hide the side tab widget * Does not hide the side tab widget
*/ */
void collapseView(bool Enable); void collapseView(bool Enable);
/** /**
* Toggles the current collapse state * Toggles the current collapse state
*/ */
void toggleCollapseState(); void toggleCollapseState();
/** /**
* Use this instead of resize. * Use this instead of resize.
* Depending on the sidebar location this will set the width or height * Depending on the sidebar location this will set the width or height
* of this auto hide container. * of this auto hide container.
*/ */
void setSize(int Size); void setSize(int Size);
/** /**
* Resets the width or height to the initial dock widget size dependinng on * Resets the width or height to the initial dock widget size dependinng on
* the orientation. * the orientation.
* If the orientation is Qt::Horizontal, then the height is reset to * If the orientation is Qt::Horizontal, then the height is reset to
* the initial size and if orientation is Qt::Vertical, then the width is * the initial size and if orientation is Qt::Vertical, then the width is
* reset to the initial size * reset to the initial size
*/ */
void resetToInitialDockWidgetSize(); void resetToInitialDockWidgetSize();
/** /**
* Returns orientation of this container. * Returns orientation of this container.
* Left and right containers have a Qt::Vertical orientation and top / bottom * Left and right containers have a Qt::Vertical orientation and top / bottom
* containers have a Qt::Horizontal orientation. * containers have a Qt::Horizontal orientation.
* The function returns the orientation of the corresponding auto hide * The function returns the orientation of the corresponding auto hide
* side bar. * side bar.
*/ */
Qt::Orientation orientation() const; Qt::Orientation orientation() const;
/** /**
* Removes the AutoHide container from the current side bar and adds * Removes the AutoHide container from the current side bar and adds
* it to the new side bar given in SideBarLocation * it to the new side bar given in SideBarLocation
*/ */
void moveToNewSideBarLocation(SideBarLocation SideBarLocation, int TabIndex = -1); void moveToNewSideBarLocation(SideBarLocation SideBarLocation,
int TabIndex = -1);
}; };
} // namespace ads } // namespace ads
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#endif #endif

View File

@ -33,6 +33,8 @@
#include <QApplication> #include <QApplication>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QMenu> #include <QMenu>
#include <qevent.h>
#include <qnamespace.h>
#include "AutoHideDockContainer.h" #include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h" #include "AutoHideSideBar.h"
@ -41,6 +43,7 @@
#include "DockWidget.h" #include "DockWidget.h"
#include "FloatingDragPreview.h" #include "FloatingDragPreview.h"
#include "DockOverlay.h" #include "DockOverlay.h"
#include "ads_globals.h"
namespace ads namespace ads
{ {
@ -55,6 +58,7 @@ struct AutoHideTabPrivate
CAutoHideSideBar* SideBar = nullptr; CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical}; Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress; QElapsedTimer TimeSinceHoverMousePress;
QElapsedTimer TimeSinceDragOver;
bool MousePressed = false; bool MousePressed = false;
eDragState DragState = DraggingInactive; eDragState DragState = DraggingInactive;
QPoint GlobalDragStartMousePosition; QPoint GlobalDragStartMousePosition;
@ -252,6 +256,9 @@ CAutoHideTab::CAutoHideTab(QWidget* parent) :
{ {
setAttribute(Qt::WA_NoMousePropagation); setAttribute(Qt::WA_NoMousePropagation);
setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
setAcceptDrops(true);
}
} }
@ -355,7 +362,6 @@ bool CAutoHideTab::event(QEvent* event)
case QEvent::Leave: case QEvent::Leave:
d->forwardEventToDockContainer(event); d->forwardEventToDockContainer(event);
break; break;
default: default:
break; break;
} }
@ -537,6 +543,37 @@ void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev)
Super::mouseMoveEvent(ev); Super::mouseMoveEvent(ev);
} }
//============================================================================
void CAutoHideTab::dragEnterEvent(QDragEnterEvent* ev) {
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
if (!d->TimeSinceDragOver.isValid()) {
d->TimeSinceDragOver.restart();
ev->accept();
}
else if (d->TimeSinceDragOver.hasExpired(500)) {
ev->accept();
}
}
}
//============================================================================
void CAutoHideTab::dragLeaveEvent(QDragLeaveEvent* ev) {
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
d->TimeSinceDragOver.invalidate();
d->forwardEventToDockContainer(ev);
}
}
//============================================================================
void CAutoHideTab::dragMoveEvent(QDragMoveEvent* ev) {
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)
&& d->TimeSinceDragOver.isValid()
&& d->TimeSinceDragOver.hasExpired(500)) {
d->TimeSinceDragOver.invalidate();
d->DockWidget->autoHideDockContainer()->collapseView(false);
ev->accept();
}
}
//============================================================================ //============================================================================
void CAutoHideTab::requestCloseDockWidget() void CAutoHideTab::requestCloseDockWidget()

View File

@ -55,7 +55,7 @@ class ADS_EXPORT CAutoHideTab : public CPushButton
Q_PROPERTY(bool activeTab READ isActiveTab) Q_PROPERTY(bool activeTab READ isActiveTab)
Q_PROPERTY(bool iconOnly READ iconOnly) Q_PROPERTY(bool iconOnly READ iconOnly)
private: private:
AutoHideTabPrivate* d; ///< private data (pimpl) AutoHideTabPrivate* d; ///< private data (pimpl)
friend struct AutoHideTabPrivate; friend struct AutoHideTabPrivate;
friend class CDockWidget; friend class CDockWidget;
@ -76,6 +76,9 @@ protected:
virtual void mousePressEvent(QMouseEvent* ev) override; virtual void mousePressEvent(QMouseEvent* ev) override;
virtual void mouseReleaseEvent(QMouseEvent* ev) override; virtual void mouseReleaseEvent(QMouseEvent* ev) override;
virtual void mouseMoveEvent(QMouseEvent* ev) override; virtual void mouseMoveEvent(QMouseEvent* ev) override;
virtual void dragEnterEvent(QDragEnterEvent* ev) override;
virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
virtual void dragMoveEvent(QDragMoveEvent* ev) override;
public: public:
using Super = CPushButton; using Super = CPushButton;

View File

@ -254,6 +254,7 @@ public:
AutoHideCloseButtonCollapsesDock = 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely AutoHideCloseButtonCollapsesDock = 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely
AutoHideHasCloseButton = 0x80, //< If the flag is set an auto hide title bar has a close button AutoHideHasCloseButton = 0x80, //< If the flag is set an auto hide title bar has a close button
AutoHideHasMinimizeButton = 0x100, ///< if this flag is set, the auto hide title bar has a minimize button to collapse the dock widget AutoHideHasMinimizeButton = 0x100, ///< if this flag is set, the auto hide title bar has a minimize button to collapse the dock widget
AutoHideOpenOnDragHover = 0x200, ///< if this flag is set, dragging hover the tab bar will open the dock
DefaultAutoHideConfig = AutoHideFeatureEnabled DefaultAutoHideConfig = AutoHideFeatureEnabled
| DockAreaHasAutoHideButton | DockAreaHasAutoHideButton