From 15d1f20836d4246f3d5a4eafbeb5095d4c4ba7bc Mon Sep 17 00:00:00 2001 From: Tobias Markmann <tm@ayena.de> Date: Wed, 10 Aug 2016 12:43:01 +0100 Subject: Fix crash during trellis size change on Windows Due to Windows focus handling, the handleApplicationFocusChanged method was called during the relayout process while the dynamic grid layout is not in a consistent state. With this change a call to handleApplicationFocusChanged will just be ignored during the relayout process when changing the layout. Now it also remembers the current active widget in the layout and activates it after the relayouting is done. Test-Information: The crash happened in a scenario where you had a few rows and columns and with many tabs randomly distributed, leaving some trellis cells without a widget. When changing back to a 1x1 grid in this situation it sometimes crashed. Now it does not anymore. Tested on Windows 8 with Qt 5.4.2. Change-Id: I829bac2ba050cf320e15ab48b49bbb9606a82831 diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp index cafecf9..3d80d95 100644 --- a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp +++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp @@ -70,7 +70,7 @@ QWidget* QtDynamicGridLayout::widget(int index) const { for (int y = 0; y < gridLayout_->rowCount(); y++) { for (int x = 0; x < gridLayout_->columnCount(); x++) { QLayoutItem* layoutItem = gridLayout_->itemAtPosition(y, x); - QtTabWidget* tabWidget = dynamic_cast<QtTabWidget*>(layoutItem->widget()); + QtTabWidget* tabWidget = dynamic_cast<QtTabWidget*>(layoutItem ? layoutItem->widget() : nullptr); if (tabWidget) { if (index < tabWidget->count()) { widgetAtIndex = tabWidget->widget(index); @@ -108,7 +108,7 @@ int QtDynamicGridLayout::indexOf(const QWidget* widget) const { } void QtDynamicGridLayout::handleApplicationFocusChanged(QWidget*, QWidget* newFocus) { - if (movingTab_) { + if (movingTab_ || resizing_) { return; } @@ -188,14 +188,16 @@ QWidget* QtDynamicGridLayout::currentWidget() const { } void QtDynamicGridLayout::setCurrentWidget(QWidget* widget) { - for (int y = 0; y < gridLayout_->rowCount(); y++) { - for (int x = 0; x < gridLayout_->columnCount(); x++) { - QLayoutItem* layoutItem = gridLayout_->itemAtPosition(y, x); - QtTabWidget* tabWidget = dynamic_cast<QtTabWidget*>(layoutItem->widget()); - if (tabWidget) { - for (int n = 0; n < tabWidget->count(); n++) { - if (tabWidget->widget(n) == widget) { - tabWidget->setCurrentWidget(widget); + if (widget) { + for (int y = 0; y < gridLayout_->rowCount(); y++) { + for (int x = 0; x < gridLayout_->columnCount(); x++) { + QLayoutItem* layoutItem = gridLayout_->itemAtPosition(y, x); + QtTabWidget* tabWidget = dynamic_cast<QtTabWidget*>(layoutItem->widget()); + if (tabWidget) { + for (int n = 0; n < tabWidget->count(); n++) { + if (tabWidget->widget(n) == widget) { + tabWidget->setCurrentWidget(widget); + } } } } @@ -245,11 +247,14 @@ QSize QtDynamicGridLayout::getDimension() const { } void QtDynamicGridLayout::setDimensions(const QSize& dim) { + resizing_ = true; assert(dim.width() > 0 && dim.height() > 0); setUpdatesEnabled(false); + QWidget* restoredWidget = currentWidget(); + QGridLayout* oldLayout = dynamic_cast<QGridLayout*>(layout()); - QGridLayout* newLayout = new QGridLayout; + QGridLayout* newLayout = new QGridLayout(this); newLayout->setSpacing(4); newLayout->setContentsMargins(0,0,0,0); @@ -310,6 +315,9 @@ void QtDynamicGridLayout::setDimensions(const QSize& dim) { delete layout(); setLayout(newLayout); gridLayout_ = newLayout; + + resizing_ = false; + setCurrentWidget(restoredWidget); } void QtDynamicGridLayout::moveCurrentTabRight() { diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.h b/Swift/QtUI/Trellis/QtDynamicGridLayout.h index dad0f7e..4aed0df 100644 --- a/Swift/QtUI/Trellis/QtDynamicGridLayout.h +++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.h @@ -76,5 +76,6 @@ namespace Swift { bool dndEnabled_; QHash<QString, QPoint> tabPositions_; QtTabbable* movingTab_; + bool resizing_ = false; }; } -- cgit v0.10.2-6-g49f6