2017-02-04 05:56:08 +08:00
|
|
|
//============================================================================
|
|
|
|
/// \file ContainerWidget.cpp
|
|
|
|
/// \author Uwe Kindler
|
|
|
|
/// \date 03.02.2017
|
|
|
|
/// \brief Implementation of CContainerWidget
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
// INCLUDES
|
|
|
|
//============================================================================
|
|
|
|
#include "ads/ContainerWidget.h"
|
|
|
|
|
2016-04-06 13:52:17 +08:00
|
|
|
#include <QDebug>
|
2015-12-09 19:21:38 +08:00
|
|
|
#include <QPaintEvent>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QContextMenuEvent>
|
|
|
|
#include <QMenu>
|
|
|
|
#include <QSplitter>
|
2016-02-11 21:33:02 +08:00
|
|
|
#include <QDataStream>
|
|
|
|
#include <QtGlobal>
|
2016-02-26 19:43:14 +08:00
|
|
|
#include <QGridLayout>
|
|
|
|
#include <QPoint>
|
2017-01-31 05:44:27 +08:00
|
|
|
#include <QApplication>
|
2016-02-26 19:43:14 +08:00
|
|
|
|
2017-02-08 06:51:29 +08:00
|
|
|
#include <iostream>
|
|
|
|
|
2016-02-26 19:43:14 +08:00
|
|
|
#include "ads/Internal.h"
|
|
|
|
#include "ads/SectionWidget.h"
|
|
|
|
#include "ads/SectionTitleWidget.h"
|
|
|
|
#include "ads/SectionContentWidget.h"
|
2016-04-15 14:21:23 +08:00
|
|
|
#include "ads/DropOverlay.h"
|
2016-04-01 19:06:12 +08:00
|
|
|
#include "ads/Serialization.h"
|
2017-02-08 06:51:29 +08:00
|
|
|
#include "ads/MainContainerWidget.h"
|
2015-12-09 19:21:38 +08:00
|
|
|
|
2017-02-04 05:56:08 +08:00
|
|
|
namespace ads
|
2015-12-09 19:21:38 +08:00
|
|
|
{
|
2017-02-08 06:51:29 +08:00
|
|
|
unsigned int CContainerWidget::zOrderCounter = 0;
|
|
|
|
|
2017-02-04 05:56:08 +08:00
|
|
|
//============================================================================
|
2017-02-08 06:51:29 +08:00
|
|
|
CContainerWidget::CContainerWidget(MainContainerWidget* MainContainer, QWidget *parent)
|
|
|
|
: QFrame(parent),
|
|
|
|
m_MainContainerWidget(MainContainer)
|
2015-12-09 19:21:38 +08:00
|
|
|
{
|
2017-01-31 05:44:27 +08:00
|
|
|
m_MainLayout = new QGridLayout();
|
|
|
|
m_MainLayout->setContentsMargins(0, 1, 0, 0);
|
|
|
|
m_MainLayout->setSpacing(0);
|
|
|
|
setLayout(m_MainLayout);
|
2016-02-18 22:06:00 +08:00
|
|
|
}
|
|
|
|
|
2016-02-24 18:45:19 +08:00
|
|
|
|
2017-02-04 05:56:08 +08:00
|
|
|
//============================================================================
|
|
|
|
CContainerWidget::~CContainerWidget()
|
2016-04-21 13:51:26 +08:00
|
|
|
{
|
2017-02-08 06:51:29 +08:00
|
|
|
std::cout << "CContainerWidget::~CContainerWidget()" << std::endl;
|
2017-02-11 04:23:14 +08:00
|
|
|
m_MainContainerWidget->m_Containers.removeAll(this);
|
2017-02-08 06:51:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2017-02-12 05:05:23 +08:00
|
|
|
SectionWidget* sectionWidget = sectionWidgetAt(TargetPos);
|
2017-02-08 06:51:29 +08:00
|
|
|
DropArea dropArea = InvalidDropArea;
|
|
|
|
if (sectionWidget)
|
|
|
|
{
|
2017-02-11 04:23:14 +08:00
|
|
|
auto dropOverlay = m_MainContainerWidget->sectionDropOverlay();
|
|
|
|
dropOverlay->setAllowedAreas(ADS_NS::AllAreas);
|
|
|
|
dropArea = dropOverlay->showDropOverlay(sectionWidget);
|
2017-02-08 06:51:29 +08:00
|
|
|
if (dropArea != InvalidDropArea)
|
|
|
|
{
|
2017-02-12 05:05:23 +08:00
|
|
|
std::cout << "Section Drop Content: " << dropArea << std::endl;
|
2017-02-08 06:51:29 +08:00
|
|
|
InternalContentData data;
|
|
|
|
FloatingWidget->takeContent(data);
|
|
|
|
FloatingWidget->deleteLater();
|
2017-02-11 04:23:14 +08:00
|
|
|
dropContent(data, sectionWidget, dropArea, true);
|
2017-02-08 06:51:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// mouse is over container
|
|
|
|
if (InvalidDropArea == dropArea)
|
|
|
|
{
|
2017-02-11 04:23:14 +08:00
|
|
|
dropArea = m_MainContainerWidget->dropOverlay()->dropAreaUnderCursor();
|
2017-02-12 05:05:23 +08:00
|
|
|
std::cout << "Container Drop Content: " << dropArea << std::endl;
|
2017-02-08 06:51:29 +08:00
|
|
|
if (dropArea != InvalidDropArea)
|
|
|
|
{
|
2017-02-12 05:05:23 +08:00
|
|
|
dropIntoContainer(FloatingWidget, dropArea);
|
2017-02-08 06:51:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 02:59:29 +08:00
|
|
|
/*void dumpChildSplitters(QWidget* Widget)
|
|
|
|
{
|
|
|
|
QSplitter* ParentSplitter = dynamic_cast<QSplitter*>(Widget);
|
|
|
|
auto Sections = Widget->findChildren<SectionWidget*>(QString(), Qt::FindDirectChildrenOnly);
|
|
|
|
auto Splitters = Widget->findChildren<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
|
|
|
|
|
|
|
|
std::cout << "-----------------------" << std::endl;
|
|
|
|
std::cout << "Sections " << Sections.size() << std::endl;
|
|
|
|
std::cout << "Splitters " << Splitters.size() << std::endl;
|
|
|
|
for (const auto& Splitter : Splitters)
|
|
|
|
{
|
|
|
|
if (ParentSplitter)
|
|
|
|
{
|
|
|
|
std::cout << "Orientation " << Splitter->orientation() << " index " << ParentSplitter->indexOf(Splitter) << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << "Orientation " << Splitter->orientation() << std::endl;
|
|
|
|
}
|
|
|
|
dumpChildSplitters(Splitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CContainerWidget::dumpLayout()
|
|
|
|
{
|
|
|
|
dumpChildSplitters(this);
|
|
|
|
}*/
|
|
|
|
|
|
|
|
void CContainerWidget::dropChildSections(QWidget* Parent)
|
|
|
|
{
|
|
|
|
auto Sections = Parent->findChildren<SectionWidget*>(QString(), Qt::FindDirectChildrenOnly);
|
|
|
|
auto Splitters = Parent->findChildren<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
|
|
|
|
|
|
|
|
std::cout << "-----------------------" << std::endl;
|
|
|
|
std::cout << "Sections " << Sections.size() << std::endl;
|
|
|
|
std::cout << "Splitters " << Splitters.size() << std::endl;
|
|
|
|
|
|
|
|
for (auto Section : Sections)
|
|
|
|
{
|
|
|
|
// drop section
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto Splitter : Splitters)
|
|
|
|
{
|
|
|
|
dropChildSections(Splitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-08 06:51:29 +08:00
|
|
|
|
2017-02-12 05:05:23 +08:00
|
|
|
void CContainerWidget::dropIntoContainer(FloatingWidget* FloatingWidget, DropArea area)
|
|
|
|
{
|
2017-02-13 02:59:29 +08:00
|
|
|
dropChildSections(FloatingWidget->containerWidget());
|
2017-02-12 05:05:23 +08:00
|
|
|
InternalContentData data;
|
|
|
|
FloatingWidget->takeContent(data);
|
|
|
|
FloatingWidget->deleteLater();
|
|
|
|
dropContent(data, nullptr, area, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-08 06:51:29 +08:00
|
|
|
SectionWidget* CContainerWidget::sectionWidgetAt(const QPoint& pos) const
|
|
|
|
{
|
2017-02-12 05:05:23 +08:00
|
|
|
for (const auto& SectionWidget : m_Sections)
|
2017-02-08 06:51:29 +08:00
|
|
|
{
|
2017-02-12 05:05:23 +08:00
|
|
|
if (SectionWidget->rect().contains(SectionWidget->mapFromGlobal(pos)))
|
2017-02-08 06:51:29 +08:00
|
|
|
{
|
2017-02-12 05:05:23 +08:00
|
|
|
return SectionWidget;
|
2017-02-08 06:51:29 +08:00
|
|
|
}
|
|
|
|
}
|
2017-02-12 05:05:23 +08:00
|
|
|
|
2017-02-08 06:51:29 +08:00
|
|
|
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);
|
2016-04-21 13:51:26 +08:00
|
|
|
|
2017-02-12 05:05:23 +08:00
|
|
|
connect(data.titleWidget, SIGNAL(activeTabChanged()), this, SLOT(onActiveTabChanged()));
|
2017-02-08 06:51:29 +08:00
|
|
|
return dropContent(data, sw, area, false);
|
2016-04-21 13:51:26 +08:00
|
|
|
}
|
2017-02-12 05:05:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
void dumpChildSplitters(QWidget* Widget)
|
|
|
|
{
|
|
|
|
QSplitter* ParentSplitter = dynamic_cast<QSplitter*>(Widget);
|
|
|
|
auto Sections = Widget->findChildren<SectionWidget*>(QString(), Qt::FindDirectChildrenOnly);
|
|
|
|
auto Splitters = Widget->findChildren<QSplitter*>(QString(), Qt::FindDirectChildrenOnly);
|
|
|
|
|
|
|
|
std::cout << "-----------------------" << std::endl;
|
|
|
|
std::cout << "Sections " << Sections.size() << std::endl;
|
|
|
|
std::cout << "Splitters " << Splitters.size() << std::endl;
|
|
|
|
for (const auto& Splitter : Splitters)
|
|
|
|
{
|
|
|
|
if (ParentSplitter)
|
|
|
|
{
|
|
|
|
std::cout << "Orientation " << Splitter->orientation() << " index " << ParentSplitter->indexOf(Splitter) << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << "Orientation " << Splitter->orientation() << std::endl;
|
|
|
|
}
|
|
|
|
dumpChildSplitters(Splitter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CContainerWidget::dumpLayout()
|
|
|
|
{
|
|
|
|
dumpChildSplitters(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CContainerWidget::onActiveTabChanged()
|
|
|
|
{
|
|
|
|
SectionTitleWidget* stw = qobject_cast<SectionTitleWidget*>(sender());
|
|
|
|
if (stw)
|
|
|
|
{
|
|
|
|
emit activeTabChanged(stw->m_Content, stw->isActiveTab());
|
|
|
|
}
|
|
|
|
}
|
2017-02-04 05:56:08 +08:00
|
|
|
} // namespace ads
|
2016-04-21 13:51:26 +08:00
|
|
|
|
2017-02-04 05:56:08 +08:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// EOF ContainerWidget.cpp
|