diff --git a/AdvancedDockingSystem/src/ads/ads.cpp b/AdvancedDockingSystem/src/ads/ads.cpp index 81410af..bdaa793 100644 --- a/AdvancedDockingSystem/src/ads/ads.cpp +++ b/AdvancedDockingSystem/src/ads/ads.cpp @@ -57,4 +57,21 @@ QSplitter* findParentSplitter(class QWidget* w) return cw; } +QSplitter* findImmediateSplitter(class QWidget* w) +{ + QSplitter* sp = NULL; + QLayout* l = w->layout(); + if (!l || l->count() <= 0) + return sp; + for (int i = 0; i < l->count(); ++i) + { + QLayoutItem* li = l->itemAt(0); + if (!li->widget()) + continue; + if ((sp = dynamic_cast(li->widget())) != NULL) + break; + } + return sp; +} + ADS_NAMESPACE_END \ No newline at end of file diff --git a/AdvancedDockingSystem/src/ads/ads.h b/AdvancedDockingSystem/src/ads/ads.h index bfa4eb1..3f3fa04 100644 --- a/AdvancedDockingSystem/src/ads/ads.h +++ b/AdvancedDockingSystem/src/ads/ads.h @@ -79,6 +79,7 @@ public: class ContainerWidget* findParentContainerWidget(class QWidget* w); class SectionWidget* findParentSectionWidget(class QWidget* w); QSplitter* findParentSplitter(class QWidget* w); +QSplitter* findImmediateSplitter(class QWidget* w); ADS_NAMESPACE_END diff --git a/AdvancedDockingSystem/src/ads/container_widget.cpp b/AdvancedDockingSystem/src/ads/container_widget.cpp index d51ed0c..e10b6e7 100644 --- a/AdvancedDockingSystem/src/ads/container_widget.cpp +++ b/AdvancedDockingSystem/src/ads/container_widget.cpp @@ -19,6 +19,41 @@ static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal) return s; } +static void dropContentOuterHelper(ContainerWidget* cw, QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append) +{ + auto sw = new SectionWidget(cw); + sw->addContent(data, true); + + QSplitter* oldsp = findImmediateSplitter(cw); + if (oldsp->orientation() == orientation + || oldsp->count() == 1) + { + oldsp->setOrientation(orientation); + if (append) + oldsp->addWidget(sw); + else + oldsp->insertWidget(0, sw); + } + else + { + auto sp = newSplitter(orientation); + if (append) + { + auto li = l->replaceWidget(oldsp, sp); + sp->addWidget(oldsp); + sp->addWidget(sw); + delete li; + } + else + { + sp->addWidget(sw); + auto li = l->replaceWidget(oldsp, sp); + sp->addWidget(oldsp); + delete li; + } + } +} + /////////////////////////////////////////////////////////////////////// ContainerWidget::ContainerWidget(QWidget *parent) : @@ -49,9 +84,24 @@ void ContainerWidget::setOrientation(Qt::Orientation orientation) void ContainerWidget::dropContent(const InternalContentData& data, SectionWidget* targetSection, DropArea area) { + // Drop on outer area if (!targetSection) { - qWarning() << "Drop on invalid targetSection"; + switch (area) + { + case TopDropArea: + dropContentOuterHelper(this, _mainLayout, data, Qt::Vertical, false); + break; + case RightDropArea: + dropContentOuterHelper(this, _mainLayout, data, Qt::Horizontal, true); + break; + case BottomDropArea: + dropContentOuterHelper(this, _mainLayout, data, Qt::Vertical, true); + break; + case LeftDropArea: + dropContentOuterHelper(this, _mainLayout, data, Qt::Horizontal, false); + break; + } return; } @@ -226,6 +276,27 @@ QRect ContainerWidget::outerLeftDropRect() const return QRect(r.left(), r.top(), w, r.height()); } +QByteArray ContainerWidget::saveGeometry() const +{ + QByteArray ba; + QDataStream out(&ba, QIODevice::WriteOnly); + out.setVersion(QDataStream::Qt_4_5); + out << (int) 0x00001337; + out << _sections.size(); + return ba; +} + +bool ContainerWidget::restoreGeometry(const QByteArray& data) +{ + QDataStream in(data); + in.setVersion(QDataStream::Qt_4_5); + + int magic = 0; + in >> magic; + + return false; +} + void ContainerWidget::paintEvent(QPaintEvent* e) { QFrame::paintEvent(e); diff --git a/AdvancedDockingSystem/src/ads/container_widget.h b/AdvancedDockingSystem/src/ads/container_widget.h index b174778..4123c49 100644 --- a/AdvancedDockingSystem/src/ads/container_widget.h +++ b/AdvancedDockingSystem/src/ads/container_widget.h @@ -41,6 +41,10 @@ public: QRect outerBottomDropRect() const; QRect outerLeftDropRect() const; + // Geometry and state serialization + QByteArray saveGeometry() const; + bool restoreGeometry(const QByteArray& data); + protected: virtual void paintEvent(QPaintEvent*); virtual void contextMenuEvent(QContextMenuEvent*); diff --git a/AdvancedDockingSystem/src/ads/drop_overlay.cpp b/AdvancedDockingSystem/src/ads/drop_overlay.cpp index 0201630..afa2154 100644 --- a/AdvancedDockingSystem/src/ads/drop_overlay.cpp +++ b/AdvancedDockingSystem/src/ads/drop_overlay.cpp @@ -168,6 +168,7 @@ DropArea DropSplitAreas::cursorLocation() const static QPointer MyOverlay; static QPointer MyOverlayParent; +static QRect MyOverlayParentRect; DropArea showDropOverlay(QWidget* parent) { @@ -190,6 +191,27 @@ DropArea showDropOverlay(QWidget* parent) return MyOverlay->cursorLocation(); } +void showDropOverlay(QWidget* parent, const QRect& areaRect) +{ + if (MyOverlay) + { + if (MyOverlayParent == parent && MyOverlayParentRect == areaRect) + { + return; + } + hideDropOverlay(); + } + + // Create overlay and move it to the parent's areaRect + MyOverlay = new DropOverlay(parent); + MyOverlay->resize(areaRect.size()); + MyOverlay->move(parent->mapToGlobal(QPoint(areaRect.x(), areaRect.y()))); + MyOverlay->show(); + MyOverlayParent = parent; + MyOverlayParentRect = areaRect; + return; +} + void hideDropOverlay() { if (MyOverlay) @@ -197,6 +219,7 @@ void hideDropOverlay() MyOverlay->hide(); delete MyOverlay; MyOverlayParent.clear(); + MyOverlayParentRect = QRect(); } } diff --git a/AdvancedDockingSystem/src/ads/drop_overlay.h b/AdvancedDockingSystem/src/ads/drop_overlay.h index c1de5c3..d97468a 100644 --- a/AdvancedDockingSystem/src/ads/drop_overlay.h +++ b/AdvancedDockingSystem/src/ads/drop_overlay.h @@ -2,6 +2,7 @@ #define DROP_OVERLAY_H #include +#include #include "ads.h" @@ -54,6 +55,7 @@ private: DropArea showDropOverlay(QWidget* parent); +void showDropOverlay(QWidget* parent, const QRect& areaRect); void hideDropOverlay(); ADS_NAMESPACE_END diff --git a/AdvancedDockingSystem/src/ads/section_title_widget.cpp b/AdvancedDockingSystem/src/ads/section_title_widget.cpp index 3da8856..0ff382a 100644 --- a/AdvancedDockingSystem/src/ads/section_title_widget.cpp +++ b/AdvancedDockingSystem/src/ads/section_title_widget.cpp @@ -29,12 +29,12 @@ static void deleteEmptySplitter(ContainerWidget* container) auto splitters = container->findChildren(); for (auto i = 0; i < splitters.count(); ++i) { - if (splitters[i]->count() == 0 && container->_splitter != splitters[i]) + if (splitters[i]->count() == 0 /*&& container->_splitter != splitters[i]*/) { if (splitters[i] == container->_splitter) continue; qDebug() << "Delete empty QSplitter"; - splitters[i]->deleteLater(); + delete splitters[i];//splitters[i]->deleteLater(); } } } @@ -96,11 +96,7 @@ void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev) if (sw) { auto loc = showDropOverlay(sw); - if (loc == InvalidDropArea) - { - qDebug() << "Invalid drop area"; - } - else + if (loc != InvalidDropArea) { #if !defined(ADS_ANIMATIONS_ENABLED) auto data = _fw->takeContent(); @@ -133,9 +129,28 @@ void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev) } } // Mouse is over a outer-edge drop area - else if (false) + else { + DropArea dropArea = DropArea::InvalidDropArea; + if (cw->outerTopDropRect().contains(cw->mapFromGlobal(ev->globalPos()))) + dropArea = DropArea::TopDropArea; + if (cw->outerRightDropRect().contains(cw->mapFromGlobal(ev->globalPos()))) + dropArea = DropArea::RightDropArea; + if (cw->outerBottomDropRect().contains(cw->mapFromGlobal(ev->globalPos()))) + dropArea = DropArea::BottomDropArea; + if (cw->outerLeftDropRect().contains(cw->mapFromGlobal(ev->globalPos()))) + dropArea = DropArea::LeftDropArea; + if (dropArea != DropArea::InvalidDropArea) + { +#if !defined(ADS_ANIMATIONS_ENABLED) + auto data = _fw->takeContent(); + _fw->deleteLater(); + _fw.clear(); + cw->dropContent(data, NULL, dropArea); +#else +#endif + } } } @@ -169,19 +184,19 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev) // Top, Right, Bottom, Left else if (cw->outerTopDropRect().contains(cw->mapFromGlobal(QCursor::pos()))) { - qDebug() << "Top area..."; + showDropOverlay(cw, cw->outerTopDropRect()); } else if (cw->outerRightDropRect().contains(cw->mapFromGlobal(QCursor::pos()))) { - qDebug() << "Right area..."; + showDropOverlay(cw, cw->outerRightDropRect()); } else if (cw->outerBottomDropRect().contains(cw->mapFromGlobal(QCursor::pos()))) { - qDebug() << "Bottom area..."; + showDropOverlay(cw, cw->outerBottomDropRect()); } else if (cw->outerLeftDropRect().contains(cw->mapFromGlobal(QCursor::pos()))) { - qDebug() << "Left area..."; + showDropOverlay(cw, cw->outerLeftDropRect()); } else {