mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2025-01-12 16:20:25 +08:00
Added suppport for floating widgets with native toolbar to support the windows desktop docking and split system
This commit is contained in:
parent
0716020ab4
commit
a4de5c5560
@ -22,9 +22,13 @@ class CFloatingTitleWidget : public QFrame
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QPoint m_DragStartPosition;
|
QPoint m_DragStartPosition;
|
||||||
|
QPoint m_DragStartMousePosition;
|
||||||
FloatingWidget* floatingWidget() const;
|
FloatingWidget* floatingWidget() const;
|
||||||
MainContainerWidget* mainContainerWidget() const;
|
MainContainerWidget* mainContainerWidget() const;
|
||||||
void moveFloatingWidget(QMouseEvent* ev, MainContainerWidget* MainContainer);
|
void moveFloatingWidget(QMouseEvent* ev);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onMaximizeButtonClicked();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void mousePressEvent(QMouseEvent* ev);
|
virtual void mousePressEvent(QMouseEvent* ev);
|
||||||
@ -46,6 +50,7 @@ class FloatingWidget : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class MainContainerWidget;
|
friend class MainContainerWidget;
|
||||||
|
friend class CFloatingTitleWidget;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FloatingWidget(MainContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent = NULL);
|
FloatingWidget(MainContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent = NULL);
|
||||||
@ -73,6 +78,9 @@ public://private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void changeEvent(QEvent *event) override;
|
virtual void changeEvent(QEvent *event) override;
|
||||||
|
virtual void moveEvent(QMoveEvent *event) override;
|
||||||
|
virtual bool event(QEvent *e);
|
||||||
|
void updateDropOverlays(const QPoint& GlobalPos);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onCloseButtonClicked();
|
void onCloseButtonClicked();
|
||||||
@ -83,8 +91,7 @@ private:
|
|||||||
SectionTitleWidget* _titleWidget;
|
SectionTitleWidget* _titleWidget;
|
||||||
SectionContentWidget* _contentWidget;
|
SectionContentWidget* _contentWidget;
|
||||||
CContainerWidget* m_ContainerWidget;
|
CContainerWidget* m_ContainerWidget;
|
||||||
|
bool m_DraggingActive = false;
|
||||||
//QBoxLayout* _titleLayout;
|
|
||||||
unsigned int m_zOrderIndex = 0;
|
unsigned int m_zOrderIndex = 0;
|
||||||
static unsigned int zOrderCounter;
|
static unsigned int zOrderCounter;
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,8 @@ public:
|
|||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Closeable = 1,
|
Closeable = 1,
|
||||||
AllFlags = Closeable
|
Maximizable = 2,
|
||||||
|
AllFlags = Closeable | Maximizable
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include "ads/SectionTitleWidget.h"
|
#include "ads/SectionTitleWidget.h"
|
||||||
#include "ads/SectionContentWidget.h"
|
#include "ads/SectionContentWidget.h"
|
||||||
@ -31,23 +32,40 @@ CFloatingTitleWidget::CFloatingTitleWidget(SectionContent::Flags Flags, Floating
|
|||||||
Label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
Label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||||
Label->setAlignment(Qt::AlignLeft);
|
Label->setAlignment(Qt::AlignLeft);
|
||||||
Layout->addWidget(Label, 1, Qt::AlignLeft | Qt::AlignVCenter);
|
Layout->addWidget(Label, 1, Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
Layout->setSpacing(0);
|
||||||
setLayout(Layout);
|
setLayout(Layout);
|
||||||
|
|
||||||
|
if (Flags.testFlag(SectionContent::Maximizable))
|
||||||
|
{
|
||||||
|
QPushButton* Button = new QPushButton();
|
||||||
|
Button->setObjectName("maximizeButton");
|
||||||
|
Button->setFlat(true);
|
||||||
|
Button->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
|
||||||
|
Button->setToolTip(tr("Close"));
|
||||||
|
Button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
|
Layout->addWidget(Button);
|
||||||
|
connect(Button, SIGNAL(clicked(bool)), this, SLOT(onMaximizeButtonClicked()));
|
||||||
|
}
|
||||||
|
|
||||||
if (Flags.testFlag(SectionContent::Closeable))
|
if (Flags.testFlag(SectionContent::Closeable))
|
||||||
{
|
{
|
||||||
QPushButton* closeButton = new QPushButton();
|
QPushButton* closeButton = new QPushButton();
|
||||||
closeButton->setObjectName("closeButton");
|
closeButton->setObjectName("closeButton");
|
||||||
closeButton->setFlat(true);
|
closeButton->setFlat(true);
|
||||||
closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
|
closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
|
||||||
closeButton->setToolTip(tr("Close"));
|
closeButton->setToolTip(tr("Maximize"));
|
||||||
closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
Layout->addWidget(closeButton);
|
Layout->addWidget(closeButton);
|
||||||
connect(closeButton, SIGNAL(clicked(bool)), this, SIGNAL(closeButtonClicked()));
|
connect(closeButton, SIGNAL(clicked(bool)), this, SIGNAL(closeButtonClicked()));
|
||||||
Layout->setContentsMargins(6, 0, 0, 0);
|
}
|
||||||
|
|
||||||
|
if (Flags == 0)
|
||||||
|
{
|
||||||
|
Layout->setContentsMargins(6, 6, 6, 6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Layout->setContentsMargins(6, 6, 6, 6);
|
Layout->setContentsMargins(6, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +85,8 @@ void CFloatingTitleWidget::mousePressEvent(QMouseEvent* ev)
|
|||||||
if (ev->button() == Qt::LeftButton)
|
if (ev->button() == Qt::LeftButton)
|
||||||
{
|
{
|
||||||
ev->accept();
|
ev->accept();
|
||||||
//m_DragStartPosition = ev->pos();
|
m_DragStartPosition = floatingWidget()->pos();
|
||||||
|
m_DragStartMousePosition = ev->globalPos();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QFrame::mousePressEvent(ev);
|
QFrame::mousePressEvent(ev);
|
||||||
@ -88,62 +107,37 @@ void CFloatingTitleWidget::mouseMoveEvent(QMouseEvent* ev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint Pos = QCursor::pos();
|
floatingWidget()->updateDropOverlays(ev->globalPos());
|
||||||
// TODO make a member with the main container widget and assign it on
|
ev->accept();
|
||||||
// creation
|
moveFloatingWidget(ev);
|
||||||
MainContainerWidget* MainContainerWidget = mainContainerWidget();
|
|
||||||
auto Containers = MainContainerWidget->m_Containers;
|
|
||||||
CContainerWidget* TopContainer = nullptr;
|
|
||||||
for (auto ContainerWidget : Containers)
|
|
||||||
{
|
|
||||||
if (!ContainerWidget->isVisible())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (floatingWidget()->containerWidget() == ContainerWidget)
|
|
||||||
|
void CFloatingTitleWidget::moveFloatingWidget(QMouseEvent* ev)
|
||||||
{
|
{
|
||||||
continue;
|
const QPoint DragDistance = ev->globalPos() - m_DragStartMousePosition;
|
||||||
|
const QPoint moveToPos = m_DragStartPosition + DragDistance;
|
||||||
|
floatingWidget()->move(moveToPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint MappedPos = ContainerWidget->mapFromGlobal(Pos);
|
|
||||||
if (ContainerWidget->rect().contains(MappedPos))
|
|
||||||
{
|
|
||||||
std::cout << "Container " << ContainerWidget << " contains maousepos" << std::endl;
|
|
||||||
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
|
|
||||||
{
|
|
||||||
TopContainer = ContainerWidget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TopContainer)
|
void CFloatingTitleWidget::onMaximizeButtonClicked()
|
||||||
{
|
{
|
||||||
MainContainerWidget->dropOverlay()->showDropOverlay(TopContainer);
|
if (floatingWidget()->isMaximized())
|
||||||
MainContainerWidget->dropOverlay()->raise();
|
{
|
||||||
|
floatingWidget()->showNormal();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MainContainerWidget->dropOverlay()->hideDropOverlay();
|
floatingWidget()->showMaximized();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ev->accept();
|
|
||||||
moveFloatingWidget(ev, MainContainerWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CFloatingTitleWidget::moveFloatingWidget(QMouseEvent* ev, MainContainerWidget* cw)
|
|
||||||
{
|
|
||||||
const QPoint moveToPos = ev->globalPos() - (m_DragStartPosition + QPoint(ADS_WINDOW_FRAME_BORDER_WIDTH, ADS_WINDOW_FRAME_BORDER_WIDTH));
|
|
||||||
floatingWidget()->move(moveToPos);
|
|
||||||
// cw->moveFloatingWidget(moveToPos);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FloatingWidget::FloatingWidget(MainContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent) :
|
FloatingWidget::FloatingWidget(MainContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent) :
|
||||||
QWidget(parent, Qt::CustomizeWindowHint | Qt::Tool),
|
QWidget(parent, Qt::Window/*Qt::CustomizeWindowHint | Qt::Tool*/),
|
||||||
m_MainContainerWidget(container),
|
m_MainContainerWidget(container),
|
||||||
_content(sc),
|
_content(sc),
|
||||||
_titleWidget(titleWidget),
|
_titleWidget(titleWidget),
|
||||||
@ -155,12 +149,9 @@ FloatingWidget::FloatingWidget(MainContainerWidget* container, SectionContent::R
|
|||||||
setLayout(l);
|
setLayout(l);
|
||||||
|
|
||||||
// Title + Controls
|
// Title + Controls
|
||||||
CFloatingTitleWidget* TitleBar = new CFloatingTitleWidget(sc->flags(), this);
|
/*CFloatingTitleWidget* TitleBar = new CFloatingTitleWidget(sc->flags(), this);
|
||||||
l->insertWidget(0, TitleBar);
|
l->insertWidget(0, TitleBar);
|
||||||
connect(TitleBar, SIGNAL(closeButtonClicked()), this, SLOT(onCloseButtonClicked()));
|
connect(TitleBar, SIGNAL(closeButtonClicked()), this, SLOT(onCloseButtonClicked()));*/
|
||||||
|
|
||||||
//l->addWidget(contentWidget, 1);
|
|
||||||
//contentWidget->show();
|
|
||||||
|
|
||||||
m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this);
|
m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this);
|
||||||
l->addWidget(m_ContainerWidget, 1);
|
l->addWidget(m_ContainerWidget, 1);
|
||||||
@ -236,10 +227,87 @@ void FloatingWidget::changeEvent(QEvent *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FloatingWidget::moveEvent(QMoveEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::moveEvent(event);
|
||||||
|
if (m_DraggingActive)
|
||||||
|
{
|
||||||
|
std::cout << "Dragging" << std::endl;
|
||||||
|
updateDropOverlays(QCursor::pos());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FloatingWidget::event(QEvent *e)
|
||||||
|
{
|
||||||
|
//std::cout << "FloatingWidget::event " << e->type() << std::endl;
|
||||||
|
if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
|
||||||
|
{
|
||||||
|
if (QGuiApplication::mouseButtons() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
m_DraggingActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((e->type() == QEvent::NonClientAreaMouseButtonRelease) && m_DraggingActive)
|
||||||
|
{
|
||||||
|
m_DraggingActive = false;
|
||||||
|
std::cout << "Dropped" << std::endl;
|
||||||
|
}
|
||||||
|
else if (e->type() == QEvent::WindowActivate)
|
||||||
|
{
|
||||||
|
m_DraggingActive = true;
|
||||||
|
std::cout << "QEvent::WindowActivate MouseButtons " << QGuiApplication::mouseButtons() << std::endl;
|
||||||
|
}
|
||||||
|
return QWidget::event(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int FloatingWidget::zOrderIndex() const
|
unsigned int FloatingWidget::zOrderIndex() const
|
||||||
{
|
{
|
||||||
return m_zOrderIndex;
|
return m_zOrderIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FloatingWidget::updateDropOverlays(const QPoint& GlobalPos)
|
||||||
|
{
|
||||||
|
// TODO make a member with the main container widget and assign it on
|
||||||
|
// creation
|
||||||
|
MainContainerWidget* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TopContainer)
|
||||||
|
{
|
||||||
|
MainContainerWidget->dropOverlay()->showDropOverlay(TopContainer);
|
||||||
|
MainContainerWidget->dropOverlay()->raise();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainContainerWidget->dropOverlay()->hideDropOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ADS_NAMESPACE_END
|
ADS_NAMESPACE_END
|
||||||
|
Loading…
Reference in New Issue
Block a user