17#include <QApplication>
23class DockFloatingPreviewPrivate
28 DockFloatingPreviewPrivate();
30 void updateDropOverlays(
const QPoint &globalPos);
31 void setHidden(
bool Value);
33 void cancelDragging();
34 void createFloatingWidget();
35 bool isContentFloatable()
const;
36 bool isContentPinnable()
const;
38 DockWidget::DockWidgetFeatures contentFeatures()
const;
40 QWidget *m_content =
nullptr;
41 DockPanel *m_contentSourcePanel =
nullptr;
42 QPoint m_dragStartMousePosition;
43 DockWindow *m_window =
nullptr;
44 DockContainer *m_dropContainer =
nullptr;
45 DockWidget::DockWidgetFeatures m_contentFeatures;
46 QPixmap m_contentPreviewPixmap;
47 bool m_canceled =
false;
48 bool m_hidden =
false;
51DockFloatingPreviewPrivate::DockFloatingPreviewPrivate()
55void DockFloatingPreviewPrivate::updateDropOverlays(
const QPoint &globalPos)
57 Q_Q(DockFloatingPreview);
58 if (!q->isVisible() || !m_window) {
62 auto containers = m_window->dockContainers();
63 DockContainer *topContainer =
nullptr;
64 for (
auto container : containers) {
65 if (!container->isVisible()) {
69 QPoint mappedPos = container->mapFromGlobal(globalPos);
70 if (container->rect().contains(mappedPos)) {
71 if (!topContainer || container->isInFrontOf(topContainer)) {
72 topContainer = container;
77 m_dropContainer = topContainer;
78 auto containerOverlay = m_window->containerOverlay();
79 auto panelOverlay = m_window->panelOverlay();
82 containerOverlay->hideOverlay();
83 panelOverlay->hideOverlay();
84 if (DockManager::testConfigFlag(DockManager::DragPreviewIsDynamic)) {
90 auto panelDropArea = panelOverlay->dropAreaUnderCursor();
91 auto containerDropArea = containerOverlay->dropAreaUnderCursor();
93 int visibleDockpanels = topContainer->visibleDockPanelCount();
96 auto panel = qobject_cast<DockPanel *>(m_content);
97 if (panel && panel->isAutoHide()) {
102 auto topPanel = topContainer->dockPanelAt(globalPos);
106 if (visibleDockpanels == 1 && topPanel) {
111 if (isContentPinnable()) {
115 containerOverlay->setAllowedAreas(allowedContainerAreas);
117 if (topPanel && topPanel->isVisible() && visibleDockpanels >= 0 && topPanel != m_contentSourcePanel) {
118 panelOverlay->enableDropPreview(
true);
119 panelOverlay->setAllowedAreas((visibleDockpanels == 1) ?
Qx::NoDockWidgetArea : topPanel->allowedAreas());
127 panelOverlay->enableDropPreview(
false);
128 containerOverlay->enableDropPreview(
true);
132 containerOverlay->showOverlay(topContainer);
134 panelOverlay->hideOverlay();
139 if (visibleDockpanels == 1) {
142 containerOverlay->showOverlay(topContainer);
145 m_dropContainer =
nullptr;
149 if (DockManager::testConfigFlag(DockManager::DragPreviewIsDynamic)) {
154void DockFloatingPreviewPrivate::setHidden(
bool Value)
156 Q_Q(DockFloatingPreview);
161void DockFloatingPreviewPrivate::cancelDragging()
163 Q_Q(DockFloatingPreview);
165 Q_EMIT q->draggingCanceled();
166 m_window->containerOverlay()->hideOverlay();
167 m_window->panelOverlay()->hideOverlay();
171void DockFloatingPreviewPrivate::createFloatingWidget()
173 Q_Q(DockFloatingPreview);
174 DockWidget *widget = qobject_cast<DockWidget *>(m_content);
175 DockPanel *panel = qobject_cast<DockPanel *>(m_content);
177 DockFloatingContainer *floatingWidget =
nullptr;
179 if (widget && widget->features().testFlag(DockWidget::DockWidgetFloatable)) {
180 floatingWidget =
new DockFloatingContainer(widget);
181 }
else if (panel && panel->features().testFlag(DockWidget::DockWidgetFloatable)) {
182 floatingWidget =
new DockFloatingContainer(panel);
185 if (floatingWidget) {
186 floatingWidget->setGeometry(q->geometry());
187 floatingWidget->show();
188 if (!DockManager::testConfigFlag(DockManager::DragPreviewHasWindowFrame)) {
189 QApplication::processEvents();
190 int FrameHeight = floatingWidget->frameGeometry().height() - floatingWidget->geometry().height();
191 QRect FixedGeometry = q->geometry();
192 FixedGeometry.adjust(0, FrameHeight, 0, 0);
193 floatingWidget->setGeometry(FixedGeometry);
198bool DockFloatingPreviewPrivate::isContentFloatable()
const
200 return m_contentFeatures.testFlag(DockWidget::DockWidgetFloatable);
203bool DockFloatingPreviewPrivate::isContentPinnable()
const
205 return m_contentFeatures.testFlag(DockWidget::DockWidgetPinnable);
208DockWidget::DockWidgetFeatures DockFloatingPreviewPrivate::contentFeatures()
const
210 DockWidget *widget = qobject_cast<DockWidget *>(m_content);
212 return widget->features();
214 DockPanel *panel = qobject_cast<DockPanel *>(m_content);
216 return panel->features();
219 return DockWidget::DockWidgetFeatures();
222DockFloatingPreview::DockFloatingPreview(
DockPanel *content)
227 d->m_contentSourcePanel = content;
237 d->m_contentSourcePanel = content->
dockPanel();
239 setWindowTitle(content->windowTitle());
251 d->m_content = content;
252 d->m_contentFeatures = d->contentFeatures();
254 setAttribute(Qt::WA_DeleteOnClose);
256 setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
258 setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
259 setAttribute(Qt::WA_NoSystemBackground);
260 setAttribute(Qt::WA_TranslucentBackground);
264 auto flags = windowFlags();
265 flags |= Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint;
266 setWindowFlags(flags);
273 d->m_contentPreviewPixmap = QPixmap(content->size());
274 content->render(&d->m_contentPreviewPixmap);
277 connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
282 qApp->installEventFilter(
this);
291 QWidget *mouseEventHandler)
293 Q_UNUSED(mouseEventHandler)
297 d->m_dragStartMousePosition = dragStartMousePos;
305 auto panelDropArea = d->m_window->panelOverlay()->visibleDropAreaUnderCursor();
306 auto containerDropArea = d->m_window->containerOverlay()->visibleDropAreaUnderCursor();
313 if (validDropArea || d->isContentFloatable()) {
317 if (!d->m_dropContainer) {
318 d->createFloatingWidget();
320 d->m_dropContainer->dropWidget(d->m_content, panelDropArea, d->m_dropContainer->dockPanelAt(QCursor::pos()),
321 d->m_window->panelOverlay()->tabIndexUnderCursor());
327 dropPanel = d->m_dropContainer->dockPanelAt(QCursor::pos());
330 d->m_dropContainer->dropWidget(d->m_content, containerDropArea, dropPanel,
331 d->m_window->containerOverlay()->tabIndexUnderCursor());
333 d->createFloatingWidget();
337 d->m_window->containerOverlay()->hideOverlay();
338 d->m_window->panelOverlay()->hideOverlay();
344 int borderSize = (frameSize().width() - size().width()) / 2;
345 const QPoint moveToPos = QCursor::pos() - d->m_dragStartMousePosition - QPoint(borderSize, 0);
347 d->updateDropOverlays(QCursor::pos());
353 auto droppedDockWidget = qobject_cast<DockWidget *>(d->m_content);
354 auto droppedPanel = qobject_cast<DockPanel *>(d->m_content);
355 auto autoHideContainer =
356 droppedDockWidget ? droppedDockWidget->autoHideContainer() : droppedPanel->autoHideContainer();
358 if (!autoHideContainer) {
365 if (
internal::isSideBarArea(containerDropArea) && (d->m_dropContainer == autoHideContainer->dockContainer())) {
369 autoHideContainer->cleanupAndDelete();
378 if (state != Qt::ApplicationActive) {
379 disconnect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
this,
389 if (!d->m_canceled && event->type() == QEvent::KeyPress) {
390 QKeyEvent *e =
static_cast<QKeyEvent *
>(event);
391 if (e->key() == Qt::Key_Escape) {
392 watched->removeEventFilter(
this);
408 QPainter painter(
this);
409 painter.setOpacity(0.6);
411 painter.drawPixmap(QPoint(0, 0), d->m_contentPreviewPixmap);
417 QColor color = palette().color(QPalette::Active, QPalette::Highlight);
418 QPen pen = painter.pen();
419 pen.setColor(color.darker(120));
420 pen.setStyle(Qt::SolidLine);
422 pen.setCosmetic(
true);
424 color = color.lighter(130);
426 painter.setBrush(color);
427 painter.drawRect(rect().adjusted(0, 0, -1, -1));
A floating overlay is a temporary floating widget that is just used to indicate the floating widget m...
virtual ~DockFloatingPreview()
virtual bool eventFilter(QObject *watched, QEvent *event) override
virtual void finishDragging() override
Tells the widget that to finish dragging if the mouse is released.
void moveFloating() override
Moves the widget to a new position relative to the position given when startFloating() was called.
virtual void paintEvent(QPaintEvent *e) override
void onApplicationStateChanged(Qt::ApplicationState state)
Cancel non opaque undocking if application becomes inactive
virtual void startFloating(const QPoint &dragStartMousePos, const QSize &size, Qx::DockDragState dragState, QWidget *mouseEventHandler) override
Starts floating.
void cleanupAutoHideContainerWidget(Qx::DockWidgetArea containerDropArea)
DockFloatingPreview(DockPanel *content)
@ DragPreviewHasWindowFrame
@ DragPreviewShowsContentPixmap
static bool testConfigFlag(ConfigFlag flag)
DockPanel manages multiple instances of DockWidgets.
DockWidget * currentDockWidget() const
DockWindow * dockWindow() const
int openDockWidgetsCount() const
bool isSideBarArea(Qx::DockWidgetArea area)
#define QX_INIT_PRIVATE(Class)
#define QX_DECLARE_PUBLIC(Class)
#define QX_FINI_PRIVATE()
#define QX_DOCK_END_NAMESPACE
#define QX_DOCK_BEGIN_NAMESPACE