Some refactorings to cleanup code, moved ContainerWidget private data into private data class

This commit is contained in:
Uwe Kindler 2017-01-20 22:43:18 +01:00
parent 68b93f6fa9
commit 889d9bff5b
10 changed files with 206 additions and 221 deletions

View File

@ -60,6 +60,11 @@ enum DropArea
LeftDropArea = 8,
CenterDropArea = 16,
TopBorderDropArea = 32,
RightBorderDropArea = 64,
BottomBorderDropArea = 128,
LeftBorderDropArea = 256,
AllAreas = TopDropArea | RightDropArea | BottomDropArea | LeftDropArea | CenterDropArea
};
Q_DECLARE_FLAGS(DropAreas, DropArea)

View File

@ -21,6 +21,30 @@ class SectionWidget;
class DropOverlay;
class InternalContentData;
struct ContainerWidgetPrivate
{
// Elements inside container.
QList<SectionWidget*> sections;
QList<FloatingWidget*> floatings;
QHash<int, HiddenSectionItem> hiddenSectionContents;
// Helper lookup maps, restricted to this container.
QHash<int, SectionContent::WeakPtr> scLookupMapById;
QHash<QString, SectionContent::WeakPtr> scLookupMapByName;
QHash<int, SectionWidget*> swLookupMapById;
// Layout stuff
QGridLayout* mainLayout = nullptr;;
Qt::Orientation orientation = Qt::Horizontal;
QPointer<QSplitter> splitter; // $mfreiholz: I'd like to remove this variable entirely,
// because it changes during user interaction anyway.
// Drop overlay stuff.
QPointer<DropOverlay> dropOverlay;
};
/*!
* ContainerWidget is the main container to provide the docking
@ -36,6 +60,7 @@ class ADS_EXPORT_API ContainerWidget : public QFrame
friend class SectionTitleWidget;
friend class SectionContentWidget;
friend class SectionWidgetTabsScrollArea;
friend class ContainerWidgetPrivate;
public:
explicit ContainerWidget(QWidget *parent = NULL);
@ -169,26 +194,7 @@ signals:
void sectionContentVisibilityChanged(const SectionContent::RefPtr& sc, bool visible);
private:
// Elements inside container.
QList<SectionWidget*> _sections;
QList<FloatingWidget*> _floatings;
QHash<int, HiddenSectionItem> _hiddenSectionContents;
// Helper lookup maps, restricted to this container.
QHash<int, SectionContent::WeakPtr> _scLookupMapById;
QHash<QString, SectionContent::WeakPtr> _scLookupMapByName;
QHash<int, SectionWidget*> _swLookupMapById;
// Layout stuff
QGridLayout* _mainLayout;
Qt::Orientation _orientation;
QPointer<QSplitter> _splitter; // $mfreiholz: I'd like to remove this variable entirely,
// because it changes during user interaction anyway.
// Drop overlay stuff.
QPointer<DropOverlay> _dropOverlay;
ContainerWidgetPrivate* d;///< private data
};
ADS_NAMESPACE_END

View File

@ -36,6 +36,11 @@ public:
void showDropOverlay(QWidget* target, const QRect& targetAreaRect);
void hideDropOverlay();
/**
* Creates a drop indicator widget for the given drop area
*/
static QWidget* createDropIndicatorWidget(DropArea dropArea);
protected:
virtual void paintEvent(QPaintEvent *e);
virtual void showEvent(QShowEvent* e);
@ -51,6 +56,7 @@ private:
QPointer<QWidget> _target;
QRect _targetRect;
DropArea _lastLocation;
QWidget* m_LeftBorderDropArea;
};
/*!

View File

@ -11,9 +11,6 @@
#include "ads/SectionContent.h"
#endif
#define SCLookupMapById(X) X->_scLookupMapById
#define SCLookupMapByName(X) X->_scLookupMapByName
#define SWLookupMapById(X) X->_swLookupMapById
ADS_NAMESPACE_BEGIN
class SectionContent;

View File

@ -18,8 +18,12 @@
#include "ads/DropOverlay.h"
#include "ads/Serialization.h"
#include <iostream>
ADS_NAMESPACE_BEGIN
// Static Helper //////////////////////////////////////////////////////
static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget* parent = 0)
@ -35,15 +39,13 @@ static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWid
ContainerWidget::ContainerWidget(QWidget *parent) :
QFrame(parent),
_mainLayout(NULL),
_orientation(Qt::Horizontal),
_splitter(NULL),
_dropOverlay(new DropOverlay(this))
d(new ContainerWidgetPrivate())
{
_mainLayout = new QGridLayout();
_mainLayout->setContentsMargins(9, 9, 9, 9);
_mainLayout->setSpacing(0);
setLayout(_mainLayout);
d->dropOverlay = new DropOverlay(this);
d->mainLayout = new QGridLayout();
d->mainLayout->setContentsMargins(4, 4, 4, 4);
d->mainLayout->setSpacing(0);
setLayout(d->mainLayout);
}
ContainerWidget::~ContainerWidget()
@ -52,21 +54,23 @@ ContainerWidget::~ContainerWidget()
// Remove from list, and then delete.
// Because the destrcutor of objects wants to modfiy the current
// iterating list as well... :-/
while (!_sections.isEmpty())
while (!d->sections.isEmpty())
{
SectionWidget* sw = _sections.takeLast();
SectionWidget* sw = d->sections.takeLast();
delete sw;
}
while (!_floatings.isEmpty())
while (!d->floatings.isEmpty())
{
FloatingWidget* fw = _floatings.takeLast();
FloatingWidget* fw = d->floatings.takeLast();
delete fw;
}
_scLookupMapById.clear();
_scLookupMapByName.clear();
_swLookupMapById.clear();
d->scLookupMapById.clear();
d->scLookupMapByName.clear();
d->swLookupMapById.clear();
delete d;
}
SectionWidget* ContainerWidget::addSectionContent(const SectionContent::RefPtr& sc, SectionWidget* sw, DropArea area)
{
ADS_Expects(!sc.isNull());
@ -77,12 +81,7 @@ SectionWidget* ContainerWidget::addSectionContent(const SectionContent::RefPtr&
data.titleWidget = new SectionTitleWidget(sc, NULL);
data.contentWidget = new SectionContentWidget(sc, NULL);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QObject::connect(data.titleWidget, &SectionTitleWidget::activeTabChanged, this, &ContainerWidget::onActiveTabChanged);
#else
QObject::connect(data.titleWidget, SIGNAL(activeTabChanged()), this, SLOT(onActiveTabChanged()));
#endif
connect(data.titleWidget, SIGNAL(activeTabChanged()), this, SLOT(onActiveTabChanged()));
return dropContent(data, sw, area, false);
}
@ -100,13 +99,13 @@ bool ContainerWidget::removeSectionContent(const SectionContent::RefPtr& sc)
// but only cares about SectionWidgets right now. So we need to check whether it was a FloatingWidget
// and delete it.
bool found = false;
for (int i = 0; i < _floatings.count(); ++i)
for (int i = 0; i < d->floatings.count(); ++i)
{
FloatingWidget* fw = _floatings.at(i);
FloatingWidget* fw = d->floatings.at(i);
InternalContentData data;
if (!(found = fw->takeContent(data)))
continue;
_floatings.removeAll(fw);
d->floatings.removeAll(fw);
delete fw;
delete data.titleWidget;
delete data.contentWidget;
@ -114,14 +113,14 @@ bool ContainerWidget::removeSectionContent(const SectionContent::RefPtr& sc)
} // End of ugly work arround.
// Get from hidden contents and delete associated internal stuff.
if (!_hiddenSectionContents.contains(sc->uid()))
if (!d->hiddenSectionContents.contains(sc->uid()))
{
qFatal("Something went wrong... The content should have been there :-/");
return false;
}
// Delete internal objects.
HiddenSectionItem hsi = _hiddenSectionContents.take(sc->uid());
HiddenSectionItem hsi = d->hiddenSectionContents.take(sc->uid());
delete hsi.data.titleWidget;
delete hsi.data.contentWidget;
@ -136,9 +135,9 @@ bool ContainerWidget::showSectionContent(const SectionContent::RefPtr& sc)
ADS_Expects(!sc.isNull());
// Search SC in floatings
for (int i = 0; i < _floatings.count(); ++i)
for (int i = 0; i < d->floatings.count(); ++i)
{
FloatingWidget* fw = _floatings.at(i);
FloatingWidget* fw = d->floatings.at(i);
const bool found = fw->content()->uid() == sc->uid();
if (!found)
continue;
@ -152,19 +151,19 @@ bool ContainerWidget::showSectionContent(const SectionContent::RefPtr& sc)
// Search SC in hidden sections
// Try to show them in the last position, otherwise simply append
// it to the first section (or create a new section?)
if (_hiddenSectionContents.contains(sc->uid()))
if (d->hiddenSectionContents.contains(sc->uid()))
{
const HiddenSectionItem hsi = _hiddenSectionContents.take(sc->uid());
const HiddenSectionItem hsi = d->hiddenSectionContents.take(sc->uid());
hsi.data.titleWidget->setVisible(true);
hsi.data.contentWidget->setVisible(true);
SectionWidget* sw = NULL;
if (hsi.preferredSectionId > 0 && (sw = SWLookupMapById(this).value(hsi.preferredSectionId)) != NULL)
SectionWidget* sw = nullptr;
if (hsi.preferredSectionId > 0 && (sw = d->swLookupMapById.value(hsi.preferredSectionId)) != nullptr)
{
sw->addContent(hsi.data, true);
emit sectionContentVisibilityChanged(sc, true);
return true;
}
else if (_sections.size() > 0 && (sw = _sections.first()) != NULL)
else if (d->sections.size() > 0 && (sw = d->sections.first()) != NULL)
{
sw->addContent(hsi.data, true);
emit sectionContentVisibilityChanged(sc, true);
@ -192,12 +191,12 @@ bool ContainerWidget::hideSectionContent(const SectionContent::RefPtr& sc)
// Search SC in floatings
// We can simply hide floatings, nothing else required.
for (int i = 0; i < _floatings.count(); ++i)
for (int i = 0; i < d->floatings.count(); ++i)
{
const bool found = _floatings.at(i)->content()->uid() == sc->uid();
const bool found = d->floatings.at(i)->content()->uid() == sc->uid();
if (!found)
continue;
_floatings.at(i)->setVisible(false);
d->floatings.at(i)->setVisible(false);
emit sectionContentVisibilityChanged(sc, false);
return true;
}
@ -206,9 +205,9 @@ bool ContainerWidget::hideSectionContent(const SectionContent::RefPtr& sc)
// It's required to remove the SC from SW completely and hold it in a
// separate list as long as a "showSectionContent" gets called for the SC again.
// In case that the SW does not have any other SCs, we need to delete it.
for (int i = 0; i < _sections.count(); ++i)
for (int i = 0; i < d->sections.count(); ++i)
{
SectionWidget* sw = _sections.at(i);
SectionWidget* sw = d->sections.at(i);
const bool found = sw->indexOfContent(sc) >= 0;
if (!found)
continue;
@ -221,7 +220,7 @@ bool ContainerWidget::hideSectionContent(const SectionContent::RefPtr& sc)
hsi.data.titleWidget->setVisible(false);
hsi.data.contentWidget->setVisible(false);
_hiddenSectionContents.insert(sc->uid(), hsi);
d->hiddenSectionContents.insert(sc->uid(), hsi);
if (sw->contents().isEmpty())
{
@ -235,7 +234,7 @@ bool ContainerWidget::hideSectionContent(const SectionContent::RefPtr& sc)
// Search SC in hidden elements
// The content may already be hidden
if (_hiddenSectionContents.contains(sc->uid()))
if (d->hiddenSectionContents.contains(sc->uid()))
return true;
qFatal("Unable to hide SectionContent, don't know this one 8-/");
@ -247,9 +246,9 @@ bool ContainerWidget::raiseSectionContent(const SectionContent::RefPtr& sc)
ADS_Expects(!sc.isNull());
// Search SC in sections
for (int i = 0; i < _sections.count(); ++i)
for (int i = 0; i < d->sections.count(); ++i)
{
SectionWidget* sw = _sections.at(i);
SectionWidget* sw = d->sections.at(i);
int index = sw->indexOfContent(sc);
if (index < 0)
continue;
@ -258,9 +257,9 @@ bool ContainerWidget::raiseSectionContent(const SectionContent::RefPtr& sc)
}
// Search SC in floatings
for (int i = 0; i < _floatings.size(); ++i)
for (int i = 0; i < d->floatings.size(); ++i)
{
FloatingWidget* fw = _floatings.at(i);
FloatingWidget* fw = d->floatings.at(i);
if (fw->content()->uid() != sc->uid())
continue;
fw->setVisible(true);
@ -269,7 +268,7 @@ bool ContainerWidget::raiseSectionContent(const SectionContent::RefPtr& sc)
}
// Search SC in hidden
if (_hiddenSectionContents.contains(sc->uid()))
if (d->hiddenSectionContents.contains(sc->uid()))
return showSectionContent(sc);
qFatal("Unable to hide SectionContent, don't know this one 8-/");
@ -281,18 +280,18 @@ bool ContainerWidget::isSectionContentVisible(const SectionContent::RefPtr& sc)
ADS_Expects(!sc.isNull());
// Search SC in floatings
for (int i = 0; i < _floatings.count(); ++i)
for (int i = 0; i < d->floatings.count(); ++i)
{
const bool found = _floatings.at(i)->content()->uid() == sc->uid();
const bool found = d->floatings.at(i)->content()->uid() == sc->uid();
if (!found)
continue;
return _floatings.at(i)->isVisible();
return d->floatings.at(i)->isVisible();
}
// Search SC in sections
for (int i = 0; i < _sections.count(); ++i)
for (int i = 0; i < d->sections.count(); ++i)
{
SectionWidget* sw = _sections.at(i);
SectionWidget* sw = d->sections.at(i);
const int index = sw->indexOfContent(sc);
if (index < 0)
continue;
@ -300,7 +299,7 @@ bool ContainerWidget::isSectionContentVisible(const SectionContent::RefPtr& sc)
}
// Search SC in hidden
if (_hiddenSectionContents.contains(sc->uid()))
if (d->hiddenSectionContents.contains(sc->uid()))
return false;
qWarning() << "SectionContent is not a part of this ContainerWidget:" << sc->uniqueName();
@ -313,9 +312,9 @@ QMenu* ContainerWidget::createContextMenu() const
QMap<QString, QAction*> actions;
// Visible contents of sections
for (int i = 0; i < _sections.size(); ++i)
for (int i = 0; i < d->sections.size(); ++i)
{
const SectionWidget* sw = _sections.at(i);
const SectionWidget* sw = d->sections.at(i);
const QList<SectionContent::RefPtr>& contents = sw->contents();
foreach (const SectionContent::RefPtr& sc, contents)
{
@ -326,17 +325,13 @@ QMenu* ContainerWidget::createContextMenu() const
a->setCheckable(true);
a->setChecked(true);
a->setEnabled(sc->flags().testFlag(SectionContent::Closeable));
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QObject::connect(a, &QAction::toggled, this, &ContainerWidget::onActionToggleSectionContentVisibility);
#else
QObject::connect(a, SIGNAL(toggled(bool)), this, SLOT(onActionToggleSectionContentVisibility(bool)));
#endif
connect(a, SIGNAL(toggled(bool)), this, SLOT(onActionToggleSectionContentVisibility(bool)));
actions.insert(a->text(), a);
}
}
// Hidden contents of sections
QHashIterator<int, HiddenSectionItem> hiddenIter(_hiddenSectionContents);
QHashIterator<int, HiddenSectionItem> hiddenIter(d->hiddenSectionContents);
while (hiddenIter.hasNext())
{
hiddenIter.next();
@ -348,18 +343,14 @@ QMenu* ContainerWidget::createContextMenu() const
a->setProperty("type", "section");
a->setCheckable(true);
a->setChecked(false);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QObject::connect(a, &QAction::toggled, this, &ContainerWidget::onActionToggleSectionContentVisibility);
#else
QObject::connect(a, SIGNAL(toggled(bool)), this, SLOT(onActionToggleSectionContentVisibility(bool)));
#endif
connect(a, SIGNAL(toggled(bool)), this, SLOT(onActionToggleSectionContentVisibility(bool)));
actions.insert(a->text(), a);
}
// Floating contents
for (int i = 0; i < _floatings.size(); ++i)
for (int i = 0; i < d->floatings.size(); ++i)
{
const FloatingWidget* fw = _floatings.at(i);
const FloatingWidget* fw = d->floatings.at(i);
const SectionContent::RefPtr sc = fw->content();
QAction* a = new QAction(QIcon(), sc->visibleTitle(), NULL);
@ -368,11 +359,7 @@ QMenu* ContainerWidget::createContextMenu() const
a->setProperty("type", "floating");
a->setCheckable(true);
a->setChecked(fw->isVisible());
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QObject::connect(a, &QAction::toggled, this, &ContainerWidget::onActionToggleSectionContentVisibility);
#else
QObject::connect(a, SIGNAL(toggled(bool)), this, SLOT(onActionToggleSectionContentVisibility(bool)));
#endif
connect(a, SIGNAL(toggled(bool)), this, SLOT(onActionToggleSectionContentVisibility(bool)));
actions.insert(a->text(), a);
}
@ -453,7 +440,7 @@ QRect ContainerWidget::outerLeftDropRect() const
QList<SectionContent::RefPtr> ContainerWidget::contents() const
{
QList<SectionContent::WeakPtr> wl = _scLookupMapById.values();
QList<SectionContent::WeakPtr> wl = d->scLookupMapById.values();
QList<SectionContent::RefPtr> sl;
for (int i = 0; i < wl.count(); ++i)
{
@ -466,7 +453,7 @@ QList<SectionContent::RefPtr> ContainerWidget::contents() const
QPointer<DropOverlay> ContainerWidget::dropOverlay() const
{
return _dropOverlay;
return d->dropOverlay;
}
///////////////////////////////////////////////////////////////////////
@ -476,7 +463,7 @@ QPointer<DropOverlay> ContainerWidget::dropOverlay() const
SectionWidget* ContainerWidget::newSectionWidget()
{
SectionWidget* sw = new SectionWidget(this);
_sections.append(sw);
d->sections.append(sw);
return sw;
}
@ -487,7 +474,7 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
SectionWidget* ret = NULL;
// If no sections exists yet, create a default one and always drop into it.
if (_sections.count() <= 0)
if (d->sections.count() <= 0)
{
targetSection = newSectionWidget();
addSection(targetSection);
@ -500,17 +487,17 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
switch (area)
{
case TopDropArea:
ret = dropContentOuterHelper(_mainLayout, data, Qt::Vertical, false);
ret = dropContentOuterHelper(d->mainLayout, data, Qt::Vertical, false);
break;
case RightDropArea:
ret = dropContentOuterHelper(_mainLayout, data, Qt::Horizontal, true);
ret = dropContentOuterHelper(d->mainLayout, data, Qt::Horizontal, true);
break;
case CenterDropArea:
case BottomDropArea:
ret = dropContentOuterHelper(_mainLayout, data, Qt::Vertical, true);
ret = dropContentOuterHelper(d->mainLayout, data, Qt::Vertical, true);
break;
case LeftDropArea:
ret = dropContentOuterHelper(_mainLayout, data, Qt::Horizontal, false);
ret = dropContentOuterHelper(d->mainLayout, data, Qt::Horizontal, false);
break;
default:
return NULL;
@ -620,25 +607,25 @@ void ContainerWidget::addSection(SectionWidget* section)
ADS_Expects(section != NULL);
// Create default splitter.
if (!_splitter)
if (!d->splitter)
{
_splitter = newSplitter(_orientation);
_mainLayout->addWidget(_splitter, 0, 0);
d->splitter = newSplitter(d->orientation);
d->mainLayout->addWidget(d->splitter, 0, 0);
}
if (_splitter->indexOf(section) != -1)
if (d->splitter->indexOf(section) != -1)
{
qWarning() << Q_FUNC_INFO << QString("Section has already been added");
return;
}
_splitter->addWidget(section);
d->splitter->addWidget(section);
}
SectionWidget* ContainerWidget::sectionAt(const QPoint& pos) const
{
const QPoint gpos = mapToGlobal(pos);
for (int i = 0; i < _sections.size(); ++i)
for (int i = 0; i < d->sections.size(); ++i)
{
SectionWidget* sw = _sections[i];
SectionWidget* sw = d->sections[i];
if (sw->rect().contains(sw->mapFromGlobal(gpos)))
{
return sw;
@ -748,40 +735,40 @@ QByteArray ContainerWidget::saveHierarchy() const
saveFloatingWidgets(out);
// Save state of sections and contents
if (_mainLayout->count() <= 0 || _sections.isEmpty())
if (d->mainLayout->count() <= 0 || d->sections.isEmpty())
{
// Looks like the user has hidden all contents and no more sections
// are available. We can simply write a list of all hidden contents.
out << 0; // Mode
out << _hiddenSectionContents.count();
QHashIterator<int, HiddenSectionItem> iter(_hiddenSectionContents);
out << d->hiddenSectionContents.count();
QHashIterator<int, HiddenSectionItem> iter(d->hiddenSectionContents);
while (iter.hasNext())
{
iter.next();
out << iter.value().data.content->uniqueName();
}
}
else if (_mainLayout->count() == 1)
else if (d->mainLayout->count() == 1)
{
out << 1; // Mode
// There should only be one!
QLayoutItem* li = _mainLayout->itemAt(0);
QLayoutItem* li = d->mainLayout->itemAt(0);
if (!li->widget())
qFatal("Not a widget in _mainLayout, this shouldn't happen.");
qFatal("Not a widget in d->mainLayout, this shouldn't happen.");
// Save sections beginning with the first QSplitter (li->widget()).
saveSectionWidgets(out, li->widget());
// Safe state of hidden contents, which doesn't have an section association
// or the section association points to a no longer existing section.
QHashIterator<int, HiddenSectionItem> iter(_hiddenSectionContents);
QHashIterator<int, HiddenSectionItem> iter(d->hiddenSectionContents);
int cnt = 0;
while (iter.hasNext())
{
iter.next();
if (iter.value().preferredSectionId <= 0 || !SWLookupMapById(this).contains(iter.value().preferredSectionId))
if (iter.value().preferredSectionId <= 0 || !d->swLookupMapById.contains(iter.value().preferredSectionId))
cnt++;
}
out << cnt;
@ -789,7 +776,7 @@ QByteArray ContainerWidget::saveHierarchy() const
while (iter.hasNext())
{
iter.next();
if (iter.value().preferredSectionId <= 0 || !SWLookupMapById(this).contains(iter.value().preferredSectionId))
if (iter.value().preferredSectionId <= 0 || !d->swLookupMapById.contains(iter.value().preferredSectionId))
out << iter.value().data.content->uniqueName();
}
}
@ -797,17 +784,17 @@ QByteArray ContainerWidget::saveHierarchy() const
{
// More? Oh oh.. something is wrong :-/
out << -1;
qWarning() << "Oh noooz.. Something went wrong. There are too many items in _mainLayout.";
qWarning() << "Oh noooz.. Something went wrong. There are too many items in d->mainLayout.";
}
return ba;
}
void ContainerWidget::saveFloatingWidgets(QDataStream& out) const
{
out << _floatings.count();
for (int i = 0; i < _floatings.count(); ++i)
out << d->floatings.count();
for (int i = 0; i < d->floatings.count(); ++i)
{
FloatingWidget* fw = _floatings.at(i);
FloatingWidget* fw = d->floatings.at(i);
out << fw->content()->uniqueName();
out << fw->saveGeometry();
out << fw->isVisible();
@ -848,7 +835,7 @@ void ContainerWidget::saveSectionWidgets(QDataStream& out, QWidget* widget) cons
const QList<SectionContent::RefPtr>& contents = sw->contents();
QList<HiddenSectionItem> hiddenContents;
QHashIterator<int, HiddenSectionItem> iter(_hiddenSectionContents);
QHashIterator<int, HiddenSectionItem> iter(d->hiddenSectionContents);
while (iter.hasNext())
{
iter.next();
@ -879,25 +866,25 @@ void ContainerWidget::saveSectionWidgets(QDataStream& out, QWidget* widget) cons
bool ContainerWidget::saveSectionIndex(ADS_NS_SER::SectionIndexData& sid) const
{
if (_sections.count() <= 0)
if (d->sections.count() <= 0)
return false;
sid.sectionsCount = _sections.count();
sid.sectionsCount = d->sections.count();
for (int i = 0; i < sid.sectionsCount; ++i)
{
ADS_NS_SER::SectionEntity se;
se.x = mapFromGlobal(_sections[i]->parentWidget()->mapToGlobal(_sections[i]->pos())).x();
se.y = mapFromGlobal(_sections[i]->parentWidget()->mapToGlobal(_sections[i]->pos())).y();
se.width = _sections[i]->geometry().width();
se.height = _sections[i]->geometry().height();
se.currentIndex = _sections[i]->currentIndex();
se.sectionContentsCount = _sections[i]->contents().count();
foreach (const SectionContent::RefPtr& sc, _sections[i]->contents())
se.x = mapFromGlobal(d->sections[i]->parentWidget()->mapToGlobal(d->sections[i]->pos())).x();
se.y = mapFromGlobal(d->sections[i]->parentWidget()->mapToGlobal(d->sections[i]->pos())).y();
se.width = d->sections[i]->geometry().width();
se.height = d->sections[i]->geometry().height();
se.currentIndex = d->sections[i]->currentIndex();
se.sectionContentsCount = d->sections[i]->contents().count();
foreach (const SectionContent::RefPtr& sc, d->sections[i]->contents())
{
ADS_NS_SER::SectionContentEntity sce;
sce.uniqueName = sc->uniqueName();
sce.visible = true;
sce.preferredIndex = _sections[i]->indexOfContent(sc);
sce.preferredIndex = d->sections[i]->indexOfContent(sc);
se.sectionContents.append(sce); // std::move()?
}
sid.sections.append(se); // std::move()?
@ -920,8 +907,8 @@ bool ContainerWidget::restoreHierarchy(const QByteArray& data)
if (version != 1)
return false;
QList<FloatingWidget*> oldFloatings = _floatings;
QList<SectionWidget*> oldSections = _sections;
QList<FloatingWidget*> oldFloatings = d->floatings;
QList<SectionWidget*> oldSections = d->sections;
// Restore floating widgets
QList<FloatingWidget*> floatings;
@ -954,7 +941,7 @@ bool ContainerWidget::restoreHierarchy(const QByteArray& data)
QString uname;
in >> uname;
const SectionContent::RefPtr sc = SCLookupMapByName(this).value(uname);
const SectionContent::RefPtr sc = d->scLookupMapByName.value(uname);
if (!sc)
continue;
@ -980,7 +967,7 @@ bool ContainerWidget::restoreHierarchy(const QByteArray& data)
{
QString uname;
in >> uname;
const SectionContent::RefPtr sc = SCLookupMapByName(this).value(uname);
const SectionContent::RefPtr sc = d->scLookupMapByName.value(uname);
if (!sc)
continue;
@ -1019,7 +1006,7 @@ bool ContainerWidget::restoreHierarchy(const QByteArray& data)
contents.append(contentsToHide.at(i));
// Compare restored contents with available contents
const QList<SectionContent::WeakPtr> allContents = SCLookupMapById(this).values();
const QList<SectionContent::WeakPtr> allContents = d->scLookupMapById.values();
for (int i = 0; i < allContents.count(); ++i)
{
const SectionContent::RefPtr sc = allContents.at(i).toStrongRef();
@ -1055,12 +1042,12 @@ bool ContainerWidget::restoreHierarchy(const QByteArray& data)
}
}
_floatings = floatings;
_sections = sections;
d->floatings = floatings;
d->sections = sections;
// Delete old objects
QLayoutItem* old = _mainLayout->takeAt(0);
_mainLayout->addWidget(_splitter);
QLayoutItem* old = d->mainLayout->takeAt(0);
d->mainLayout->addWidget(d->splitter);
delete old;
qDeleteAll(oldFloatings);
qDeleteAll(oldSections);
@ -1091,7 +1078,7 @@ bool ContainerWidget::restoreFloatingWidgets(QDataStream& in, int version, QList
bool visible = false;
in >> visible;
const SectionContent::RefPtr sc = SCLookupMapByName(this).value(uname).toStrongRef();
const SectionContent::RefPtr sc = d->scLookupMapByName.value(uname).toStrongRef();
if (!sc)
{
qWarning() << "Can not find SectionContent:" << uname;
@ -1147,7 +1134,7 @@ bool ContainerWidget::restoreSectionWidgets(QDataStream& in, int version, QSplit
sp->setSizes(sizes);
if (!currentSplitter)
_splitter = sp;
d->splitter = sp;
else
currentSplitter->addWidget(sp);
}
@ -1174,7 +1161,7 @@ bool ContainerWidget::restoreSectionWidgets(QDataStream& in, int version, QSplit
int preferredIndex = -1;
in >> preferredIndex;
const SectionContent::RefPtr sc = SCLookupMapByName(this).value(uname).toStrongRef();
const SectionContent::RefPtr sc = d->scLookupMapByName.value(uname).toStrongRef();
if (!sc)
{
qWarning() << "Can not find SectionContent:" << uname;
@ -1220,23 +1207,23 @@ bool ContainerWidget::takeContent(const SectionContent::RefPtr& sc, InternalCont
// Search in sections
bool found = false;
for (int i = 0; i < _sections.count() && !found; ++i)
for (int i = 0; i < d->sections.count() && !found; ++i)
{
found = _sections.at(i)->takeContent(sc->uid(), data);
found = d->sections.at(i)->takeContent(sc->uid(), data);
}
// Search in floating widgets
for (int i = 0; i < _floatings.count() && !found; ++i)
for (int i = 0; i < d->floatings.count() && !found; ++i)
{
found = _floatings.at(i)->content()->uid() == sc->uid();
found = d->floatings.at(i)->content()->uid() == sc->uid();
if (found)
_floatings.at(i)->takeContent(data);
d->floatings.at(i)->takeContent(data);
}
// Search in hidden items
if (!found && _hiddenSectionContents.contains(sc->uid()))
if (!found && d->hiddenSectionContents.contains(sc->uid()))
{
const HiddenSectionItem hsi = _hiddenSectionContents.take(sc->uid());
const HiddenSectionItem hsi = d->hiddenSectionContents.take(sc->uid());
data = hsi.data;
found = true;
}
@ -1259,7 +1246,7 @@ void ContainerWidget::onActionToggleSectionContentVisibility(bool visible)
if (!a)
return;
const int uid = a->property("uid").toInt();
const SectionContent::RefPtr sc = SCLookupMapById(this).value(uid).toStrongRef();
const SectionContent::RefPtr sc = d->scLookupMapById.value(uid).toStrongRef();
if (sc.isNull())
{
qCritical() << "Can not find content by ID" << uid;
@ -1276,37 +1263,21 @@ void ContainerWidget::moveFloatingWidget(const QPoint& TargetPos)
{
// Mouse is over a SectionWidget
SectionWidget* sectionwidget = sectionAt(mapFromGlobal(QCursor::pos()));
if (rect().contains(mapFromGlobal(QCursor::pos())))
{
std::cout << "over Container" << std::endl;
}
if (sectionwidget)
{
qInfo() << "over sectionWidget";
_dropOverlay->setAllowedAreas(ADS_NS::AllAreas);
_dropOverlay->showDropOverlay(sectionwidget);
}
// Mouse is at the edge of the ContainerWidget
// Top, Right, Bottom, Left
else if (outerTopDropRect().contains(mapFromGlobal(QCursor::pos())))
{
_dropOverlay->setAllowedAreas(ADS_NS::TopDropArea);
_dropOverlay->showDropOverlay(this, outerTopDropRect());
}
else if (outerRightDropRect().contains(mapFromGlobal(QCursor::pos())))
{
_dropOverlay->setAllowedAreas(ADS_NS::RightDropArea);
_dropOverlay->showDropOverlay(this, outerRightDropRect());
}
else if (outerBottomDropRect().contains(mapFromGlobal(QCursor::pos())))
{
_dropOverlay->setAllowedAreas(ADS_NS::BottomDropArea);
_dropOverlay->showDropOverlay(this, outerBottomDropRect());
}
else if (outerLeftDropRect().contains(mapFromGlobal(QCursor::pos())))
{
_dropOverlay->setAllowedAreas(ADS_NS::LeftDropArea);
_dropOverlay->showDropOverlay(this, outerLeftDropRect());
d->dropOverlay->setAllowedAreas(ADS_NS::AllAreas);
d->dropOverlay->showDropOverlay(sectionwidget);
}
else
{
_dropOverlay->hideDropOverlay();
d->dropOverlay->hideDropOverlay();
}
}
@ -1323,7 +1294,7 @@ FloatingWidget* ContainerWidget::startFloating(SectionWidget* sectionwidget, int
FloatingWidget* fw = new FloatingWidget(this, data.content, data.titleWidget, data.contentWidget, this);
fw->resize(sectionwidget->size());
_floatings.append(fw);
d->floatings.append(fw);
fw->move(TargetPos);
fw->show();

View File

@ -12,6 +12,8 @@
#include <QtGlobal>
#include <QDebug>
#include <iostream>
ADS_NAMESPACE_BEGIN
// Helper /////////////////////////////////////////////////////////////
@ -42,42 +44,40 @@ static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size
switch (dropArea)
{
case TopDropArea:
case TopBorderDropArea:
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
gradient.setStart(areaRect.topLeft());
gradient.setFinalStop(areaRect.bottomLeft());
gradient.setColorAt(0.f, areaBackgroundColor);
gradient.setColorAt(1.f, areaBackgroundColor.lighter(120));
break;
case RightDropArea:
case RightBorderDropArea:
areaRect = QRectF(baseRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
gradient.setStart(areaRect.topLeft());
gradient.setFinalStop(areaRect.topRight());
gradient.setColorAt(0.f, areaBackgroundColor.lighter(120));
gradient.setColorAt(1.f, areaBackgroundColor);
break;
case BottomDropArea:
case BottomBorderDropArea:
areaRect = QRectF(baseRect.x(), baseRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
gradient.setStart(areaRect.topLeft());
gradient.setFinalStop(areaRect.bottomLeft());
gradient.setColorAt(0.f, areaBackgroundColor.lighter(120));
gradient.setColorAt(1.f, areaBackgroundColor);
break;
case LeftDropArea:
case LeftBorderDropArea:
areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
gradient.setStart(areaRect.topLeft());
gradient.setFinalStop(areaRect.topRight());
gradient.setColorAt(0.f, areaBackgroundColor);
gradient.setColorAt(1.f, areaBackgroundColor.lighter(120));
break;
default:
break;
}
if (areaRect.isValid())
{
gradient.setColorAt(0.f, areaBackgroundColor);
gradient.setColorAt(1.f, areaBackgroundColor.lighter(120));
p.fillRect(areaRect, gradient);
pen = p.pen();
@ -104,7 +104,7 @@ static QPixmap createDropIndicatorPixmap(const QPalette& pal, const QSizeF& size
return pm;
}
static QWidget* createDropIndicatorWidget(DropArea dropArea)
QWidget* DropOverlay::createDropIndicatorWidget(DropArea dropArea)
{
QLabel* l = new QLabel();
l->setObjectName("DropAreaLabel");
@ -113,6 +113,8 @@ static QWidget* createDropIndicatorWidget(DropArea dropArea)
const QSizeF size(metric, metric);
l->setPixmap(createDropIndicatorPixmap(l->palette(), size, dropArea));
l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
l->setAttribute(Qt::WA_TranslucentBackground);
return l;
}
@ -142,6 +144,10 @@ DropOverlay::DropOverlay(QWidget* parent) :
areaWidgets.insert(ADS_NS::LeftDropArea, createDropIndicatorWidget(LeftDropArea));//createDropWidget(":/img/split-left.png"));
areaWidgets.insert(ADS_NS::CenterDropArea, createDropIndicatorWidget(CenterDropArea));//createDropWidget(":/img/dock-center.png"));
m_LeftBorderDropArea = createDropIndicatorWidget(LeftDropArea);
m_LeftBorderDropArea->setVisible(false);
m_LeftBorderDropArea->setWindowTitle("DropOverlayCross");
_cross->setAreaWidgets(areaWidgets);
_cross->setVisible(false);
setVisible(false);
@ -253,6 +259,7 @@ void DropOverlay::paintEvent(QPaintEvent*)
// Draw rect based on location
QRect r = rect();
const DropArea da = cursorLocation();
std::cout << "CursorLocation: " << cursorLocation() << std::endl;
switch (da)
{
case ADS_NS::TopDropArea:
@ -293,11 +300,17 @@ void DropOverlay::paintEvent(QPaintEvent*)
void DropOverlay::showEvent(QShowEvent*)
{
_cross->show();
QRect ContainerWidgetRect = parentWidget()->rect();
QPoint Pos(ContainerWidgetRect.left(), ContainerWidgetRect.center().y());
m_LeftBorderDropArea->move(parentWidget()->mapToGlobal(Pos));
m_LeftBorderDropArea->show();
}
void DropOverlay::hideEvent(QHideEvent*)
{
_cross->hide();
m_LeftBorderDropArea->hide();
}
void DropOverlay::resizeEvent(QResizeEvent* e)

View File

@ -41,18 +41,10 @@ FloatingWidget::FloatingWidget(ContainerWidget* container, SectionContent::RefPt
closeButton->setToolTip(tr("Close"));
closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_titleLayout->addWidget(closeButton);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QObject::connect(closeButton, &QPushButton::clicked, this, &FloatingWidget::onCloseButtonClicked);
#else
QObject::connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked()));
#endif
connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked()));
}
// Content
l->addWidget(contentWidget, 1);
contentWidget->show();
// _container->_floatingWidgets.append(this);
}
@ -69,7 +61,7 @@ FloatingWidget::FloatingWidget(SectionWidget* sectionWidget)
FloatingWidget::~FloatingWidget()
{
_container->_floatings.removeAll(this); // Note: I don't like this here, but we have to remove it from list...
_container->d->floatings.removeAll(this); // Note: I don't like this here, but we have to remove it from list...
}
bool FloatingWidget::takeContent(InternalContentData& data)

View File

@ -16,12 +16,15 @@ SectionContent::SectionContent() :
SectionContent::RefPtr SectionContent::newSectionContent(const QString& uniqueName, ContainerWidget* container, QWidget* title, QWidget* content)
{
auto SectionContentNameMap = container->d->scLookupMapByName;
auto SectionContentIdMap = container->d->scLookupMapById;
if (uniqueName.isEmpty())
{
qFatal("Can not create SectionContent with empty uniqueName");
return RefPtr();
}
else if (SCLookupMapByName(container).contains(uniqueName))
else if (SectionContentNameMap.contains(uniqueName))
{
qFatal("Can not create SectionContent with already used uniqueName");
return RefPtr();
@ -38,17 +41,20 @@ SectionContent::RefPtr SectionContent::newSectionContent(const QString& uniqueNa
sc->_titleWidget = title;
sc->_contentWidget = content;
SCLookupMapById(container).insert(sc->uid(), sc);
SCLookupMapByName(container).insert(sc->uniqueName(), sc);
SectionContentIdMap.insert(sc->uid(), sc);
SectionContentNameMap.insert(sc->uniqueName(), sc);
return sc;
}
SectionContent::~SectionContent()
{
auto SectionContentNameMap = _containerWidget->d->scLookupMapByName;
auto SectionContentIdMap = _containerWidget->d->scLookupMapById;
if (_containerWidget)
{
SCLookupMapById(_containerWidget).remove(_uid);
SCLookupMapByName(_containerWidget).remove(_uniqueName);
SectionContentIdMap.remove(_uid);
SectionContentNameMap.remove(_uniqueName);
}
delete _titleWidget;
delete _contentWidget;

View File

@ -83,8 +83,8 @@ void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
SectionWidget* sw = cw->sectionAt(cw->mapFromGlobal(ev->globalPos()));
if (sw)
{
cw->_dropOverlay->setAllowedAreas(ADS_NS::AllAreas);
DropArea loc = cw->_dropOverlay->showDropOverlay(sw);
cw->d->dropOverlay->setAllowedAreas(ADS_NS::AllAreas);
DropArea loc = cw->d->dropOverlay->showDropOverlay(sw);
if (loc != InvalidDropArea)
{
InternalContentData data;
@ -140,7 +140,7 @@ void SectionTitleWidget::mouseReleaseEvent(QMouseEvent* ev)
// Reset
m_DragStartPosition = QPoint();
m_TabMoving = false;
cw->_dropOverlay->hideDropOverlay();
cw->d->dropOverlay->hideDropOverlay();
QFrame::mouseReleaseEvent(ev);
}

View File

@ -82,11 +82,7 @@ SectionWidget::SectionWidget(ContainerWidget* parent) :
_closeButton->setToolTip(tr("Close"));
_closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
_topLayout->addWidget(_closeButton, 0);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QObject::connect(_closeButton, &QPushButton::clicked, this, &SectionWidget::onCloseButtonClicked);
#else
QObject::connect(_closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked()));
#endif
connect(_closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked()));
_tabsLayoutInitCount = _tabsLayout->count();
@ -97,22 +93,15 @@ SectionWidget::SectionWidget(ContainerWidget* parent) :
_contentsLayout->setSpacing(0);
l->addLayout(_contentsLayout, 1);
#if defined(ADS_ANIMATIONS_ENABLED)
QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect(this);
shadow->setOffset(0, 0);
shadow->setBlurRadius(8);
setGraphicsEffect(shadow);
#endif
SWLookupMapById(_container).insert(_uid, this);
_container->d->swLookupMapById.insert(_uid, this);
}
SectionWidget::~SectionWidget()
{
if (_container)
{
SWLookupMapById(_container).remove(_uid);
_container->_sections.removeAll(this); // Note: I don't like this here, but we have to remove it from list...
_container->d->swLookupMapById.remove(_uid);
_container->d->sections.removeAll(this); // Note: I don't like this here, but we have to remove it from list...
}
// Delete empty QSplitter.