Implemented initial support for floating widgets

This commit is contained in:
Uwe Kindler 2017-03-01 14:09:56 +01:00
parent b31c5f1f3d
commit 2c9ceb8645
15 changed files with 722 additions and 70 deletions

View File

@ -229,6 +229,26 @@ void FloatingWidget::onCloseButtonClicked()
}
void FloatingWidget::setDraggingActive(bool Active)
{
if (m_DraggingActive == Active)
{
return;
}
m_DraggingActive = Active;
if (Active)
{
std::cout << "FloatingWidget:: InstallEventFilter" << std::endl;
qApp->installEventFilter(this);
}
else
{
std::cout << "FloatingWidget:: RemoveEventFilter" << std::endl;
qApp->removeEventFilter(this);
}
}
void FloatingWidget::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
@ -251,28 +271,6 @@ void FloatingWidget::moveEvent(QMoveEvent *event)
}
}
void FloatingWidget::setDraggingActive(bool Active)
{
if (m_DraggingActive == Active)
{
return;
}
m_DraggingActive = Active;
if (Active)
{
std::cout << "FloatingWidget:: InstallEventFilter" << std::endl;
qApp->installEventFilter(this);
}
else
{
std::cout << "FloatingWidget:: RemoveEventFilter" << std::endl;
qApp->removeEventFilter(this);
}
}
bool FloatingWidget::event(QEvent *e)
{
if ((e->type() == QEvent::NonClientAreaMouseButtonPress))

View File

@ -98,6 +98,7 @@ struct DockAreaWidgetPrivate
QPushButton* TabsMenuButton;
QPushButton* CloseButton;
int TabsLayoutInitCount;
CDockManager* DockManager = nullptr;
/**
* Private data constructor
@ -127,8 +128,11 @@ struct DockAreaWidgetPrivate
/**
* Adds a tabs menu entry for the given dock widget
* If menu is 0, a menu entry is added to the menu of the TabsMenuButton
* member. If menu is a valid menu pointer, the entry will be added to
* the given menu
*/
void addTabsMenuEntry(CDockWidget* DockWidget);
void addTabsMenuEntry(CDockWidget* DockWidget, QMenu* menu = 0);
/**
* Returns the tab action of the given dock widget
@ -145,6 +149,12 @@ struct DockAreaWidgetPrivate
{
return DockWidget->property(INDEX_PROPERTY).toInt();
}
/**
* Update the tabs menu if dock widget order changed or if dock widget has
* been removed
*/
void updateTabsMenu();
};
// struct DockAreaWidgetPrivate
@ -202,19 +212,35 @@ void DockAreaWidgetPrivate::createTabBar()
//============================================================================
void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget)
void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
QMenu* menu)
{
auto Action = TabsMenuButton->menu()->addAction(DockWidget->windowTitle());
menu = menu ? menu : TabsMenuButton->menu();
auto Action = menu->addAction(DockWidget->windowTitle());
QVariant vAction = QVariant::fromValue(Action);
DockWidget->setProperty(ACTION_PROPERTY, vAction);
}
//============================================================================
void DockAreaWidgetPrivate::updateTabsMenu()
{
QMenu* menu = TabsMenuButton->menu();
menu->clear();
for (int i = 0; i < ContentsLayout->count(); ++i)
{
CDockWidget* DockWidget = dockWidgetAt(i);
addTabsMenuEntry(dockWidgetAt(i), menu);
}
}
//============================================================================
CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
QFrame(parent),
d(new DockAreaWidgetPrivate(this))
{
d->DockManager = DockManager;
setStyleSheet("ads--CDockAreaWidget {border: 1px solid white;}");
d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
d->Layout->setContentsMargins(0, 0, 0, 0);
@ -232,12 +258,20 @@ CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget
//============================================================================
CDockAreaWidget::~CDockAreaWidget()
{
std::cout << "~CDockAreaWidget()" << std::endl;
delete d;
}
//============================================================================
CDockContainerWidget* CDockAreaWidget::dockContainerWidget() const
CDockManager* CDockAreaWidget::dockManager() const
{
return d->DockManager;
}
//============================================================================
CDockContainerWidget* CDockAreaWidget::dockContainer() const
{
QWidget* Parent = parentWidget();
while (Parent)
@ -274,6 +308,25 @@ void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
}
//============================================================================
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
{
std::cout << "CDockAreaWidget::removeDockWidget" << std::endl;
d->ContentsLayout->removeWidget(DockWidget);
auto TitleBar = DockWidget->titleBar();
d->TabsLayout->removeWidget(TitleBar);
disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
d->updateTabsMenu();
if (d->ContentsLayout->isEmpty())
{
std::cout << "Dock Area empty" << std::endl;
dockContainer()->removeDockArea(this);
this->deleteLater();
}
}
//============================================================================
void CDockAreaWidget::onDockWidgetTitleClicked()
{

View File

@ -66,11 +66,16 @@ public:
*/
virtual ~CDockAreaWidget();
/**
* Returns the dock manager object this dock area belongs to
*/
CDockManager* dockManager() const;
/**
* Returns the dock container widget this dock area widget belongs to or 0
* if there is no
*/
CDockContainerWidget* dockContainerWidget() const;
CDockContainerWidget* dockContainer() const;
/**
* Add a new dock widget to dock area.
@ -78,6 +83,11 @@ public:
*/
void addDockWidget(CDockWidget* DockWidget);
/**
* Removes the given dock widget from the dock area
*/
void removeDockWidget(CDockWidget* DockWidget);
/**
* Returns the rectangle of the title area
*/

View File

@ -37,6 +37,7 @@
#include "DockManager.h"
#include "DockAreaWidget.h"
#include "DockWidget.h"
#include "ads_globals.h"
#include <iostream>
@ -97,6 +98,11 @@ struct DockContainerWidgetPrivate
*/
CDockAreaWidget* dockWidgetIntoDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* TargetDockArea);
/**
* Add dock area to this container
*/
void addDockArea(CDockAreaWidget* NewDockWidget, DockWidgetArea area = CenterDockWidgetArea);
}; // struct DockContainerWidgetPrivate
@ -114,8 +120,15 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetA
{
CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
NewDockArea->addDockWidget(Dockwidget);
auto InsertParam = internal::dockAreaInsertParameters(area);
addDockArea(NewDockArea, area);
return NewDockArea;
}
//============================================================================
void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockWidgetArea area)
{
auto InsertParam = internal::dockAreaInsertParameters(area);
if (DockAreas.isEmpty())
{
Layout->addWidget(NewDockArea, 0, 0);
@ -156,7 +169,6 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetA
}
DockAreas.append(NewDockArea);
return NewDockArea;
}
@ -173,7 +185,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetAr
CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
NewDockArea->addDockWidget(Dockwidget);
auto InsertParam = internal::dockAreaInsertParameters(area);
QSplitter* TargetAreaSplitter = internal::findParentSplitter(TargetDockArea);
QSplitter* TargetAreaSplitter = internal::findParent<QSplitter*>(TargetDockArea);
int index = TargetAreaSplitter ->indexOf(TargetDockArea);
if (TargetAreaSplitter->orientation() == InsertParam.orientation())
{
@ -219,6 +231,13 @@ CDockContainerWidget::~CDockContainerWidget()
CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget)
{
CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
if (OldDockArea)
{
OldDockArea->removeDockWidget(Dockwidget);
}
Dockwidget->setDockManager(d->DockManager);
if (DockAreaWidget)
{
return d->dockWidgetIntoDockArea(area, Dockwidget, DockAreaWidget);
@ -259,6 +278,49 @@ bool CDockContainerWidget::event(QEvent *e)
return Result;
}
//============================================================================
void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
DockWidgetArea area)
{
CDockContainerWidget* Container = DockAreaWidget->dockContainer();
if (Container && Container != this)
{
Container->removeDockArea(DockAreaWidget);
}
d->addDockArea(DockAreaWidget);
}
//============================================================================
void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
{
d->DockAreas.removeAll(area);
QSplitter* Splitter = internal::findParent<QSplitter*>(area);
area->setParent(0);
if (!(Splitter && Splitter->count() == 1))
{
return;
}
// It the splitter contains only one single widget, then we do not need
// it anymore and can replace it with its content
std::cout << "Replacing splitter with content" << std::endl;
QWidget* widget = Splitter->widget(0);
widget->setParent(this);
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
if (ParentSplitter)
{
internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
}
else
{
d->Layout->replaceWidget(Splitter, widget);
}
delete Splitter;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -78,6 +78,16 @@ public:
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget = nullptr);
/**
* Adds the given dock area to this container widget
*/
void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
/**
* Removes the given dock area from this container
*/
void removeDockArea(CDockAreaWidget* area);
/**
* Returns the current zOrderIndex
*/

