Better implementation of empty QSplitter deletion (no longer crashes).

Call it after restore, because sometimes one splitter was left ?-/
This commit is contained in:
mfreiholz 2016-03-08 10:58:56 +01:00
parent 94d8fe3e25
commit 9bbc5e41a3
5 changed files with 57 additions and 15 deletions

View File

@ -3,21 +3,48 @@
#include <QWidget> #include <QWidget>
#include <QSplitter> #include <QSplitter>
#include <QLayout> #include <QLayout>
#include <QVariant>
#include "ads/ContainerWidget.h" #include "ads/ContainerWidget.h"
#include "ads/SectionWidget.h" #include "ads/SectionWidget.h"
ADS_NAMESPACE_BEGIN ADS_NAMESPACE_BEGIN
static bool splitterContainsSectionWidget(QSplitter* splitter)
{
for (int i = 0; i < splitter->count(); ++i)
{
QWidget* w = splitter->widget(i);
QSplitter* sp = qobject_cast<QSplitter*>(w);
SectionWidget* sw = NULL;
if (sp && splitterContainsSectionWidget(sp))
return true;
else if ((sw = qobject_cast<SectionWidget*>(w)) != NULL)
return true;
}
return false;
}
void deleteEmptySplitter(ContainerWidget* container) void deleteEmptySplitter(ContainerWidget* container)
{ {
QList<QSplitter*> splitters = container->findChildren<QSplitter*>(); bool doAgain = false;
for (int i = 0; i < splitters.count(); ++i) do
{ {
QSplitter* sp = splitters.at(i); doAgain = false;
if (sp->count() == 0) QList<QSplitter*> splitters = container->findChildren<QSplitter*>();
for (int i = 0; i < splitters.count(); ++i)
{
QSplitter* sp = splitters.at(i);
if (!sp->property("ads-splitter").toBool())
continue;
if (sp->count() > 0 && splitterContainsSectionWidget(sp))
continue;
delete splitters[i]; delete splitters[i];
doAgain = true;
break;
}
} }
while (doAgain);
} }
ContainerWidget* findParentContainerWidget(QWidget* w) ContainerWidget* findParentContainerWidget(QWidget* w)

View File

