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

View File

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

View File

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

View File

@ -31,13 +31,7 @@ FloatingWidget::FloatingWidget(ContainerWidget* container, SectionContent::RefPt
_titleLayout = new QBoxLayout(QBoxLayout::LeftToRight); _titleLayout = new QBoxLayout(QBoxLayout::LeftToRight);
_titleLayout->addWidget(titleWidget, 1); _titleLayout->addWidget(titleWidget, 1);
l->addLayout(_titleLayout, 0); l->addLayout(_titleLayout, 0);
titleWidget->setActiveTab(false);
// 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);
QPushButton* closeButton = new QPushButton(); QPushButton* closeButton = new QPushButton();
closeButton->setObjectName("closeButton"); closeButton->setObjectName("closeButton");
@ -53,13 +47,13 @@ FloatingWidget::FloatingWidget(ContainerWidget* container, SectionContent::RefPt
l->addWidget(contentWidget, 1); l->addWidget(contentWidget, 1);
contentWidget->show(); contentWidget->show();
_container->_floatingWidgets.append(this); // _container->_floatingWidgets.append(this);
} }
FloatingWidget::~FloatingWidget() FloatingWidget::~FloatingWidget()
{ {
qDebug() << Q_FUNC_INFO; 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) 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 = new FloatingWidget(cw, data.content, data.titleWidget, data.contentWidget, cw);
_fw->resize(section->size()); _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)); const QPoint moveToPos = ev->globalPos() - (_dragStartPos + QPoint(ADS_WINDOW_FRAME_BORDER_WIDTH, ADS_WINDOW_FRAME_BORDER_WIDTH));
_fw->move(moveToPos); _fw->move(moveToPos);

View File

@ -26,6 +26,7 @@ ADS_NAMESPACE_BEGIN
int SectionWidget::NextUid = 1; int SectionWidget::NextUid = 1;
QHash<int, SectionWidget*> SectionWidget::LookupMap; QHash<int, SectionWidget*> SectionWidget::LookupMap;
QHash<ContainerWidget*, QHash<int, SectionWidget*> > SectionWidget::LookupMapByContainer;
SectionWidget::SectionWidget(ContainerWidget* parent) : SectionWidget::SectionWidget(ContainerWidget* parent) :
QFrame(parent), QFrame(parent),
@ -56,14 +57,16 @@ SectionWidget::SectionWidget(ContainerWidget* parent) :
#endif #endif
LookupMap.insert(_uid, this); LookupMap.insert(_uid, this);
_container->_sections.append(this); LookupMapByContainer[_container].insert(_uid, this);
// _container->_sections.append(this);
} }
SectionWidget::~SectionWidget() SectionWidget::~SectionWidget()
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
LookupMap.remove(_uid); 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. // Delete empty QSplitter.
QSplitter* splitter = findParentSplitter(this); QSplitter* splitter = findParentSplitter(this);
@ -79,6 +82,11 @@ int SectionWidget::uid() const
return _uid; return _uid;
} }
ContainerWidget* SectionWidget::containerWidget() const
{
return _container;
}
QRect SectionWidget::titleAreaGeometry() const QRect SectionWidget::titleAreaGeometry() const
{ {
return _tabsLayout->geometry(); 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 Sorted by priority
- **[DONE]** Improve FloatingWidget (Remove maximize button, only support close-button which hides the widget) - **[DONE]** Improve FloatingWidget (Remove maximize button, only support close-button which hides the widget)
- **[DONE]** Serialize and Deserialize state/size/positions of dockings - **[DONE]** Serialize and Deserialize state/size/positions of dockings
- **[90%]** Make compatible with Qt 4.5 (\*ROFL!\*) - **[DONE]** Make compatible with Qt 4.5 (\*ROFL!\*)
- Save and restore FloatingWidget states - **[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 - 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 - Pin contents: Pins a content and its title widget to the edge and opens on click/hover as long as it has focus