diff --git a/AdvancedDockingSystem/include/ads/ContainerWidget.h b/AdvancedDockingSystem/include/ads/ContainerWidget.h index 3061139..67819ad 100644 --- a/AdvancedDockingSystem/include/ads/ContainerWidget.h +++ b/AdvancedDockingSystem/include/ads/ContainerWidget.h @@ -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 _splitter; ///< Default/main splitter. + Qt::Orientation _orientation; + QPointer _splitter; }; ADS_NAMESPACE_END diff --git a/AdvancedDockingSystem/include/ads/SectionContent.h b/AdvancedDockingSystem/include/ads/SectionContent.h index 5e28f2c..9ecb58d 100644 --- a/AdvancedDockingSystem/include/ads/SectionContent.h +++ b/AdvancedDockingSystem/include/ads/SectionContent.h @@ -5,6 +5,7 @@ #include #include #include +#include #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 RefPtr; + typedef QWeakPointer 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 _title; QPointer _content; static int NextUid; - static QHash LookupMap; + static QHash LookupMap; + static QHash LookupMapByName; }; ADS_NAMESPACE_END diff --git a/AdvancedDockingSystem/include/ads/SectionWidget.h b/AdvancedDockingSystem/include/ads/SectionWidget.h index b9afc7c..3b66c7d 100644 --- a/AdvancedDockingSystem/include/ads/SectionWidget.h +++ b/AdvancedDockingSystem/include/ads/SectionWidget.h @@ -35,7 +35,7 @@ public: QRect titleAreaGeometry() const; QRect contentAreaGeometry() const; - QList contents() const { return _contents; } + const QList& contents() const { return _contents; } void addContent(SectionContent::RefPtr c); void addContent(const InternalContentData& data, bool autoActivate); InternalContentData take(int uid, bool del = true); diff --git a/AdvancedDockingSystem/src/ContainerWidget.cpp b/AdvancedDockingSystem/src/ContainerWidget.cpp index 2a74f59..80d3566 100644 --- a/AdvancedDockingSystem/src/ContainerWidget.cpp +++ b/AdvancedDockingSystem/src/ContainerWidget.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include 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 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(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(widget)) != NULL) + { + out << 2; // Type = SectionWidget + out << sw->geometry(); + out << sw->contents().count(); + const QList& 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 diff --git a/AdvancedDockingSystem/src/SectionContent.cpp b/AdvancedDockingSystem/src/SectionContent.cpp index 14d1c34..59fa23b 100644 --- a/AdvancedDockingSystem/src/SectionContent.cpp +++ b/AdvancedDockingSystem/src/SectionContent.cpp @@ -5,20 +5,21 @@ ADS_NAMESPACE_BEGIN int SectionContent::NextUid = 1; -QHash SectionContent::LookupMap; +QHash SectionContent::LookupMap; +QHash 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(new SectionContent(title, content)); -} - -SectionContent::RefPtr SectionContent::newSectionContent(const QString& title, QWidget* content) -{ - return QSharedPointer(new SectionContent(new QLabel(title), content)); + QSharedPointer 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 \ No newline at end of file diff --git a/AdvancedDockingSystemDemo/src/mainwindow.cpp b/AdvancedDockingSystemDemo/src/mainwindow.cpp index 688183c..efe3338 100644 --- a/AdvancedDockingSystemDemo/src/mainwindow.cpp +++ b/AdvancedDockingSystemDemo/src/mainwindow.cpp @@ -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(); + } +} diff --git a/AdvancedDockingSystemDemo/src/mainwindow.h b/AdvancedDockingSystemDemo/src/mainwindow.h index eab5146..54995ee 100644 --- a/AdvancedDockingSystemDemo/src/mainwindow.h +++ b/AdvancedDockingSystemDemo/src/mainwindow.h @@ -25,6 +25,7 @@ private slots: protected: virtual void contextMenuEvent(QContextMenuEvent* e); + virtual void closeEvent(QCloseEvent* e); private: Ui::MainWindow *ui;