View File

@ -31,6 +31,11 @@
#include "DockManager.h"
#include <QMainWindow>
#include <QList>
#include <iostream>
#include "FloatingDockContainer.h"
namespace ads
{
@ -40,6 +45,7 @@ namespace ads
struct DockManagerPrivate
{
CDockManager* _this;
QList<CFloatingDockContainer*> FloatingWidgets;
/**
* Private data constructor
@ -73,6 +79,15 @@ CDockManager::~CDockManager()
{
delete d;
}
//============================================================================
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
{
d->FloatingWidgets.append(FloatingWidget);
std::cout << "d->FloatingWidgets.count() " << d->FloatingWidgets.count()
<< std::endl;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@
namespace ads
{
struct DockManagerPrivate;
class CFloatingDockContainer;
/**
* The central dock manager that maintains the complete docking system
@ -46,10 +47,11 @@ private:
DockManagerPrivate* d; ///< private data (pimpl)
friend class DockManagerPrivate;
protected:
public:
/**
* Default Constructor.
* If the given parent is a QMainWindow, the dck manager sets itself as the
* If the given parent is a QMainWindow, the dock manager sets itself as the
* central widget
*/
CDockManager(QWidget* parent = 0);
@ -58,6 +60,12 @@ public:
* Virtual Destructor
*/
virtual ~CDockManager();
/**
* Registers the given floating widget in the internal list of
* floating widgets
*/
void registerFloatingWidget(CFloatingDockContainer* FloatingWidget);
}; // class DockManager
} // namespace ads
//-----------------------------------------------------------------------------

