proposal for redesign of toolbar menu feature in kdeui

Simon Hausmann hausmann at kde.org
Tue Jul 2 11:30:58 BST 2002


Hi,

kdeui (in particular KMainWindow) has this feature that allows
applications to have a menu / menu item (depending on the number of
toolbars) that allows showing/hiding all toolbars automatically.

To be honest: I don't like the current implementation, design wise.

It resulted in a lot of ugly hacks -- see latest kstdaction patch
for example, self unplugging/plugging in KToolBarMenuAction or the
hooks for the toolbar creation -- and it caused unnecessary
additions to the public kdeui API (setMainCollectionFor for example
; what does that name mean btw?) . And in addition it works only
with toolbars created by the xmlgui framework.

I wrote a new implementation of that feature. To the user there is
no visible change. The the developer there is a change: The feature
is off by default. (however the change itself is no problem as it is
a feature that is new in 3.1/HEAD) . Otherwise it tries to address
the deficencies of the current implementation.

There are two reasons why I think it should be off by default:

- it caused really ugly hacks to maintain backwards compatibility

- Other kmainwindow features like the autoSaveSettings feature are
  off by default, too. Too much auto-magic usually causes more
  confusion to developers that it helps IMHO. Also it having it on
  increases default memory usage (and not every application uses it).

Much like the autoSaveSettings feature I added a method that makes
turning on the feature easy:

void KMainWindow::setStandardToolBarMenuEnabled( bool enable );

