Do some refactoring for public api logic

This commit is contained in:
mfreiholz 2016-02-15 11:13:58 +01:00
parent 77d05431c6
commit 9b09ae2fa6
9 changed files with 172 additions and 165 deletions

View File

@ -52,6 +52,18 @@ public:
*/
QMenu* createContextMenu() const;
/*!
* Serializes the current state of contents and returns it as a plain byte array.
* \see restoreState(const QByteArray&)
*/
QByteArray saveState() const;
/*!
* Deserilizes the state of contents from <em>data</em>, which was written with <em>saveState()</em>.
* \see saveState()
*/
bool restoreState(const QByteArray& data);
//
// Internal Stuff Begins Here
//
@ -70,11 +82,8 @@ public:
QRect outerBottomDropRect() const;
QRect outerLeftDropRect() const;
// Geometry and state serialization
QByteArray saveState() const;
bool restoreState(const QByteArray& data);
private:
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);

View File

@ -22,6 +22,8 @@ class FloatingWidget : public QWidget
{
Q_OBJECT
friend class ContainerWidget;
public:
FloatingWidget(ContainerWidget* container, SectionContent::RefPtr sc, SectionTitleWidget* titleWidget, SectionContentWidget* contentWidget, QWidget* parent = NULL);
virtual ~FloatingWidget();

View File

@ -8,12 +8,15 @@
ADS_NAMESPACE_BEGIN
class ContainerWidget;
class SectionWidget;
class SectionContentWidget : public QFrame
{
Q_OBJECT
friend class ContainerWidget;
public:
SectionContentWidget(SectionContent::RefPtr c, QWidget* parent = 0);

View File

@ -8,7 +8,7 @@
#include "ads/SectionContent.h"
ADS_NAMESPACE_BEGIN
class ContainerWidget;
class SectionWidget;
class FloatingWidget;
@ -17,6 +17,7 @@ class SectionTitleWidget : public QFrame
Q_OBJECT
Q_PROPERTY(bool activeTab MEMBER _activeTab NOTIFY activeTabChanged)
friend class ContainerWidget;
friend class SectionWidget;
SectionContent::RefPtr _content;

View File

@ -25,9 +25,11 @@ class InternalContentData;
class SectionWidget : public QFrame
{
Q_OBJECT
friend class ContainerWidget;
explicit SectionWidget(ContainerWidget* parent);
public:
explicit SectionWidget(ContainerWidget* parent);
virtual ~SectionWidget();
int uid() const;
@ -39,7 +41,7 @@ public:
const QList<SectionContent::RefPtr>& contents() const { return _contents; }
void addContent(SectionContent::RefPtr c);
void addContent(const InternalContentData& data, bool autoActivate);
bool take(int uid, InternalContentData& data);
bool takeContent(int uid, InternalContentData& data);
int indexOfContent(SectionContent::RefPtr c) const;
int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = NULL) const;

View File

@ -23,58 +23,6 @@ static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWid
return s;
}
static SectionWidget* dropContentOuterHelper(ContainerWidget* cw, QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append)
{
SectionWidget* sw = new SectionWidget(cw);
sw->addContent(data, true);
QSplitter* oldsp = findImmediateSplitter(cw);
if (oldsp->orientation() == orientation
|| oldsp->count() == 1)
{
oldsp->setOrientation(orientation);
if (append)
oldsp->addWidget(sw);
else
oldsp->insertWidget(0, sw);
}
else
{
QSplitter* sp = newSplitter(orientation);
if (append)
{
#if QT_VERSION >= 0x050000
QLayoutItem* li = l->replaceWidget(oldsp, sp);
sp->addWidget(oldsp);
sp->addWidget(sw);
delete li;
#else
int index = l->indexOf(oldsp);
QLayoutItem* li = l->takeAt(index);
sp->addWidget(oldsp);
sp->addWidget(sw);
delete li;
#endif
}
else
{
#if QT_VERSION >= 0x050000
sp->addWidget(sw);
QLayoutItem* li = l->replaceWidget(oldsp, sp);
sp->addWidget(oldsp);
delete li;
#else
sp->addWidget(sw);
int index = l->indexOf(oldsp);
QLayoutItem* li = l->takeAt(index);
sp->addWidget(oldsp);
delete li;
#endif
}
}
return sw;
}
///////////////////////////////////////////////////////////////////////
ContainerWidget::ContainerWidget(QWidget *parent) :
@ -174,6 +122,100 @@ QMenu* ContainerWidget::createContextMenu() const
return m;
}
QByteArray ContainerWidget::saveState() const
{
QByteArray ba;
QDataStream out(&ba, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
out << (quint32) 0x00001337; // Magic
out << (quint32) 1; // Version
// Save state of floating contents
out << _floatingWidgets.count();
for (int i = 0; i < _floatingWidgets.count(); ++i)
{
FloatingWidget* fw = _floatingWidgets.at(i);
out << fw->content()->uniqueName();
out << fw->saveGeometry();
}
// Walk through layout for splitters
// Well.. there actually shouldn't be more than one
for (int i = 0; i < _mainLayout->count(); ++i)
{
QLayoutItem* li = _mainLayout->itemAt(i);
if (!li->widget())
continue;
saveGeometryWalk(out, li->widget());
}
return ba;
}
bool ContainerWidget::restoreState(const QByteArray& data)
{
QDataStream in(data);
in.setVersion(QDataStream::Qt_4_5);
quint32 magic = 0;
in >> magic;
if (magic != 0x00001337)
return false;
quint32 version = 0;
in >> version;
if (version != 1)
return false;
QList<FloatingWidget*> oldFloatings = _floatingWidgets;
QList<SectionWidget*> oldSections = _sections;
// Restore floating widgets
int fwCount = 0;
in >> fwCount;
if (fwCount > 0)
{
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;
}
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)
{
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;
}
///////////////////////////////////////////////////////////////////////
// PRIVATE API BEGINS HERE
///////////////////////////////////////////////////////////////////////
@ -207,16 +249,16 @@ SectionWidget* ContainerWidget::dropContent(const InternalContentData& data, Sec
switch (area)
{
case TopDropArea:
ret = dropContentOuterHelper(this, _mainLayout, data, Qt::Vertical, false);
ret = dropContentOuterHelper(_mainLayout, data, Qt::Vertical, false);
break;
case RightDropArea:
ret = dropContentOuterHelper(this, _mainLayout, data, Qt::Horizontal, true);
ret = dropContentOuterHelper(_mainLayout, data, Qt::Horizontal, true);
break;
case BottomDropArea:
ret = dropContentOuterHelper(this, _mainLayout, data, Qt::Vertical, true);
ret = dropContentOuterHelper(_mainLayout, data, Qt::Vertical, true);
break;
case LeftDropArea:
ret = dropContentOuterHelper(this, _mainLayout, data, Qt::Horizontal, false);
ret = dropContentOuterHelper(_mainLayout, data, Qt::Horizontal, false);
break;
default:
return NULL;
@ -379,86 +421,57 @@ QRect ContainerWidget::outerLeftDropRect() const
return QRect(r.left(), r.top(), w, r.height());
}
QByteArray ContainerWidget::saveState() const
SectionWidget* ContainerWidget::dropContentOuterHelper(QLayout* l, const InternalContentData& data, Qt::Orientation orientation, bool append)
{
QByteArray ba;
QDataStream out(&ba, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
out << (quint32) 0x00001337; // Magic
out << (quint32) 1; // Version
ContainerWidget* cw = this;
SectionWidget* sw = new SectionWidget(cw);
sw->addContent(data, true);
// Walk through layout for splitters
// Well.. there actually shouldn't be more than one
for (int i = 0; i < _mainLayout->count(); ++i)
QSplitter* oldsp = findImmediateSplitter(cw);
if (oldsp->orientation() == orientation
|| oldsp->count() == 1)
{
QLayoutItem* li = _mainLayout->itemAt(i);
if (!li->widget())
continue;
saveGeometryWalk(out, li->widget());
oldsp->setOrientation(orientation);
if (append)
oldsp->addWidget(sw);
else
oldsp->insertWidget(0, sw);
}
// Save state of FloatingWidgets
out << _floatingWidgets.count();
for (int i = 0; i < _floatingWidgets.count(); ++i)
else
{
FloatingWidget* fw = _floatingWidgets.at(i);
out << fw->content()->uniqueName();
out << fw->isVisible();
out << fw->saveGeometry();
}
return ba;
}
bool ContainerWidget::restoreState(const QByteArray& data)
QSplitter* sp = newSplitter(orientation);
if (append)
{
QDataStream in(data);
in.setVersion(QDataStream::Qt_4_5);
quint32 magic = 0;
in >> magic;
if (magic != 0x00001337)
return false;
quint32 version = 0;
in >> version;
if (version != 1)
return false;
QList<SectionWidget*> currentSections = _sections;
_sections.clear();
// Restore splitters and section widgets
const bool success = restoreGeometryWalk(in, NULL);
if (success)
{
QLayoutItem* old = _mainLayout->takeAt(0);
_mainLayout->addWidget(_splitter);
delete old;
qDeleteAll(currentSections);
#if QT_VERSION >= 0x050000
QLayoutItem* li = l->replaceWidget(oldsp, sp);
sp->addWidget(oldsp);
sp->addWidget(sw);
delete li;
#else
int index = l->indexOf(oldsp);
QLayoutItem* li = l->takeAt(index);
sp->addWidget(oldsp);
sp->addWidget(sw);
delete li;
#endif
}
// Restore floating widgets
int fwCount = 0;
in >> fwCount;
for (int i = 0; i < fwCount; ++i)
else
{
QString uname;
bool visible = false;
QRect geom;
in >> uname >> visible >> geom;
SectionContent::RefPtr sc = SectionContent::LookupMapByName.value(uname).toStrongRef();
if (!sc)
{
qWarning() << "Can not find floating widget section-content" << uname;
continue;
#if QT_VERSION >= 0x050000
sp->addWidget(sw);
QLayoutItem* li = l->replaceWidget(oldsp, sp);
sp->addWidget(oldsp);
delete li;
#else
sp->addWidget(sw);
int index = l->indexOf(oldsp);
QLayoutItem* li = l->takeAt(index);
sp->addWidget(oldsp);
delete li;
#endif
}
// FloatingWidget* fw = new FloatingWidget(this, sc,)
}
return success;
return sw;
}
void ContainerWidget::saveGeometryWalk(QDataStream& out, QWidget* widget) const
@ -532,7 +545,6 @@ bool ContainerWidget::restoreGeometryWalk(QDataStream& in, QSplitter* currentSpl
in >> currentIndex >> count;
SectionWidget* sw = new SectionWidget(this);
// sw->setGeometry(geom);
for (int i = 0; i < count; ++i)
{
QString name;
@ -547,7 +559,7 @@ bool ContainerWidget::restoreGeometryWalk(QDataStream& in, QSplitter* currentSpl
// Unknown
else
{
qDebug() << QString("");
qDebug() << QString();
}
return true;
@ -559,7 +571,7 @@ bool ContainerWidget::takeContent(const SectionContent::RefPtr& sc, InternalCont
bool found = false;
for (int i = 0; i < _sections.count() && !found; ++i)
{
found = _sections.at(i)->take(sc->uid(), data);
found = _sections.at(i)->takeContent(sc->uid(), data);
}
// Search in floating widgets

View File

@ -227,7 +227,7 @@ void SectionTitleWidget::mouseMoveEvent(QMouseEvent* ev)
{
// Create floating widget.
InternalContentData data;
if (!section->take(_content->uid(), data))
if (!section->takeContent(_content->uid(), data))
{
qWarning() << "THIS SHOULD NOT HAPPEN!!" << _content->uid() << _content->uniqueName();
return;

View File

@ -145,7 +145,7 @@ void SectionWidget::addContent(const InternalContentData& data, bool autoActivat
// take removes a widget from the SectionWidget but does not delete
// the used SectionTitle- and SectionContent-Widget. Instead it returns
// these objects.
bool SectionWidget::take(int uid, InternalContentData& data)
bool SectionWidget::takeContent(int uid, InternalContentData& data)
{
// Find SectionContent.
SectionContent::RefPtr sc;

View File

@ -95,29 +95,7 @@ MainWindow::MainWindow(QWidget *parent) :
_container->setOrientation(Qt::Vertical);
setCentralWidget(_container);
// Test #1: Use low-level API
// if (true)
// {
// ADS_NS::SectionWidget* section = NULL;
// section = new ADS_NS::SectionWidget(_container);
// section->addContent(createLongTextLabelSC());
// _container->addSection(section);
// section = new ADS_NS::SectionWidget(_container);
// section->addContent(createCalendarSC());
// _container->addSection(section);
// section = new ADS_NS::SectionWidget(_container);
// section->addContent(createFileSystemTreeSC());
// _container->addSection(section);
// section = new ADS_NS::SectionWidget(_container);
// section->addContent(createCalendarSC());
// _container->addSection(section);
// }
// Test #2: Use high-level public API
// Test #1: Use high-level public API
if (true)
{
ADS_NS::SectionWidget* sw1 = _container->addSectionContent(createLongTextLabelSC());
@ -130,8 +108,8 @@ MainWindow::MainWindow(QWidget *parent) :
resize(800, 600);
// Restore window geometry and ContainerWidget state from last session
// restoreGeometry(loadDataHelper("MainWindow"));
// _container->restoreState(loadDataHelper("ContainerWidget"));
restoreGeometry(loadDataHelper("MainWindow"));
_container->restoreState(loadDataHelper("ContainerWidget"));
}
MainWindow::~MainWindow()