From 274afe71968739b3387d0250baa59845e912e0c0 Mon Sep 17 00:00:00 2001 From: Prasanth Ullattil Date: Thu, 17 Dec 2009 10:20:03 +0100 Subject: Stack overflow when closing a Color panel in Cocoa. The QCocoaColorPanelDelegate was going into an infinite recrusion in this particular case. The patch guards the delegate from calling accept() or reject() more than once. Task-number: QTBUG-6636 Reviewed-by: Richard Moe Gustavsen --- src/gui/dialogs/qcolordialog_mac.mm | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm index 53d2e1e..5753954 100644 --- a/src/gui/dialogs/qcolordialog_mac.mm +++ b/src/gui/dialogs/qcolordialog_mac.mm @@ -79,6 +79,7 @@ QT_USE_NAMESPACE BOOL mHackedPanel; NSInteger mResultCode; BOOL mDialogIsExecuting; + BOOL mResultSet; } - (id)initWithColorPanel:(NSColorPanel *)panel stolenContentView:(NSView *)stolenContentView @@ -116,6 +117,7 @@ QT_USE_NAMESPACE mHackedPanel = (okButton != 0); mResultCode = NSCancelButton; mDialogIsExecuting = false; + mResultSet = false; if (mHackedPanel) { [self relayout]; @@ -159,11 +161,13 @@ QT_USE_NAMESPACE - (BOOL)windowShouldClose:(id)window { Q_UNUSED(window); - if (mHackedPanel) { - [self onCancelClicked]; - } else { + if (!mHackedPanel) [self updateQtColor]; + if (mDialogIsExecuting) { [self finishOffWithCode:NSCancelButton]; + } else { + mResultSet = true; + mPriv->colorDialog()->reject(); } return true; } @@ -240,11 +244,12 @@ QT_USE_NAMESPACE - (void)onCancelClicked { - Q_ASSERT(mHackedPanel); - [[mStolenContentView window] close]; - delete mQtColor; - mQtColor = new QColor(); - [self finishOffWithCode:NSCancelButton]; + if (mHackedPanel) { + [[mStolenContentView window] close]; + delete mQtColor; + mQtColor = new QColor(); + [self finishOffWithCode:NSCancelButton]; + } } - (void)updateQtColor @@ -306,10 +311,16 @@ QT_USE_NAMESPACE } else { // Since we are not in a modal event loop, we can safely close // down QColorDialog - if (mResultCode == NSCancelButton) - mPriv->colorDialog()->reject(); - else - mPriv->colorDialog()->accept(); + // Calling accept() or reject() can in turn call closeCocoaColorPanel. + // This check will prevent any such recursion. + if (!mResultSet) { + mResultSet = true; + if (mResultCode == NSCancelButton) { + mPriv->colorDialog()->reject(); + } else { + mPriv->colorDialog()->accept(); + } + } } } -- cgit v0.12 From ea8d13b61097ec295721b1e6f2bf614d12253c8c Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 17 Dec 2009 13:17:21 +0100 Subject: doc: Added discussion on connecting signals that have default arg values. Task-number: QTBUG-3913 --- doc/src/objectmodel/signalsandslots.qdoc | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/src/objectmodel/signalsandslots.qdoc b/doc/src/objectmodel/signalsandslots.qdoc index 9515904..d5e3280 100644 --- a/doc/src/objectmodel/signalsandslots.qdoc +++ b/doc/src/objectmodel/signalsandslots.qdoc @@ -376,6 +376,45 @@ Some irrelevant member functions have been omitted from this example. + \section1 Signals And Slots With Default Arguments + + The signatures of signals and slots may contain arguments, and the + arguments can have defualt values. Consider QObject::destroyed(): + + \code + void destroyed(QObject* = 0); + \endcode + + When a QObject is deleted, it emits this QObject::destroyed() + signal. We want to catch this signal, wherever we might have a + dangling reference to the deleted QObject, so we can clean it up. + A suitable slot signature might be: + + \code + void objectDestroyed(QObject* obj = 0); + \endcode + + To connect the signal to the slot, we use QObject::connect() and + the \c{SIGNAL()} and \c{SLOT()} macros. The rule about whether to + include arguments or not in the \c{SIGNAL()} and \c{SLOT()} + macros, if the arguments have default values, is that the + signature passed to the \c{SIGNAL()} macro must \e not have fewer + arguments than the signature passed to the \c{SLOT()} macro. + + All of these would work: + \code + connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(Qbject*))); + connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed())); + connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed())); + \endcode + But this one won't work: + \code + connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed(QObject*))); + \endcode + + ...because the slot will be expecting a QObject that the signal + will not send. This connection will report a runtime error. + \section1 Advanced Signals and Slots Usage For cases where you may require information on the sender of the -- cgit v0.12