View File

@ -33,6 +33,9 @@
#include <QBoxLayout>
#include "DockWidgetTitleBar.h"
#include "DockContainerWidget.h"
#include "DockAreaWidget.h"
#include "ads_globals.h"
namespace ads
{
@ -46,6 +49,7 @@ struct DockWidgetPrivate
QWidget* Widget = nullptr;
CDockWidgetTitleBar* TitleWidget;
CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
CDockManager* DockManager = nullptr;
/**
* Private data constructor
@ -125,6 +129,34 @@ CDockWidget::DockWidgetFeatures CDockWidget::features() const
return d->Features;
}
//============================================================================
CDockManager* CDockWidget::dockManager() const
{
return d->DockManager;
}
//============================================================================
void CDockWidget::setDockManager(CDockManager* DockManager)
{
d->DockManager = DockManager;
}
//============================================================================
CDockContainerWidget* CDockWidget::dockContainer() const
{
return internal::findParent<CDockContainerWidget*>(this);
}
//============================================================================
CDockAreaWidget* CDockWidget::dockAreaWidget() const
{
return internal::findParent<CDockAreaWidget*>(this);
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -36,6 +36,9 @@ namespace ads
{
struct DockWidgetPrivate;
class CDockWidgetTitleBar;
class CDockManager;
class CDockContainerWidget;
class CDockAreaWidget;
/**
* The QDockWidget class provides a widget that can be docked inside a
@ -47,7 +50,14 @@ class CDockWidget : public QFrame
private:
DockWidgetPrivate* d; ///< private data (pimpl)
friend class DockWidgetPrivate;
protected:
friend class CDockContainerWidget;
/**
* Assigns the dock manager that manages this dock widget
*/
void setDockManager(CDockManager* DockManager);
public:
enum DockWidgetFeature
{
@ -97,6 +107,24 @@ public:
* 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
*/
CDockManager* dockManager() const;
/**
* Returns the dock container widget this dock area widget belongs to or 0
* if this dock widget has nt been docked yet
*/
CDockContainerWidget* dockContainer() const;
/**
* Returns the dock area widget this dock widget belongs to or 0
* if this dock widget has not been docked yet
*/
CDockAreaWidget* dockAreaWidget() const;
}; // class DockWidget
}
// namespace ads

