Skip to content

Commit

Permalink
Add the possibility to open an auto-hide dock on a drag & drop (#667)
Browse files Browse the repository at this point in the history
* Add open auto-hide dock on hover from drag and drop (#663)

* Fix formatting (#663)

* Fix formatting#2 (#663)

* Add AutoHideDragNDrop example
  • Loading branch information
TheBoje authored Nov 19, 2024
1 parent 952131a commit a941c10
Show file tree
Hide file tree
Showing 18 changed files with 498 additions and 17 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if (POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)
Expand Down
Binary file added doc/cfg_flag_AutoHideOpenOnDragHover.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 21 additions & 11 deletions doc/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
- [`AutoHideCloseButtonCollapsesDock`](#autohideclosebuttoncollapsesdock)
- [`AutoHideHasCloseButton`](#autohidehasclosebutton)
- [`AutoHideHasMinimizeButton`](#autohidehasminimizebutton)
- [`AutoHideOpenOnDragHover`](#autohideopenondraghover)
- [DockWidget Feature Flags](#dockwidget-feature-flags)
- [`DockWidgetClosable`](#dockwidgetclosable)
- [`DockWidgetMovable`](#dockwidgetmovable)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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).

Expand All @@ -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.

Expand Down Expand Up @@ -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`:

Expand Down Expand Up @@ -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++
Expand All @@ -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)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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. See `AutoHideDragNDropExample` for more details.
## DockWidget Feature Flags
### `DockWidgetClosable`
Expand Down
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ add_subdirectory(sidebar)
add_subdirectory(deleteonclose)
add_subdirectory(centralwidget)
add_subdirectory(autohide)
add_subdirectory(autohidedragndrop)
add_subdirectory(emptydockarea)
add_subdirectory(dockindock)
add_subdirectory(dockindock)
29 changes: 29 additions & 0 deletions examples/autohidedragndrop/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_autohide_dragndrop VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(AutoHideDragNDropExample WIN32
main.cpp
mainwindow.cpp
mainwindow.ui
droppableitem.cpp
)
target_include_directories(AutoHideDragNDropExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(AutoHideDragNDropExample PRIVATE qt${QT_VERSION_MAJOR}advanceddocking)
target_link_libraries(AutoHideDragNDropExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(AutoHideDragNDropExample PROPERTIES
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "Qt Advanced Docking System Auto Hide With Drag N Drop Example"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)
36 changes: 36 additions & 0 deletions examples/autohidedragndrop/autohidedragndrop.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
ADS_OUT_ROOT = $${OUT_PWD}/../..

QT += core gui widgets

TARGET = AutoHideDragNDropExample
DESTDIR = $${ADS_OUT_ROOT}/lib
TEMPLATE = app
CONFIG += c++14
CONFIG += debug_and_release
adsBuildStatic {
DEFINES += ADS_STATIC
}

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
main.cpp \
mainwindow.cpp \
droppableitem.cpp

HEADERS += \
mainwindow.h
droppableitem.h

FORMS += \
mainwindow.ui

LIBS += -L$${ADS_OUT_ROOT}/lib
include(../../ads.pri)
INCLUDEPATH += ../../src
DEPENDPATH += ../../src

37 changes: 37 additions & 0 deletions examples/autohidedragndrop/droppableitem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "droppableitem.h"

#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDropEvent>
#include <QMimeData>
#include <qsizepolicy.h>

DroppableItem::DroppableItem(const QString& text, QWidget* parent)
: QPushButton(text, parent)
{
setAcceptDrops(true);
setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
}

void DroppableItem::dragEnterEvent(QDragEnterEvent* event)
{
if (event->mimeData()->hasText())
{
event->acceptProposedAction();
setCursor(Qt::DragMoveCursor);
}
}

void DroppableItem::dragLeaveEvent(QDragLeaveEvent* event)
{
unsetCursor();
}

void DroppableItem::dropEvent(QDropEvent* event)
{
if (event->mimeData()->hasText())
{
event->acceptProposedAction();
setText(event->mimeData()->text());
}
}
19 changes: 19 additions & 0 deletions examples/autohidedragndrop/droppableitem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <QObject>
#include <QPushButton>

class QDragEnterEvent;
class QDragLeaveEvent;
class QDropEvent;

class DroppableItem : public QPushButton
{
Q_OBJECT;

public:
DroppableItem(const QString& text = QString(), QWidget* parent = nullptr);

protected:
void dragEnterEvent(QDragEnterEvent* event) override;
void dragLeaveEvent(QDragLeaveEvent* event) override;
void dropEvent(QDropEvent* event) override;
};
10 changes: 10 additions & 0 deletions examples/autohidedragndrop/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <mainwindow.h>
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CMainWindow w;
w.show();
return a.exec();
}
84 changes: 84 additions & 0 deletions examples/autohidedragndrop/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import os
import sys

from PyQt5 import uic
from PyQt5.QtCore import Qt, QTimer, QDir, QSignalBlocker
from PyQt5.QtGui import QCloseEvent, QIcon
from PyQt5.QtWidgets import (QApplication, QLabel, QCalendarWidget, QFrame, QTreeView,
QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar,
QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog)

import PyQtAds as QtAds

UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)

class MainWindow(MainWindowUI, MainWindowBase):

def __init__(self, parent=None):
super().__init__(parent)

self.setupUi(self)

QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.OpaqueSplitterResize, True)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.XmlCompressionEnabled, False)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting, True)
QtAds.CDockManager.setAutoHideConfigFlag(QtAds.CDockManager.AutoHideOpenOnDragHover, True);
self.dock_manager = QtAds.CDockManager(self)

# Set central widget
text_edit = QPlainTextEdit()
text_edit.setPlaceholderText("This is the central editor. Enter your text here.")
central_dock_widget = QtAds.CDockWidget("CentralWidget")
central_dock_widget.setWidget(text_edit)
central_dock_area = self.dock_manager.setCentralWidget(central_dock_widget)
central_dock_area.setAllowedAreas(QtAds.DockWidgetArea.OuterDockAreas)


droppable_item = DroppableItem("Drop text here.")
drop_dock_widget = QtAds.CDockWidget("Tab")
drop_dock_widget.setWidget(droppable_item)
drop_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
drop_dock_widget.setMinimumSize(200, 150)
drop_dock_widget.setAcceptDrops(True)
drop_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, drop_dock_widget)
drop_area.setAcceptDrops(True)
self.menuView.addAction(drop_dock_widget.toggleViewAction())

self.create_perspective_ui()

def create_perspective_ui(self):
save_perspective_action = QAction("Create Perspective", self)
save_perspective_action.triggered.connect(self.save_perspective)
perspective_list_action = QWidgetAction(self)
self.perspective_combobox = QComboBox(self)
self.perspective_combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
self.perspective_combobox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.perspective_combobox.activated[str].connect(self.dock_manager.openPerspective)
perspective_list_action.setDefaultWidget(self.perspective_combobox)
self.toolBar.addSeparator()
self.toolBar.addAction(perspective_list_action)
self.toolBar.addAction(save_perspective_action)

def save_perspective(self):
perspective_name, ok = QInputDialog.getText(self, "Save Perspective", "Enter Unique name:")
if not ok or not perspective_name:
return

self.dock_manager.addPerspective(perspective_name)
blocker = QSignalBlocker(self.perspective_combobox)
self.perspective_combobox.clear()
self.perspective_combobox.addItems(self.dock_manager.perspectiveNames())
self.perspective_combobox.setCurrentText(perspective_name)

def closeEvent(self, event: QCloseEvent):
self.dock_manager.deleteLater()
super().closeEvent(event)


if __name__ == '__main__':
app = QApplication(sys.argv)

w = MainWindow()
w.show()
app.exec_()
Loading

0 comments on commit a941c10

Please sign in to comment.