Fix crash when moving separator

We weren't recurring up the tree to find the next separator
This commit is contained in:
Sergio Martins
2020-05-19 14:46:30 +01:00
parent af22e3e12d
commit 6001e655fd
3 changed files with 53 additions and 2 deletions

View File

@@ -2020,8 +2020,11 @@ void ItemContainer::requestSeparatorMove(Separator *separator, int delta)
const int max = maxPosForSeparator_global(separator);
if (pos + delta < min || pos + delta > max) {
root()->dumpLayout();
qWarning() << "Separator would have gone out of bounds"
<< separator << min << pos << max << delta;
<< "; separators=" << separator
<< "; min=" << min << "; pos=" << pos
<< "; max=" << max << "; delta=" << delta;
return;
}
@@ -2073,7 +2076,13 @@ void ItemContainer::requestSeparatorMove(Separator *separator, int delta)
qWarning() << Q_FUNC_INFO << "Not enough space to move separator"
<< this;
} else {
Separator *nextSeparator = parentContainer()->neighbourSeparator(this, moveDirection, m_orientation);
Separator *nextSeparator = parentContainer()->neighbourSeparator_recursive(this, moveDirection, m_orientation);
if (!nextSeparator) {
// Doesn't happen
qWarning() << Q_FUNC_INFO << "nextSeparator is null, report a bug";
return;
}
// nextSeparator might not belong to parentContainer(), due to different orientation
const int remainingDelta = moveDirection == Side1 ? -remainingToTake : remainingToTake;
nextSeparator->parentContainer()->requestSeparatorMove(nextSeparator, remainingDelta);
@@ -2965,6 +2974,19 @@ Separator *ItemContainer::neighbourSeparator(const Item *item, Side side, Qt::Or
return m_separators[separatorIndex];
}
Separator *ItemContainer::neighbourSeparator_recursive(const Item *item, Side side,
Qt::Orientation orientation) const
{
Separator *separator = neighbourSeparator(item, side, orientation);
if (separator)
return separator;
if (!parentContainer())
return nullptr;
return parentContainer()->neighbourSeparator_recursive(this, side, orientation);
}
void ItemContainer::updateWidgets_recursive()
{
for (Item *item : m_children) {

View File

@@ -548,6 +548,7 @@ private:
void resizeChildren(QSize oldSize, QSize newSize, SizingInfo::List &sizes, ChildrenResizeStrategy);
void scheduleCheckSanity() const;
Separator *neighbourSeparator(const Item *item, Side, Qt::Orientation) const;
Separator *neighbourSeparator_recursive(const Item *item, Side, Qt::Orientation) const;
void updateWidgets_recursive();
/// Returns the positions that each separator should have (x position if Qt::Horizontal, y otherwise)
QVector<int> requiredSeparatorPositions() const;

View File

@@ -167,6 +167,7 @@ private Q_SLOTS:
void tst_mapToRoot();
void tst_closeAndRestorePreservesPosition();
void tst_minSizeChangedBeforeRestore();
void tst_separatorMoveCrash();
};
class MyHostWidget : public QWidget {
@@ -1482,6 +1483,33 @@ void TestMultiSplitter::tst_minSizeChangedBeforeRestore()
item2->restore(guest2);
}
void TestMultiSplitter::tst_separatorMoveCrash()
{
// Tests a crash I got when moving separator to the right
auto root = createRoot();
auto item1 = createItem();
auto item2 = createItem();
auto item3 = createItem();
auto item4 = createItem();
auto item5 = createItem();
auto item6 = createItem();
root->insertItem(item1, Item::Location_OnTop);
root->insertItem(item2, Item::Location_OnBottom);
item2->insertItem(item3, Item::Location_OnRight);
item3->insertItem(item4, Item::Location_OnBottom);
item4->insertItem(item5, Item::Location_OnRight);
root->insertItem(item6, Item::Location_OnRight);
ItemContainer *c = item5->parentContainer();
auto separator = c->separators()[0];
const int available5 = item5->availableLength(Qt::Horizontal);
// Separator squeezes item5 and starts squeezing item6 by 10px
c->requestSeparatorMove(separator, available5 + 10);
}
int main(int argc, char *argv[])
{
bool qpaPassed = false;