mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-25 23:51:33 +08:00
Implemented initial support for floating widgets
This commit is contained in:
parent
b31c5f1f3d
commit
2c9ceb8645
@ -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))
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user