@ -22,6 +22,7 @@ ADS_NAMESPACE_BEGIN
static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget* parent = 0) static QSplitter* newSplitter(Qt::Orientation orientation = Qt::Horizontal, QWidget* parent = 0)
{ {
QSplitter* s = new QSplitter(orientation, parent); QSplitter* s = new QSplitter(orientation, parent);
s->setProperty("ads-splitter", QVariant(true));
s->setChildrenCollapsible(false); s->setChildrenCollapsible(false);
s->setOpaqueResize(false); s->setOpaqueResize(false);
return s; return s;
@ -348,9 +349,9 @@ QByteArray ContainerWidget::saveState() const
{ {
// Looks like the user has hidden all contents and no more sections // Looks like the user has hidden all contents and no more sections
// are available. We can simply write a list of all hidden contents. // are available. We can simply write a list of all hidden contents.
out << 0; out << 0; // Mode
out << _hiddenSectionContents.count();
out << _hiddenSectionContents.count();
QHashIterator<int, HiddenSectionItem> iter(_hiddenSectionContents); QHashIterator<int, HiddenSectionItem> iter(_hiddenSectionContents);
while (iter.hasNext()) while (iter.hasNext())
{ {
@ -360,13 +361,15 @@ QByteArray ContainerWidget::saveState() const
} }
else if (_mainLayout->count() == 1) else if (_mainLayout->count() == 1)
{ {
out << 1; // Mode
// There should only be one! // There should only be one!
out << 1;
QLayoutItem* li = _mainLayout->itemAt(0); QLayoutItem* li = _mainLayout->itemAt(0);
if (!li->widget()) if (!li->widget())
qFatal("Not a widget in _mainLayout, this shouldn't happen."); qFatal("Not a widget in _mainLayout, this shouldn't happen.");
else
saveSectionWidgets(out, li->widget()); // Save sections beginning with the first QSplitter (li->widget()).
saveSectionWidgets(out, li->widget());
// Safe state of hidden contents, which doesn't have an section association // Safe state of hidden contents, which doesn't have an section association
// or the section association points to a no longer existing section. // or the section association points to a no longer existing section.
@ -563,6 +566,8 @@ bool ContainerWidget::restoreState(const QByteArray& data)
for (int i = 0; i < contentsToHide.count(); ++i) for (int i = 0; i < contentsToHide.count(); ++i)
hideSectionContent(contentsToHide.at(i)); hideSectionContent(contentsToHide.at(i));
deleteEmptySplitter(this);
qDebug() << "End of restore state" << success; qDebug() << "End of restore state" << success;
return success; return success;
} }

View File

@ -97,17 +97,21 @@ MainWindow::MainWindow(QWidget *parent) :
#if QT_VERSION >= 0x050000 #if QT_VERSION >= 0x050000
QObject::connect(_container, &ADS_NS::ContainerWidget::activeTabChanged, this, &MainWindow::onActiveTabChanged); QObject::connect(_container, &ADS_NS::ContainerWidget::activeTabChanged, this, &MainWindow::onActiveTabChanged);
#else #else
QObject::connect(_container, SIGNAL(activeTabChanged(SectionContent::RefPtr,bool)), this, SLOT(onActiveTabChanged(const::ads::SectionContent::RefPtr&,bool))); QObject::connect(_container, SIGNAL(activeTabChanged(const SectionContent::RefPtr&, bool)), this, SLOT(onActiveTabChanged(const SectionContent::RefPtr&, bool)));
#endif #endif
setCentralWidget(_container); setCentralWidget(_container);
// Test #1: Use high-level public API // Test #1: Use high-level public API
if (true) if (true)
{ {
ADS_NS::SectionWidget* sw1 = _container->addSectionContent(createLongTextLabelSC(_container)); ADS_NS::ContainerWidget* cw = _container;
_container->addSectionContent(createCalendarSC(_container), sw1, ADS_NS::BottomDropArea); ADS_NS::SectionWidget* sw = NULL;
_container->addSectionContent(createFileSystemTreeSC(_container), NULL, ADS_NS::RightDropArea);
_container->addSectionContent(createCalendarSC(_container)); sw = _container->addSectionContent(createLongTextLabelSC(cw), sw, ADS_NS::CenterDropArea);
sw = _container->addSectionContent(createCalendarSC(cw), sw, ADS_NS::RightDropArea);
sw = _container->addSectionContent(createFileSystemTreeSC(cw), sw, ADS_NS::CenterDropArea);
// _container->addSectionContent(createCalendarSC(_container));
// _container->addSectionContent(createLongTextLabelSC(_container)); // _container->addSectionContent(createLongTextLabelSC(_container));
// _container->addSectionContent(createLongTextLabelSC(_container)); // _container->addSectionContent(createLongTextLabelSC(_container));
// _container->addSectionContent(createLongTextLabelSC(_container)); // _container->addSectionContent(createLongTextLabelSC(_container));

View File

@ -19,7 +19,11 @@ public:
virtual ~MainWindow(); virtual ~MainWindow();
private slots: private slots:
#if QT_VERSION >= 0x050000
void onActiveTabChanged(const ADS_NS::SectionContent::RefPtr& sc, bool active); void onActiveTabChanged(const ADS_NS::SectionContent::RefPtr& sc, bool active);
#else
void onActiveTabChanged(const SectionContent::RefPtr& sc, bool active);
#endif
void onActionAddSectionContentTriggered(); void onActionAddSectionContentTriggered();
protected: protected:

View File

@ -40,13 +40,15 @@ Items sorted by priority
### Beta 0.2 ### Beta 0.2
- [ ] Use scrolling for SectionWidget tabs? - [ ] Use scrolling for SectionWidget tabs?
- [ ] It would be easier when the SectionTitleWidget and SectionContentWidget are created inside the "SectionContent::newSectionContent(..)" method. - [ ] It would be easier when the SectionTitleWidget and SectionContentWidget are created inside the "SectionContent::newSectionContent(..)" method.
This would make sure, that those two objects always exists. This would make sure, that those two objects always exists.
- [ ] `ContainerWidget::showSectionContent` needs to insert the SC at the correct preferred position of SW - [ ] `ContainerWidget::showSectionContent` needs to insert the SC at the correct preferred position of SW
- [ ] It should be possible to drop a floating widget directly into the SW's tab-bar.
- [ ] Empty splitters, if only 2 or 1 items are in container - [ ] Empty splitters, if only 2 or 1 items are in container
- [ ] Restore: Handle out-of-screen geometry for floating widgets - [ ] Restore: Handle out-of-screen geometry for floating widgets
- [ ] Better handling of sizes when dropping contents. Currently it's unpredictable. - [ ] Better handling of sizes when dropping contents. Currently it's unpredictable.
It might be good to use the same width/height as the parent content, if dropped on existing content. It might be good to use the same width/height as the parent content, if dropped on existing content.
In case of outer-drop we might use the preferred size of the content. In case of outer-drop we might use the preferred size of the content.
- [ ] Floating widget should be a real window with all of its functionality (maximize and split by moving it to the edge of the screen)
### Beta 0.1 ### Beta 0.1
- [x] Improve FloatingWidget (Remove maximize button, only support close-button which hides the widget) - [x] Improve FloatingWidget (Remove maximize button, only support close-button which hides the widget)