View File

@ -35,14 +35,29 @@
#include <QMouseEvent>
#include <QStyle>
#include <QApplication>
#include <QSplitter>
#include <iostream>
#include "ads_globals.h"
#include "DockWidget.h"
#include "DockAreaWidget.h"
#include "FloatingDockContainer.h"
namespace ads
{
/**
* The different dragging states
*/
enum eDragState
{
DraggingInactive, //!< DraggingInactive
DraggingMousePressed, //!< DraggingMousePressed
DraggingTab, //!< DraggingTab
DraggingFloatingWidget//!< DraggingFloatingWidget
};
/**
* Private data class of CDockWidgetTitleBar class (pimpl)
*/
@ -54,8 +69,8 @@ struct DockWidgetTitleBarPrivate
QLabel* TitleLabel;
QPoint DragStartMousePosition;
bool IsActiveTab = false;
bool TabMoving = false;
CDockAreaWidget* DockArea = nullptr;
eDragState DragState = DraggingInactive;
/**
* Private data constructor
@ -71,6 +86,29 @@ struct DockWidgetTitleBarPrivate
* Moves the tab depending on the position in the given mouse event
*/
void moveTab(QMouseEvent* ev);
/**
* Test function for current drag state
*/
bool isDraggingState(eDragState dragState)
{
return this->DragState == dragState;
}
/**
* Returns true if the given global point is inside the title area geometry
* rectangle.
* The position is given as global position.
*/
bool titleAreaGeometryContains(const QPoint& GlobalPos) const
{
return DockArea->titleAreaGeometry().contains(DockArea->mapFromGlobal(GlobalPos));
}
/**
* Starts floating of the dock widget that belongs to this title bar
*/
void startFloating(const QPoint& GlobalPos);
};
// struct DockWidgetTitleBarPrivate
@ -114,6 +152,39 @@ void DockWidgetTitleBarPrivate::moveTab(QMouseEvent* ev)
}
//============================================================================
void DockWidgetTitleBarPrivate::startFloating(const QPoint& GlobalPos)
{
std::cout << "startFloating" << std::endl;
DragState = DraggingFloatingWidget;
QSize Size = DockArea->size();
CFloatingDockContainer* FloatingWidget = nullptr;
if (DockArea->count() > 1)
{
// If section widget has multiple tabs, we take only one tab
FloatingWidget = new CFloatingDockContainer(DockWidget);
}
else
{
// If section widget has only one content widget, we can move the complete
// section widget into floating widget
auto splitter = internal::findParent<QSplitter*>(DockArea);
FloatingWidget = new CFloatingDockContainer(DockArea);
}
FloatingWidget->resize(Size);
FloatingWidget->setObjectName("FloatingWidget");
FloatingWidget->startFloating(DragStartMousePosition);
/*
* DropOverlay* ContainerDropOverlay = cw->dropOverlay();
ContainerDropOverlay->setAllowedAreas(OuterAreas);
ContainerDropOverlay->showDropOverlay(this);
ContainerDropOverlay->raise();
*/
}
//============================================================================
CDockWidgetTitleBar::CDockWidgetTitleBar(CDockWidget* DockWidget, QWidget *parent) :
QFrame(parent),
@ -137,6 +208,7 @@ void CDockWidgetTitleBar::mousePressEvent(QMouseEvent* ev)
{
ev->accept();
d->DragStartMousePosition = ev->pos();
d->DragState = DraggingMousePressed;
return;
}
QFrame::mousePressEvent(ev);
@ -148,7 +220,7 @@ void CDockWidgetTitleBar::mousePressEvent(QMouseEvent* ev)
void CDockWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev)
{
// End of tab moving, change order now
if (d->TabMoving && d->DockArea)
if (d->isDraggingState(DraggingTab) && d->DockArea)
{
// Find tab under mouse
QPoint pos = d->DockArea->mapFromGlobal(ev->globalPos());
@ -168,7 +240,7 @@ void CDockWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev)
}
d->DragStartMousePosition = QPoint();
d->TabMoving = false;
d->DragState = DraggingInactive;
//mcw->m_SectionDropOverlay->hideDropOverlay();
//mcw->hideContainerOverlay();
QFrame::mouseReleaseEvent(ev);
@ -178,22 +250,34 @@ void CDockWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev)
//============================================================================
void CDockWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev)
{
if (!(ev->buttons() & Qt::LeftButton))
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
{
d->DragState = DraggingInactive;
QFrame::mouseMoveEvent(ev);
return;
}
if (d->isDraggingState(DraggingFloatingWidget))
{
QFrame::mouseMoveEvent(ev);
return;
}
// move tab
if (d->TabMoving)
if (d->isDraggingState(DraggingTab))
{
d->moveTab(ev);
}
if ((ev->pos() - d->DragStartMousePosition).manhattanLength() >= QApplication::startDragDistance() // Wait a few pixels before start moving
&& d->DockArea->titleAreaGeometry().contains(d->DockArea->mapFromGlobal(ev->globalPos())))
bool MouseInsideTitleArea = d->titleAreaGeometryContains(ev->globalPos());
if (!MouseInsideTitleArea)
{
d->TabMoving = true;
d->startFloating(ev->globalPos());
return;
}
else if ((ev->pos() - d->DragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
{
d->DragState = DraggingTab;
return;
}
@ -239,6 +323,13 @@ void CDockWidgetTitleBar::setDockAreaWidget(CDockAreaWidget* DockArea)
{
d->DockArea = DockArea;
}
//============================================================================
CDockAreaWidget* CDockWidgetTitleBar::dockAreaWidget() const
{
return d->DockArea;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -89,6 +89,13 @@ public:
*/
void setDockAreaWidget(CDockAreaWidget* DockArea);
/**
* Returns the dock area widget this title bar belongs to.
* \return This function returns 0 if the dock widget that owns this title
* bar widget has not been added to any dock area yet.
*/
CDockAreaWidget* dockAreaWidget() const;
signals:
void activeTabChanged();
void clicked();

View File

@ -20,8 +20,8 @@
//============================================================================
/// \file FloatingDockContainer.cpp
/// \author Uwe Kindler
/// \date 23.02.2017
/// \brief Implementation of CFloatingDockContainer
/// \date 01.03.2017
/// \brief Implementation of CFloatingDockContainer class
//============================================================================
@ -30,9 +30,288 @@
//============================================================================
#include "FloatingDockContainer.h"
#include <QBoxLayout>
#include <QApplication>
#include <QMouseEvent>
#include <iostream>
#include "DockContainerWidget.h"
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "DockWidget.h"
namespace ads
{
static unsigned int zOrderCounter = 0;
/**
* Private data class of CFloatingDockContainer class (pimpl)
*/
struct FloatingDockContainerPrivate
{
CFloatingDockContainer* _this;
CDockContainerWidget* DockContainer;
unsigned int zOrderIndex = ++zOrderCounter;
CDockManager* DockManager = nullptr;
bool DraggingActive = false;
QPoint DragStartMousePosition;
/**
* Private data constructor
*/
FloatingDockContainerPrivate(CFloatingDockContainer* _public);
void titleMouseReleaseEvent();
void updateDropOverlays(const QPoint& GlobalPos);
void setDraggingActive(bool Active);
};
// struct FloatingDockContainerPrivate
//============================================================================
FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContainer* _public) :
_this(_public)
{
}
//============================================================================
void FloatingDockContainerPrivate::titleMouseReleaseEvent()
{
setDraggingActive(false);
/*if (!m_DropContainer)
{
return;
}
std::cout << "Dropped" << std::endl;
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
m_DropContainer->dropFloatingWidget(this, QCursor::pos());
MainContainerWidget->dropOverlay()->hideDropOverlay();
MainContainerWidget->sectionDropOverlay()->hideDropOverlay();*/
}
//============================================================================
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
{
/*if (!isVisible())
{
return;
}
CMainContainerWidget* MainContainerWidget = mainContainerWidget();
auto Containers = MainContainerWidget->m_Containers;
CContainerWidget* TopContainer = nullptr;
for (auto ContainerWidget : Containers)
{
if (!ContainerWidget->isVisible())
{
continue;
}
if (containerWidget() == ContainerWidget)
{
continue;
}
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
if (ContainerWidget->rect().contains(MappedPos))
{
std::cout << "Container " << ContainerWidget << " contains mousepos" << std::endl;
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
{
TopContainer = ContainerWidget;
}
}
}
m_DropContainer = TopContainer;
DropOverlay* ContainerDropOverlay = MainContainerWidget->dropOverlay();
DropOverlay* SectionDropOverlay = MainContainerWidget->sectionDropOverlay();
if (!TopContainer)
{
ContainerDropOverlay->hideDropOverlay();
SectionDropOverlay->hideDropOverlay();
return;
}
ContainerDropOverlay->showDropOverlay(TopContainer);
ContainerDropOverlay->raise();
SectionWidget* sectionwidget = TopContainer->sectionWidgetAt(GlobalPos);
if (sectionwidget)
{
SectionDropOverlay->setAllowedAreas(AllAreas);
SectionDropOverlay->showDropOverlay(sectionwidget);
}
else
{
SectionDropOverlay->hideDropOverlay();
}
if (TopContainer)
{
ContainerDropOverlay->showDropOverlay(TopContainer);
ContainerDropOverlay->raise();
}
else
{
ContainerDropOverlay->hideDropOverlay();
}*/
}
//============================================================================
void FloatingDockContainerPrivate::setDraggingActive(bool Active)
{
if (DraggingActive == Active)
{
return;
}
DraggingActive = Active;
if (Active)
{
std::cout << "FloatingWidget:: InstallEventFilter" << std::endl;
qApp->installEventFilter(_this);
}
else
{
std::cout << "FloatingWidget:: RemoveEventFilter" << std::endl;
qApp->removeEventFilter(_this);
}
}
//============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
QWidget(DockManager, Qt::Window),
d(new FloatingDockContainerPrivate(this))
{
d->DockManager = DockManager;
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
setLayout(l);
d->DockContainer = new CDockContainerWidget(DockManager, this);
l->addWidget(d->DockContainer);
DockManager->registerFloatingWidget(this);
}
//============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) :
CFloatingDockContainer(DockArea->dockManager())
{
d->DockContainer->addDockArea(DockArea);
}
//============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
CFloatingDockContainer(DockWidget->dockManager())
{
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
}
//============================================================================
CFloatingDockContainer::~CFloatingDockContainer()
{
delete d;
}
//============================================================================
CDockContainerWidget* CFloatingDockContainer::dockContainer() const
{
return d->DockContainer;
}
//============================================================================
void CFloatingDockContainer::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
{
std::cout << "FloatingWidget::changeEvent QEvent::ActivationChange " << std::endl;
d->zOrderIndex = ++zOrderCounter;
return;
}
}
//============================================================================
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
{
QWidget::moveEvent(event);
if (d->DraggingActive && qApp->mouseButtons().testFlag(Qt::LeftButton))
{
//updateDropOverlays(QCursor::pos());
}
}
//============================================================================
bool CFloatingDockContainer::event(QEvent *e)
{
if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
{
if (QGuiApplication::mouseButtons() == Qt::LeftButton)
{
std::cout << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type() << std::endl;
d->setDraggingActive(true);
}
}
else if (e->type() == QEvent::NonClientAreaMouseButtonDblClick)
{
std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick" << std::endl;
d->setDraggingActive(false);
}
else if ((e->type() == QEvent::NonClientAreaMouseButtonRelease) && d->DraggingActive)
{
std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease" << std::endl;
d->titleMouseReleaseEvent();
}
return QWidget::event(e);
}
//============================================================================
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::MouseButtonRelease)
{
std::cout << "FloatingWidget::eventFilter QEvent::MouseButtonRelease" << std::endl;
d->titleMouseReleaseEvent();
}
else if ((event->type() == QEvent::MouseMove) && d->DraggingActive)
{
QMouseEvent* MouseEvent = dynamic_cast<QMouseEvent*>(event);
int BorderSize = (frameSize().width() - size().width()) / 2;
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0);
move(moveToPos);
return true;
}
return false;
}
//============================================================================
void CFloatingDockContainer::startFloating(const QPoint& Pos)
{
d->setDraggingActive(true);
QPoint TargetPos = QCursor::pos() - Pos;
move(TargetPos);
show();
d->DragStartMousePosition = Pos;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@ -22,25 +22,73 @@
//============================================================================
/// \file FloatingDockContainer.h
/// \author Uwe Kindler
/// \date 23.02.2017
/// \brief Declaration of CFloatingDockContainer
/// \date 01.03.2017
/// \brief Declaration of CFloatingDockContainer class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <QWidget>
namespace ads
{
struct FloatingDockContainerPrivate;
class CDockAreaWidget;
class CDockContainerWidget;
class CDockWidget;
class CDockManager;
/**
* @brief
* This implements a floating widget that is a dock container that accepts
* docking of dock widgets like the main window and that can be docked into
* another dock container
*/
class CFloatingDockContainer
class CFloatingDockContainer : public QWidget
{
};
Q_OBJECT
private:
FloatingDockContainerPrivate* d; ///< private data (pimpl)
friend class FloatingDockContainerPrivate;
protected:
/**
* Private constructor that is called from public constructors
*/
CFloatingDockContainer(CDockManager* DockManager);
} // namespace ads
protected: // reimplements QWidget
virtual void changeEvent(QEvent *event) override;
virtual void moveEvent(QMoveEvent *event) override;
virtual bool event(QEvent *e) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
//---------------------------------------------------------------------------
public:
/**
* Create floating widget with the given dock area
*/
CFloatingDockContainer(CDockAreaWidget* DockArea);
/**
* Create floating widget with the given dock widget
*/
CFloatingDockContainer(CDockWidget* DockWidget);
/**
* Virtual Destructor
*/
virtual ~CFloatingDockContainer();
/**
* Access function for the internal dock container
*/
CDockContainerWidget* dockContainer() const;
/**
* Starts floating at the given global position
*/
void startFloating(const QPoint& Pos);
}; // class FloatingDockContainer
}
// namespace ads
//-----------------------------------------------------------------------------
#endif // FloatingDockContainerH

