diff options
Diffstat (limited to 'Swift/QtUI/Trellis')
-rw-r--r-- | Swift/QtUI/Trellis/QtDynamicGridLayout.cpp | 60 | ||||
-rw-r--r-- | Swift/QtUI/Trellis/QtDynamicGridLayout.h | 3 |
2 files changed, 55 insertions, 8 deletions
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp index cc3208b..e2b6e27 100644 --- a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp +++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp @@ -10,18 +10,20 @@ #include <QApplication> #include <QEvent> -#include <QLayoutItem> #include <QGridLayout> +#include <QLayoutItem> #include <QtDebug> +#include <Swiften/Base/Log.h> + #include <Swift/QtUI/QtSwiftUtil.h> -#include <Swift/QtUI/QtTabbable.h> #include <Swift/QtUI/QtTabWidget.h> +#include <Swift/QtUI/QtTabbable.h> #include <Swift/QtUI/Trellis/QtDNDTabBar.h> namespace Swift { -QtDynamicGridLayout::QtDynamicGridLayout(QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND) { +QtDynamicGridLayout::QtDynamicGridLayout(QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND), movingTab_(NULL) { gridLayout_ = new QGridLayout(this); setContentsMargins(0,0,0,0); setDimensions(QSize(1,1)); @@ -107,6 +109,10 @@ int QtDynamicGridLayout::indexOf(const QWidget* widget) const { } void QtDynamicGridLayout::handleApplicationFocusChanged(QWidget*, QWidget* newFocus) { + if (movingTab_) { + return; + } + if (newFocus) { if (isAncestorOf(newFocus)) { QtTabbable *newTab = dynamic_cast<QtTabbable*>(newFocus->parentWidget()); @@ -142,6 +148,29 @@ void QtDynamicGridLayout::removeTab(int index) { } } +/** + * This event filter serves the purpose of filtering out all QEvent::Show events targeted at + * all widgets excepts the currently moving widget. + * It is required because of the way Qt internally implements the QTabBar::moveTab method. + * It does not move the actual tab in the underlying structure, but instead removes it from + * a stacked layout and later adds it again. + * Both the remove and insert produce a lot signal emission and focus changes. Most of which + * the application MUST NOT react on because of the QTabBar and the corresponding QTabWidget + * being out of sync in an inconsistent state. + */ +bool QtDynamicGridLayout::eventFilter(QObject* object, QEvent* event) { + QtTabbable* tab = qobject_cast<QtTabbable*>(object); + if (!tab) { + return false; + } + if (tab && (tab != movingTab_)) { + if (event->type() == QEvent::Show) { + return true; + } + } + return false; +} + QWidget* QtDynamicGridLayout::currentWidget() const { QWidget* current = NULL; current = focusWidget(); @@ -394,6 +423,10 @@ void QtDynamicGridLayout::handleTabCloseRequested(int index) { } void QtDynamicGridLayout::handleTabCurrentChanged(int index) { + if (movingTab_) { + return; + } + if (index >= 0) { QTabWidget* sendingTabWidget = dynamic_cast<QTabWidget*>(sender()); assert(sendingTabWidget); @@ -417,14 +450,25 @@ void QtDynamicGridLayout::updateTabPositions() { } void QtDynamicGridLayout::moveTab(QtTabWidget* tabWidget, int oldIndex, int newIndex) { - tabWidget->widget(oldIndex)->blockSignals(true); - tabWidget->widget(newIndex)->blockSignals(true); #if QT_VERSION >= 0x040500 - tabWidget->tabBar()->moveTab(oldIndex, newIndex); + SWIFT_LOG_ASSERT(movingTab_ == NULL, error) << std::endl; + movingTab_ = qobject_cast<QtTabbable*>(tabWidget->widget(oldIndex)); + SWIFT_LOG_ASSERT(movingTab_ != NULL, error) << std::endl; + + if (movingTab_) { + // Install event filter that filters out events issued during the internal movement of the + // tab but not targeted at the moving tab. + qApp->installEventFilter(this); + + tabWidget->tabBar()->moveTab(oldIndex, newIndex); + + qApp->removeEventFilter(this); + SWIFT_LOG_ASSERT(movingTab_ == tabWidget->widget(newIndex), error) << std::endl; + } + movingTab_ = NULL; + tabWidget->widget(newIndex)->setFocus(); #else #warning Qt 4.5 or later is needed. Trying anyway, some things will be disabled. - tabWidget->widget(oldIndex)->blockSignals(false); - tabWidget->widget(newIndex)->blockSignals(false); #endif } diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.h b/Swift/QtUI/Trellis/QtDynamicGridLayout.h index 616ee5e..ed8a9fc 100644 --- a/Swift/QtUI/Trellis/QtDynamicGridLayout.h +++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.h @@ -45,6 +45,8 @@ namespace Swift { QHash<QString, QPoint> getTabPositions() const; void setTabPositions(const QHash<QString, QPoint> positions); + bool eventFilter(QObject* object, QEvent* event); + signals: void tabCloseRequested(int index); void onCurrentIndexChanged(int newIndex); @@ -73,5 +75,6 @@ namespace Swift { QGridLayout *gridLayout_; bool dndEnabled_; QHash<QString, QPoint> tabPositions_; + QtTabbable* movingTab_; }; } |