(I'm open for suggestions for a better name, of course :)

Applications that do not use ui_standards.rc require an additional
small change in their .rc file. I explained that in the
documentation to the method.

I attached three patches: One holding the actual diff for kdeui and
two for kate/konqueror (both not using ui_standards.rc, illustrating
the changes necessary) .

Any opinions which implementation we should have in kdeui?


Simon
-------------- next part --------------
Index: Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/kdeui/Makefile.am,v
retrieving revision 1.276
diff -u -p -r1.276 Makefile.am
--- Makefile.am	2002/06/27 11:23:31	1.276
+++ Makefile.am	2002/07/02 10:07:14
@@ -99,7 +99,8 @@ libkdeui_la_SOURCES = \
 		kdatewidget.cpp karrowbutton.cpp kmainwindowiface.cpp \
                 kmainwindowiface.skel kguiitem.cpp kstdguiitem.cpp \
 		kstringvalidator.cpp kactivelabel.cpp kaccelmanager.cpp \
-		kwindowinfo.cpp ktextedit.cpp kwizard.cpp kpassivepopup.cpp
+		kwindowinfo.cpp ktextedit.cpp kwizard.cpp kpassivepopup.cpp \
+		ktoolbarhandler.cpp
 
 noinst_HEADERS = kdockwidget_private.h klistviewlineedit.h \
 		kdialogbase_priv.h kaboutdialog_private.h kcursor_private.h \
Index: kaction.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kaction.cpp,v
retrieving revision 1.281
diff -u -p -r1.281 kaction.cpp
--- kaction.cpp	2002/07/02 09:53:46	1.281
+++ kaction.cpp	2002/07/02 10:07:16
@@ -2723,176 +2723,6 @@ int KActionMenu::plug( QWidget* widget, 
 
 ////////
 
-
-class KToolBarMenuAction::KToolBarMenuActionPrivate
-{
-	public:
-	KMainWindow *window;
-	QMap<KToolBar*,	KToggleToolBarAction*> toolbarActionMap;
-        KPopupMenu *popup;
-
-};
-
-class KToolBarMenuAction::NullItem: public QCustomMenuItem
-{
-public:
-	NullItem():QCustomMenuItem(){;}
-	virtual ~NullItem(){;}
-	virtual QSize sizeHint(){return QSize(0,0);}
-	virtual	void paint ( QPainter * /*p*/, const QColorGroup & /*cg*/, bool /*act*/, bool /*enabled*/, int /*x*/, int /*y*/, int /*w*/, int /*h*/ ) {
-		return;
-	}
-};
-
-KToolBarMenuAction::KToolBarMenuAction( KMainWindow* parent,
-                 const char* name):KAction(parent->actionCollection(),name)
-{
-	d=new KToolBarMenuActionPrivate;
-	d->window=parent;
-        d->popup = new KPopupMenu(parent,"KToolBarMenuAction::KToolBarMenuAction");
-}
-
-KToolBarMenuAction::~KToolBarMenuAction()
-{
-	delete d;
- 	d=0;
-}   
-
-void KToolBarMenuAction::clear()
-{
-	d->popup->clear();
-	for (QMap<KToolBar*,KToggleToolBarAction*>::iterator it=d->toolbarActionMap.begin();it!=d->toolbarActionMap.end();++it)
-	{
-		delete it.data();
-	}
-	d->toolbarActionMap.clear();
-}
-
-void KToolBarMenuAction::addToolbar(KToolBar *bar)
-{
-	uint oldcount=d->toolbarActionMap.count();
-	KToggleToolBarAction *act;
-	d->toolbarActionMap.insert(bar,act=new KToggleToolBarAction(
-                bar->name(), i18n("Show %1").arg(bar->label()),
-                0, 0));
-	connect(act,SIGNAL(activated()),this,SLOT(slotActivated()));
-	if (oldcount==0)
-	{
-		setText(i18n("Show %1").arg(d->toolbarActionMap.begin().key()->label()));
-		connect(act,SIGNAL(toggled(bool)),this,SLOT(singleBarToggled(bool)));
-		act->plug(d->popup);
-		for (int i=0;i<containerCount();i++)
-		{
-		  	if ( container(i)->inherits("QPopupMenu") )
-			{
-
-				QPopupMenu *menu=static_cast<QPopupMenu*>(container(i));
-				int id=itemId(i);
-				int pos=menu->indexOf(id);
-				unplug(menu);
-				plug(menu,pos);
-//				menu->removeItem(id);  I don't know why that doesn't work
-//				menu->insertItem(text(),d->popup,id,pos);		I don't know why that doesn't work
-			}
-		}
-	}
-	else if (oldcount==1)
-	{
-		setText(i18n("Toolbars"));
-		act->plug(d->popup);
-		for (int i=0;i<containerCount();i++)
-		{
-		  	if ( container(i)->inherits("QPopupMenu") )
-			{
-
-				QPopupMenu *menu=static_cast<QPopupMenu*>(container(i));
-				int id=itemId(i);
-				int pos=menu->indexOf(id);
-				unplug(menu);
-				plug(menu,pos);
-//				menu->removeItem(id);  I don't know why that doesn't work
-//				menu->insertItem(text(),d->popup,id,pos);		I don't know why that doesn't work
-			}
-		}
-
-	}
-	else
-	{
-		act->plug(d->popup);
-	}
-}
-
-void KToolBarMenuAction::removeToolbar(KToolBar * /*bar*/)
-{
-//	d->toolbarActionMap.remove(bar);
-
-}
-
-int KToolBarMenuAction::plug( QWidget* widget, int index )
-{
-//  return KAction::plug(widget,index);
-  if (kapp && !kapp->authorizeKAction(name()))
-    return -1;
-  kdDebug(129) << "KAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis
-  if ( widget->inherits("QPopupMenu") )
-  {
-    QPopupMenu* menu = static_cast<QPopupMenu*>( widget );
-    int id;
-      if (d->toolbarActionMap.count()>1)
-	      id = menu->insertItem( text(), d->popup, -1, index );
-	else 
-	if (d->toolbarActionMap.count()==1)
-	{
-		id=menu->insertItem(text(),-1,index);
-		menu->setItemChecked(id,d->toolbarActionMap.begin().data()->isChecked());
-		menu->connectItem(id,d->toolbarActionMap.begin().data(),SLOT(slotActivated()));
-		
-	}
-	else 
-	{
-		id=menu->insertItem(new KToolBarMenuAction::NullItem(),-1,index);
-//		id=menu->insertItem(text(),-1,index);
-		menu->setItemEnabled(id,false);
-	}
-
-    if ( !isEnabled() )
-        menu->setItemEnabled( id, false );
-
-    addContainer( menu, id );
-    connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
-
-    return containerCount() - 1;
-  } else return -1;
-}
-
-
-void KToolBarMenuAction::singleBarToggled(bool)
-{
-	if (d->toolbarActionMap.count()==1)
-	{
-		bool checked=d->toolbarActionMap.begin().data()->isChecked();
-                for (int i=0;i<containerCount();i++)
-                {
-                        if ( container(i)->inherits("QPopupMenu") )
-                        {
-
-                                QPopupMenu *menu=static_cast<QPopupMenu*>(container(i));
-                                int id=itemId(i);
-				menu->setItemChecked(id,checked);
-                        }
-                }
-	
-	}
-	
-}
-
-void KToolBarMenuAction::slotActivated()
-{
-	emit activated();
-}
-
-////////
-
 KToolBarPopupAction::KToolBarPopupAction( const QString& text,
                                           const QString& icon,
                                           const KShortcut& cut,
@@ -3197,7 +3027,6 @@ public:
     m_highlight = false;
     m_currentHighlightAction = 0;
     m_statusCleared = true;
-    m_mw=0;
   }
 
   KInstance *m_instance;
@@ -3218,7 +3047,6 @@ public:
   bool m_highlight;
   KAction *m_currentHighlightAction;
   bool m_statusCleared;
-  KMainWindow *m_mw;
 };
 
 KActionCollection::KActionCollection( QWidget *parent, const char *name,
@@ -3283,10 +3111,6 @@ KActionCollection::~KActionCollection()
   delete d->m_builderKAccel;
   delete d; d = 0;
 }
-
-void KActionCollection::setMainActionCollectionFor(KMainWindow *w){d->m_mw=w;}
-KMainWindow *KActionCollection::mainActionCollectionFor(){return d->m_mw;}
-
 
 void KActionCollection::setWidget( QWidget* w )
 {
Index: kaction.h
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kaction.h,v
retrieving revision 1.156
diff -u -p -r1.156 kaction.h
--- kaction.h	2002/07/01 08:13:46	1.156
+++ kaction.h	2002/07/02 10:07:18
@@ -1487,36 +1487,7 @@ private:
     KActionMenuPrivate *d;
 };
 
-
 /**
- Automatically handle toolbars created by the xmlgui framework
- */
-
-class KToolBarMenuAction: public KAction
-{
-    Q_OBJECT
-public:
-    KToolBarMenuAction( KMainWindow* parent = 0,
-                 const char* name = 0 );
-    virtual ~KToolBarMenuAction();
-    void addToolbar(KToolBar *bar);
-    void removeToolbar(KToolBar *bar);
-    void clear();
-    virtual int plug( QWidget* widget, int index =-1);
-
-    class NullItem;
-
-private:
-    class KToolBarMenuActionPrivate;
-    KToolBarMenuActionPrivate *d;
-protected slots:
-    virtual void slotActivated();
-    void singleBarToggled(bool);
-
-};
-
-
-/**
  * This action is a normal action everywhere, except in a toolbar
  * where it also has a popupmenu (optionnally delayed). This action is designed
  * for history actions (back/forward, undo/redo) and for any other action
@@ -1909,12 +1880,6 @@ protected:
 private:
     class KActionCollectionPrivate;
     KActionCollectionPrivate *d;
-
-protected:
-	friend class KMainWindow;
-	void setMainActionCollectionFor(KMainWindow *);
-public:
-	KMainWindow *mainActionCollectionFor();
 };
 
 #endif
Index: kmainwindow.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kmainwindow.cpp,v
retrieving revision 1.78
diff -u -p -r1.78 kmainwindow.cpp
--- kmainwindow.cpp	2002/06/30 18:33:18	1.78
+++ kmainwindow.cpp	2002/07/02 10:07:19
@@ -24,6 +24,7 @@
 
 #include "kmainwindow.h"
 #include "kmainwindowiface.h"
+#include "ktoolbarhandler.h"
 #include <qsessionmanager.h>
 #include <qobjectlist.h>
 #include <qstyle.h>
@@ -60,7 +61,7 @@ public:
     QString autoSaveGroup;
     KAccel * kaccel;
     KMainWindowInterface *m_interface;
-    KToolBarMenuAction *toolbarMenu;
+    KDEPrivate::ToolBarHandler *toolBarHandler;
 };
 
 QPtrList<KMainWindow>* KMainWindow::memberList = 0L;
@@ -154,31 +155,15 @@ static bool beeing_first = true;
 KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f )
     : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
 {
-    initKMainWindow(true,name);
+    initKMainWindow(name);
 }
 
-KMainWindow::KMainWindow( QWidget* parent, const char *name,WFlags f, bool createToolbarAction)
-    : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
-{
-    initKMainWindow(createToolbarAction,name);
-}
-
-void KMainWindow::removeToolBarMenuAction()
-{
-	delete d->toolbarMenu;
-	d->toolbarMenu=0;
-}
-
-void KMainWindow::initKMainWindow(bool createToolbarAction,const char *name)
+void KMainWindow::initKMainWindow(const char *name)
 {
-  if (createToolbarAction)
-    kdDebug(200) << "KMainWindow::init called with createToolbarAction=true"<< endl;
-
     setDockMenuEnabled( FALSE );
     mHelpMenu = 0;
     kapp->setTopWidget( this );
     actionCollection()->setWidget( this );
-    actionCollection()->setMainActionCollectionFor(this);
     connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
     if( !memberList )
         memberList = new QPtrList<KMainWindow>;
@@ -208,10 +193,7 @@ void KMainWindow::initKMainWindow(bool c
     d->autoSaveSettings = false;
     d->autoSaveWindowSize = true; // for compatibility
     d->kaccel = actionCollection()->kaccel();
-    if (createToolbarAction)
-    {
-       d->toolbarMenu=new KToolBarMenuAction(this,"options_show_toolbar");
-    } else d->toolbarMenu=0;
+    d->toolBarHandler = 0;
     if ((d->care_about_geometry = beeing_first)) {
         beeing_first = false;
         if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater
@@ -228,9 +210,12 @@ void KMainWindow::initKMainWindow(bool c
         setDockWindowsMovable(false);
 }
 
-KToolBarMenuAction *KMainWindow::toolBarMenuAction()
+KAction *KMainWindow::toolBarMenuAction()
 {
-	return d->toolbarMenu;
+    if ( !d->toolBarHandler )
+	return 0;
+
+    return d->toolBarHandler->toolBarMenuAction();
 }
 
 void KMainWindow::parseGeometry(bool parsewidth)
@@ -634,6 +619,33 @@ void KMainWindow::saveMainWindowSettings
     }
 }
 
+void KMainWindow::setStandardToolBarMenuEnabled( bool enable )
+{
+    if ( enable ) {
+	if ( d->toolBarHandler )
+	    return;
+
+	d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
+
+	if ( factory() ) 
+	    factory()->addClient( d->toolBarHandler );
+    } else {
+	if ( !d->toolBarHandler )
+	    return;
+
+	if ( factory() )
+	    factory()->removeClient( d->toolBarHandler );
+
+	delete d->toolBarHandler;
+	d->toolBarHandler = 0;
+    }
+}
+
+bool KMainWindow::isStandardToolBarMenuEnabled() const
+{
+    return ( d->toolBarHandler != 0 );
+}
+
 bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
 {
     if ( number == 1 )
@@ -725,13 +737,9 @@ void KMainWindow::finalizeGUI( bool forc
     // we call positionYourself again for each of them, but this time
     // the toolbariterator should give them in the proper order.
     // Both the XMLGUI and applySettings call this, hence "force" for the latter.
-    if (d->toolbarMenu) d->toolbarMenu->clear();
     QPtrListIterator<KToolBar> it( toolBarIterator() );
     for ( ; it.current() ; ++ it )
-        {
-            if (d->toolbarMenu) d->toolbarMenu->addToolbar(it.current());
             it.current()->positionYourself( force );
-        }
 
     d->settingsDirty = false;
 }
Index: kmainwindow.h
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kmainwindow.h,v
retrieving revision 1.52
diff -u -p -r1.52 kmainwindow.h
--- kmainwindow.h	2002/07/01 19:59:25	1.52
+++ kmainwindow.h	2002/07/02 10:07:20
@@ -121,17 +121,9 @@ public:
      *
      * KMainWindows must be created on the heap with 'new', like:
      *  <pre> KMainWindow *kmw = new KMainWindow (...</pre>
-     *
-     * This constructor automatically creates the "Show Toolbar" action
      **/
     KMainWindow( QWidget* parent = 0, const char *name = 0, WFlags f = WType_TopLevel | WDestructiveClose );
 
-    /*
-     * this constructor exists for BIC reasons. It allows specifying, if the "Show Toolbar" action should be created
-     * automatically. The default is going to be true in KDE 4
-     **/
-    KMainWindow( QWidget* parent, const char *name, WFlags f, bool createToolbarAction);
-
 
     /**
      * Destructor.
@@ -393,6 +385,31 @@ public:
      */
     void saveMainWindowSettings(KConfig *config, const QString &groupName = QString::null);
 
+    /**
+     * Sets whether KMainWindow should provide a menu that allows showing/hiding
+     * the available toolbars ( using @ref KToggleToolBarAction ) . In case there
+     * is only one toolbar configured a simple 'Show <toolbar name here>' menu item
+     * is shown.
+     *
+     * The menu / menu item is implemented using xmlgui. It will be inserted in your
+     * menu structure in the 'Settings' menu.
+     *
+     * If your application uses a non-standard xmlgui resource file then you can
+     * specify the exact position of the menu / menu item by adding a
+     * <Merge name="StandardToolBarMenuHandler" />
+     * line to the settings menu section of your resource file ( usually appname.rc ).
+     *
+     * Note that you should enable this feature before calling createGUI() ( or similar ) .
+     * You enable/disable it anytime if you pass false to the conserveMemory argument of createGUI.
+     */
+    void setStandardToolBarMenuEnabled( bool enable );
+    bool isStandardToolBarMenuEnabled() const;
+
+    /**
+     * Returns a pointer to the mainwindows action responsible for the toolbars menu
+     */
+    KAction *toolBarMenuAction();
+
     // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
     virtual void finalizeGUI( KXMLGUIClient *client );
 
@@ -497,11 +514,6 @@ public slots:
      */
     void setSettingsDirty();
 
-   /**
-    * Returns a pointer to the mainwindows action responsible for the toolbars menu
-    */
-    KToolBarMenuAction *toolBarMenuAction();
-    void removeToolBarMenuAction();
 protected:
     void paintEvent( QPaintEvent* e );
     void childEvent( QChildEvent* e);
@@ -687,7 +699,7 @@ protected:
     virtual void virtual_hook( int id, void* data );
 private:
     KMainWindowPrivate *d;
-    void initKMainWindow(bool createToolbarAction,const char *name);
+    void initKMainWindow(const char *name);
 };
 
 #define RESTORE(type) { int n = 1;\