View File

@ -48,6 +48,14 @@ QSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent)
return s;
}
//============================================================================
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To)
{
int index = Splitter->indexOf(From);
From->setParent(0);
Splitter->insertWidget(index, To);
}
//============================================================================
CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area)
{
@ -64,24 +72,6 @@ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area)
return CDockInsertParam(Qt::Vertical, false);
}
//============================================================================
QSplitter* findParentSplitter(QWidget* w)
{
QWidget* parentWidget = w;
do
{
QSplitter* splitter = dynamic_cast<QSplitter*>(parentWidget);
if (splitter)
{
return splitter;
}
parentWidget = parentWidget->parentWidget();
}
while (parentWidget);
return 0;
}
} // namespace internal
} // namespace ads

View File

@ -57,6 +57,11 @@ namespace internal
*/
QSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = 0);
/**
* Replace the from widget in the given splitter with the To widget
*/
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To);
/**
* Convenience class for QPair to provide better naming than first and
* second
@ -76,10 +81,26 @@ public:
CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area);
/**
* Returns the parent splitter of the given widget or 0 if the widget is not
* child of any splitter
* Searches for the parent widget of the given type.
* Returns the parent widget of the given widget or 0 if the widget is not
* child of any widget of type T
*/
QSplitter* findParentSplitter(QWidget* w);
template <class T>
T findParent(const QWidget* w)
{
QWidget* parentWidget = w->parentWidget();
while (parentWidget)
{
T ParentImpl = dynamic_cast<T>(parentWidget);
if (ParentImpl)
{
return ParentImpl;
}
parentWidget = parentWidget->parentWidget();
}
return 0;
}
} // namespace internal
} // namespace ads