Trolltech Home | Qt4-preview-feedback Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt4-preview-feedback Archive, May 2007
Re: Update: Re: Crash: Qt4.3 bug


Message 1 in thread

Hello,
Le mercredi 02 mai 2007, David Faure a écrit :
> On Monday 30 April 2007, Kleag wrote:
> > I have no idea why it happens, particularly because I use only two
> > KToolBar that are never deleted.
>
> valgrind would tell ;)
Well, I tried before to use valgrind. It's right, It reported the error. But 
it wasn't very useful to me as it just printed out the same stack trace as 
gdb, deep inside the Qt control loop. As I don't now Qt internals enough, 
this does not give me valuable data.
I already posted a valgrind output previously in this thread, on april first 
and it wasn't a fish :-)

But I (finally!!) found the origin of the crash and, as Thiago asked, 
created "a small, self-contained testcase that illustrates the bug". The 
problem appears when I replace the central widget. It seems to be a 
regression from Qt4.1.3 which announced this bug as corrected.

The code below crashes:
*****************************
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QTimer>

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QMainWindow w;
    QPushButton* b1 = new QPushButton("Abc",&w);
    w.setCentralWidget(b1);
    w.show();
    QPushButton* b2 = new QPushButton("Def",&w);
    w.setCentralWidget(b2);

    return app.exec();
}
*****************************

Furthermore, as a direction to look at, the following diff allows the above 
program to work:

******************************
Index: qmainwindowlayout.cpp
===================================================================
--- qmainwindowlayout.cpp       (révision 660602)
+++ qmainwindowlayout.cpp       (copie de travail)
@@ -1561,17 +1561,17 @@

 void QMainWindowLayout::animationFinished(QWidget *widget)
 {
-#ifndef QT_NO_TOOLBAR
-    if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
-        QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
-        if (tbl->expanded && tbl->collapsing) {
-            tbl->expanded = false;
-            tbl->collapsing = false;
-            tbl->invalidate();
-            tb->update();
-        }
-    }
-#endif
+// #ifndef QT_NO_TOOLBAR
+//     if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
+//         QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
+//         if (tbl->expanded && tbl->collapsing) {
+//             tbl->expanded = false;
+//             tbl->collapsing = false;
+//             tbl->invalidate();
+//             tb->update();
+//         }
+//     }
+// #endif

     if (widget != pluggingWidget)
         return;
******************************

I hope this will allow the bug to be corrected.

Best regards,

Kleag
-- 
 [ signature omitted ] 

Message 2 in thread

Kleag wrote:

> The code below crashes:
> *****************************
> #include <QApplication>
> #include <QMainWindow>
> #include <QPushButton>
> #include <QTimer>
> 
> int main(int argc, char **argv)
> {
>     QApplication app(argc, argv);
> 
>     QMainWindow w;
>     QPushButton* b1 = new QPushButton("Abc",&w);
>     w.setCentralWidget(b1);
>     w.show();
>     QPushButton* b2 = new QPushButton("Def",&w);
>     w.setCentralWidget(b2);
> 
>     return app.exec();
> }

Ah, you nailed it. :)

Fixed for 4.3.0.

Jacek


--- gui/kernel/qapplication.h  2007/03/01 07:25:45.000000000
+++ gui/kernel/qapplication.h  2007/05/04 13:00:16.000000000

@@ -309,6 +309,7 @@
     friend class QETWidget;
     friend class Q3AccelManager;
     friend class QTranslator;
+    friend class QWidgetAnimator;
 #ifndef QT_NO_SHORTCUT
     friend class QShortcut;
 #endif


--- gui/widgets/qwidgetanimator.cpp  2007/03/14 13:40:28.000000000
+++ gui/widgets/qwidgetanimator.cpp  2007/05/04 13:00:16.000000000

@@ -16,6 +16,8 @@
 #include <QtGui/qwidget.h>
 #include <QtGui/qtextedit.h>
 #include <QtGui/private/qwidget_p.h>
+#include <QtGui/qapplication.h>
+#include <QtGui/private/qapplication_p.h>
 #include <qdebug.h>
 
 #include "qwidgetanimator_p.h"
@@ -63,6 +65,21 @@
 {
     QRect final_geometry = _final_geometry;
 
+    /* If QApplication::exec() hasn't been called yet, there is no point
trying to animate
+       anything. It won't work, since there are no timers, and it will
crash when the
+       finshed(QWidget*) signal is delivered through the qeued connection
to QMainWindowLayout,
+       if the widget is deleted before QApplication::exec() is called. This
happens when
+       you f.ex. call QMainWindow::setCentralWidget() twice before exec().
*/
+    if (qApp != 0 && !qApp->d_func()->in_exec) {
+        if (!final_geometry.isValid() && !widget->isWindow()) {
+            // Make the wigdet go away by sending it to negative space
+            QSize s = widget->size();
+            final_geometry = QRect(-500 - s.width(), -500 - s.height(),
s.width(), s.height());
+        }
+        widget->setGeometry(final_geometry);
+        return;
+    }
+
     QRect r = widget->geometry();
     if (r.right() < 0 || r.bottom() < 0)
         r = QRect();
@@ -70,9 +87,6 @@
     if (r.isNull() || final_geometry.isNull())
         animate = false;
 
-//    if (r != final_geometry)
-//        qDebug() << "QWidgetAnimator::animate():" << widget << r <<
_final_geometry;
-
     AnimationMap::const_iterator it = m_animation_map.constFind(widget);
     if (it == m_animation_map.constEnd()) {
         if (r == final_geometry) {

To unsubscribe - send "unsubscribe" in the subject to qt4-preview-feedback-request@xxxxxxxxxxxxx