From d43037d3cc7f273a7d23ac1162a7498a4230c359 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 5 May 2010 11:58:33 +0200 Subject: Fixes a crash when unregistering a recognizer. Another fix for the same problem - we also need to be careful - when ungrabbing a gesture for the recognizer that has already been destroyed and cleaning up the QGesture object for it we need to make sure we know it is removed from the obsolete gestures list so that we won't delete it again in the QGestureManager detructor. Task-number: QTBUG-9801 Reviewed-by: Thomas Zander --- src/gui/graphicsview/qgraphicsitem.cpp | 7 +++++++ src/gui/kernel/qgesturemanager.cpp | 16 ++++++++++++---- src/gui/kernel/qgesturemanager_p.h | 2 +- src/gui/kernel/qwidget.cpp | 3 +++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 326f130..7fcf4d2 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1423,6 +1423,13 @@ QGraphicsItem::~QGraphicsItem() d_ptr->inDestructor = 1; d_ptr->removeExtraItemCache(); + if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) { + QGraphicsObject *o = static_cast(this); + QGestureManager *manager = QGestureManager::instance(); + foreach (Qt::GestureType type, d_ptr->gestureContext.keys()) + manager->cleanupCachedGestures(o, type); + } + clearFocus(); // Update focus scope item ptr. diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index a806629..6ce7667 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -140,9 +140,10 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) ObjectGesture objectGesture = iter.key(); if (objectGesture.gesture == type) { foreach (QGesture *g, iter.value()) { - QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g); - m_gestureToRecognizer.remove(g); - m_obsoleteGestures[recognizer].append(g); + if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g)) { + m_gestureToRecognizer.remove(g); + m_obsoleteGestures[recognizer].insert(g); + } } } ++iter; @@ -155,7 +156,14 @@ void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType typ while (iter != m_objectGestures.end()) { ObjectGesture objectGesture = iter.key(); if (objectGesture.gesture == type && target == objectGesture.object.data()) { - qDeleteAll(iter.value()); + QSet gestures = iter.value().toSet(); + for (QHash >::iterator + it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { + it.value() -= gestures; + } + foreach (QGesture *g, gestures) + m_deletedRecognizers.remove(g); + qDeleteAll(gestures); iter = m_objectGestures.erase(iter); } else { ++iter; diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index a0ff83f..c105c9b 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -127,7 +127,7 @@ private: int m_lastCustomGestureId; - QHash > m_obsoleteGestures; + QHash > m_obsoleteGestures; QHash m_deletedRecognizers; void cleanupGesturesForRemovedRecognizer(QGesture *gesture); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 20d1d30..0334d47 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1388,6 +1388,9 @@ QWidget::~QWidget() qWarning("QWidget: %s (%s) deleted while being painted", className(), name()); #endif + foreach (Qt::GestureType type, d->gestureContext.keys()) + ungrabGesture(type); + // force acceptDrops false before winId is destroyed. d->registerDropSite(false); -- cgit v0.12