Implements storeGeometry() and restoreGeometry() for ContainerWidget. It

correctly aligns all widgets... wohooo.
This commit is contained in:
mfreiholz 2016-02-11 14:33:02 +01:00
parent 7123410bb1
commit 9050d1910c
7 changed files with 181 additions and 29 deletions

View File

@ -50,6 +50,10 @@ public:
QMenu* createContextMenu() const;
private:
void saveGeometryWalk(QDataStream& out, QWidget* widget) const;
bool restoreGeometryWalk(QDataStream& in, QSplitter* currentSplitter = NULL);
signals:
void orientationChanged();
@ -63,8 +67,8 @@ public:
// Layout stuff
QGridLayout* _mainLayout;
Qt::Orientation _orientation; ///< Default orientation of new sections.
QPointer<QSplitter> _splitter; ///< Default/main splitter.
Qt::Orientation _orientation;
QPointer<QSplitter> _splitter;
};
ADS_NAMESPACE_END

View File

@ -5,6 +5,7 @@
#include <QWidget>
#include <QHash>
#include <QSharedPointer>
#include <QWeakPointer>
#include "ads/API.h"
@ -12,28 +13,32 @@ ADS_NAMESPACE_BEGIN
class SectionContent
{
friend class ContainerWidget;
private:
SectionContent(QWidget* title, QWidget* content, const QString& uniqueName = QString()); ///< Do not use!
public:
typedef QSharedPointer<SectionContent> RefPtr;
typedef QWeakPointer<SectionContent> WeakPtr;
SectionContent(QWidget* title, QWidget* content, const QString& uniqueName = QString()); ///< Do not use!
virtual ~SectionContent();
int uid() const;
QString uniqueName() const;
QWidget* titleWidget() const;
QWidget* contentWidget() const;
static RefPtr newSectionContent(QWidget* title, QWidget* content);
static RefPtr newSectionContent(const QString& title, QWidget* content);
static RefPtr newSectionContent(QWidget* title, QWidget* content, const QString& uniqueName = QString());
public:
private:
const int _uid;
const QString _uniqueName;
QPointer<QWidget> _title;
QPointer<QWidget> _content;
static int NextUid;
static QHash<int, SectionContent*> LookupMap;
static QHash<int, SectionContent::WeakPtr> LookupMap;
static QHash<QString, SectionContent::WeakPtr> LookupMapByName;
};
ADS_NAMESPACE_END

View File

@ -35,7 +35,7 @@ public:
QRect titleAreaGeometry() const;
QRect contentAreaGeometry() const;
QList<SectionContent::RefPtr> contents() const { return _contents; }
const QList<SectionContent::RefPtr>& contents() const { return _contents; }
void addContent(SectionContent::RefPtr c);
void addContent(const InternalContentData& data, bool autoActivate);
InternalContentData take(int uid, bool del = true);

View File

