Added suppport for floating widgets with native toolbar to support the windows desktop docking and split system

This commit is contained in:
Uwe Kindler 2017-02-08 23:03:13 +01:00
parent 0716020ab4
commit a4de5c5560
3 changed files with 135 additions and 59 deletions

View File

@ -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;
}; };

View File

@ -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)

View File

@ -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)
{
continue;
}
QPoint MappedPos = ContainerWidget->mapFromGlobal(Pos); void CFloatingTitleWidget::moveFloatingWidget(QMouseEvent* ev)
if (ContainerWidget->rect().contains(MappedPos)) {
{ const QPoint DragDistance = ev->globalPos() - m_DragStartMousePosition;
std::cout << "Container " << ContainerWidget << " contains maousepos" << std::endl; const QPoint moveToPos = m_DragStartPosition + DragDistance;
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) floatingWidget()->move(moveToPos);
{ }
TopContainer = ContainerWidget;
}
}
}
if (TopContainer)
void CFloatingTitleWidget::onMaximizeButtonClicked()
{
if (floatingWidget()->isMaximized())
{ {
MainContainerWidget->dropOverlay()->showDropOverlay(TopContainer); floatingWidget()->showNormal();
MainContainerWidget->dropOverlay()->raise();
} }
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