mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-11-15 13:15:43 +08:00
Serializes and deserializes FloatingWidgets.
This commit is contained in:
parent
5a17a88146
commit
f0b1ea4735
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user