From 0716020ab4a06d1670e0106e019e990fa46cf5e4 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 7 Feb 2017 23:51:29 +0100 Subject: [PATCH] Created CFloatingTitleWidget --- .../include/ads/ContainerWidget.h | 44 ++- .../include/ads/FloatingWidget.h | 33 ++- .../include/ads/MainContainerWidget.h | 16 +- .../include/ads/SectionTitleWidget.h | 2 + .../include/ads/SectionWidget.h | 8 +- AdvancedDockingSystem/src/ContainerWidget.cpp | 260 +++++++++++++++++- AdvancedDockingSystem/src/DropOverlay.cpp | 5 +- AdvancedDockingSystem/src/FloatingWidget.cpp | 169 ++++++++++-- .../src/MainContainerWidget.cpp | 136 ++------- .../src/SectionTitleWidget.cpp | 48 +++- AdvancedDockingSystem/src/SectionWidget.cpp | 33 +-- .../src/icontitlewidget.cpp | 3 +- 12 files changed, 553 insertions(+), 204 deletions(-) diff --git a/AdvancedDockingSystem/include/ads/ContainerWidget.h b/AdvancedDockingSystem/include/ads/ContainerWidget.h index fa1d994..00ddde9 100644 --- a/AdvancedDockingSystem/include/ads/ContainerWidget.h +++ b/AdvancedDockingSystem/include/ads/ContainerWidget.h @@ -24,6 +24,7 @@ namespace ads class SectionWidget; class DropOverlay; class InternalContentData; +class MainContainerWidget; /** * @brief @@ -39,19 +40,54 @@ class CContainerWidget : public QFrame friend class ContainerWidgetPrivate; public: - explicit CContainerWidget(QWidget *parent = nullptr); + explicit CContainerWidget(MainContainerWidget* MainContainerWidget, QWidget *parent = nullptr); virtual ~CContainerWidget(); + void moveFloatingWidget(const QPoint& TargetPos); + /** + * Returns the current zOrderIndex + */ + unsigned int zOrderIndex() const; + + void dropFloatingWidget(FloatingWidget* FloatingWidget, + const QPoint& TargetPos); + + SectionWidget* sectionWidgetAt(const QPoint& pos) const; + + /** + * This function returns true if this container widgets z order index is + * higher than the index of the container widget given in Other parameter + */ + bool isInFrontOf(CContainerWidget* Other) const; + + SectionWidget* dropContent(const InternalContentData& data, SectionWidget* targetSection, DropArea area, bool autoActive = true); + + /*! + * Adds the section-content sc to this container-widget into the section-widget sw. + * If sw is not NULL, the area is used to indicate how the content should be arranged. + * Returns a pointer to the SectionWidget of the added SectionContent. Do not use it for anything else than adding more + * SectionContent elements with this method. + */ + SectionWidget* addSectionContent(const SectionContent::RefPtr& sc, SectionWidget* sw = NULL, DropArea area = CenterDropArea); + protected: + virtual bool event(QEvent *e) override; + SectionWidget* newSectionWidget(); + void addSectionWidget(SectionWidget* section); + SectionWidget* dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append); + SectionWidget* insertNewSectionWidget(const InternalContentData& data, + SectionWidget* targetSection, SectionWidget* ret, Qt::Orientation Orientation, int InsertIndexOffset); + + QList m_Sections; // Layout stuff QGridLayout* m_MainLayout = nullptr; Qt::Orientation m_Orientation = Qt::Horizontal; QPointer m_Splitter; // $mfreiholz: I'd like to remove this variable entirely, // because it changes during user interaction anyway. - // Drop overlay stuff. - QPointer m_SectionDropOverlay; - QPointer m_ContainerDropOverlay; + MainContainerWidget* m_MainContainerWidget = 0; + unsigned int m_zOrderIndex = 0; + static unsigned int zOrderCounter; }; } // namespace ads diff --git a/AdvancedDockingSystem/include/ads/FloatingWidget.h b/AdvancedDockingSystem/include/ads/FloatingWidget.h index 6870c5e..7235b50 100644 --- a/AdvancedDockingSystem/include/ads/FloatingWidget.h +++ b/AdvancedDockingSystem/include/ads/FloatingWidget.h @@ -2,6 +2,7 @@ #define FLOATINGWIDGET_H #include +#include class QBoxLayout; #include "ads/API.h" @@ -13,6 +14,30 @@ class SectionTitleWidget; class SectionContentWidget; class InternalContentData; class SectionWidget; +class CContainerWidget; +class FloatingWidget; + +class CFloatingTitleWidget : public QFrame +{ + Q_OBJECT +private: + QPoint m_DragStartPosition; + FloatingWidget* floatingWidget() const; + MainContainerWidget* mainContainerWidget() const; + void moveFloatingWidget(QMouseEvent* ev, MainContainerWidget* MainContainer); + +protected: + virtual void mousePressEvent(QMouseEvent* ev); + virtual void mouseReleaseEvent(QMouseEvent* ev); + virtual void mouseMoveEvent(QMouseEvent* ev); + +public: + CFloatingTitleWidget(SectionContent::Flags Flags, FloatingWidget* Parent); + +signals: + void closeButtonClicked(); +}; + // FloatingWidget holds and displays SectionContent as a floating window. // It can be resized, moved and dropped back into a SectionWidget. @@ -40,6 +65,9 @@ public: */ unsigned int zOrderIndex() const; + CContainerWidget* containerWidget() const {return m_ContainerWidget;} + MainContainerWidget* mainContainerWidget() const {return m_MainContainerWidget;} + public://private: bool takeContent(InternalContentData& data); @@ -50,12 +78,13 @@ private slots: void onCloseButtonClicked(); private: - MainContainerWidget* _container; + MainContainerWidget* m_MainContainerWidget; SectionContent::RefPtr _content; SectionTitleWidget* _titleWidget; SectionContentWidget* _contentWidget; + CContainerWidget* m_ContainerWidget; - QBoxLayout* _titleLayout; + //QBoxLayout* _titleLayout; unsigned int m_zOrderIndex = 0; static unsigned int zOrderCounter; }; diff --git a/AdvancedDockingSystem/include/ads/MainContainerWidget.h b/AdvancedDockingSystem/include/ads/MainContainerWidget.h index a7d572d..d7c8439 100644 --- a/AdvancedDockingSystem/include/ads/MainContainerWidget.h +++ b/AdvancedDockingSystem/include/ads/MainContainerWidget.h @@ -39,6 +39,7 @@ class ADS_EXPORT_API MainContainerWidget : public CContainerWidget friend class FloatingWidget; friend class SectionTitleWidget; friend class ContainerWidgetPrivate; + friend class CFloatingTitleWidget; public: explicit MainContainerWidget(QWidget *parent = nullptr); @@ -119,6 +120,10 @@ public: */ QPointer sectionDropOverlay() const; + QPointer dropOverlay() const; + + static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget* parent = 0); + /** * Filters the events of the floating widgets */ @@ -128,12 +133,8 @@ private: // // Internal Stuff Begins Here // - - SectionWidget* newSectionWidget(); SectionWidget* dropContent(const InternalContentData& data, SectionWidget* targetSection, DropArea area, bool autoActive = true); - void addSectionWidget(SectionWidget* section); SectionWidget* sectionWidgetAt(const QPoint& pos) const; - SectionWidget* dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append); // Serialization QByteArray saveHierarchy() const; @@ -149,8 +150,6 @@ private: bool takeContent(const SectionContent::RefPtr& sc, InternalContentData& data); FloatingWidget* startFloating(SectionWidget* sectionwidget, int ContentUid, const QPoint& TargetPos); void hideContainerOverlay(); - SectionWidget* insertNewSectionWidget(const InternalContentData& data, - SectionWidget* targetSection, SectionWidget* ret, Qt::Orientation Orientation, int InsertIndexOffset); void moveFloatingWidget(const QPoint& TargetPos); void dropFloatingWidget(FloatingWidget* FloatingWidget, const QPoint& TargetPos); @@ -178,13 +177,16 @@ signals: private: QList m_Sections; QList m_Floatings; + QList m_Containers; QHash m_HiddenSectionContents; - // Helper lookup maps, restricted to this container. QHash m_SectionContentIdMap; QHash m_SectionContentNameMap; QHash m_SectionWidgetIdMap; + + QPointer m_ContainerDropOverlay; + QPointer m_SectionDropOverlay; }; ADS_NAMESPACE_END diff --git a/AdvancedDockingSystem/include/ads/SectionTitleWidget.h b/AdvancedDockingSystem/include/ads/SectionTitleWidget.h index 52f0224..08b7861 100644 --- a/AdvancedDockingSystem/include/ads/SectionTitleWidget.h +++ b/AdvancedDockingSystem/include/ads/SectionTitleWidget.h @@ -8,6 +8,8 @@ #include "ads/API.h" #include "ads/SectionContent.h" +class QPushButton; + ADS_NAMESPACE_BEGIN class MainContainerWidget; class SectionWidget; diff --git a/AdvancedDockingSystem/include/ads/SectionWidget.h b/AdvancedDockingSystem/include/ads/SectionWidget.h index f45c11b..1dc0330 100644 --- a/AdvancedDockingSystem/include/ads/SectionWidget.h +++ b/AdvancedDockingSystem/include/ads/SectionWidget.h @@ -28,14 +28,15 @@ class ADS_EXPORT_API SectionWidget : public QFrame { Q_OBJECT friend class MainContainerWidget; + friend class CContainerWidget; - explicit SectionWidget(MainContainerWidget* parent); + explicit SectionWidget(MainContainerWidget* MainContainer, CContainerWidget* parent); public: virtual ~SectionWidget(); int uid() const; - MainContainerWidget* containerWidget() const; + CContainerWidget* containerWidget() const; QRect titleAreaGeometry() const; QRect contentAreaGeometry() const; @@ -69,7 +70,8 @@ private slots: private: const int _uid; - QPointer _container; + QPointer m_ContainerWidget; + QPointer m_MainContainerWidget; QList _contents; QList _sectionTitles; QList _sectionContents; diff --git a/AdvancedDockingSystem/src/ContainerWidget.cpp b/AdvancedDockingSystem/src/ContainerWidget.cpp index 549ec99..274dc8b 100644 --- a/AdvancedDockingSystem/src/ContainerWidget.cpp +++ b/AdvancedDockingSystem/src/ContainerWidget.cpp @@ -22,24 +22,25 @@ #include #include +#include + #include "ads/Internal.h" #include "ads/SectionWidget.h" #include "ads/SectionTitleWidget.h" #include "ads/SectionContentWidget.h" #include "ads/DropOverlay.h" #include "ads/Serialization.h" +#include "ads/MainContainerWidget.h" namespace ads { -//============================================================================ -CContainerWidget::CContainerWidget(QWidget *parent) - : QFrame(parent) -{ - m_SectionDropOverlay = new DropOverlay(this, DropOverlay::ModeSectionOverlay); - m_ContainerDropOverlay = new DropOverlay(this, DropOverlay::ModeContainerOverlay); - m_ContainerDropOverlay->setAttribute(Qt::WA_TransparentForMouseEvents); - m_ContainerDropOverlay->setWindowFlags(m_ContainerDropOverlay->windowFlags() | Qt::WindowTransparentForInput); +unsigned int CContainerWidget::zOrderCounter = 0; +//============================================================================ +CContainerWidget::CContainerWidget(MainContainerWidget* MainContainer, QWidget *parent) + : QFrame(parent), + m_MainContainerWidget(MainContainer) +{ m_MainLayout = new QGridLayout(); m_MainLayout->setContentsMargins(0, 1, 0, 0); m_MainLayout->setSpacing(0); @@ -50,7 +51,250 @@ CContainerWidget::CContainerWidget(QWidget *parent) //============================================================================ CContainerWidget::~CContainerWidget() { + std::cout << "CContainerWidget::~CContainerWidget()" << std::endl; +} + +bool CContainerWidget::event(QEvent *e) +{ + bool Result = QWidget::event(e); + if (e->type() == QEvent::WindowActivate) + { + m_zOrderIndex = ++zOrderCounter; + } + else if (e->type() == QEvent::Show && !m_zOrderIndex) + { + m_zOrderIndex = ++zOrderCounter; + } + + return Result; +} + + +unsigned int CContainerWidget::zOrderIndex() const +{ + return m_zOrderIndex; +} + +void CContainerWidget::dropFloatingWidget(FloatingWidget* FloatingWidget, + const QPoint& TargetPos) +{ + if (!FloatingWidget->isDraggingActive()) + { + return; + } + + QPoint MousePos = mapFromGlobal(TargetPos); + SectionWidget* sectionWidget = sectionWidgetAt(MousePos); + DropArea dropArea = InvalidDropArea; + if (sectionWidget) + { + //m_SectionDropOverlay->setAllowedAreas(ADS_NS::AllAreas); + //dropArea = m_SectionDropOverlay->showDropOverlay(sectionWidget); + if (dropArea != InvalidDropArea) + { + InternalContentData data; + FloatingWidget->takeContent(data); + FloatingWidget->deleteLater(); + //dropContent(data, sectionWidget, dropArea, true); + } + } + + // mouse is over container + if (InvalidDropArea == dropArea) + { + //dropArea = m_ContainerDropOverlay->dropAreaUnderCursor(); + std::cout << "Cursor location: " << dropArea << std::endl; + if (dropArea != InvalidDropArea) + { + InternalContentData data; + FloatingWidget->takeContent(data); + FloatingWidget->deleteLater(); + //dropContent(data, nullptr, dropArea, true); + } + } +} + + +SectionWidget* CContainerWidget::sectionWidgetAt(const QPoint& pos) const +{ + const QPoint gpos = mapToGlobal(pos); + for (int i = 0; i < m_Sections.size(); ++i) + { + SectionWidget* sw = m_Sections[i]; + if (sw->rect().contains(sw->mapFromGlobal(gpos))) + { + return sw; + } + } + return 0; +} + + +bool CContainerWidget::isInFrontOf(CContainerWidget* Other) const +{ + return this->m_zOrderIndex > Other->m_zOrderIndex; +} + +SectionWidget* CContainerWidget::dropContent(const InternalContentData& data, SectionWidget* targetSectionWidget, DropArea area, bool autoActive) +{ + ADS_Expects(targetSection != NULL); + + SectionWidget* section_widget = nullptr; + + // If no sections exists yet, create a default one and always drop into it. + if (m_Sections.isEmpty()) + { + targetSectionWidget = newSectionWidget(); + addSectionWidget(targetSectionWidget); + area = CenterDropArea; + } + + // Drop on outer area + if (!targetSectionWidget) + { + switch (area) + { + case TopDropArea:return dropContentOuterHelper(m_MainLayout, data, Qt::Vertical, false); + case RightDropArea: return dropContentOuterHelper(m_MainLayout, data, Qt::Horizontal, true); + case CenterDropArea: + case BottomDropArea:return dropContentOuterHelper(m_MainLayout, data, Qt::Vertical, true); + case LeftDropArea: return dropContentOuterHelper(m_MainLayout, data, Qt::Horizontal, false); + default: + return nullptr; + } + return section_widget; + } + + // Drop logic based on area. + switch (area) + { + case TopDropArea:return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Vertical, 0); + case RightDropArea: return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Horizontal, 1); + case BottomDropArea: return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Vertical, 1); + case LeftDropArea: return insertNewSectionWidget(data, targetSectionWidget, section_widget, Qt::Horizontal, 0); + case CenterDropArea: + targetSectionWidget->addContent(data, autoActive); + return targetSectionWidget; + + default: + break; + } + return section_widget; +} + + +SectionWidget* CContainerWidget::newSectionWidget() +{ + SectionWidget* sw = new SectionWidget(m_MainContainerWidget, this); + m_Sections.append(sw); + return sw; +} + +void CContainerWidget::addSectionWidget(SectionWidget* section) +{ + ADS_Expects(section != NULL); + + // Create default splitter. + if (!m_Splitter) + { + m_Splitter = MainContainerWidget::newSplitter(m_Orientation); + m_MainLayout->addWidget(m_Splitter, 0, 0); + } + if (m_Splitter->indexOf(section) != -1) + { + qWarning() << Q_FUNC_INFO << QString("Section has already been added"); + return; + } + m_Splitter->addWidget(section); +} + +SectionWidget* CContainerWidget::dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append) +{ + ADS_Expects(l != NULL); + + SectionWidget* sw = newSectionWidget(); + sw->addContent(data, true); + + QSplitter* oldsp = findImmediateSplitter(this); + if (!oldsp) + { + QSplitter* sp = MainContainerWidget::newSplitter(orientation); + if (l->count() > 0) + { + qWarning() << "Still items in layout. This should never happen."; + QLayoutItem* li = l->takeAt(0); + delete li; + } + l->addWidget(sp); + sp->addWidget(sw); + } + else if (oldsp->orientation() == orientation + || oldsp->count() == 1) + { + oldsp->setOrientation(orientation); + if (append) + oldsp->addWidget(sw); + else + oldsp->insertWidget(0, sw); + } + else + { + QSplitter* sp = MainContainerWidget::newSplitter(orientation); + if (append) + { + QLayoutItem* li = l->replaceWidget(oldsp, sp); + sp->addWidget(oldsp); + sp->addWidget(sw); + delete li; + } + else + { + sp->addWidget(sw); + QLayoutItem* li = l->replaceWidget(oldsp, sp); + sp->addWidget(oldsp); + delete li; + } + } + return sw; +} + +SectionWidget* CContainerWidget::insertNewSectionWidget( + const InternalContentData& data, SectionWidget* targetSection, SectionWidget* ret, + Qt::Orientation Orientation, int InsertIndexOffset) +{ + QSplitter* targetSectionSplitter = findParentSplitter(targetSection); + SectionWidget* sw = newSectionWidget(); + sw->addContent(data, true); + if (targetSectionSplitter->orientation() == Orientation) + { + const int index = targetSectionSplitter->indexOf(targetSection); + targetSectionSplitter->insertWidget(index + InsertIndexOffset, sw); + } + else + { + const int index = targetSectionSplitter->indexOf(targetSection); + QSplitter* s = MainContainerWidget::newSplitter(Orientation); + s->addWidget(sw); + s->addWidget(targetSection); + targetSectionSplitter->insertWidget(index, s); + } + ret = sw; + return ret; +} + +SectionWidget* CContainerWidget::addSectionContent(const SectionContent::RefPtr& sc, SectionWidget* sw, DropArea area) +{ + ADS_Expects(!sc.isNull()); + + // Drop it based on "area" + InternalContentData data; + data.content = sc; + data.titleWidget = new SectionTitleWidget(sc, NULL); + data.contentWidget = new SectionContentWidget(sc, NULL); + + //connect(data.titleWidget, SIGNAL(activeTabChanged()), this, SLOT(onActiveTabChanged())); + return dropContent(data, sw, area, false); } } // namespace ads diff --git a/AdvancedDockingSystem/src/DropOverlay.cpp b/AdvancedDockingSystem/src/DropOverlay.cpp index ea1b2e1..6cfa351 100644 --- a/AdvancedDockingSystem/src/DropOverlay.cpp +++ b/AdvancedDockingSystem/src/DropOverlay.cpp @@ -252,8 +252,9 @@ void DropOverlay::paintEvent(QPaintEvent*) void DropOverlay::showEvent(QShowEvent*) { _cross->show(); - QRect ContainerWidgetRect = parentWidget()->rect(); - QPoint Pos(ContainerWidgetRect.left(), ContainerWidgetRect.center().y()); + QWidget* w = parentWidget() ? parentWidget() : _target.data(); + QRect WidgetRect = w->rect(); + QPoint Pos(WidgetRect.left(), WidgetRect.center().y()); } void DropOverlay::hideEvent(QHideEvent*) diff --git a/AdvancedDockingSystem/src/FloatingWidget.cpp b/AdvancedDockingSystem/src/FloatingWidget.cpp index ccfe52a..dee719f 100644 --- a/AdvancedDockingSystem/src/FloatingWidget.cpp +++ b/AdvancedDockingSystem/src/FloatingWidget.cpp @@ -6,19 +6,145 @@ #include #include #include +#include #include "ads/SectionTitleWidget.h" #include "ads/SectionContentWidget.h" #include "ads/Internal.h" #include "ads/SectionWidget.h" +#include "ads/ContainerWidget.h" + +#include ADS_NAMESPACE_BEGIN unsigned int FloatingWidget::zOrderCounter = 0; + + +CFloatingTitleWidget::CFloatingTitleWidget(SectionContent::Flags Flags, FloatingWidget* Parent) + : QFrame(Parent) +{ + auto Layout = new QHBoxLayout(); + QLabel* Label = new QLabel(this); + Label->setText("Floating Widget"); + Label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + Label->setAlignment(Qt::AlignLeft); + Layout->addWidget(Label, 1, Qt::AlignLeft | Qt::AlignVCenter); + setLayout(Layout); + + if (Flags.testFlag(SectionContent::Closeable)) + { + QPushButton* closeButton = new QPushButton(); + closeButton->setObjectName("closeButton"); + closeButton->setFlat(true); + closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton)); + closeButton->setToolTip(tr("Close")); + closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + Layout->addWidget(closeButton); + connect(closeButton, SIGNAL(clicked(bool)), this, SIGNAL(closeButtonClicked())); + Layout->setContentsMargins(6, 0, 0, 0); + } + else + { + Layout->setContentsMargins(6, 6, 6, 6); + } +} + +FloatingWidget* CFloatingTitleWidget::floatingWidget() const +{ + return dynamic_cast(parentWidget()); +} + +MainContainerWidget* CFloatingTitleWidget::mainContainerWidget() const +{ + return floatingWidget()->mainContainerWidget(); +} + + +void CFloatingTitleWidget::mousePressEvent(QMouseEvent* ev) +{ + if (ev->button() == Qt::LeftButton) + { + ev->accept(); + //m_DragStartPosition = ev->pos(); + return; + } + QFrame::mousePressEvent(ev); +} + + +void CFloatingTitleWidget::mouseReleaseEvent(QMouseEvent* ev) +{ + +} + + +void CFloatingTitleWidget::mouseMoveEvent(QMouseEvent* ev) +{ + if (!(ev->buttons() & Qt::LeftButton)) + { + QFrame::mouseMoveEvent(ev); + return; + } + + QPoint Pos = QCursor::pos(); + // 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 (floatingWidget()->containerWidget() == ContainerWidget) + { + continue; + } + + 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) + { + MainContainerWidget->dropOverlay()->showDropOverlay(TopContainer); + MainContainerWidget->dropOverlay()->raise(); + } + else + { + MainContainerWidget->dropOverlay()->hideDropOverlay(); + } + + 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) : QWidget(parent, Qt::CustomizeWindowHint | Qt::Tool), - _container(container), + m_MainContainerWidget(container), _content(sc), _titleWidget(titleWidget), _contentWidget(contentWidget) @@ -29,24 +155,21 @@ FloatingWidget::FloatingWidget(MainContainerWidget* container, SectionContent::R setLayout(l); // Title + Controls - _titleLayout = new QBoxLayout(QBoxLayout::LeftToRight); - _titleLayout->addWidget(titleWidget, 1); - l->addLayout(_titleLayout, 0); - titleWidget->setActiveTab(false); + CFloatingTitleWidget* TitleBar = new CFloatingTitleWidget(sc->flags(), this); + l->insertWidget(0, TitleBar); + connect(TitleBar, SIGNAL(closeButtonClicked()), this, SLOT(onCloseButtonClicked())); - if (sc->flags().testFlag(SectionContent::Closeable)) - { - QPushButton* closeButton = new QPushButton(); - closeButton->setObjectName("closeButton"); - closeButton->setFlat(true); - closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton)); - closeButton->setToolTip(tr("Close")); - closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - _titleLayout->addWidget(closeButton); - connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked())); - } - l->addWidget(contentWidget, 1); - contentWidget->show(); + //l->addWidget(contentWidget, 1); + //contentWidget->show(); + + m_ContainerWidget = new CContainerWidget(m_MainContainerWidget, this); + l->addWidget(m_ContainerWidget, 1); + InternalContentData data; + data.content = sc; + data.contentWidget = contentWidget; + data.titleWidget = titleWidget; + m_ContainerWidget->dropContent(data, nullptr, CenterDropArea); + m_ContainerWidget->show(); m_zOrderIndex = ++zOrderCounter; } @@ -67,7 +190,7 @@ FloatingWidget::FloatingWidget(SectionWidget* sectionWidget) FloatingWidget::~FloatingWidget() { // maybe we can implement this this via connection to destroyed signal - _container->m_Floatings.removeAll(this); // Note: I don't like this here, but we have to remove it from list... + m_MainContainerWidget->m_Floatings.removeAll(this); // Note: I don't like this here, but we have to remove it from list... } bool FloatingWidget::takeContent(InternalContentData& data) @@ -76,12 +199,12 @@ bool FloatingWidget::takeContent(InternalContentData& data) data.titleWidget = _titleWidget; data.contentWidget = _contentWidget; - _titleLayout->removeWidget(_titleWidget); - _titleWidget->setParent(_container); + //_titleLayout->removeWidget(_titleWidget); + _titleWidget->setParent(m_MainContainerWidget); _titleWidget = NULL; layout()->removeWidget(_contentWidget); - _contentWidget->setParent(_container); + _contentWidget->setParent(m_MainContainerWidget); _contentWidget = NULL; return true; @@ -89,7 +212,7 @@ bool FloatingWidget::takeContent(InternalContentData& data) void FloatingWidget::onCloseButtonClicked() { - _container->hideSectionContent(_content); + m_MainContainerWidget->hideSectionContent(_content); } bool FloatingWidget::isDraggingActive() const diff --git a/AdvancedDockingSystem/src/MainContainerWidget.cpp b/AdvancedDockingSystem/src/MainContainerWidget.cpp index a3675ec..2a0dbb4 100644 --- a/AdvancedDockingSystem/src/MainContainerWidget.cpp +++ b/AdvancedDockingSystem/src/MainContainerWidget.cpp @@ -23,7 +23,7 @@ ADS_NAMESPACE_BEGIN -static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget* parent = 0) +QSplitter* MainContainerWidget::newSplitter(Qt::Orientation orientation, QWidget* parent) { QSplitter* s = new QSplitter(orientation, parent); s->setProperty("ads-splitter", QVariant(true)); @@ -35,9 +35,14 @@ static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWid MainContainerWidget::MainContainerWidget(QWidget *parent) : - CContainerWidget(parent) + CContainerWidget(this, parent) { + m_SectionDropOverlay = new DropOverlay(this, DropOverlay::ModeSectionOverlay); + m_ContainerDropOverlay = new DropOverlay(this, DropOverlay::ModeContainerOverlay); + m_ContainerDropOverlay->setAttribute(Qt::WA_TransparentForMouseEvents); + m_ContainerDropOverlay->setWindowFlags(m_ContainerDropOverlay->windowFlags() | Qt::WindowTransparentForInput); + m_Containers.append(this); } MainContainerWidget::~MainContainerWidget() @@ -420,41 +425,16 @@ QPointer MainContainerWidget::sectionDropOverlay() const return m_SectionDropOverlay; } + +QPointer MainContainerWidget::dropOverlay() const +{ + return m_ContainerDropOverlay; +} + /////////////////////////////////////////////////////////////////////// // PRIVATE API BEGINS HERE /////////////////////////////////////////////////////////////////////// -SectionWidget* MainContainerWidget::newSectionWidget() -{ - SectionWidget* sw = new SectionWidget(this); - m_Sections.append(sw); - return sw; -} - -SectionWidget* MainContainerWidget::insertNewSectionWidget( - const InternalContentData& data, SectionWidget* targetSection, SectionWidget* ret, - Qt::Orientation Orientation, int InsertIndexOffset) -{ - QSplitter* targetSectionSplitter = findParentSplitter(targetSection); - SectionWidget* sw = newSectionWidget(); - sw->addContent(data, true); - if (targetSectionSplitter->orientation() == Orientation) - { - const int index = targetSectionSplitter->indexOf(targetSection); - targetSectionSplitter->insertWidget(index + InsertIndexOffset, sw); - } - else - { - const int index = targetSectionSplitter->indexOf(targetSection); - QSplitter* s = newSplitter(Orientation); - s->addWidget(sw); - s->addWidget(targetSection); - targetSectionSplitter->insertWidget(index, s); - } - ret = sw; - return ret; -} - SectionWidget* MainContainerWidget::dropContent(const InternalContentData& data, SectionWidget* targetSectionWidget, DropArea area, bool autoActive) { ADS_Expects(targetSection != NULL); @@ -502,23 +482,6 @@ SectionWidget* MainContainerWidget::dropContent(const InternalContentData& data, return section_widget; } -void MainContainerWidget::addSectionWidget(SectionWidget* section) -{ - ADS_Expects(section != NULL); - - // Create default splitter. - if (!m_Splitter) - { - m_Splitter = newSplitter(m_Orientation); - m_MainLayout->addWidget(m_Splitter, 0, 0); - } - if (m_Splitter->indexOf(section) != -1) - { - qWarning() << Q_FUNC_INFO << QString("Section has already been added"); - return; - } - m_Splitter->addWidget(section); -} SectionWidget* MainContainerWidget::sectionWidgetAt(const QPoint& pos) const { @@ -534,73 +497,7 @@ SectionWidget* MainContainerWidget::sectionWidgetAt(const QPoint& pos) const return 0; } -SectionWidget* MainContainerWidget::dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append) -{ - ADS_Expects(l != NULL); - SectionWidget* sw = newSectionWidget(); - sw->addContent(data, true); - - QSplitter* oldsp = findImmediateSplitter(this); - if (!oldsp) - { - QSplitter* sp = newSplitter(orientation); - if (l->count() > 0) - { - qWarning() << "Still items in layout. This should never happen."; - QLayoutItem* li = l->takeAt(0); - delete li; - } - l->addWidget(sp); - sp->addWidget(sw); - } - else if (oldsp->orientation() == orientation - || oldsp->count() == 1) - { - oldsp->setOrientation(orientation); - if (append) - oldsp->addWidget(sw); - else - oldsp->insertWidget(0, sw); - } - else - { - QSplitter* sp = newSplitter(orientation); - if (append) - { -#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) - QLayoutItem* li = l->replaceWidget(oldsp, sp); - sp->addWidget(oldsp); - sp->addWidget(sw); - delete li; -#else - int index = l->indexOf(oldsp); - QLayoutItem* li = l->takeAt(index); - l->addWidget(sp); - sp->addWidget(oldsp); - sp->addWidget(sw); - delete li; -#endif - } - else - { -#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) - sp->addWidget(sw); - QLayoutItem* li = l->replaceWidget(oldsp, sp); - sp->addWidget(oldsp); - delete li; -#else - sp->addWidget(sw); - int index = l->indexOf(oldsp); - QLayoutItem* li = l->takeAt(index); - l->addWidget(sp); - sp->addWidget(oldsp); - delete li; -#endif - } - } - return sw; -} QByteArray MainContainerWidget::saveHierarchy() const { @@ -833,7 +730,7 @@ bool MainContainerWidget::restoreHierarchy(const QByteArray& data) if(cnt > 0) { // Create dummy section, required to call hideSectionContent() later. - SectionWidget* sw = new SectionWidget(this); + SectionWidget* sw = new SectionWidget(this, this); sections.append(sw); for (int i = 0; i < cnt; ++i) @@ -927,7 +824,7 @@ bool MainContainerWidget::restoreHierarchy(const QByteArray& data) if (sections.isEmpty()) { - sw = new SectionWidget(this); + sw = new SectionWidget(this, this); sections.append(sw); addSectionWidget(sw); } @@ -1051,7 +948,7 @@ bool MainContainerWidget::restoreSectionWidgets(QDataStream& in, int version, QS int currentIndex, count; in >> currentIndex >> count; - SectionWidget* sw = new SectionWidget(this); + SectionWidget* sw = new SectionWidget(this, this); for (int i = 0; i < count; ++i) { QString uname; @@ -1178,6 +1075,7 @@ FloatingWidget* MainContainerWidget::startFloating(SectionWidget* sectionwidget, FloatingWidget* fw = new FloatingWidget(this, data.content, data.titleWidget, data.contentWidget, this); fw->resize(sectionwidget->size()); m_Floatings.append(fw); + m_Containers.append(fw->containerWidget()); fw->move(TargetPos); fw->show(); fw->setObjectName("FloatingWidget"); diff --git a/AdvancedDockingSystem/src/SectionTitleWidget.cpp b/AdvancedDockingSystem/src/SectionTitleWidget.cpp index 01f1a6f..75b1c91 100644 --- a/AdvancedDockingSystem/src/SectionTitleWidget.cpp +++ b/AdvancedDockingSystem/src/SectionTitleWidget.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef ADS_ANIMATIONS_ENABLED #include @@ -37,9 +38,9 @@ SectionTitleWidget::SectionTitleWidget(SectionContent::RefPtr content, QWidget* l->setSpacing(0); l->addWidget(content->titleWidget()); setLayout(l); - } + SectionTitleWidget::~SectionTitleWidget() { layout()->removeWidget(m_Content->titleWidget()); @@ -118,8 +119,7 @@ void SectionTitleWidget::moveFloatingWidget(QMouseEvent* ev, MainContainerWidget { const QPoint moveToPos = ev->globalPos() - (m_DragStartPosition + QPoint(ADS_WINDOW_FRAME_BORDER_WIDTH, ADS_WINDOW_FRAME_BORDER_WIDTH)); m_FloatingWidget->move(moveToPos); - cw->moveFloatingWidget(moveToPos); - + // cw->moveFloatingWidget(moveToPos); } @@ -156,24 +156,42 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev) } QPoint Pos = QCursor::pos(); - MainContainerWidget* cw = findParentContainerWidget(this); - auto Floatings = cw->m_Floatings; - FloatingWidget* TopWidget = nullptr; - for (auto widget : Floatings) + // TODO make a member with the main container widget and assign it on + // creation + MainContainerWidget* MainContainerWidget = findParentContainerWidget(this); + auto Containers = MainContainerWidget->m_Containers; + CContainerWidget* TopContainer = nullptr; + for (auto ContainerWidget : Containers) { - if ((widget != m_FloatingWidget.data()) && widget->geometry().contains(Pos)) + if (!ContainerWidget->isVisible()) { - if (!TopWidget || widget->zOrderIndex() > TopWidget->zOrderIndex()) + continue; + } + + if (!m_FloatingWidget || (m_FloatingWidget->containerWidget() == ContainerWidget)) + { + continue; + } + + QPoint MappedPos = ContainerWidget->mapFromGlobal(Pos); + if (ContainerWidget->rect().contains(MappedPos)) + { + std::cout << "Container " << ContainerWidget << " contains maousepos" << std::endl; + if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) { - TopWidget = widget; + TopContainer = ContainerWidget; } } } - if (TopWidget) + if (TopContainer) { - std::cout << "TopWidget " << std::hex << (int)TopWidget << std::dec - << " Z: " << TopWidget->zOrderIndex() << std::endl; + MainContainerWidget->dropOverlay()->showDropOverlay(TopContainer); + MainContainerWidget->dropOverlay()->raise(); + } + else + { + MainContainerWidget->dropOverlay()->hideDropOverlay(); } ev->accept(); @@ -181,7 +199,7 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev) // Move already existing FloatingWidget if (isDraggingFloatingWidget()) { - moveFloatingWidget(ev, cw); + moveFloatingWidget(ev, MainContainerWidget); return; } @@ -209,7 +227,7 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev) // Begin to drag/float the SectionContent. if (!sectionwidget->titleAreaGeometry().contains(sectionwidget->mapFromGlobal(ev->globalPos()))) { - startFloating(ev, cw, sectionwidget); + startFloating(ev, MainContainerWidget, sectionwidget); return; } // Begin to drag title inside the title area to switch its position inside the SectionWidget. diff --git a/AdvancedDockingSystem/src/SectionWidget.cpp b/AdvancedDockingSystem/src/SectionWidget.cpp index 1f6c289..216a291 100644 --- a/AdvancedDockingSystem/src/SectionWidget.cpp +++ b/AdvancedDockingSystem/src/SectionWidget.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #if defined(ADS_ANIMATIONS_ENABLED) #include @@ -29,10 +30,11 @@ ADS_NAMESPACE_BEGIN -SectionWidget::SectionWidget(MainContainerWidget* parent) : +SectionWidget::SectionWidget(MainContainerWidget* MainContainer, CContainerWidget* parent) : QFrame(parent), _uid(GetNextUid()), - _container(parent), + m_ContainerWidget(parent), + m_MainContainerWidget(MainContainer), _tabsLayout(NULL), _tabsLayoutInitCount(0), _contentsLayout(NULL), @@ -44,7 +46,6 @@ SectionWidget::SectionWidget(MainContainerWidget* parent) : setLayout(l); /* top area with tabs and close button */ - _topLayout = new QBoxLayout(QBoxLayout::LeftToRight); _topLayout->setContentsMargins(0, 0, 0, 0); _topLayout->setSpacing(0); @@ -93,15 +94,15 @@ SectionWidget::SectionWidget(MainContainerWidget* parent) : _contentsLayout->setSpacing(0); l->addLayout(_contentsLayout, 1); - _container->m_SectionWidgetIdMap.insert(_uid, this); + m_MainContainerWidget->m_SectionWidgetIdMap.insert(_uid, this); } SectionWidget::~SectionWidget() { - if (_container) + if (m_MainContainerWidget) { - _container->m_SectionWidgetIdMap.remove(_uid); - _container->m_Sections.removeAll(this); // Note: I don't like this here, but we have to remove it from list... + m_MainContainerWidget->m_SectionWidgetIdMap.remove(_uid); + m_MainContainerWidget->m_Sections.removeAll(this); // Note: I don't like this here, but we have to remove it from list... } // Delete empty QSplitter. @@ -117,9 +118,9 @@ int SectionWidget::uid() const return _uid; } -MainContainerWidget* SectionWidget::containerWidget() const +CContainerWidget* SectionWidget::containerWidget() const { - return _container; + return m_ContainerWidget; } QRect SectionWidget::titleAreaGeometry() const @@ -139,11 +140,7 @@ void SectionWidget::addContent(const SectionContent::RefPtr& c) SectionTitleWidget* title = new SectionTitleWidget(c, NULL); _sectionTitles.append(title); _tabsLayout->insertWidget(_tabsLayout->count() - _tabsLayoutInitCount, title); -#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - QObject::connect(title, &SectionTitleWidget::clicked, this, &SectionWidget::onSectionTitleClicked); -#else QObject::connect(title, SIGNAL(clicked()), this, SLOT(onSectionTitleClicked())); -#endif SectionContentWidget* content = new SectionContentWidget(c, NULL); _sectionContents.append(content); @@ -168,11 +165,7 @@ void SectionWidget::addContent(const InternalContentData& data, bool autoActivat _sectionTitles.append(data.titleWidget); _tabsLayout->insertWidget(_tabsLayout->count() - _tabsLayoutInitCount, data.titleWidget); data.titleWidget->setVisible(true); -#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - QObject::connect(data.titleWidget, &SectionTitleWidget::clicked, this, &SectionWidget::onSectionTitleClicked); -#else QObject::connect(data.titleWidget, SIGNAL(clicked()), this, SLOT(onSectionTitleClicked())); -#endif // Add content-widget to stack. // Visibility is managed by QStackedWidget. @@ -217,7 +210,7 @@ bool SectionWidget::takeContent(int uid, InternalContentData& data) title->setAttribute(Qt::WA_WState_Created, false); /* fix: floating rubberband #16 */ #endif title->disconnect(this); - title->setParent(_container); + title->setParent(m_MainContainerWidget); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) title->setAttribute(Qt::WA_WState_Created, true); /* fix: floating rubberband #16 */ #endif @@ -229,7 +222,7 @@ bool SectionWidget::takeContent(int uid, InternalContentData& data) { _contentsLayout->removeWidget(content); content->disconnect(this); - content->setParent(_container); + content->setParent(m_MainContainerWidget); } // Select the previous tab as activeTab. @@ -372,7 +365,7 @@ void SectionWidget::onCloseButtonClicked() SectionContent::RefPtr sc = _contents.at(index); if (sc.isNull()) return; - _container->hideSectionContent(sc); + m_MainContainerWidget->hideSectionContent(sc); } void SectionWidget::onTabsMenuActionTriggered(bool) diff --git a/AdvancedDockingSystemDemo/src/icontitlewidget.cpp b/AdvancedDockingSystemDemo/src/icontitlewidget.cpp index 9bf7b45..a2db3af 100644 --- a/AdvancedDockingSystemDemo/src/icontitlewidget.cpp +++ b/AdvancedDockingSystemDemo/src/icontitlewidget.cpp @@ -14,7 +14,8 @@ IconTitleWidget::IconTitleWidget(const QIcon& icon, const QString& title, QWidge setLayout(l); _iconLabel = new QLabel(); - l->addWidget(_iconLabel); + _iconLabel->setAlignment(Qt::AlignVCenter); + l->addWidget(_iconLabel, Qt::AlignVCenter); _titleLabel = new QLabel(); l->addWidget(_titleLabel, 1);