Serializes and deserializes FloatingWidgets.

This commit is contained in:
mfreiholz 2016-02-17 09:59:11 +01:00
parent 5a17a88146
commit f0b1ea4735
7 changed files with 109 additions and 73 deletions

View File

@ -84,12 +84,14 @@ private:
// Internal Stuff Begins Here
//
SectionWidget* newSectionWidget();
SectionWidget* dropContent(const InternalContentData& data, SectionWidget* targetSection, DropArea area, bool autoActive = true);
void addSection(SectionWidget* section);
SectionWidget* sectionAt(const QPoint& pos) const;
SectionWidget* dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append);
void saveGeometryWalk(QDataStream& out, QWidget* widget) const;
bool restoreGeometryWalk(QDataStream& in, QSplitter* currentSplitter = NULL);
bool restoreFloatingWidgets(QDataStream& in, QList<FloatingWidget*>& floatings);
bool restoreSectionWidgets(QDataStream& in, QSplitter* currentSplitter, QList<SectionWidget*>& sections);
bool takeContent(const SectionContent::RefPtr& sc, InternalContentData& data);
private slots:
@ -99,17 +101,16 @@ signals:
void orientationChanged();
private:
// Existing sections.
// SectionWidgets are always visible.
// Sections of this container
QList<SectionWidget*> _sections;
// All currently active Floatingwidgets.
QList<FloatingWidget*> _floatingWidgets;
//Floatings of this container
QList<FloatingWidget*> _floatings;
// Layout stuff
QGridLayout* _mainLayout;
Qt::Orientation _orientation;
QPointer<QSplitter> _splitter;
QPointer<QSplitter> _splitter; // $mfreiholz: I'd like to remove this variable entirely.
};
ADS_NAMESPACE_END

View File

@ -31,6 +31,7 @@ public:
virtual ~SectionWidget();
int uid() const;
ContainerWidget* containerWidget() const;
QRect titleAreaGeometry() const;
QRect contentAreaGeometry() const;
@ -71,6 +72,7 @@ private:
static int NextUid;
static QHash<int, SectionWidget*> LookupMap;
static QHash<ContainerWidget*, QHash<int, SectionWidget*> > LookupMapByContainer;
};
ADS_NAMESPACE_END

View File

