problem with KToggleToolBarAction (+patch)

Simon Hausmann hausmann at kde.org
Fri Oct 25 19:34:52 BST 2002


Hi,

it looks like some things changed in Qt. It looks like hiding a widget using
hide() will cause hide events to be sent to child widgets, too. Sounds like it
makes sense. In case of an explicit hide() call QDockWindow emits the
visibilityChanged signal. KToggleToolBarAction connects that signal to the
setChecked slot. This connection (or the setChecked implementation) causes the
following problem:

When shutting down Konqueror, KonqMainWindow's closeEvent does an
explicit hide(). This causes a visibilityChanged( false ) signal
emission for all toolbars and therefore causes setChecked( false )
to get called. Backtrace for reference:

#0  QToolBar::hide() (this=0x81521d8) at widgets/qtoolbar.cpp:472
#1  0x4057c20f in KToolBar::hide() (this=0x81521d8) at ../../../src/kdelibs/kdeui/ktoolbar.cpp:1329
#2  0x4055ebfb in KToggleToolBarAction::setChecked(bool) (this=0x8137570, c=false) at ../../../src/kdelibs/kdeui/kaction.cpp:2907
#3  0x40567f06 in KToggleToolBarAction::qt_invoke(int, QUObject*) (this=0x8137570, _id=135492976, _o=0xbfffe970) at /build/src/qt-copy/include/private/qucom_p.h:369
#4  0x40c28a3e in QObject::activate_signal(QConnectionList*, QUObject*) (this=0x81521d8, clist=0x8179d88, o=0xbfffe970) at kernel/qobject.cpp:2217
#5  0x40c28e7b in QObject::activate_signal_bool(int, bool) (this=0x81521d8, signal=4, param=false) at kernel/qobject.cpp:2265
#6  0x40f2ec9f in QDockWindow::visibilityChanged(bool) (this=0x81521d8, t0=false) at .moc/debug-shared-mt/moc_qdockwindow.cpp:179
#7  0x40cccdde in QDockWindow::hideEvent(QHideEvent*) (this=0x81521d8, e=0xbfffece0) at widgets/qdockwindow.cpp:1803
#8  0x40c5ffe1 in QWidget::event(QEvent*) (this=0x81521d8, e=0xbfffece0) at kernel/qwidget.cpp:4463
#9  0x40ccd2d4 in QDockWindow::event(QEvent*) (this=0x81521d8, e=0xbfffece0) at widgets/qdockwindow.cpp:1914
#10 0x40d5124c in QToolBar::event(QEvent*) (this=0x81521d8, e=0xbfffece0) at widgets/qtoolbar.cpp:523
#11 0x4057d729 in KToolBar::event(QEvent*) (this=0x8137570, e=0x8137570) at ../../../src/kdelibs/kdeui/ktoolbar.cpp:1608
#12 0x40bc215b in QApplication::internalNotify(QObject*, QEvent*) (this=0xbffff710, receiver=0x81521d8, e=0xbfffece0) at kernel/qapplication.cpp:2288
#13 0x40bc1e3c in QApplication::notify(QObject*, QEvent*) (this=0xbffff710, receiver=0x81521d8, e=0xbfffece0) at kernel/qapplication.cpp:2211
#14 0x4076ff89 in KApplication::notify(QObject*, QEvent*) (this=0x81521d8, receiver=0x81521d8, event=0xbfffece0) at ../../../src/kdelibs/kdecore/kapplication.cpp:440
#15 0x40b76064 in QApplication::sendEvent(QObject*, QEvent*) (receiver=0x81521d8, event=0xbfffece0) at kernel/qapplication.h:477
#16 0x40c5ef2b in QWidget::hideChildren(bool) (this=0x80b3448, spontaneous=false) at kernel/qwidget.cpp:3818
#17 0x40c5eef4 in QWidget::hideChildren(bool) (this=0x80a1e60, spontaneous=false) at kernel/qwidget.cpp:3813
#18 0x40c5ebf8 in QWidget::hide() (this=0x80a1e60) at kernel/qwidget.cpp:3742
#19 0x40d10126 in QMainWindow::hide() (this=0x80a1e60) at widgets/qmainwindow.cpp:1500
#20 0x400772ac in KonqMainWindow::closeEvent(QCloseEvent*) (this=0x80a1e60, e=0xbffff1d0) at ../../../src/kdebase/konqueror/konq_mainwindow.cc:3962