@ -5,6 +5,8 @@
#include <QContextMenuEvent>
#include <QMenu>
#include <QSplitter>
#include <QDataStream>
#include <QtGlobal>
ADS_NAMESPACE_BEGIN
@ -25,7 +27,7 @@ static void dropContentOuterHelper(ContainerWidget* cw, QLayout* l, const Intern
QSplitter* oldsp = findImmediateSplitter(cw);
if (oldsp->orientation() == orientation
|| oldsp->count() == 1)
|| oldsp->count() == 1)
{
oldsp->setOrientation(orientation);
if (append)
@ -276,8 +278,18 @@ QByteArray ContainerWidget::saveGeometry() const
QByteArray ba;
QDataStream out(&ba, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
out << (int) 0x00001337;
out << _sections.size();
out << (quint32) 0x00001337; // Magic
out << (quint32) 1; // Version
// 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;
}
@ -286,10 +298,28 @@ bool ContainerWidget::restoreGeometry(const QByteArray& data)
QDataStream in(data);
in.setVersion(QDataStream::Qt_4_5);
int magic = 0;
quint32 magic = 0;
in >> magic;
if (magic != 0x00001337)
return false;
return false;
quint32 version = 0;
in >> version;
if (version != 1)
return false;
QList<SectionWidget*> currentSections = _sections;
_sections.clear();
const bool success = restoreGeometryWalk(in, NULL);
if (success)
{
QLayoutItem* old = _mainLayout->takeAt(0);
_mainLayout->addWidget(_splitter);
delete old;
qDeleteAll(currentSections);
}
return success;
}
QMenu* ContainerWidget::createContextMenu() const
@ -326,4 +356,91 @@ QMenu* ContainerWidget::createContextMenu() const
return m;
}
void ContainerWidget::saveGeometryWalk(QDataStream& out, QWidget* widget) const
{
QSplitter* sp = NULL;
SectionWidget* sw = NULL;
if (!widget)
{
out << 0;
}
else if ((sp = dynamic_cast<QSplitter*>(widget)) != NULL)
{
out << 1; // Type = QSplitter
out << ((sp->orientation() == Qt::Horizontal) ? (int) 1 : (int) 2);
out << sp->count();
for (int i = 0; i < sp->count(); ++i)
{
saveGeometryWalk(out, sp->widget(i));
}
}
else if ((sw = dynamic_cast<SectionWidget*>(widget)) != NULL)
{
out << 2; // Type = SectionWidget
out << sw->geometry();
out << sw->contents().count();
const QList<SectionContent::RefPtr>& contents = sw->contents();
for (int i = 0; i < contents.count(); ++i)
{
out << contents[i]->uniqueName();
}
}
}
bool ContainerWidget::restoreGeometryWalk(QDataStream& in, QSplitter* currentSplitter)
{
int type;
in >> type;
// Splitter
if (type == 1)
{
int orientation, count;
in >> orientation >> count;
QSplitter* sp = newSplitter((Qt::Orientation) orientation);
for (int i = 0; i < count; ++i)
{
if (!restoreGeometryWalk(in, sp))
return false;
}
if (!currentSplitter)
_splitter = sp;
else
currentSplitter->addWidget(sp);
}
// Section
else if (type == 2)
{
if (!currentSplitter)
{
qWarning() << "Missing splitter object for section";
return false;
}
QRect geom;
int count;
in >> geom >> count;
SectionWidget* sw = new SectionWidget(this);
sw->setGeometry(geom);
for (int i = 0; i < count; ++i)
{
QString name;
in >> name;
SectionContent::RefPtr sc = SectionContent::LookupMapByName.value(name).toStrongRef();
if (sc)
sw->addContent(sc);
}
currentSplitter->addWidget(sw);
}
// Unknown
else
{
qDebug() << QString("");
}
return true;
}
ADS_NAMESPACE_END

View File

@ -5,20 +5,21 @@
ADS_NAMESPACE_BEGIN
int SectionContent::NextUid = 1;
QHash<int, SectionContent*> SectionContent::LookupMap;
QHash<int, SectionContent::WeakPtr> SectionContent::LookupMap;
QHash<QString, SectionContent::WeakPtr> SectionContent::LookupMapByName;
SectionContent::SectionContent(QWidget* title, QWidget* content, const QString& uniqueName) :
_uid(NextUid++),
_uniqueName(uniqueName)
_uniqueName(uniqueName),
_title(title),
_content(content)
{
_title = title;
_content = content;
LookupMap.insert(_uid, this);
}
SectionContent::~SectionContent()
{
LookupMap.remove(_uid);
LookupMapByName.remove(_uniqueName);
delete _title;
delete _content;
}
@ -43,14 +44,13 @@ QWidget* SectionContent::contentWidget() const
return _content;
}
SectionContent::RefPtr SectionContent::newSectionContent(QWidget* title, QWidget* content)
SectionContent::RefPtr SectionContent::newSectionContent(QWidget* title, QWidget* content, const QString& uniqueName)
{
return QSharedPointer<SectionContent>(new SectionContent(title, content));
}
SectionContent::RefPtr SectionContent::newSectionContent(const QString& title, QWidget* content)
{
return QSharedPointer<SectionContent>(new SectionContent(new QLabel(title), content));
QSharedPointer<SectionContent> sc(new SectionContent(title, content, uniqueName));
LookupMap.insert(sc->uid(), sc);
if (!sc->uniqueName().isEmpty())
LookupMapByName.insert(sc->uniqueName(), sc);
return sc;
}
ADS_NAMESPACE_END