Index: kstdaction.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdeui/kstdaction.cpp,v
retrieving revision 1.73
diff -u -p -r1.73 kstdaction.cpp
--- kstdaction.cpp	2002/06/30 18:33:18	1.73
+++ kstdaction.cpp	2002/07/02 10:07:20
@@ -282,11 +282,6 @@ KToggleAction *showMenubar( const QObjec
 KToggleAction *showToolbar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
 {
     KToggleAction *ret;
-        if ((!name) && (parent->mainActionCollectionFor()))
-        {
-                parent->mainActionCollectionFor()->removeToolBarMenuAction();
-        }
-
     ret = new KToggleAction(i18n("Show &Toolbar"), 0, recvr, slot, parent,
                             name ? name : stdName(ShowToolbar));
     ret->setChecked(true);
@@ -296,10 +291,6 @@ KToggleAction *showToolbar( const QObjec
 
 KToggleToolBarAction *showToolbar( const char* toolBarName, KActionCollection* parent, const char *name )
 {
-    if ((!name) && (parent->mainActionCollectionFor()))
-        {
-                parent->mainActionCollectionFor()->removeToolBarMenuAction();
-        }
     KToggleToolBarAction *ret;
     ret = new KToggleToolBarAction(toolBarName, i18n("Show &Toolbar"), parent,
                             name ? name : stdName(ShowToolbar));
Index: ktoolbarhandler.cpp
===================================================================
RCS file: ktoolbarhandler.cpp
diff -N ktoolbarhandler.cpp
--- /dev/null	Fri Feb  1 11:53:05 2002
+++ ktoolbarhandler.cpp	Tue Jul  2 12:07:20 2002
@@ -0,0 +1,221 @@
+
+#include "ktoolbarhandler.h"
+
+#include <qpopupmenu.h>
+#include <ktoolbar.h>
+#include <kmainwindow.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <assert.h>
+
+namespace
+{
+    const char *actionListName = "show_menu_and_toolbar_actionlist";
+
+    const char *guiDescription = ""
+        "<!DOCTYPE kpartgui><kpartgui name=\"StandardToolBarMenuHandler\">"
+        "<MenuBar>"
+        "    <Menu name=\"settings\">"
+        "        <ActionList name=\"%1\" />"
+        "    </Menu>"
+        "</MenuBar>"
+        "</kpartgui>";
+
+    const char *resourceFileName = "barhandler.rc";
+
+    class BarActionBuilder
+    {
+    public:
+        BarActionBuilder( KActionCollection *actionCollection, KMainWindow *mainWindow, QPtrList<KToolBar> &oldToolBarList )
+            : m_actionCollection( actionCollection ), m_mainWindow( mainWindow ), m_menuBar( 0 ), m_menuBarAction( 0 ), m_needsRebuild( false )
+        {
+            QPtrList<QDockWindow> dockWindows = m_mainWindow->dockWindows();
+            QPtrListIterator<QDockWindow> dockWindowIt( dockWindows );
+            for ( ; dockWindowIt.current(); ++dockWindowIt ) {
+
+                KToolBar *toolBar = dynamic_cast<KToolBar *>( dockWindowIt.current() );
+                if ( !toolBar )
+                    continue;
+
+                if ( oldToolBarList.findRef( toolBar ) == -1 )
+                    m_needsRebuild = true;
+
+                m_toolBars.append( toolBar );
+            }
+
+            if ( !m_needsRebuild )
+                m_needsRebuild = ( oldToolBarList.count() != m_toolBars.count() );
+        }
+
+        bool needsRebuild() const { return m_needsRebuild; }
+
+        QPtrList<KAction> create()
+        {
+            if ( !m_needsRebuild )
+                return QPtrList<KAction>();
+
+            QPtrListIterator<KToolBar> toolBarIt( m_toolBars );
+            for ( ; toolBarIt.current(); ++toolBarIt ) 
+                handleToolBar( toolBarIt.current() );
+
+            QPtrList<KAction> actions;
+
+            if ( m_toolBarActions.count() == 0 )
+                return actions;
+
+            if ( m_toolBarActions.count() == 1 )
+                return m_toolBarActions;
+
+            KActionMenu *menuAction = new KActionMenu( i18n( "Toolbars" ), m_actionCollection, "toolbars_submenu_action" );
+
+            QPtrListIterator<KAction> actionIt( m_toolBarActions );
+            for ( ; actionIt.current(); ++actionIt )
+                menuAction->insert( actionIt.current() );
+
+            actions.append( menuAction );
+            return actions;
+        }
+
+        const QPtrList<KToolBar> &toolBars() const { return m_toolBars; }
+
+    private:
+        void handleToolBar( KToolBar *toolBar )
+        {
+            KAction *action = new KToggleToolBarAction( toolBar,
+                                                        i18n( "Show %1" ).arg( toolBar->label() ),
+                                                        m_actionCollection, 
+                                                        toolBar->name() );
+
+            m_toolBarActions.append( action );
+        }
+
+        KActionCollection *m_actionCollection;
+        KMainWindow *m_mainWindow;
+
+        QPtrList<KToolBar> m_toolBars; 
+        QMenuBar *m_menuBar;
+
+        QPtrList<KAction> m_toolBarActions;
+        KAction *m_menuBarAction;
+
+        bool m_needsRebuild : 1;
+    };
+}
+
+using namespace KDEPrivate;
+
+ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, const char *name )
+    : QObject( mainWindow, name ), KXMLGUIClient( mainWindow )
+{
+    init( mainWindow );
+}
+
+ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name ) 
+    : QObject( parent, name ), KXMLGUIClient( mainWindow )  
+{ 
+    init( mainWindow ); 
+}
+
+ToolBarHandler::~ToolBarHandler()
+{
+    m_actions.setAutoDelete( true );
+    m_actions.clear();
+}
+
+KAction *ToolBarHandler::toolBarMenuAction()
+{
+    assert( m_actions.count() == 1 );
+    return m_actions.getFirst();
+}
+
+void ToolBarHandler::setupActions()
+{
+    if ( !factory() || !m_mainWindow )
+        return;
+
+    BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars );
+
+    if ( !builder.needsRebuild() ) 
+        return;
+
+    unplugActionList( actionListName );
+
+    m_actions.setAutoDelete( true );
+    m_actions.clear();
+    m_actions.setAutoDelete( false );
+
+    m_actions = builder.create();
+
+    for (  QPtrListIterator<KToolBar> toolBarIt( m_toolBars );
+           toolBarIt.current(); ++toolBarIt )
+        toolBarIt.current()->disconnect( this );
+
+    m_toolBars = builder.toolBars();
+
+    for (  QPtrListIterator<KToolBar> toolBarIt( m_toolBars );
+           toolBarIt.current(); ++toolBarIt )
+        connect( toolBarIt.current(), SIGNAL( destroyed() ),
+                 this, SLOT( setupActions() ) );
+
+    plugActionList( actionListName, m_actions );
+
+    connectToActionContainers();
+}
+
+void ToolBarHandler::clientAdded( KXMLGUIClient *client )
+{
+    if ( client == this )
+        setupActions();
+}
+
+void ToolBarHandler::init( KMainWindow *mainWindow )
+{
+    d = 0;
+    m_mainWindow = mainWindow;
+
+    connect( m_mainWindow->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ),
+             this, SLOT( clientAdded( KXMLGUIClient * ) ) );
+
+    /* re-use an existing resource file if it exists. can happen if the user launches the
+     * toolbar editor */
+    /*
+    setXMLFile( resourceFileName );
+    */
+
+    if ( domDocument().documentElement().isNull() ) {
+
+        QString completeDescription = QString::fromLatin1( guiDescription )
+            .arg( actionListName );
+
+        setXML( completeDescription, false /*merge*/ );
+    }
+}
+
+void ToolBarHandler::connectToActionContainers()
+{
+    QPtrListIterator<KAction> actionIt( m_actions );
+    for ( ; actionIt.current(); ++actionIt ) 
+        connectToActionContainer( actionIt.current() );
+}
+
+void ToolBarHandler::connectToActionContainer( KAction *action )
+{
+    uint containerCount = action->containerCount();
+    for ( uint i = 0; i < containerCount; ++i )
+        connectToActionContainer( action->container( i ) );
+}
+
+void ToolBarHandler::connectToActionContainer( QWidget *container )
+{
+    QPopupMenu *popupMenu = dynamic_cast<QPopupMenu *>( container );
+    if ( !popupMenu )
+        return;
+
+    connect( popupMenu, SIGNAL( aboutToShow() ),
+             this, SLOT( setupActions() ) );
+}
+
+#include "ktoolbarhandler.moc"
+
+/* vim: et sw=4 ts=4
+ */
Index: ktoolbarhandler.h
===================================================================
RCS file: ktoolbarhandler.h
diff -N ktoolbarhandler.h
--- /dev/null	Fri Feb  1 11:53:05 2002
+++ ktoolbarhandler.h	Tue Jul  2 12:07:20 2002
@@ -0,0 +1,50 @@
+#ifndef KBARHANDLER_H
+#define KBARHANDLER_H
+
+#include <qobject.h>
+#include <qguardedptr.h>
+#include <kxmlguiclient.h>
+
+class KMainWindow;
+class KToolBar;
+
+namespace KDEPrivate
+{
+
+class ToolBarHandler : public QObject,
+                       public KXMLGUIClient
+{
+    Q_OBJECT
+public:
+    ToolBarHandler( KMainWindow *mainWindow, const char *name = 0 );
+    ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name = 0 );
+    virtual ~ToolBarHandler();
+
+    KAction *toolBarMenuAction();
+
+public slots:
+    void setupActions();
+
+private slots:
+    void clientAdded( KXMLGUIClient *client );
+
+private:
+    void init( KMainWindow *mainWindow );
+    void connectToActionContainers();
+    void connectToActionContainer( KAction *action );
+    void connectToActionContainer( QWidget *container );
+
+    struct Data;
+    Data *d;
+
+    QGuardedPtr<KMainWindow> m_mainWindow;
+    QPtrList<KAction> m_actions;
+    QPtrList<KToolBar> m_toolBars;
+};
+
+} // namespace KDEPrivate
+
+#endif // KBARHANDLER_H
+
+/* vim: et sw=4 ts=4
+ */
Index: ui_standards.rc
===================================================================
RCS file: /home/kde/kdelibs/kdeui/ui_standards.rc,v
retrieving revision 1.23
diff -u -p -r1.23 ui_standards.rc
--- ui_standards.rc	2002/06/05 20:57:40	1.23
+++ ui_standards.rc	2002/07/02 10:07:20
@@ -1,5 +1,5 @@
 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="standard_containers" version="3">