KToggleToolBarAction's setChecked method calls show()/hide() on the toolbar,
hide() in this case. Later on when KMainWindow calls saveSettings on each
Toolbar isHidden() will return true and Hidde=true will be saved in
konquerorrc, causing all toolbars to be hidden the next time Konqueror gets
started.

To solutions come to my mind (patches for both attached) :

1) We could make setChecked less intelligent. I guess the original idea behind
the current setChecked implementation was to make things easier for developers
calling setChecked explicitly. To still update the toolbar visibility status
when the user activates the corresponding 'Show Foo Toolbar' menu item we could
simply call setShown() on the toolbar in slotActivated() . This solution is
implemented in kaction2_patch.txt

2) The other solution is to connect the visibilityChanged signal to a new slot,
one that just calls KToggleAction::setChecked, not causing a show()/hide() on
the toolbar.

Solution 1 could possibly break third-party apps that rely on setChecked
basically causing the activation on the action (-> showing/hiding the toolbar)
. Solution 2 on the other hand I dislike design wise :)

Any opinions?

Simon
-------------- next part --------------
Index: kaction.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kaction.cpp,v
retrieving revision 1.296
diff -u -p -b -r1.296 kaction.cpp
--- kaction.cpp	2002/10/24 17:51:01	1.296
+++ kaction.cpp	2002/10/25 18:17:25
@@ -2897,16 +2897,18 @@ int KToggleToolBarAction::plug( QWidget*
 void KToggleToolBarAction::setChecked( bool c )
 {
   if( m_toolBar && c != m_toolBar->isVisible() ) {
-    if( c ) {
-      m_toolBar->show();
-    } else {
-      m_toolBar->hide();
-    }
     QMainWindow* mw = m_toolBar->mainWindow();
     if ( mw && mw->inherits( "KMainWindow" ) )
       static_cast<KMainWindow *>( mw )->setSettingsDirty();
   }
   KToggleAction::setChecked( c );
+}
+
+void KToggleToolBarAction::slotActivated()
+{
+  KToggleAction::slotActivated();
+  if ( m_toolBar )
+    m_toolBar->setShown( isChecked() );
 }
 
 ////////
Index: kaction.h
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kaction.h,v
retrieving revision 1.166
diff -u -p -b -r1.166 kaction.h
--- kaction.h	2002/10/07 15:06:34	1.166
+++ kaction.h	2002/10/25 18:17:26
@@ -1682,6 +1682,9 @@ public:
 public slots:
     virtual void setChecked( bool );
 
+protected slots:
+    virtual void slotActivated();
+
 private:
     QCString               m_toolBarName;
     QGuardedPtr<KToolBar>  m_toolBar;
-------------- next part --------------
Index: kaction.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kaction.cpp,v
retrieving revision 1.296
diff -u -p -b -r1.296 kaction.cpp
--- kaction.cpp	2002/10/24 17:51:01	1.296
+++ kaction.cpp	2002/10/25 18:06:52
@@ -2884,7 +2884,7 @@ int KToggleToolBarAction::plug( QWidget*
 
   if( m_toolBar ) {
     setChecked( m_toolBar->isVisible() );
-    connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(setChecked(bool)) );
+    connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(toolBarVisibilityChanged(bool)) );
     // Also emit toggled when the toolbar's visibility changes (see comment in header)
     connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SIGNAL(toggled(bool)) );
   } else {
@@ -2907,6 +2907,13 @@ void KToggleToolBarAction::setChecked( b
       static_cast<KMainWindow *>( mw )->setSettingsDirty();
   }
   KToggleAction::setChecked( c );
+}
+
+void KToggleToolBarAction::toolBarVisibilityChanged( bool visible )
+{
+    // update the action's status but don't explicitly call show/hide
+    // on the toolbar
+    KToggleAction::setChecked( visible );
 }
 
 ////////
Index: kaction.h
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kaction.h,v
retrieving revision 1.166
diff -u -p -b -r1.166 kaction.h
--- kaction.h	2002/10/07 15:06:34	1.166
+++ kaction.h	2002/10/25 18:06:53
@@ -1687,6 +1687,9 @@ private:
     QGuardedPtr<KToolBar>  m_toolBar;
 protected:
     virtual void virtual_hook( int id, void* data );
+private slots:
+    void toolBarVisibilityChanged( bool visible );
+
 private:
     class KToggleToolBarActionPrivate;
     KToggleToolBarActionPrivate *d;


More information about the kde-core-devel mailing list