mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-12-25 07:31:33 +08:00
Better implementation of empty QSplitter deletion (no longer crashes).
Call it after restore, because sometimes one splitter was left ?-/
This commit is contained in:
parent
94d8fe3e25
commit
9bbc5e41a3
@ -3,22 +3,49 @@
|
|||||||
#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)
|
||||||
{
|
{
|
||||||
|
bool doAgain = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
doAgain = false;
|
||||||
QList<QSplitter*> splitters = container->findChildren<QSplitter*>();
|
QList<QSplitter*> splitters = container->findChildren<QSplitter*>();
|
||||||
for (int i = 0; i < splitters.count(); ++i)
|
for (int i = 0; i < splitters.count(); ++i)
|
||||||
{
|
{
|
||||||
QSplitter* sp = splitters.at(i);
|
QSplitter* sp = splitters.at(i);
|
||||||
if (sp->count() == 0)
|
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)
|
||||||
{
|
{
|
||||||
|
@ -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,12 +361,14 @@ 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
|
|
||||||
|
// Save sections beginning with the first QSplitter (li->widget()).
|
||||||
saveSectionWidgets(out, 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
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
@ -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:
|
||||||
|
@ -42,11 +42,13 @@ Items sorted by priority
|
|||||||
- [ ] 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)
|
||||||
|
Loading…
Reference in New Issue
Block a user