+<kpartgui name="standard_containers" version="4">
 <MenuBar>
   <Menu name="file"><text>&File</text>
     <Action name="file_new"/>
@@ -132,6 +132,7 @@
   <Menu name="settings"><text>&Settings</text>
     <Action name="options_show_menubar"/>
     <Action name="options_show_toolbar"/>
+    <Merge name="StandardToolBarMenuHandler" />
     <MergeLocal name="show_toolbar_merge"/>
     <Action name="options_show_statusbar"/>
     <MergeLocal name="show_merge"/>
-------------- next part --------------
Index: app/katemainwindow.cpp
===================================================================
RCS file: /home/kde/kdebase/kate/app/katemainwindow.cpp,v
retrieving revision 1.83
diff -u -p -r1.83 katemainwindow.cpp
--- app/katemainwindow.cpp	2002/06/30 09:37:25	1.83
+++ app/katemainwindow.cpp	2002/07/02 10:10:33
@@ -97,6 +97,8 @@ KateMainWindow::KateMainWindow(KateDocMa
 
   setupActions();
 
+  setStandardToolBarMenuEnabled( true );
+
   setXMLFile( "kateui.rc" );
   createShellGUI ( true );
   
Index: data/kateui.rc
===================================================================
RCS file: /home/kde/kdebase/kate/data/kateui.rc,v
retrieving revision 1.55
diff -u -p -r1.55 kateui.rc
--- data/kateui.rc	2002/06/26 16:12:58	1.55
+++ data/kateui.rc	2002/07/02 10:10:33
@@ -1,5 +1,5 @@
 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="kate" version="15">
+<kpartgui name="kate" version="16">
 
 <MenuBar noMerge="1">
   <Menu name="file"><text>&File</text>
@@ -65,7 +65,7 @@
   </Menu>
 
   <Menu name="settings"><text>&Settings</text>
-    <Action name="options_show_toolbar"/>
+    <Merge name="StandardToolBarMenuHandler"/>
     <Action name="settings_show_toolviews" />
     <Action name="settings_show_tooldocks" />
     <DefineGroup name="show_merge" />
-------------- next part --------------
Index: konq_mainwindow.cc
===================================================================
RCS file: /home/kde/kdebase/konqueror/konq_mainwindow.cc,v
retrieving revision 1.1016
diff -u -p -r1.1016 konq_mainwindow.cc
--- konq_mainwindow.cc	2002/07/01 17:12:31	1.1016
+++ konq_mainwindow.cc	2002/07/02 10:10:54
@@ -173,6 +173,8 @@ KonqMainWindow::KonqMainWindow( const KU
 
   setXMLFile( "konqueror.rc" );
 
+  setStandardToolBarMenuEnabled( true );
+
   createGUI( 0L );
 
   if ( !m_toggleViewGUIClient->empty() )
Index: konqueror.rc
===================================================================
RCS file: /home/kde/kdebase/konqueror/konqueror.rc,v
retrieving revision 1.99
diff -u -p -r1.99 konqueror.rc
--- konqueror.rc	2002/06/12 13:48:00	1.99
+++ konqueror.rc	2002/07/02 10:10:55
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="Konqueror" version="40">
+<kpartgui name="Konqueror" version="41">
 <MenuBar>
  <Menu name="file" noMerge="1"><text>&Location</text>
   <Action name="new_window"/>
@@ -72,7 +72,7 @@
  </Menu>
  <Menu name="settings" noMerge="1"><text>&Settings</text>
   <Action name="showmenubar"/>
-  <Action name="options_show_toolbar"/>
+  <Merge name="StandardToolBarMenuHandler" />
   <Separator/>
   <Action name="saveViewPropertiesLocally"/>
   <Action name="removeLocalProperties"/>


More information about the kde-core-devel mailing list