@ -57,7 +57,7 @@ SectionWidget* ContainerWidget::addSectionContent(const SectionContent::RefPtr&
{
if (_sections.isEmpty())
{ // Create default section
sw = new SectionWidget(this);
sw = newSectionWidget();
addSection(sw);
}
else if (area == CenterDropArea)
@ -98,13 +98,13 @@ QMenu* ContainerWidget::createContextMenu() const
}
// Contents of FloatingWidgets
if (_floatingWidgets.size())
if (_floatings.size())
{
if (m->actions().size())
m->addSeparator();
for (int i = 0; i < _floatingWidgets.size(); ++i)
for (int i = 0; i < _floatings.size(); ++i)
{
FloatingWidget* fw = _floatingWidgets.at(i);
FloatingWidget* fw = _floatings.at(i);
SectionContent::RefPtr c = fw->content();
QAction* a = m->addAction(QIcon(), c->uniqueName());
a->setProperty("uid", c->uid());
@ -131,10 +131,10 @@ QByteArray ContainerWidget::saveState() const
out << (quint32) 1; // Version
// Save state of floating contents
out << _floatingWidgets.count();
for (int i = 0; i < _floatingWidgets.count(); ++i)
out << _floatings.count();
for (int i = 0; i < _floatings.count(); ++i)
{
FloatingWidget* fw = _floatingWidgets.at(i);
FloatingWidget* fw = _floatings.at(i);
out << fw->content()->uniqueName();
out << fw->saveGeometry();
}
@ -167,51 +167,37 @@ bool ContainerWidget::restoreState(const QByteArray& data)
if (version != 1)
return false;
QList<FloatingWidget*> oldFloatings = _floatingWidgets;
QList<FloatingWidget*> oldFloatings = _floatings;
QList<SectionWidget*> oldSections = _sections;
// Restore floating widgets
int fwCount = 0;
in >> fwCount;
if (fwCount > 0)
QList<FloatingWidget*> floatings;
bool success = restoreFloatingWidgets(in, floatings);
if (!success)
{
for (int i = 0; i < fwCount; ++i)
{
QString uname;
in >> uname;
QByteArray geom;
in >> geom;
SectionContent::RefPtr sc = SectionContent::LookupMapByName.value(uname).toStrongRef();
if (!sc)
{
qWarning() << "Can not find floating widget section-content" << uname;
continue;
qWarning() << "Could not restore floatings completely";
}
InternalContentData data;
if (!this->takeContent(sc, data))
continue;
FloatingWidget* fw = new FloatingWidget(this, sc, data.titleWidget, data.contentWidget, this);
fw->restoreGeometry(geom);
}
}
_sections.clear();
// Restore splitters and section widgets
const bool success = restoreGeometryWalk(in, NULL);
if (success)
QList<SectionWidget*> sections;
success = restoreSectionWidgets(in, NULL, sections);
if (!success)
{
qWarning() << "Could not restore sections completely";
}
_floatings = floatings;
_sections = sections;
// TODO Handle contents which are not mentioned by deserialized data
// ...
// Delete old objects
QLayoutItem* old = _mainLayout->takeAt(0);
_mainLayout->addWidget(_splitter);
delete old;
qDeleteAll(oldFloatings);
qDeleteAll(oldSections);
}
// TODO Handle contents which are not mentioned by deserialized data
// ...
return success;
}
@ -248,6 +234,13 @@ QRect ContainerWidget::outerLeftDropRect() const
// PRIVATE API BEGINS HERE
///////////////////////////////////////////////////////////////////////
SectionWidget* ContainerWidget::newSectionWidget()
{
SectionWidget* sw = new SectionWidget(this);
_sections.append(sw);
return sw;
}
SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, SectionWidget* targetSection, DropArea area, bool autoActive)
{
SectionWidget* ret = NULL;
@ -282,7 +275,7 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
{
case TopDropArea:
{
SectionWidget* sw = new SectionWidget(this);
SectionWidget* sw = newSectionWidget();
sw->addContent(data, true);
if (targetSectionSplitter->orientation() == Qt::Vertical)
{
@ -302,7 +295,7 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
}
case RightDropArea:
{
SectionWidget* sw = new SectionWidget(this);
SectionWidget* sw = newSectionWidget();
sw->addContent(data, true);
if (targetSectionSplitter->orientation() == Qt::Horizontal)
{
@ -322,7 +315,7 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
}
case BottomDropArea:
{
SectionWidget* sw = new SectionWidget(this);
SectionWidget* sw = newSectionWidget();
sw->addContent(data, true);
if (targetSectionSplitter->orientation() == Qt::Vertical)
{
@ -342,7 +335,7 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
}
case LeftDropArea:
{
SectionWidget* sw = new SectionWidget(this);
SectionWidget* sw = newSectionWidget();
sw->addContent(data, true);
if (targetSectionSplitter->orientation() == Qt::Horizontal)
{
@ -404,11 +397,10 @@ SectionWidget* ContainerWidget::sectionAt(const QPoint& pos) const
SectionWidget* ContainerWidget::dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append)
{
ContainerWidget* cw = this;
SectionWidget* sw = new SectionWidget(cw);
SectionWidget* sw = newSectionWidget();
sw->addContent(data, true);
QSplitter* oldsp = findImmediateSplitter(cw);
QSplitter* oldsp = findImmediateSplitter(this);
if (oldsp->orientation() == orientation
|| oldsp->count() == 1)
{
@ -490,7 +482,42 @@ void ContainerWidget::saveGeometryWalk(QDataStream& out, QWidget* widget) const
}
}
bool ContainerWidget::restoreGeometryWalk(QDataStream& in, QSplitter* currentSplitter)
bool ContainerWidget::restoreFloatingWidgets(QDataStream& in, QList<FloatingWidget*>& floatings)
{
int fwCount = 0;
in >> fwCount;
if (fwCount <= 0)
return true;
for (int i = 0; i < fwCount; ++i)
{
QString uname;
in >> uname;
QByteArray geom;
in >> geom;
qDebug() << "Restore FloatingWidget" << uname << geom;
const SectionContent::RefPtr sc = SectionContent::LookupMapByName.value(uname).toStrongRef();
if (!sc)
{
qWarning() << "Can not find SectionContent:" << uname;
continue;
}
InternalContentData data;
if (!this->takeContent(sc, data))
continue;
FloatingWidget* fw = new FloatingWidget(this, sc, data.titleWidget, data.contentWidget, this);
fw->restoreGeometry(geom);
fw->setVisible(true);
data.titleWidget->_fw = fw; // $mfreiholz: Don't look at it :-< It's more than ugly...
floatings.append(fw);
}
return true;
}
bool ContainerWidget::restoreSectionWidgets(QDataStream& in, QSplitter* currentSplitter, QList<SectionWidget*>& sections)
{
int type;
in >> type;
@ -505,7 +532,7 @@ bool ContainerWidget::restoreGeometryWalk(QDataStream& in, QSplitter* currentSpl
QSplitter* sp = newSplitter((Qt::Orientation) orientation);
for (int i = 0; i < count; ++i)
{
if (!restoreGeometryWalk(in, sp))
if (!restoreSectionWidgets(in, sp, sections))
return false;
}
sp->setSizes(sizes);
@ -532,12 +559,13 @@ bool ContainerWidget::restoreGeometryWalk(QDataStream& in, QSplitter* currentSpl
{
QString name;
in >> name;
SectionContent::RefPtr sc = SectionContent::LookupMapByName.value(name).toStrongRef();
const SectionContent::RefPtr sc = SectionContent::LookupMapByName.value(name).toStrongRef();
if (sc)
sw->addContent(sc);
}
sw->setCurrentIndex(currentIndex);
currentSplitter->addWidget(sw);
sections.append(sw);
}
// Unknown
else
@ -558,10 +586,10 @@ bool ContainerWidget::takeContent(const SectionContent::RefPtr& sc, InternalCont
}
// Search in floating widgets
for (int i = 0; i < _floatingWidgets.count() && !found; ++i)
for (int i = 0; i < _floatings.count() && !found; ++i)
{
found = _floatingWidgets.at(i)->content()->uid() == sc->uid();
_floatingWidgets.at(i)->takeContent(data);
found = _floatings.at(i)->content()->uid() == sc->uid();
_floatings.at(i)->takeContent(data);
}
return found;

View File

@ -31,13 +31,7 @@ FloatingWidget::FloatingWidget(ContainerWidget* container, SectionContent::RefPt
_titleLayout = new QBoxLayout(QBoxLayout::LeftToRight);
_titleLayout->addWidget(titleWidget, 1);
l->addLayout(_titleLayout, 0);
// auto maximizeButton = new QPushButton();
// maximizeButton->setObjectName("maximizeButton");
// maximizeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
// maximizeButton->setToolTip(tr("Maximize"));
// maximizeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// _titleLayout->addWidget(maximizeButton);
titleWidget->setActiveTab(false);
QPushButton* closeButton = new QPushButton();
closeButton->setObjectName("closeButton");
@ -53,13 +47,13 @@ FloatingWidget::FloatingWidget(ContainerWidget* container, SectionContent::RefPt
l->addWidget(contentWidget, 1);
contentWidget->show();
_container->_floatingWidgets.append(this);
// _container->_floatingWidgets.append(this);
}
FloatingWidget::~FloatingWidget()
{
qDebug() << Q_FUNC_INFO;
_container->_floatingWidgets.removeAll(this);
_container->_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

@ -237,7 +237,8 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
_fw = new FloatingWidget(cw, data.content, data.titleWidget, data.contentWidget, cw);
_fw->resize(section->size());
setActiveTab(false);
cw->_floatings.append(_fw); // Note: I don't like this...
//setActiveTab(false);
const QPoint moveToPos = ev->globalPos() - (_dragStartPos + QPoint(ADS_WINDOW_FRAME_BORDER_WIDTH, ADS_WINDOW_FRAME_BORDER_WIDTH));
_fw->move(moveToPos);

View File

@ -26,6 +26,7 @@ ADS_NAMESPACE_BEGIN
int SectionWidget::NextUid = 1;
QHash<int, SectionWidget*> SectionWidget::LookupMap;
QHash<ContainerWidget*, QHash<int, SectionWidget*> > SectionWidget::LookupMapByContainer;
SectionWidget::SectionWidget(ContainerWidget* parent) :
QFrame(parent),
@ -56,14 +57,16 @@ SectionWidget::SectionWidget(ContainerWidget* parent) :
#endif
LookupMap.insert(_uid, this);
_container->_sections.append(this);
LookupMapByContainer[_container].insert(_uid, this);
// _container->_sections.append(this);
}
SectionWidget::~SectionWidget()
{
qDebug() << Q_FUNC_INFO;
LookupMap.remove(_uid);
_container->_sections.removeAll(this);
LookupMapByContainer[_container].remove(_uid);
_container->_sections.removeAll(this); // Note: I don't like this here, but we have to remove it from list...
// Delete empty QSplitter.
QSplitter* splitter = findParentSplitter(this);
@ -79,6 +82,11 @@ int SectionWidget::uid() const
return _uid;
}
ContainerWidget* SectionWidget::containerWidget() const
{
return _container;
}
QRect SectionWidget::titleAreaGeometry() const
{
return _tabsLayout->geometry();

View File

@ -23,8 +23,10 @@ Open the `build.pro` with QtCreator and start the build, that's it.
Sorted by priority
- **[DONE]** Improve FloatingWidget (Remove maximize button, only support close-button which hides the widget)
- **[DONE]** Serialize and Deserialize state/size/positions of dockings
- **[90%]** Make compatible with Qt 4.5 (\*ROFL!\*)
- Save and restore FloatingWidget states
- **[DONE]** Make compatible with Qt 4.5 (\*ROFL!\*)
- **[DONE]** Save and restore FloatingWidget states
- Restore: Manage new or deleted SectionContent objects, which are not available
- Show close button on right corner of SectionWidget
- Drop indicator images should be fully visible over the DropOverlay rectangle
- Pin contents: Pins a content and its title widget to the edge and opens on click/hover as long as it has focus