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)
- [`AutoHideHasCloseButton`](#autohidehasclosebutton)
- [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton)
- [`AutoHideOpenOnDragHover`](#autohideopenondraghover)
- [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable)
@ -150,7 +151,7 @@ This ie enabled by default to minimize the size of the saved data.
### `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
application requires `QToolButtons` instead of `QPushButtons` for styling reasons
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`
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
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
@ -197,7 +198,7 @@ CDockManager::setConfigFlag(CDockManager::DragPreviewHasWindowFrame, false);
### `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
flag is enabled (default).
@ -210,7 +211,7 @@ like window without any content.
### `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,
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
(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`
to properly switch the focus on `QEvent::MouseButtonPress`:
@ -422,7 +423,7 @@ bool CMainWindow::eventFilter(QObject *watched, QEvent *event)
### `EqualSplitOnInsertion`
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
```c++
@ -433,7 +434,7 @@ then this is the result, if the flag is disabled:
![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:
![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**
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.
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
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:
![Auo-Hide sort tabs](AutoHide_Sort_Tabs.gif)
@ -632,7 +633,7 @@ the other Auto-Hide flags will be evaluated.
### `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.
![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
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
the auto hide dock (collapsing the dock).
the auto hide dock (collapsing the dock).
![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)
### `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
### `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/>.
******************************************************************************/
//============================================================================
/// \file AutoHideDockContainer.h
/// \author Syarif Fakhri
@ -29,10 +28,10 @@
//============================================================================
// INCLUDES
//============================================================================
#include "ads_globals.h"
#include <QSplitter>
#include "AutoHideTab.h"
#include "ads_globals.h"
QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
@ -52,151 +51,153 @@ struct SideTabBarPrivate;
*/
class ADS_EXPORT CAutoHideDockContainer : public QFrame
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(int sideBarLocation READ sideBarLocation)
private:
AutoHideDockContainerPrivate* d; ///< private data (pimpl)
friend struct AutoHideDockContainerPrivate;
friend CAutoHideSideBar;
friend SideTabBarPrivate;
AutoHideDockContainerPrivate* d; ///< private data (pimpl)
friend struct AutoHideDockContainerPrivate;
friend CAutoHideSideBar;
friend SideTabBarPrivate;
protected:
virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void leaveEvent(QEvent *event) override;
virtual bool event(QEvent* event) override;
virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual void resizeEvent(QResizeEvent* event) override;
virtual void leaveEvent(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
*/
void updateSize();
/**
* Updates the size considering the size limits and the resize margins
*/
void updateSize();
/*
* Saves the state and size
*/
void saveState(QXmlStreamWriter& Stream);
/*
* Saves the state and size
*/
void saveState(QXmlStreamWriter& Stream);
public:
using Super = QFrame;
using Super = QFrame;
/**
* Create Auto Hide widget with the given dock widget
*/
CAutoHideDockContainer(CDockWidget* DockWidget, SideBarLocation area,
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);
* Create Auto Hide widget with the given dock widget
*/
CAutoHideDockContainer(CDockWidget* DockWidget, SideBarLocation area,
CDockContainerWidget* parent);
/**
* Returns the side tab bar area of this Auto Hide dock container
*/
SideBarLocation sideBarLocation() const;
* Virtual Destructor
*/
virtual ~CAutoHideDockContainer();
/**
* 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);
/**
* Gets the side tab bar
*/
CAutoHideSideBar* autoHideSideBar() const;
/**
* Returns the dock area widget of this Auto Hide dock container
*/
CDockAreaWidget* dockAreaWidget() const;
/**
* Returns the side tab
*/
CAutoHideTab* autoHideTab() const;
/**
* Returns the parent container that hosts this auto hide container
*/
CDockContainerWidget* dockContainer() const;
/**
* Gets the dock widget in this dock container
*/
CDockWidget* dockWidget() const;
/**
* Moves the contents to the parent container widget
* Used before removing this Auto Hide dock container
*/
/**
* 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
*/
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();
/**
* Cleanups up the side tab widget and then deletes itself
*/
void cleanupAndDelete();
/**
* Cleanups up the side tab widget and then deletes itself
*/
void cleanupAndDelete();
/*
* Toggles the auto Hide dock container widget
* This will also hide the side tab widget
*/
void toggleView(bool Enable);
/*
* Toggles the auto Hide dock container widget
* This will also hide the side tab widget
*/
void toggleView(bool Enable);
/*
* Collapses the auto hide dock container widget
* Does not hide the side tab widget
*/
void collapseView(bool Enable);
/*
* Collapses the auto hide dock container widget
* Does not hide the side tab widget
*/
void collapseView(bool Enable);
/**
* Toggles the current collapse state
*/
void toggleCollapseState();
/**
* Toggles the current collapse state
*/
void toggleCollapseState();
/**
* Use this instead of resize.
* Depending on the sidebar location this will set the width or height
* of this auto hide container.
*/
void setSize(int Size);
/**
* Use this instead of resize.
* Depending on the sidebar location this will set the width or height
* of this auto hide container.
*/
void setSize(int Size);
/**
* Resets the width or height to the initial dock widget size dependinng on
* the orientation.
* 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
* reset to the initial size
*/
void resetToInitialDockWidgetSize();
/**
* Resets the width or height to the initial dock widget size dependinng on
* the orientation.
* 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
* reset to the initial size
*/
void resetToInitialDockWidgetSize();
/**
* Returns orientation of this container.
* Left and right containers have a Qt::Vertical orientation and top / bottom
* containers have a Qt::Horizontal orientation.
* The function returns the orientation of the corresponding auto hide
* side bar.
*/
Qt::Orientation orientation() const;
/**
* Returns orientation of this container.
* Left and right containers have a Qt::Vertical orientation and top / bottom
* containers have a Qt::Horizontal orientation.
* The function returns the orientation of the corresponding auto hide
* side bar.
*/
Qt::Orientation orientation() const;
/**
* Removes the AutoHide container from the current side bar and adds
* it to the new side bar given in SideBarLocation
*/
void moveToNewSideBarLocation(SideBarLocation SideBarLocation, int TabIndex = -1);
/**
* Removes the AutoHide container from the current side bar and adds
* it to the new side bar given in SideBarLocation
*/
void moveToNewSideBarLocation(SideBarLocation SideBarLocation,
int TabIndex = -1);
};
} // namespace ads
} // namespace ads
//-----------------------------------------------------------------------------
#endif

View File

@ -33,6 +33,8 @@
#include <QApplication>
#include <QElapsedTimer>
#include <QMenu>
#include <qevent.h>
#include <qnamespace.h>
#include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h"
@ -41,6 +43,7 @@
#include "DockWidget.h"
#include "FloatingDragPreview.h"
#include "DockOverlay.h"
#include "ads_globals.h"
namespace ads
{
@ -55,6 +58,7 @@ struct AutoHideTabPrivate
CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress;
QElapsedTimer TimeSinceDragOver;
bool MousePressed = false;
eDragState DragState = DraggingInactive;
QPoint GlobalDragStartMousePosition;
@ -252,6 +256,9 @@ CAutoHideTab::CAutoHideTab(QWidget* parent) :
{
setAttribute(Qt::WA_NoMousePropagation);
setFocusPolicy(Qt::NoFocus);
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
setAcceptDrops(true);
}
}
@ -355,7 +362,6 @@ bool CAutoHideTab::event(QEvent* event)
case QEvent::Leave:
d->forwardEventToDockContainer(event);
break;
default:
break;
}
@ -537,6 +543,37 @@ void CAutoHideTab::mouseMoveEvent(QMouseEvent* 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()

View File

@ -55,7 +55,7 @@ class ADS_EXPORT CAutoHideTab : public CPushButton
Q_PROPERTY(bool activeTab READ isActiveTab)
Q_PROPERTY(bool iconOnly READ iconOnly)
private:
private:
AutoHideTabPrivate* d; ///< private data (pimpl)
friend struct AutoHideTabPrivate;
friend class CDockWidget;
@ -76,6 +76,9 @@ protected:
virtual void mousePressEvent(QMouseEvent* ev) override;
virtual void mouseReleaseEvent(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:
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
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
AutoHideOpenOnDragHover = 0x200, ///< if this flag is set, dragging hover the tab bar will open the dock
DefaultAutoHideConfig = AutoHideFeatureEnabled
| DockAreaHasAutoHideButton