View File

@ -31,13 +31,16 @@ static ads::SectionContent::RefPtr createLongTextLabelSC()
l->setText(QString("Lorem Ipsum ist ein einfacher Demo-Text für die Print- und Schriftindustrie. Lorem Ipsum ist in der Industrie bereits der Standard Demo-Text seit 1500, als ein unbekannter Schriftsteller eine Hand voll Wörter nahm und diese durcheinander warf um ein Musterbuch zu erstellen. Es hat nicht nur 5 Jahrhunderte überlebt, sondern auch in Spruch in die elektronische Schriftbearbeitung geschafft (bemerke, nahezu unverändert). Bekannt wurde es 1960, mit dem erscheinen von Letrase, welches Passagen von Lorem Ipsum enhielt, so wie Desktop Software wie Aldus PageMaker - ebenfalls mit Lorem Ipsum."));
bl->addWidget(l);
return ads::SectionContent::newSectionContent(new IconTitleWidget(QIcon(), QString("Label %1").arg(++CONTENT_COUNT)), w);
const int index = ++CONTENT_COUNT;
return ads::SectionContent::newSectionContent(new IconTitleWidget(QIcon(), QString("Label %1").arg(index)), w, QString("uname-%1").arg(index));
}
static ads::SectionContent::RefPtr createCalendarSC()
{
QCalendarWidget* w = new QCalendarWidget();
return ads::SectionContent::newSectionContent(new IconTitleWidget(QIcon(), QString("Calendar %1").arg(++CONTENT_COUNT)), w);
const int index = ++CONTENT_COUNT;
return ads::SectionContent::newSectionContent(new IconTitleWidget(QIcon(), QString("Calendar %1").arg(index)), w, QString("uname-%1").arg(index));
}
static ads::SectionContent::RefPtr createFileSystemTreeSC()
@ -46,7 +49,9 @@ static ads::SectionContent::RefPtr createFileSystemTreeSC()
// QFileSystemModel* m = new QFileSystemModel(w);
// m->setRootPath(QDir::currentPath());
// w->setModel(m);
return ads::SectionContent::newSectionContent(new IconTitleWidget(QIcon(), QString("Filesystem %1").arg(++CONTENT_COUNT)), w);
const int index = ++CONTENT_COUNT;
return ads::SectionContent::newSectionContent(new IconTitleWidget(QIcon(), QString("Filesystem %1").arg(index)), w, QString("uname-%1").arg(index));
}
///////////////////////////////////////////////////////////////////////
@ -82,6 +87,15 @@ MainWindow::MainWindow(QWidget *parent) :
section = new ads::SectionWidget(_container);
section->addContent(createCalendarSC());
_container->addSection(section);
QByteArray ba;
QFile f("test.dat");
if (f.open(QFile::ReadOnly))
{
ba = f.readAll();
f.close();
}
_container->restoreGeometry(ba);
}
MainWindow::~MainWindow()
@ -108,3 +122,14 @@ void MainWindow::contextMenuEvent(QContextMenuEvent* e)
m->exec(QCursor::pos());
delete m;
}
void MainWindow::closeEvent(QCloseEvent* e)
{
QByteArray ba = _container->saveGeometry();
QFile f("test.dat");
if (f.open(QFile::WriteOnly))
{
f.write(ba);
f.close();
}
}

View File

@ -25,6 +25,7 @@ private slots:
protected:
virtual void contextMenuEvent(QContextMenuEvent* e);
virtual void closeEvent(QCloseEvent* e);
private:
Ui::MainWindow *ui;